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.
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.
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...
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.
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 :
oDocument=oDesktop.loadComponentFromURL(surl,"_blank",0,Noargs())
Ce que je cherche à avoir, c'est une référence sur oDocument mais sans qu'il soit visible. Un peu comme le mode -invisible quand on lance OpenOffice.org en ligne de commande.dim args(0) as new com.sun.star.beans.PropertyValue
args(0).Name = "Hidden"
args(0).Value = True
dim tab() as string
oGraphic=CreateUnoService("com.sun.star.drawing.GraphicExportFilter")
tab=ographic.getSupportedMimeTypeNames()
for i=0 to ubound(tab)
msgbox(tab(i))
next i
Voir la Macro pour leur utilisation.sub ExportDocumentPDF
rem -----------------------------------------------------
rem define variables
dim doc as object, desktop as object
dim args() as new com.sun.star.beans.PropertyValue
rem -----------------------------------------------------
rem get access to the document
oDesktop=createUnoService("com.sun.star.frame.Desktop")
sUrl="file:///test.sxw"
doc=oDesktop.loadComponentFromURL(surl,"_blank",0,args())
rem -----------------------------------------------------
Dim PDFArgs(1) as new com.sun.star.beans.PropertyValue
PDFArgs(0).Name = "FilterName"
PDFArgs(0).Value = "writer_pdf_Export"
PDFArgs(1).Name = "CompressMode"
PDFArgs(1).Value = 0 'Valeurs possibles : 0 - 1 - 2
doc.storeToURL("file:///test.pdf",PDFArgs())
doc.dispose()
end sub
De plus, il y a une ressource (XML) très utile dans les répertoires d'OpenOffice.org.Si vous avez des questions et surtout des réponses, n'hésitez pas à m'envoyer un mail.
Dans la mesure de mes capacités, voici une ou deux pistes que je compte explorer.
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...).
<?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);
};
?>
'************************************************
'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