diff --git a/mozilla/mailnews/base/public/nsIMessenger.idl b/mozilla/mailnews/base/public/nsIMessenger.idl index 70e19e20d68..66e3fde7837 100644 --- a/mozilla/mailnews/base/public/nsIMessenger.idl +++ b/mozilla/mailnews/base/public/nsIMessenger.idl @@ -80,8 +80,10 @@ interface nsIMessenger : nsISupports { void SetDocumentCharset(in wstring characterSet); void saveAs(in string url, in boolean asFile, in nsIMsgIdentity identity, in nsIMsgWindow aMsgWindow); void openAttachment(in string contentTpe, in string url, in string displayName, in string messageUri); - void saveAttachment(in string url, in string displayName, in string messageUri); - void saveAllAttachments(in unsigned long count, [array, size_is(count)] in string urlArray, [array, size_is(count)] in string displayNameArray, [array, size_is(count)] in string messageUriArray); + void saveAttachment(in string contentTpe, in string url, in string displayName, in string messageUri); + void saveAllAttachments(in unsigned long count, [array, size_is(count)] in string contentTypeArray, + [array, size_is(count)] in string urlArray, [array, size_is(count)] in string displayNameArray, + [array, size_is(count)] in string messageUriArray); void find(); void findAgain(); diff --git a/mozilla/mailnews/base/resources/content/msgHdrViewOverlay.js b/mozilla/mailnews/base/resources/content/msgHdrViewOverlay.js index 15b569b06ed..5224bbdb46e 100644 --- a/mozilla/mailnews/base/resources/content/msgHdrViewOverlay.js +++ b/mozilla/mailnews/base/resources/content/msgHdrViewOverlay.js @@ -714,7 +714,7 @@ function createNewAttachmentInfo(contentType, url, displayName, uri, notDownload function saveAttachment(contentType, url, displayName, messageUri) { - messenger.saveAttachment(url, displayName, messageUri); + messenger.saveAttachment(contentType, url, displayName, messageUri); } function openAttachment(contentType, url, displayName, messageUri) @@ -899,6 +899,7 @@ function SaveAllAttachments() try { // convert our attachment data into some c++ friendly structs + var attachmentContentTypeArray = new Array(); var attachmentUrlArray = new Array(); var attachmentDisplayNameArray = new Array(); var attachmentMessageUriArray = new Array(); @@ -907,17 +908,20 @@ function SaveAllAttachments() for (index in currentAttachments) { var attachment = currentAttachments[index]; + attachmentContentTypeArray[index] = attachment.contentType; attachmentUrlArray[index] = attachment.url; attachmentDisplayNameArray[index] = escape(attachment.displayName); attachmentMessageUriArray[index] = attachment.uri; } // okay the list has been built...now call our save all attachments code... - messenger.saveAllAttachments(attachmentUrlArray.length, attachmentUrlArray, attachmentDisplayNameArray, attachmentMessageUriArray); + messenger.saveAllAttachments(attachmentContentTypeArray.length, + attachmentContentTypeArray, attachmentUrlArray, + attachmentDisplayNameArray, attachmentMessageUriArray); } catch (ex) { - dump ("** failed to save all attachments ** \n"); + dump ("** failed to save all attachments **\n"); } } diff --git a/mozilla/mailnews/base/src/nsMessenger.cpp b/mozilla/mailnews/base/src/nsMessenger.cpp index aa314118116..ecfc5dd8161 100644 --- a/mozilla/mailnews/base/src/nsMessenger.cpp +++ b/mozilla/mailnews/base/src/nsMessenger.cpp @@ -32,6 +32,9 @@ #include "nsEscape.h" #include "nsXPIDLString.h" #include "nsTextFormatter.h" +#ifdef XP_MAC +#include "nsIAppleFileDecoder.h" +#endif // necko #include "nsMimeTypes.h" @@ -210,12 +213,16 @@ public: nsString m_charset; nsString m_outputFormat; nsString m_msgBuffer; + + nsString m_contentType; // used only when saving attachment }; class nsSaveAllAttachmentsState { public: - nsSaveAllAttachmentsState(PRUint32 count, const char **urlArray, + nsSaveAllAttachmentsState(PRUint32 count, + const char **contentTypeArray, + const char **urlArray, const char **displayNameArray, const char **messageUriArray, const char *directoryName); @@ -224,6 +231,7 @@ public: PRUint32 m_count; PRUint32 m_curIndex; char* m_directoryName; + char** m_contentTypeArray; char** m_urlArray; char** m_displayNameArray; char** m_messageUriArray; @@ -529,6 +537,7 @@ nsresult nsMessenger::SaveAttachment(nsIFileSpec * fileSpec, const char * unescapedUrl, const char * messageUri, + const char * contentType, void *closure) { nsIMsgMessageService * messageService = nsnull; @@ -550,6 +559,7 @@ nsMessenger::SaveAttachment(nsIFileSpec * fileSpec, } NS_ADDREF(aListener); + aListener->m_contentType.AssignWithConversion(contentType); if (saveState) aListener->m_saveAllAttachmentsState = saveState; @@ -617,8 +627,8 @@ nsMessenger::OpenAttachment(const char * aContentType, const char * aUrl, const } NS_IMETHODIMP -nsMessenger::SaveAttachment(const char * url, const char * displayName, - const char * messageUri) +nsMessenger::SaveAttachment(const char * contentType, const char * url, + const char * displayName, const char * messageUri) { nsresult rv = NS_ERROR_OUT_OF_MEMORY; char *unescapedUrl = nsnull; @@ -674,7 +684,7 @@ nsMessenger::SaveAttachment(const char * url, const char * displayName, fileSpec = do_CreateInstance("@mozilla.org/filespec;1", &rv); if (NS_FAILED(rv)) goto done; fileSpec->SetNativePath(filePath); - rv = SaveAttachment(fileSpec, unescapedUrl, messageUri, nsnull); + rv = SaveAttachment(fileSpec, unescapedUrl, messageUri, contentType, nsnull); done: PR_FREEIF(unescapedUrl); @@ -683,7 +693,9 @@ done: NS_IMETHODIMP -nsMessenger::SaveAllAttachments(PRUint32 count, const char **urlArray, +nsMessenger::SaveAllAttachments(PRUint32 count, + const char **contentTypeArray, + const char **urlArray, const char **displayNameArray, const char **messageUriArray) { @@ -714,7 +726,9 @@ nsMessenger::SaveAllAttachments(PRUint32 count, const char **urlArray, rv = NS_NewFileSpec(getter_AddRefs(fileSpec)); if (NS_FAILED(rv)) goto done; - saveState = new nsSaveAllAttachmentsState(count, urlArray, + saveState = new nsSaveAllAttachmentsState(count, + contentTypeArray, + urlArray, displayNameArray, messageUriArray, (const char*) dirName); @@ -736,7 +750,7 @@ nsMessenger::SaveAllAttachments(PRUint32 count, const char **urlArray, if (NS_FAILED(rv)) return rv; fileSpec->SetFromFileSpec(aFileSpec); rv = SaveAttachment(fileSpec, unescapedUrl, messageUriArray[0], - (void *)saveState); + contentTypeArray[0], (void *)saveState); if (NS_FAILED(rv)) goto done; } done: @@ -1566,6 +1580,31 @@ nsSaveMsgListener::OnStartRequest(nsIRequest* request, nsISupports* aSupport) { m_dataBuffer = (char*) PR_CALLOC(FOUR_K+1); } + +#ifdef XP_MAC + /* On Mac, if we are saving an appledouble or applesingle attachment, we need to use an Apple File Decoder */ + char * contentType = m_contentType.ToNewCString(); + if (contentType && *contentType) + if ((nsCRT::strcasecmp(contentType, APPLICATION_APPLEFILE) == 0) || + (nsCRT::strcasecmp(contentType, MULTIPART_APPLEDOUBLE) == 0)) + { + /* ggrrrrr, I have a nsFileSpec but I need a nsILocalFile... */ + nsCOMPtr outputFile; + nsFileSpec realSpec; + m_fileSpec->GetFileSpec(&realSpec); + NS_FileSpecToIFile(&realSpec, getter_AddRefs(outputFile)); + + nsCOMPtr appleFileDecoder = do_CreateInstance(NS_IAPPLEFILEDECODER_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv) && appleFileDecoder) + { + rv = appleFileDecoder->Initialize(m_outputStream, outputFile); + if (NS_SUCCEEDED(rv)) + m_outputStream = do_QueryInterface(appleFileDecoder, &rv); + } + } + CRTFREEIF(contentType); +#endif + return rv; } @@ -1645,8 +1684,10 @@ nsSaveMsgListener::OnStopRequest(nsIRequest* request, nsISupports* aSupport, rv = m_messenger->PromptIfFileExists(aFileSpec); if (NS_FAILED(rv)) goto done; fileSpec->SetFromFileSpec(aFileSpec); - rv = m_messenger->SaveAttachment(fileSpec, unescapedUrl, + rv = m_messenger->SaveAttachment(fileSpec, + unescapedUrl, state->m_messageUriArray[i], + state->m_contentTypeArray[i], (void *)state); done: if (NS_FAILED(rv)) @@ -1761,6 +1802,7 @@ nsMessenger::GetString(const PRUnichar *aStringName) } nsSaveAllAttachmentsState::nsSaveAllAttachmentsState(PRUint32 count, + const char **contentTypeArray, const char **urlArray, const char **nameArray, const char **uriArray, @@ -1772,11 +1814,13 @@ nsSaveAllAttachmentsState::nsSaveAllAttachmentsState(PRUint32 count, m_count = count; m_curIndex = 0; + m_contentTypeArray = new char*[count]; m_urlArray = new char*[count]; m_displayNameArray = new char*[count]; m_messageUriArray = new char*[count]; for (i = 0; i < count; i++) { + m_contentTypeArray[i] = nsCRT::strdup(contentTypeArray[i]); m_urlArray[i] = nsCRT::strdup(urlArray[i]); m_displayNameArray[i] = nsCRT::strdup(nameArray[i]); m_messageUriArray[i] = nsCRT::strdup(uriArray[i]); @@ -1789,10 +1833,12 @@ nsSaveAllAttachmentsState::~nsSaveAllAttachmentsState() PRUint32 i; for (i = 0; i < m_count; i++) { + nsCRT::free(m_contentTypeArray[i]); nsCRT::free(m_urlArray[i]); nsCRT::free(m_displayNameArray[i]); nsCRT::free(m_messageUriArray[i]); } + delete m_contentTypeArray; delete m_urlArray; delete m_displayNameArray; delete m_messageUriArray; diff --git a/mozilla/mailnews/base/src/nsMessenger.h b/mozilla/mailnews/base/src/nsMessenger.h index 7ea00a261b0..30e91ed678d 100644 --- a/mozilla/mailnews/base/src/nsMessenger.h +++ b/mozilla/mailnews/base/src/nsMessenger.h @@ -46,7 +46,8 @@ public: nsresult Alert(const char * stringName); nsresult SaveAttachment(nsIFileSpec *fileSpec, const char* unescapedUrl, - const char* messageUri, void *closure); + const char* messageUri, const char* contentType, + void *closure); nsresult PromptIfFileExists(nsFileSpec &fileSpec); protected: diff --git a/mozilla/netwerk/build/nsNetModule.cpp b/mozilla/netwerk/build/nsNetModule.cpp index 3d3adb811de..ea033e1d2c7 100644 --- a/mozilla/netwerk/build/nsNetModule.cpp +++ b/mozilla/netwerk/build/nsNetModule.cpp @@ -53,6 +53,10 @@ /////////////////////////////////////////////////////////////////////////////// #include "nsStreamConverterService.h" +#if defined(XP_MAC) +#include "nsAppleFileDecoder.h" +NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppleFileDecoder) +#endif /////////////////////////////////////////////////////////////////////////////// @@ -732,6 +736,14 @@ static nsModuleComponentInfo gNetModuleInfo[] = { RegisterStreamConverters, // registers *all* converters UnregisterStreamConverters // unregisters *all* converters }, + +#if defined(XP_MAC) + { NS_APPLEFILEDECODER_CLASSNAME, + NS_APPLEFILEDECODER_CID, + NS_IAPPLEFILEDECODER_CONTRACTID, + nsAppleFileDecoderConstructor + }, +#endif // from netwerk/streamconv/converters: { "FTPDirListingConverter", diff --git a/mozilla/netwerk/macbuild/netwerk.mcp b/mozilla/netwerk/macbuild/netwerk.mcp index c68217dc01b..e856fbd82fb 100644 Binary files a/mozilla/netwerk/macbuild/netwerk.mcp and b/mozilla/netwerk/macbuild/netwerk.mcp differ diff --git a/mozilla/netwerk/macbuild/netwerkIDL.mcp b/mozilla/netwerk/macbuild/netwerkIDL.mcp index 9eed9a544fc..c54faf09aff 100644 Binary files a/mozilla/netwerk/macbuild/netwerkIDL.mcp and b/mozilla/netwerk/macbuild/netwerkIDL.mcp differ diff --git a/mozilla/netwerk/streamconv/public/nsIAppleFileDecoder.idl b/mozilla/netwerk/streamconv/public/nsIAppleFileDecoder.idl new file mode 100644 index 00000000000..2a07db62659 --- /dev/null +++ b/mozilla/netwerk/streamconv/public/nsIAppleFileDecoder.idl @@ -0,0 +1,52 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): Jean-Francois Ducarroz + */ + +#include "nsIOutputStream.idl" +#include "nsIFile.idl" + + +%{C++ +#define NS_APPLEFILEDECODER_CLASSNAME "Apple Single/Double File decoder" + +#define NS_APPLEFILEDECODER_CID \ +{ /* 3a2bb281-64b8-11d5-9daa-bb433143c53c */ \ + 0x3a2bb281, \ + 0x64b8, \ + 0x11d5, \ + {0x9d, 0xaa, 0xbb, 0x43, 0x31, 0x43, 0xc5, 0x3c} \ +} + +#define NS_IAPPLEFILEDECODER_CONTRACTID "@mozilla.org/applefiledecoder;1" +%} + + +[scriptable, uuid(3a2bb280-64b8-11d5-9daa-bb433143c53c)] +interface nsIAppleFileDecoder : nsIOutputStream { + + /** + * Initialize the Apple File Decoder Output stream. + * + * @param outputStream The output stream which the AppleFile Decoder will write to the data fork. + * @param outputFile The output file which the AppleFile Decoder will write to the resource fork. + */ + void Initialize(in nsIOutputStream outputStream, in nsIFile outputFile); +}; diff --git a/mozilla/netwerk/streamconv/src/nsAppleFileDecoder.cpp b/mozilla/netwerk/streamconv/src/nsAppleFileDecoder.cpp new file mode 100644 index 00000000000..c14d6ef6ab5 --- /dev/null +++ b/mozilla/netwerk/streamconv/src/nsAppleFileDecoder.cpp @@ -0,0 +1,423 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Jean-Francois Ducarroz + */ + +#include "nsAppleFileDecoder.h" +#include "prmem.h" +#include "nsCRT.h" + + +NS_IMPL_THREADSAFE_ISUPPORTS2(nsAppleFileDecoder, nsIAppleFileDecoder, nsIOutputStream); + +nsAppleFileDecoder::nsAppleFileDecoder() +{ + NS_INIT_ISUPPORTS(); + + m_state = parseHeaders; + m_dataBufferLength = 0; + m_dataBuffer = (unsigned char*) PR_MALLOC(MAX_BUFFERSIZE); + m_entries = nsnull; + m_rfRefNum = -1; + m_totalDataForkWritten = 0; + m_totalResourceForkWritten = 0; + m_headerOk = PR_FALSE; + + m_comment[0] = 0; + nsCRT::zero(&m_dates, sizeof(m_dates)); + nsCRT::zero(&m_finderInfo, sizeof(m_dates)); + nsCRT::zero(&m_finderExtraInfo, sizeof(m_dates)); +} + +nsAppleFileDecoder::~nsAppleFileDecoder() +{ + if (m_output) + Close(); + + PR_FREEIF(m_dataBuffer); + if (m_entries) + delete [] m_entries; +} + +NS_IMETHODIMP nsAppleFileDecoder::Initialize(nsIOutputStream *outputStream, nsIFile *outputFile) +{ + m_output = outputStream; + + nsCOMPtr macFile = do_QueryInterface(outputFile); + macFile->GetTargetFSSpec(&m_fsFileSpec); + + m_offset = 0; + m_dataForkOffset = 0; + + return NS_OK; +} + +NS_IMETHODIMP nsAppleFileDecoder::Close(void) +{ + nsresult rv; + rv = m_output->Close(); + + PRInt32 i; + + if (m_rfRefNum != -1) + FSClose(m_rfRefNum); + + /* Check if the file is complete and if it's the case, write file attributes */ + if (m_headerOk) + { + PRBool dataOk = PR_TRUE; /* It's ok if the file doesn't have a datafork, therefore set it to true by default. */ + if (m_headers.magic == APPLESINGLE_MAGIC) + { + for (i = 0; i < m_headers.entriesCount; i ++) + if (ENT_DFORK == m_entries[i].id) + { + dataOk = (PRBool)(m_totalDataForkWritten == m_entries[i].length); + break; + } + } + + PRBool resourceOk = FALSE; + for (i = 0; i < m_headers.entriesCount; i ++) + if (ENT_RFORK == m_entries[i].id) + { + resourceOk = (PRBool)(m_totalResourceForkWritten == m_entries[i].length); + break; + } + + if (dataOk && resourceOk) + { + HFileInfo *fpb; + CInfoPBRec cipbr; + + fpb = (HFileInfo *) &cipbr; + fpb->ioVRefNum = m_fsFileSpec.vRefNum; + fpb->ioDirID = m_fsFileSpec.parID; + fpb->ioNamePtr = m_fsFileSpec.name; + fpb->ioFDirIndex = 0; + PBGetCatInfoSync(&cipbr); + + /* set finder info */ + nsCRT::memcpy(&fpb->ioFlFndrInfo, &m_finderInfo, sizeof (FInfo)); + nsCRT::memcpy(&fpb->ioFlXFndrInfo, &m_finderExtraInfo, sizeof (FXInfo)); + fpb->ioFlFndrInfo.fdFlags &= 0xfc00; /* clear flags maintained by finder */ + + /* set file dates */ + fpb->ioFlCrDat = m_dates.create - CONVERT_TIME; + fpb->ioFlMdDat = m_dates.modify - CONVERT_TIME; + fpb->ioFlBkDat = m_dates.backup - CONVERT_TIME; + + /* update file info */ + fpb->ioDirID = fpb->ioFlParID; + PBSetCatInfoSync(&cipbr); + + /* set comment */ + IOParam vinfo; + GetVolParmsInfoBuffer vp; + DTPBRec dtp; + + nsCRT::zero((void *) &vinfo, sizeof (vinfo)); + vinfo.ioVRefNum = fpb->ioVRefNum; + vinfo.ioBuffer = (Ptr) &vp; + vinfo.ioReqCount = sizeof (vp); + if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr && ((vp.vMAttrib >> bHasDesktopMgr) & 1)) + { + nsCRT::zero((void *) &dtp, sizeof (dtp)); + dtp.ioVRefNum = fpb->ioVRefNum; + if (PBDTGetPath(&dtp) == noErr) + { + dtp.ioDTBuffer = (Ptr) &m_comment[1]; + dtp.ioNamePtr = fpb->ioNamePtr; + dtp.ioDirID = fpb->ioDirID; + dtp.ioDTReqCount = m_comment[0]; + if (PBDTSetCommentSync(&dtp) == noErr) + PBDTFlushSync(&dtp); + } + } + } + } + + /* setting m_headerOk to false will prevent us to reprocess the header in case the Close function is called several time*/ + m_headerOk = PR_FALSE; + + return rv; +} + +NS_IMETHODIMP nsAppleFileDecoder::Flush(void) +{ + return m_output->Flush(); +} + +NS_IMETHODIMP nsAppleFileDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval) +{ + return m_output->WriteFrom(inStr, count, _retval); +} + +NS_IMETHODIMP nsAppleFileDecoder::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval) +{ + return m_output->WriteSegments(reader, closure, count, _retval); +} + +NS_IMETHODIMP nsAppleFileDecoder::GetNonBlocking(PRBool *aNonBlocking) +{ + return m_output->GetNonBlocking(aNonBlocking); +} + +NS_IMETHODIMP nsAppleFileDecoder::SetNonBlocking(PRBool aNonBlocking) +{ + return m_output->SetNonBlocking(aNonBlocking); +} + +NS_IMETHODIMP nsAppleFileDecoder::GetObserver(nsIOutputStreamObserver * *aObserver) +{ + return m_output->GetObserver(aObserver); +} + +NS_IMETHODIMP nsAppleFileDecoder::SetObserver(nsIOutputStreamObserver * aObserver) +{ + return m_output->SetObserver(aObserver); +} + +NS_IMETHODIMP nsAppleFileDecoder::Write(const char *buffer, PRUint32 bufferSize, PRUint32* writeCount) +{ + /* WARNING: to simplify my life, I presume that I should get all appledouble headers in the first block, + else I would have to implement a buffer */ + + const char * buffPtr = buffer; + PRUint32 dataCount; + PRInt32 i; + nsresult rv = NS_OK; + + *writeCount = 0; + + while (bufferSize > 0 && NS_SUCCEEDED(rv)) + { + switch (m_state) + { + case parseHeaders : + dataCount = sizeof(ap_header) - m_dataBufferLength; + if (dataCount > bufferSize) + dataCount = bufferSize; + nsCRT::memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount); + m_dataBufferLength += dataCount; + + if (m_dataBufferLength == sizeof(ap_header)) + { + nsCRT::memcpy(&m_headers, m_dataBuffer, sizeof(ap_header)); + + /* Check header to be sure we are dealing with the right kind of data, else just write it to the data fork. */ + if ((m_headers.magic == APPLEDOUBLE_MAGIC || m_headers.magic == APPLESINGLE_MAGIC) && + m_headers.version == VERSION && m_headers.entriesCount) + { + /* Just to be sure, the filler must contains only 0 */ + for (i = 0; i < 4 && m_headers.fill[i] == 0L; i ++) + ; + if (i == 4) + m_state = parseEntries; + } + m_dataBufferLength = 0; + + if (m_state == parseHeaders) + { + dataCount = 0; + m_state = parseWriteThrough; + } + } + break; + + case parseEntries : + if (!m_entries) + { + m_entries = new ap_entry[m_headers.entriesCount]; + if (!m_entries) + return NS_ERROR_OUT_OF_MEMORY; + } + PRUint32 entriesSize = sizeof(ap_entry) * m_headers.entriesCount; + dataCount = entriesSize - m_dataBufferLength; + if (dataCount > bufferSize) + dataCount = bufferSize; + nsCRT::memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount); + m_dataBufferLength += dataCount; + + if (m_dataBufferLength == entriesSize) + { + for (i = 0; i < m_headers.entriesCount; i ++) + { + nsCRT::memcpy(&m_entries[i], &m_dataBuffer[i * sizeof(ap_entry)], sizeof(ap_entry)); + if (m_headers.magic == APPLEDOUBLE_MAGIC) + { + PRUint32 offset = m_entries[i].offset + m_entries[i].length; + if (offset > m_dataForkOffset) + m_dataForkOffset = offset; + } + } + m_headerOk = PR_TRUE; + m_state = parseLookupPart; + } + break; + + case parseLookupPart : + /* which part are we parsing? */ + m_currentPartID = -1; + for (i = 0; i < m_headers.entriesCount; i ++) + if (m_offset == m_entries[i].offset && m_entries[i].length) + { + m_currentPartID = m_entries[i].id; + m_currentPartLength = m_entries[i].length; + m_currentPartCount = 0; + + switch (m_currentPartID) + { + case ENT_DFORK : m_state = parseDataFork; break; + case ENT_RFORK : m_state = parseResourceFork; break; + + case ENT_COMMENT : + case ENT_DATES : + case ENT_FINFO : + m_dataBufferLength = 0; + m_state = parsePart; + break; + + default : m_state = parseSkipPart; break; + } + break; + } + + if (m_currentPartID == -1) + { + /* maybe is the datafork of an appledouble file? */ + if (m_offset == m_dataForkOffset) + { + m_currentPartID = ENT_DFORK; + m_currentPartLength = -1; + m_currentPartCount = 0; + m_state = parseDataFork; + } + else + dataCount = 1; + } + break; + + case parsePart : + dataCount = m_currentPartLength - m_dataBufferLength; + if (dataCount > bufferSize) + dataCount = bufferSize; + nsCRT::memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount); + m_dataBufferLength += dataCount; + + if (m_dataBufferLength == m_currentPartLength) + { + switch (m_currentPartID) + { + case ENT_COMMENT : + m_comment[0] = m_currentPartLength > 255 ? 255 : m_currentPartLength; + nsCRT::memcpy(&m_comment[1], buffPtr, m_comment[0]); + break; + case ENT_DATES : + if (m_currentPartLength == sizeof(m_dates)) + nsCRT::memcpy(&m_dates, buffPtr, m_currentPartLength); + break; + case ENT_FINFO : + if (m_currentPartLength == (sizeof(m_finderInfo) + sizeof(m_finderExtraInfo))) + { + nsCRT::memcpy(&m_finderInfo, buffPtr, sizeof(m_finderInfo)); + nsCRT::memcpy(&m_finderExtraInfo, buffPtr + sizeof(m_finderInfo), sizeof(m_finderExtraInfo)); + } + break; + } + m_state = parseLookupPart; + } + break; + + case parseSkipPart : + dataCount = m_currentPartLength - m_currentPartCount; + if (dataCount > bufferSize) + dataCount = bufferSize; + else + m_state = parseLookupPart; + break; + + case parseDataFork : + if (m_headers.magic == APPLEDOUBLE_MAGIC) + dataCount = bufferSize; + else + { + dataCount = m_currentPartLength - m_currentPartCount; + if (dataCount > bufferSize) + dataCount = bufferSize; + else + m_state = parseLookupPart; + } + + if (m_output) + { + PRUint32 writeCount; + rv = m_output->Write((const char *)buffPtr, dataCount, &writeCount); + if (dataCount != writeCount) + rv = NS_ERROR_FAILURE; + m_totalDataForkWritten += dataCount; + } + + break; + + case parseResourceFork : + dataCount = m_currentPartLength - m_currentPartCount; + if (dataCount > bufferSize) + dataCount = bufferSize; + else + m_state = parseLookupPart; + + if (m_rfRefNum == -1) + { + if (noErr != FSpOpenRF(&m_fsFileSpec, fsWrPerm, &m_rfRefNum)) + return NS_ERROR_FAILURE; + } + + long count = dataCount; + if (noErr != FSWrite(m_rfRefNum, &count, buffPtr) || count != dataCount) + return NS_ERROR_FAILURE; + m_totalResourceForkWritten += dataCount; + break; + + case parseWriteThrough : + dataCount = bufferSize; + if (m_output) + { + PRUint32 writeCount; + rv = m_output->Write((const char *)buffPtr, dataCount, &writeCount); + if (dataCount != writeCount) + rv = NS_ERROR_FAILURE; + } + break; + } + + if (dataCount) + { + *writeCount += dataCount; + bufferSize -= dataCount; + buffPtr += dataCount; + m_currentPartCount += dataCount; + m_offset += dataCount; + dataCount = 0; + } + } + + return rv; +} diff --git a/mozilla/netwerk/streamconv/src/nsAppleFileDecoder.h b/mozilla/netwerk/streamconv/src/nsAppleFileDecoder.h new file mode 100644 index 00000000000..c79e6d8269a --- /dev/null +++ b/mozilla/netwerk/streamconv/src/nsAppleFileDecoder.h @@ -0,0 +1,132 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Jean-Francois Ducarroz + */ + +#ifndef nsAppleFileDecoder_h__ +#define nsAppleFileDecoder_h__ + +#include "nsIAppleFIleDecoder.h" +#include "nsILocalFileMac.h" + +/* +** applefile definitions used +*/ +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#endif + +#define APPLESINGLE_MAGIC 0x00051600L +#define APPLEDOUBLE_MAGIC 0x00051607L +#define VERSION 0x00020000 + +#define NUM_ENTRIES 6 + +#define ENT_DFORK 1L +#define ENT_RFORK 2L +#define ENT_NAME 3L +#define ENT_COMMENT 4L +#define ENT_DATES 8L +#define ENT_FINFO 9L + +#define CONVERT_TIME 1265437696L + +/* +** data type used in the header decoder. +*/ +typedef struct ap_header +{ + PRInt32 magic; + PRInt32 version; + PRInt32 fill[4]; + PRInt16 entriesCount; + +} ap_header; + +typedef struct ap_entry +{ + PRInt32 id; + PRInt32 offset; + PRInt32 length; + +} ap_entry; + +typedef struct ap_dates +{ + PRInt32 create, modify, backup, access; + +} ap_dates; + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#endif + +/* +**Error codes +*/ +enum { + errADNotEnoughData = -12099, + errADNotSupported, + errADBadVersion +}; + + +class nsAppleFileDecoder : public nsIAppleFileDecoder +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOUTPUTSTREAM + NS_DECL_NSIAPPLEFILEDECODER + + nsAppleFileDecoder(); + virtual ~nsAppleFileDecoder(); + +private: + #define MAX_BUFFERSIZE 1024 + enum ParserState {parseHeaders, parseEntries, parseLookupPart, parsePart, parseSkipPart, + parseDataFork, parseResourceFork, parseWriteThrough}; + + nsCOMPtr m_output; + FSSpec m_fsFileSpec; + SInt16 m_rfRefNum; + + unsigned char * m_dataBuffer; + PRInt32 m_dataBufferLength; + ParserState m_state; + ap_header m_headers; + ap_entry * m_entries; + PRInt32 m_offset; + PRInt32 m_dataForkOffset; + PRInt32 m_totalDataForkWritten; + PRInt32 m_totalResourceForkWritten; + PRBool m_headerOk; + + PRInt32 m_currentPartID; + PRInt32 m_currentPartLength; + PRInt32 m_currentPartCount; + + Str255 m_comment; + ap_dates m_dates; + FInfo m_finderInfo; + FXInfo m_finderExtraInfo; +}; + +#endif diff --git a/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp b/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp index 5efb311b3d9..b89eca87cae 100644 --- a/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/mozilla/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -64,7 +64,7 @@ #ifdef XP_MAC #include "nsILocalFileMac.h" #include "nsIInternetConfigService.h" -#include "nsDecodeAppleFile.h" +#include "nsIAppleFileDecoder.h" #endif // XP_MAC const char *FORCE_ALWAYS_ASK_PREF = "browser.helperApps.alwaysAsk.force"; @@ -797,12 +797,12 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel * aChannel) (nsCRT::strcasecmp(contentType, APPLICATION_APPLEFILE) == 0) || (nsCRT::strcasecmp(contentType, MULTIPART_APPLEDOUBLE) == 0)) { - nsCOMPtr appleFileDecoder; - NS_NEWXPCOM(appleFileDecoder, nsDecodeAppleFile); - if (appleFileDecoder) + nsCOMPtr appleFileDecoder = do_CreateInstance(NS_IAPPLEFILEDECODER_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv) && appleFileDecoder) { - NS_STATIC_CAST(nsDecodeAppleFile*, NS_STATIC_CAST(nsIOutputStream*, appleFileDecoder))->Initialize(mOutStream, mTempFile); - mOutStream = appleFileDecoder; + rv = appleFileDecoder->Initialize(mOutStream, mTempFile); + if (NS_SUCCEEDED(rv)) + mOutStream = do_QueryInterface(appleFileDecoder, &rv); } } #endif diff --git a/mozilla/uriloader/macbuild/uriLoader.mcp b/mozilla/uriloader/macbuild/uriLoader.mcp index bf1d99cc6bd..e1a7f0dc285 100644 Binary files a/mozilla/uriloader/macbuild/uriLoader.mcp and b/mozilla/uriloader/macbuild/uriLoader.mcp differ