OOoConv

Convertisseur en ligne

Logo OOoConv

L'idée de ce convertisseur a émergée sur la liste de diffusion francophone de OpenOffice.org. Je vais donner dans ces quelques lignes le schéma général de l'application, les objectifs de développements futurs et le détail des différents codes sources intervenant. Je tiens à signaler que ceci n'est que ma vision de ce convertisseur et que cela n'a rien d'officiel.

Outils historiques

Le version d'OpenOffice.org utilisée est la Beta 1.1. Mon choix s'est porté sur cette version pour sa capacité à l'export PDF natif ainsi que son indispensable enregistreur de macro. La machine hébergeante est sous windows. J'y ai installé easyPHP (version 1.6) contenant Apache et PHP4. Enfin, tout cela est monté sur une ligne ADSL avec un DNS dynamique pour le nom de domaine.

L'architecture

A l'origine ce convertisseur a été pensé pour un export PDF des fichiers SXW. Le résultat devait être envoyé par mail à l'utilisateur. Il a ensuite evolué vers une tentative d'exports plus complets. Suite à quelques remarques concernant la CNIL, j'ai désactivé le support de mail ce serveur n'ayant pas vocation à héberger définitivement ce convertisseur. Après traitement, il est donc proposé un lien de visualisation/téléchargement sur la page de résultat.

Sur la page principale, l'utilisateur indique le document OpenOffice.org qu'il veut convertir et le format cible de la conversion.
Le formulaire ainsi renseigné et contrôlé est envoyé à un script PHP qui se charge de :

L'utilisateur peut ainsi visualiser le résultat immédiatement en cliquant sur le lien et faire un "enregistrer sous" si le résultat lui convient. Les fichiers de sessions ne sont pas conservés plus de 24h.
Je tiens à remercier Frederic Labbe pour ses conseils sur l'utilisation de PHP et des mails ainsi que toute la communauté pour sa participation aux tests qui continuent d'ailleurs...

Tableau des exports supportés

Tableau des exports supportés
Fichiers OpenOffice.org Formats d'exports disponibles
Writer : SXW, STW, SDW, VOR Acrobat PDF
HTML
Latex 2e (Writer2Latex)
XHTML + MathML (Writer2Latex)
RTF
MS Word 97/2000/XP
MS Word 95
MS Word 6.0
Calc : SXC, STC, SDC Acrobat PDF
HTML
MS Excel 97/2000/XP
MS Excel 95
MS Excel 5.0
Draw : SXD, STD, SDD, SDA Acrobat PDF
Macromedia Flash
Image JPG
Image PNG
Image EPS
Image TIFF
Image SVG
Impress : SXI, STI, SDP Acrobat PDF
MS PowerPoint 97/2000/XP
Macromedia Flash
Image JPG
Image PNG
Image EPS
Image TIFF
Image SVG

Attention : toutes les combinaisons n'ont pas été testées. Merci de ma signaler celles qui poseraient des problèmes.

Les questions en suspens

Bien sûr, rien ne va jamais sans mal ! Voici une liste de points sur lesquels je bloque. Mais tout d'abord, un peu de documentation :


Si vous avez des questions et surtout des réponses, n'hésitez pas à m'envoyer un mail.

Les développements futurs

Dans la mesure de mes capacités, voici une ou deux pistes que je compte explorer.

Les sources

Ces sources sont librement utilisables sous licence GNU LGPL. N'hésitez pas à me contacter si ce n'est pas clair (je suis quelquefois tortueux...).

Form.php

