Subversion Repositories eFlore/Applications.cel

Rev

Rev 1413 | Rev 1469 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
// In : utf8
// Out : utf8

// TODO : doublons

/**
Octobre 2010 David Delon.
Import d'observations dans le carnet en ligne à partir d'un fichier excel chargé par l'utilisateur
et liaison d'images déjà chargee aux observations ainsi crées.

Nom des colonnes imposé, mais présence de toutes les colonnes non obligatoires, ordre non imposé
Aucune valeur dans les colonnes n'est obligatoire
Pour une ligne donnée, si tous les champs vides on ne fait rien, ou si seul le champ image est présent.
Si la seule différence entre deux lignes est la valeur de la colonne image, on considère que c'est la même observation à laquelle on associe plusieurs images.
Si au moins deux lignes (ou plus) sont complètement identiques on prend en compte une seule ligne (les doublons sont éliminés).
**/

// Nom des colonnes

define('COMMUNE','commune'); // soit un nom de commune, soit un code INSEE (5 chiffres), ou "nom de commune (numero departement)"
define('LIEUDIT','lieu-dit'); // Texte libre
define('STATION','station'); // Texte libre
define('MILIEU','milieu'); // Texte libre
define('LATITUDE','latitude'); // En decimal systeme WGS84
define('LONGITUDE','longitude'); // En decimal systeme WGS84 
define('NOTES','notes'); // Texte libre
define('DATEOBS','date'); // date au format jj/mm/aaaa
define('ESPECE','espece'); // texte libre, nom latin, ou code nomenclatural (format BDNFFnn999999)
define('IMAGE','image'); //  nom des fichiers images préalablement uploadés sur le CEL séparés par des "/"
define('DEPARTEMENT','departement'); //  Texte libre
define('TRANSMETTRE','transmettre'); //  "1" ou "oui", toute autre valeur (y compris vide) sera consideree comme "non""


// Resultat de l'analyse d'une ligne
define('LIGNE_VIDE',1); //  
define('LIGNE_NORMALE',2); //  
define('LIGNE_IMAGE_SEULEMENT',3); //  


//TODO: refactoriser entièrement cette classe
class InventoryImportExcel extends Cel  {

        // Element constituant une observation 
        var $format_observation=array(COMMUNE ,LIEUDIT ,STATION , DEPARTEMENT, MILIEU ,LATITUDE ,LONGITUDE ,NOTES ,DATEOBS ,ESPECE ,TRANSMETTRE, IMAGE );

        // Encapsulation classe lecture fichier excel
        var $extendExcelReader;

        // Dernier numero d'ordre utilise
        var $dernier_ordre = 1;
        
        var $cpt_images_liees = 0;
        
        var $utilisateur = array();

        /**
         Constructeur
        **/
        function InventoryImportExcel($config) {

                parent::__construct($config);   
                // Pas d'heritage multiple en php :(
                $this->extendExcelReader = new ExcelReader();
                $this->extendExcelReader->initExcelReader();
        }

