source: spip-zone/_plugins_/acces_restreint/trunk/action/api_docrestreint.php @ 84556

Last change on this file since 84556 was 84556, checked in by marcimat@…, 6 years ago

Petit reformattage pour y voir un rien plus clair dans la fonction api_docrestreint. À suivre...

File size: 5.7 KB
Line 
1<?php
2
3/***************************************************************************\
4 *  SPIP, Systeme de publication pour l'internet                           *
5 *                                                                         *
6 *  Copyright (c) 2001-2009                                                *
7 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
8 *                                                                         *
9 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
10 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
11\***************************************************************************/
12
13if (!defined("_ECRIRE_INC_VERSION")) return;
14
15include_spip('inc/headers');
16
17/**
18 * Acces aux documents joints securise
19 *
20 * verifie soit que le demandeur est authentifie
21 * soit que le document est publie, c'est-a-dire
22 * joint a au moins 1 article, breve ou rubrique publie
23 *
24 * URLs de la forme :
25 * docrestreint.api/id/cle/file
26 *
27 * @param null $arg
28 */
29function action_api_docrestreint_dist($arg=null) {
30
31        // Obtenir l'argument '{id_document}/{cle_action}/{chemin_fichier.ext}'
32        if (is_null($arg)) {
33                $arg = _request('arg');
34        }
35        $arg = explode("/", $arg);
36
37        // Supprimer et vider les buffers qui posent des problemes de memory limit
38        accesrestreint_vider_buffers();
39
40        // manque des arguments : 404
41        if (count($arg) < 3) {
42                accesrestreint_afficher_404_document();
43                return;
44        }
45
46        // Séparer les 3 arguments
47        // file ($f) exige pour eviter le scan id_document par id_document
48        $id_document = intval(array_shift($arg));
49        $cle         = array_shift($arg);
50        $f           = implode("/", $arg);
51
52        /**
53         * URL de test de fonctionnement
54         * @see accesrestreint_gerer_htaccess()
55         */
56        if ($id_document==0 AND $cle==1 AND $f=="test/.test") {
57                echo "OK";
58                return;
59        }
60
61        include_spip('inc/documents');
62
63        $file = get_spip_doc($f);
64        spip_log($file, 'dbg');
65
66        $status = $doc = false;
67        $dossiers_a_exclure = array('nl');
68
69        // securite : on refuse tout ../ ou url absolue
70        if ((strpos($f, '../') !== false) OR (preg_match(',^\w+://,', $f))) {
71                $status = 403;
72        } elseif (!file_exists($file) OR !is_readable($file)) {
73                $status = 404;
74        }
75
76        // Si c'est dans un sous-dossier explicitement utilisé pour autre chose que les documents
77        // (exemple : les newsletters)
78        // et bien on ne teste pas l'accès
79        elseif (preg_match('%^(' . join('|', $dossiers_a_exclure) . ')/%', $f)){
80                $status = 200;
81        }
82        else {
83                $where = "documents.fichier=".sql_quote(set_spip_doc($file))
84                . ($id_document ? " AND documents.id_document=".intval($id_document): '');
85                spip_log($where,'dbg');
86
87                $doc = sql_fetsel("documents.id_document, documents.titre, documents.fichier, types.mime_type, types.inclus, documents.extension", "spip_documents AS documents LEFT JOIN spip_types_documents AS types ON documents.extension=types.extension",$where);
88                spip_log($doc,'dbg');
89                if (!$doc) {
90                        $status = 404;
91                }
92                else {
93
94                        // ETag pour gerer le status 304
95                        $ETag = md5($file . ': '. filemtime($file));
96                        if (isset($_SERVER['HTTP_IF_NONE_MATCH'])
97                          AND $_SERVER['HTTP_IF_NONE_MATCH'] == $ETag) {
98                                http_status(304); // Not modified
99                                exit;
100                        }
101                        else {
102                                header('ETag: '.$ETag);
103                        }
104
105                        //
106                        // Verifier les droits de lecture du document
107
108                        // en controlant la cle passee en argument si elle est dispo
109                        // (perf issue : toutes les urls ont en principe cette cle fournie dans la page au moment du calcul de la page)
110                        if ($cle){
111                                include_spip('inc/securiser_action');
112                                if (!verifier_cle_action($doc['id_document'].','.$f, $cle)) {
113                                        spip_log("acces interdit $cle erronee");
114                                        $status = 403;
115                                }
116                        }
117                        // en verifiant le droit explicitement sinon, plus lent !
118                        else {
119                                if (!function_exists("autoriser"))
120                                        include_spip("inc/autoriser");
121                                if (!autoriser('voir', 'document', $doc['id_document'])) {
122                                        $status = 403;
123                                        spip_log("acces interdit $cle erronee");
124                                }
125                        }
126                }
127        }
128
129
130        switch($status) {
131
132        case 403:
133                include_spip('inc/minipres');
134                echo minipres("","","",true);
135                break;
136
137        case 404:
138                accesrestreint_afficher_404_document();
139                break;
140
141        default:
142                header("Content-Type: ". $doc['mime_type']);
143                // pour les images ne pas passer en attachment
144                // sinon, lorsqu'on pointe directement sur leur adresse,
145                // le navigateur les downloade au lieu de les afficher
146
147                if ($doc['inclus']=='non') {
148
149                        $f = basename($file);
150                        // ce content-type est necessaire pour eviter des corruptions de zip dans ie6
151                        header('Content-Type: application/octet-stream');
152
153                        header("Content-Disposition: attachment; filename=\"$f\";");
154                        header("Content-Transfer-Encoding: binary");
155
156                        // fix for IE catching or PHP bug issue
157                        header("Pragma: public");
158                        header("Expires: 0"); // set expiration time
159                        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
160
161                }
162                else {
163                        header("Expires: 3600"); // set expiration time
164                }
165
166                if ($cl = filesize($file))
167                        header("Content-Length: ". $cl);
168
169                readfile($file);
170                break;
171        }
172
173}
174
175/**
176 * Supprimer et vider les buffers qui posent des problemes de memory limit
177 *
178 * @link http://www.php.net/manual/en/function.readfile.php#81032
179 *
180 * @return void
181**/
182function accesrestreint_vider_buffers() {
183        @ini_set("zlib.output_compression","0"); // pour permettre l'affichage au fur et a mesure
184        @ini_set("output_buffering","off");
185        @ini_set('implicit_flush', 1);
186        @ob_implicit_flush(1);
187        $level = ob_get_level();
188        while ($level--){
189                @ob_end_clean();
190        }
191}
192
193/**
194 * Retourne une page 404 indiquant un document introuvable
195 *
196 * @return void
197**/
198function accesrestreint_afficher_404_document() {
199        http_status(404);
200        include_spip('inc/minipres');
201        echo minipres(_T('erreur') . ' 404', _T('medias:info_document_indisponible'), "", true);
202}
Note: See TracBrowser for help on using the repository browser.