1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsDecodeAppleFile.h"
9 NS_IMPL_ADDREF(nsDecodeAppleFile
)
10 NS_IMPL_RELEASE(nsDecodeAppleFile
)
12 NS_INTERFACE_MAP_BEGIN(nsDecodeAppleFile
)
13 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIOutputStream
)
14 NS_INTERFACE_MAP_ENTRY(nsIOutputStream
)
17 nsDecodeAppleFile::nsDecodeAppleFile() {
18 m_state
= parseHeaders
;
19 m_dataBufferLength
= 0;
20 m_dataBuffer
= (unsigned char*)malloc(MAX_BUFFERSIZE
);
23 m_totalDataForkWritten
= 0;
24 m_totalResourceForkWritten
= 0;
28 memset(&m_dates
, 0, sizeof(m_dates
));
29 memset(&m_finderInfo
, 0, sizeof(m_dates
));
30 memset(&m_finderExtraInfo
, 0, sizeof(m_dates
));
33 nsDecodeAppleFile::~nsDecodeAppleFile() {
35 m_dataBuffer
= nullptr;
36 if (m_entries
) delete[] m_entries
;
39 NS_IMETHODIMP
nsDecodeAppleFile::Initialize(nsIOutputStream
* output
,
43 nsCOMPtr
<nsILocalFileMac
> macFile
= do_QueryInterface(file
);
44 macFile
->GetTargetFSSpec(&m_fsFileSpec
);
52 NS_IMETHODIMP
nsDecodeAppleFile::Close(void) {
54 rv
= m_output
->Close();
58 if (m_rfRefNum
!= -1) FSClose(m_rfRefNum
);
60 /* Check if the file is complete and if it's the case, write file attributes
63 bool dataOk
= true; /* It's ok if the file doesn't have a datafork,
64 therefore set it to true by default. */
65 if (m_headers
.magic
== APPLESINGLE_MAGIC
) {
66 for (i
= 0; i
< m_headers
.entriesCount
; i
++)
67 if (ENT_DFORK
== m_entries
[i
].id
) {
68 dataOk
= (bool)(m_totalDataForkWritten
== m_entries
[i
].length
);
73 bool resourceOk
= FALSE
;
74 for (i
= 0; i
< m_headers
.entriesCount
; i
++)
75 if (ENT_RFORK
== m_entries
[i
].id
) {
76 resourceOk
= (bool)(m_totalResourceForkWritten
== m_entries
[i
].length
);
80 if (dataOk
&& resourceOk
) {
84 fpb
= (HFileInfo
*)&cipbr
;
85 fpb
->ioVRefNum
= m_fsFileSpec
.vRefNum
;
86 fpb
->ioDirID
= m_fsFileSpec
.parID
;
87 fpb
->ioNamePtr
= m_fsFileSpec
.name
;
89 PBGetCatInfoSync(&cipbr
);
92 memcpy(&fpb
->ioFlFndrInfo
, &m_finderInfo
, sizeof(FInfo
));
93 memcpy(&fpb
->ioFlXFndrInfo
, &m_finderExtraInfo
, sizeof(FXInfo
));
94 fpb
->ioFlFndrInfo
.fdFlags
&=
95 0xfc00; /* clear flags maintained by finder */
98 fpb
->ioFlCrDat
= m_dates
.create
- CONVERT_TIME
;
99 fpb
->ioFlMdDat
= m_dates
.modify
- CONVERT_TIME
;
100 fpb
->ioFlBkDat
= m_dates
.backup
- CONVERT_TIME
;
102 /* update file info */
103 fpb
->ioDirID
= fpb
->ioFlParID
;
104 PBSetCatInfoSync(&cipbr
);
108 GetVolParmsInfoBuffer vp
;
111 memset((void*)&vinfo
, 0, sizeof(vinfo
));
112 vinfo
.ioVRefNum
= fpb
->ioVRefNum
;
113 vinfo
.ioBuffer
= (Ptr
)&vp
;
114 vinfo
.ioReqCount
= sizeof(vp
);
115 if (PBHGetVolParmsSync((HParmBlkPtr
)&vinfo
) == noErr
&&
116 ((vp
.vMAttrib
>> bHasDesktopMgr
) & 1)) {
117 memset((void*)&dtp
, 0, sizeof(dtp
));
118 dtp
.ioVRefNum
= fpb
->ioVRefNum
;
119 if (PBDTGetPath(&dtp
) == noErr
) {
120 dtp
.ioDTBuffer
= (Ptr
)&m_comment
[1];
121 dtp
.ioNamePtr
= fpb
->ioNamePtr
;
122 dtp
.ioDirID
= fpb
->ioDirID
;
123 dtp
.ioDTReqCount
= m_comment
[0];
124 if (PBDTSetCommentSync(&dtp
) == noErr
) PBDTFlushSync(&dtp
);
133 NS_IMETHODIMP
nsDecodeAppleFile::Flush(void) { return m_output
->Flush(); }
135 NS_IMETHODIMP
nsDecodeAppleFile::StreamStatus(void) {
136 return m_output
->StreamStatus();
139 NS_IMETHODIMP
nsDecodeAppleFile::WriteFrom(nsIInputStream
* inStr
,
140 uint32_t count
, uint32_t* _retval
) {
141 return m_output
->WriteFrom(inStr
, count
, _retval
);
144 NS_IMETHODIMP
nsDecodeAppleFile::WriteSegments(nsReadSegmentFun reader
,
145 void* closure
, uint32_t count
,
147 return m_output
->WriteSegments(reader
, closure
, count
, _retval
);
150 NS_IMETHODIMP
nsDecodeAppleFile::IsNonBlocking(bool* aNonBlocking
) {
151 return m_output
->IsNonBlocking(aNonBlocking
);
154 NS_IMETHODIMP
nsDecodeAppleFile::Write(const char* buffer
, uint32_t bufferSize
,
155 uint32_t* writeCount
) {
156 /* WARNING: to simplify my life, I presume that I should get all appledouble
157 headers in the first block, else I would have to implement a buffer */
159 const char* buffPtr
= buffer
;
166 while (bufferSize
> 0 && NS_SUCCEEDED(rv
)) {
169 dataCount
= sizeof(ap_header
) - m_dataBufferLength
;
170 if (dataCount
> bufferSize
) dataCount
= bufferSize
;
171 memcpy(&m_dataBuffer
[m_dataBufferLength
], buffPtr
, dataCount
);
172 m_dataBufferLength
+= dataCount
;
174 if (m_dataBufferLength
== sizeof(ap_header
)) {
175 memcpy(&m_headers
, m_dataBuffer
, sizeof(ap_header
));
177 /* Check header to be sure we are dealing with the right kind of data,
178 * else just write it to the data fork. */
179 if ((m_headers
.magic
== APPLEDOUBLE_MAGIC
||
180 m_headers
.magic
== APPLESINGLE_MAGIC
) &&
181 m_headers
.version
== VERSION
&& m_headers
.entriesCount
) {
182 /* Just to be sure, the filler must contains only 0 */
183 for (i
= 0; i
< 4 && m_headers
.fill
[i
] == 0L; i
++)
185 if (i
== 4) m_state
= parseEntries
;
187 m_dataBufferLength
= 0;
189 if (m_state
== parseHeaders
) {
191 m_state
= parseWriteThrough
;
198 m_entries
= new ap_entry
[m_headers
.entriesCount
];
199 if (!m_entries
) return NS_ERROR_OUT_OF_MEMORY
;
201 uint32_t entriesSize
= sizeof(ap_entry
) * m_headers
.entriesCount
;
202 dataCount
= entriesSize
- m_dataBufferLength
;
203 if (dataCount
> bufferSize
) dataCount
= bufferSize
;
204 memcpy(&m_dataBuffer
[m_dataBufferLength
], buffPtr
, dataCount
);
205 m_dataBufferLength
+= dataCount
;
207 if (m_dataBufferLength
== entriesSize
) {
208 for (i
= 0; i
< m_headers
.entriesCount
; i
++) {
209 memcpy(&m_entries
[i
], &m_dataBuffer
[i
* sizeof(ap_entry
)],
211 if (m_headers
.magic
== APPLEDOUBLE_MAGIC
) {
212 uint32_t offset
= m_entries
[i
].offset
+ m_entries
[i
].length
;
213 if (offset
> m_dataForkOffset
) m_dataForkOffset
= offset
;
217 m_state
= parseLookupPart
;
221 case parseLookupPart
:
222 /* which part are we parsing? */
223 m_currentPartID
= -1;
224 for (i
= 0; i
< m_headers
.entriesCount
; i
++)
225 if (m_offset
== m_entries
[i
].offset
&& m_entries
[i
].length
) {
226 m_currentPartID
= m_entries
[i
].id
;
227 m_currentPartLength
= m_entries
[i
].length
;
228 m_currentPartCount
= 0;
230 switch (m_currentPartID
) {
232 m_state
= parseDataFork
;
235 m_state
= parseResourceFork
;
241 m_dataBufferLength
= 0;
246 m_state
= parseSkipPart
;
252 if (m_currentPartID
== -1) {
253 /* maybe is the datafork of an appledouble file? */
254 if (m_offset
== m_dataForkOffset
) {
255 m_currentPartID
= ENT_DFORK
;
256 m_currentPartLength
= -1;
257 m_currentPartCount
= 0;
258 m_state
= parseDataFork
;
265 dataCount
= m_currentPartLength
- m_dataBufferLength
;
266 if (dataCount
> bufferSize
) dataCount
= bufferSize
;
267 memcpy(&m_dataBuffer
[m_dataBufferLength
], buffPtr
, dataCount
);
268 m_dataBufferLength
+= dataCount
;
270 if (m_dataBufferLength
== m_currentPartLength
) {
271 switch (m_currentPartID
) {
274 m_currentPartLength
> 255 ? 255 : m_currentPartLength
;
275 memcpy(&m_comment
[1], buffPtr
, m_comment
[0]);
278 if (m_currentPartLength
== sizeof(m_dates
))
279 memcpy(&m_dates
, buffPtr
, m_currentPartLength
);
282 if (m_currentPartLength
==
283 (sizeof(m_finderInfo
) + sizeof(m_finderExtraInfo
))) {
284 memcpy(&m_finderInfo
, buffPtr
, sizeof(m_finderInfo
));
285 memcpy(&m_finderExtraInfo
, buffPtr
+ sizeof(m_finderInfo
),
286 sizeof(m_finderExtraInfo
));
290 m_state
= parseLookupPart
;
295 dataCount
= m_currentPartLength
- m_currentPartCount
;
296 if (dataCount
> bufferSize
)
297 dataCount
= bufferSize
;
299 m_state
= parseLookupPart
;
303 if (m_headers
.magic
== APPLEDOUBLE_MAGIC
)
304 dataCount
= bufferSize
;
306 dataCount
= m_currentPartLength
- m_currentPartCount
;
307 if (dataCount
> bufferSize
)
308 dataCount
= bufferSize
;
310 m_state
= parseLookupPart
;
315 rv
= m_output
->Write((const char*)buffPtr
, dataCount
, &writeCount
);
316 if (dataCount
!= writeCount
) rv
= NS_ERROR_FAILURE
;
317 m_totalDataForkWritten
+= dataCount
;
322 case parseResourceFork
:
323 dataCount
= m_currentPartLength
- m_currentPartCount
;
324 if (dataCount
> bufferSize
)
325 dataCount
= bufferSize
;
327 m_state
= parseLookupPart
;
329 if (m_rfRefNum
== -1) {
330 if (noErr
!= FSpOpenRF(&m_fsFileSpec
, fsWrPerm
, &m_rfRefNum
))
331 return NS_ERROR_FAILURE
;
334 long count
= dataCount
;
335 if (noErr
!= FSWrite(m_rfRefNum
, &count
, buffPtr
) || count
!= dataCount
)
336 return NS_ERROR_FAILURE
;
337 m_totalResourceForkWritten
+= dataCount
;
340 case parseWriteThrough
:
341 dataCount
= bufferSize
;
344 rv
= m_output
->Write((const char*)buffPtr
, dataCount
, &writeCount
);
345 if (dataCount
!= writeCount
) rv
= NS_ERROR_FAILURE
;
351 *writeCount
+= dataCount
;
352 bufferSize
-= dataCount
;
353 buffPtr
+= dataCount
;
354 m_currentPartCount
+= dataCount
;
355 m_offset
+= dataCount
;