diff --git a/stdlib/src/compress.rs b/stdlib/src/compress.rs index d1daf83b..455bda97 100644 --- a/stdlib/src/compress.rs +++ b/stdlib/src/compress.rs @@ -5,9 +5,127 @@ use std::io::{Read, Write}; use std::path::Path; use std::rc::Rc; use techscript_runtime::{ - context::Capability, error::RuntimeError, error::RuntimeErrorKind, value::RuntimeValue, + context::{Capability, RuntimeContext}, + error::RuntimeError, + error::RuntimeErrorKind, + value::RuntimeValue, }; +fn check_fs_capability(ctx: &RuntimeContext) -> Result<(), RuntimeError> { + if !ctx.config.capabilities.contains(&Capability::FileSystem) { + return Err(RuntimeError::new( + RuntimeErrorKind::InvalidOperation( + "Security policy violation: FileSystem capability is denied".to_string(), + ), + None, + None, + )); + } + Ok(()) +} + +fn sys_zip( + ctx: &mut RuntimeContext, + args: Vec, +) -> Result { + check_fs_capability(ctx)?; + let src_dir = args[0].try_into_string()?; + let archive_path = args[1].try_into_string()?; + zip_dir(&src_dir, &archive_path).map_err(|e| { + RuntimeError::new( + RuntimeErrorKind::InvalidOperation(format!("ZIP error: {}", e)), + None, + None, + ) + })?; + Ok(RuntimeValue::Null) +} + +fn sys_unzip( + ctx: &mut RuntimeContext, + args: Vec, +) -> Result { + check_fs_capability(ctx)?; + let archive_path = args[0].try_into_string()?; + let dest_dir = args[1].try_into_string()?; + unzip_archive(&archive_path, &dest_dir).map_err(|e| { + RuntimeError::new( + RuntimeErrorKind::InvalidOperation(format!("UNZIP error: {}", e)), + None, + None, + ) + })?; + Ok(RuntimeValue::Null) +} + +fn sys_tar( + ctx: &mut RuntimeContext, + args: Vec, +) -> Result { + check_fs_capability(ctx)?; + let src_dir = args[0].try_into_string()?; + let archive_path = args[1].try_into_string()?; + tar_dir(&src_dir, &archive_path).map_err(|e| { + RuntimeError::new( + RuntimeErrorKind::InvalidOperation(format!("TAR error: {}", e)), + None, + None, + ) + })?; + Ok(RuntimeValue::Null) +} + +fn sys_untar( + ctx: &mut RuntimeContext, + args: Vec, +) -> Result { + check_fs_capability(ctx)?; + let archive_path = args[0].try_into_string()?; + let dest_dir = args[1].try_into_string()?; + untar_archive(&archive_path, &dest_dir).map_err(|e| { + RuntimeError::new( + RuntimeErrorKind::InvalidOperation(format!("UNTAR error: {}", e)), + None, + None, + ) + })?; + Ok(RuntimeValue::Null) +} + +fn sys_gzip( + ctx: &mut RuntimeContext, + args: Vec, +) -> Result { + check_fs_capability(ctx)?; + let src_file = args[0].try_into_string()?; + let archive_path = args[1].try_into_string()?; + gzip_file(&src_file, &archive_path).map_err(|e| { + RuntimeError::new( + RuntimeErrorKind::InvalidOperation(format!("GZIP error: {}", e)), + None, + None, + ) + })?; + Ok(RuntimeValue::Null) +} + +fn sys_gunzip( + ctx: &mut RuntimeContext, + args: Vec, +) -> Result { + check_fs_capability(ctx)?; + let archive_path = args[0].try_into_string()?; + let dest_file = args[1].try_into_string()?; + gunzip_archive(&archive_path, &dest_file).map_err(|e| { + RuntimeError::new( + RuntimeErrorKind::InvalidOperation(format!("GUNZIP error: {}", e)), + None, + None, + ) + })?; + Ok(RuntimeValue::Null) +} + impl StdlibRegistry { pub fn register_compress(&mut self) { let mut exports: HashMap> = @@ -18,28 +136,7 @@ impl StdlibRegistry { Rc::new(StdFunction { name: "zip".to_string(), arity: 2, - callback: |ctx, args| { - if !ctx.config.capabilities.contains(&Capability::FileSystem) { - return Err(RuntimeError::new( - RuntimeErrorKind::InvalidOperation( - "Security policy violation: FileSystem capability is denied" - .to_string(), - ), - None, - None, - )); - } - let src_dir = args[0].try_into_string()?; - let archive_path = args[1].try_into_string()?; - zip_dir(&src_dir, &archive_path).map_err(|e| { - RuntimeError::new( - RuntimeErrorKind::InvalidOperation(format!("ZIP error: {}", e)), - None, - None, - ) - })?; - Ok(RuntimeValue::Null) - }, + callback: sys_zip, }), ); @@ -48,28 +145,7 @@ impl StdlibRegistry { Rc::new(StdFunction { name: "unzip".to_string(), arity: 2, - callback: |ctx, args| { - if !ctx.config.capabilities.contains(&Capability::FileSystem) { - return Err(RuntimeError::new( - RuntimeErrorKind::InvalidOperation( - "Security policy violation: FileSystem capability is denied" - .to_string(), - ), - None, - None, - )); - } - let archive_path = args[0].try_into_string()?; - let dest_dir = args[1].try_into_string()?; - unzip_archive(&archive_path, &dest_dir).map_err(|e| { - RuntimeError::new( - RuntimeErrorKind::InvalidOperation(format!("UNZIP error: {}", e)), - None, - None, - ) - })?; - Ok(RuntimeValue::Null) - }, + callback: sys_unzip, }), ); @@ -78,28 +154,7 @@ impl StdlibRegistry { Rc::new(StdFunction { name: "tar".to_string(), arity: 2, - callback: |ctx, args| { - if !ctx.config.capabilities.contains(&Capability::FileSystem) { - return Err(RuntimeError::new( - RuntimeErrorKind::InvalidOperation( - "Security policy violation: FileSystem capability is denied" - .to_string(), - ), - None, - None, - )); - } - let src_dir = args[0].try_into_string()?; - let archive_path = args[1].try_into_string()?; - tar_dir(&src_dir, &archive_path).map_err(|e| { - RuntimeError::new( - RuntimeErrorKind::InvalidOperation(format!("TAR error: {}", e)), - None, - None, - ) - })?; - Ok(RuntimeValue::Null) - }, + callback: sys_tar, }), ); @@ -108,28 +163,7 @@ impl StdlibRegistry { Rc::new(StdFunction { name: "untar".to_string(), arity: 2, - callback: |ctx, args| { - if !ctx.config.capabilities.contains(&Capability::FileSystem) { - return Err(RuntimeError::new( - RuntimeErrorKind::InvalidOperation( - "Security policy violation: FileSystem capability is denied" - .to_string(), - ), - None, - None, - )); - } - let archive_path = args[0].try_into_string()?; - let dest_dir = args[1].try_into_string()?; - untar_archive(&archive_path, &dest_dir).map_err(|e| { - RuntimeError::new( - RuntimeErrorKind::InvalidOperation(format!("UNTAR error: {}", e)), - None, - None, - ) - })?; - Ok(RuntimeValue::Null) - }, + callback: sys_untar, }), ); @@ -138,28 +172,7 @@ impl StdlibRegistry { Rc::new(StdFunction { name: "gzip".to_string(), arity: 2, - callback: |ctx, args| { - if !ctx.config.capabilities.contains(&Capability::FileSystem) { - return Err(RuntimeError::new( - RuntimeErrorKind::InvalidOperation( - "Security policy violation: FileSystem capability is denied" - .to_string(), - ), - None, - None, - )); - } - let src_file = args[0].try_into_string()?; - let archive_path = args[1].try_into_string()?; - gzip_file(&src_file, &archive_path).map_err(|e| { - RuntimeError::new( - RuntimeErrorKind::InvalidOperation(format!("GZIP error: {}", e)), - None, - None, - ) - })?; - Ok(RuntimeValue::Null) - }, + callback: sys_gzip, }), ); @@ -168,28 +181,7 @@ impl StdlibRegistry { Rc::new(StdFunction { name: "gunzip".to_string(), arity: 2, - callback: |ctx, args| { - if !ctx.config.capabilities.contains(&Capability::FileSystem) { - return Err(RuntimeError::new( - RuntimeErrorKind::InvalidOperation( - "Security policy violation: FileSystem capability is denied" - .to_string(), - ), - None, - None, - )); - } - let archive_path = args[0].try_into_string()?; - let dest_file = args[1].try_into_string()?; - gunzip_archive(&archive_path, &dest_file).map_err(|e| { - RuntimeError::new( - RuntimeErrorKind::InvalidOperation(format!("GUNZIP error: {}", e)), - None, - None, - ) - })?; - Ok(RuntimeValue::Null) - }, + callback: sys_gunzip, }), ); diff --git a/stdlib/tests/stdlib_tests.rs b/stdlib/tests/stdlib_tests.rs index ce296064..50a54c49 100644 --- a/stdlib/tests/stdlib_tests.rs +++ b/stdlib/tests/stdlib_tests.rs @@ -540,7 +540,9 @@ fn test_http_module() { &mut ctx_unprivileged, vec![RuntimeValue::Str(format!("http://127.0.0.1:{}", port))], ); - assert!(matches!(res_get, Err(techscript_runtime::RuntimeError { kind: techscript_runtime::RuntimeErrorKind::InvalidOperation(msg), .. }) if msg.contains("Security policy violation"))); + assert!( + matches!(res_get, Err(techscript_runtime::RuntimeError { kind: techscript_runtime::RuntimeErrorKind::InvalidOperation(msg), .. }) if msg.contains("Security policy violation")) + ); let post = http.exports.get("post").unwrap(); let res_post = post.call( @@ -550,7 +552,9 @@ fn test_http_module() { RuntimeValue::Str("body".to_string()), ], ); - assert!(matches!(res_post, Err(techscript_runtime::RuntimeError { kind: techscript_runtime::RuntimeErrorKind::InvalidOperation(msg), .. }) if msg.contains("Security policy violation"))); + assert!( + matches!(res_post, Err(techscript_runtime::RuntimeError { kind: techscript_runtime::RuntimeErrorKind::InvalidOperation(msg), .. }) if msg.contains("Security policy violation")) + ); // Test with Network capability let mut caps = HashSet::new();