php generate-manifest.php [--critical]\n" ); exit( 1 ); } $secret_b64 = getenv( 'ARGUS_RELEASE_SECRET_KEY' ); if ( ! $secret_b64 ) { fwrite( STDERR, "ARGUS_RELEASE_SECRET_KEY environment variable is not set.\n" ); exit( 1 ); } $secret_key = base64_decode( $secret_b64, true ); if ( false === $secret_key || SODIUM_CRYPTO_SIGN_SECRETKEYBYTES !== strlen( $secret_key ) ) { fwrite( STDERR, "ARGUS_RELEASE_SECRET_KEY is not a valid base64-encoded Ed25519 secret key.\n" ); exit( 1 ); } $zip = new ZipArchive(); if ( true !== $zip->open( $zip_path ) ) { fwrite( STDERR, "Could not open {$zip_path}\n" ); exit( 1 ); } $header = null; for ( $i = 0; $i < $zip->numFiles; $i++ ) { $name = $zip->getNameIndex( $i ); if ( preg_match( '#(^|/)argus-wordpress-defence\.php$#', $name ) ) { $header = $zip->getFromIndex( $i ); break; } } $zip->close(); if ( ! $header ) { fwrite( STDERR, "Could not find argus-wordpress-defence.php inside the archive.\n" ); exit( 1 ); } preg_match( '/Version:\s*([^\r\n]+)/', $header, $m_version ); preg_match( '/Requires at least:\s*([^\r\n]+)/', $header, $m_wp ); preg_match( '/Requires PHP:\s*([^\r\n]+)/', $header, $m_php ); $version = trim( $m_version[1] ?? '' ); $min_wp = trim( $m_wp[1] ?? '0' ); $min_php = trim( $m_php[1] ?? '0' ); if ( '' === $version ) { fwrite( STDERR, "Could not read Version from the archive's plugin header.\n" ); exit( 1 ); } $sha256 = hash_file( 'sha256', $zip_path ); $payload = array( 'version' => $version, 'released_at' => gmdate( 'Y-m-d\TH:i:s\Z' ), 'package_url' => $package_url, 'sha256' => $sha256, 'min_php' => $min_php, 'min_wp' => $min_wp, 'critical' => $critical, ); $canonical = wp_json_encode_stable( $payload ); $signature = sodium_crypto_sign_detached( $canonical, $secret_key ); $manifest = $payload; $manifest['signature'] = base64_encode( $signature ); echo json_encode( $manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ) . "\n"; function wp_json_encode_stable( array $payload ) { $ordered = array(); foreach ( array( 'version', 'released_at', 'package_url', 'sha256', 'min_php', 'min_wp', 'critical' ) as $key ) { $ordered[ $key ] = $payload[ $key ]; } return json_encode( $ordered, JSON_UNESCAPED_SLASHES ); }