Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Protected Member Functions | Protected Attributes
nsBinHexDecoder Class Reference

#include <nsBinHexDecoder.h>

Inheritance diagram for nsBinHexDecoder:
Inheritance graph
[legend]
Collaboration diagram for nsBinHexDecoder:
Collaboration graph
[legend]

List of all members.

Public Member Functions

NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMCONVERTER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER 
nsBinHexDecoder ()
nsIInputStream convert (in nsIInputStream aFromStream, in string aFromType, in string aToType, in nsISupports aCtxt)
 SYNCRONOUS VERSION Converts a stream of one type, to a stream of another type.
void asyncConvertData (in string aFromType, in string aToType, in nsIStreamListener aListener, in nsISupports aCtxt)
 ASYNCRONOUS VERSION Converts data arriving via the converter's nsIStreamListener::OnDataAvailable() method from one type to another, pushing the converted data out to the caller via aListener::OnDataAvailable().
void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext, in nsIInputStream aInputStream, in unsigned long aOffset, in unsigned long aCount)
 Called when the next chunk of data (corresponding to the request) may be read without blocking the calling thread.
void onStartRequest (in nsIRequest aRequest, in nsISupports aContext)
 Called to signify the beginning of an asynchronous request.
void onStopRequest (in nsIRequest aRequest, in nsISupports aContext, in nsresult aStatusCode)
 Called to signify the end of an asynchronous request.

Protected Member Functions

virtual ~nsBinHexDecoder ()
PRInt16 GetNextChar (PRUint32 numBytesInBuffer)
nsresult ProcessNextChunk (nsIRequest *aRequest, nsISupports *aContext, PRUint32 numBytesInBuffer)
nsresult ProcessNextState (nsIRequest *aRequest, nsISupports *aContext)
nsresult SetContentType (nsIRequest *aRequest, const char *fileName)

Protected Attributes

nsCOMPtr< nsIStreamListenermNextListener
nsCOMPtr< nsIOutputStreammOutputStream
nsCOMPtr< nsIInputStreammInputStream
PRInt16 mState
PRUint16 mCRC
PRUint16 mFileCRC
longbuf mOctetBuf
PRInt16 mOctetin
PRInt16 mDonePos
PRInt16 mInCRC
binhex_header mHeader
char mName [64]
char * mDataBuffer
char * mOutgoingBuffer
PRUint32 mPosInDataBuffer
unsigned char mRlebuf
PRInt32 mCount
PRInt16 mMarker
PRInt32 mPosInbuff
PRInt32 mPosOutputBuff

Detailed Description

Definition at line 94 of file nsBinHexDecoder.h.


Constructor & Destructor Documentation

Definition at line 64 of file nsBinHexDecoder.cpp.

nsBinHexDecoder::~nsBinHexDecoder ( ) [protected, virtual]

Definition at line 80 of file nsBinHexDecoder.cpp.

{
  if (mDataBuffer)
    nsMemory::Free(mDataBuffer);
  if (mOutgoingBuffer)
    nsMemory::Free(mOutgoingBuffer);
}

Member Function Documentation

void nsIStreamConverter::asyncConvertData ( in string  aFromType,
in string  aToType,
in nsIStreamListener  aListener,
in nsISupports  aCtxt 
) [inherited]

ASYNCRONOUS VERSION Converts data arriving via the converter's nsIStreamListener::OnDataAvailable() method from one type to another, pushing the converted data out to the caller via aListener::OnDataAvailable().

Use this method when you want to proxy (and convert) nsIStreamListener callbacks asynchronously.

Parameters:
aFromTypeThe MIME type of the original/raw data.
aToTypeThe MIME type of the converted data.
aListenerThe listener who receives the converted data.
aCtxtEither an opaque context, or a converter specific context (implementation specific).
nsIInputStream nsIStreamConverter::convert ( in nsIInputStream  aFromStream,
in string  aFromType,
in string  aToType,
in nsISupports  aCtxt 
) [inherited]

SYNCRONOUS VERSION Converts a stream of one type, to a stream of another type.

Use this method when you have a stream you want to convert.

Parameters:
aFromStreamThe stream representing the original/raw data.
aFromTypeThe MIME type of aFromStream.
aToTypeThe MIME type of the returned stream.
aCtxtEither an opaque context, or a converter specific context (implementation specific).
Returns:
The converted stream. NOTE: The returned stream may not already be converted. An efficient stream converter implementation will converter data on demand rather than buffering the converted data until it is used.
PRInt16 nsBinHexDecoder::GetNextChar ( PRUint32  numBytesInBuffer) [protected]

