[SPIP] v3.2.1-->v3.2.3
[lhc/web/www.git] / www / plugins-dist / medias / action / acceder_document.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2019 *
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
13 if (!defined('_ECRIRE_INC_VERSION')) {
14 return;
15 }
16
17 include_spip('inc/headers');
18
19 // acces aux documents joints securise
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 ou rubrique publie
23
24 // https://code.spip.net/@action_acceder_document_dist
25 function action_acceder_document_dist() {
26 include_spip('inc/documents');
27
28 // $file exige pour eviter le scan id_document par id_document
29 $f = rawurldecode(_request('file'));
30 $file = get_spip_doc($f);
31 $arg = rawurldecode(_request('arg'));
32
33 $status = false;
34 if (strpos($f, '../') !== false
35 or preg_match(',^\w+://,', $f)
36 ) {
37 $status = 403;
38 } else {
39 if (!file_exists($file) or !is_readable($file)) {
40 $status = 404;
41 } else {
42 $where = 'D.fichier=' . sql_quote(set_spip_doc($file))
43 . ($arg ? ' AND D.id_document=' . intval($arg) : '');
44
45 $doc = sql_fetsel(
46 'D.id_document, D.titre, D.fichier, T.mime_type, T.inclus, D.extension',
47 'spip_documents AS D LEFT JOIN spip_types_documents AS T ON D.extension=T.extension',
48 $where
49 );
50 if (!$doc) {
51 $status = 404;
52 } else {
53 // ETag pour gerer le status 304
54 $ETag = md5($file . ': ' . filemtime($file));
55 if (isset($_SERVER['HTTP_IF_NONE_MATCH'])
56 and $_SERVER['HTTP_IF_NONE_MATCH'] == $ETag
57 ) {
58 http_status(304); // Not modified
59 exit;
60 } else {
61 header('ETag: ' . $ETag);
62 }
63
64 //
65 // Verifier les droits de lecture du document
66 // en controlant la cle passee en argument
67 //
68 include_spip('inc/securiser_action');
69 $cle = _request('cle');
70 if (!verifier_cle_action($doc['id_document'] . ',' . $f, $cle)) {
71 spip_log("acces interdit $cle erronee");
72 $status = 403;
73 }
74 }
75 }
76 }
77
78 switch ($status) {
79 case 403:
80 include_spip('inc/minipres');
81 echo minipres();
82 break;
83
84 case 404:
85 http_status(404);
86 include_spip('inc/minipres');
87 echo minipres(_T('erreur') . ' 404', _T('medias:info_document_indisponible'));
88 break;
89
90 default:
91 header('Content-Type: ' . $doc['mime_type']);
92
93 // pour les images ne pas passer en attachment
94 // sinon, lorsqu'on pointe directement sur leur adresse,
95 // le navigateur les downloade au lieu de les afficher
96
97 if ($doc['inclus'] == 'non') {
98 // Si le fichier a un titre avec extension,
99 // ou si c'est un nom bien connu d'Unix, le prendre
100 // sinon l'ignorer car certains navigateurs pataugent
101
102 $f = basename($file);
103 if (isset($doc['titre'])
104 and (preg_match('/^\w+[.]\w+$/', $doc['titre']) or $doc['titre'] == 'Makefile')
105 ) {
106 $f = $doc['titre'];
107 }
108
109 // ce content-type est necessaire pour eviter des corruptions de zip dans ie6
110 header('Content-Type: application/octet-stream');
111
112 header("Content-Disposition: attachment; filename=\"$f\";");
113 header('Content-Transfer-Encoding: binary');
114
115 // fix for IE catching or PHP bug issue
116 header('Pragma: public');
117 header('Expires: 0'); // set expiration time
118 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
119 }
120
121 if ($cl = filesize($file)) {
122 header('Content-Length: ' . $cl);
123 }
124
125 readfile($file);
126 break;
127 }
128 }