<?php /* Copyright (C) 2003 Laurent Godard oooconv@free.fr This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache"); error_reporting (E_ALL); echo("<html><head><meta http-equiv=\"Content-Type\" "); echo("content=\"text/html; charset=iso-8859-1\">"); echo (" <style type=\"text/css\"><!-- A:link {text-decoration: none;} A:visited {text-decoration: none;} A:active {text-decoration: none;} A:hover {text-decoration: none; color:red;} --></style> "); // logo echo("</head><body bgcolor=\"#D3ECFF\">"); echo("<center><img src=\"ooobanner.gif\" border=\"1\"></center>"); echo("<br><br>"); //Chargement du fichier de langue //Load the language file $IndPage="2"; include "tradOOO.inc"; //ajout pour oooconv.de $lang=$_POST['lang']; $trad=ChargeLang($lang, $IndPage); //Recherche du chemin Prod/Dev - seeking for root prod/Dev $a=strpos($_SERVER['PATH_TRANSLATED'],"form.php"); $racine=substr($_SERVER['PATH_TRANSLATED'],0,$a); //Renseignez ici le chemin absolu du répertoire http de OOOconv $oooconv_home="/home/httpd/oooconv.de/engine/"; $nom_fichier=$_FILES["file"]["name"]; $nom_fichier=str_replace(" ","-",$nom_fichier); $nom_fichier=str_replace(",","-",$nom_fichier); $nom_fichier=str_replace("'","-",$nom_fichier); for ($i = 0 ; $i<strlen($nom_fichier) ; $i++) { $chaine=substr($nom_fichier,$i,1); if((ord($chaine)<32)||(ord($chaine)>128)) { $nom_fichier=substr_replace($nom_fichier,"_",$i,1); } } //code de session - session code $code=UniqueID(); //Creation du repertoire de session - Create session directory $chemin=$racine . "temp/$code"; mkdir ( $chemin , 0777); $dest="temp/$code/" . $nom_fichier; $retour = move_uploaded_file ($_FILES['file']['tmp_name'] , $dest ); echo("<b>" . $nom_fichier . "</b> : $trad[1]"); //code de session - session code $code=UniqueID(); $type_doc = $_POST['type_doc']; //Cherche l'extension du fichier généré - Look for the file extension of the generated file $ExtFin=TrouveExtension($dest,$type_doc,$IsZip,$ExtSrc); //Test de compatibilité de l'export - Export compatibility test if($ExtFin=="") { echo("<br><br><b><font size=\"+1\" color=\"red\">"); echo("$trad[2]"); echo("<br><br>$trad[3]"); echo("<br><br>$trad[4]"); echo("</font></b>"); echo("<br><br>"); $retour="<b><u><a href='javascript:history.back()'> $trad[5] </a></u></b>"; echo("$retour"); exit; }; //cas des fichiers resultats multiples - Multiple output files if ($IsZip !=0){ //$chemin=$racine . "temp\\$code.$type_doc"; $chemin=$racine . "temp/$code/$type_doc"; mkdir ( $chemin , 0777); if ($type_doc=="TEX"){ copy("writer.sty",$chemin."/writer.sty"); }; }; // Appel de la macro par transforme.bat contenant juste la ligne suivante // call the macro via transforme.bat that only contains the following line // "<ooo path>\program\soffice.exe" macro:///convOOO.Module1.Test("%1,%2,%3") echo("<br><br>"); echo("$trad[6]"); $execution=" HOME=\"/home/httpd\" ".$oooconv_home."transforme.sh ". $racine.$dest ; $execution = $execution . " " . $type_doc . " " . $code ; $execution = $execution . " 2>&1 > /tmp/test.txt"; exec( $execution ); echo("<br>"); //Test de bon déroulement du script == Existence du fichier cible // Test correct execution of the script $erreur=0; //Fichier de stats - Stat file log $fp = fopen("Stats.log", "a+"); $string ="\n".date("Y/m/d H:i:s")."|$ExtSrc|$type_doc|$erreur|$lang"; $write = fputs($fp, $string); fclose($fp); if ($erreur==0) { $filename = $racine.$dest.$ExtFin; $AjoutHTML=""; if ($IsZip !=0) { $AjoutHTML=".zip"; } //liens de fin - end links echo("<br><br>"); $fic=""; if ($IsZip!=0) { echo("$trad[8]"); echo("<br><br>"); $fic="temp/$code/$type_doc/$nom_fichier$ExtFin"; //zip repertoire - zip directory ZipRepertoire("temp/".$code."/".$type_doc, $nom_fichier .$ExtFin, $code); //creation de la page de consultation - creating the viewing page if ($IsZip==2) { $string = "<html><body bgcolor=\"#D3ECFF\">"; $string.="<font size=\"+1\"><b>$trad[9]</b></font><br><br>"; //examen du repertoire - scanning the directory $rep=$racine."temp/$code/$type_doc"; if ($dh = opendir($rep)) { while (($f = readdir($dh)) !== false) { if ($f!="." and $f!="..") { $string.="<br><a href=\"$f\">$f</a>"; } } closedir($dh); } $string .="<br><br><a href=\"../$nom_fichier$ExtFin$AjoutHTML\; $string .=">$trad[10]</a>"; $string .="<br><br><a href='javascript:history.go(-2)'>$trad[5]</a>"; $fic="temp/$code/$type_doc/voir.html"; $fp = fopen($racine."/temp/$code/$type_doc/voir.html", "w"); $write = fputs($fp, $string); fclose($fp); } else { $string ="<br><a href=\"temp/$code/$nom_fichier$ExtFin$AjoutHTML\; $qtring .=">$trad[10]</a><br><br>"; echo($string); } } else { $fic= $dest.$ExtFin; } } $retour="<b><u><a href=\"$fic\"> $trad[11] </a></u></b>"; echo("$retour"); echo("<br><br>"); $retour="<b><u><a href='javascript:history.back()'> $trad[5] </a></u></b>"; echo("$retour"); echo("</body></html>"); // //----------------------------------------------------------------------------------------- //Fin du script //end of the script //----------------------------------------------------------------------------------------- // function TrouveExtension($dest,$type_doc,&$IsZip,&$ExtSrc){ //recherche de l'extension cible suivant le format d'entré sxc ou sxw //et le type d'export demandé //look for the target file extension according to the entrance file extension // and the kind of export required $ExtSrc =strtoupper(substr($dest,-3)); $ExtFin=""; $IsZip=0; switch ($ExtSrc) { case "SXC" : case "STC" : case "SDC" : switch($type_doc) { case "PDF": $ExtFin=".pdf"; break; case "MSXP": case "MS95": case "MS50": $ExtFin=".xls"; break; case "HTML": $ExtFin=".html"; $IsZip=1; break; }; break; case "SXW" : case "STW" : case "SDW" : case "VOR" : switch($type_doc) { case "PDF": $ExtFin=".pdf"; break; case "MSXP": case "MS95": case "MS60": $ExtFin=".doc"; break; case "RTF": $ExtFin=".rtf"; break; case "HTML": $ExtFin=".html"; $IsZip=1; break; case "XHTML": $ExtFin=".xhtml"; $IsZip=2; break; case "TEX": $ExtFin=".tex"; $IsZip=2; break; }; break; case "SXI" : case "STI" : case "SDP" : switch($type_doc) { case "PDF": $ExtFin=".pdf"; break; case "MSXP": $ExtFin=".ppt"; break; case "HTML": $ExtFin=".html"; $IsZip=1; break; case "JPG": $ExtFin=".jpg"; $IsZip=2; break; case "PNG": $ExtFin=".png"; $IsZip=2; break; case "TIFF": $ExtFin=".tif"; $IsZip=2; break; case "SVG": $ExtFin=".svg"; $IsZip=2; break; case "EPS": $ExtFin=".eps"; $IsZip=2; break; case "SWF": $ExtFin=".swf"; $IsZip=2; break; }; break; case "SXD" : case "STD" : case "SDD" : case "SDA" : switch($type_doc) { case "PDF": $ExtFin=".pdf"; break; case "JPG": $ExtFin=".jpg"; $IsZip=2; break; case "PNG": $ExtFin=".png"; $IsZip=2; break; case "TIFF": $ExtFin=".tif"; $IsZip=2; break; case "EPS": $ExtFin=".eps"; $IsZip=2; break; case "SVG": $ExtFin=".svg"; $IsZip=2; break; case "SWF": $ExtFin=".swf"; $IsZip=2; break; }; break; }; return $ExtFin; } // ---------------------------------------------------------------------------- function UniqueID() { $id="uniqueID"; $i=0; srand(time()); $a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; for($i; $i<=16; $i++) { $id.=substr($a, (rand()%(strlen($a))),1); } return(md5($id)); } // ---------------------------------------------------------------------------- function ZipRepertoire($rep, $FichierFin,$code){ require("pclzip.lib.php3"); $fichier=array(); /* Liste les fichiers - File list */ $i=-1; if ($dh = opendir($rep)) { while (($file = readdir($dh)) !== false) { if ($file!="." and $file!=".." and $file!="voir.html"){ $i+=1; $fichier[$i] = $rep."/".$file; }; } closedir($dh); }; $fichier_zip = "temp/$code/".$FichierFin.".zip"; // nom du fichier zip a obtenir - zip file name to get // On crée un nouvel objet zip de la classe zipfile // create a new zip object having the zipfile class $zip= new pclzip($fichier_zip); // On efface l'ancienne archive si zip.zip existe déja // (sinon les fichiers identiques sont ajoutés en fin d'archive !!!) // delete old archive if zip.zip already exists // (otherwise the files are added to the end of the archive !!!) $taille = sizeof($zip->listContent()) -1; $zip->deleteByIndex(0-$taille); // On lui ajoute le fichier voulu avec ou sans chemin pour l'extraction // then add the desired file with or without its path for extraction $zip->add($fichier,$FichierFin,$rep); }; ?>

