Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
7 #include "prmem.h"
8 #include "nsCRT.h"
11 NS_IMPL_ADDREF(nsDecodeAppleFile)
12 NS_IMPL_RELEASE(nsDecodeAppleFile)
14 NS_INTERFACE_MAP_BEGIN(nsDecodeAppleFile)
15 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIOutputStream)
16 NS_INTERFACE_MAP_ENTRY(nsIOutputStream)
17 NS_INTERFACE_MAP_END_THREADSAFE
19 nsDecodeAppleFile::nsDecodeAppleFile()
20 {
21 m_state = parseHeaders;
22 m_dataBufferLength = 0;
23 m_dataBuffer = (unsigned char*) PR_MALLOC(MAX_BUFFERSIZE);
24 m_entries = nullptr;
25 m_rfRefNum = -1;
26 m_totalDataForkWritten = 0;
27 m_totalResourceForkWritten = 0;
28 m_headerOk = false;
30 m_comment[0] = 0;
31 memset(&m_dates, 0, sizeof(m_dates));
32 memset(&m_finderInfo, 0, sizeof(m_dates));
33 memset(&m_finderExtraInfo, 0, sizeof(m_dates));
34 }
36 nsDecodeAppleFile::~nsDecodeAppleFile()
37 {
39 PR_FREEIF(m_dataBuffer);
40 if (m_entries)
41 delete [] m_entries;
42 }
44 NS_IMETHODIMP nsDecodeAppleFile::Initialize(nsIOutputStream *output, nsIFile *file)
45 {
46 m_output = output;
48 nsCOMPtr<nsILocalFileMac> macFile = do_QueryInterface(file);
49 macFile->GetTargetFSSpec(&m_fsFileSpec);
51 m_offset = 0;
52 m_dataForkOffset = 0;
54 return NS_OK;
55 }
57 NS_IMETHODIMP nsDecodeAppleFile::Close(void)
58 {
59 nsresult rv;
60 rv = m_output->Close();
62 int32_t i;
64 if (m_rfRefNum != -1)
65 FSClose(m_rfRefNum);
67 /* Check if the file is complete and if it's the case, write file attributes */
68 if (m_headerOk)
69 {
70 bool dataOk = true; /* It's ok if the file doesn't have a datafork, therefore set it to true by default. */
71 if (m_headers.magic == APPLESINGLE_MAGIC)
72 {
73 for (i = 0; i < m_headers.entriesCount; i ++)
74 if (ENT_DFORK == m_entries[i].id)
75 {
76 dataOk = (bool)(m_totalDataForkWritten == m_entries[i].length);
77 break;
78 }
79 }
81 bool resourceOk = FALSE;
82 for (i = 0; i < m_headers.entriesCount; i ++)
83 if (ENT_RFORK == m_entries[i].id)
84 {
85 resourceOk = (bool)(m_totalResourceForkWritten == m_entries[i].length);
86 break;
87 }
89 if (dataOk && resourceOk)
90 {
91 HFileInfo *fpb;
92 CInfoPBRec cipbr;
94 fpb = (HFileInfo *) &cipbr;
95 fpb->ioVRefNum = m_fsFileSpec.vRefNum;
96 fpb->ioDirID = m_fsFileSpec.parID;
97 fpb->ioNamePtr = m_fsFileSpec.name;
98 fpb->ioFDirIndex = 0;
99 PBGetCatInfoSync(&cipbr);
101 /* set finder info */
102 memcpy(&fpb->ioFlFndrInfo, &m_finderInfo, sizeof (FInfo));
103 memcpy(&fpb->ioFlXFndrInfo, &m_finderExtraInfo, sizeof (FXInfo));
104 fpb->ioFlFndrInfo.fdFlags &= 0xfc00; /* clear flags maintained by finder */
106 /* set file dates */
107 fpb->ioFlCrDat = m_dates.create - CONVERT_TIME;
108 fpb->ioFlMdDat = m_dates.modify - CONVERT_TIME;
109 fpb->ioFlBkDat = m_dates.backup - CONVERT_TIME;
111 /* update file info */
112 fpb->ioDirID = fpb->ioFlParID;
113 PBSetCatInfoSync(&cipbr);
115 /* set comment */
116 IOParam vinfo;
117 GetVolParmsInfoBuffer vp;
118 DTPBRec dtp;
120 memset((void *) &vinfo, 0, sizeof (vinfo));
121 vinfo.ioVRefNum = fpb->ioVRefNum;
122 vinfo.ioBuffer = (Ptr) &vp;
123 vinfo.ioReqCount = sizeof (vp);
124 if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr && ((vp.vMAttrib >> bHasDesktopMgr) & 1))
125 {
126 memset((void *) &dtp, 0, sizeof (dtp));
127 dtp.ioVRefNum = fpb->ioVRefNum;
128 if (PBDTGetPath(&dtp) == noErr)
129 {
130 dtp.ioDTBuffer = (Ptr) &m_comment[1];
131 dtp.ioNamePtr = fpb->ioNamePtr;
132 dtp.ioDirID = fpb->ioDirID;
133 dtp.ioDTReqCount = m_comment[0];
134 if (PBDTSetCommentSync(&dtp) == noErr)
135 PBDTFlushSync(&dtp);
136 }
137 }
138 }
139 }
141 return rv;
142 }
144 NS_IMETHODIMP nsDecodeAppleFile::Flush(void)
145 {
146 return m_output->Flush();
147 }
149 NS_IMETHODIMP nsDecodeAppleFile::WriteFrom(nsIInputStream *inStr, uint32_t count, uint32_t *_retval)
150 {
151 return m_output->WriteFrom(inStr, count, _retval);
152 }
154 NS_IMETHODIMP nsDecodeAppleFile::WriteSegments(nsReadSegmentFun reader, void * closure, uint32_t count, uint32_t *_retval)
155 {
156 return m_output->WriteSegments(reader, closure, count, _retval);
157 }
159 NS_IMETHODIMP nsDecodeAppleFile::IsNonBlocking(bool *aNonBlocking)
160 {
161 return m_output->IsNonBlocking(aNonBlocking);
162 }
164 NS_IMETHODIMP nsDecodeAppleFile::Write(const char *buffer, uint32_t bufferSize, uint32_t* writeCount)
165 {
166 /* WARNING: to simplify my life, I presume that I should get all appledouble headers in the first block,
167 else I would have to implement a buffer */
169 const char * buffPtr = buffer;
170 uint32_t dataCount;
171 int32_t i;
172 nsresult rv = NS_OK;
174 *writeCount = 0;
176 while (bufferSize > 0 && NS_SUCCEEDED(rv))
177 {
178 switch (m_state)
179 {
180 case parseHeaders :
181 dataCount = sizeof(ap_header) - m_dataBufferLength;
182 if (dataCount > bufferSize)
183 dataCount = bufferSize;
184 memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount);
185 m_dataBufferLength += dataCount;
187 if (m_dataBufferLength == sizeof(ap_header))
188 {
189 memcpy(&m_headers, m_dataBuffer, sizeof(ap_header));
191 /* Check header to be sure we are dealing with the right kind of data, else just write it to the data fork. */
192 if ((m_headers.magic == APPLEDOUBLE_MAGIC || m_headers.magic == APPLESINGLE_MAGIC) &&
193 m_headers.version == VERSION && m_headers.entriesCount)
194 {
195 /* Just to be sure, the filler must contains only 0 */
196 for (i = 0; i < 4 && m_headers.fill[i] == 0L; i ++)
197 ;
198 if (i == 4)
199 m_state = parseEntries;
200 }
201 m_dataBufferLength = 0;
203 if (m_state == parseHeaders)
204 {
205 dataCount = 0;
206 m_state = parseWriteThrough;
207 }
208 }
209 break;
211 case parseEntries :
212 if (!m_entries)
213 {
214 m_entries = new ap_entry[m_headers.entriesCount];
215 if (!m_entries)
216 return NS_ERROR_OUT_OF_MEMORY;
217 }
218 uint32_t entriesSize = sizeof(ap_entry) * m_headers.entriesCount;
219 dataCount = entriesSize - m_dataBufferLength;
220 if (dataCount > bufferSize)
221 dataCount = bufferSize;
222 memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount);
223 m_dataBufferLength += dataCount;
225 if (m_dataBufferLength == entriesSize)
226 {
227 for (i = 0; i < m_headers.entriesCount; i ++)
228 {
229 memcpy(&m_entries[i], &m_dataBuffer[i * sizeof(ap_entry)], sizeof(ap_entry));
230 if (m_headers.magic == APPLEDOUBLE_MAGIC)
231 {
232 uint32_t offset = m_entries[i].offset + m_entries[i].length;
233 if (offset > m_dataForkOffset)
234 m_dataForkOffset = offset;
235 }
236 }
237 m_headerOk = true;
238 m_state = parseLookupPart;
239 }
240 break;
242 case parseLookupPart :
243 /* which part are we parsing? */
244 m_currentPartID = -1;
245 for (i = 0; i < m_headers.entriesCount; i ++)
246 if (m_offset == m_entries[i].offset && m_entries[i].length)
247 {
248 m_currentPartID = m_entries[i].id;
249 m_currentPartLength = m_entries[i].length;
250 m_currentPartCount = 0;
252 switch (m_currentPartID)
253 {
254 case ENT_DFORK : m_state = parseDataFork; break;
255 case ENT_RFORK : m_state = parseResourceFork; break;
257 case ENT_COMMENT :
258 case ENT_DATES :
259 case ENT_FINFO :
260 m_dataBufferLength = 0;
261 m_state = parsePart;
262 break;
264 default : m_state = parseSkipPart; break;
265 }
266 break;
267 }
269 if (m_currentPartID == -1)
270 {
271 /* maybe is the datafork of an appledouble file? */
272 if (m_offset == m_dataForkOffset)
273 {
274 m_currentPartID = ENT_DFORK;
275 m_currentPartLength = -1;
276 m_currentPartCount = 0;
277 m_state = parseDataFork;
278 }
279 else
280 dataCount = 1;
281 }
282 break;
284 case parsePart :
285 dataCount = m_currentPartLength - m_dataBufferLength;
286 if (dataCount > bufferSize)
287 dataCount = bufferSize;
288 memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount);
289 m_dataBufferLength += dataCount;
291 if (m_dataBufferLength == m_currentPartLength)
292 {
293 switch (m_currentPartID)
294 {
295 case ENT_COMMENT :
296 m_comment[0] = m_currentPartLength > 255 ? 255 : m_currentPartLength;
297 memcpy(&m_comment[1], buffPtr, m_comment[0]);
298 break;
299 case ENT_DATES :
300 if (m_currentPartLength == sizeof(m_dates))
301 memcpy(&m_dates, buffPtr, m_currentPartLength);
302 break;
303 case ENT_FINFO :
304 if (m_currentPartLength == (sizeof(m_finderInfo) + sizeof(m_finderExtraInfo)))
305 {
306 memcpy(&m_finderInfo, buffPtr, sizeof(m_finderInfo));
307 memcpy(&m_finderExtraInfo, buffPtr + sizeof(m_finderInfo), sizeof(m_finderExtraInfo));
308 }
309 break;
310 }
311 m_state = parseLookupPart;
312 }
313 break;
315 case parseSkipPart :
316 dataCount = m_currentPartLength - m_currentPartCount;
317 if (dataCount > bufferSize)
318 dataCount = bufferSize;
319 else
320 m_state = parseLookupPart;
321 break;
323 case parseDataFork :
324 if (m_headers.magic == APPLEDOUBLE_MAGIC)
325 dataCount = bufferSize;
326 else
327 {
328 dataCount = m_currentPartLength - m_currentPartCount;
329 if (dataCount > bufferSize)
330 dataCount = bufferSize;
331 else
332 m_state = parseLookupPart;
333 }
335 if (m_output)
336 {
337 uint32_t writeCount;
338 rv = m_output->Write((const char *)buffPtr, dataCount, &writeCount);
339 if (dataCount != writeCount)
340 rv = NS_ERROR_FAILURE;
341 m_totalDataForkWritten += dataCount;
342 }
344 break;
346 case parseResourceFork :
347 dataCount = m_currentPartLength - m_currentPartCount;
348 if (dataCount > bufferSize)
349 dataCount = bufferSize;
350 else
351 m_state = parseLookupPart;
353 if (m_rfRefNum == -1)
354 {
355 if (noErr != FSpOpenRF(&m_fsFileSpec, fsWrPerm, &m_rfRefNum))
356 return NS_ERROR_FAILURE;
357 }
359 long count = dataCount;
360 if (noErr != FSWrite(m_rfRefNum, &count, buffPtr) || count != dataCount)
361 return NS_ERROR_FAILURE;
362 m_totalResourceForkWritten += dataCount;
363 break;
365 case parseWriteThrough :
366 dataCount = bufferSize;
367 if (m_output)
368 {
369 uint32_t writeCount;
370 rv = m_output->Write((const char *)buffPtr, dataCount, &writeCount);
371 if (dataCount != writeCount)
372 rv = NS_ERROR_FAILURE;
373 }
374 break;
375 }
377 if (dataCount)
378 {
379 *writeCount += dataCount;
380 bufferSize -= dataCount;
381 buffPtr += dataCount;
382 m_currentPartCount += dataCount;
383 m_offset += dataCount;
384 dataCount = 0;
385 }
386 }
388 return rv;
389 }