aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-php-shim/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe-php-shim/src')
-rw-r--r--crates/shirabe-php-shim/src/runtime.rs7
-rw-r--r--crates/shirabe-php-shim/src/zip.rs36
2 files changed, 25 insertions, 18 deletions
diff --git a/crates/shirabe-php-shim/src/runtime.rs b/crates/shirabe-php-shim/src/runtime.rs
index c00c8f51..13513b9d 100644
--- a/crates/shirabe-php-shim/src/runtime.rs
+++ b/crates/shirabe-php-shim/src/runtime.rs
@@ -77,14 +77,9 @@ pub fn defined(name: &str) -> bool {
// `Composer\Autoload\ClassLoader` (and its `getRegisteredLoaders`) is absent from the running
// process; the class-name form therefore reports no such method. The object form needs runtime
// reflection that PhpMixed::Object does not carry.
-pub fn method_exists(object_or_class: &PhpMixed, method_name: &str) -> bool {
+pub fn method_exists(object_or_class: &PhpMixed, _method_name: &str) -> bool {
match object_or_class {
PhpMixed::String(_) => false,
- // `ZipArchiver::archive` guards `$zip->setExternalAttributesName(...)` with
- // `method_exists($zip, 'setExternalAttributesName')` (only available with libzip >= 0.11.2).
- // The `zip`-crate-backed shim cannot amend an already-written entry's external attributes,
- // so the method is deliberately absent here and the guard reports it missing.
- PhpMixed::Null if method_name == "setExternalAttributesName" => false,
_ => todo!(),
}
}
diff --git a/crates/shirabe-php-shim/src/zip.rs b/crates/shirabe-php-shim/src/zip.rs
index 7284b029..f028ffd0 100644
--- a/crates/shirabe-php-shim/src/zip.rs
+++ b/crates/shirabe-php-shim/src/zip.rs
@@ -218,17 +218,23 @@ impl ZipArchive {
)))
}
- pub fn add_empty_dir(&self, local_name: &str) -> bool {
+ pub fn add_empty_dir(&self, local_name: &str, opsys: i64, attr: i64) -> bool {
let mut state = self.state.borrow_mut();
let ZipState::Writer { writer, .. } = &mut *state else {
return false;
};
writer
- .add_directory(local_name, SimpleFileOptions::default())
+ .add_directory(local_name, Self::entry_options(opsys, attr))
.is_ok()
}
- pub fn add_file(&self, filepath: impl AsRef<std::path::Path>, local_name: &str) -> bool {
+ pub fn add_file(
+ &self,
+ filepath: impl AsRef<std::path::Path>,
+ local_name: &str,
+ opsys: i64,
+ attr: i64,
+ ) -> bool {
let contents = match std::fs::read(filepath.as_ref()) {
Ok(c) => c,
Err(_) => return false,
@@ -238,21 +244,27 @@ impl ZipArchive {
return false;
};
let options =
- SimpleFileOptions::default().compression_method(zip::CompressionMethod::Deflated);
+ Self::entry_options(opsys, attr).compression_method(zip::CompressionMethod::Deflated);
if writer.start_file(local_name, options).is_err() {
return false;
}
std::io::Write::write_all(writer, &contents).is_ok()
}
- pub fn set_external_attributes_name(&self, _name: &str, _opsys: i64, _attr: i64) -> bool {
- // TODO(phase-c): PHP's setExternalAttributesName mutates an already-added
- // entry's external attributes (e.g. Unix permissions) after addFile. The
- // `zip` crate fixes external attributes at start_file time via FileOptions
- // and exposes no API to amend a written entry, so this cannot be faithfully
- // reproduced without re-architecting add_file. Left unimplemented rather
- // than silently dropping the permission bits.
- todo!()
+ /// `opsys` and `attr` carry what PHP passes to `setExternalAttributesName`, which
+ /// amends an entry after `addFile`. The `zip` crate fixes external attributes when
+ /// the entry is started, so they are taken up front instead. `unix_permissions`
+ /// keeps only the low 9 mode bits, on top of which the crate restores `S_IFREG` for
+ /// files and `S_IFDIR` for directories; libzip stores `attr` verbatim, so
+ /// setuid/setgid/sticky bits and the remaining file types do not survive.
+ fn entry_options(opsys: i64, attr: i64) -> SimpleFileOptions {
+ let system = match opsys {
+ Self::OPSYS_UNIX => zip::System::Unix,
+ _ => todo!(),
+ };
+ SimpleFileOptions::default()
+ .system(system)
+ .unix_permissions((attr >> 16) as u32)
}
pub fn get_status_string(&self) -> String {