        /**
         Sur post
        **/
        function createElement($pairs) {

                if(!isset($pairs['utilisateur']) || trim($pairs['utilisateur']) == '') {
                        echo '0'; exit;
                }
                
                if(!isset($_SESSION)) {session_start();}
        $this->controleUtilisateur($pairs['utilisateur']);
        
        $this->utilisateur = $this->getInfosComplementairesUtilisateur($pairs['utilisateur']);

        foreach($_FILES as $file) { // C'est le plus simple
            $infos_fichier = $file ;
        }
        
                // Chargement tableau en memoire
                $data = new Spreadsheet_Excel_Reader($infos_fichier['tmp_name'], true); // false : pour menager la memoire.
                $arr = array();

                $rowcount=$data->rowcount(0);
                $colcount=$data->colcount(0);

                if ($rowcount<=1) { // TODO : retour erreur
                        print "Tableau vide";
                        exit;
                }

                // Chargement tableau 
        for($row=1;$row<=$rowcount;$row++) 
            for($col=1;$col<=$colcount;$col++) 
                $arr[$col][$row] = $data->val($row,$col,0); // Attention, inversion voulue
              
                // 1 : Traitement intitules
                $line = array();

                /* Les colonnes ne sont pas forcemment dans l'ordre  : on les extrait pour traitement futur  */ 
        for($col=1;$col<=$colcount;$col++) {
            $colonne=strtolower($arr[$col][1]);
            $colonne=trim($colonne);
            $colonne=cp1252_to_utf8($colonne);
            $colonne=remove_accent($colonne);
            switch ($colonne) {  // On ne garde que les colonnes que l'on souhaite traiter
                case COMMUNE:
                case LIEUDIT:
                case STATION:
                case MILIEU:
                case DEPARTEMENT:
                case LATITUDE:
                case LONGITUDE:
                case NOTES:
                case DATEOBS:
                case ESPECE:
                case TRANSMETTRE:
                case IMAGE:
                    $selection=array_values($arr[$col]);
                    array_shift($selection); // On ne garde pas la premiere ligne, qui contient les intitules
                    $line[$colonne]=$selection;
                    break;

            }
        } 
                // 1 : Traitement lignes
                $cpt_obs=0;
                $cpt_img=0;

        /* Recherche dernier numero d'ordre utilise : pas de mise a jour concurente a priori */
        $requete = "SELECT MAX(ordre) AS ordre FROM cel_obs WHERE ce_utilisateur = ".$this->proteger($pairs['utilisateur'])." ";
                $resultat = $this->requeter($requete);

        if(is_array($resultat) && count($resultat) > 0) {
            $this->dernier_ordre = $resultat[0]['ordre']; // 1  par defaut
        }

                for ($i=0;$i<=$rowcount-1;$i++) {
                        // On saute les eventuelles lignes vides du debut et les lignes contenant des information sur image uniquement
                        while ((in_array($retour_analyse=$this->analyserLigne($line,$i),array(LIGNE_IMAGE_SEULEMENT, LIGNE_VIDE))) && ($i<=$rowcount)) {
                                if  ($retour_analyse==LIGNE_IMAGE_SEULEMENT) {
                                        // image non rattachée à une observation
                                }
                                else {
                                        // ligne vide
                                }
                                $i++;
                        }
                        while (($this->analyserLigne($line,$i)==LIGNE_NORMALE) && ($i<=$rowcount)) {
                                $id_obs = $this->traiterLigne($line,$i,$pairs['utilisateur']);
                                if ($this->dernier_ordre > 0) {
                                        $cpt_obs++; // Compteur d'observations crees
                                }
                                $i++;
                                // On saute les lignes vide ou on traite les lignes suivantes contenant des informations sur image seulement
                                while ((in_array($retour_analyse=$this->analyserLigne($line,$i),array(LIGNE_IMAGE_SEULEMENT, LIGNE_VIDE))) && ($i<=$rowcount)) {
                                        if  ($retour_analyse==LIGNE_IMAGE_SEULEMENT) {
                                                $this->traiterLigneComplement($line,$i,$pairs['utilisateur'],$id_obs); // images supplementaires
                                        }
                                        else {
                                                // print "vide";
                                        }
                                        $i++;
                                }       
                        }
                }
                $message = '';
                
                if($this->cpt_images_liees > 0) {
                        $message = $this->cpt_images_liees.' images liees pour ';
                }
                
                $message .= $cpt_obs;
                print $message;
        }

