<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
// +----------------------------------------------------------------------+
// | Copyright (c) 2006 Tom Klingenberg |
// +----------------------------------------------------------------------+
// | license info GPL/LGPL |
// +----------------------------------------------------------------------+
// | Author: Tom Klingenberg <tklingenberg@lastflood.com> |
// +----------------------------------------------------------------------+
//
/**
* ISBN
*
* Handle, Convert and Validate ISBN Numbers
*
* PHP version 5
*
* LICENSE: GPL/LGPL
*
* Package to handle, convert and validate ISBN numbers. It includes:
* - ISBN specifics:
* - EAN/Prefix (integer)
* - 'ISBNBody' (string)
* - Group/Registration Group [2001: Group identifier] (integer)
* (- GroupTitle/Registration Group Title (string))
* - 'ISBNSubbody'' (string)
* - Publisher/Registrant [2001: Publisher identifier] (string)
* - Title/Publication [2001: Title identifier] (string)
* - Checkdigit (string)
* - Version (integer) value as of a CONST
* - Syntactical Validation plus Validation based on real ISBN Data
* - ISBN-10 (ISO 2108)
* - checksum calculation (ISBN-10)
* - validation
* - conversion to ISBN-13-978
* - ISBN-13-978 (2005 Handbook, ISO pending; ISBN-13)
* - checksum calculation (EAN)
* - validation
*
* Based on standards published by international ISBN Agency
* http://www.isbn-international.org/
*
*
* @category UNKNOWN
* @package ISBN
* @author Tom Klingenberg <tklingenberg@lastflood.com>
* @copyright 2006 Tom Klingenberg
* @license GPL/LGPL
* @version 0.1.0
*/
// {{{ constants
/**
* ISBN Versions supported
*/
define("ISBN_VERSION_NONE", false);
/*
* VERSION_UNKNOWN is by the caller only, this shall never
* be a value returned by a public function or getter
*/
define("ISBN_VERSION_UNKNOWN", 0);
define("ISBN_VERSION_ISBN_10", 10);
define("ISBN_VERSION_ISBN_13", 13978);
define("ISBN_VERSION_ISBN_13_978", ISBN_VERSION_ISBN_13);
define("ISBN_VERSION_ISBN_13_979", 13979); /* reserved */
/**
* Default Additonal ISBN (formatting) Values
*/
define("ISBN_DEFAULT_INPUTVERSION", ISBN_VERSION_UNKNOWN);
define("ISBN_DEFAULT_COSMETIC_SEPERATOR", "-");
/*
* ISBN_DEFAULT_PRINT_LANG_SPECIFIC_PREFIX
*
* When printed, the ISBN is always preceded by the letters "ISBN".
* Note: In countries where the Latin alphabet is not used, an abbreviation
* in the characters of the local script may be used in addition to the
* Latin letters "ISBN".
* This can be defined as a default value wihtin this constant.
*/
define("ISBN_DEFAULT_PRINT_LANG_SPECIFIC_PREFIX", "");
// }}}
// {{{ ISBN
/**
* class ISBN
*
* @since Class available since Release 0.0.0
*/
class ISBN
{
/**
* @var string ISBN Registration Group
*/
private $isbn_group = "";
/**
* @var string ISBN Publisher
*/
private $isbn_publisher = "";
/**
* @var string ISBN Title
*/
private $isbn_title = "";
/**
* @var mixed ISBN number version
*/
private $ver = ISBN_VERSION_NONE;
// {{{ __construct
/**
* Constructor
*
* @param array $isbn String of ISBN Value to use
* @param mixed $ver Optional Version Constant
*
* @access public
*/
function __construct($isbn = "", $ver = ISBN_DEFAULT_INPUTVERSION) {
/* validate & handle optional isbn parameter */
if (is_string($isbn) == false ) {
throw new Exception("ISBN parameter must be a string", 4);
}
if (strlen($isbn) == 0) {
$this->setISBN($isbn);
return;
}
/* validate version parameter */
if (self::_ISBNVersionIs($ver) == false) {
throw new Exception("ISBN Version parameter is not an ISBN Version", 3);
}
/* ISBN has been passed, check the version now:
* if it is unknown, try to dertine it, if this fails
* throw an exception
*/
if ($ver == ISBN_VERSION_UNKNOWN) {
$verguess = self::_ISBNVersionGuess($isbn);
if (self::_ISBNVersionIsValid($verguess)) {
$ver = $verguess;
} else {
// throw new Exception("Unknown ISBN Version could not be guessed.", 5);
$ver = ISBN_VERSION_NONE;
}
}
/* version determined */
$this->ver = $ver;
/* handle a complete invalid ISBN of which a version could
* not be determined. */
if ($ver === ISBN_VERSION_NONE) {
$this->setISBN("");
return;
}
try {
$this->setISBN($isbn);
} catch(Exception $e) {
/* the isbn is invalid and not set, sothat this
* ISBN object will be set to a blank value. */
$this->setISBN("");
}
}
// }}}
// {{{ __extractCheckdigit()
/**
*
* extract Checkdigit of an ISBN-Number
*
* @param string $isbnn normalized ISBN string
*
* @return boolean False if failed
* @return string string containing the ISBN-Body
*
*/
private static function __extractCheckdigit($isbnn) {
$checkdigit = false;
$checkdigit = substr($isbnn,-1);
return (string) $checkdigit;
}
// }}}
// {{{ __extractEANPrefix()
/**
* extracts EAN-Prefix of a normalized isbn string
*
*
* @param string $isbnn normalized isbn string
*
* @return boolean False if failed
* @return string Prefix
*/
private static function __extractEANPrefix($isbnn)
{
$r = settype($isbnn, "string");
if ($r === false) {
return false;
}
if (strlen($isbnn) < 3) {
return false;
}
$prefix = substr($isbnn, 0, 3);
return $prefix;
}
// }}}
// {{{ __extractGroup()
/**
* extract Registration Group of an ISBN-Body
*
* @param string $isbnbody ISBN-Body
*
* @return boolean false if failed
* @return integer Value of Registration Group
*/
private static function __extractGroup($isbnbody) {
$group = '';
$subbody = '';
$r = self::__ISBNBodyParts($isbnbody, $group, $subbody);
if ($r === false) {
return false;
}
return $group;
}
// }}}
// {{{ __extractISBNBody()
/**
* extract ISBN-Body of an ISBN-Number
*
* @param string $isbnn normalized ISBN string
*
* @return boolean False if failed
* @return string string containing the ISBN-Body
*/
private static function __extractISBNBody($isbnn) {
/* extract */
$body = false;
$isbnn = (string) $isbnn;
$l = strlen($isbnn);
if ($l == 10) {
$body = substr($isbnn, 0, -1);
} elseif ($l == 13) {
$body = substr($isbnn, 3, -1);
} else {
return false;
}
/* verify */
$r = settype($body, "string");
if ($r === false) {
return false;
}
if (strlen($body) != 9) {
return false;
}
if (ctype_digit($body) === false) {
return false;
}
return $body;
}
// }}}
// {{{ __ISBNBodyParts()
/**
* Get the 2 Parts of the ISBN-Body (ISBN-10/ISBN-13-978)
*
* @param string $isbnbody ISBN-Body
* @param string &$registrationgroup Registration Group
* @param string &$isbnsubbody ISBN-Subbody
*
* @return boolean False if failed, True on success
*
* @access private
*/
private static function __ISBNBodyParts($isbnbody, &$registrationgroup, &$isbnsubbody) {
/* validate input (should not be needed, @access private) */
$r = settype($isbnbody, "string");
if ($r === false) {
return false;
}
if (strlen($isbnbody) != 9) {
return false;
}
if (ctype_digit($isbnbody) === false) {
return false;
}
/* extract registraion group
* boundaries see p.13 2005 handbook
*/
$boundaries = array();
$boundaries[] = array( 0, 59999, 1);
$boundaries[] = array(60000, 60099, 3); // Iran 2006-12-05
$boundaries[] = array(60100, 69999, 0);
$boundaries[] = array(70000, 79999, 1);
$boundaries[] = array(80000, 94999, 2);
$boundaries[] = array(95000, 98999, 3);
$boundaries[] = array(99000, 99899, 4);
$boundaries[] = array(99900, 99999, 5);
/* segment value */
$segment = substr($isbnbody, 0, 5);
$segmentvalue = intval($segment);
/* test segment value against boundaries */
$r = false;
foreach ($boundaries as $boundary) {
if ($segmentvalue >= $boundary[0] && $segmentvalue <= $boundary[1]) {
$r = $boundary[2];
}
}
if ($r === false) {
return false;
}
/* $r is 0 when the boundary is not defined */
if ($r === 0) {
return false;
}
$registrationgroup = substr($isbnbody, 0, $r);
$isbnsubbody = substr($isbnbody, $r);
return true;
}
// }}}
// {{{ __ISBNSubbodyParts()
/**
* Get the 2 Parts of the ISBN-Subbody (ISBN-10/ISBN-13)
*
* @param string $isbnsubbody ISBN-Subbody
* @param integer $groupid Registrationgroup
* @param string &$registrant Registrant
* @param string &$publication Publication
*
* @return boolean False if failed, true on success
*
* @access private
*/
private static function __ISBNSubbodyParts($isbnsubbody, $groupid, &$registrant, &$publication) {
/* validate input (should not be needed, @access private) */
$r = settype($isbnsubbody, "string");
if ($r === false) {
return false;
}
$l = strlen($isbnsubbody);
if ( $l < 1 || $l > 8) {
return false;
}
if (ctype_digit($isbnsubbody) === false) {
return false;
}
$r = settype($groupid, 'integer');
if ($r === false) {
return false;
}
if ($groupid < 0 || $groupid > 99999) {
return false;
}
/* extract registrant based on group and registrant range
* parse this specific group format: array("English speaking area",
* "00-09;10-19;200-699;7000-8499;85000-89999;900000-949999;9500000-9999999");
*/
$group = self::__getISBN10Group($groupid);
if ($group === false) {
return false;
}
$len = self::__getRegistrantLength($isbnsubbody, $group[1]);
if ($len === false) {
return false;
}
$registrant = substr($isbnsubbody, 0, $len);
$publication = substr($isbnsubbody, $len);
return true;
}
// }}}
// {{{ __getRegistrantLength()
/*
* Return Length of Registrant part within an ISBNSubbody in a specific
* grouprange in this specific format:
*
* "00-09;10-19;200-699;7000-8499;85000-89999;900000-949999;9500000-9999999"
*
* Info: This function is compatible with Groupranges formatted in the
* .js file and might become obsolete if new formats are more fitting.
*
* @param string $isbnsubbody
* @param string $grouprange Grouprange in the Format "#a1-#z1;#a2-z2[...]"
*
* @return boolean False if failed
* @return int Length (in chars) of Registrant
*
* @access private
*/
private static function __getRegistrantLength($isbnsubbody, $grouprange) {
$r = settype($grouprange, 'string');
if ($r === false) {
return false;
}
if (strlen($grouprange) < 3) {
return false;
}
$sl = strlen($isbnsubbody);
$ranges = explode(";", $grouprange);
foreach($ranges as $range) {
$range = trim($range);
$fromto = explode("-", $range);
if (count($fromto) !== 2) {
return false;
}
/* validation:
* from and to need to be in the same class,
* having the same length.
* registrant can not be bigger or same then the
* whole subbody, at least there is one digit for
* the publication.
*/
$l = strlen($fromto[0]);
if ($l != strlen($fromto[1])) {
return false;
}
if ($l >= $sl) {
return false;
}
/* check that from/to values are in order */
if (strcmp($fromto[0], $fromto[1]) >= 0) {
return false;
}
/* compare and fire if matched */
$compare = intval(substr($isbnsubbody, 0, $l));
if (strcmp($fromto[0], $compare) < 1 && strcmp($fromto[1], $compare) > -1) {
return $l;
}
}
return false;
}
// }}}
// {{{ __getISBN10Group()
/**
* Get ISBN-10 Registration Group Data by its numeric ID
*
* @param integer $id Registration Group Identifier
*
* @return mixed array: group array
* boolean: False if failed
*/
private static function __getISBN10Group($id) {
$r = settype($id, "integer");
if ($r === false) {
return false;
}
$groups = self::__getISBN10Groups();
if ($groups === false) {
return false;
}
if (isset($groups[$id]) === false) {
return false;
}
$group = $groups[$id];
return $group;
}
// }}}
// {{{ __getISBN10Groups()
/**
* Get all ISBN-10 Registration Groups
*
* @return array groups array
*
* Info: This function connects outer world data into this class logic
* which can be generated with the supplied tools.
* A user should not alter the array data. This data should be altered
* together with the international ISBN Agency only.
*/
private static function __getISBN10Groups() {
$groups = array();
/* ISBN Code-Generator - Ranges */
$groups[0] = array("English speaking area" , "00-09;10-19;200-699;7000-8499;85000-89999;900000-949999;9500000-9999999");
$groups[1] = array("English speaking area" , "00-09;100-399;4000-5499;55000-86979;869800-998999");
$groups[2] = array("French speaking area" , "00-09;10-19;200-349;35000-39999;400-699;7000-8399;84000-89999;900000-949999;9500000-9999999");
$groups[3] = array("German speaking area" , "00-02;030-033;0340-0369;03700-03999;04-19;200-699;7000-8499;85000-89999;900000-949999;9500000-9999999");
$groups[4] = array("Japan" , "00-09;10-19;200-699;7000-8499;85000-89999;900000-949999;9500000-9999999");
$groups[5] = array("Russian Federation" , "00-09;10-19;200-699;7000-8499;85000-89999;900000-909999;91000-91999;9200-9299;93000-94999;9500-9799;98000-98999;9900000-9909999;9910-9999");
$groups[600] = array("Iran" , "00-09;100-499;5000-8999;90000-99999");
$groups[7] = array("China, People's Republic" , "00-09;100-499;5000-7999;80000-89999;900000-999999");
$groups[80] = array("Czech Republic; Slovakia" , "00-09;10-19;200-699;7000-8499;85000-89999;900000-999999");
$groups[81] = array("India" , "00-09;10-19;200-699;7000-8499;85000-89999;900000-999999");
$groups[82] = array("Norway" , "00-09;10-19;200-699;7000-8999;90000-98999;990000-999999");
$groups[83] = array("Poland" , "00-09;10-19;200-599;60000-69999;7000-8499;85000-89999;900000-999999");
$groups[84] = array("Spain" , "00-09;10-19;200-699;7000-8499;85000-89999;9000-9199;920000-923999;92400-92999;930000-949999;95000-96999;9700-9999");
$groups[85] = array("Brazil" , "00-09;10-19;200-599;60000-69999;7000-8499;85000-89999;900000-979999;98000-99999");
$groups[86] = array("Serbia and Montenegro" , "00-09;10-29;300-599;6000-7999;80000-89999;900000-999999");
$groups[87] = array("Denmark" , "00-09;10-29;400-649;7000-7999;85000-94999;970000-999999");
$groups[88] = array("Italian speaking area" , "00-09;10-19;200-599;6000-8499;85000-89999;900000-949999;95000-99999");
$groups[89] = array("Korea" , "00-09;10-24;250-549;5500-8499;85000-94999;950000-999999");
$groups[90] = array("Netherlands, Belgium (Flemish)" , "00-09;10-19;200-499;5000-6999;70000-79999;800000-849999;8500-8999;900000-909999;940000-949999");
$groups[91] = array("Sweden" , "0-1;20-49;500-649;7000-7999;85000-94999;970000-999999");
$groups[92] = array("International Publishers (Unesco, EU), European Community Organizations" , "0-5;60-79;800-899;9000-9499;95000-98999;990000-999999");
$groups[93] = array("India - no ranges fixed yet" , "");
$groups[950] = array("Argentina" , "00-09;10-49;500-899;9000-9899;99000-99999");
$groups[951] = array("Finland" , "0-1;20-54;550-889;8900-9499;95000-99999");
$groups[952] = array("Finland" , "00-19;200-499;5000-5999;60-65;6600-6699;67000-69999;7000-7999;80-94;9500-9899;99000-99999");
$groups[953] = array("Croatia" , "0-0;10-14;150-599;6000-9499;95000-99999");
$groups[954] = array("Bulgaria" , "00-09;10-29;300-799;8000-8999;90000-92999;9300-9999");
$groups[955] = array("Sri Lanka" , "0-0;1000-1999;20-54;550-799;8000-9499;95000-99999");
$groups[956] = array("Chile" , "00-09;10-19;200-699;7000-9999");
$groups[957] = array("Taiwan, China" , "00-02;0300-0499;05-19;2000-2099;21-27;28000-30999;31-43;440-819;8200-9699;97000-99999");
$groups[958] = array("Colombia" , "00-09;10-59;600-799;8000-9499;95000-99999");
$groups[959] = array("Cuba" , "00-09;10-19;200-699;7000-8499");
$groups[960] = array("Greece" , "00-09;10-19;200-659;6600-6899;690-699;7000-8499;85000-99999");
$groups[961] = array("Slovenia" , "00-09;10-19;200-599;6000-8999;90000-94999");
$groups[962] = array("Hong Kong" , "00-09;10-19;200-699;7000-8499;85000-86999;8700-8999;900-999");
$groups[963] = array("Hungary" , "00-09;10-19;200-699;7000-8499;85000-89999;9000-9999");
$groups[964] = array("Iran" , "00-09;10-14;150-249;2500-2999;300-549;5500-8999;90000-96999;970-989;9900-9999");
$groups[965] = array("Israel" , "00-09;10-19;200-599;7000-7999;90000-99999");
$groups[966] = array("Ukraine" , "00-19;2000-2999;300-699;7000-8999;90000-99999");
$groups[967] = array("Malaysia" , "0-5;60-89;900-989;9900-9989;99900-99999");
$groups[968] = array("Mexico" , "01-09;10-39;400-499;5000-7999;800-899");
$groups[969] = array("Pakistan" , "0-1;20-39;400-799;8000-9999");
$groups[970] = array("Mexico" , "01-09;10-59;600-899;9000-9099;91000-96999;9700-9999");
$groups[971] = array("Philippines?" , "000-019;02-02;0300-0599;06-09;10-49;500-849;8500-9099;91000-99999");
$groups[972] = array("Portugal" , "0-1;20-54;550-799;8000-9499;95000-99999");
$groups[973] = array("Romania" , "0-0;100-169;1700-1999;20-54;550-759;7600-8499;85000-88999;8900-9499;95000-99999");
$groups[974] = array("Thailand" , "00-09;10-19;200-699;7000-8499;85000-89999;90000-94999;9500-9999");
$groups[975] = array("Turkey" , "00000-00999;01-09;10-24;250-599;6000-9199;92000-98999;990-999");
$groups[976] = array("Caribbean Community" , "0-3;40-59;600-799;8000-9499;95000-99999");
$groups[977] = array("Egypr" , "00-09;10-19;200-499;5000-6999;700-999");
$groups[978] = array("Nigeria" , "000-199;2000-2999;30000-79999;8000-8999;900-999");
$groups[979] = array("Indonesia" , "000-099;1000-1499;15000-19999;20-29;3000-3999;400-799;8000-9499;95000-99999");
$groups[980] = array("Venezuela" , "00-09;10-19;200-599;6000-9999");
$groups[981] = array("Singapore" , "200-299;3000-9999;00-09");
$groups[982] = array("South Pacific" , "00-09;100-699;70-89;9000-9999");
$groups[983] = array("Malaysia" , "00-01;020-199;2000-3999;40000-49999;50-79;800-899;9000-9899;99000-99999");
$groups[984] = array("Bangladesh" , "00-09;10-39;400-799;8000-8999;90000-99999");
$groups[985] = array("Belarus" , "00-09;10-39;400-599;6000-8999;90000-99999");
$groups[986] = array("Taiwan, China" , "120-559;5600-7999;80000-99999;00-09;10-11");
$groups[987] = array("Argentina" , "00-09;1000-1999;20000-29999;30-49;500-899;9000-9499;95000-99999");
$groups[988] = array("Hongkong" , "00-09;10-19;200-799;8000-9699;97000-99999");
$groups[989] = array("Portugal" , "0-1;20-54;550-799;8000-9499;95000-99999");
$groups[9940] = array("Montenegro" , "0-1;20-49;500-899;9000-9999");
$groups[9941] = array("Georgia" , "0-0;10-39;400-899;9000-9999");
$groups[9942] = array("Ecuador" , "00-89;900-994;9950-9999");
$groups[9943] = array("Uzbekistan" , "00-29;300-399;4000-9999");
$groups[9944] = array("Turkey" , "0-2;300-499;5000-5999;60-89;900-999");
$groups[9945] = array("Dominican Republic" , "00-09;10-39;400-849;8500-9999");
$groups[9946] = array("Korea, P.D.R." , "0-1;20-39;400-899;9000-9999");
$groups[9947] = array("Algeria" , "0-1;20-79;800-999");
$groups[9948] = array("United Arab Emirates" , "00-09;10-39;400-849;8500-9999");
$groups[9949] = array("Estonia" , "0-0;10-39;400-899;9000-9999");
$groups[9950] = array("Palestine" , "00-29;300-840;8500-9999");
$groups[9951] = array("Kosova" , "00-09;10-39;400-849;8500-9999");
$groups[9952] = array("Azerbaijan" , "0-1;20-39;400-799;8000-9999");
$groups[9953] = array("Lebanon" , "0-0;10-39;400-599;60-89;9000-9999");
$groups[9954] = array("Morocco" , "0-1;20-39;400-799;8000-9999");
$groups[9955] = array("Lithuania" , "00-09;10-39;400-929;9300-9999");
$groups[9956] = array("Cameroon" , "0-0;10-39;400-899;9000-9999");
$groups[9957] = array("Jordan" , "00-09;10-39;400-849;8500-9999");
$groups[9958] = array("Bosnia and Herzegovina" , "0-0;10-49;500-899;9000-9999");
$groups[9959] = array("Libya" , "0-1;20-79;800-949;9500-9999");
$groups[9960] = array("Saudi Arabia" , "00-09;10-59;600-899;9000-9999");
$groups[9961] = array("Algeria" , "0-2;30-69;700-949;9500-9999");
$groups[9962] = array("Panama" , "00-09;10-54;5500-5599;56-59;600-849;8500-9999");
$groups[9963] = array("Cyprus" , "0-2;30-54;550-749;7500-9999");
$groups[9964] = array("Ghana" , "0-6;70-94;950-999");
$groups[9965] = array("Kazakhstan" , "00-09;10-39;400-899;9000-9999");
$groups[9966] = array("Kenya" , "00-09;10-69;7000-7499;750-959;9600-9999");
$groups[9967] = array("Kyrgyzstan" , "00-09;10-39;400-899;9000-9999");
$groups[9968] = array("Costa Rica" , "00-09;10-49;500-939;9400-9999");
$groups[9970] = array("Uganda" , "00-09;10-39;400-899;9000-9999");
$groups[9971] = array("Singapore" , "0-5;60-89;900-989;9900-9999");
$groups[9972] = array("Peru" , "00-09;1;200-249;2500-2999;30-59;600-899;9000-9999");
$groups[9973] = array("Tunisia" , "0-0;10-69;700-969;9700-9999");
$groups[9974] = array("Uruguay" , "0-2;30-54;550-749;7500-9499;95-99");
$groups[9975] = array("Moldova" , "0;100-399;4000-4499;45-89;900-949;9500-9999");
$groups[9976] = array("Tanzania" , "0-5;60-89;900-989;9990-9999");
$groups[9977] = array("Costa Rica" , "00-09;10-89;900-989;9900-9999");
$groups[9978] = array("Ecuador" , "00-09;10-29;300-399;40-94;950-989;9900-9999");
$groups[9979] = array("Iceland" , "0-4;50-75;760-899;9000-9999");
$groups[9980] = array("Papua New Guinea" , "0-3;40-89;900-989;9900-9999");
$groups[9981] = array("Morocco" , "00-09;100-159;1600-1999;20-79;800-949;9500-9999");
$groups[9982] = array("Zambia" , "00-09;10-79;800-889;9900-9999");
$groups[9983] = array("Gambia" , "80-94;950-989;9900-9999");
$groups[9984] = array("Latvia" , "00-09;10-49;500-899;9000-9999");
$groups[9985] = array("Estonia" , "0-4;50-79;800-899;9000-9999");
$groups[9986] = array("Lithuania" , "00-09;10-39;400-899;9000-9399;940-969;97-99");
$groups[9987] = array("Tanzania" , "00-09;10-39;400-879;8800-9999");
$groups[9988] = array("Ghana" , "0-2;30-54;550-749;7500-9999");
$groups[9989] = array("Macedonia" , "0-0;100-199;2000-2999;30-59;600-949;9500-9999");
$groups[99901] = array("Bahrain" , "00-09;10-49;500-799;80-99");
$groups[99902] = array("Gabon - no ranges fixed yet" , "");
$groups[99903] = array("Mauritius" , "0-1;20-89;900-999");
$groups[99904] = array("Netherlands Antilles; Aruba, Neth. Ant" , "0-5;60-89;900-999");
$groups[99905] = array("Bolivia" , "0-3;40-79;800-999");
$groups[99906] = array("Kuwait" , "0-2;30-59;600-699;70-89;9-9");
$groups[99908] = array("Malawi" , "0-0;10-89;900-999");
$groups[99909] = array("Malta" , "0-3;40-94;950-999");
$groups[99910] = array("Sierra Leone" , "0-2;30-89;900-999");
$groups[99911] = array("Lesotho" , "00-09;10-59;600-999");
$groups[99912] = array("Botswana" , "0-3;400-599;60-89;900-999");
$groups[99913] = array("Andorra"