1"""Stuffit handlers.
2
3We currently support detecting two specific Stuffit file formats:
4
5 - Stuffit SIT (with 'SIT!' magic)
6
7 - Stuffit 5 (with 'StuffIt (c)1997-' magic)
8
9Due to lack of access to sample files, source code, and really old
10packing tools, we don't support the following Stuffit file formats at
11the moment:
12
13 - Stuffit X ('StuffIt!' or 'StuffIt?' magic)
14
15 - Stuffit Delux ('SITD' magic)
16
17If you have the resources to add support for these archive formats,
18feel free to do so !
19"""
20
21from structlog import get_logger
22
23from ...extractors import Command
24from ...file_utils import Endian
25from ...models import (
26 File,
27 HandlerDoc,
28 HandlerType,
29 HexString,
30 Reference,
31 StructHandler,
32 ValidChunk,
33)
34
35logger = get_logger()
36
37
38class _StuffItHandlerBase(StructHandler):
39 """A common base for all StuffIt formats."""
40
41 def calculate_chunk(self, file: File, start_offset: int) -> ValidChunk | None:
42 header = self.parse_header(file, endian=Endian.BIG)
43
44 return ValidChunk(
45 start_offset=start_offset,
46 end_offset=start_offset + header.archive_length,
47 )
48
49 EXTRACTOR = Command("unar", "-no-directory", "-o", "{outdir}", "{inpath}")
50
51
52class StuffItSITHandler(_StuffItHandlerBase):
53 NAME = "stuffit"
54
55 PATTERNS = [
56 HexString(
57 """
58 // "SIT!\\x00", then 6 bytes (uint16 number of files and uint32 size), then "rLau".
59 53 49 54 21 [6] 72 4C 61 75
60 """
61 )
62 ]
63
64 C_DEFINITIONS = r"""
65 typedef struct sit_header
66 {
67 char signature[4];
68 uint16 num_files;
69 uint32 archive_length;
70 char signature2[4];
71 } sit_header_t;
72 """
73 HEADER_STRUCT = "sit_header_t"
74
75 EXTRACTOR = Command("unar", "-no-directory", "-o", "{outdir}", "{inpath}")
76
77 DOC = HandlerDoc(
78 name="Stuffit SIT",
79 description="StuffIt SIT archives is a legacy compressed archive format commonly used on macOS and earlier Apple systems.",
80 handler_type=HandlerType.ARCHIVE,
81 vendor="StuffIt Technologies",
82 references=[
83 Reference(
84 title="StuffIt SIT File Format Documentation",
85 url="https://en.wikipedia.org/wiki/StuffIt",
86 )
87 ],
88 limitations=[],
89 )
90
91
92class StuffIt5Handler(_StuffItHandlerBase):
93 NAME = "stuffit5"
94
95 PATTERNS = [
96 HexString(
97 """
98 // "StuffIt (c)1997-"
99 53 74 75 66 66 49 74 20 28 63 29 31 39 39 37 2D
100 """
101 )
102 ]
103
104 C_DEFINITIONS = r"""
105 typedef struct stuffit5_header
106 {
107 char signature[80];
108 uint32 unknown;
109 uint32 archive_length;
110 uint32 entry_offset;
111 uint16 num_root_dir_entries;
112 uint32 first_entry_offset;
113 } stuffit5_header_t;
114 """
115 HEADER_STRUCT = "stuffit5_header_t"
116
117 EXTRACTOR = Command("unar", "-no-directory", "-o", "{outdir}", "{inpath}")
118
119 DOC = HandlerDoc(
120 name="Stuffit SIT (v5)",
121 description="StuffIt SIT archives is a legacy compressed archive format commonly used on macOS and earlier Apple systems.",
122 handler_type=HandlerType.ARCHIVE,
123 vendor="StuffIt Technologies",
124 references=[
125 Reference(
126 title="StuffIt SIT File Format Documentation",
127 url="https://en.wikipedia.org/wiki/StuffIt",
128 )
129 ],
130 limitations=[],
131 )