Definition at line 454 of file nsBinHexDecoder.cpp.

{
       char c = 0;
       
       while (mPosInDataBuffer < numBytesInBuffer)
       {
              c = mDataBuffer[mPosInDataBuffer++];
              if (c != LF && c != CR)
                     break;
       }
       return (c == LF || c == CR) ? 0 : (int) c;
}

Here is the caller graph for this function:

void nsIStreamListener::onDataAvailable ( in nsIRequest  aRequest,
in nsISupports  aContext,
in nsIInputStream  aInputStream,
in unsigned long  aOffset,
in unsigned long  aCount 
) [inherited]

Called when the next chunk of data (corresponding to the request) may be read without blocking the calling thread.

The onDataAvailable impl must read exactly |aCount| bytes of data before returning.

Parameters:
aRequestrequest corresponding to the source of the data
aContextuser defined context
aInputStreaminput stream containing the data chunk
aOffsetNumber of bytes that were sent in previous onDataAvailable calls for this request. In other words, the sum of all previous count parameters. If that number is greater than or equal to 2^32, this parameter will be PR_UINT32_MAX (2^32 - 1).
aCountnumber of bytes available in the stream

NOTE: The aInputStream parameter must implement readSegments.

An exception thrown from onDataAvailable has the side-effect of causing the request to be canceled.

void nsIRequestObserver::onStartRequest ( in nsIRequest  aRequest,
in nsISupports  aContext 
) [inherited]

Called to signify the beginning of an asynchronous request.

Parameters:
aRequestrequest being observed
aContextuser defined context

An exception thrown from onStartRequest has the side-effect of causing the request to be canceled.

Here is the caller graph for this function:

void nsIRequestObserver::onStopRequest ( in nsIRequest  aRequest,
in nsISupports  aContext,
in nsresult  aStatusCode 
) [inherited]

Called to signify the end of an asynchronous request.

This call is always preceded by a call to onStartRequest.

Parameters:
aRequestrequest being observed
aContextuser defined context
aStatusCodereason for stopping (NS_OK if completed successfully)

An exception thrown from onStopRequest is generally ignored.

Here is the caller graph for this function:

nsresult nsBinHexDecoder::ProcessNextChunk ( nsIRequest aRequest,
nsISupports *  aContext,
PRUint32  numBytesInBuffer 
) [protected]

Definition at line 338 of file nsBinHexDecoder.cpp.

{
       PRBool foundStart;
       PRInt16 octetpos, c = 0;
       PRUint32             val;
  mPosInDataBuffer  = 0; // use member variable.

  NS_ENSURE_TRUE(numBytesInBuffer > 0, NS_ERROR_FAILURE);
       
       //     if it is the first time, seek to the right start place. 
       if (mState == BINHEX_STATE_START)
       {
               foundStart = PR_FALSE;
              // go through the line, until we get a ':'
              while (mPosInDataBuffer < numBytesInBuffer)
              {
                     c = mDataBuffer[mPosInDataBuffer++];
                     while (c == CR || c == LF)
                     {
                            if (mPosInDataBuffer >= numBytesInBuffer)
                                   break;
                                                                                                                
                            c = mDataBuffer[mPosInDataBuffer++];
                            if (c == ':')
                            {
                                   foundStart = PR_TRUE;
                                   break;
                            }
                     }
                     if (foundStart)      break;        /* we got the start point. */
              }
              
              if (mPosInDataBuffer >= numBytesInBuffer)
                     return NS_OK;               /* we meet buff end before we get the start point, wait till next fills. */
              
              if (c != ':')
                     return NS_ERROR_FAILURE;           /* can't find the start character. */
       }
       
       while (mState != BINHEX_STATE_DONE) 
       {
              /* fill in octetbuf */
              do 
              {
                     if (mPosInDataBuffer >= numBytesInBuffer)
                            return NS_OK;               /* end of buff, go on for the nxet calls. */
                                   
                     c = GetNextChar(numBytesInBuffer);
                     if (c == 0)   return NS_OK;
                             
                     if ((val = BHEXVAL(c)) == PRUint32(-1))
                     {
                            /* we incount an invalid character.       */
                            if (c) 
                            {
                                   /* rolling back. */
                                   mDonePos --;
                                   if (mOctetin >= 14)         mDonePos--;
                                   if (mOctetin >= 20)  mDonePos--;
                            }
                            break;
                     }
                     mOctetBuf.val |= val << mOctetin;
              } 
              while ((mOctetin -= 6) > 2);
                     
              /* handle decoded characters -- run length encoding (rle) detection */

              // We put decoded chars into mOctetBuf.val in order from high to low (via
              // bitshifting, above).  But we want to byte-address them, so we want the
              // first byte to correspond to the high byte.  In other words, we want
              // these bytes to be in network order.
              mOctetBuf.val = PR_htonl(mOctetBuf.val);

              for (octetpos = 0; octetpos < mDonePos; ++octetpos) 
              {
                     c = mOctetBuf.c[octetpos];
                     
                     if (c == 0x90 && !mMarker++) 
                            continue;
                                          
                     if (mMarker) 
                     {
                            if (c == 0) 
                            {
                                   mRlebuf = 0x90;
                                   ProcessNextState(aRequest, aContext);
                            } 
                            else 
                            {
                                   while (--c > 0)                           /* we are in the run lenght mode */ 
                                          ProcessNextState(aRequest, aContext);
                            }
                            mMarker = 0;
                     } 
                     else 
                     {
                            mRlebuf = (unsigned char) c;
                            ProcessNextState(aRequest, aContext);
                     }             
                     
                     if (mState >= BINHEX_STATE_DONE) 
                            break;
              }
              
              /* prepare for next 3 characters.  */
              if (mDonePos < 3 && mState < BINHEX_STATE_DONE) 
                     mState = BINHEX_STATE_DONE;
                                   
              mOctetin = 26;
              mOctetBuf.val        = 0;
       }

  return      NS_OK;
}

