\n remains \n //$nl=1 -> \n gets ' ' //$nl=2 -> \n gets
like in nl2br(htmlentities()); //$nl=3 -> \n gets
, ' ' gets   and TAB gets ' ' like using '
'.htmlentities().'
'; //(c) by Claude Martin $text = str_replace('&#','[!UNICODE!]#',$text); //some Browser send the html-code on special chars $text = htmlentities($text,3); //commun spacial chars $text = str_replace('[!UNICODE!]#','&#',$text); //convert those back that already where here $out = ""; //loop for all chars in the string for($i=0;$i=2) $out .= "
\n"; //nl2br //elseif($ord === 11) $out .= "\v"; //Vertical Tab. IE would show ' ', Opera NL, Modzilla elseif($ord === 9 && $nl===3) $out .= '    '; //' ' elseif($ord === 13 && !$nl) $out .= "\r";//return elseif($ord === 13 && $nl) $r;//\r delete return elseif($ord === 32 && $nl===3) $out .= ' '; //no breaking space //Normal chars (like abcd or 〹 and ' ') are not altered elseif( $ord >= 32 && $ord <= 122 ) $out .= $text{$i}; //less output data //else unicode entities: else $out .= '&#'.$ord.';'; } return $out; } function htmlchars($text) { return htmlentities($text,3); //common spacial chars } /** * This function gets the data from $_GET or $_POST and save it to the session and also sets the variable variable ($$var) * using =& should save some memory since the variable is not stored three times! */ function check_var ($var, $default = FALSE) { global $$var; if(!isset ($_POST[$var]) && !isset ($_GET[$var])) { $_POST[$var] = &$_SESSION[$var]; $_GET[$var] = &$_SESSION[$var]; } elseif (isset ($_POST[$var])) { $_SESSION[$var] = &$_POST[$var]; $_GET[$var] = &$_POST[$var]; } else { $_SESSION[$var] = &$_GET[$var]; $_POST[$var] = &$_GET[$var]; //$_SESSION[$var] = $_POST[$var] = $_GET[$var]; } $bReset = FALSE; if (!isset ($_SESSION[$var])) $bReset = TRUE; if (is_string ($_SESSION[$var])) { if (trim ($_SESSION[$var]) === "") $bReset = TRUE; } else if (is_array ($_SESSION[$var])) { if (count ($_SESSION[$var]) == 0) $bRest = TRUE; } if ($bReset) $_SESSION[$var] = $_GET[$var] = $_POST[$var] = $default; $$var = $_SESSION[$var]; } //delets it from everywhere //ok maybe this is exaggerated but i just wanna be sure function reset_var($var) { $_POST[$var]=''; $_SESSION[$var]=''; $_GET[$var]=''; $$var=''; unset($_POST[$var]); unset($_SESSION[$var]); unset($_GET[$var]); unset($$var); } //print as human readable - better than var_dump() function print_a($array,$pre=false,$prep = '') { //(c) by Roland Tapken //modified by Claude Martin if(!$prep) { $firstrun=true; if(!is_array($array)) { return NULL; } if($pre) { $ret="
$pre\n"; $pre = true; } }
    
    $prep = "$prep '"; 
    $ret = "";
    
    foreach($array as $key=>$val) { 
        $type = gettype($val); 
        if (is_string($val) && strlen($val)===0) $type='empty string';
        if(is_array($val)) { 
            $line = "-¬ $key ($type)\n"; //
            $line .= print_a($val,$pre,$prep); 
        } else { 
            $line = '-> '.htmlentities($key,3).' = '.unicode($val)." ($type)\n"; 
        } 
        $ret .= $prep.$line; 
    } 
    if($firstrun) echo $ret."

