uriloader/exthandler/mac/nsDecodeAppleFile.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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 }

mercurial