        function analyserLigne($line,$i) {
                
                $ligne_vide=true;
                $ligne_image_seulement=true;
                $ligne_normale=true;
                
                $ligne_identique_sauf_image = true;
                
                foreach ($this->format_observation as $colonne) {
                        
                        if($i < 1) {
                                $ligne_identique_sauf_image = false;
                        } else {
                                
                                if($colonne!= IMAGE && isset($line[$colonne]) && isset($line[$colonne][$i - 1]) && isset($line[$colonne][$i]) 
                                        && $line[$colonne][$i - 1] != $line[$colonne][$i] && $line[$colonne][$i] != '') {
                                        $ligne_identique_sauf_image = false;
                                }
                        } 
                        
                        if (isset ($line[$colonne][$i]) && $line[$colonne][$i]!='') {
                                if ($colonne!=IMAGE) {
                                        $ligne_image_seulement=false;
                                        $ligne_vide=false;
                                }               
                                $ligne_vide=false;
                        }               
                }
                
                if ($ligne_vide) {
                        return LIGNE_VIDE;
                }
                else {
                        if ($ligne_image_seulement || $ligne_identique_sauf_image) {
                                return LIGNE_IMAGE_SEULEMENT;
                        }
                        else {
                                return LIGNE_NORMALE;
                        }
                }
        }

