Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/uriloader/exthandler/mac/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 11 kB image not shown  

Quelle  nsDecodeAppleFile.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "nsDecodeAppleFile.h"
#include "nsCRT.h"

NS_IMPL_ADDREF(nsDecodeAppleFile)
NS_IMPL_RELEASE(nsDecodeAppleFile)

NS_INTERFACE_MAP_BEGIN(nsDecodeAppleFile)
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIOutputStream)
  NS_INTERFACE_MAP_ENTRY(nsIOutputStream)
NS_INTERFACE_MAP_END

nsDecodeAppleFile::nsDecodeAppleFile() {
  m_state = parseHeaders;
  m_dataBufferLength = 0;
  m_dataBuffer = (unsigned char*)malloc(MAX_BUFFERSIZE);
  m_entries = nullptr;
  m_rfRefNum = -1;
  m_totalDataForkWritten = 0;
  m_totalResourceForkWritten = 0;
  m_headerOk = false;

  m_comment[0] = 0;
  memset(&m_dates, 0, sizeof(m_dates));
  memset(&m_finderInfo, 0, sizeof(m_dates));
  memset(&m_finderExtraInfo, 0, sizeof(m_dates));
}

nsDecodeAppleFile::~nsDecodeAppleFile() {
  free(m_dataBuffer);
  m_dataBuffer = nullptr;
  if (m_entries) delete[] m_entries;
}

NS_IMETHODIMP nsDecodeAppleFile::Initialize(nsIOutputStream* output,
                                            nsIFile* file) {
  m_output = output;

  nsCOMPtr<nsILocalFileMac> macFile = do_QueryInterface(file);
  macFile->GetTargetFSSpec(&m_fsFileSpec);

  m_offset = 0;
  m_dataForkOffset = 0;

  return NS_OK;
}

NS_IMETHODIMP nsDecodeAppleFile::Close(void) {
  nsresult rv;
  rv = m_output->Close();

  int32_t 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) {
    bool dataOk = 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 = (bool)(m_totalDataForkWritten == m_entries[i].length);
          break;
        }
    }

    bool resourceOk = FALSE;
    for (i = 0; i < m_headers.entriesCount; i++)
      if (ENT_RFORK == m_entries[i].id) {
        resourceOk = (bool)(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 */
      memcpy(&fpb->ioFlFndrInfo, &m_finderInfo, sizeof(FInfo));
      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;

      memset((void*)&vinfo, 0, sizeof(vinfo));
      vinfo.ioVRefNum = fpb->ioVRefNum;
      vinfo.ioBuffer = (Ptr)&vp;
      vinfo.ioReqCount = sizeof(vp);
      if (PBHGetVolParmsSync((HParmBlkPtr)&vinfo) == noErr &&
          ((vp.vMAttrib >> bHasDesktopMgr) & 1)) {
        memset((void*)&dtp, 0, 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);
        }
      }
    }
  }

  return rv;
}

NS_IMETHODIMP nsDecodeAppleFile::Flush(void) { return m_output->Flush(); }

NS_IMETHODIMP nsDecodeAppleFile::StreamStatus(void) {
  return m_output->StreamStatus();
}

NS_IMETHODIMP nsDecodeAppleFile::WriteFrom(nsIInputStream* inStr,
                                           uint32_t count, uint32_t* _retval) {
  return m_output->WriteFrom(inStr, count, _retval);
}

NS_IMETHODIMP nsDecodeAppleFile::WriteSegments(nsReadSegmentFun reader,
                                               void* closure, uint32_t count,
                                               uint32_t* _retval) {
  return m_output->WriteSegments(reader, closure, count, _retval);
}

NS_IMETHODIMP nsDecodeAppleFile::IsNonBlocking(bool* aNonBlocking) {
  return m_output->IsNonBlocking(aNonBlocking);
}

NS_IMETHODIMP nsDecodeAppleFile::Write(const char* buffer, uint32_t bufferSize,
                                       uint32_t* 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;
  uint32_t dataCount;
  int32_t 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;
        memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount);
        m_dataBufferLength += dataCount;

        if (m_dataBufferLength == sizeof(ap_header)) {
          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;
        }
        uint32_t entriesSize = sizeof(ap_entry) * m_headers.entriesCount;
        dataCount = entriesSize - m_dataBufferLength;
        if (dataCount > bufferSize) dataCount = bufferSize;
        memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount);
        m_dataBufferLength += dataCount;

        if (m_dataBufferLength == entriesSize) {
          for (i = 0; i < m_headers.entriesCount; i++) {
            memcpy(&m_entries[i], &m_dataBuffer[i * sizeof(ap_entry)],
                   sizeof(ap_entry));
            if (m_headers.magic == APPLEDOUBLE_MAGIC) {
              uint32_t offset = m_entries[i].offset + m_entries[i].length;
              if (offset > m_dataForkOffset) m_dataForkOffset = offset;
            }
          }
          m_headerOk = 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;
        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;
              memcpy(&m_comment[1], buffPtr, m_comment[0]);
              break;
            case ENT_DATES:
              if (m_currentPartLength == sizeof(m_dates))
                memcpy(&m_dates, buffPtr, m_currentPartLength);
              break;
            case ENT_FINFO:
              if (m_currentPartLength ==
                  (sizeof(m_finderInfo) + sizeof(m_finderExtraInfo))) {
                memcpy(&m_finderInfo, buffPtr, sizeof(m_finderInfo));
                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) {
          uint32_t 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) {
          uint32_t 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;
}

Messung V0.5
C=90 H=95 G=92

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.