3 if (!defined('_ECRIRE_INC_VERSION')) {
8 * Indique si la commande 'libreoffice' est disponible sur ce serveur
11 function odt2spip_commande_libreoffice_disponible() {
12 static $est_disponible = null;
13 if (is_null($est_disponible)) {
14 if (defined('_LIBREOFFICE_PATH') and _LIBREOFFICE_PATH
) {
15 $est_disponible = true;
17 $est_disponible = (bool)odt2spip_obtenir_commande_serveur('libreoffice');
20 return $est_disponible;
24 * Obtient le chemin d'un executable sur le serveur.
26 * @param string $command
29 * Chemin de la commande
31 function odt2spip_obtenir_commande_serveur($command) {
32 static $commands = array();
34 if (array_key_exists($command, $commands)) {
35 return $commands[$command];
38 exec("which $command", $output, $err);
39 if (!$err and count($output) and $cmd = trim($output[0])) {
40 spip_log("Commande '$command' trouvée dans $cmd", 'odtspip.' . _LOG_DEBUG
);
41 return $commands[$command] = $cmd;
44 spip_log("Commande '$command' introuvable sur ce serveur…", 'odtspip.' . _LOG_DEBUG
);
45 return $commands[$command] = '';
50 * Indique si une clé est autorisée à utiliser ce site comme
51 * serveur de conversion
53 function odt2spip_cle_autorisee($key) {
54 include_spip('inc/config');
55 // récupérer la liste des clés
56 $keys = lire_config('odt2spip/authorized_keys');
57 $keys = explode("\n", trim($keys));
58 $keys = array_filter(array_map('trim', $keys));
60 foreach ($keys as $line) {
61 list($k, $nom) = explode(':', $line, 2);
62 $liste[trim($k)] = trim($nom);
64 // tester si la clé est correcte
65 $ok = in_array($key, array_keys($liste));
67 spip_log('Cle autorisée du site : ' . $liste[$key], 'odtspip.' . _LOG_INFO
);
69 spip_log('Cle invalide utilisée : ' . $key, 'odtspip.' . _LOG_INFO
);
71 // maintenir un temps fixe d’exécution, si possible
72 if (function_exists('hash_equals')) {
73 hash_equals($key, $key);
79 * Indique si un convertisseur de document est disponible
82 * - la commande libreoffice est disponible
83 * - OU un serveur de conversion est indiqué
87 function odt2spip_convertisseur_disponible() {
88 static $est_disponible = null;
89 if (is_null($est_disponible)) {
90 include_spip('inc/config');
91 if (odt2spip_commande_libreoffice_disponible()) {
92 $est_disponible = true;
94 function_exists('curl_file_create') // php 5.5+
95 and lire_config('odt2spip/serveur_api_url')
96 and lire_config('odt2spip/serveur_api_cle')
98 $est_disponible = true;
100 $est_disponible = false;
103 return $est_disponible;
107 * Retourne la liste des extensions de documents acceptées
108 * @param bool $accept True pour retourner au format 'accept' d’html5
109 * @return string|string[]
111 function odt2spip_liste_extensions_acceptees($accept = false) {
112 if (odt2spip_convertisseur_disponible()) {
113 // TODO: vérifier la liste des extensions possibles
114 $liste = array('odt', 'doc', 'docx', 'html');
116 $liste = array('odt');
119 return '.' . implode(',.', $liste);
126 * Retourne le répertoire de stockage des documents à traiter
130 function odt2spip_get_repertoire_temporaire() {
131 // ss-rep temporaire specifique de l'auteur en cours: tmp/odt2spip/id_auteur/
132 // => le créer s'il n'existe pas
133 $base_dezip = _DIR_TMP
. 'odt2spip/'; // avec / final
134 if (!is_dir($base_dezip) and !sous_repertoire(_DIR_TMP
, 'odt2spip')) {
135 throw new \
Exception(_T('odtspip:err_repertoire_tmp'));
138 include_spip('inc/session');
139 $id_auteur = (int)session_get('id_auteur');
140 $rep_dezip = $base_dezip . $id_auteur . '/';
142 if (!is_dir($rep_dezip) and !sous_repertoire($base_dezip, $id_auteur)) {
143 throw new \
Exception(_T('odtspip:err_repertoire_tmp'));
146 // $rep_pictures = $rep_dezip.'Pictures/';
151 * Déplace un fichier posté dans un répertoire temporaire de travail
155 function odt2spip_deplacer_fichier_upload($key) {
156 $rep_dezip = odt2spip_get_repertoire_temporaire();
158 // traitement d'un fichier envoyé par $_POST
160 empty($_FILES[$key]['name'])
161 or $_FILES[$key]['error'] != 0
162 or !($fichier = $rep_dezip . addslashes($_FILES[$key]['name']))
164 throw new \
Exception(_T('odtspip:err_telechargement_fichier'));
167 include_spip('inc/documents');
168 if (!deplacer_fichier_upload($_FILES[$key]['tmp_name'], $fichier, true)) {
169 throw new \
Exception(_T('odtspip:err_telechargement_fichier'));
176 * Dézippe un fichier dans le répertoire temporaire d’odt2spip
177 * @param string $fichier Chemin du fichier ODT
181 function odt2spip_deziper_fichier($fichier) {
182 $rep_dezip = odt2spip_get_repertoire_temporaire();
184 // dezipper le fichier odt a la mode SPIP
185 include_spip('inc/pclzip');
186 $zip = new \
PclZip($fichier);
190 PCLZIP_OPT_SET_CHMOD
,
192 PCLZIP_OPT_REPLACE_NEWER
195 if ($zip->error_code
< 0) {
196 spip_log('charger_decompresser erreur zip ' . $zip->error_code
. ' pour fichier ' . $fichier, 'odtspip.' . _LOG_ERREUR
);
197 throw new \
Exception($zip->errorName(true));
204 * Intègre le contenu du fichier dans l’objet indiqué (ou un nouvel enfant)
206 * @param string $fichier
207 * @param string $objet
208 * @param int $id_objet
209 * @param string $objet_dest Nouvel objet enfant, si indiqué
210 * @param array $options {
211 * @var bool attacher_fichier
214 * @var bool|int $id_objet ou fales,
215 * @var string|null $errors,
218 function odt2spip_integrer_fichier($fichier, $objet, $id_objet, $objet_dest = '', $options = array()) {
219 list($champs, $erreurs) = odt2spip_analyser_fichier($fichier);
221 return array(false, $erreurs);
223 // si necessaire créer l'objet
225 include_spip('action/editer_objet');
226 $id_objet = objet_inserer($objet_dest, $id_objet);
227 $objet = $objet_dest;
229 return array(false, _T('odtspip:err_creer_nouvel_objet'));
233 odt2spip_objet_modifier($fichier, $objet, $id_objet, $champs, $options);
235 // vider le contenu du rep de dezippage
236 include_spip('inc/getdocument');
237 effacer_repertoire_temporaire(odt2spip_get_repertoire_temporaire());
239 // identifiant d’objet créé éventuellement.
240 return array($id_objet, null);
244 * Analyse le fichier ODT transmis
245 * @param string $fichier Chemin vers le fichier ODT
248 function odt2spip_analyser_fichier($fichier) {
250 if (!odt2spip_deziper_fichier($fichier)) {
251 return array(false, _T('odtspip:err_decompresser_fichier'));
253 } catch (\Exception
$e) {
254 return array(false, _T('odtspip:err_decompresser_fichier'));
258 $rep_dezip = odt2spip_get_repertoire_temporaire();
259 } catch (\Exception
$e) {
260 return array(false, _T('odtspip:err_repertoire_temporaire'));
263 // Création de l'array avec les parametres de l'article:
264 // c'est ici que le gros de l'affaire se passe!
265 $odt2spip_generer_sortie = charger_fonction('odt2spip_generer_sortie', 'inc');
267 $champs = $odt2spip_generer_sortie($rep_dezip, $fichier);
268 } catch (\Exception
$e) {
269 spip_log($e->getMessage(), 'odtspip.' . _LOG_ERREUR
);
270 return array(false, _T('odtspip:err_analyse_odt'));
273 return array($champs, null);
277 * Modifie le contenu d’un objet avec les champs indiqués
279 * Note qu’une clé contient la liste des images.
281 * @param string $fichier
282 * @param string $objet
283 * @param int $id_objet
285 * @param array $options
288 function odt2spip_objet_modifier($fichier, $objet, $id_objet, $set, $options = array()) {
291 include_spip('action/editer_objet');
292 objet_modifier($objet, $id_objet, $set);
294 // si necessaire recup les id_doc des images associées et les lier à l'article
295 if (!empty($set['Timages']) > 0) {
296 foreach ($set['Timages'] as $id_img) {
298 'parents' => array($objet . '|' . $id_objet),
301 document_modifier($id_img, $champs);
305 // si nécessaire attacher le fichier source à l'article
306 if (!empty($options['attacher_fichier']) and !empty($options['fichier_source'])) {
307 odt2spip_objet_lier_fichier($options['fichier_source'], $objet, $id_objet, $set['titre']);
310 // si nécessaire attacher le fichier odt généré à l'article
312 !empty($options['attacher_fichier_odt']) and !empty($options['fichier_source'])
313 and ($fichier != $options['fichier_source'] or !empty($options['attacher_fichier']))
315 odt2spip_objet_lier_fichier($fichier, $objet, $id_objet, $set['titre']);
322 * Lie un fichier en tant que document d’un objet.
324 * @param string $fichier
325 * @param string $objet
326 * @param int $id_objet
327 * @param string $titre
329 function odt2spip_objet_lier_fichier($fichier, $objet, $id_objet, $titre) {
330 $ajouter_documents = charger_fonction('ajouter_documents', 'action');
331 $id_document = $ajouter_documents(
335 'tmp_name' => $fichier,
336 'name' => basename($fichier),
348 and $id_doc_odt = intval($id_document[0])
349 and $id_doc_odt == $id_document[0]
353 'descriptif' => _T('odtspip:cet_article_version_odt'),
356 document_modifier($id_doc_odt, $c);
361 * Convertir un fichier vers le format odt en utilisant
362 * un outil de conversion, local ou distant
364 * @param string $fichier_source
365 * @return string|bool
367 function odt2spip_convertir_fichier($fichier_source) {
368 if (!odt2spip_convertisseur_disponible()) {
371 if (odt2spip_commande_libreoffice_disponible()) {
372 include_spip('inc/convertir_avec_libreoffice');
373 $fichier = convertir_avec_libreoffice($fichier_source, 'odt');
376 if ($fichier = odt2spip_convertir_fichier_par_api($fichier_source)) {
383 * Convertir un fichier vers le format odt en utilisant
384 * un serveur distant de conversion
386 * @param string $fichier_source
387 * @return string|bool
389 function odt2spip_convertir_fichier_par_api($fichier_source, $format = 'odt') {
390 include_spip('inc/config');
391 $api_url = lire_config('odt2spip/serveur_api_url');
392 $api_key = lire_config('odt2spip/serveur_api_cle');
393 if (!$api_url or !$api_key) {
396 $api_url = rtrim($api_url, '/') . '/convert_to.api/' . $format;
399 'api_key' => $api_key,
400 'file'=> curl_file_create(realpath($fichier_source))
403 // Poster la requête et récupérer le contenu du fichier
404 // FIXME: idéalement il faudrait streamer le fichier retourné… mais comment ?
406 curl_setopt($ch, CURLOPT_URL
, $api_url);
407 curl_setopt($ch, CURLOPT_POST
, 1);
408 curl_setopt($ch, CURLOPT_POSTFIELDS
, $post);
409 curl_setopt($ch, CURLOPT_RETURNTRANSFER
, 1);
410 curl_setopt($ch, CURLOPT_BINARYTRANSFER
, 1);
411 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER
, false);
412 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST
, false);
413 $content = curl_exec($ch);
416 // Écrire le nouveau fichier localement
418 $fichier = dirname($fichier_source) . DIRECTORY_SEPARATOR
. pathinfo($fichier_source, PATHINFO_FILENAME
) . '.' . $format;
419 if (file_put_contents($fichier, $content)) {
420 spip_log('Fichier converti dans : ' . $fichier, 'odtspip.' . _LOG_DEBUG
);