        function traiterLigne($line,$i,$utilisateur) { 
                // Controle donnee et insertion
                $info_image=array();
                $info_transmettre = "0";
                $info_espece = array('en_id_nom' => '',
                        'nom_sel' => '',
                        'nom_sel_nn' => '',
                        'nom_ret' => '',
                        'nom_ret_nn' => '',
                        'nt' => '',
                        'famille' => ''
                );
                $info_commune = array('nom' => '', 'code' => '');
                
                foreach ($this->format_observation as $colonne) {
                        if (isset ($line[$colonne][$i]) && $line[$colonne][$i]!='') {
                                switch ($colonne) {  // On ne garde que les colonnes que l'on souhaite traiter
                                        case COMMUNE:
                                                $info_commune = $this->traiterCommune($line[COMMUNE][$i]);
                                                break;
                                        case LIEUDIT:
                                                $info_lieudit = $this->traiterLieudit($line[LIEUDIT][$i]);
                                                break;
                                        case STATION:
                                                $info_station = $this->traiterStation($line[STATION][$i]);
                                                break;
                                        case MILIEU:
                                                $info_milieu = $this->traiterMilieu($line[MILIEU][$i]);
                                                break;
                        case DEPARTEMENT:
                                $dpt = $this->traiterDepartement($line[DEPARTEMENT][$i]);
                                if(is_numeric($dpt) && strlen($dpt == 5) && $info_commune['code'] == 'NULL') {                          
                                        $info_commune['code'] = $dpt;
                                }
                                                break;
                                        case LATITUDE:
                                                $info_latitude = $this->traiterLatitude($line[LATITUDE][$i]);
                                                break;
                                        case LONGITUDE:
                                                $info_longitude = $this->traiterLongitude($line[LONGITUDE][$i]);
                                                break;
                                        case NOTES:
                                                $info_notes = $this->traiterNotes($line[NOTES][$i]);
                                                break;
                                        case DATEOBS:
                                                $info_dateobs = $this->traiterDateObs($line[DATEOBS][$i]);
                                                break;
                                        case TRANSMETTRE:
                                                $info_transmettre = $this->traiterTransmettre($line[TRANSMETTRE][$i]);
                                        break;
                                        case ESPECE:
                                                $chercheur_infos_taxon = new RechercheInfosTaxonBeta($this->config);
                                                $resultat_recherche_espece = $chercheur_infos_taxon->rechercherInfosSurTexteCodeOuNumTax($line[ESPECE][$i]);
                            if (isset($resultat_recherche_espece['en_id_nom']) && $resultat_recherche_espece['en_id_nom']!='') {
                                $info_espece['nom_sel'] = $resultat_recherche_espece['nom_sel'];
                                $info_espece['nom_sel_nn'] = $resultat_recherche_espece['en_id_nom'];
                                $complement = $chercheur_infos_taxon->rechercherInformationsComplementairesSurNumNom($resultat_recherche_espece['en_id_nom']);
                                $info_espece['nom_ret'] = $complement['Nom_Retenu'];
                                $info_espece['nom_ret_nn'] = $complement['Num_Nom_Retenu'];
                                $info_espece['nt'] = $complement['Num_Taxon'];
                                $info_espece['famille'] = $complement['Famille'];
                            } else {
                                $info_espece['nom_sel'] = $line[ESPECE][$i];
                            }
                                        case IMAGE:
                                                $info_image=$this->traiterImage($line[IMAGE][$i],$utilisateur); // Image separee par des / +  utilisateur
                                                break;
                                }
                        }
                        else {  
                                switch($colonne) {
                                        case COMMUNE:
                                                $info_commune['nom']="";
                                                break;
                                        case LIEUDIT:
                                                $info_lieudit="";
                                                break;
                                        case STATION:
                                                $info_station="";
                                                break;
                                        case MILIEU:
                                                $info_milieu="";
                                                break;
                                        case DEPARTEMENT:
                                    if (!isset ($info_commune['code']) || $info_commune['code']=='') {
                                                    $info_commune['code']="";
                            }
                                                break;
                                        case LATITUDE:
                                                $info_latitude = "";
                                                break;
                                        case LONGITUDE:
                                                $info_longitude = "";
                                                break;
                                        case NOTES:
                                                $info_notes='';
                                                break;
                                        case TRANSMETTRE:
                                                $info_transmettre = "0";
                                        break;
                                }
                        }
                }
        
        $this->dernier_ordre++;
        list($jour,$mois,$annee) = isset($info_dateobs) ? explode("/",$info_dateobs) : array(null,null,null);
        $info_dateobs=$annee."-".$mois."-".$jour." 0:0:0";
        $requete  = "INSERT INTO cel_obs (".
                "ce_utilisateur,prenom_utilisateur,nom_utilisateur,courriel_utilisateur,".
                "ordre,".
                "nom_sel,nom_sel_nn,nom_ret,nom_ret_nn,nt,famille,".
                "zone_geo,ce_zone_geo,".
                "date_observation,".
                "lieudit,station, milieu, commentaire, transmission, ".
                "date_creation,date_modification,latitude,longitude) ".
                " VALUES(".$this->proteger($utilisateur).",".
                $this->proteger($this->utilisateur['prenom']).",".
                $this->proteger($this->utilisateur['nom']).",".
                $this->proteger($this->utilisateur['courriel']).",".
                $this->proteger($this->dernier_ordre).",".
                $this->proteger($info_espece['nom_sel']).",".
                $this->proteger($info_espece['nom_sel_nn']).",".
                $this->proteger($info_espece['nom_ret']).",".
                $this->proteger($info_espece['nom_ret_nn']).",".
                $this->proteger($info_espece['nt']).",".
                $this->proteger($info_espece['famille']).",".
                $this->proteger($info_commune['nom']).",".
                $this->proteger('INSEE-C:'.$info_commune['code']).",".
                $this->proteger($info_dateobs).",".
                $this->proteger($info_lieudit).",".
                $this->proteger($info_station).",".
                $this->proteger($info_milieu).",".
                $this->proteger($info_notes).",".
                $this->proteger($info_transmettre).",".
                "now() , now(),".
                $this->proteger($info_latitude).",".
                $this->proteger($info_longitude).")";
        
                $insertion = $this->executer($requete);
                
                $requete_id_obs = 'SELECT id_observation FROM cel_obs WHERE ordre = '.$this->proteger($this->dernier_ordre).' AND ce_utilisateur = '.$this->proteger($utilisateur);
                $resultat_id_obs = $this->requeter($requete_id_obs);
                        
                $id_obs = $resultat_id_obs[0]['id_observation'];
                
                // creation lien image
                foreach ($info_image as $pic) {
                                
                        $requete_liaison = 'INSERT INTO cel_obs_images (id_image, id_observation ) VALUES ('.$this->proteger($pic['id_image']).', '.$id_obs.') ON DUPLICATE KEY UPDATE id_image = id_image ';   
                        $liaison = $this->executer($requete_liaison);
            if ($liaison !== false) {
                $this->cpt_images_liees++;
            } else {
                return false;           
            }
                }
        
                return $id_obs;
        }