"; else return $ret; } //gets a person from tblPeople and returns the html e.g. function acronym($who,$field=2,$format = '%s') { //not in use! $who = trim($who); if(!$who) return false; //which field should be returned as the abbreviation? if($field == 1 || strtolower($field) === 'coll') $field = "IF(CollAbbreviation != '',CollAbbreviation,AuthAbbreviation)"; elseif($field == 2 || strtolower($field) === 'auth') $field = "IF(AuthAbbreviation != '',AuthAbbreviation,CollAbbreviation)"; if(is_numeric($who)) { $sql = mysql_query("SELECT FullName, $field as acronym FROM tblPeople WHERE PeopleID = '$who' LIMIT 1"); } else { $sql = mysql_query("SELECT FullName, $field as acronym FROM tblPeople WHERE CollAbbreviation = '$who' OR AuthAbbreviation = '$who' OR FullName = '$who' LIMIT 1"); } if(mysql_num_rows($sql)==0) return $who; //most untriumphant! else { $ppl = mysql_fetch_assoc($sql); //get the data into the right format: $return = sprintf($format,str_replace(" "," ",htmlchars($ppl[FullName])),str_replace(" "," ",htmlchars($ppl[acronym]))); //this one certain browser doesn't know although its standard! //this would use abbr on all good browsers: //if(stristr($_SERVER[HTTP_USER_AGENT],MSIE)===false) { $return = str_replace('acronym','abbr',$return);} return $return; } } //if there is a 2nd author then the first is in brackets and else its just the first one. function authors ($full1,$abbr1,$full2=false,$abbr2=false) { //echo("1=$full1,$abbr1; 2=$full2,$abbr2"); if(!$abbr1) return ""; elseif($abbr2) { return sprintf ('(%s%s', str_replace(" "," ",htmlchars($full1)), str_replace(" "," ",htmlchars($abbr1)), str_replace(" "," ",htmlentities($full2,3)), str_replace(" "," ",htmlentities($abbr2,3))); } else { return sprintf ('%s', str_replace(" "," ",htmlchars($full1)), str_replace(" "," ",htmlchars($abbr1))); } } function backup_encode($data) { //must be array if(!is_array($data)) return false; if($data = addslashes(@gzcompress(@serialize($data),9))) return $data; } function backup_decode($data) { //must be string if(!is_string($data)) return false; if($data = @unserialize(@gzuncompress($data))) return $data; } //keys of $overlay will be added to $initial and overwritten if existing. function array_overlay(&$initial, $overlay) { //not recoursive!!! if(!is_array($overlay)) return false; elseif(!is_array($initial)) $initial = $overlay; else $initial = $overlay+$initial; return true; } /* very importatn note about this functions: SLASHES / $slashes is TRUE -> slashes will be added (good if that data is going to be used in other mysql queries) SLASHES / $slashes is FALSE -> no slashes (good for outputting to browser) but this means that shlashes must be addes b4 using any string in a SELECT thats it. adding slashes here makes it easier to transform data but its not wanted for getting data to output in html! but the thing is that SLASHES = TRUE was only used when transforming the data from access structure to mysql pinv. now its not used so it would be a good idea to get rid of it and optimize it to ^not add any slashes here. */ function transmit($table, $relation, $line=__LINE__, $slashes=SLASHES) { //this will check if the data is in the database. //if so: the ID of that will be returned //else: the data is inserted and the new ID is returned //its very important that the value NULL is submitted as array { [key] => NULL } mainly at renz_det! //note: theres no need to check fields like _Last_Change (anything that has a "_" as the first char!) //this is so stupid but kinda briliant: if(count($relation)==1 && !current($relation)) return NULL; foreach($relation as $key => $val) { if(!$slashes) { $key = addsl($key); $val = addsl($val); } if(isset($check)) { $fields .= " , $key "; if(!$val) { if($key[0] != '_') { $check .= " AND $key IS NULL "; } $values .= " , NULL "; } else { if($key[0] != '_') { $check .= " AND $key = '$val' "; } $values .= " , '$val' "; } } else { $check = " $key = '$val' "; $fields = " $key "; if(!$val) { if($key[0] != '_') { $check = " $key IS NULL "; } $values = " NULL "; } else { if($key[0] != '_') { $check = " $key = '$val' "; } $values = " '$val' "; } } } $sql = "SELECT ID FROM $table WHERE $check LIMIT 1"; //ID is irrelevant! $dest = db_get_field($sql,$line,$slashes); //one row, one field if(!$dest) { //so this one is not known yet $dest = db_insert("INSERT INTO $table ($fields) VALUES ($values)" ,$line); } return $dest; //return the (new) ID of the row. } function transmit_auth($PeopleID, $line=__LINE__,$slashes=SLASHES) { //function not used anymore!!! //this functions only knows the old ID of an author, transmits him to the new database and returns the new ID $sql = "SELECT FullName, AuthAbbreviation, BirthYear, DeathYear, Countries, AuthCheck, CollCheck, DetCheck, Notes FROM tblPeople WHERE PeopleID = $PeopleID"; $src = db_get_row($sql,$line,$slashes); //one row $sql = "SELECT ID FROM renz_ppl_auth WHERE Full_Name = '$src[FullName]' AND Abbreviation = '$src[AuthAbbreviation]' LIMIT 1"; //ID is irrelevant! Check on names should be sufficient(?) $dest = db_get_field($sql,$line,$slashes); //one row, one field if(!$dest) { //so this one is not known yet $dest = db_insert("INSERT INTO renz_ppl_auth (Abbreviation,Full_Name) VALUES ('$src[AuthAbbreviation]','$src[FullName]')" ,$line); //transmit the info as well: if(!$src['BirthYear']) $src['BirthYear'] = "NULL"; //unknown birthyear... if(!$src['DeathYear']) $src['DeathYear'] = "NULL"; //So its easier to see who is still alive... $src['Countries'] = trim($src['Countries']); $src['AuthCheck'] = ($src['AuthCheck'])?"1":"0"; //this should be boolean $src['CollCheck'] = ($src['CollCheck'])?"1":"0"; //this should be boolean $src['DetCheck'] = ($src['DetCheck'])?"1":"0"; //this should be boolean $src['Notes'] = trim($src['Notes']); $sql = "INSERT INTO renz_ppl_info (ID,Birth_Year,Death_Year,Countries,AuthCheck,CollCheck,DetCheck,Notes ) VALUES ($dest,$src[BirthYear],$src[DeathYear],'$src[Countries]',$src[AuthCheck],$src[CollCheck],$src[DetCheck],'$src[Notes]')"; db_query($sql,$line); } return $dest; } function get_specimen_link ($ID) { //var_dump($ID); if (!$ID) return FALSE; $row = db_get_row ("SELECT * FROM flast WHERE ID='$ID'"); return get_specimen_link_2($row['Renz_Herbarium_Number'],$row['Position'],$row['Genus'],$row['Species'],$row['a1F'],$row['a2F'],$row['Infraspecies'],$row['a3F'],$row['a4F']); } function get_specimen_link_by_herbarium_number ($ID) { if (!$ID) return FALSE; $row = db_get_row ("SELECT * FROM flast WHERE Renz_Herbarium_Number='$ID'"); return get_specimen_link_2 ($row['Renz_Herbarium_Number'], 1, $row['Genus'], $row['Species'], $row['a1F'], $row['a2F'], $row['Infraspecies'], $row['a3F'],$row['a4F']); } function get_specimen_link_2($Renz_Herbarium_Number,$Position,$Genus,$Species,$a1F,$a2F,$Infraspecies,$a3F,$a4F) { $base = "$_SERVER[ROOT]phpMyHerbarium/" . urlchars ($Renz_Herbarium_Number) . "/" . urlchars ($Position) . "/" . urlchars ($Genus) . "/" . urlchars ($Species) . "/" . urlchars ($a1F); if ($a2F) $base .= "/" . urlchars ($a2F); if ($Infraspecies) $base .= "/" . urlchars ($Infraspecies) . "/" . urlchars($a3F); if ($a4F) $base .= "/" . urlchars ($a4F); return "$base/"; } function urlchars($var,$my=false) { //Google erkennt in Dateinamen keine Hexwerte! //es existiert keine gegenfunktion //ue, ae, oe usw aber schon! static $array2=array( '_','_','_','_', 'c','c','ss','n', 'a','a','a','a','a','ae','ae', 'e','e','e','e', 'i','i','i','i', 'o','o','o','o','o','oe','oe', 'u','u','u','ue', 'C','N', 'A','A','A','A','A','Ae','Ae', 'E','E','E','E', 'I','I','I','I', 'O','O','O','O','O','Oe','Oe', 'U','U','U','Ue','_','_' ), $array1=array( ' ','',' ',"\n", 'ç','¢','ß','ñ', 'â','ã','à','á','å','ä','æ', 'é','è','ê','ë', 'í','ì','î','ï', 'ó','ò','ô','õ','ø','ö','œ', 'ú','ù','û','ü', 'Ç','Ñ', 'Â','Ã','Á','À','Å','Ä','Æ', 'É','È','Ê','Ë', 'Í','Ì','Î','Ï', 'Ó','Ò','Õ','Ô','Ø','Ö','Œ', 'Ú','Ù','Û','Ü','___','__' ); if(count($array1) != count($array2)) die("FATAL ERROR!"); $var = str_replace($array1,$array2,$var); //Alles andere wird entfernt $var = ($my)?my_urlencode($var):urlencode($var); $var = preg_replace("!%[A-Fa-f0-9]{2}!",'',$var); return str_replace('__','_',$var); } function ob_end(&$contents) { if($GLOBALS['remote'] && !strrpos($contents,'Claude Martin')) die("

