private function end($data)
{
if (!$this->bodies && $data != "") {
// if we end up here, we haven't parsed anything at all yet, so do a quick parse
if ($this->boundary !== null) {
$fields = $metadata = [];
// RFC 7578, RFC 2046 Section 5.1.1
if (strncmp($data, "--{$this->boundary}\r\n", \strlen($this->boundary) + 4) !== 0) {
return new ParsedBody([]);
}
$exp = explode("\r\n--{$this->boundary}\r\n", $data);
$exp[0] = substr($exp[0], \strlen($this->boundary) + 4);
$exp[count($exp) - 1] = substr(end($exp), 0, -\strlen($this->boundary) - 8);
foreach ($exp as $entry) {
list($rawheaders, $text) = explode("\r\n\r\n", $entry, 2);
$headers = [];
foreach (explode("\r\n", $rawheaders) as $header) {
$split = explode(":", $header, 2);
if (!isset($split[1])) {
return new ParsedBody([]);
}
$headers[strtolower($split[0])] = trim($split[1]);
}
if (!preg_match('#^\\s*form-data(?:\\s*;\\s*(?:name\\s*=\\s*"([^"]+)"|filename\\s*=\\s*"([^"]+)"))+\\s*$#', $headers["content-disposition"] ?? "", $m) || !isset($m[1])) {
return new ParsedBody([]);
}
$name = $m[1];
$fields[$name][] = $text;
// Ignore Content-Transfer-Encoding as deprecated and hence we won't support it
if (isset($m[2])) {
$metadata[$name][count($fields[$name]) - 1] = ["filename" => $m[2], "mime" => $headers["content-type"] ?? "application/octet-stream"];
} elseif (isset($headers["content-type"])) {
$metadata[$name][count($fields[$name]) - 1]["mime"] = $headers["content-type"];
}
}
return new ParsedBody($fields, $metadata);
} else {
$fields = [];
foreach (explode("&", $data) as $pair) {
$pair = explode("=", $pair, 2);
$fields[urldecode($pair[0])][] = urldecode($pair[1] ?? "");
}
return new ParsedBody($fields, []);
}
} else {
$fields = $metadata = [];
$when = static function ($e, $data) use(&$fields, &$key) {
$fields[$key][] = $data;
};
$metawhen = static function ($e, $data) use(&$metadata, &$key) {
$metadata[$key][] = $data;
};
foreach ($this->bodies as $key => $bodies) {
foreach ($bodies as $body) {
$body->when($when);
$body->getMetadata()->when($metawhen);
}
$metadata[$key] = array_filter($metadata[$key]);
}
return new ParsedBody($fields, array_filter($metadata));
}
}