use gpg_inspector_lib::packet::tags::PacketTag;
use gpg_inspector_lib::parse_bytes;
fn build_user_attribute_image(image_format: u8, image_data: &[u8]) -> Vec<u8> {
let mut packet = Vec::new();
packet.push(0xC0 | 17);
let header_len = 16;
let subpacket_data_len = 1 + header_len + image_data.len();
let subpacket_len_bytes = if subpacket_data_len < 192 { 1 } else { 2 };
let body_len = subpacket_len_bytes + subpacket_data_len;
packet.push(body_len as u8);
if subpacket_data_len < 192 {
packet.push(subpacket_data_len as u8);
} else {
let first = ((subpacket_data_len - 192) >> 8) as u8 + 192;
let second = ((subpacket_data_len - 192) & 0xFF) as u8;
packet.push(first);
packet.push(second);
}
packet.push(1);
packet.push(0x10); packet.push(0x00); packet.push(0x01); packet.push(image_format);
packet.extend_from_slice(&[0x00; 12]);
packet.extend_from_slice(image_data);
packet
}
fn build_user_attribute_unknown(subpacket_type: u8, data: &[u8]) -> Vec<u8> {
let mut packet = Vec::new();
packet.push(0xC0 | 17);
let subpacket_data_len = 1 + data.len(); let body_len = 1 + subpacket_data_len;
packet.push(body_len as u8);
packet.push(subpacket_data_len as u8); packet.push(subpacket_type);
packet.extend_from_slice(data);
packet
}
#[test]
fn test_user_attribute_basic() {
let packet = build_user_attribute_image(1, &[0xFF, 0xD8, 0xFF, 0xE0]);
let result = parse_bytes(packet);
assert!(result.is_ok(), "Failed: {:?}", result.err());
let packets = result.unwrap();
assert_eq!(packets[0].tag, PacketTag::UserAttribute);
}
#[test]
fn test_user_attribute_jpeg_format() {
let packet = build_user_attribute_image(1, &[0xFF, 0xD8, 0xFF, 0xE0]);
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let format_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Format");
assert!(format_field.is_some());
assert!(format_field.unwrap().value.contains("JPEG"));
}
#[test]
fn test_user_attribute_jpeg_detected() {
let packet = build_user_attribute_image(1, &[0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10]);
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let data_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Data");
assert!(data_field.is_some());
assert!(data_field.unwrap().value.contains("JPEG detected"));
}
#[test]
fn test_user_attribute_png_detected() {
let png_magic = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
let packet = build_user_attribute_image(1, &png_magic);
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let data_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Data");
assert!(data_field.is_some());
assert!(data_field.unwrap().value.contains("PNG detected"));
}
#[test]
fn test_user_attribute_gif_detected() {
let gif_magic = [0x47, 0x49, 0x46, 0x38, 0x39, 0x61];
let packet = build_user_attribute_image(1, &gif_magic);
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let data_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Data");
assert!(data_field.is_some());
assert!(data_field.unwrap().value.contains("GIF detected"));
}
#[test]
fn test_user_attribute_bmp_detected() {
let bmp_magic = [0x42, 0x4D, 0x00, 0x00];
let packet = build_user_attribute_image(1, &bmp_magic);
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let data_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Data");
assert!(data_field.is_some());
assert!(data_field.unwrap().value.contains("BMP detected"));
}
#[test]
fn test_user_attribute_private_format() {
let packet = build_user_attribute_image(100, &[0x00; 10]);
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let format_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Format");
assert!(format_field.is_some());
assert!(format_field.unwrap().value.contains("Private"));
}
#[test]
fn test_user_attribute_unknown_format() {
let packet = build_user_attribute_image(99, &[0x00; 10]);
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let format_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Format");
assert!(format_field.is_some());
assert!(format_field.unwrap().value.contains("Unknown"));
}
#[test]
fn test_user_attribute_unknown_subpacket() {
let packet = build_user_attribute_unknown(50, &[0xAB, 0xCD, 0xEF]);
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let subpacket_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Unknown Subpacket");
assert!(subpacket_field.is_some());
assert!(subpacket_field.unwrap().value.contains("Type 50"));
}
#[test]
fn test_user_attribute_private_subpacket() {
let packet = build_user_attribute_unknown(105, &[0x00; 5]);
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let subpacket_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Private Subpacket");
assert!(subpacket_field.is_some());
assert!(subpacket_field.unwrap().value.contains("Type 105"));
}
#[test]
fn test_user_attribute_image_data_size() {
let image_data = [0x00; 100];
let packet = build_user_attribute_image(1, &image_data);
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let data_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Data");
assert!(data_field.is_some());
assert!(data_field.unwrap().value.contains("100 bytes"));
}
#[test]
fn test_user_attribute_header_version() {
let packet = build_user_attribute_image(1, &[0xFF, 0xD8, 0xFF]);
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let subpacket_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Subpacket");
assert!(subpacket_field.is_some());
assert!(subpacket_field.unwrap().value.contains("Header v1"));
}
fn build_user_attribute_zero_length() -> Vec<u8> {
let mut packet = Vec::new();
packet.push(0xC0 | 17);
let image_data = [0xFF, 0xD8, 0xFF, 0xE0];
let header_len = 16;
let valid_subpacket_data_len = 1 + header_len + image_data.len();
let body_len = 1 + 1 + valid_subpacket_data_len; packet.push(body_len as u8);
packet.push(0);
packet.push(valid_subpacket_data_len as u8);
packet.push(1); packet.push(0x10); packet.push(0x00); packet.push(0x01); packet.push(1); packet.extend_from_slice(&[0x00; 12]); packet.extend_from_slice(&image_data);
packet
}
#[test]
fn test_user_attribute_zero_length_subpacket() {
let packet = build_user_attribute_zero_length();
let result = parse_bytes(packet);
assert!(result.is_ok(), "Failed: {:?}", result.err());
let packets = result.unwrap();
assert_eq!(packets[0].tag, PacketTag::UserAttribute);
}
fn build_user_attribute_unknown_header_version(header_version: u8, data: &[u8]) -> Vec<u8> {
let mut packet = Vec::new();
packet.push(0xC0 | 17);
let header_len = 16;
let subpacket_data_len = 1 + header_len + data.len();
let body_len = 1 + subpacket_data_len;
packet.push(body_len as u8);
packet.push(subpacket_data_len as u8);
packet.push(1);
packet.push(0x10); packet.push(0x00); packet.push(header_version); packet.extend_from_slice(&[0x00; 13]); packet.extend_from_slice(data);
packet
}
#[test]
fn test_user_attribute_unknown_header_version() {
let packet = build_user_attribute_unknown_header_version(99, &[0xAB, 0xCD, 0xEF]);
let result = parse_bytes(packet);
assert!(result.is_ok(), "Failed: {:?}", result.err());
let packets = result.unwrap();
assert_eq!(packets[0].tag, PacketTag::UserAttribute);
let data_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Data");
assert!(data_field.is_some());
assert!(data_field.unwrap().value.contains("unknown header v99"));
}
fn build_user_attribute_two_byte_length() -> Vec<u8> {
let mut packet = Vec::new();
packet.push(0xC0 | 17);
let subpacket_data_len = 200;
let first_len_byte = ((subpacket_data_len - 192) >> 8) as u8 + 192;
let second_len_byte = ((subpacket_data_len - 192) & 0xFF) as u8;
let body_len = 2 + subpacket_data_len;
if body_len < 192 {
packet.push(body_len as u8);
} else {
let first = ((body_len - 192) >> 8) as u8 + 192;
let second = ((body_len - 192) & 0xFF) as u8;
packet.push(first);
packet.push(second);
}
packet.push(first_len_byte);
packet.push(second_len_byte);
packet.push(50);
packet.extend_from_slice(&vec![0xAB; subpacket_data_len - 1]);
packet
}
#[test]
fn test_user_attribute_two_byte_length() {
let packet = build_user_attribute_two_byte_length();
let result = parse_bytes(packet);
assert!(result.is_ok(), "Failed: {:?}", result.err());
let packets = result.unwrap();
assert_eq!(packets[0].tag, PacketTag::UserAttribute);
let subpacket_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Unknown Subpacket");
assert!(subpacket_field.is_some());
assert!(subpacket_field.unwrap().value.contains("199 bytes")); }
fn build_user_attribute_tiny_image() -> Vec<u8> {
let mut packet = Vec::new();
packet.push(0xC0 | 17);
let image_data = [0x00, 0x00];
let header_len = 16;
let subpacket_data_len = 1 + header_len + image_data.len();
let body_len = 1 + subpacket_data_len;
packet.push(body_len as u8);
packet.push(subpacket_data_len as u8);
packet.push(1); packet.push(0x10);
packet.push(0x00);
packet.push(0x01); packet.push(1); packet.extend_from_slice(&[0x00; 12]);
packet.extend_from_slice(&image_data);
packet
}
#[test]
fn test_user_attribute_tiny_image_no_detection() {
let packet = build_user_attribute_tiny_image();
let result = parse_bytes(packet);
assert!(result.is_ok());
let packets = result.unwrap();
let data_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Data");
assert!(data_field.is_some());
assert!(data_field.unwrap().value.contains("2 bytes"));
}
fn build_user_attribute_unknown_header_no_remaining() -> Vec<u8> {
let mut packet = Vec::new();
packet.push(0xC0 | 17);
let subpacket_data_len = 4;
let body_len = 1 + subpacket_data_len;
packet.push(body_len as u8);
packet.push(subpacket_data_len as u8);
packet.push(1);
packet.push(0x03); packet.push(0x00); packet.push(99);
packet
}
#[test]
fn test_user_attribute_unknown_header_no_remaining_data() {
let packet = build_user_attribute_unknown_header_no_remaining();
let result = parse_bytes(packet);
assert!(result.is_ok(), "Failed: {:?}", result.err());
let packets = result.unwrap();
assert_eq!(packets[0].tag, PacketTag::UserAttribute);
let data_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Data");
assert!(data_field.is_some());
assert!(data_field.unwrap().value.contains("0 bytes"));
assert!(data_field.unwrap().value.contains("unknown header v99"));
}
fn build_user_attribute_five_byte_length() -> Vec<u8> {
let mut packet = Vec::new();
packet.push(0xC0 | 17);
let subpacket_data_len: u32 = 300;
let body_len = 5 + subpacket_data_len as usize;
let first = ((body_len - 192) >> 8) as u8 + 192;
let second = ((body_len - 192) & 0xFF) as u8;
packet.push(first);
packet.push(second);
packet.push(0xFF);
packet.extend_from_slice(&subpacket_data_len.to_be_bytes());
packet.push(50);
packet.extend_from_slice(&vec![0xAB; (subpacket_data_len - 1) as usize]);
packet
}
#[test]
fn test_user_attribute_five_byte_length_encoding() {
let packet = build_user_attribute_five_byte_length();
let result = parse_bytes(packet);
assert!(result.is_ok(), "Failed: {:?}", result.err());
let packets = result.unwrap();
assert_eq!(packets[0].tag, PacketTag::UserAttribute);
let subpacket_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Unknown Subpacket");
assert!(subpacket_field.is_some());
assert!(subpacket_field.unwrap().value.contains("299 bytes"));
}
fn build_user_attribute_truncated_image() -> Vec<u8> {
let mut packet = Vec::new();
packet.push(0xC0 | 17);
let subpacket_data_len = 20; let body_len = 1 + 17;
packet.push(body_len as u8); packet.push(subpacket_data_len as u8); packet.push(1);
packet.push(0x10); packet.push(0x00); packet.push(0x01); packet.push(1); packet.extend_from_slice(&[0x00; 12]);
packet.push(0xAB);
packet
}
#[test]
fn test_user_attribute_truncated_image_uses_rest() {
let packet = build_user_attribute_truncated_image();
let result = parse_bytes(packet);
assert!(result.is_ok(), "Failed: {:?}", result.err());
let packets = result.unwrap();
assert_eq!(packets[0].tag, PacketTag::UserAttribute);
let data_field = packets[0]
.fields
.iter()
.find(|f| f.name.as_ref() == "Image Data");
assert!(data_field.is_some(), "No Image Data field found");
let value = &data_field.unwrap().value;
assert!(
value.contains("0 bytes"),
"Expected '0 bytes' in value: {}",
value
);
}