0

I'm having an issue trying to read data from a HTTP POST request that has multiple attachments with mime boundaries like so :

----MIME_boundary

Content-Type: text/xml; charset=UTF-8

Content-Transfer-Encoding: 8bit

Content-Id: <xml.xml>

xml data

----MIME_boundary

Content-Type: application/zip

Content-Transfer-Encoding: binary

Content-Disposition: attachment; filename="test.zip"

Content-Id: <test.zip>

PK (binary/ASCII data)

----MIME_boundary--

I have split the request up into the data I need using a function wrote with help from this post : Manually parse raw multipart/form-data data with PHP

Essentially, I have been able to take the binary of that zip file, and then feed it to another function I have written, which should be able to create a temporary zip file from the binary, that I can then use the ZipArchive class in PHP to read and return a list of all the files within that zip file.

public static function unzip($zipBinary) {

    $zip = new ZipArchive;

    // create temp file from given binary
    $file = tempnam("tmp", "zip");
    file_put_contents($file, $zipBinary);

    $res = $zip->open($file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE);

    if ($res === TRUE) {

        $files = [];

        // create array of files from zip

        for ($i = 0; $i < $zip->numFiles; $i++) {  
            $files[$zip->getNameIndex($i)] = $zip->getFromIndex($i);
        }  

        $zip->close();  

        // delete temp file

        unlink($file);

        return $files;

    } 

}

The issue I've been having and can't seem to solve for the life of me is that the zip file created using file_put_contents seems to not work at all. When I try to count the number of files, I get 0. I am not sure if this is a problem with the binary in the example request that I have been given to set up the REST endpoint, or if it's an issue with my code.

I have tried a few different forms of debugging - I've tested that the zip file is actually being populated by looking at the return value of file_put_contents(), and I've also tried using rename() on the temporary file to put it in the same directory as my script to see if the zip file is valid and can be opened - which it is not, I get 'unsupported format' errors when trying to open it - I have also tried opening it with a text editor to no avail. I will probably try converting a different zip file to binary and trying to see if I encounter the same issues after I have finished posting this.

I would be extremely grateful if anyone could point me in the right direction and let me know if it's a problem with the binary (and how I could possibly solve it), or whether I can make code changes to alleviate the issue.

I have tried many different things from many different google/stackoverflow searches with no success, and thought that I would post here as a last resort.

Thanks

lsg93
  • 76
  • 6
  • Ostensibly if `ZIPARCHIVE::OVERWRITE` were enabled it would blank out the file. Since you're trying to open an existing archive with this function I would suggest not including the create or overwrite flags at all. – Sammitch Jul 30 '21 at 17:32
  • Thanks for replying - I've corrected this, but I'm now being greeted with ZIPARCHIVE::ER_NOZIP - 19 when trying to run $zip->open - there must definitely be a problem of some sort with the actual zip I'm attempting to create. – lsg93 Jul 30 '21 at 18:03
  • Now that I think about it, why are you manually parsing this POST request? PHP should already have done that and made these files available via the information in `$_FILES`. https://www.php.net/manual/en/features.file-upload.post-method.php – Sammitch Jul 30 '21 at 18:10
  • All three of $_REQUEST, $_POST and $_FILES are empty when I attempt to parse the request in PHP. I've had to use php://input in order to read the request, then basically preg_split the request on the boundaries in order to get the file data needed. – lsg93 Jul 30 '21 at 19:59
  • Then your issue may further up the chain. I would venture to guess that the POST is being submitted without a proper `Content-Type: multipart/form-data` header, which is what would trigger PHP to process the POST data for this case. – Sammitch Jul 30 '21 at 20:28
  • Yes - the requests are going to have the Content-Type: multipart/related, which is not what I'm typically used to working with when it comes to POST requests. – lsg93 Jul 30 '21 at 20:56
  • Specifically with regard to PHP it _must_ be `multipart/form-data` if you want to leverage PHP's handling of the data. `related` might be semantically correct for your intended usage, but it won't trigger PHP. If it's completely infeasible to alter the header sent by the client, then I would suggest rewriting this header somewhere intermediate, eg: in the web server config. – Sammitch Jul 30 '21 at 21:07
  • Parsing MIME messages is problematic in PHP because there's a presiding assumption that this is handled entirely by PHP's core/extension code, which is why there are no useful MIME functions expose to userspace. Personally, I wholly disagree with this and would like to see them exposed for niche cases, but ultimately yours is not really one of those and you should be able to leverage the POST processor by tickling it with the correct header. – Sammitch Jul 30 '21 at 21:08

0 Answers0