        function traiterLigneComplement($line,$i,$utilisateur, $id_obs = null) {
        
                $info_image=$this->traiterImage($line[IMAGE][$i],$utilisateur); // Image separee par des / +  utilisateur       
                // creation lien image
                foreach ($info_image as $pic) { 
                        $requete = 'INSERT INTO cel_obs_images (id_image, id_observation) VALUES ('.$this->proteger($pic['id_image']).', '.$this->proteger($id_obs).') ON DUPLICATE KEY UPDATE id_image = id_image' ;   
                        $resultat_liaison = $this->executer($requete);
                if ($resultat_liaison !== false) {
                        $this->cpt_images_liees++;
                } else {
                        return false;
                }
                }
        }
        
        function traiterCommune($identifiant_commune) {  
                // Recherche correspondance sur nom, si pas unique, correspondance dep. sinon code insee
            $identifiant_commune=trim($identifiant_commune);
            $identifiant_commune=utf8_encode($identifiant_commune); // FIXME : devrait deja etre en utf8 a ce niveau
        
                preg_match('/(.*) \(([0-9][0-9]*)\)/',$identifiant_commune,$elements);
        
                if (isset($elements[1])) { // commune + departement : montpellier (34)
                        $nom_commune=$elements[1];
                        $code_commune=$elements[2];
                    $requete="SELECT DISTINCT nom, code  FROM cel_zones_geo WHERE nom = ".$this->proteger($nom_commune)." AND code LIKE ".$this->proteger($code_commune.'%');
                }
                else { // Code insee seul 
                preg_match('/([0-9][0-9]*)|(2A[0-9][0-9]*)|(2B[0-9][0-9]*)/',$identifiant_commune,$elements);
                if (isset($elements[1])) { // code insee  commune
                    $code_insee_commune=$elements[1];
                    $requete="SELECT DISTINCT nom, code  FROM cel_zones_geo WHERE code = ".$this->proteger($code_insee_commune);
                }       
                else { // Commune seule (le departement sera recupere dans la colonne departement si elle est presente, on prend le risque ici de retourner une mauvaise
                       // Commune
                    preg_match('/(.*)/',$identifiant_commune,$elements);
                    if (isset($elements[1])) { // commune 
                        $nom_commune=$elements[1];
                        $nom_commune=trim($nom_commune);
                        $nom_commune=utf8_decode($nom_commune);
                        $nom_commune=cp1252_to_utf8($nom_commune);
                        $nom_commune=remove_accent($nom_commune);
                        $nom_commune=preg_replace("/ /","%",$nom_commune);
                        $requete="SELECT DISTINCT nom, code  FROM cel_zones_geo WHERE nom like ".$this->proteger($nom_commune.'%');
                    }
                }
                }
        
                $resultat_commune = $this->requeter($requete);
                
                // cas de la commune introuvable dans le référentiel
                if(!is_array($resultat_commune) || count($resultat_commune) == 0) {
                        $resultat_commune['nom'] = fix_latin($identifiant_commune);
                        $resultat_commune['code'] = 'NULL';
                } else {
                        $resultat_commune = $resultat_commune[0];
                }
                        
                return $resultat_commune;
        }

        function traiterLieudit($lieudit) { 
                // texte libre
            $lieudit=fix_latin($lieudit);
                return trim($lieudit);
        }

        function traiterStation($station) { 
                // texte libre
            $station=fix_latin($station);
                return trim($station);
        }

        function traiterMilieu($milieu) { 
                // texte libre
            $milieu=fix_latin($milieu);
                return trim($milieu);
        }

        function traiterDepartement($departement) { 
                // texte libre
                if(is_numeric($departement) && strlen($departement) == 4) {
                        $departement = "0"+$departement;
                }
        
                if(is_numeric($departement) && $departement <= 9) {
                        $departement = "0"+$departement;
                }
                
                return utf8_encode(trim($departement));
        }

