From 5ba670f027a0b09e05958098c84ba60c83dddf33 Mon Sep 17 00:00:00 2001
From: Cerdic <cedric@yterium.com>
Date: Tue, 11 Jan 2022 11:51:20 +0100
Subject: [PATCH] Refactoring de la gestion des options headers/datas de
 recuperer_url() pour mieux gerer les sequences POST => 301 + Location => GET
 sur la nouvelle URL voire POST => 307 sur url2 => POST sur url2 => 302 sur
 url3 => GET sur url3 le tout sans perdre les headers d'origine en consequence
 on refabrique les donnes formattes a chaque redirection si besoin a partir
 des options headers+datas dont la derniere est eventuellement videe en cours
 de route

---
 ecrire/inc/distant.php | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/ecrire/inc/distant.php b/ecrire/inc/distant.php
index 21c48f4f69..a26ec61a64 100644
--- a/ecrire/inc/distant.php
+++ b/ecrire/inc/distant.php
@@ -453,30 +453,28 @@ function recuperer_url($url, $options = []) {
 
 
 	// Ajout des en-têtes spécifiques si besoin
-	$head_add = '';
+	$formatted_data = '';
 	if (!empty($options['headers'])) {
 		foreach ($options['headers'] as $champ => $valeur) {
-			$head_add .= $champ . ': ' . $valeur . "\r\n";
+			$formatted_data .= $champ . ': ' . $valeur . "\r\n";
 		}
-		// ne pas le repasser a recuperer_url si on follow un location, car ils seront dans datas
-		unset($options['headers']);
 	}
 
 	if (!empty($options['datas'])) {
 		[$head, $postdata] = prepare_donnees_post($options['datas'], $options['boundary']);
-		$head .= $head_add;
+		$head .= $formatted_data;
 		if (stripos($head, 'Content-Length:') === false) {
 			$head .= 'Content-Length: ' . strlen($postdata) . "\r\n";
 		}
-		$options['datas'] = $head . "\r\n" . $postdata;
+		$formatted_data = $head . "\r\n" . $postdata;
 		if (
 			strlen($postdata)
 			and !$methode_demandee
 		) {
 			$options['methode'] = 'POST';
 		}
-	} elseif ($head_add) {
-		$options['datas'] = $head_add . "\r\n";
+	} elseif ($formatted_data) {
+		$formatted_data .= "\r\n";
 	}
 
 	// Accepter les URLs au format feed:// ou qui ont oublie le http:// ou les urls relatives au protocole
@@ -508,7 +506,7 @@ function recuperer_url($url, $options = []) {
 		$url,
 		$refuser_gz,
 		$options['uri_referer'],
-		$options['datas'],
+		$formatted_data,
 		$options['version_http'],
 		$options['if_modified_since']
 	);
@@ -551,7 +549,15 @@ function recuperer_url($url, $options = []) {
 			fclose($handle);
 			include_spip('inc/filtres');
 			$url = suivre_lien($url, $res['location']);
-			spip_log("recuperer_url recommence sur $url", 'distant');
+
+			// une redirection doit se faire en GET, sauf status explicite 307 ou 308 qui indique de garder la meme methode
+			if ($options['methode'] !== 'GET') {
+				if (empty($res['status']) or !in_array($res['status'], [307, 308])) {
+					$options['methode'] = 'GET';
+					$options['datas'] = '';
+				}
+			}
+			spip_log("recuperer_url recommence " . $options['methode']. " sur $url", 'distant');
 
 			return recuperer_url($url, $options);
 		} elseif ($res['status'] !== 200) {
-- 
GitLab