Here is the call graph for this function:

nsresult nsBinHexDecoder::ProcessNextState ( nsIRequest aRequest,
nsISupports *  aContext 
) [protected]

Definition at line 184 of file nsBinHexDecoder.cpp.

{
       nsresult status = NS_OK;
       PRUint16      tmpcrc, cval;
       unsigned char  ctmp, c = mRlebuf;
       
       /* do CRC */
       ctmp = mInCRC ? c : 0;
       cval = mCRC & 0xf000;
       tmpcrc = ((PRUint16) (mCRC << 4) | (ctmp >> 4)) ^ (cval | (cval >> 7) | (cval >> 12));
       cval = tmpcrc & 0xf000;
       mCRC = ((PRUint16) (tmpcrc << 4) | (ctmp & 0x0f)) ^ (cval | (cval >> 7) | (cval >> 12));

       /* handle state */
       switch (mState) 
       {
              case BINHEX_STATE_START:
                     mState = BINHEX_STATE_FNAME;
                     mCount = 1;

      // c & 63 returns the length of mName. So if we need the length, that's how
      // you can figure it out...for now we are storing it in the first byte of mName
                     *(mName) = (c & 63);     
                     break;
                     
              case BINHEX_STATE_FNAME:
                     mName[mCount] = c;
                     
                     if (mCount++ > *(mName)) // the first byte of mName is the length...
                     {                    
        // okay we've figured out the file name....set the content type on the channel
        // based on the file name AND issue our delayed on start request....
        // be sure to skip the first byte of mName which is the size of the file name
        
        SetContentType(aRequest, &mName[1]);
        // now propagate the on start request
        mNextListener->OnStartRequest(aRequest, aContext);

                            mState = BINHEX_STATE_HEADER;
                            mCount = 0;
                     }
                     break;
                     
              case BINHEX_STATE_HEADER:
                     ((char *) &mHeader)[mCount] = c;
                     if (++mCount == 18) 
                     {
                            if (sizeof(binhex_header) != 18)   /* fix an alignment problem in some OSes */
                            {
                                   char *p = (char *)&mHeader;
                                   p += 19;
                                   for (c = 0; c < 8; c++)
          {
                                          *p = *(p-2);  p--;
          }
                            }

        mState = BINHEX_STATE_HCRC;
                            mInCRC = 1;
                            mCount = 0;
                     }
                     break;
                     
              case BINHEX_STATE_DFORK:
              case BINHEX_STATE_RFORK:
                     mOutgoingBuffer[mPosOutputBuff++] = c;
                     if (-- mCount == 0) 
                     {
                     /* only output data fork in the non-mac system.                */
                            if (mState == BINHEX_STATE_DFORK)
                            {
          PRUint32 numBytesWritten = 0; 
          mOutputStream->Write(mOutgoingBuffer, mPosOutputBuff, &numBytesWritten);
          if (PRInt32(numBytesWritten) != mPosOutputBuff)
            status = NS_ERROR_FAILURE;

          // now propagate the data we just wrote
          mNextListener->OnDataAvailable(aRequest, aContext, mInputStream, 0, numBytesWritten);
                            }
                            else
                                   status = NS_OK;                           /* do nothing for resource fork.   */

                            mPosOutputBuff = 0;
                            
                            if (status != NS_OK)
                                   mState = BINHEX_STATE_DONE;
                            else
                                   mState ++;
                            
        mInCRC = 1;
                     }
                     else if (mPosOutputBuff >= DATA_BUFFER_SIZE)
                     {                           
                            if (mState == BINHEX_STATE_DFORK)
                            {
          PRUint32 numBytesWritten = 0; 
          mOutputStream->Write(mOutgoingBuffer, mPosOutputBuff, &numBytesWritten);
          if (PRInt32(numBytesWritten) != mPosOutputBuff)
            status = NS_ERROR_FAILURE;

          mNextListener->OnDataAvailable(aRequest, aContext, mInputStream, 0, numBytesWritten);
          mPosOutputBuff = 0;
        }                                               
                     }
                     break;
                     
              case BINHEX_STATE_HCRC:
              case BINHEX_STATE_DCRC:
              case BINHEX_STATE_RCRC:
                     if (!mCount++) 
                            mFileCRC = (unsigned short) c << 8;
                     else 
                     {
                            if ((mFileCRC | c) != mCRC) 
                            {
                                   mState = BINHEX_STATE_DONE;
                                   break;
                            }
                            
                            /* passed the CRC check!!!*/
                            mCRC = 0;
                            if (++ mState == BINHEX_STATE_FINISH) 
                            { 
          // when we reach the finished state...fire an on stop request on the event listener...
          mNextListener->OnStopRequest(aRequest, aContext, NS_OK);
          mNextListener = 0;
      
          /*  now We are done with everything.   */            
                                   mState++;
                                   break;
                            }
                            
                            if (mState == BINHEX_STATE_DFORK) 
                                   mCount = PR_ntohl(mHeader.dlen);
                            else
                            {
          // we aren't processing the resurce Fork. uncomment this line if we make this converter
          // smart enough to do this in the future.
                                   // mCount = PR_ntohl(mHeader.rlen);       /* it should in host byte order */
          mCount = 0; 
                            }
                            
                            if (mCount) 
                                   mInCRC = 0;                                      
                            else 
                                   /* nothing inside, so skip to the next state. */
                                   mState ++;
                     }
                     break;
       }
       
       return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsBinHexDecoder::SetContentType ( nsIRequest aRequest,
const char *  fileName 
) [protected]

Definition at line 496 of file nsBinHexDecoder.cpp.

{
  if (!fileName || !*fileName) {
    // Nothing to do here.
    return NS_OK;
  }

  nsresult rv;
  nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest, &rv));
  NS_ENSURE_SUCCESS(rv, rv);
  
  nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1", &rv));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCAutoString contentType;

  // extract the extension from fileName and look it up.
  const char * fileExt = strrchr(fileName, '.');
  if (!fileExt) {
    return NS_OK;
  }

  mimeService->GetTypeFromExtension(nsDependentCString(fileExt), contentType);

  // Only set the type if it's not empty and, to prevent recursive loops, not the binhex type
  if (!contentType.IsEmpty() && !contentType.Equals(APPLICATION_BINHEX)) {
    channel->SetContentType(contentType);
  } else {
    channel->SetContentType(NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE));
  }

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Definition at line 146 of file nsBinHexDecoder.h.