        function traiterLatitude($latitude) {   
                //  verifier formal decimal + limite france ? TODO 
                return trim($latitude);
        }
        
        function traiterLongitude($longitude) { 
                // verifier format decimal + limite france ? TODO 
                return trim($longitude);
        }
        
        function traiterNotes($notes) { 
                // texte libre
            $notes=remove_accent($notes);
                return utf8_encode(trim($notes));
        }
        
        function traiterDateObs($dateobs) { 
                // verifier jj/mm/aaaa sinon date vide TODO 
                $date = trim($dateobs);
                if(!preg_match("#[0-9]{2}/[0-9]{2}/([0-9]{4}|[0-9]{2})#", $date)) {
                        $date = '00/00/0000';
                }
                return $date;
        }

        function traiterTransmettre($transmettre) {             
                $transmission = '0';             
                if (trim($transmettre) == "1" || trim($transmettre) == "oui") { 
                        $transmission = '1';
                }                       
                return $transmission;
        }
        
        function traiterImage($images,$utilisateur) { // recherche id image de ce nom   
                $liste_images = explode("/",$images) ;
                $row =array();
                foreach($liste_images as $image) {
                        $image = remove_accent(fix_latin($image));
                        $requete = "SELECT * FROM cel_images WHERE ce_utilisateur = ".$this->proteger($utilisateur)." AND nom_original= ".$this->proteger($image);
                        $ligne = $this->requeter($requete);
                    if(is_array($ligne) && !empty($ligne)) {
                        $row[] = $ligne[0];
                    }
                }
                return $row;
        }
}

function init_byte_map(){
    $byte_map = array();
    for($x=128;$x<256;++$x){
        $byte_map[chr($x)]=utf8_encode(chr($x));
    }
    $cp1252_map=array(
            "\x80"=>"\xE2\x82\xAC",    // EURO SIGN
            "\x82" => "\xE2\x80\x9A",  // SINGLE LOW-9 QUOTATION MARK
            "\x83" => "\xC6\x92",      // LATIN SMALL LETTER F WITH HOOK
            "\x84" => "\xE2\x80\x9E",  // DOUBLE LOW-9 QUOTATION MARK
            "\x85" => "\xE2\x80\xA6",  // HORIZONTAL ELLIPSIS
            "\x86" => "\xE2\x80\xA0",  // DAGGER
            "\x87" => "\xE2\x80\xA1",  // DOUBLE DAGGER
            "\x88" => "\xCB\x86",      // MODIFIER LETTER CIRCUMFLEX ACCENT
            "\x89" => "\xE2\x80\xB0",  // PER MILLE SIGN
            "\x8A" => "\xC5\xA0",      // LATIN CAPITAL LETTER S WITH CARON
            "\x8B" => "\xE2\x80\xB9",  // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
            "\x8C" => "\xC5\x92",      // LATIN CAPITAL LIGATURE OE
            "\x8E" => "\xC5\xBD",      // LATIN CAPITAL LETTER Z WITH CARON
            "\x91" => "\xE2\x80\x98",  // LEFT SINGLE QUOTATION MARK
            "\x92" => "\xE2\x80\x99",  // RIGHT SINGLE QUOTATION MARK
            "\x93" => "\xE2\x80\x9C",  // LEFT DOUBLE QUOTATION MARK
            "\x94" => "\xE2\x80\x9D",  // RIGHT DOUBLE QUOTATION MARK
            "\x95" => "\xE2\x80\xA2",  // BULLET
            "\x96" => "\xE2\x80\x93",  // EN DASH
            "\x97" => "\xE2\x80\x94",  // EM DASH
            "\x98" => "\xCB\x9C",      // SMALL TILDE
            "\x99" => "\xE2\x84\xA2",  // TRADE MARK SIGN
            "\x9A" => "\xC5\xA1",      // LATIN SMALL LETTER S WITH CARON
            "\x9B" => "\xE2\x80\xBA",  // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
            "\x9C" => "\xC5\x93",      // LATIN SMALL LIGATURE OE
            "\x9E" => "\xC5\xBE",      // LATIN SMALL LETTER Z WITH CARON
            "\x9F" => "\xC5\xB8"       // LATIN CAPITAL LETTER Y WITH DIAERESIS
                );
    foreach($cp1252_map as $k=>$v){
        $byte_map[$k]=$v;
    }
    
    return $byte_map;
}

