mod bitmap;
mod commands;
mod types;
mod util;
pub use bitmap::*;
pub use commands::*;
pub use types::*;
pub use util::*;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_afp_status_round_trip() {
let status = FPGetSrvrInfo {
machine_type: MacString::from("Macintosh"),
afp_versions: vec![
AfpVersion::Version1_1,
AfpVersion::Version2,
AfpVersion::Version2_1,
],
uams: vec![AfpUam::NoUserAuthent, AfpUam::CleartxtPasswrd],
volume_icon: Some([0xAA; 256]), flags: 0x0001, server_name: MacString::from("Test Server"),
};
let bytes = status.to_bytes().expect("Serialization failed");
assert_eq!(bytes.len(), 368);
let parsed = FPGetSrvrInfo::parse(&bytes).expect("Parsing failed");
assert_eq!(status, parsed);
}
#[test]
fn test_afp_status_no_icon() {
let status = FPGetSrvrInfo {
machine_type: MacString::from("Macintosh"),
afp_versions: vec![AfpVersion::Version2],
uams: vec![AfpUam::NoUserAuthent],
volume_icon: None,
flags: 0,
server_name: MacString::from("Mini"),
};
let bytes = status.to_bytes().expect("Serialization failed");
let parsed = FPGetSrvrInfo::parse(&bytes).expect("Parsing failed");
assert_eq!(status, parsed);
}
#[test]
fn test_afp_status_binary() {
let test_data: &[u8] = &[
0x0, 0x2b, 0x0, 0x35, 0x0, 0x63, 0x0, 0x9d, 0x80, 0xb, 0xc, 0x50, 0x6f, 0x77, 0x65,
0x72, 0x42, 0x6f, 0x6f, 0x6b, 0x20, 0x47, 0x33, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x9, 0x4d, 0x61, 0x63, 0x69, 0x6e, 0x74, 0x6f, 0x73, 0x68, 0x3, 0xe, 0x41, 0x46, 0x50,
0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x2e, 0x31, 0xe, 0x41, 0x46,
0x50, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x2e, 0x30, 0xe, 0x41,
0x46, 0x50, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x2e, 0x31, 0x3,
0x10, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x74, 0x78, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73,
0x77, 0x72, 0x64, 0x10, 0x52, 0x61, 0x6e, 0x64, 0x6e, 0x75, 0x6d, 0x20, 0x65, 0x78,
0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x16, 0x32, 0x2d, 0x57, 0x61, 0x79, 0x20, 0x52,
0x61, 0x6e, 0x64, 0x6e, 0x75, 0x6d, 0x20, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
0x65, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x9f, 0xe0,
0x0, 0x4, 0x50, 0x30, 0x0, 0x8, 0x30, 0x28, 0x0, 0x10, 0x10, 0x3c, 0x7, 0xa0, 0x8, 0x4,
0x18, 0x7f, 0x4, 0x4, 0x10, 0x0, 0x82, 0x4, 0x10, 0x0, 0x81, 0x4, 0x10, 0x0, 0x82, 0x4,
0x10, 0x0, 0x84, 0x4, 0x10, 0x0, 0x88, 0x4, 0x10, 0x0, 0x90, 0x4, 0x10, 0x0, 0xb0, 0x4,
0x10, 0x0, 0xd0, 0x4, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0x2, 0x3f, 0xff, 0xff,
0xfc, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x5, 0x0,
0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0x8, 0x80, 0x0, 0x0, 0x8, 0x80, 0x0, 0x0, 0xf, 0x80,
0x0, 0x0, 0xa, 0x80, 0xbf, 0xff, 0xf2, 0x74, 0x0, 0x0, 0x5, 0x0, 0xbf, 0xff, 0xf8,
0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x3, 0x9f, 0xe0,
0x0, 0x7, 0xdf, 0xf0, 0x0, 0xf, 0xff, 0xf8, 0x0, 0x1f, 0xff, 0xfc, 0x7, 0xbf, 0xff,
0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f,
0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff,
0xfc, 0x1f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f,
0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0,
0x0, 0x7, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0,
0xf, 0x80, 0x0, 0x0, 0xf, 0x80, 0x0, 0x0, 0xf, 0x80, 0xbf, 0xff, 0xff, 0xf4, 0xbf,
0xff, 0xfd, 0xf4, 0xbf, 0xff, 0xf8, 0xf4,
];
let packet = FPGetSrvrInfo::parse(test_data).expect("Failed to parse test data");
assert_eq!(packet.machine_type.as_str(), "Macintosh");
assert_eq!(packet.afp_versions.len(), 3);
assert_eq!(packet.uams.len(), 3);
assert_eq!(packet.server_name.as_str(), "PowerBook G3");
let encoded = packet.to_bytes().expect("Failed to encode packet");
let reparsed = FPGetSrvrInfo::parse(&encoded).expect("Failed to reparse encoded data");
assert_eq!(packet, reparsed);
}
#[test]
fn test_fplogin_no_auth() {
let login = FPLogin {
afp_version: AfpVersion::Version2,
auth: FPLoginAuth::NoUserAuthent,
};
let encoded = login.to_bytes().expect("Failed to encode");
let decoded = FPLogin::parse(&encoded).expect("Failed to parse");
assert_eq!(login, decoded);
assert_eq!(decoded.afp_version, AfpVersion::Version2);
assert_eq!(decoded.auth, FPLoginAuth::NoUserAuthent);
}
#[test]
fn test_fplogin_cleartext() {
let mut password = [0u8; 8];
password[..4].copy_from_slice(b"pass");
let login = FPLogin {
afp_version: AfpVersion::Version2_1,
auth: FPLoginAuth::CleartxtPasswrd {
username: MacString::from("testuser"),
password,
},
};
let encoded = login.to_bytes().expect("Failed to encode");
let decoded = FPLogin::parse(&encoded).expect("Failed to parse");
assert_eq!(login, decoded);
assert_eq!(decoded.afp_version, AfpVersion::Version2_1);
if let FPLoginAuth::CleartxtPasswrd {
username,
password: pwd,
} = decoded.auth
{
assert_eq!(username.as_str(), "testuser");
assert_eq!(&pwd[..4], b"pass");
assert_eq!(&pwd[4..], &[0, 0, 0, 0]); } else {
panic!("Expected CleartxtPasswrd auth");
}
}
#[test]
fn test_fplogin_round_trip() {
let test_cases = vec![
FPLogin {
afp_version: AfpVersion::Version1,
auth: FPLoginAuth::NoUserAuthent,
},
FPLogin {
afp_version: AfpVersion::Version2,
auth: FPLoginAuth::CleartxtPasswrd {
username: MacString::from("admin"),
password: *b"secret\0\0",
},
},
];
for original in test_cases {
let encoded = original.to_bytes().expect("Failed to encode");
let decoded = FPLogin::parse(&encoded).expect("Failed to parse");
assert_eq!(original, decoded);
}
}
#[test]
fn test_fplogin_errors() {
assert!(FPLogin::parse(&[]).is_err());
assert!(FPLogin::parse(&[5]).is_err());
let invalid_version = vec![
10, b'B', b'a', b'd', b'V', b'e', b'r', b's', b'i', b'o', b'n', 16, b'N', b'o', b' ',
b'U', b's', b'e', b'r', b' ', b'A', b'u', b't', b'h', b'e', b'n', b't',
];
assert!(FPLogin::parse(&invalid_version).is_err());
let invalid_uam = vec![
14, b'A', b'F', b'P', b'V', b'e', b'r', b's', b'i', b'o', b'n', b' ', b'2', b'.', b'0',
10, b'B', b'a', b'd', b'U', b'A', b'M', b'N', b'a', b'm', b'e',
];
assert!(FPLogin::parse(&invalid_uam).is_err());
let missing_password = vec![
14, b'A', b'F', b'P', b'V', b'e', b'r', b's', b'i', b'o', b'n', b' ', b'2', b'.', b'0',
16, b'C', b'l', b'e', b'a', b'r', b't', b'x', b't', b' ', b'P', b'a', b's', b's', b'w',
b'r', b'd', 4, b'u', b's', b'e', b'r',
];
assert!(FPLogin::parse(&missing_password).is_err());
}
#[test]
fn test_fplogin_long_username() {
let long_username = "a".repeat(300);
let mut password = [0u8; 8];
password[..4].copy_from_slice(b"test");
let login = FPLogin {
afp_version: AfpVersion::Version2,
auth: FPLoginAuth::CleartxtPasswrd {
username: MacString::from(long_username.clone()),
password,
},
};
let encoded = login.to_bytes().expect("Failed to encode");
let decoded = FPLogin::parse(&encoded).expect("Failed to parse");
if let FPLoginAuth::CleartxtPasswrd { username, .. } = decoded.auth {
assert_eq!(username.len(), 255);
assert_eq!(username.as_str(), "a".repeat(255));
} else {
panic!("Expected CleartxtPasswrd auth");
}
}
}