if (sourceOffset != mCurrentStreamOffset || mCurrentStreamOffset == -1 ) { mPosition = 0; mCurrentStreamOffset = sourceOffset; }  pluginInfo->GetURL(&mNPStream.url); pluginInfo->GetLastModified((PRUint32*)&(mNPStream.lastmodified));  if (callbacks->write == nsnull || length == 0) return NS_OK;  if (nsnull == mStreamBuffer) {   mStreamBuffer = (char*) PR_Malloc(length); if (!mStreamBuffer) return NS_ERROR_OUT_OF_MEMORY; createdHere = PR_TRUE; }  if (length > MAX_PLUGIN_NECKO_BUFFER) { leftToRead = length - MAX_PLUGIN_NECKO_BUFFER; length     = MAX_PLUGIN_NECKO_BUFFER; } nsresult rv = input->Read(mStreamBuffer, length, (PRUint32*)&amountRead); if (NS_FAILED(rv)) goto error;      while (amountRead > 0) { if (callbacks->writeready != NULL)
while (amountRead > 0)
ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,                                          nsIInputStream* input,                                          PRUint32 sourceOffset,                                           PRUint32 length){  if (!mInst || !mInst->IsStarted())    return NS_ERROR_FAILURE;  const NPPluginFuncs *callbacks = nsnull;  NPP npp;  mInst->GetCallbacks(&callbacks);  mInst->GetNPP(&npp);  if(!callbacks)    return NS_ERROR_FAILURE;  PRInt32   numtowrite = 0;  PRInt32   amountRead = 0;  PRInt32   writeCount = 0;  PRUint32  leftToRead = 0;         // just in case OnDataaAvail tries to overflow our buffer  PRBool   createdHere = PR_FALSE;  // we did malloc in locally, so we must free locally  // if we are getting a range request, reset mPosition.    if (sourceOffset != mCurrentStreamOffset ||      mCurrentStreamOffset == -1 )   {    mPosition = 0;    mCurrentStreamOffset = sourceOffset;  }  pluginInfo->GetURL(&mNPStream.url);  pluginInfo->GetLastModified((PRUint32*)&(mNPStream.lastmodified));  if (callbacks->write == nsnull || length == 0)    return NS_OK; // XXX ?  if (nsnull == mStreamBuffer)  {    // create the buffer here because we failed in OnStartBinding    // XXX why don't we always get an OnStartBinding? This will protect us.    mStreamBuffer = (char*) PR_Malloc(length);    if (!mStreamBuffer)    return NS_ERROR_OUT_OF_MEMORY;    createdHere = PR_TRUE;  }  if (length > MAX_PLUGIN_NECKO_BUFFER)  // what if Necko gives us a lot of data?  {    leftToRead = length - MAX_PLUGIN_NECKO_BUFFER; // break it up    length     = MAX_PLUGIN_NECKO_BUFFER;  }  nsresult rv = input->Read(mStreamBuffer, length, (PRUint32*)&amountRead);  if (NS_FAILED(rv))    goto error;  // amountRead tells us how many bytes were put in the buffer  // WriteReady returns to us how many bytes the plugin is   // ready to handle  - we have to keep calling WriteReady and  // Write until the buffer is empty  while (amountRead > 0)  {    if (callbacks->writeready != NULL)    {      PRLibrary* lib = nsnull;      lib = mInst->fLibrary;      NS_TRY_SAFE_CALL_RETURN(numtowrite, CallNPP_WriteReadyProc(callbacks->writeready,                                                                   npp,                                                                   &mNPStream), lib);      NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,      ("NPP WriteReady called: this=%p, npp=%p, return(towrite)=%d, url=%s\n",      this, npp, numtowrite, mNPStream.url));      // if WriteReady returned 0, the plugin is not ready to handle       // the data, return FAILURE for now      if (numtowrite <= 0) {        rv = NS_ERROR_FAILURE;        goto error;      }      if (numtowrite > amountRead)        numtowrite = amountRead;    }    else     {      // if WriteReady is not supported by the plugin,       // just write the whole buffer      numtowrite = length;    }    if (numtowrite > 0)    {#if 0 // useful for debugging problems with byte range buffers      printf(">  %d - %d \n", sourceOffset + writeCount + mPosition, numtowrite);      nsCString x;       x.Append("d:\\parts\\");      x.AppendInt(sourceOffset);      PRFileDesc* fd;      fd = PR_Open(x, PR_CREATE_FILE |PR_SYNC| PR_APPEND | PR_RDWR, 777);      PR_Write(fd, mStreamBuffer, numtowrite);      PR_Close(fd);#endif      NS_TRY_SAFE_CALL_RETURN(writeCount, CallNPP_WriteProc(callbacks->write,                                                            npp,                                                            &mNPStream,                                                             sourceOffset + writeCount + mPosition,                                                            numtowrite,                                                            (void *)mStreamBuffer), mInst->fLibrary);     NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,     ("NPP Write called: this=%p, npp=%p, pos=%d, len=%d, buf=%s, return(written)=%d, url=%s\n",     this, npp, mPosition, numtowrite, (char *)mStreamBuffer, writeCount, mNPStream.url));      if (writeCount < 0) {        rv = NS_ERROR_FAILURE;        goto error;      }      if (sourceOffset == 0)          mPosition += numtowrite;      amountRead -= numtowrite;    }  }  rv = NS_OK;error:  if (PR_TRUE == createdHere) // cleanup buffer if we made it locally  {    PR_Free(mStreamBuffer);    mStreamBuffer=nsnull;  }  if (leftToRead > 0)  // if we have more to read in this pass, do it recursivly  {    OnDataAvailable(pluginInfo, input, sourceOffset, leftToRead);  }  return rv;}