[ Index ] |
|
Code source de SPIP 1.9.2c |
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 // Cree au besoin la copie locale d'un fichier distant 17 // mode = 'test' - ne faire que tester 18 // mode = 'auto' - charger au besoin 19 // mode = 'force' - charger toujours (mettre a jour) 20 // 21 // Prend en argument un chemin relatif au rep racine, ou une URL 22 // Renvoie un chemin relatif au rep racine, ou false 23 // 24 // http://doc.spip.org/@copie_locale 25 function copie_locale($source, $mode='auto') { 26 $local = fichier_copie_locale($source); 27 28 // test d'existence du fichier 29 if ($mode == 'test') 30 return @file_exists(_DIR_RACINE.$local) ? $local : ''; 31 32 // si $local = '' c'est un fichier refuse par fichier_copie_locale(), 33 // par exemple un fichier qui ne figure pas dans nos documents ; 34 // dans ce cas on n'essaie pas de le telecharger pour ensuite echouer 35 if (!$local) return false; 36 37 // sinon voir si on doit le telecharger 38 if ($local != $source 39 AND preg_match(',^\w+://,', $source)) { 40 if (($mode=='auto' AND !@file_exists(_DIR_RACINE.$local)) 41 OR $mode=='force') { 42 $contenu = recuperer_page($source); 43 if ($contenu) { 44 ecrire_fichier(_DIR_RACINE.$local, $contenu); 45 46 // signaler au moteur de recherche qu'il peut reindexer ce doc 47 $id_document = spip_fetch_array(spip_query("SELECT id_document FROM spip_documents WHERE fichier=" . _q($source))); 48 $id_document = $id_document['id_document']; 49 if ($id_document) { 50 include_spip('inc/indexation'); 51 marquer_indexer('spip_documents', $id_document); 52 } 53 } 54 else 55 return false; 56 } 57 } 58 59 return $local; 60 } 61 62 // http://doc.spip.org/@prepare_donnees_post 63 function prepare_donnees_post($donnees, $boundary = '') { 64 65 // permettre a la fonction qui a demande le post de formater elle meme ses donnees 66 // pour un appel soap par exemple 67 // l'entete est separe des donnees par un double retour a la ligne 68 // on s'occupe ici de passer tous les retours lignes (\r\n, \r ou \n) en \r\n 69 if (is_string($donnees) && strlen($donnees)){ 70 $entete = ""; 71 // on repasse tous les \r\n et \r en simples \n 72 $donnees = str_replace("\r\n","\n",$donnees); 73 $donnees = str_replace("\r","\n",$donnees); 74 // un double retour a la ligne signifie la fin de l'entete et le debut des donnees 75 $p = strpos($donnees,"\n\n"); 76 if ($p!==FALSE){ 77 $entete = str_replace("\n","\r\n",substr($donnees,0,$p+1)); 78 $donnees = substr($donnees,$p+2); 79 } 80 $chaine = str_replace("\n","\r\n",$donnees); 81 } 82 else { 83 /* boundary automatique */ 84 // Si on a plus de 500 octects de donnees, on "boundarise" 85 if($boundary == '') { 86 $taille = 0; 87 foreach ($donnees as $cle => $valeur) { 88 if (is_array($valeur)) { 89 foreach ($valeur as $val2) { 90 $taille += strlen($val2); 91 } 92 } else { 93 // faut-il utiliser spip_strlen() dans inc/charsets ? 94 $taille += strlen($valeur); 95 } 96 } 97 if($taille>500) { 98 $boundary = substr(md5(rand().'spip'), 0, 8); 99 } 100 } 101 102 if($boundary) { 103 // fabrique une chaine HTTP pour un POST avec boundary 104 $entete = "Content-Type: multipart/form-data; boundary=$boundary\r\n"; 105 $chaine = ''; 106 if (is_array($donnees)) { 107 foreach ($donnees as $cle => $valeur) { 108 $chaine .= "\r\n--$boundary\r\n"; 109 $chaine .= "Content-Disposition: form-data; name=\"$cle\"\r\n"; 110 $chaine .= "\r\n"; 111 $chaine .= $valeur; 112 } 113 $chaine .= "\r\n--$boundary\r\n"; 114 } 115 } else { 116 // fabrique une chaine HTTP simple pour un POST 117 $entete = 'Content-Type: application/x-www-form-urlencoded'."\r\n"; 118 $chaine = array(); 119 if (is_array($donnees)) { 120 foreach ($donnees as $cle => $valeur) { 121 if (is_array($valeur)) { 122 foreach ($valeur as $val2) { 123 $chaine[] = rawurlencode($cle).'='.rawurlencode($val2); 124 } 125 } else { 126 $chaine[] = rawurlencode($cle).'='.rawurlencode($valeur); 127 } 128 } 129 $chaine = implode('&', $chaine); 130 } else { 131 $chaine = $donnees; 132 } 133 } 134 } 135 return array($entete, $chaine); 136 } 137 138 // 139 // Recupere une page sur le net 140 // et au besoin l'encode dans le charset local 141 // 142 // options : get_headers si on veut recuperer les entetes 143 // taille_max : arreter le contenu au-dela (0 = seulement les entetes) 144 // Par defaut taille_max = 1Mo. 145 // datas, une chaine ou un tableau pour faire un POST de donnees 146 // boundary, pour forcer l'envoi par cette methode 147 // et refuser_gz pour forcer le refus de la compression (cas des serveurs orthographiques) 148 // date_verif, un timestamp unix pour arreter la recuperation si la page distante n'a pas ete modifiee depuis une date donnee 149 // uri_referer, preciser un referer different 150 // http://doc.spip.org/@recuperer_page 151 function recuperer_page($url, $munge_charset=false, $get_headers=false, 152 $taille_max = 1048576, $datas='', $boundary='', $refuser_gz = false, 153 $date_verif = '', $uri_referer = '') { 154 $gz = false; 155 156 // Accepter les URLs au format feed:// ou qui ont oublie le http:// 157 $url = preg_replace(',^feed://,i', 'http://', $url); 158 if (!preg_match(',^[a-z]+://,i', $url)) $url = 'http://'.$url; 159 160 if ($taille_max == 0) 161 $get = 'HEAD'; 162 else 163 $get = 'GET'; 164 165 if (!empty($datas)) { 166 $get = 'POST'; 167 list($content_type, $postdata) = prepare_donnees_post($datas); 168 } 169 170 for ($i=0;$i<10;$i++) { // dix tentatives maximum en cas d'entetes 301... 171 list($f, $fopen) = init_http($get, $url, $refuser_gz, $uri_referer); 172 173 // si on a utilise fopen() - passer a la suite 174 if ($fopen) { 175 spip_log('connexion via fopen'); 176 break; 177 } else { 178 // Fin des entetes envoyees par SPIP 179 if($get == 'POST') { 180 fputs($f, $content_type); 181 fputs($f, 'Content-Length: '.strlen($postdata)."\r\n"); 182 fputs($f, "\r\n".$postdata); 183 } else { 184 fputs($f,"\r\n"); 185 } 186 187 // Reponse du serveur distant 188 $s = trim(fgets($f, 16384)); 189 if (ereg('^HTTP/[0-9]+\.[0-9]+ ([0-9]+)', $s, $r)) { 190 $status = $r[1]; 191 } 192 else return; 193 194 // Entetes HTTP de la page 195 $headers = ''; 196 while ($s = trim(fgets($f, 16384))) { 197 $headers .= $s."\n"; 198 if (eregi('^Location: (.*)', $s, $r)) { 199 include_spip('inc/filtres'); 200 $location = suivre_lien($url, $r[1]); 201 spip_log("Location: $location"); 202 } 203 if ($date_verif AND preg_match(',^Last-Modified: (.*),', $s, $r)) { 204 if(strtotime($date_verif)>=strtotime($r[1])) { 205 //Cas ou la page distante n'a pas bouge depuis 206 //la derniere visite 207 return $status; 208 } 209 } 210 if (preg_match(",^Content-Encoding: .*gzip,i", $s)) 211 $gz = true; 212 } 213 if ($status >= 300 AND $status < 400 AND $location) 214 $url = $location; 215 else if ($status != 200) 216 return false; 217 else 218 break; # ici on est content 219 fclose($f); 220 $f = false; 221 } 222 } 223 224 // Contenu de la page 225 if (!$f) { 226 spip_log("ECHEC chargement $url"); 227 return false; 228 } 229 230 $result = ''; 231 while (!feof($f) AND strlen($result)<$taille_max) 232 $result .= fread($f, 16384); 233 fclose($f); 234 235 // Decompresser le flux 236 if ($gz AND $result) 237 $result = gzinflate(substr($result,10)); 238 239 // Faut-il l'importer dans notre charset local ? 240 if ($munge_charset) { 241 include_spip('inc/charsets'); 242 $result = transcoder_page ($result, $headers); 243 } 244 245 return ($get_headers ? $headers."\n" : '').$result; 246 } 247 248 249 // Si on doit conserver une copie locale des fichiers distants, autant que ca 250 // soit a un endroit canonique -- si ca peut etre bijectif c'est encore mieux, 251 // mais la tout de suite je ne trouve pas l'idee, etant donne les limitations 252 // des filesystems 253 // http://doc.spip.org/@nom_fichier_copie_locale 254 function nom_fichier_copie_locale($source, $extension) { 255 $dir = sous_repertoire(_DIR_IMG, 'distant'); # IMG/distant/ 256 $dir2 = sous_repertoire($dir, $extension); # IMG/distant/pdf/ 257 $chemin = $dir2 . substr(preg_replace(',[^\w-],', '', basename($source)).'-'.md5($source),0,12). 258 substr(md5($source),0,4).'.'.$extension; 259 260 // on se place tout le temps comme si on etait a la racine 261 if (_DIR_RACINE) 262 $chemin = preg_replace(',^'.preg_quote(_DIR_RACINE).',', '', $chemin); 263 264 return $chemin; 265 } 266 267 // 268 // Donne le nom de la copie locale de la source 269 // 270 // http://doc.spip.org/@fichier_copie_locale 271 function fichier_copie_locale($source) { 272 // Si c'est une image locale pas de souci 273 if (!preg_match(',^\w+://,', $source)) { 274 if (_DIR_RACINE) 275 $source = preg_replace(',^'.preg_quote(_DIR_RACINE).',', '', $source); 276 return $source; 277 } 278 279 $extension = ""; 280 // Chercher d'abord le doc dans la table des documents, pour se baser sur son type reel 281 $t = spip_fetch_array(spip_query("SELECT id_type FROM spip_documents WHERE fichier=" . _q($source) . " AND distant='oui'")); 282 if ($t) { 283 $t = spip_fetch_array(spip_query("SELECT extension FROM spip_types_documents WHERE id_type=".$t['id_type'])); 284 if ($t) 285 $extension = $t['extension']; 286 } 287 288 // si la source n'est pas dans la table des documents, on regarde si son extension est connue et autorisee 289 if (!strlen($extension)) { 290 $path_parts = pathinfo($source); 291 if (isset($path_parts['extension']) && strlen($path_parts['extension'])){ 292 // verifier que c'est un type autorise 293 $t = spip_fetch_array(spip_query("SELECT extension FROM spip_types_documents WHERE extension="._q($path_parts['extension']))); 294 if ($t) 295 $extension = $t['extension']; 296 } 297 } 298 299 if (strlen($extension)) 300 return nom_fichier_copie_locale($source, $extension); 301 } 302 303 304 // Recuperer les infos d'un document distant, sans trop le telecharger 305 // http://doc.spip.org/@recuperer_infos_distantes 306 function recuperer_infos_distantes($source, $max=0) { 307 308 $a = array(); 309 $mime_type = ''; 310 // On va directement charger le debut des images et des fichiers html, 311 // de maniere a attrapper le maximum d'infos (titre, taille, etc). Si 312 // ca echoue l'utilisateur devra les entrer... 313 if ($headers = recuperer_page($source, false, true, $max)) { 314 list($headers, $a['body']) = split("\n\n", $headers, 2); 315 $t = preg_match(",\nContent-Type: *([^[:space:];]*),i", 316 "\n$headers", $regs); 317 if ($t) { 318 $mime_type = (trim($regs[1])); 319 $t = spip_fetch_array(spip_query("SELECT id_type,extension FROM spip_types_documents WHERE mime_type=" . _q($mime_type))); 320 } 321 if ($t) { 322 spip_log("mime-type $mime_type ok"); 323 $a['id_type'] = $t['id_type']; 324 $a['extension'] = $t['extension']; 325 } else { 326 # par defaut on retombe sur '.bin' si c'est autorise 327 spip_log("mime-type $mime_type inconnu"); 328 $t = spip_fetch_array(spip_query("SELECT id_type,extension FROM spip_types_documents WHERE extension='bin'")); 329 if (!$t) return false; 330 $a['id_type'] = $t['id_type']; 331 $a['extension'] = $t['extension']; 332 } 333 334 if (preg_match(",\nContent-Length: *([^[:space:]]*),i", 335 "\n$headers", $regs)) 336 $a['taille'] = intval($regs[1]); 337 } 338 339 // Echec avec HEAD, on tente avec GET 340 if (!$a AND !$max) { 341 spip_log("tente $source"); 342 $a = recuperer_infos_distantes($source, 1024*1024); 343 } 344 345 // S'il s'agit d'une image pas trop grosse ou d'un fichier html, on va aller 346 // recharger le document en GET et recuperer des donnees supplementaires... 347 if (preg_match(',^image/(jpeg|gif|png|swf),', $mime_type)) { 348 if ($max == 0 349 AND $a['taille'] < 1024*1024 350 AND ereg(",".$a['extension'].",", 351 ','.$GLOBALS['meta']['formats_graphiques'].',')){ 352 $a = recuperer_infos_distantes($source, 1024*1024); 353 } 354 else if ($a['body']) { 355 $a['fichier'] = nom_fichier_copie_locale($source, $a['extension']); 356 ecrire_fichier($a['fichier'], $a['body']); 357 $size_image = @getimagesize($a['fichier']); 358 $a['largeur'] = intval($size_image[0]); 359 $a['hauteur'] = intval($size_image[1]); 360 $a['type_image'] = true; 361 } 362 } 363 364 if ($mime_type == 'text/html') { 365 include_spip('inc/filtres'); 366 $page = recuperer_page($source, true, false, 1024*1024); 367 if(preg_match(',<title>(.*?)</title>,ims', $page, $regs)) 368 $a['titre'] = corriger_caracteres(trim($regs[1])); 369 if (!$a['taille']) $a['taille'] = strlen($page); # a peu pres 370 } 371 372 return $a; 373 } 374 375 376 // 377 // Demarre une transaction HTTP (s'arrete a la fin des entetes) 378 // retourne un descripteur de fichier 379 // 380 // http://doc.spip.org/@init_http 381 function init_http($get, $url, $refuse_gz=false, $uri_referer = '') { 382 $via_proxy = ''; $proxy_user = ''; $fopen = false; 383 $http_proxy = $GLOBALS['meta']["http_proxy"]; 384 if (!eregi("^http://", $http_proxy)) 385 $http_proxy = ''; 386 else 387 $via_proxy = " (proxy $http_proxy)"; 388 389 spip_log("http $get $url$via_proxy"); 390 391 $t = @parse_url($url); 392 $host = $t['host']; 393 if ($t['scheme'] == 'http') { 394 $scheme = 'http'; $scheme_fsock=''; 395 } else { 396 $scheme = $t['scheme']; $scheme_fsock=$scheme.'://'; 397 } 398 if (!isset($t['port']) || !($port = $t['port'])) $port = 80; 399 $query = $t['query']; 400 if (!isset($t['path']) || !($path = $t['path'])) $path = "/"; 401 402 if ($http_proxy) { 403 $t2 = @parse_url($http_proxy); 404 $proxy_host = $t2['host']; 405 $proxy_user = $t2['user']; 406 $proxy_pass = $t2['pass']; 407 if (!($proxy_port = $t2['port'])) $proxy_port = 80; 408 $f = @fsockopen($proxy_host, $proxy_port); 409 } else 410 $f = @fsockopen($scheme_fsock.$host, $port); 411 412 if ($f) { 413 if ($http_proxy) 414 fputs($f, "$get $scheme://$host" . (($port != 80) ? ":$port" : "") . $path . ($query ? "?$query" : "") . " HTTP/1.0\r\n"); 415 else 416 fputs($f, "$get $path" . ($query ? "?$query" : "") . " HTTP/1.0\r\n"); 417 418 fputs($f, "Host: $host\r\n"); 419 fputs($f, "User-Agent: SPIP-".$GLOBALS['spip_version_affichee']." (http://www.spip.net/)\r\n"); 420 421 // Proxy authentifiant 422 if ($proxy_user) { 423 fputs($f, "Proxy-Authorization: Basic " 424 . base64_encode($proxy_user . ":" . $proxy_pass) . "\r\n"); 425 } 426 // Referer = c'est nous ! 427 if ($referer = $GLOBALS['meta']["adresse_site"]) { 428 $referer .= '/'.$uri_referer; 429 fputs($f, "Referer: $referer\r\n"); 430 } 431 432 // On sait lire du gzip 433 if ($GLOBALS['flag_gz'] AND !$refuse_gz) 434 fputs($f, "Accept-Encoding: gzip\r\n"); 435 436 } 437 // fallback : fopen 438 else if (!$GLOBALS['tester_proxy']) { 439 $f = @fopen($url, "rb"); 440 $fopen = true; 441 } 442 // echec total 443 else { 444 $f = false; 445 } 446 447 return array($f, $fopen); 448 } 449 450 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Wed Nov 21 10:20:27 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |