manifest = $manifest; $this->directory = untrailingslashit( $directory ); $this->zip_path = $zip_path; } /** * Returns the manifest. * * @return Manifest */ public function get_manifest(): Manifest { return $this->manifest; } /** * Returns the extraction directory. * * @return string */ public function get_directory(): string { return $this->directory; } /** * Returns the absolute local path of a file declared in the manifest. * * @param string $package_path Relative path inside the package. * @return string * @throws PackageException When the file is not declared, cannot be extracted, or is corrupted. */ public function get_file_path( string $package_path ): string { $file = $this->manifest->get_file( $package_path ); if ( null === $file ) { throw new PackageException( sprintf( /* translators: %s: File path inside the package. */ esc_html__( 'The file %s is not part of this package.', 'cherrylift' ), esc_html( $package_path ) ) ); } $path = $this->directory . '/' . $package_path; if ( null !== $this->zip_path && ! is_file( $path ) ) { $this->extract( $package_path, $file['sha256'], $path ); } return $path; } /** * Extracts one declared file and verifies its checksum. * * @param string $package_path Relative path inside the package (validated against the manifest). * @param string $sha256 Expected SHA-256. * @param string $path Absolute destination path. * @return void * @throws PackageException When extraction fails or the checksum does not match. */ private function extract( string $package_path, string $sha256, string $path ): void { $zip = new ZipArchive(); if ( true !== $zip->open( (string) $this->zip_path ) ) { throw new PackageException( esc_html__( 'The package file could not be read.', 'cherrylift' ) ); } $extracted = $zip->extractTo( $this->directory, $package_path ); $zip->close(); if ( ! $extracted || ! is_file( $path ) ) { throw new PackageException( esc_html__( 'The package could not be extracted.', 'cherrylift' ) ); } if ( ! hash_equals( $sha256, (string) hash_file( 'sha256', $path ) ) ) { wp_delete_file( $path ); throw new PackageException( sprintf( /* translators: %s: File path inside the package. */ esc_html__( 'The file %s is corrupted: its checksum does not match the manifest.', 'cherrylift' ), esc_html( $package_path ) ) ); } } }