ZipArchive et ODT bug

Tags:: openoffice :: php

Je viens enfin de rendre mon article à PHP Solutions magazine qui devrait paraître en novembre sur l'édition de document OpenOffice via PHP. Durant la rédaction, je remarque que plus aucun de mes anciens exemples ne fonctionnent, la faute à ZipArchive qui a un bug depuis quelques versions. Vous trouverez ici l'explication http://bugs.php.net/bug.php?id=48763.

J'ai donc une solution: dériver ZipArchive pour faire ce dont j'ai besoin: décompresser tout, virer l'archive, recompresser... c'est plus lent, mais ça marche.

Voici donc pour vous mes chers lecteurs, la classe ZipArchive_Proxy, présentée dans le magazine PHP Solutions du mois prochain, qui permet de recréer une archive correcte.


<?php
/**
* Zip system to use for ODT files... because a bug exists in ZipArchive for PHP 5.2
*
* @author Patrice Ferlet <metal3d@copix.org>
* @license GNU/GPLv3
*/


class ZipArchive_Proxy{
       
    //temporary directory
    private $temp=''
   
    //file to use 
    private $file = '';
   
    /**
    * Create/open zip instance
    *
    * @param string $filename   
    */

    public function __construct($file = null) {
        if(!is_null($file)) $this->open($file);
    }
   
    /**
    * Init zip handler
    * @param string $filename
    * @return class instance
    */

    public function open($file){

        $this->file = $file;
       
        //prepare temporary directory
        if(is_dir('/dev/shm')) {
            $this->temp = '/dev/shm/'.uniqid('tmp_zip_');
            $this->cleanDir($this->temp);
        }
        else {
            $this->temp = sys_get_temp_dir().'/'.uniqid('tmp_zip_');
            $this->cleanDir($this->temp);
        }   
        mkdir($this->temp);       
       
        //unzip archive in temporary directory
        $zip = new ZipArchive();
        $zip->open($file);
        $zip->extractTo($this->temp);
        $zip->close();
        return $this;
    }
   
    /**
    * Return content by filename from archive
    *
    * @param string $filename
    * @return string file_content or null
    */

    public function getFromName ($file){
        $curpath = getcwd();
        chdir($this->temp);
       
        if(file_exists($file)) $toReturn = file_get_contents($file);
        else $toReturn = false;
       
        chdir($curpath);
        return $toReturn;
    }
   
   
    /**
    * Insert content in file in archive
    *
    * @param string $filename
    * @param mixed content
    * @return class instance
    */

    public function addFromString ($file, $content){
        echo "current path: ". getcwd();
        $curpath = getcwd();
        chdir($this->temp);       
        file_put_contents($file, $content);       
        chdir($curpath);
    }
   
   
    /**
    * Close archive
    * @return bool $ok
    */

    public function close(){
        unlink($this->file);       
        $zip = new ZipArchive();
        $zip->open($this->file, ZIPARCHIVE::CREATE);
        $curpath = getcwd();
        chdir($this->temp);
        $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('.'));
        foreach ($iterator as $key=>$value) {
           $key = preg_replace('/^\.\//','',$key);
           echo "Append: $key::$key\n";
           $zip->addFile($key,$key ) or die ("ERROR: Could not add file: $key");
        }
        $zip->close();
        chdir($curpath);
        $this->cleanDir($this->temp);       
        return true;
    }

    /**
    * Recursive method to clean directory
    */

    private function cleanDir($dir){
        if(!is_dir($dir)) return;
        $handle = opendir($dir);
        while (($entry = readdir($handle)) !== FALSE) {
            if( $entry == '.' || $entry == '..') continue; //ne pas compresser les répertoires parents
            $path = $dir.'/'.$entry;
            if (is_dir($path)) $this->cleanDir($path); //supprime le répertoire trouvé
            else unlink ($path); //supprime le fichier
        }
        closedir($handle);
        //et en fin on supprime le répertoire parent
        rmdir($dir);
    }
}
 

Ainsi, voici comment je m'y prend pour modifier le content.xml contenu dans un odt:


//ouvre l'archive odt
$zip = new ZipArchive_Proxy('test.odt');

//récupère le contenu de content.xml et modifie le contenu
$content = $zip->getFromName('content.xml');
$content = str_replace ('{titre}', 'Le titre du document', $content);

//on remet content.xml en place
$zip->addFromString('content.xml',$content);

//et on ferme
$zip->close();

 

Pour information, j'utilise si possible /dev/shm afin de taper dans la mémoire plutôt que le disque dur, si cela est impossible alors j'utilise le répertoire temporaire proposé par le système d'exploitation.

En espérant que cela vous rende service.

PS: L'article en question qui paraitra dans PHP Solutions parle évidemment de odtPHP, la classe incontournable pour éditer du ODT en PHP. Je vous donne rendez-vous au prochain numéro !

Utilisez le code barre pour ouvrir le ticket dans votre mobile:
This ticket on you mobile

Pas de commentaire pour le moment

Ajouter un commentaire
Veuillez répondre à la question suivante : Indiquez mon prénom, Patrice, avec une majuscule en première lettre

Trackbacks

Pour ajouter un trackback (retrolien) sur ce ticket, utilisez cette adresse: http://www.metal3d.org/index.php/trackback/default/tb?id=blog%2F231

Tags

Blog Copix Communication PC Config Fedora Vidéo Humour Autre Web Materiel Informatique PHP Développement Mootools HTML Linux WEB IE CSS Vista Microsoft Sympa XHTML Quizz Widget Klik CWE Voeux Bonne année Musique CCRMA Son Audio MAO Reconnaissance vocale Windows Mac Compiz MacOS Mysql Sun Base de données BD Screenlets Screenlet RPM compiz Ubuntu Live FireFox Derambarsh Facebook media informations Sécurité javascript SSH Commande Marketing concours ipod wii QT Trooltech Nokia Libre Logiciels GPL Attali Gnome Dock Compiler Bench undelete reiserfs recovery recover Thread Serveur Optimisation Server Apache Album RSS Flash Air XML Firefox Blender Opensource Orange Internet LiveBox Animaux Droits Logiciels Libres Google Loi RBS netcat Bash Téléphone Spam 3D NIDIA Standards Widgets Merise UML Streaming Developpement Perl MySQL Firewall Parfeu Bayes Novell Réseau Python LVS Salon FTP Dedibox Chrome Administration IRC Gentoo troll video Nouveauté Finance Etudiant spéctacle OpenOffice Javascript Java Info Eclpise ATI design mootools KDE Bureau Design GNU C Pages Jaunes Fun Bijoux Art mail Admin vmware fedora linux VirtualBox VMWare Qemu KVM vim Grep Fglrx Webkit GTK google web JQuery Coup de gueule coup de gueule Lois SVG Raycaster Canvas Hadopi Desktop Jeux Les Sims développement astuces Screen firefox Mobile Safaru Wine bash commande astuce Wave ooc C++ C# Netbook Hercules Bureautique Twitter Safari W3C chrome kazehakaze midori navigateur gecko webkit Links Liens Pyhon Nouvelles Metal Perso Conférence JDLL PCC Roadsend OOC News Acteur Cinéma Chanteur Seven windows orthographe pcc php jdll Slide Application mysql Html twitter python screen curses SVN Android Gphone iPhone OpenGL MindMap Projet Javascrtip Ajax Guitare Tab Tablature JSON firebug Chromium Iphone Titanium music sound android ogg ogv streaming

  • twitter entries...
follow me on Twitter

Valid XHTML 1.0 Strict