http.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <?php
  2. /**
  3. * Gestion du téléporteur HTTP.
  4. *
  5. * @plugin SVP pour SPIP
  6. * @license GPL
  7. * @package SPIP\SVP\Teleporteur
  8. */
  9. /**
  10. * Téléporter et déballer un composant HTTP
  11. *
  12. * @param string $methode
  13. * Méthode de téléportation : http|git|svn|...
  14. * @param string $source
  15. * URL de la source HTTP
  16. * @param string $dest
  17. * Chemin du répertoire de destination
  18. * @param array $options
  19. * Tableau d'options.
  20. * Doit au moins avoir l'index :
  21. * - dir_tmp : Indique un répertoire temporaire pour stocker
  22. * les fichiers. Par exemple défini avec : sous_repertoire(_DIR_CACHE, 'chargeur');
  23. * @return bool|string
  24. * Texte d'erreur si erreur,
  25. * True si l'opération réussie.
  26. */
  27. function teleporter_http_dist($methode,$source,$dest,$options=array()){
  28. $tmp = $options['dir_tmp'];
  29. # on ne se contente pas du basename qui peut etre un simple v1
  30. # exemple de l'url http://nodeload.github.com/kbjr/Git.php/zipball/v0.1.1-rc
  31. $fichier = $tmp . (basename($dest)."-".substr(md5($source),0,8)."-".basename($source));
  32. $res = teleporter_http_recuperer_source($source,$fichier);
  33. if (!is_array($res))
  34. return $res;
  35. list($fichier,$extension) = $res;
  36. if (!$deballe = charger_fonction("http_deballe_".preg_replace(",\W,","_",$extension),"teleporter",true))
  37. return _T('svp:erreur_teleporter_format_archive_non_supporte',array('extension' => $extension));
  38. $old = teleporter_nettoyer_vieille_version($dest);
  39. if (!$target = $deballe($fichier, $dest, $tmp)){
  40. // retablir l'ancien sinon
  41. if ($old)
  42. rename($old,$dest);
  43. return _T('svp:erreur_teleporter_echec_deballage_archive',array('fichier' => $fichier));
  44. }
  45. return true;
  46. }
  47. /**
  48. * Récupérer la source et détecter son extension
  49. *
  50. * @param string $source
  51. * URL de la source HTTP
  52. * @param string $dest_tmp
  53. * Répertoire de destination
  54. * @return array|string
  55. * - Texte d'erreur si une erreur survient,
  56. * - Liste sinon (répertoire de destination temporaire, extension du fichier source)
  57. */
  58. function teleporter_http_recuperer_source($source,$dest_tmp){
  59. # securite : ici on repart toujours d'une source neuve
  60. if (file_exists($dest_tmp))
  61. spip_unlink($dest_tmp);
  62. $extension = "";
  63. # si on ne dispose pas encore du fichier
  64. # verifier que le zip en est bien un (sans se fier a son extension)
  65. # en chargeant son entete car l'url initiale peut etre une simple
  66. # redirection et ne pas comporter d'extension .zip
  67. include_spip('inc/distant');
  68. $head = recuperer_page($source, false, true, 0);
  69. if (preg_match(",^Content-Type:\s*?(.*)$,Uims",$head,$m)
  70. AND include_spip('base/typedoc')){
  71. $mime = $m[1];
  72. // passer du mime a l'extension !
  73. if ($e = array_search($mime,$GLOBALS['tables_mime']))
  74. $extension = $e;
  75. }
  76. if (!$extension
  77. // cas des extensions incertaines car mime-type ambigu
  78. OR in_array($extension,array('bin','gz'))){
  79. if (preg_match(",^Content-Disposition:\s*attachment;\s*filename=(.*)['\"]?$,Uims",$head,$m)
  80. AND $e=teleporter_http_extension($m[1])){
  81. $extension = $e;
  82. }
  83. // au cas ou, si le content-type n'est pas la
  84. // mais que l'extension est explicite
  85. else{
  86. $extension = teleporter_http_extension($source);
  87. }
  88. }
  89. # format de fichier inconnu
  90. if (!$extension) {
  91. spip_log("Type de fichier inconnu pour la source $source","teleport"._LOG_ERREUR);
  92. return _T('svp:erreur_teleporter_type_fichier_inconnu',array('source' => $source));
  93. }
  94. $dest_tmp = preg_replace(";\.[\w]{2,3}$;i","",$dest_tmp).".$extension";
  95. include_spip('inc/distant');
  96. $dest_tmp = copie_locale($source,'force',$dest_tmp);
  97. if (!$dest_tmp
  98. OR !file_exists($dest_tmp = _DIR_RACINE . $dest_tmp)) {
  99. spip_log("Chargement impossible de la source $source","teleport"._LOG_ERREUR);
  100. return _T('svp:erreur_teleporter_chargement_source_impossible',array('source' => $source));
  101. }
  102. return array($dest_tmp,$extension);
  103. }
  104. /**
  105. * Retrouve l'extension d'un fichier
  106. *
  107. * @note
  108. * Retourne tgz pour un fichier .tar.gz
  109. *
  110. * @param string $file
  111. * Chemin du fichier
  112. * @return string
  113. * Extension du fichier, sinon vide
  114. **/
  115. function teleporter_http_extension($file){
  116. $e = pathinfo($file, PATHINFO_EXTENSION);
  117. // cas particuliers : redresser .tar.gz
  118. if ($e=='gz'
  119. AND preg_match(',tar\.gz,i',$file))
  120. $e = 'tgz';
  121. return $e;
  122. }
  123. /**
  124. * Cherche la plus longue racine commune à tous les fichiers
  125. *
  126. * @param array $list
  127. * Liste de chemin de fichiers
  128. * @return string
  129. * Chemin commun entre tous les fichiers
  130. **/
  131. function http_deballe_recherche_racine($list){
  132. // on cherche la plus longue racine commune a tous les fichiers
  133. // pour l'enlever au deballage
  134. $max_n = 999999;
  135. $paths = array();
  136. foreach($list as $n) {
  137. $p = array();
  138. foreach(explode('/', $n['filename']) as $n => $x) {
  139. if ($n>$max_n)
  140. continue;
  141. $sofar = join('/',$p);
  142. $paths[$n][$sofar]++;
  143. $p[] = $x;
  144. }
  145. $max_n = min($n,$max_n);
  146. }
  147. $total = $paths[0][''];
  148. $i = 0;
  149. while (isset($paths[$i])
  150. AND count($paths[$i]) <= 1
  151. AND array_values($paths[$i]) == array($total))
  152. $i++;
  153. $racine = '';
  154. if ($i){
  155. $racine = array_keys($paths[$i-1]);
  156. $racine = array_pop($racine).'/';
  157. }
  158. return $racine;
  159. }