REMEMBER CLAUDE MARTIN!

"); else ob_end_clean(); } //why cant i return it directrly?! the same problem in all db_*-functions function db_query($sql,$line=__LINE__) { //swstart(); $ret = @mysql_query($sql) or die("
Fatal Error:
".preg_replace("/\r?\n([^\n]*)/e","\"\n\".(++\$c).\": \".htmlentities(stripslashes(\"\\1\"))","\n".$sql)."
".htmlentities(mysql_error())."
Origin Line: $line
"); //swend($sql,true); return $ret; } function db_insert($sql,$line=__LINE__) { //returns ID generated from an INSERT operation $res = @mysql_query($sql) or die("
Fatal Error:
".preg_replace("/\r?\n([^\n]*)/e","\"
\".(++\$c).\": \".htmlentities(stripslashes(\"\\1\"))","\n".$sql)."
".htmlentities(mysql_error())."
Origin Line: $line
"); $id = @mysql_insert_id() or die("
Fatal Error:
".preg_replace("/\r?\n([^\n]*)/e","\"\".(++\$c).\": \".htmlentities(stripslashes(\"\\1\"))","\n".$sql)."
".htmlentities(mysql_error())."
Failed getting ID generated from the previous INSERT operation!
Origin Line: $line
"); return $id; } /* very importatn note about this functions: SLASHES / $slashes is TRUE -> there will be slashes SLASHES / $slashes is FALSE -> there will be NO slashes thats it. adding slashes here makes it easier to transform data but its not wanted for getting data to output in html! */ function db_fetch($resource,$line=__LINE__,$slashes=SLASHES) { //like mysql_fetch_assoc $ret = mysql_fetch_assoc($resource);//can't use "or die()" because it returns false for no rows. if(!$slashes) return $ret; else return addsl($ret); } function db_get_row($sql,$line=__LINE__,$slashes=SLASHES) { //get only first row (no while-loop) $r = @mysql_query($sql) or die("
Fatal Error:
".preg_replace("/\r?\n([^\n]*)/e","\"\n\".(++\$c).\": \".htmlentities(stripslashes(\"\\1\"))","\n".$sql)."
".htmlentities(mysql_error())."
Origin Line: $line
"); $f = @mysql_fetch_assoc($r); //this might return false if(!$slashes) return $f; else return addsl($f); } function db_get_field($sql,$line=__LINE__,$slashes=SLASHES) { //get only first field of first row (no while-loop) $r = @mysql_query($sql) or die("
Fatal Error:
".(($err=mysql_error())?htmlentities($err):"No problem report available. Query: $sql")."
Origin Line: $line
"); $f = @mysql_fetch_assoc($r); //this might return false if(is_array($f)) { $ret = current($f); //current() or reset()? what is better? if(!$slashes) return $ret; else return addsl($ret); } else { //error? return $f; //just return whatever it is } } function addsl($f) { //not recursive!! AFAP if(is_array($f)) { foreach($f as $k => $v) $f[$k] = addslashes($v); //there might be a faster way? return $f; } elseif(is_string($f)) { return addslashes($f); } else { //numerical/boolean/NULL: return $f; } } //this can be used to do some performance tests. its like a stopwatch function swstart() { global $stopwatch; $stopwatch = microtime(); } function swend($line="Time",$hidden = false) { global $stopwatch; $end=microtime(); list($startmsec,$startsec)=explode(" ",$stopwatch); list($endmsec,$endsec)=explode(" ",$end); if($hidden) echo "\n\n"; else echo '

'.$line.': '.(((float)$endmsec+(float)$endsec)-((float)$startmsec+(float)$startsec)).'

'; } function flush_page () { global $buffer; // output of all data if ($buffer) { $contents = ob_get_contents (); //ob_end ($contents); ob_end_clean(); //compress using gzip algorithm echo ("\x1f\x8b\x08\x00\x00\x00\x00\x00"); // the last chars are redundand, but I think its faster to leave them and output directly. // echo substr (gzcompress ($contents, 9), 0, -4); echo (gzcompress ($contents, 9)); exit (); } exit (); } function isRobot () { $strAgent = &$_SERVER['HTTP_USER_AGENT']; if ($strAgent) { $arrRobots = array ("wget", "getright", "yahoo", "altavista", "lycos", "infoseek", "lwp", "webcrawler", "linkexchange", "slurp", "google", "msnbot", "nicebot", "crawler"); foreach ($arrRobots as $strRobot) if (strpos (strtolower ($strAgent), $strRobot) !== FALSE) return TRUE; } return FALSE; } function get_enum_values ($strTableName, $strFieldName) { $res = db_query ("SHOW COLUMNS FROM $strTableName LIKE '$strFieldName'"); $row = mysql_fetch_assoc ($res); $arrEnums = explode (",", substr ($row["Type"], 5, strlen ($row["Type"]) - 6)); mysql_free_result ($res); for ($i = 0; $i < count ($arrEnums); $i++) $arrEnums[$i] = substr ($arrEnums[$i], 1, strlen ($arrEnums[$i]) - 2); return $arrEnums; } function make_enum_options ($strTableName, $strFieldName, $strSelectedValue) { foreach (get_enum_values ($strTableName, $strFieldName) as $strValue) { echo (""); } } /** * Ensures that the argument $s is UTF8 encoded. * If it isn't, the encoding is performed. Otherwise, $s is returned as is. */ function ensure_utf8 ($s) { // From http://w3.org/International/questions/qa-forms-utf-8.html if (preg_match("%^(?: [\x09\x0A\x0D\x20-\x7E] # ASCII | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 )*$%xs", $s)) { return $s; } return utf8_encode ($s); } ?> $b) ? -1 : 1;')); } return $arrLang; } function getLanguage ($arrAvailableLangs = NULL, $strDefaultLang = "en") { if ($arrAvailableLangs == NULL) $arrAvailableLangs = array ("en"); $arrAcceptedLangs = parseAcceptLanguage (); foreach ($arrAcceptedLangs as $strLang) if (in_array ($strLang, $arrAvailableLangs)) return $strLang; return $strDefaultLang; } ///////////////////////////////////////////////////////////////////////////////// // Parser Functions $arrDict = array (); $strCurrentLang = ""; function startElement_dict ($parser, $strName, $attrs) { global $arrDict; global $strCurrentLang; if ($strName == "lang") $strCurrentLang = $attrs["id"]; else if ($strName == "entry") { if ($strCurrentLang == $_SESSION["language"]) $arrDict[$attrs["key"]] = $attrs["value"]; } } function endElement_dict ($parser, $name) { } function initDict () { //ini_set("session.name","pmhSID"); //session_start (); $xml_parser = xml_parser_create (); xml_parser_set_option ($xml_parser, XML_OPTION_CASE_FOLDING, 0); xml_set_element_handler ($xml_parser, "startElement_dict", "endElement_dict"); if (!($fp = fopen ("dict.xml", "r"))) die("could not open XML input"); while ($data = fread ($fp, 4096)) { if (!xml_parse ($xml_parser, $data, feof ($fp))) die (sprintf ("XML error: %s at line %d", xml_error_string (xml_get_error_code ($xml_parser)), xml_get_current_line_number ($xml_parser))); } xml_parser_free ($xml_parser); } function translate ($str, $oParams = NULL) { if ($_SESSION["language"] == "en") return translate_printf ($str, $oParams); global $arrDict; if (!array_key_exists ($str, $arrDict)) return ("[!! not translated !! -- add this string to dict.xml]: $str"); return translate_printf ($arrDict[$str], $oParams); } function translate_printf ($str, $oParams) { if ($oParams == NULL) return $str; if (!is_array ($oParams)) return sprintf ($str, $oParams); $strEvalString = ""; foreach ($oParams as $strParam) $strEvalString .= ",\"" . str_replace ("\"", "\\\"", $strParam) . "\""; eval ("\$strResult = sprintf (\"" . str_replace ("\$", "\\\$", str_replace ("\"", "\\\"", $str)) . "\" $strEvalString);"); return $strResult; //return call_user_func_array ("sprintf", array_merge ((array) $str, $oParams)); } function getFullLanguageName ($strLang) { switch (strtoupper ($strLang)) { case "AA": return "Afar"; case "AB": return "Abkhazian"; case "AF": return "Afrikaans"; case "AM": return "Amharic"; case "AR": return "Arabic"; case "AS": return "Assamese"; case "AY": return "Aymara"; case "AZ": return "Azerbaijani"; case "BA": return "Bashkir"; case "BE": return "Byelorussian"; case "BG": return "Bulgarian"; case "BH": return "Bihari"; case "BI": return "Bislama"; case "BN": return "Bengali"; case "BO": return "Tibetan"; case "BR": return "Breton"; case "CA": return "Catalan"; case "CO": return "Corsican"; case "CS": return "Czech"; case "CY": return "Welsh"; case "DA": return "Danish"; case "DE": return "German"; case "DZ": return "Bhutani"; case "EL": return "Greek"; case "EN": return "English"; case "EO": return "Esperanto"; case "ES": return "Spanish"; case "ET": return "Estonian"; case "EU": return "Basque"; case "FA": return "Persian"; case "FI": return "Finnish"; case "FJ": return "Fiji"; case "FO": return "Faeroese"; case "FR": return "French"; case "FY": return "Frisian"; case "GA": return "Irish"; case "GD": return "Gaelic"; case "GL": return "Galician"; case "GN": return "Guarani"; case "GU": return "Gujarati"; case "HA": return "Hausa"; case "HI": return "Hindi"; case "HR": return "Croatian"; case "HU": return "Hungarian"; case "HY": return "Armenian"; case "IA": return "Interlingua"; case "IE": return "Interlingue"; case "IK": return "Inupiak"; case "IN": return "Indonesian"; case "IS": return "Icelandic"; case "IT": return "Italian"; case "IW": return "Hebrew"; case "JA": return "Japanese"; case "JI": return "Yiddish"; case "JW": return "Javanese"; case "KA": return "Georgian"; case "KK": return "Kazakh"; case "KL": return "Greenlandic"; case "KM": return "Cambodian"; case "KN": return "Kannada"; case "KO": return "Korean"; case "KS": return "Kashmiri"; case "KU": return "Kurdish"; case "KY": return "Kirghiz"; case "LA": return "Latin"; case "LN": return "Lingala"; case "LO": return "Laothian"; case "LT": return "Lithuanian"; case "LV": return "Latvian"; case "MG": return "Malagasy"; case "MI": return "Maori"; case "MK": return "Macedonian"; case "ML": return "Malayalam"; case "MN": return "Mongolian"; case "MO": return "Moldavian"; case "MR": return "Marathi"; case "MS": return "Malay"; case "MT": return "Maltese"; case "MY": return "Burmese"; case "NA": return "Nauru"; case "NE": return "Nepali"; case "NL": return "Dutch"; case "NO": return "Norwegian"; case "OC": return "Occitan"; case "OM": return "Oromo"; case "OR": return "Oriya"; case "PA": return "Punjabi"; case "PL": return "Polish"; case "PS": return "Pashto"; case "PT": return "Portuguese"; case "QU": return "Quechua"; case "RM": return "Rhaeto-Romance"; case "RN": return "Kirundi"; case "RO": return "Romanian"; case "RU": return "Russian"; case "RW": return "Kinyarwanda"; case "SA": return "Sanskrit"; case "SD": return "Sindhi"; case "SG": return "Sangro"; case "SH": return "Serbo-Croatian"; case "SI": return "Singhalese"; case "SK": return "Slovak"; case "SL": return "Slovenian"; case "SM": return "Samoan"; case "SN": return "Shona"; case "SO": return "Somali"; case "SQ": return "Albanian"; case "SR": return "Serbian"; case "SS": return "Siswati"; case "ST": return "Sesotho"; case "SU": return "Sudanese"; case "SV": return "Swedish"; case "SW": return "Swahili"; case "TA": return "Tamil"; case "TE": return "Tegulu"; case "TG": return "Tajik"; case "TH": return "Thai"; case "TI": return "Tigrinya"; case "TK": return "Turkmen"; case "TL": return "Tagalog"; case "TN": return "Setswana"; case "TO": return "Tonga"; case "TR": return "Turkish"; case "TS": return "Tsonga"; case "TT": return "Tatar"; case "TW": return "Twi"; case "UK": return "Ukrainian"; case "UR": return "Urdu"; case "UZ": return "Uzbek"; case "VI": return "Vietnamese"; case "VO": return "Volapuk"; case "WO": return "Wolof"; case "XH": return "Xhosa"; case "YO": return "Yoruba"; case "ZH": return "Chinese"; case "ZU": return "Zulu"; } return "(Unknown)"; } ?>