Definition at line 127 of file nsBinHexDecoder.h.

char* nsBinHexDecoder::mDataBuffer [protected]

Definition at line 140 of file nsBinHexDecoder.h.

Definition at line 131 of file nsBinHexDecoder.h.

Definition at line 128 of file nsBinHexDecoder.h.

Definition at line 135 of file nsBinHexDecoder.h.

Definition at line 132 of file nsBinHexDecoder.h.

Definition at line 124 of file nsBinHexDecoder.h.

Definition at line 147 of file nsBinHexDecoder.h.

char nsBinHexDecoder::mName[64] [protected]

Definition at line 136 of file nsBinHexDecoder.h.

Definition at line 120 of file nsBinHexDecoder.h.

Definition at line 129 of file nsBinHexDecoder.h.

Definition at line 130 of file nsBinHexDecoder.h.

Definition at line 141 of file nsBinHexDecoder.h.

Definition at line 123 of file nsBinHexDecoder.h.

Definition at line 149 of file nsBinHexDecoder.h.

Definition at line 142 of file nsBinHexDecoder.h.

Definition at line 150 of file nsBinHexDecoder.h.

unsigned char nsBinHexDecoder::mRlebuf [protected]

Definition at line 144 of file nsBinHexDecoder.h.

Definition at line 126 of file nsBinHexDecoder.h.


The documentation for this class was generated from the following files: