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