function fix_latin($instr){
    
    $byte_map = init_byte_map();
    
    $ascii_char='[\x00-\x7F]';
    $cont_byte='[\x80-\xBF]';
    $utf8_2='[\xC0-\xDF]'.$cont_byte;
    $utf8_3='[\xE0-\xEF]'.$cont_byte.'{2}';
    $utf8_4='[\xF0-\xF7]'.$cont_byte.'{3}';
    $utf8_5='[\xF8-\xFB]'.$cont_byte.'{4}';
    
    $nibble_good_chars = "@^($ascii_char+|$utf8_2|$utf8_3|$utf8_4|$utf8_5)(.*)$@s";

    if(mb_check_encoding($instr,'UTF-8'))return $instr; // no need for the rest if it's all valid UTF-8 already
    $outstr='';
    $char='';
    $rest='';
    while((strlen($instr))>0){
        if(1==@preg_match($nibble_good_chars,$instr,$match)){
            $char=$match[1];
            $rest=$match[2];
            $outstr.=$char;
        }elseif(1==@preg_match('@^(.)(.*)$@s',$instr,$match)){
            $char=$match[1];
            $rest=$match[2];
            $outstr.=$byte_map[$char];
        }
        $instr=$rest;
    }
    return $outstr;
}

function remove_accent($str) {
  $a = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î',
             'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß',
             'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î',
             'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā',
             'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď',
             'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ',
             'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ',
             'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ',
             'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ',
             'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ',
             'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ',
             'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż',
             'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ', 'Ǒ', 'ǒ',
             'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ');
             
  $b = array('A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I',
             'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's',
             'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i',
             'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a',
             'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd',
             'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g',
             'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i',
             'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'l', 'l',
             'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R',
             'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't',
             'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y',
             'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I',
             'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o');
  return str_replace($a, $b, $str);
}

function cp1252_to_utf8($str) {
        $cp1252_map = array ("\xc2\x80" => "\xe2\x82\xac",
                "\xc2\x82" => "\xe2\x80\x9a",
                "\xc2\x83" => "\xc6\x92",    
                "\xc2\x84" => "\xe2\x80\x9e",
                "\xc2\x85" => "\xe2\x80\xa6",
                "\xc2\x86" => "\xe2\x80\xa0",
                "\xc2\x87" => "\xe2\x80\xa1",
                "\xc2\x88" => "\xcb\x86",
                "\xc2\x89" => "\xe2\x80\xb0",
                "\xc2\x8a" => "\xc5\xa0",
                "\xc2\x8b" => "\xe2\x80\xb9",
                "\xc2\x8c" => "\xc5\x92",
                "\xc2\x8e" => "\xc5\xbd",
                "\xc2\x91" => "\xe2\x80\x98",
                "\xc2\x92" => "\xe2\x80\x99",
                "\xc2\x93" => "\xe2\x80\x9c",
                "\xc2\x94" => "\xe2\x80\x9d",
                "\xc2\x95" => "\xe2\x80\xa2",
                "\xc2\x96" => "\xe2\x80\x93",
                "\xc2\x97" => "\xe2\x80\x94",
                
                "\xc2\x98" => "\xcb\x9c",
                "\xc2\x99" => "\xe2\x84\xa2",
                "\xc2\x9a" => "\xc5\xa1",
                "\xc2\x9b" => "\xe2\x80\xba",
                "\xc2\x9c" => "\xc5\x93",
                "\xc2\x9e" => "\xc5\xbe",
                "\xc2\x9f" => "\xc5\xb8"
        );
        return strtr(utf8_encode($str), $cp1252_map);
}
?>