source: spip-zone/_plugins_/oficina/action/oficina_api_v1.php

Last change on this file was 76826, checked in by lesage.sylvain@…, 6 years ago

Nouveau plugin "oficina" écrit par _fil_

C'est le code de http://office.spip.net.
Voir aussi http://seenthis.net/messages/126350 et INSTALL.md

File size: 10.2 KB
Line 
1<?php
2
3/*
4 *
5
6 curl "http://site/?email=user@server.tld&key=b375bb198e1b59667a3713cd464941f029c32234&url=http://nanolinenturkey.org/v1/bursaries.docx"
7 
8 # &format=json pour debug ou communiquer proprement
9
10 # &filter=readability,tidy,spip,sale pour appliquer les filtres
11 # ou &filter[]=readability&filter[]=sale
12
13 il faut cliquer sur http://site/?action=cron pour activer les jobs
14
15
16 *
17 */
18
19
20 
21function action_oficina_api_v1_dist() {
22        $r = oficina_v1_traiter(_request('signature'));
23
24        if (_request('format') == 'json') {
25                header('Content-Type: text/plain; charset=utf8');
26                echo json_encode($r);
27        } else if (_request('format') == 'dl') {
28                include_spip('inc/headers');
29                http_status($r['code']);
30
31                if ($r['content']) {
32                        header('Content-Type: text/html; charset=utf8');
33                        echo $r['content'];
34                }
35                else {
36                        echo $r['message'];
37                }
38        }
39        else {
40                header('Content-Type: text/html; charset=utf8');
41                echo $r['code'].": ".$r['message'];
42                echo oficina_form();
43                if ($r['content']) {
44                        echo "<hr />". $r['content'];
45                }
46        }
47
48        flush();
49
50        cron();
51}
52
53
54function oficina_v1_traiter($signature='') {
55        include_spip('inc/filtres_mini');
56
57        // verifier la cle
58        include_spip('inc/securiser_action');
59        if ($_REQUEST['key'] != oficina_key($_REQUEST['email'])) {
60                return array(
61                        'code' => '403', # Forbidden
62                        'message' => 'Please authenticate with your email and API key',
63                        'debug' => var_export($_REQUEST,true),
64                );
65        }
66
67        /*
68         * permettre de solliciter des clés pour autrui
69         */
70        if ($for = _request('for')
71        AND _request('email') == 'admin@server.tld'  # todo : autoriser()
72        ) {
73                return array(
74                        'code' => 200,
75                        'message' => 'key for '.htmlspecialchars($for).' = '.oficina_key($for)
76                );
77        }
78
79        $tmp = sous_repertoire(_DIR_TMP, 'oficina');
80        $tmp = sous_repertoire($tmp, _request('email'));
81        define ('_DIR_OFICINA', $tmp);
82
83        // method       = GET
84        if (!$_FILES) {
85
86                if ($url = _request('url')
87                AND preg_match(',^https?://,', $url)) {
88                        if (strlen($signature) == 0)
89                                $signature = md5($url);
90                }
91
92
93                if (strlen($signature) == 0) {
94                        return array(
95                                'code' => 404, # Not Found
96                                'message' => 'Please give me something (url or file)'
97                        );
98                }
99
100                $dest = md5($signature);
101
102                if (file_exists($convert = _DIR_OFICINA.$dest.'.html')) {
103                        $html = file_get_contents($convert);
104                        $html = oficina_images($html, _request('images'));
105
106                        $html = oficina_filtrer($html, _request('filter'));
107
108                        return array(
109                                'code' => 200, # OK
110                                'message' => 'Here is your file',
111                                'content' => $html,
112                        );
113                }
114
115                // en cours de download
116                if ($url) {
117                        if (@file_exists($tmpu = _DIR_OFICINA.$dest.'.url')) {
118                                if (count(glob(_DIR_OFICINA.$dest.'.*')) == 1) {
119                                        return array(
120                                                'code' => 204, # No Content
121                                                'message' => 'Please wait for download to finish',
122                                        );
123                                }
124                        // lancer le chargement ?
125                        } else {
126                                ecrire_fichier($tmpu, $url);
127                                oficina_lancer_chargement($url);
128                                return array(
129                                        'code' => 204, # Not Found
130                                        'message' => 'Starting download',
131                                );
132                        }
133                }
134
135                if (file_exists($convert = _DIR_OFICINA.$dest.'.json')) {
136                        return array(
137                                'code' => 404, # OK
138                                'message' => 'URL did not return a file',
139                        );
140                }
141
142
143                // en cours de conversion ou pas
144                if (glob(_DIR_OFICINA.$dest.'.*')) {
145                        return array(
146                                'code' => 204, # No Content
147                                'message' => 'Please wait for conversion',
148                        );
149                }
150
151                return array(
152                        'code' => 404, # Not Found
153                        'message' => 'Please upload a file',
154                );
155        }
156       
157        // upload
158        if ($_FILES) {
159                // accepter ou pas
160                foreach ($_FILES as $file) {
161                        $tmp = _DIR_OFICINA.'tmp.'.getmypid();
162                        if (@move_uploaded_file($file['tmp_name'], $tmp)) {
163                                #$finfo = new finfo(FILEINFO_MIME);
164                                #$fres = $finfo->file($file);
165                                #$fres = mime_content_type($tmp);
166                                #$fres = exec("file $tmp");
167
168                                preg_match(',\.([^.]*)$,', $file['name'], $r);
169                                $ext = $r[1];
170
171                                switch($ext) {
172                                        case 'html':
173                                        case 'htm':
174                                                $ext = 'html';
175                                                break;
176                                        case 'docx':
177                                        case 'doc':
178                                        case 'rtf':
179                                        case 'odt':
180                                                break;
181                                        default:
182                                                return array(
183                                                        'code' => 406, # Not Acceptable ?
184                                                        'message' => 'File format rejected: '.var_export($file,true),
185                                                );
186                                }
187
188                                if (strlen($signature)==0)
189                                        $signature = md5_file($tmp);
190
191                                $dest = md5($signature).'.'.$ext;
192                                rename($tmp, _DIR_OFICINA.$dest);
193
194                                oficina_lancer_conversion(_DIR_OFICINA.$dest);
195                                $url =  url_absolue($signature, url_absolue($_SERVER['REQUEST_URI']));
196
197                                return array(
198                                        'code' => 201, # Created
199                                        'message' => 'File accepted. '.$url,
200                                        'url' => $url,
201#                                       'local' => $dest, # debug
202                                );
203                        }
204                }
205        }
206
207}
208
209
210// s'il y a job_queue, creer le job, sinon lancer tout de suite
211function oficina_lancer_conversion($local) {
212        include_spip('inc/queue');
213        if ($_REQUEST['no_queue'] OR !function_exists('queue_add_job')) {
214                include_spip('inc/oficina');
215                oficina_convertir($local);
216        } else {
217                queue_add_job('oficina_convertir', 'convertir '.$local, array($local), 'action/oficina_api_v1' /* 'inc/oficina' */, $no_duplicate = true);
218        }
219}
220
221// lancer le download d'une URL
222function oficina_lancer_chargement($url) {
223        include_spip('inc/queue');
224        if ($_REQUEST['no_queue'] OR !function_exists('queue_add_job')) {
225                include_spip('inc/oficina');
226                oficina_charger($url);
227        } else {
228                queue_add_job('oficina_charger', 'charger '.$url, array($url), 'action/oficina_api_v1' /* 'inc/oficina' */, $no_duplicate = true);
229        }
230}
231
232
233# a mettre dans inc/oficina
234
235function oficina_charger($url) {
236        $mark = _DIR_OFICINA.md5(md5($url));
237        $exts = array('txt', 'html', 'doc', 'docx', 'rtf', 'odt');
238
239        include_spip('inc/distant');
240
241        if ($a = recuperer_infos_distantes($url)
242#       AND $a['url'] = $url
243        AND ( in_array($ext = $a['extension'], $exts )
244                OR in_array($ext = preg_replace(',^.*\.,', '', $url), $exts )
245        )
246        AND $doc = recuperer_page($url)) {
247
248                $dest = $mark.'.'.$ext;
249                ecrire_fichier($dest, $doc);
250
251                return oficina_lancer_conversion($dest);
252        }
253        else {
254                $dest = $mark.'.json';
255                ecrire_fichier($dest, json_encode($a));
256                return false;
257        }
258}
259
260
261// calcule la version HTML du fichier $local, les images en lien
262function oficina_convertir($local) {
263        preg_match(',^(.*)\.([^.]+)$,', basename($local), $r);
264        $dir = dirname($local);
265        $base = $r[1];
266        $ext = $r[2];
267
268        switch($ext) {
269                case 'html':
270                        return true;
271                case 'doc':
272                case 'docx':
273                case 'rtf':
274                case 'odt':
275                        return oficina_unoconv($local);
276                default:
277                        return false;
278        }
279}
280
281// convertir via unoconv
282function oficina_unoconv($doc) {
283        exec($c = "unoconv --format=html $doc 2>&1", $output, $returnvar);
284        if ($returnvar) {
285                spip_log('err'.$c.': '.join("\n", $output), 'oficina');
286                return false;
287        }
288
289        // ici utiliser eventuellement tidy car le resultat n'est pas propre
290        # http://www.php.net/manual/fr/tidy.examples.basic.php
291
292        // + gerer les images
293
294        return true;
295}
296
297function oficina_images($html, $images) {
298        include_spip('inc/filtres');
299        foreach(extraire_balises(strtolower($html), 'img') as $img) {
300                if ($src = extraire_attribut($img, 'src')
301                AND preg_match(',^[0-9a-f_]+\w+\.(jpg|gif|png)$,', $src, $regs)) {
302                        if ($images
303                        AND $i = @file_get_contents(_DIR_OFICINA.$regs[0])) {
304                                $base64 = 'data:image/'.str_replace('jpg', 'jpeg', $regs[1]).';base64,'.base64_encode($i);
305                                $repl = inserer_attribut($img, 'src', $base64);
306                        }
307                        else
308                                $repl = extraire_attribut($img, 'alt');
309
310                        $html = preg_replace('/'.preg_quote($img,'/').'/i', $repl, $html);
311                }
312        }
313
314        return $html;
315}
316
317function oficina_filtrer($html, $filter) {
318        if (!is_array($filter))
319                $filter = explode(',', $filter);
320
321        foreach($filter as $f) {
322                switch($f) {
323
324                        case 'readability':
325                                include_spip('inc/readability');
326                                if (function_exists('readability_html'))
327                                        $html = readability_html($html);
328                                break;
329
330                        case 'tidy':
331                                $tidy = new tidy;
332                                $tidy->parseString($html, oficina_tidy_config(), 'utf8');
333                                $tidy->cleanRepair();
334                                $html = (string) $tidy;
335                                break;
336
337                        case 'spip':
338                        case 'sale':
339                                include_spip('inc/fonctionsale');
340                                if (function_exists('sale')) {
341                                        $html = sale($html);
342                                        if (!_request('format'))
343                                                $html = "<pre>".htmlspecialchars($html)."</pre>"; // pour affichage
344                                }
345                                break;
346                }
347        }
348
349        return $html;
350}
351
352function oficina_tidy_config() {
353        return array(
354        'show-body-only' => false,
355        'clean' => true,
356        'char-encoding' => 'utf8',
357        'add-xml-decl' => true,
358        'add-xml-space' => true,
359        'output-html' => false,
360        'output-xml' => false,
361        'output-xhtml' => true,
362        'numeric-entities' => false,
363        'ascii-chars' => false,
364        'doctype' => 'strict',
365        'bare' => true,
366        'fix-uri' => true,
367        'indent' => true,
368        'indent-spaces' => 4,
369        'tab-size' => 4,
370        'wrap-attributes' => true,
371        'wrap' => 0,
372        'indent-attributes' => true,
373        'join-classes' => false,
374        'join-styles' => false,
375        'enclose-block-text' => true,
376        'fix-bad-comments' => true,
377        'fix-backslash' => true,
378        'replace-color' => false,
379        'wrap-asp' => false,
380        'wrap-jste' => false,
381        'wrap-php' => false,
382        'write-back' => true,
383        'drop-proprietary-attributes' => true,
384        'hide-comments' => false,
385        'hide-endtags' => false,
386        'literal-attributes' => false,
387        'drop-empty-paras' => true,
388        'enclose-text' => true,
389        'quote-ampersand' => true,
390        'quote-marks' => false,
391        'quote-nbsp' => true,
392        'vertical-space' => true,
393        'wrap-script-literals' => false,
394        'tidy-mark' => true,
395        'merge-divs' => false,
396        'repeated-attributes' => 'keep-last',
397        'break-before-br' => true,
398    );
399}
400
401
402
403function oficina_form() {
404        return "<form method='get' action='./'>"
405
406                . "email: "
407                . "<input type='text' name='email' value='".htmlspecialchars(_request('email'))."' />"
408
409                . "<br/>key: "
410                . "<input type='text' name='key' value='".htmlspecialchars(_request('key'))."' />"
411
412                . "<br/>URL: "
413                . "<input type='text' name='url' value='".htmlspecialchars(_request('url'))."' /> (http://....[doc,docx,rtf,odt]) &nbsp; "
414                . "<input type='submit' />"
415
416                . "<br />format: "
417                . "<input type='text' name='format' value='".htmlspecialchars(_request('format'))."' /> (json,dl)"
418
419                . "<br />filter: "
420                . "<input type='text' name='filter' value='".htmlspecialchars(_request('filter'))."' /> (readability,tidy,sale)"
421
422                . "<br />images: "
423                . "<input type='checkbox' name='images'"
424                        .(_request('images') ? ' checked="checked"':'')
425                        ." /> (inline)"
426
427                . "</form>";
428
429}
430
Note: See TracBrowser for help on using the repository browser.