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

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

Reformattage (suite) pour y voir un rien plus clair dans la fonction api_docrestreint. À suivre...

File size: 6.0 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_erreur_document(404);
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        // securite : on refuse tout ../ ou url absolue
67        if ((strpos($f, '../') !== false) OR (preg_match(',^\w+://,', $f))) {
68                accesrestreint_afficher_erreur_document(403);
69                return;
70        }
71
72        // inexistant ou illisible : 404
73        if (!file_exists($file) OR !is_readable($file)) {
74                accesrestreint_afficher_erreur_document(404);
75                return;
76        }
77
78        $status = $doc = false;
79        $dossiers_a_exclure = array('nl');
80
81        // Si c'est dans un sous-dossier explicitement utilisé pour autre chose que les documents
82        // (exemple : les newsletters)
83        // et bien on ne teste pas l'accès
84        if (preg_match('%^(' . join('|', $dossiers_a_exclure) . ')/%', $f)){
85                $status = 200;
86        }
87        else {
88                $where = "documents.fichier=".sql_quote(set_spip_doc($file))
89                . ($id_document ? " AND documents.id_document=".intval($id_document): '');
90                spip_log($where,'dbg');
91
92                $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);
93                spip_log($doc,'dbg');
94                if (!$doc) {
95                        $status = 404;
96                }
97                else {
98
99                        // ETag pour gerer le status 304
100                        $ETag = md5($file . ': '. filemtime($file));
101                        if (isset($_SERVER['HTTP_IF_NONE_MATCH'])
102                          AND $_SERVER['HTTP_IF_NONE_MATCH'] == $ETag) {
103                                http_status(304); // Not modified
104                                exit;
105                        }
106                        else {
107                                header('ETag: '.$ETag);
108                        }
109
110                        //
111                        // Verifier les droits de lecture du document
112
113                        // en controlant la cle passee en argument si elle est dispo
114                        // (perf issue : toutes les urls ont en principe cette cle fournie dans la page au moment du calcul de la page)
115                        if ($cle){
116                                include_spip('inc/securiser_action');
117                                if (!verifier_cle_action($doc['id_document'].','.$f, $cle)) {
118                                        spip_log("acces interdit $cle erronee");
119                                        $status = 403;
120                                }
121                        }
122                        // en verifiant le droit explicitement sinon, plus lent !
123                        else {
124                                if (!function_exists("autoriser"))
125                                        include_spip("inc/autoriser");
126                                if (!autoriser('voir', 'document', $doc['id_document'])) {
127                                        $status = 403;
128                                        spip_log("acces interdit $cle erronee");
129                                }
130                        }
131                }
132        }
133
134
135        switch($status) {
136
137        case 403:
138                accesrestreint_afficher_erreur_document(403);
139                break;
140
141        case 404:
142                accesrestreint_afficher_erreur_document(404);
143                break;
144
145        default:
146                header("Content-Type: ". $doc['mime_type']);
147                // pour les images ne pas passer en attachment
148                // sinon, lorsqu'on pointe directement sur leur adresse,
149                // le navigateur les downloade au lieu de les afficher
150
151                if ($doc['inclus']=='non') {
152
153                        $f = basename($file);
154                        // ce content-type est necessaire pour eviter des corruptions de zip dans ie6
155                        header('Content-Type: application/octet-stream');
156
157                        header("Content-Disposition: attachment; filename=\"$f\";");
158                        header("Content-Transfer-Encoding: binary");
159
160                        // fix for IE catching or PHP bug issue
161                        header("Pragma: public");
162                        header("Expires: 0"); // set expiration time
163                        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
164
165                }
166                else {
167                        header("Expires: 3600"); // set expiration time
168                }
169
170                if ($cl = filesize($file))
171                        header("Content-Length: ". $cl);
172
173                readfile($file);
174                break;
175        }
176
177}
178
179/**
180 * Supprimer et vider les buffers qui posent des problemes de memory limit
181 *
182 * @link http://www.php.net/manual/en/function.readfile.php#81032
183 *
184 * @return void
185**/
186function accesrestreint_vider_buffers() {
187        @ini_set("zlib.output_compression","0"); // pour permettre l'affichage au fur et a mesure
188        @ini_set("output_buffering","off");
189        @ini_set('implicit_flush', 1);
190        @ob_implicit_flush(1);
191        $level = ob_get_level();
192        while ($level--){
193                @ob_end_clean();
194        }
195}
196
197/**
198 * Affiche une page indiquant un document introuvable ou interdit
199 *
200 * @param string $status
201 *     Numero d'erreur (403 ou 404)
202 * @return void
203**/
204function accesrestreint_afficher_erreur_document($status = 404) {
205
206        switch ($status)
207        {
208                case 403:
209                        include_spip('inc/minipres');
210                        echo minipres("","","",true);
211                        break;
212
213                case 404:
214                        http_status(404);
215                        include_spip('inc/minipres');
216                        echo minipres(_T('erreur') . ' 404', _T('medias:info_document_indisponible'), "", true);
217                        break;
218        }
219}
Note: See TracBrowser for help on using the repository browser.