wp-cli / extension-command

Manages plugins and themes, including installs, activations, and updates.
MIT License
90 stars 79 forks source link

PCLZIP_ERR_BAD_FORMAT for 3rd party updates #362

Closed jfacemyer closed 1 year ago

jfacemyer commented 1 year ago

Problem: when I update plugins with wp-cli on many sites, official WP plugin repo plugins update fine; 3rd party updates do not, and error out with: PCLZIP_ERR_BAD_FORMAT (-10) : Unable to find End of Central Dir Record signature

When updating from the WP admin panel, the updates work fine.

(This happens with about 50 sites on this server - not all have 3rd party plugins, but the ones that do exhibit the same behavior according to my non-exhaustive testing.)

When I look at the wp-cli cached update files, the failed 3rd party updates do not have the .zip ending, and attempting to unzip them fails with a corruption error.

I recently moved my sites to php8.1 from 7.4. I'm on Ubuntu server 20.04.

I don't have any way to know if this is related to the update to 8.1, just going on the coincident occurrences.

I have made sure software is up-to-date (especially wp-cli and the php curl and zip packages).

Thoughts on how I can test this for further info, and possibly a fix? I'm assuming it's something configured oddly on my server.

Thank you!

Luc45 commented 1 year ago

This can happen if the archive was generated by MacOS Archiver.

PHP comes with the zip extension. The zip extension uses libzip, a C library that follows the PKWARE ZIP specification, the de-facto standard for Zip files in the world.

The Archive Utility in macOS is poorly written, and produces zip files that violates the specificiation.

Some Zip softwares are tolerant to this, and can parse it, others, such as libzip, can’t. Therefore, PHP can’t either.

I’ve just opened a bug report at libzip, and they added a workaround to tolerate this failure from the Archive Utility: https://github.com/nih-at/libzip/issues/341

So in the future versions of PHP (8.3+), this probably happen anymore.

As a workaround for this, WordPress Core uses PclZip as a fallback in wp-admin/includes/file.php. I'm not sure about WP CLI.

jfacemyer commented 1 year ago

Thanks for thinking about this problem, @Luc45!

I don't know all the workings as well as you, but it doesn't seem like this is what's going on:

  1. The error is from PCLZIP
  2. It only happens with 3rd party plugin sources, and AFAICT it happens with all third party plugin sources I use on my sites from various vendors (Gravity Forms, Gravity Wiz, WC Booster, Astra to name a few). It seems highly coincidental that ALL the 3rd party vendor plugins use Macs for zipping.
  3. I can't be the only person who's seen this if it's a problem with the software in general. There should be other reports?
  4. It appears that the files are just not saved correctly when downloaded by WP-Cli - they can't be unzipped with the linux zip command either, they don't have a *.zip extension, they can't be installed by WP. But when WP downloads the same plugin archives, the files install just fine.

I'd love to have some thoughts on tracking down why it's happening so I can maybe fix it.

jfacemyer commented 1 year ago

Any other help with this?

danielbachhuber commented 1 year ago

@jfacemyer Can you provide a problematic file to test with?

Ideally, it would be some small generic plugin we could incorporate into our test suite.

jfacemyer commented 1 year ago

Are you asking for a corrupted zip file after a failed update? One I have ATM that could work is LayerSlider. It's not really small...

I did just notice that gravitywiz plugins updated fine on one of my sites with WP-CLI, so I'm really not sure what's going on...

danielbachhuber commented 1 year ago

Yeah, a corrupted ZIP file to test with. Ideally, it would be an example of the failure, so we don't have to worry about distributing trademarks, etc.

jfacemyer commented 1 year ago

I can't really provide anything except third party plugins - I don't know what would work other than that, I don't have, e.g., personal plugins in a repo that updated this way.

Since they're corrupted, I doubt they can be used by anyone for anything?

I could also provide the file privately so at least there's no public file being transferred?

jfacemyer commented 1 year ago

Dude, I figured this out. It's my fault, so apologies up front.

I had (unknown to me) php 8.2 installed alongside 8.1. 8.2 was being used as default for command-line! Once I changed default command line php to 8.1, issue seems to be resolved.

Glad I figured that out - and maybe this can help someone else sometime :)