Macro

'************************************************ 'Copyright (C) 2003 Laurent Godard 'oooconv@free.fr 'This library is free software; you can redistribute it and/or 'modify it under the terms of the GNU Lesser General Public 'License as published by the Free Software Foundation; either 'version 2.1 of the License, or (at your option) any later version. 'This library is distributed in the hope that it will be useful, 'but WITHOUT ANY WARRANTY; without even the implied warranty of 'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 'Lesser General Public License for more details. 'You should have received a copy of the GNU Lesser General Public 'License along with this library; if not, write to the Free Software 'Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA '************************************************ dim FilterName as string dim ExtDESt as string dim FichDest as string Sub Exporte(fichier, typedoc,code) call DefinirFiltre(fichier, typedoc,code) call TransformeDocument(fichier,TypeDoc,code) End Sub sub DefinirFiltre(fichier, typedoc,code) 'Determine quel type d'export faire ExtSRC=lcase(right(fichier,3)) fichdest=fichier Select case ExtSRc case "sxc","stc","sdc": select case typedoc case "PDF": FilterName="calc_pdf_Export" ExtDESt=".pdf" case "MSXP": FilterName="MS Excel 97" ExtDESt=".xls" case "MS95": FilterName="MS Excel 95" ExtDESt=".xls" case "MS50": FilterName="MS Excel 5.0/95" ExtDESt=".xls" case "HTML": FilterName="HTML (StarCalc)" ExtDESt=".html" FichDest=TrouveNomRep(fichier,code,typedoc) end select case "sxw","vor","stw","sdw": select case typedoc case "PDF": FilterName="writer_pdf_Export" ExtDESt=".pdf" case "MSXP": FilterName="MS Word 97" ExtDESt=".doc" case "MS95": FilterName="MS Word 95" ExtDESt=".doc" case "MS60": FilterName="MS WinWord 6.0" ExtDESt=".doc" case "RTF": FilterName="Rich Text Format" ExtDESt=".rtf" case "HTML": FilterName="HTML (StarWriter)" ExtDESt=".html" FichDest= TrouveNomRep(fichier,code,typedoc) case "XHTML": FilterName="XHTML plus MathML File" ExtDESt=".xhtml" FichDest= TrouveNomRep(fichier,code,typedoc) case "TEX": FilterName="Latex File" ExtDESt=".tex" FichDest= TrouveNomRep(fichier,code,typedoc) end select case "sxi","sti","sdd","sdp": select case typedoc case "PDF": FilterName="impress_pdf_Export" ExtDESt=".pdf" case "MSXP": FilterName="MS Powerpoint 97" ExtDESt=".ppt" case "JPG": FilterName="image/jpeg" ExtDESt=".jpg" FichDest= TrouveNomRep(fichier,code,typedoc) case "PNG": FilterName="image/png" ExtDESt=".png" FichDest= TrouveNomRep(fichier,code,typedoc) case "TIFF": FilterName="image/tiff" ExtDESt=".tif" FichDest= TrouveNomRep(fichier,code,typedoc) case "SVG": FilterName="image/svg+xml" ExtDESt=".svg" FichDest= TrouveNomRep(fichier,code,typedoc) case "EPS": FilterName="application/postscript" ExtDESt=".eps" FichDest= TrouveNomRep(fichier,code,typedoc) case "SWF": FilterName="impress_flash_Export" ExtDESt=".swf" FichDest= TrouveNomRep(fichier,code,typedoc) end select case "sxd","std","sda","sdd": select case typedoc case "PDF": FilterName="draw_pdf_Export" ExtDESt=".pdf" case "JPG": FilterName="image/jpeg" ExtDESt=".jpg" FichDest= TrouveNomRep(fichier,code,typedoc) case "PNG": FilterName="image/png" ExtDESt=".png" FichDest= TrouveNomRep(fichier,code,typedoc) case "TIFF": FilterName="image/tiff" ExtDESt=".tif" FichDest= TrouveNomRep(fichier,code,typedoc) case "SVG": FilterName="image/svg+xml" ExtDESt=".svg" FichDest= TrouveNomRep(fichier,code,typedoc) case "EPS": FilterName="application/postscript" ExtDESt=".eps" FichDest= TrouveNomRep(fichier,code,typedoc) case "SWF": FilterName="draw_flash_Export" ExtDESt=".swf" FichDest= TrouveNomRep(fichier,code,typedoc) end select end select end sub sub TransformeDocument(fichier,TypeDoc,code) on error resume next dim args() 'dim args(0) as new com.sun.star.beans.PropertyValue 'args(0).Name = "Hidden" 'args(0).Value = True dim oDesktop as object, oDocument as object dim surl as string oDesktop=createUnoService("com.sun.star.frame.Desktop") sURL=ConvertToURL(fichier) oDocument=oDesktop.loadComponentFromURL(surl,"_blank",0,args()) on error goto fin fichdest=ConvertToUrl(fichdest) select case typedoc 'graphical exports case "JPG", "PNG", "TIFF","EPS","SVG": oGraphic=CreateUnoService("com.sun.star.drawing.GraphicExportFilter") dim args3(1) as new com.sun.star.beans.PropertyValue for i=0 to odocument.drawpages.getcount()-1 opage=odocument.drawPages(i) ographic.setSourceDocument(opage) args3(0).Name = "URL" nom=opage.name url = ConvertToURL(fichdest+"-"+RemplaceChaine(nom," ","")+ ExtDest) args3(0).Value = url args3(1).Name = "MediaType" args3(1).Value = filtername oGraphic.filter(args3()) next i 'all other exports case else: dim args2(1) as new com.sun.star.beans.PropertyValue args2(0).Name = "InteractionHandler" args2(0).Value = "" args2(1).Name = "FilterName" args2(1).Value = FilterName NomFichier = ConvertToUrl(fichdest + ExtDest) wait(100) odocument.storeToURL(NomFichier,args2()) end select wait(100) oDocument.dispose() exit sub fin: on error resume next oDocument.dispose() end sub function CorrigeNom(chaine as string) as string 'Remplace les antislash chaine=remplacechaine(chaine,"\","/") 'Remplace les deux points chaine=remplacechaine(chaine,":","|") CorrigeNom=chaine end function function TrouveNomRep(chemin as string,code as string,typedoc as string) as string i=instr(1,chemin,"/temp/"+code+"/")+len("/temp/"+code+"/")-1 j=len(chemin)+1 nomfichier=mid(chemin,i,j-i) TrouveNomRep=mid(chemin,1,i)+typedoc+nomfichier end function function RemplaceChaine(chaine as string,src as string, dest as string) 'remplace toutes les occurences de src par dest dans chaine i=1 lsrc = len(src) ldest = len(dest) while i<>0 i = instr(i,chaine,src) if i<>0 then imax = len(chaine) avant=mid(chaine,1,i-1) apres=mid(chaine,i+lsrc,imax-i) chaine=avant + dest +apres i=i+ldest-lsrc+1 end if wend RemplaceChaine=chaine end function

Télécharger OOoConv