Commit | Line | Data |
---|---|---|
c495c100 P |
1 | <?php |
2 | ||
3 | /***************************************************************************\ | |
4 | * SPIP, Systeme de publication pour l'internet * | |
5 | * * | |
6 | * Copyright (c) 2001-2007 * | |
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")) return; | |
14 | ||
15 | // | |
16 | // Le format souhaite : "a/bout-d-url.md5" (.gz s'ajoutera pour les gros caches) | |
17 | // Attention a modifier simultanement le sanity check de | |
18 | // la fonction retire_cache() de inc/invalideur | |
19 | // | |
20 | // http://doc.spip.org/@generer_nom_fichier_cache | |
21 | function generer_nom_fichier_cache($contexte) { | |
22 | ||
23 | if ($contexte === NULL) { | |
24 | $fichier_requete = nettoyer_uri(); | |
25 | } else { | |
26 | $fichier_requete = ''; | |
27 | foreach ($contexte as $var=>$val) | |
28 | $fichier_requete .= "&$var=$val"; | |
29 | } | |
30 | ||
31 | $fichier_cache = preg_replace(',^/+,', '', $fichier_requete); | |
32 | $fichier_cache = preg_replace(',\.[a-zA-Z0-9]*,', '', $fichier_cache); | |
33 | $fichier_cache = preg_replace(',&[^&]+=([^&]+),', '&\1', $fichier_cache); | |
34 | $fichier_cache = rawurlencode(strtr($fichier_cache, '/&-', '--_')); | |
35 | if (strlen($fichier_cache) > 24) | |
36 | $fichier_cache = substr(preg_replace('/([a-zA-Z]{1,3})[^-]*-/', | |
37 | '\1-', $fichier_cache), -22); | |
38 | ||
39 | // Pour la page d'accueil | |
40 | if (!$fichier_cache) | |
41 | $fichier_cache = 'INDEX-'; | |
42 | ||
43 | // Morceau de md5 selon HOST, $dossier_squelettes, $fond et $marqueur | |
44 | // permet de changer de chemin_cache si l'on change l'un de ces elements | |
45 | // donc, par exemple, de gerer differents dossiers de squelettes | |
46 | // en parallele, ou de la "personnalisation" via un marqueur (dont la | |
47 | // composition est totalement libre...) | |
48 | $md_cache = md5( | |
49 | $fichier_requete . ' ' | |
50 | . $_SERVER['HTTP_HOST'] . ' ' | |
51 | . $GLOBALS['fond'] . ' ' | |
52 | . $GLOBALS['dossier_squelettes'] . ' ' | |
53 | . (isset($GLOBALS['marqueur']) ? $GLOBALS['marqueur'] : '') | |
54 | ); | |
55 | $fichier_cache .= '.'.substr($md_cache, 1, 8); | |
56 | ||
57 | // Sous-repertoires 0...9a..f ; ne pas prendre la base _DIR_CACHE | |
58 | $repertoire = _DIR_CACHE; | |
59 | if(!@file_exists($repertoire)) { | |
60 | $repertoire = preg_replace(','._DIR_TMP.',', '', $repertoire); | |
61 | $repertoire = sous_repertoire(_DIR_TMP, $repertoire); | |
62 | } | |
63 | $subdir = sous_repertoire($repertoire, substr($md_cache, 0, 1), true); | |
64 | ||
65 | return $subdir.$fichier_cache; | |
66 | } | |
67 | ||
68 | // Faut-il compresser ce cache ? A partir de 16ko ca vaut le coup | |
69 | // http://doc.spip.org/@cache_gz | |
70 | function cache_gz($page) { | |
71 | if ($GLOBALS['flag_gz'] AND strlen($page['texte']) > 16*1024) | |
72 | return '.gz'; | |
73 | else | |
74 | return ''; | |
75 | } | |
76 | ||
77 | // gestion des delais d'expiration du cache | |
78 | // $page passee par reference pour accelerer | |
79 | // http://doc.spip.org/@cache_valide | |
80 | function cache_valide(&$page, $date) { | |
81 | ||
82 | if (!$page) return 1; | |
83 | ||
84 | // Cache invalide par la meta 'derniere_modif' | |
85 | if ($GLOBALS['derniere_modif_invalide'] | |
86 | AND $date < $GLOBALS['meta']['derniere_modif']) | |
87 | return 1; | |
88 | ||
89 | // Sinon comparer l'age du fichier a sa duree de cache | |
90 | $duree = intval($page['entetes']['X-Spip-Cache']); | |
91 | if ($duree == 0) #CACHE{0} | |
92 | return -1; | |
93 | else if ($date + $duree < time()) | |
94 | return 1; | |
95 | else | |
96 | return 0; | |
97 | } | |
98 | ||
99 | ||
100 | // Creer le fichier cache | |
101 | # Passage par reference de $page par souci d'economie | |
102 | // http://doc.spip.org/@creer_cache | |
103 | function creer_cache(&$page, &$chemin_cache) { | |
104 | ||
105 | // Normaliser le chemin et supprimer l'eventuelle contrepartie -gz du cache | |
106 | $chemin_cache = str_replace('.gz', '', $chemin_cache); | |
107 | $gz = cache_gz($page); | |
108 | supprimer_fichier(_DIR_CACHE . $chemin_cache . ($gz ? '' : '.gz')); | |
109 | ||
110 | // l'enregistrer, compresse ou non... | |
111 | $chemin_cache .= $gz; | |
112 | $ok = ecrire_fichier(_DIR_CACHE . $chemin_cache, serialize($page)); | |
113 | ||
114 | spip_log("Creation du cache $chemin_cache pour " | |
115 | . $page['entetes']['X-Spip-Cache']." secondes". ($ok?'':' (erreur!)')); | |
116 | ||
117 | // Inserer ses invalideurs | |
118 | include_spip('inc/invalideur'); | |
119 | maj_invalideurs($chemin_cache, $page); | |
120 | ||
121 | } | |
122 | ||
123 | ||
124 | // purger un petit cache (tidy ou recherche) qui ne doit pas contenir de | |
125 | // vieux fichiers | |
126 | // http://doc.spip.org/@nettoyer_petit_cache | |
127 | function nettoyer_petit_cache($prefix, $duree = 300) { | |
128 | // determiner le repertoire a purger : 'tmp/CACHE/rech/' | |
129 | $dircache = sous_repertoire(_DIR_CACHE,$prefix); | |
130 | if (spip_touch($dircache.'purger_'.$prefix, $duree, true)) { | |
131 | foreach (preg_files($dircache,'[.]txt$') as $f) { | |
132 | if (time() - (@file_exists($f)?@filemtime($f):0) > $duree) | |
133 | @unlink($f); | |
134 | } | |
135 | } | |
136 | } | |
137 | ||
138 | ||
139 | // Interface du gestionnaire de cache | |
140 | // Si son 3e argument est non vide, elle passe la main a creer_cache | |
141 | // Sinon, elle recoit un contexte (ou le construit a partir de REQUEST_URI) | |
142 | // et affecte les 4 autres parametres recus par reference: | |
143 | // - use_cache qui vaut | |
144 | // -1 s'il faut calculer la page sans la mettre en cache | |
145 | // 0 si on peut utiliser un cache existant | |
146 | // 1 s'il faut calculer la page et la mettre en cache | |
147 | // - chemin_cache qui est le chemin d'acces au fichier ou vide si pas cachable | |
148 | // - page qui est le tableau decrivant la page, si le cache la contenait | |
149 | // - lastmodified qui vaut la date de derniere modif du fichier. | |
150 | ||
151 | // http://doc.spip.org/@public_cacher_dist | |
152 | function public_cacher_dist($contexte, &$use_cache, &$chemin_cache, &$page, &$lastmodified) { | |
153 | ||
154 | // Second appel, destine a l'enregistrement du cache sur le disque | |
155 | if ($chemin_cache) return creer_cache($page, $chemin_cache); | |
156 | ||
157 | // Toute la suite correspond au premier appel | |
158 | ||
159 | // Cas ignorant le cache car complement dynamique | |
160 | if ($_SERVER['REQUEST_METHOD'] == 'POST' | |
161 | OR (substr($contexte['fond'],0,8)=='modeles/') | |
162 | // Mode auteur authentifie appelant de ecrire/ : il ne faut rien lire du cache | |
163 | // et n'y ecrire que la compilation des squelettes (pas les pages produites) | |
164 | // car les references aux repertoires ne sont pas relatifs a l'espace public | |
165 | OR !_DIR_RESTREINT) { | |
166 | $use_cache = -1; | |
167 | $lastmodified = 0; | |
168 | $chemin_cache = ""; | |
169 | $page = array(); | |
170 | return; | |
171 | } | |
172 | ||
173 | $chemin_cache = generer_nom_fichier_cache($contexte); | |
174 | if ($GLOBALS['flag_gz'] AND @file_exists(_DIR_CACHE.$chemin_cache.'.gz')) | |
175 | $chemin_cache .= '.gz'; | |
176 | ||
177 | // HEAD : cas sans jamais de calcul pour raisons de performance | |
178 | if ($_SERVER['REQUEST_METHOD'] == 'HEAD') { | |
179 | $use_cache = 0; | |
180 | $page = array(); | |
181 | $lastmodified = @file_exists(_DIR_CACHE . $chemin_cache) ? | |
182 | @filemtime(_DIR_CACHE . $chemin_cache) : 0; | |
183 | return; | |
184 | } | |
185 | ||
186 | // Faut-il effacer des pages invalidees (en particulier ce cache-ci) ? | |
187 | if (isset($GLOBALS['meta']['invalider'])) { | |
188 | // ne le faire que si la base est disponible | |
189 | if (spip_connect()) { | |
190 | include_spip('inc/invalideur'); | |
191 | retire_caches($chemin_cache); | |
192 | } | |
193 | } | |
194 | ||
195 | // Cas sans jamais de cache pour raison interne | |
196 | if (isset($GLOBALS['var_mode']) && | |
197 | (isset($_COOKIE['spip_session']) | |
198 | || isset($_COOKIE['spip_admin']) | |
199 | || @file_exists(_ACCESS_FILE_NAME))) { | |
200 | supprimer_fichier(_DIR_CACHE . $chemin_cache); | |
201 | } | |
202 | ||
203 | // $delais par defaut (pour toutes les pages sans #CACHE{}) | |
204 | if (!isset($GLOBALS['delais'])) $GLOBALS['delais'] = 3600; | |
205 | ||
206 | // Lire le fichier cache et determiner sa validite | |
207 | if (lire_fichier(_DIR_CACHE . $chemin_cache, $page)) { | |
208 | $lastmodified = @file_exists(_DIR_CACHE . $chemin_cache) ? | |
209 | @filemtime(_DIR_CACHE . $chemin_cache) : 0; | |
210 | $page = @unserialize($page); | |
211 | $use_cache = cache_valide($page, $lastmodified); | |
212 | if (!$use_cache) return; // cache utilisable | |
213 | } else | |
214 | $use_cache = 1; // fichier cache absent : provoque le calcul | |
215 | ||
216 | // Si pas valide mais pas de connexion a la base, le garder quand meme | |
217 | if (!spip_connect()) { | |
218 | if (file_exists(_DIR_CACHE . $chemin_cache)) | |
219 | $use_cache = 0; | |
220 | else { | |
221 | spip_log("Erreur base de donnees, impossible utiliser $chemin_cache"); | |
222 | include_spip('inc/minipres'); | |
223 | echo minipres(_T('info_travaux_titre'), _T('titre_probleme_technique')); | |
224 | exit; | |
225 | } | |
226 | } | |
227 | ||
228 | if ($use_cache < 0) $chemin_cache = ''; | |
229 | return; | |
230 | } | |
231 | ||
232 | ?> |