示例#1
0
NS_IMETHODIMP
nsXPInstallManager::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
{
    nsresult rv = NS_ERROR_FAILURE;

    // If we are dealing with a HTTP request, then treat HTTP error pages as
    // download failures.
    nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(request);
    if (httpChan) {
        // If we were chrome lauched check the certificate on the request
        if (mFromChrome && NS_FAILED(CheckCert(httpChan))) {
            request->Cancel(NS_BINDING_ABORTED);
            return NS_OK;
        }
        PRBool succeeded;
        if (NS_SUCCEEDED(httpChan->GetRequestSucceeded(&succeeded)) && !succeeded) {
            // HTTP response is not a 2xx!
            request->Cancel(NS_BINDING_ABORTED);
            return NS_OK;
        }
    }

    NS_ASSERTION( mItem && mItem->mFile, "XPIMgr::OnStartRequest bad state");
    if ( mItem && mItem->mFile )
    {
        NS_ASSERTION( !mItem->mOutStream, "Received double OnStartRequest from Necko");

        rv = NS_NewLocalFileOutputStream(getter_AddRefs(mItem->mOutStream),
                                         mItem->mFile,
                                         PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
                                         0600);
    }
    return rv;
}
/* void Save (); */
NS_IMETHODIMP mozPersonalDictionary::Save()
{
  nsCOMPtr<nsIFile> theFile;
  nsresult res;

  if(!mDirty) return NS_OK;

  //FIXME Deinst  -- get dictionary name from prefs;
  res = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(theFile));
  if(NS_FAILED(res)) return res;
  if(!theFile)return NS_ERROR_FAILURE;
  res = theFile->Append(NS_LITERAL_STRING(MOZ_PERSONAL_DICT_NAME));
  if(NS_FAILED(res)) return res;

  nsCOMPtr<nsIOutputStream> outStream;
  NS_NewLocalFileOutputStream(getter_AddRefs(outStream), theFile, PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE ,0664);

  // get a buffered output stream 4096 bytes big, to optimize writes
  nsCOMPtr<nsIOutputStream> bufferedOutputStream;
  res = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream), outStream, 4096);
  if (NS_FAILED(res)) return res;

  nsTArray<nsString> array(mDictionaryTable.Count());
  mDictionaryTable.EnumerateEntries(AddHostToStringArray, &array);

  PRUint32 bytesWritten;
  nsCAutoString utf8Key;
  for (PRUint32 i = 0; i < array.Length(); ++i ) {
    CopyUTF16toUTF8(array[i], utf8Key);

    bufferedOutputStream->Write(utf8Key.get(), utf8Key.Length(), &bytesWritten);
    bufferedOutputStream->Write("\n", 1, &bytesWritten);
  }
  return res;
}
示例#3
0
NS_IMETHODIMP
nsHTMLEditorLog::StartLogging(nsIFile *aLogFile)
{
  nsresult result = NS_ERROR_FAILURE;

  NS_ENSURE_TRUE(aLogFile, NS_ERROR_NULL_POINTER);

  if (mFileStream)
  {
    result = StopLogging();

    NS_ENSURE_SUCCESS(result, result);
  }

  result = NS_NewLocalFileOutputStream(getter_AddRefs(mFileStream), aLogFile);
  NS_ENSURE_SUCCESS(result, result);

  if (mTxnMgr)
  {
    mEditorTxnLog = new nsEditorTxnLog(this);

    if (mEditorTxnLog)
    {
      NS_ADDREF(mEditorTxnLog);
      mTxnMgr->AddListener(mEditorTxnLog);
    }
    else
      return NS_ERROR_OUT_OF_MEMORY;
  }

  return NS_OK;
}
示例#4
0
//-------------------------------------------------------------------------
nsresult
DataStruct::WriteCache(nsISupports* aData, uint32_t aDataLen)
{
  // Get a new path and file to the temp directory
  nsCOMPtr<nsIFile> cacheFile ( getter_AddRefs(GetFileSpec(mCacheFileName)) );
  if (cacheFile) {
    // remember the file name
    if (!mCacheFileName) {
      nsXPIDLCString fName;
      cacheFile->GetNativeLeafName(fName);
      mCacheFileName = nsCRT::strdup(fName);
    }

    // write out the contents of the clipboard
    // to the file
    //uint32_t bytes;
    nsCOMPtr<nsIOutputStream> outStr;

    NS_NewLocalFileOutputStream(getter_AddRefs(outStr),
                                cacheFile);

    if (!outStr) return NS_ERROR_FAILURE;

    void* buff = nullptr;
    nsPrimitiveHelpers::CreateDataFromPrimitive ( mFlavor.get(), aData, &buff, aDataLen );
    if ( buff ) {
      uint32_t ignored;
      outStr->Write(reinterpret_cast<char*>(buff), aDataLen, &ignored);
      nsMemory::Free(buff);
      return NS_OK;
    }
  }
  return NS_ERROR_FAILURE;
}
示例#5
0
NS_IMETHODIMP 
nsDownloader::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
    nsresult rv;
    if (!mLocation) {
        nsCOMPtr<nsIFile> location;
        rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(location));
        if (NS_FAILED(rv)) return rv;

        char buf[13];
        NS_MakeRandomString(buf, 8);
        memcpy(buf+8, ".tmp", 5);
        rv = location->AppendNative(nsDependentCString(buf, 12));
        if (NS_FAILED(rv)) return rv;

        rv = location->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
        if (NS_FAILED(rv)) return rv;

        location.swap(mLocation);
        mLocationIsTemp = true;
    }

    rv = NS_NewLocalFileOutputStream(getter_AddRefs(mSink), mLocation);
    if (NS_FAILED(rv)) return rv;

    // we could wrap this output stream with a buffered output stream,
    // but it shouldn't be necessary since we will be writing large
    // chunks given to us via OnDataAvailable.

    return NS_OK;
}
nsPluginStreamToFile::nsPluginStreamToFile(const char* target,
                                           nsIPluginInstanceOwner* owner)
: mTarget(PL_strdup(target)),
mOwner(owner)
{
  nsresult rv;
  nsCOMPtr<nsIFile> pluginTmp;
  rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(pluginTmp));
  if (NS_FAILED(rv)) return;
  
  mTempFile = do_QueryInterface(pluginTmp, &rv);
  if (NS_FAILED(rv)) return;
  
  // need to create a file with a unique name - use target as the basis
  rv = mTempFile->AppendNative(nsDependentCString(target));
  if (NS_FAILED(rv)) return;
  
  // Yes, make it unique.
  rv = mTempFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0700); 
  if (NS_FAILED(rv)) return;
  
  // create the file
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), mTempFile, -1, 00600);
  if (NS_FAILED(rv))
    return;
	
  // construct the URL we'll use later in calls to GetURL()
  NS_GetURLSpecFromFile(mTempFile, mFileURL);
  
#ifdef DEBUG
  printf("File URL = %s\n", mFileURL.get());
#endif
}
示例#7
0
NS_IMETHODIMP nsZipWriter::Open(nsIFile *aFile, int32_t aIoFlags)
{
    if (mStream)
        return NS_ERROR_ALREADY_INITIALIZED;

    NS_ENSURE_ARG_POINTER(aFile);

    // Need to be able to write to the file
    if (aIoFlags & PR_RDONLY)
        return NS_ERROR_FAILURE;
    
    nsresult rv = aFile->Clone(getter_AddRefs(mFile));
    NS_ENSURE_SUCCESS(rv, rv);

    bool exists;
    rv = mFile->Exists(&exists);
    NS_ENSURE_SUCCESS(rv, rv);
    if (!exists && !(aIoFlags & PR_CREATE_FILE))
        return NS_ERROR_FILE_NOT_FOUND;

    if (exists && !(aIoFlags & (PR_TRUNCATE | PR_WRONLY))) {
        rv = ReadFile(mFile);
        NS_ENSURE_SUCCESS(rv, rv);
        mCDSDirty = false;
    }
    else {
        mCDSOffset = 0;
        mCDSDirty = true;
        mComment.Truncate();
    }

    // Silently drop PR_APPEND
    aIoFlags &= 0xef;

    nsCOMPtr<nsIOutputStream> stream;
    rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), mFile, aIoFlags);
    if (NS_FAILED(rv)) {
        mHeaders.Clear();
        mEntryHash.Clear();
        return rv;
    }

    rv = NS_NewBufferedOutputStream(getter_AddRefs(mStream), stream, 64 * 1024);
    if (NS_FAILED(rv)) {
        stream->Close();
        mHeaders.Clear();
        mEntryHash.Clear();
        return rv;
    }

    if (mCDSOffset > 0) {
        rv = SeekCDS();
        NS_ENSURE_SUCCESS(rv, rv);
    }

    return NS_OK;
}
示例#8
0
NS_IMETHODIMP
DataStorage::Writer::Run()
{
  nsresult rv;
  // Concurrent operations on nsIFile objects are not guaranteed to be safe,
  // so we clone the file while holding the lock and then release the lock.
  // At that point, we can safely operate on the clone.
  nsCOMPtr<nsIFile> file;
  {
    MutexAutoLock lock(mDataStorage->mMutex);
    // If we don't have a profile, bail.
    if (!mDataStorage->mBackingFile) {
      return NS_OK;
    }
    rv = mDataStorage->mBackingFile->Clone(getter_AddRefs(file));
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }
  }

  nsCOMPtr<nsIOutputStream> outputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), file,
                                   PR_CREATE_FILE | PR_TRUNCATE | PR_WRONLY);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  const char* ptr = mData.get();
  int32_t remaining = mData.Length();
  uint32_t written = 0;
  while (remaining > 0) {
    rv = outputStream->Write(ptr, remaining, &written);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }
    remaining -= written;
    ptr += written;
  }

  // Observed by tests.
  nsCOMPtr<nsIRunnable> job =
    NS_NewRunnableMethodWithArg<const char*>(mDataStorage,
                                             &DataStorage::NotifyObservers,
                                             "data-storage-written");
  rv = NS_DispatchToMainThread(job, NS_DISPATCH_NORMAL);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  return NS_OK;
}
示例#9
0
 nsresult Init(const char* origFile) {
     nsresult rv;
     nsCOMPtr<nsILocalFile> file;
     rv = NS_NewNativeLocalFile(nsDependentCString(origFile), PR_FALSE, getter_AddRefs(file));
     if (NS_FAILED(rv)) return rv;
     nsCAutoString name;
     rv = file->GetNativeLeafName(name);
     if (NS_FAILED(rv)) return rv;
     name.AppendLiteral(".bak");
     rv = file->SetNativeLeafName(name);
     if (NS_FAILED(rv)) return rv;
     rv = NS_NewLocalFileOutputStream(getter_AddRefs(mOut),
                                      file, 
                                      PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
                                      0664);
     return rv;
 }
nsresult nsMsgSaveAsListener::SetupMsgWriteStream(nsIFile *aFile, PRBool addDummyEnvelope)
{
  nsresult rv = NS_ERROR_FAILURE;

  // If the file already exists, delete it, but do this before
  // getting the outputstream.
  // Due to bug 328027, the nsSaveMsgListener created in 
  // nsMessenger::SaveAs now opens the stream on the nsIFileSpec
  // object, thus creating an empty file. Actual save operations for
  // IMAP and NNTP use this nsMsgSaveAsListener here, though, so we
  // have to close the stream before deleting the file, else data
  // would still be written happily into a now non-existing file.
  // (Windows doesn't care, btw, just unixoids do...)
  aFile->Remove(PR_FALSE);

  nsCOMPtr <nsILocalFile> localFile = do_QueryInterface(aFile);
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(m_outputStream), localFile, -1, 00600);
  NS_ENSURE_SUCCESS(rv,rv);

  if (m_outputStream && addDummyEnvelope)
  {
    nsCAutoString result;
    char *ct;
    PRUint32 writeCount;
    time_t now = time ((time_t*) 0);
    ct = ctime(&now);
    ct[24] = 0;
    result = "From - ";
    result += ct;
    result += MSG_LINEBREAK;
    
    m_outputStream->Write(result.get(), result.Length(),
                               &writeCount);
    result = "X-Mozilla-Status: 0001";
    result += MSG_LINEBREAK;
    m_outputStream->Write(result.get(), result.Length(),
                               &writeCount);
    result =  "X-Mozilla-Status2: 00000000";
    result += MSG_LINEBREAK;
    m_outputStream->Write(result.get(), result.Length(),
                               &writeCount);
  }
  return rv;
}
/**
 * asynchronously copy file.
 */
static nsresult
RunTest(nsIFile *srcFile, nsIFile *destFile)
{
    nsresult rv;

    LOG(("RunTest\n"));

    nsCOMPtr<nsIStreamTransportService> sts =
        do_GetService(kStreamTransportServiceCID, &rv);
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIInputStream> srcStr;
    rv = NS_NewLocalFileInputStream(getter_AddRefs(srcStr), srcFile);
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIOutputStream> destStr;
    rv = NS_NewLocalFileOutputStream(getter_AddRefs(destStr), destFile);
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsITransport> srcTransport;
    rv = sts->CreateInputTransport(srcStr, PRInt64(-1), PRInt64(-1), PR_TRUE,
                                   getter_AddRefs(srcTransport));
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsITransport> destTransport;
    rv = sts->CreateOutputTransport(destStr, PRInt64(-1), PRInt64(-1), PR_TRUE,
                                    getter_AddRefs(destTransport));
    if (NS_FAILED(rv)) return rv;

    MyCopier *copier = new MyCopier();
    if (copier == nsnull)
        return NS_ERROR_OUT_OF_MEMORY;
    NS_ADDREF(copier);

    rv = copier->AsyncCopy(srcTransport, destTransport);
    if (NS_FAILED(rv)) return rv;

    PumpEvents();

    NS_RELEASE(copier);
    return NS_OK;
}
示例#12
0
nsresult nsMsgMdnGenerator::CreateMdnMsg()
{
    DEBUG_MDN("nsMsgMdnGenerator::CreateMdnMsg");
    nsresult rv;

    nsCOMPtr<nsIFile> tmpFile;
    rv = GetSpecialDirectoryWithFileName(NS_OS_TEMP_DIR,
                                         "mdnmsg",
                                         getter_AddRefs(m_file));
    NS_ENSURE_SUCCESS(rv, rv);

    rv = m_file->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 00600);
    nsCOMPtr <nsILocalFile> localFile = do_QueryInterface(m_file);
    NS_ENSURE_SUCCESS(rv, rv);
    rv = NS_NewLocalFileOutputStream(getter_AddRefs(m_outputStream),
                                     localFile,
                                     PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
                                     0664);
    NS_ASSERTION(NS_SUCCEEDED(rv),"creating mdn: failed to output stream");
    if (NS_FAILED(rv))
        return NS_OK;

    rv = CreateFirstPart();
    if (NS_SUCCEEDED(rv))
    {
        rv = CreateSecondPart();
        if (NS_SUCCEEDED(rv))
            rv = CreateThirdPart();
    }

    if (m_outputStream)
    {
        m_outputStream->Flush();
        m_outputStream->Close();
    }
    if (NS_FAILED(rv))
        m_file->Remove(false);
    else
        rv = SendMdnMsg();

    return NS_OK;
}
示例#13
0
nsresult nsAutoConfig::writeFailoverFile()
{
    nsresult rv;
    nsCOMPtr<nsIFile> failoverFile; 
    nsCOMPtr<nsIOutputStream> outStr;
    PRUint32 amt;
    
    rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
                                getter_AddRefs(failoverFile));
    if (NS_FAILED(rv)) 
        return rv;
    
    failoverFile->AppendNative(NS_LITERAL_CSTRING("failover.jsc"));
    
    rv = NS_NewLocalFileOutputStream(getter_AddRefs(outStr), failoverFile);
    if (NS_FAILED(rv)) 
        return rv;
    rv = outStr->Write(mBuf.get(),mBuf.Length(),&amt);
    outStr->Close();
    return rv;
}
static nsresult
RunBlockingTest(nsIFile *srcFile, nsIFile *destFile)
{
    nsresult rv;

    LOG(("RunBlockingTest\n"));

    nsCOMPtr<nsIStreamTransportService> sts =
        do_GetService(kStreamTransportServiceCID, &rv);
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIInputStream> srcIn;
    rv = NS_NewLocalFileInputStream(getter_AddRefs(srcIn), srcFile);
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIOutputStream> fileOut;
    rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOut), destFile);
    if (NS_FAILED(rv)) return rv;
    
    nsCOMPtr<nsITransport> destTransport;
    rv = sts->CreateOutputTransport(fileOut, PRInt64(-1), PRInt64(-1),
                                    PR_TRUE, getter_AddRefs(destTransport));
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIOutputStream> destOut;
    rv = destTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING, 100, 10, getter_AddRefs(destOut));
    if (NS_FAILED(rv)) return rv;

    char buf[120];
    PRUint32 n;
    for (;;) {
        rv = srcIn->Read(buf, sizeof(buf), &n);
        if (NS_FAILED(rv) || (n == 0)) return rv;

        rv = destOut->Write(buf, n, &n);
        if (NS_FAILED(rv)) return rv;
    }

    return NS_OK;
}
nsresult
VariableLengthPrefixSet::StoreToFile(nsIFile* aFile)
{
  NS_ENSURE_ARG_POINTER(aFile);

  MutexAutoLock lock(mLock);

  nsCOMPtr<nsIOutputStream> localOutFile;
  nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(localOutFile), aFile,
                                            PR_WRONLY | PR_TRUNCATE | PR_CREATE_FILE);
  NS_ENSURE_SUCCESS(rv, rv);

  uint32_t fileSize = 0;
  // Preallocate the file storage
  {
    nsCOMPtr<nsIFileOutputStream> fos(do_QueryInterface(localOutFile));
    Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_VLPS_FALLOCATE_TIME> timer;

    fileSize += mFixedPrefixSet->CalculatePreallocateSize();
    fileSize += CalculatePreallocateSize();

    Unused << fos->Preallocate(fileSize);
  }

  // Convert to buffered stream
  nsCOMPtr<nsIOutputStream> out;
  rv = NS_NewBufferedOutputStream(getter_AddRefs(out), localOutFile.forget(),
                                  std::min(fileSize, MAX_BUFFER_SIZE));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = mFixedPrefixSet->WritePrefixes(out);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = WritePrefixes(out);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}
NS_IMETHODIMP
nsXPCFastLoadIO::GetOutputStream(nsIOutputStream **_retval)
{
    if (! mOutputStream) {
        PRInt32 ioFlags = PR_WRONLY;
        if (! mInputStream) {
            ioFlags |= PR_CREATE_FILE | PR_TRUNCATE;
        }

        nsCOMPtr<nsIOutputStream> fileOutput;
        nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOutput),
                                                  mFile, ioFlags, 0644);
        NS_ENSURE_SUCCESS(rv, rv);

        rv = NS_NewBufferedOutputStream(getter_AddRefs(mOutputStream),
                                        fileOutput,
                                        XPC_SERIALIZATION_BUFFER_SIZE);
        NS_ENSURE_SUCCESS(rv, rv);
    }

    NS_ADDREF(*_retval = mOutputStream);
    return NS_OK;
}
NS_IMETHODIMP
nsXULFastLoadFileIO::GetOutputStream(nsIOutputStream** aResult)
{
    if (! mOutputStream) {
        PRInt32 ioFlags = PR_WRONLY;
        if (mTruncateOutputFile)
            ioFlags |= PR_CREATE_FILE | PR_TRUNCATE;

        nsresult rv;
        nsCOMPtr<nsIOutputStream> fileOutput;
        rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOutput), mFile,
                                         ioFlags, 0644);
        if (NS_FAILED(rv)) return rv;

        rv = NS_NewBufferedOutputStream(getter_AddRefs(mOutputStream),
                                        fileOutput,
                                        XUL_SERIALIZATION_BUFFER_SIZE);
        if (NS_FAILED(rv)) return rv;
    }

    NS_ADDREF(*aResult = mOutputStream);
    return NS_OK;
}
示例#18
0
NS_IMETHODIMP 
nsDownloader::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
    nsresult rv = NS_ERROR_FAILURE;
    if (!mLocation) {
        nsCOMPtr<nsICachingChannel> caching = do_QueryInterface(request, &rv);
        if (NS_SUCCEEDED(rv))
            rv = caching->SetCacheAsFile(PR_TRUE);
    }
    if (NS_FAILED(rv)) {
        // OK, we will need to stream the data to disk ourselves.  Make
        // sure mLocation exists.
        if (!mLocation) {
            rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mLocation));
            if (NS_FAILED(rv)) return rv;

            char buf[13];
            MakeRandomString(buf, 8);
            memcpy(buf+8, ".tmp", 5);
            rv = mLocation->AppendNative(nsDependentCString(buf, 12));
            if (NS_FAILED(rv)) return rv;

            rv = mLocation->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
            if (NS_FAILED(rv)) return rv;

            mLocationIsTemp = PR_TRUE;
        }
        
        rv = NS_NewLocalFileOutputStream(getter_AddRefs(mSink), mLocation);
        if (NS_FAILED(rv)) return rv;

        // we could wrap this output stream with a buffered output stream,
        // but it shouldn't be necessary since we will be writing large
        // chunks given to us via OnDataAvailable.
    }
    return rv;
}
示例#19
0
    NS_IMETHOD Run() {
        nsresult rv;

        PRIntervalTime startTime = PR_IntervalNow();
        PRIntervalTime endTime;
        nsCOMPtr<nsIInputStream> inStr;
        nsCOMPtr<nsIOutputStream> outStr;
        PRUint32 copyCount = 0;

        // Open the input stream:
        nsCOMPtr<nsIInputStream> fileIn;
        rv = NS_NewLocalFileInputStream(getter_AddRefs(fileIn), mInPath);
        if (NS_FAILED(rv)) return rv;

        rv = NS_NewBufferedInputStream(getter_AddRefs(inStr), fileIn, 65535);
        if (NS_FAILED(rv)) return rv;

        // Open the output stream:
        nsCOMPtr<nsIOutputStream> fileOut;
        rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOut),
                                         mOutPath, 
                                         PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE,
                                         0664);
        if (NS_FAILED(rv)) return rv;

        rv = NS_NewBufferedOutputStream(getter_AddRefs(outStr), fileOut, 65535);
        if (NS_FAILED(rv)) return rv;

        // Copy from one to the other
        rv = Copy(inStr, outStr, mBuffer, mBufferSize, &copyCount);
        if (NS_FAILED(rv)) return rv;

        endTime = PR_IntervalNow();
        gTimeSampler.AddTime(endTime - startTime);

        return rv;
    }
示例#20
0
nsresult
LookupCacheV4::WriteMetadata(TableUpdateV4* aTableUpdate)
{
  NS_ENSURE_ARG_POINTER(aTableUpdate);

  nsCOMPtr<nsIFile> metaFile;
  nsresult rv = mStoreDirectory->Clone(getter_AddRefs(metaFile));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = metaFile->AppendNative(mTableName + METADATA_SUFFIX);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIOutputStream> outputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), metaFile,
                                   PR_WRONLY | PR_TRUNCATE | PR_CREATE_FILE);
  if (!NS_SUCCEEDED(rv)) {
    LOG(("Unable to create file to store metadata."));
    return rv;
  }

  // Write the state.
  rv = WriteValue(outputStream, aTableUpdate->ClientState());
  if (NS_FAILED(rv)) {
    LOG(("Failed to write the list state."));
    return rv;
  }

  // Write the checksum.
  rv = WriteValue(outputStream, aTableUpdate->Checksum());
  if (NS_FAILED(rv)) {
    LOG(("Failed to write the list checksum."));
    return rv;
  }

  return rv;
}
示例#21
0
nsresult
LocalStoreImpl::CreateLocalStore(nsIFile* aFile)
{
    nsresult rv;

    rv = aFile->Create(nsIFile::NORMAL_FILE_TYPE, 0666);
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIOutputStream> outStream;
    rv = NS_NewLocalFileOutputStream(getter_AddRefs(outStream), aFile);
    if (NS_FAILED(rv)) return rv;

    const char defaultRDF[] = 
        "<?xml version=\"1.0\"?>\n" \
        "<RDF:RDF xmlns:RDF=\"" RDF_NAMESPACE_URI "\"\n" \
        "         xmlns:NC=\""  NC_NAMESPACE_URI "\">\n" \
        "  <!-- Empty -->\n" \
        "</RDF:RDF>\n";

    PRUint32 count;
    rv = outStream->Write(defaultRDF, sizeof(defaultRDF)-1, &count);
    if (NS_FAILED(rv)) return rv;

    if (count != sizeof(defaultRDF)-1)
        return NS_ERROR_UNEXPECTED;

    // Okay, now see if the file exists _for real_. If it's still
    // not there, it could be that the profile service gave us
    // back a read-only directory. Whatever.
    bool fileExistsFlag = false;
    aFile->Exists(&fileExistsFlag);
    if (!fileExistsFlag)
        return NS_ERROR_UNEXPECTED;

    return NS_OK;
}
nsresult
nsMsgAttachmentHandler::UrlExit(nsresult status, const PRUnichar* aMsg)
{
  NS_ASSERTION(m_mime_delivery_state != nsnull, "not-null m_mime_delivery_state");

  // Close the file, but don't delete the disk file (or the file spec.)
  if (mOutFile)
  {
    mOutFile->Close();
    mOutFile = nsnull;
  }
  // this silliness is because Windows nsILocalFile caches its file size
  // so if an output stream writes to it, it will still return the original
  // cached size.
  if (mTmpFile)
  {
    nsCOMPtr <nsIFile> tmpFile;
    mTmpFile->Clone(getter_AddRefs(tmpFile));
    mTmpFile = do_QueryInterface(tmpFile);
  }
  mRequest = nsnull;

  // First things first, we are now going to see if this is an HTML
  // Doc and if it is, we need to see if we can determine the charset
  // for this part by sniffing the HTML file.
  // This is needed only when the charset is not set already.
  // (e.g. a charset may be specified in HTTP header)
  //
  if (!m_type.IsEmpty() && m_charset.IsEmpty() &&
      m_type.LowerCaseEqualsLiteral(TEXT_HTML))
    m_charset = nsMsgI18NParseMetaCharset(mTmpFile);

  nsresult mimeDeliveryStatus;
  m_mime_delivery_state->GetStatus(&mimeDeliveryStatus);

  if (mimeDeliveryStatus == NS_ERROR_ABORT)
    status = NS_ERROR_ABORT;

  if (NS_FAILED(status) && status != NS_ERROR_ABORT && NS_SUCCEEDED(mimeDeliveryStatus))
  {
    // At this point, we should probably ask a question to the user
    // if we should continue without this attachment.
    //
    bool              keepOnGoing = true;
    nsCString    turl;
    nsString     msg;
    PRUnichar         *printfString = nsnull;
    nsresult rv;
    nsCOMPtr<nsIStringBundleService> bundleService(do_GetService("@mozilla.org/intl/stringbundle;1", &rv));
    NS_ENSURE_SUCCESS(rv, rv);
    nsCOMPtr<nsIStringBundle> bundle;
    rv = bundleService->CreateBundle("chrome://messenger/locale/messengercompose/composeMsgs.properties", getter_AddRefs(bundle));
    NS_ENSURE_SUCCESS(rv, rv);
    nsMsgDeliverMode mode = nsIMsgSend::nsMsgDeliverNow;
    m_mime_delivery_state->GetDeliveryMode(&mode);
    if (mode == nsIMsgSend::nsMsgSaveAsDraft || mode == nsIMsgSend::nsMsgSaveAsTemplate)
      bundle->GetStringFromID(NS_MSG_FAILURE_ON_OBJ_EMBED_WHILE_SAVING, getter_Copies(msg));
    else
      bundle->GetStringFromID(NS_MSG_FAILURE_ON_OBJ_EMBED_WHILE_SENDING, getter_Copies(msg));
    if (!m_realName.IsEmpty())
      printfString = nsTextFormatter::smprintf(msg.get(), m_realName.get());
    else if (NS_SUCCEEDED(mURL->GetSpec(turl)) && !turl.IsEmpty())
    {
      nsCAutoString unescapedUrl;
      MsgUnescapeString(turl, 0, unescapedUrl);
      if (unescapedUrl.IsEmpty())
        printfString = nsTextFormatter::smprintf(msg.get(), turl.get());
      else
        printfString = nsTextFormatter::smprintf(msg.get(), unescapedUrl.get());
    }
    else
      printfString = nsTextFormatter::smprintf(msg.get(), "?");

    nsCOMPtr<nsIPrompt> aPrompt;
    if (m_mime_delivery_state)
      m_mime_delivery_state->GetDefaultPrompt(getter_AddRefs(aPrompt));
    nsMsgAskBooleanQuestionByString(aPrompt, printfString, &keepOnGoing);
    PR_FREEIF(printfString);

    if (keepOnGoing)
    {
      status = 0;
      m_bogus_attachment = true; //That will cause this attachment to be ignored.
    }
    else
    {
      status = NS_ERROR_ABORT;
      m_mime_delivery_state->SetStatus(status);
      nsresult ignoreMe;
      m_mime_delivery_state->Fail(status, nsnull, &ignoreMe);
      m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, 0, nsnull);
      SetMimeDeliveryState(nsnull);
      return status;
    }
  }

  m_done = true;

  //
  // Ok, now that we have the file here on disk, we need to see if there was
  // a need to do conversion to plain text...if so, the magic happens here,
  // otherwise, just move on to other attachments...
  //
  if (NS_SUCCEEDED(status) && !m_type.LowerCaseEqualsLiteral(TEXT_PLAIN) &&
      m_desiredType.LowerCaseEqualsLiteral(TEXT_PLAIN))
  {
    //
    // Conversion to plain text desired.
    //
    PRInt32       width = 72;
    nsCOMPtr<nsIPrefBranch> pPrefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
    if (pPrefBranch)
      pPrefBranch->GetIntPref("mailnews.wraplength", &width);
    // Let sanity reign!
    if (width == 0)
      width = 72;
    else if (width < 10)
      width = 10;
    else if (width > 30000)
      width = 30000;

    //
    // Now use the converter service here to do the right
    // thing and convert this data to plain text for us!
    //
    nsAutoString      conData;

    if (NS_SUCCEEDED(LoadDataFromFile(mTmpFile, conData, true)))
    {
      if (NS_SUCCEEDED(ConvertBufToPlainText(conData, UseFormatFlowed(m_charset.get()))))
      {
        if (mDeleteFile)
          mTmpFile->Remove(false);

        nsCOMPtr<nsIOutputStream> outputStream;
        nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), mTmpFile,  PR_WRONLY | PR_CREATE_FILE, 00600);

        if (NS_SUCCEEDED(rv))
        {
          nsCAutoString tData;
          if (NS_FAILED(ConvertFromUnicode(m_charset.get(), conData, tData)))
            LossyCopyUTF16toASCII(conData, tData);
          if (!tData.IsEmpty())
          {
            PRUint32 bytesWritten;
            (void) outputStream->Write(tData.get(), tData.Length(), &bytesWritten);
          }
          outputStream->Close();
          // this silliness is because Windows nsILocalFile caches its file size
          // so if an output stream writes to it, it will still return the original
          // cached size.
          if (mTmpFile)
          {
            nsCOMPtr <nsIFile> tmpFile;
            mTmpFile->Clone(getter_AddRefs(tmpFile));
            mTmpFile = do_QueryInterface(tmpFile);
          }

        }
      }
    }

    m_type = m_desiredType;
    m_desiredType.Truncate();
    m_encoding.Truncate();
  }

  PRUint32 pendingAttachmentCount = 0;
  m_mime_delivery_state->GetPendingAttachmentCount(&pendingAttachmentCount);
  NS_ASSERTION (pendingAttachmentCount > 0, "no more pending attachment");

  m_mime_delivery_state->SetPendingAttachmentCount(pendingAttachmentCount - 1);

  bool processAttachmentsSynchronously = false;
  m_mime_delivery_state->GetProcessAttachmentsSynchronously(&processAttachmentsSynchronously);
  if (NS_SUCCEEDED(status) && processAttachmentsSynchronously)
  {
    /* Find the next attachment which has not yet been loaded,
     if any, and start it going.
     */
    PRUint32 i;
    nsMsgAttachmentHandler *next = 0;
    nsMsgAttachmentHandler *attachments = nsnull;
    PRUint32 attachmentCount = 0;

    m_mime_delivery_state->GetAttachmentCount(&attachmentCount);
    if (attachmentCount)
      m_mime_delivery_state->GetAttachmentHandlers(&attachments);

    for (i = 0; i < attachmentCount; i++)
    {
      if (!attachments[i].m_done)
      {
        next = &attachments[i];
        //
        // rhp: We need to get a little more understanding to failed URL
        // requests. So, at this point if most of next is NULL, then we
        // should just mark it fetched and move on! We probably ignored
        // this earlier on in the send process.
        //
        if ( (!next->mURL) && (next->m_uri.IsEmpty()) )
        {
          attachments[i].m_done = true;
          m_mime_delivery_state->GetPendingAttachmentCount(&pendingAttachmentCount);
          m_mime_delivery_state->SetPendingAttachmentCount(pendingAttachmentCount - 1);
          next->mPartUserOmissionOverride = true;
          next = nsnull;
          continue;
        }

        break;
      }
    }

    if (next)
    {
      int status = next->SnarfAttachment(mCompFields);
      if (NS_FAILED(status))
      {
        nsresult ignoreMe;
        m_mime_delivery_state->Fail(status, nsnull, &ignoreMe);
        m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, 0, nsnull);
        SetMimeDeliveryState(nsnull);
        return NS_ERROR_UNEXPECTED;
      }
    }
  }

  m_mime_delivery_state->GetPendingAttachmentCount(&pendingAttachmentCount);
  if (pendingAttachmentCount == 0)
  {
    // If this is the last attachment, then either complete the
    // delivery (if successful) or report the error by calling
    // the exit routine and terminating the delivery.
    if (NS_FAILED(status))
    {
      nsresult ignoreMe;
      m_mime_delivery_state->Fail(status, aMsg, &ignoreMe);
      m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, aMsg, nsnull);
      SetMimeDeliveryState(nsnull);
      return NS_ERROR_UNEXPECTED;
    }
    else
    {
      status = m_mime_delivery_state->GatherMimeAttachments ();
      if (NS_FAILED(status))
      {
        nsresult ignoreMe;
        m_mime_delivery_state->Fail(status, aMsg, &ignoreMe);
        m_mime_delivery_state->NotifyListenerOnStopSending(nsnull, status, aMsg, nsnull);
        SetMimeDeliveryState(nsnull);
        return NS_ERROR_UNEXPECTED;
      }
    }
  }
  else
  {
    // If this is not the last attachment, but it got an error,
    // then report that error and continue
    if (NS_FAILED(status))
    {
      nsresult ignoreMe;
      m_mime_delivery_state->Fail(status, aMsg, &ignoreMe);
    }
  }

  SetMimeDeliveryState(nsnull);
  return NS_OK;
}
示例#23
0
nsresult
nsFileChannel::OpenContentStream(bool async, nsIInputStream **result,
                                 nsIChannel** channel)
{
  // NOTE: the resulting file is a clone, so it is safe to pass it to the
  //       file input stream which will be read on a background thread.
  nsCOMPtr<nsIFile> file;
  nsresult rv = GetFile(getter_AddRefs(file));
  if (NS_FAILED(rv))
    return rv;

  nsCOMPtr<nsIFileProtocolHandler> fileHandler;
  rv = NS_GetFileProtocolHandler(getter_AddRefs(fileHandler));
  if (NS_FAILED(rv))
    return rv;
    
  nsCOMPtr<nsIURI> newURI;
  rv = fileHandler->ReadURLFile(file, getter_AddRefs(newURI));
  if (NS_SUCCEEDED(rv)) {
    nsCOMPtr<nsIChannel> newChannel;
    rv = NS_NewChannel(getter_AddRefs(newChannel), newURI);
    if (NS_FAILED(rv))
      return rv;

    *result = nullptr;
    newChannel.forget(channel);
    return NS_OK;
  }

  nsCOMPtr<nsIInputStream> stream;

  if (mUploadStream) {
    // Pass back a nsFileUploadContentStream instance that knows how to perform
    // the file copy when "read" (the resulting stream in this case does not
    // actually return any data).

    nsCOMPtr<nsIOutputStream> fileStream;
    rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileStream), file,
                                     PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
                                     PR_IRUSR | PR_IWUSR);
    if (NS_FAILED(rv))
      return rv;

    nsRefPtr<nsFileUploadContentStream> uploadStream =
        new nsFileUploadContentStream(async, fileStream, mUploadStream,
                                      mUploadLength, this);
    if (!uploadStream || !uploadStream->IsInitialized()) {
      return NS_ERROR_OUT_OF_MEMORY;
    }
    stream = uploadStream.forget();

    mContentLength = 0;

    // Since there isn't any content to speak of we just set the content-type
    // to something other than "unknown" to avoid triggering the content-type
    // sniffer code in nsBaseChannel.
    // However, don't override explicitly set types.
    if (!HasContentTypeHint())
      SetContentType(NS_LITERAL_CSTRING(APPLICATION_OCTET_STREAM));
  } else {
    nsAutoCString contentType;
    rv = MakeFileInputStream(file, stream, contentType, async);
    if (NS_FAILED(rv))
      return rv;

    EnableSynthesizedProgressEvents(true);

    // fixup content length and type
    if (mContentLength < 0) {
      int64_t size;
      rv = file->GetFileSize(&size);
      if (NS_FAILED(rv)) {
        if (async && 
            (NS_ERROR_FILE_NOT_FOUND == rv ||
             NS_ERROR_FILE_TARGET_DOES_NOT_EXIST == rv)) {
          size = 0;
        } else {
          return rv;
        }
      }
      mContentLength = size;
    }
    if (!contentType.IsEmpty())
      SetContentType(contentType);
  }

  *result = nullptr;
  stream.swap(*result);
  return NS_OK;
}
示例#24
0
nsresult nsOE5File::ImportMailbox( PRUint32 *pBytesDone, PRBool *pAbort, nsString& name, nsIFile *inFile, nsIFile *pDestination, PRUint32 *pCount)
{
  nsresult  rv;
  PRInt32    msgCount = 0;
  if (pCount)
    *pCount = 0;

  nsCOMPtr <nsIInputStream> inputStream;
  rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), inFile);
  if (NS_FAILED( rv)) return( rv);
  nsCOMPtr <nsIOutputStream> outputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), pDestination, -1, 0600);
  if (NS_FAILED( rv))
    return( rv);

  PRUint32 *  pIndex;
  PRUint32  indexSize;

  if (!ReadIndex( inputStream, &pIndex, &indexSize)) {
    IMPORT_LOG1( "No messages found in mailbox: %S\n", name.get());
    return( NS_OK);
  }

  char *  pBuffer = new char[kMailboxBufferSize];
  if (!(*pAbort))
    ConvertIndex( inputStream, pBuffer, pIndex, indexSize);

  PRUint32  block[4];
  PRInt32   sepLen = (PRInt32) strlen( m_pFromLineSep);
  PRUint32   written;

  /*
      Each block is:
      marker - matches file offset
      block length
      text length in block
      pointer to next block. (0 if end)

      Each message is made up of a linked list of block data.
      So what we do for each message is:
      1. Read the first block data.
      2. Write out the From message separator if the message doesn't already
      start with one.
      3. If the block of data doesn't end with CRLF then a line is broken into two blocks,
      so save the incomplete line for later process when we read the next block. Then
      write out the block excluding the partial line at the end of the block (if exists).
      4. If there's next block of data then read next data block. Otherwise we're done.
      If we found a partial line in step #3 then find the rest of the line from the
      current block and write out this line separately.
      5. Reset some of the control variables and repeat step #3.
  */

  PRUint32  didBytes = 0;
  PRUint32  next, size;
  char *pStart, *pEnd, *partialLineStart;
  nsCAutoString partialLine, tempLine;
  rv = NS_OK;

  for (PRUint32 i = 0; (i < indexSize) && !(*pAbort); i++)
  {
    if (! pIndex[i])
      continue;

    if (ReadBytes( inputStream, block, pIndex[i], 16) && (block[0] == pIndex[i]) &&
      (block[2] < kMailboxBufferSize) && (ReadBytes( inputStream, pBuffer, kDontSeek, block[2])))
    {
      // block[2] contains the chars in the buffer (ie, buf content size).
      // block[3] contains offset to the next block of data (0 means no more data).
      size = block[2];
      pStart = pBuffer;
      pEnd = pStart + size;

      // write out the from separator.
      if (IsFromLine( pBuffer, size))
      {
        char *pChar = pStart;
        while ((pChar < pEnd) && (*pChar != '\r') && (*(pChar+1) != '\n'))
          pChar++;

        if (pChar < pEnd)
        {
          // Get the "From " line so write it out.
          rv = outputStream->Write(pStart, pChar-pStart+2, &written);
          NS_ENSURE_SUCCESS(rv,rv);
          // Now buffer starts from the 2nd line.
          pStart = pChar + 2;
        }
      }
      else
      {
        // Write out the default from line since there is none in the msg.
        rv = outputStream->Write( m_pFromLineSep, sepLen, &written);
        // FIXME: Do I need to check the return value of written???
        if (NS_FAILED( rv))
          break;
      }

      char statusLine[50];
      PRUint32 msgFlags = 0; // need to convert from OE flags to mozilla flags
      PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF);
      rv = outputStream->Write(statusLine, strlen(statusLine), &written);
      NS_ENSURE_SUCCESS(rv,rv);
      PR_snprintf(statusLine, sizeof(statusLine), X_MOZILLA_STATUS2_FORMAT MSG_LINEBREAK, msgFlags & 0xFFFF0000);
      rv = outputStream->Write(statusLine, strlen(statusLine), &written);
      NS_ENSURE_SUCCESS(rv,rv);

      do
      {
        partialLine.Truncate();
        partialLineStart = pEnd;

        // If the buffer doesn't end with CRLF then a line is broken into two blocks,
        // so save the incomplete line for later process when we read the next block.
        if ( (size > 1) && !(*(pEnd - 2) == '\r' && *(pEnd - 1) == '\n') )
        {
          partialLineStart -= 2;
          while ((partialLineStart >= pStart) && (*partialLineStart != '\r') && (*(partialLineStart+1) != '\n'))
            partialLineStart--;
          if (partialLineStart != (pEnd - 2))
            partialLineStart += 2; // skip over CRLF if we find them.
          partialLine.Assign(partialLineStart, pEnd - partialLineStart);
        }

        // Now process the block of data which ends with CRLF.
        rv = EscapeFromSpaceLine(outputStream, pStart, partialLineStart);
        if (NS_FAILED(rv))
          break;

        didBytes += block[2];

        next = block[3];
        if (! next)
        {
          // OK, we're done so flush out the partial line if it's not empty.
          if (partialLine.Length())
            rv = EscapeFromSpaceLine(outputStream, (char *)partialLine.get(), (partialLine.get()+partialLine.Length()));
        }
        else
          if (ReadBytes(inputStream, block, next, 16) && (block[0] == next) &&
            (block[2] < kMailboxBufferSize) && (ReadBytes(inputStream, pBuffer, kDontSeek, block[2])))
          {
            // See if we have a partial line from previous block. If so then build a complete
            // line (ie, take the remaining chars from this block) and process this line. Need
            // to adjust where data start and size in this case.
            size = block[2];
            pStart = pBuffer;
            pEnd = pStart + size;
            if (partialLine.Length())
            {
              while ((pStart < pEnd) && (*pStart != '\r') && (*(pStart+1) != '\n'))
                pStart++;
              if (pStart < pEnd)  // if we found a CRLF ..
                pStart += 2;      // .. then copy that too.
              tempLine.Assign(pBuffer, pStart - pBuffer);
              partialLine.Append(tempLine);
              rv = EscapeFromSpaceLine(outputStream, (char *)partialLine.get(), (partialLine.get()+partialLine.Length()));
              if (NS_FAILED(rv))
                break;

              // Adjust where data start and size (since some of the data has been processed).
              size -= (pStart - pBuffer);
            }
          }
          else
          {
            IMPORT_LOG2( "Error reading message from %S at 0x%lx\n", name.get(), pIndex[i]);
            rv = outputStream->Write( "\x0D\x0A", 2, &written);
            next = 0;
          }
      } while (next);

      // Always end a msg with CRLF. This will make sure that OE msgs without body is
      // correctly recognized as msgs. Otherwise, we'll end up with the following in
      // the msg folder where the 2nd msg starts right after the headers of the 1st msg:
      //
      // From - Jan 1965 00:00:00     <<<--- 1st msg starts here
      // Subject: Test msg
      // . . . (more headers)
      // To: <*****@*****.**>
      // From - Jan 1965 00:00:00     <<<--- 2nd msg starts here
      // Subject: How are you
      // . . .(more headers)
      //
      // In this case, the 1st msg is not recognized as a msg (it's skipped)
      // when you open the folder.
      rv = outputStream->Write( "\x0D\x0A", 2, &written);

      if (NS_FAILED(rv))
        break;

      msgCount++;
      if (pCount)
        *pCount = msgCount;
      if (pBytesDone)
        *pBytesDone = didBytes;
    }
    else {
      // Error reading message, should this be logged???
      IMPORT_LOG2( "Error reading message from %S at 0x%lx\n", name.get(), pIndex[i]);
      *pAbort = PR_TRUE;
    }
  }

  delete [] pBuffer;

  if (NS_FAILED(rv))
    *pAbort = PR_TRUE;

  return( rv);
}
// SetupPluginCacheFile is called if we have to save the stream to disk.
//
// These files will be deleted when the host is destroyed.
//
// TODO? What if we fill up the the dest dir?
nsresult
nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel)
{
  nsresult rv = NS_OK;

  bool useExistingCacheFile = false;
  nsRefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();

  // Look for an existing cache file for the URI.
  nsTArray< nsRefPtr<nsNPAPIPluginInstance> > *instances = pluginHost->InstanceArray();
  for (uint32_t i = 0; i < instances->Length(); i++) {
    // most recent streams are at the end of list
    nsTArray<nsPluginStreamListenerPeer*> *streamListeners = instances->ElementAt(i)->FileCachedStreamListeners();
    for (int32_t i = streamListeners->Length() - 1; i >= 0; --i) {
      nsPluginStreamListenerPeer *lp = streamListeners->ElementAt(i);
      if (lp && lp->mLocalCachedFileHolder) {
        useExistingCacheFile = lp->UseExistingPluginCacheFile(this);
        if (useExistingCacheFile) {
          mLocalCachedFileHolder = lp->mLocalCachedFileHolder;
          break;
        }
      }
      if (useExistingCacheFile)
        break;
    }
  }

  // Create a new cache file if one could not be found.
  if (!useExistingCacheFile) {
    nsCOMPtr<nsIFile> pluginTmp;
    rv = nsPluginHost::GetPluginTempDir(getter_AddRefs(pluginTmp));
    if (NS_FAILED(rv)) {
      return rv;
    }

    // Get the filename from the channel
    nsCOMPtr<nsIURI> uri;
    rv = channel->GetURI(getter_AddRefs(uri));
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
    if (!url)
      return NS_ERROR_FAILURE;

    nsAutoCString filename;
    url->GetFileName(filename);
    if (NS_FAILED(rv))
      return rv;

    // Create a file to save our stream into. Should we scramble the name?
    filename.Insert(NS_LITERAL_CSTRING("plugin-"), 0);
    rv = pluginTmp->AppendNative(filename);
    if (NS_FAILED(rv))
      return rv;

    // Yes, make it unique.
    rv = pluginTmp->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
    if (NS_FAILED(rv))
      return rv;

    // create a file output stream to write to...
    nsCOMPtr<nsIOutputStream> outstream;
    rv = NS_NewLocalFileOutputStream(getter_AddRefs(mFileCacheOutputStream), pluginTmp, -1, 00600);
    if (NS_FAILED(rv))
      return rv;

    // save the file.
    mLocalCachedFileHolder = new CachedFileHolder(pluginTmp);
  }

  // add this listenerPeer to list of stream peers for this instance
  mPluginInstance->FileCachedStreamListeners()->AppendElement(this);

  return rv;
}
示例#26
0
// Called on the worker thread.
nsresult
BackgroundFileSaver::ProcessStateChange()
{
  nsresult rv;

  // We might have been notified because the operation is complete, verify.
  if (CheckCompletion()) {
    return NS_OK;
  }

  // Get a copy of the current shared state for the worker thread.
  nsCOMPtr<nsIFile> initialTarget;
  bool initialTargetKeepPartial;
  nsCOMPtr<nsIFile> renamedTarget;
  bool renamedTargetKeepPartial;
  bool sha256Enabled;
  bool append;
  {
    MutexAutoLock lock(mLock);

    initialTarget = mInitialTarget;
    initialTargetKeepPartial = mInitialTargetKeepPartial;
    renamedTarget = mRenamedTarget;
    renamedTargetKeepPartial = mRenamedTargetKeepPartial;
    sha256Enabled = mSha256Enabled;
    append = mAppend;

    // From now on, another attention event needs to be posted if state changes.
    mWorkerThreadAttentionRequested = false;
  }

  // The initial target can only be null if it has never been assigned.  In this
  // case, there is nothing to do since we never created any output file.
  if (!initialTarget) {
    return NS_OK;
  }

  // Determine if we are processing the attention request for the first time.
  bool isContinuation = !!mActualTarget;
  if (!isContinuation) {
    // Assign the target file for the first time.
    mActualTarget = initialTarget;
    mActualTargetKeepPartial = initialTargetKeepPartial;
  }

  // Verify whether we have actually been instructed to use a different file.
  // This may happen the first time this function is executed, if SetTarget was
  // called two times before the worker thread processed the attention request.
  bool equalToCurrent = false;
  if (renamedTarget) {
    rv = mActualTarget->Equals(renamedTarget, &equalToCurrent);
    NS_ENSURE_SUCCESS(rv, rv);
    if (!equalToCurrent)
    {
      // If we were asked to rename the file but the initial file did not exist,
      // we simply create the file in the renamed location.  We avoid this check
      // if we have already started writing the output file ourselves.
      bool exists = true;
      if (!isContinuation) {
        rv = mActualTarget->Exists(&exists);
        NS_ENSURE_SUCCESS(rv, rv);
      }
      if (exists) {
        // We are moving the previous target file to a different location.
        nsCOMPtr<nsIFile> renamedTargetParentDir;
        rv = renamedTarget->GetParent(getter_AddRefs(renamedTargetParentDir));
        NS_ENSURE_SUCCESS(rv, rv);

        nsAutoString renamedTargetName;
        rv = renamedTarget->GetLeafName(renamedTargetName);
        NS_ENSURE_SUCCESS(rv, rv);

        // We must delete any existing target file before moving the current
        // one.
        rv = renamedTarget->Exists(&exists);
        NS_ENSURE_SUCCESS(rv, rv);
        if (exists) {
          rv = renamedTarget->Remove(false);
          NS_ENSURE_SUCCESS(rv, rv);
        }

        // Move the file.  If this fails, we still reference the original file
        // in mActualTarget, so that it is deleted if requested.  If this
        // succeeds, the nsIFile instance referenced by mActualTarget mutates
        // and starts pointing to the new file, but we'll discard the reference.
        rv = mActualTarget->MoveTo(renamedTargetParentDir, renamedTargetName);
        NS_ENSURE_SUCCESS(rv, rv);
      }

      // Now we can update the actual target file name.
      mActualTarget = renamedTarget;
      mActualTargetKeepPartial = renamedTargetKeepPartial;
    }
  }

  // Notify if the target file name actually changed.
  if (!equalToCurrent) {
    // We must clone the nsIFile instance because mActualTarget is not
    // immutable, it may change if the target is renamed later.
    nsCOMPtr<nsIFile> actualTargetToNotify;
    rv = mActualTarget->Clone(getter_AddRefs(actualTargetToNotify));
    NS_ENSURE_SUCCESS(rv, rv);

    RefPtr<NotifyTargetChangeRunnable> event =
      new NotifyTargetChangeRunnable(this, actualTargetToNotify);
    NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);

    rv = mControlThread->Dispatch(event, NS_DISPATCH_NORMAL);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  if (isContinuation) {
    // The pending rename operation might be the last task before finishing. We
    // may return here only if we have already created the target file.
    if (CheckCompletion()) {
      return NS_OK;
    }

    // Even if the operation did not complete, the pipe input stream may be
    // empty and may have been closed already.  We detect this case using the
    // Available property, because it never returns an error if there is more
    // data to be consumed.  If the pipe input stream is closed, we just exit
    // and wait for more calls like SetTarget or Finish to be invoked on the
    // control thread.  However, we still truncate the file or create the
    // initial digest context if we are expected to do that.
    uint64_t available;
    rv = mPipeInputStream->Available(&available);
    if (NS_FAILED(rv)) {
      return NS_OK;
    }
  }

  // Create the digest context if requested and NSS hasn't been shut down.
  if (sha256Enabled && !mDigestContext) {
    nsNSSShutDownPreventionLock lock;
    if (!isAlreadyShutDown()) {
      mDigestContext = UniquePK11Context(
        PK11_CreateDigestContext(SEC_OID_SHA256));
      NS_ENSURE_TRUE(mDigestContext, NS_ERROR_OUT_OF_MEMORY);
    }
  }

  // When we are requested to append to an existing file, we should read the
  // existing data and ensure we include it as part of the final hash.
  if (mDigestContext && append && !isContinuation) {
    nsCOMPtr<nsIInputStream> inputStream;
    rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream),
                                    mActualTarget,
                                    PR_RDONLY | nsIFile::OS_READAHEAD);
    if (rv != NS_ERROR_FILE_NOT_FOUND) {
      NS_ENSURE_SUCCESS(rv, rv);

      char buffer[BUFFERED_IO_SIZE];
      while (true) {
        uint32_t count;
        rv = inputStream->Read(buffer, BUFFERED_IO_SIZE, &count);
        NS_ENSURE_SUCCESS(rv, rv);

        if (count == 0) {
          // We reached the end of the file.
          break;
        }

        nsNSSShutDownPreventionLock lock;
        if (isAlreadyShutDown()) {
          return NS_ERROR_NOT_AVAILABLE;
        }

        nsresult rv = MapSECStatus(PK11_DigestOp(mDigestContext.get(),
                                                 uint8_t_ptr_cast(buffer),
                                                 count));
        NS_ENSURE_SUCCESS(rv, rv);
      }

      rv = inputStream->Close();
      NS_ENSURE_SUCCESS(rv, rv);
    }
  }

  // We will append to the initial target file only if it was requested by the
  // caller, but we'll always append on subsequent accesses to the target file.
  int32_t creationIoFlags;
  if (isContinuation) {
    creationIoFlags = PR_APPEND;
  } else {
    creationIoFlags = (append ? PR_APPEND : PR_TRUNCATE) | PR_CREATE_FILE;
  }

  // Create the target file, or append to it if we already started writing it.
  // The 0600 permissions are used while the file is being downloaded, and for
  // interrupted downloads. Those may be located in the system temporary
  // directory, as well as the target directory, and generally have a ".part"
  // extension. Those part files should never be group or world-writable even
  // if the umask allows it.
  nsCOMPtr<nsIOutputStream> outputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream),
                                   mActualTarget,
                                   PR_WRONLY | creationIoFlags, 0600);
  NS_ENSURE_SUCCESS(rv, rv);

  outputStream = NS_BufferOutputStream(outputStream, BUFFERED_IO_SIZE);
  if (!outputStream) {
    return NS_ERROR_FAILURE;
  }

  // Wrap the output stream so that it feeds the digest context if needed.
  if (mDigestContext) {
    // No need to acquire the NSS lock here, DigestOutputStream must acquire it
    // in any case before each asynchronous write. Constructing the
    // DigestOutputStream cannot fail. Passing mDigestContext to
    // DigestOutputStream is safe, because BackgroundFileSaver always outlives
    // the outputStream. BackgroundFileSaver is reference-counted before the
    // call to AsyncCopy, and mDigestContext is never destroyed before
    // AsyncCopyCallback.
    outputStream = new DigestOutputStream(outputStream, mDigestContext.get());
  }

  // Start copying our input to the target file.  No errors can be raised past
  // this point if the copy starts, since they should be handled by the thread.
  {
    MutexAutoLock lock(mLock);

    rv = NS_AsyncCopy(mPipeInputStream, outputStream, mWorkerThread,
                      NS_ASYNCCOPY_VIA_READSEGMENTS, 4096, AsyncCopyCallback,
                      this, false, true, getter_AddRefs(mAsyncCopyContext),
                      GetProgressCallback());
    if (NS_FAILED(rv)) {
      NS_WARNING("NS_AsyncCopy failed.");
      mAsyncCopyContext = nullptr;
      return rv;
    }
  }

  // If the operation succeeded, we must ensure that we keep this object alive
  // for the entire duration of the copy, since only the raw pointer will be
  // provided as the argument of the AsyncCopyCallback function.  We can add the
  // reference now, after NS_AsyncCopy returned, because it always starts
  // processing asynchronously, and there is no risk that the callback is
  // invoked before we reach this point.  If the operation failed instead, then
  // AsyncCopyCallback will never be called.
  NS_ADDREF_THIS();

  return NS_OK;
}
示例#27
0
NS_IMETHODIMP AsyncEncodeAndWriteIcon::Run()
{
  NS_PRECONDITION(!NS_IsMainThread(), "Should not be called on the main thread.");

  // Get the recommended icon width and height, or if failure to obtain 
  // these settings, fall back to 16x16 ICOs.  These values can be different
  // if the user has a different DPI setting other than 100%.
  // Windows would scale the 16x16 icon themselves, but it's better
  // we let our ICO encoder do it.
  nsCOMPtr<nsIInputStream> iconStream;
  nsRefPtr<imgIEncoder> encoder =
    do_CreateInstance("@mozilla.org/image/encoder;2?"
                      "type=image/vnd.microsoft.icon");
  NS_ENSURE_TRUE(encoder, NS_ERROR_FAILURE);
  nsresult rv = encoder->InitFromData(mBuffer, mBufferLength,
                                      mWidth, mHeight,
                                      mStride,
                                      imgIEncoder::INPUT_FORMAT_HOSTARGB,
                                      EmptyString());
  NS_ENSURE_SUCCESS(rv, rv);
  CallQueryInterface(encoder.get(), getter_AddRefs(iconStream));
  if (!iconStream) {
    return NS_ERROR_FAILURE;
  }

  NS_ENSURE_SUCCESS(rv, rv);
  nsCOMPtr<nsIFile> icoFile
    = do_CreateInstance("@mozilla.org/file/local;1");
  NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
  rv = icoFile->InitWithPath(mIconPath);

  // Setup the output stream for the ICO file on disk
  nsCOMPtr<nsIOutputStream> outputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), icoFile);
  NS_ENSURE_SUCCESS(rv, rv);

  // Obtain the ICO buffer size from the re-encoded ICO stream
  uint64_t bufSize64;
  rv = iconStream->Available(&bufSize64);
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_TRUE(bufSize64 <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);

  uint32_t bufSize = (uint32_t)bufSize64;

  // Setup a buffered output stream from the stream object
  // so that we can simply use WriteFrom with the stream object
  nsCOMPtr<nsIOutputStream> bufferedOutputStream;
  rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
                                  outputStream, bufSize);
  NS_ENSURE_SUCCESS(rv, rv);

  // Write out the icon stream to disk and make sure we wrote everything
  uint32_t wrote;
  rv = bufferedOutputStream->WriteFrom(iconStream, bufSize, &wrote);
  NS_ASSERTION(bufSize == wrote, 
              "Icon wrote size should be equal to requested write size");

  // Cleanup
  bufferedOutputStream->Close();
  outputStream->Close();
  if (mURLShortcut) {
    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0);
  }
  return rv;
}
示例#28
0
nsresult
CreateFileTask::Work()
{
  class AutoClose
  {
  public:
    explicit AutoClose(nsIOutputStream* aStream)
      : mStream(aStream)
    {
      MOZ_ASSERT(aStream);
    }

    ~AutoClose()
    {
      mStream->Close();
    }
  private:
    nsCOMPtr<nsIOutputStream> mStream;
  };

  MOZ_ASSERT(XRE_IsParentProcess(),
             "Only call from parent process!");
  MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");

  if (mFileSystem->IsShutdown()) {
    return NS_ERROR_FAILURE;
  }

  nsCOMPtr<nsIFile> file = mFileSystem->GetLocalFile(mTargetRealPath);
  if (!file) {
    return NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
  }

  if (!mFileSystem->IsSafeFile(file)) {
    return NS_ERROR_DOM_SECURITY_ERR;
  }

  bool exists = false;
  nsresult rv = file->Exists(&exists);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (exists) {
    bool isFile = false;
    rv = file->IsFile(&isFile);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }

    if (!isFile) {
      return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
    }

    if (!mReplace) {
      return NS_ERROR_DOM_FILESYSTEM_PATH_EXISTS_ERR;
    }

    // Remove the old file before creating.
    rv = file->Remove(false);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }
  }

  rv = file->Create(nsIFile::NORMAL_FILE_TYPE, 0600);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  nsCOMPtr<nsIOutputStream> outputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), file);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  AutoClose acOutputStream(outputStream);

  nsCOMPtr<nsIOutputStream> bufferedOutputStream;
  rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
                                  outputStream,
                                  sOutputBufferSize);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  AutoClose acBufferedOutputStream(bufferedOutputStream);

  if (mBlobStream) {
    // Write the file content from blob data.

    uint64_t bufSize = 0;
    rv = mBlobStream->Available(&bufSize);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }

    while (bufSize && !mFileSystem->IsShutdown()) {
      uint32_t written = 0;
      uint32_t writeSize = bufSize < UINT32_MAX ? bufSize : UINT32_MAX;
      rv = bufferedOutputStream->WriteFrom(mBlobStream, writeSize, &written);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return rv;
      }
      bufSize -= written;
    }

    mBlobStream->Close();
    mBlobStream = nullptr;

    if (mFileSystem->IsShutdown()) {
      return NS_ERROR_FAILURE;
    }

    mTargetBlobImpl = new BlobImplFile(file);
    return NS_OK;
  }

  // Write file content from array data.

  uint32_t written;
  rv = bufferedOutputStream->Write(
    reinterpret_cast<char*>(mArrayData.Elements()),
    mArrayData.Length(),
    &written);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  if (mArrayData.Length() != written) {
    return NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR;
  }

  mTargetBlobImpl = new BlobImplFile(file);
  return NS_OK;
}
示例#29
0
NS_IMETHODIMP AsyncWriteIconToDisk::Run()
{
  NS_PRECONDITION(!NS_IsMainThread(), "Should not be called on the main thread.");

  // Convert the obtained favicon data to an input stream
  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
                                      reinterpret_cast<const char*>(mBuffer.get()), 
                                      mBufferLength,
                                      NS_ASSIGNMENT_DEPEND);
  NS_ENSURE_SUCCESS(rv, rv);

  // Decode the image from the format it was returned to us in (probably PNG)
  nsCOMPtr<imgIContainer> container;
  nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1");
  rv = imgtool->DecodeImageData(stream, mMimeTypeOfInputData, 
                                getter_AddRefs(container));
  NS_ENSURE_SUCCESS(rv, rv);

  // Get the recommended icon width and height, or if failure to obtain 
  // these settings, fall back to 16x16 ICOs.  These values can be different
  // if the user has a different DPI setting other than 100%.
  // Windows would scale the 16x16 icon themselves, but it's better
  // we let our ICO encoder do it.
  PRInt32 systemIconWidth = GetSystemMetrics(SM_CXSMICON);
  PRInt32 systemIconHeight = GetSystemMetrics(SM_CYSMICON);
  if (systemIconWidth == 0 || systemIconHeight == 0) {
    systemIconWidth = 16;
    systemIconHeight = 16;
  }
  // Scale the image to the needed size and in ICO format
  mMimeTypeOfInputData.AssignLiteral("image/vnd.microsoft.icon");
  nsCOMPtr<nsIInputStream> iconStream;
  rv = imgtool->EncodeScaledImage(container, mMimeTypeOfInputData,
                                  systemIconWidth,
                                  systemIconHeight,
                                  EmptyString(),
                                  getter_AddRefs(iconStream));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsILocalFile> icoFile
    = do_CreateInstance("@mozilla.org/file/local;1");
  NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
  rv = icoFile->InitWithPath(mIconPath);

  // Setup the output stream for the ICO file on disk
  nsCOMPtr<nsIOutputStream> outputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), icoFile);
  NS_ENSURE_SUCCESS(rv, rv);

  // Obtain the ICO buffer size from the re-encoded ICO stream
  PRUint32 bufSize;
  rv = iconStream->Available(&bufSize);
  NS_ENSURE_SUCCESS(rv, rv);

  // Setup a buffered output stream from the stream object
  // so that we can simply use WriteFrom with the stream object
  nsCOMPtr<nsIOutputStream> bufferedOutputStream;
  rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
                                  outputStream, bufSize);
  NS_ENSURE_SUCCESS(rv, rv);

  // Write out the icon stream to disk and make sure we wrote everything
  PRUint32 wrote;
  rv = bufferedOutputStream->WriteFrom(iconStream, bufSize, &wrote);
  NS_ASSERTION(bufSize == wrote, "Icon wrote size should be equal to requested write size");

  // Cleanup
  bufferedOutputStream->Close();
  outputStream->Close();
  return rv;
}
示例#30
0
NS_IMETHODIMP AsyncWriteIconToDisk::Run()
{
  NS_PRECONDITION(!NS_IsMainThread(), "Should not be called on the main thread.");

  // Convert the obtained favicon data to an input stream
  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = 
    NS_NewByteInputStream(getter_AddRefs(stream),
                          reinterpret_cast<const char*>(mBuffer.get()),
                          mBufferLength,
                          NS_ASSIGNMENT_DEPEND);
  NS_ENSURE_SUCCESS(rv, rv);

  // Decode the image from the format it was returned to us in (probably PNG)
  nsCOMPtr<imgIContainer> container;
  nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1");
  rv = imgtool->DecodeImageData(stream, mMimeTypeOfInputData, 
                                getter_AddRefs(container));
  NS_ENSURE_SUCCESS(rv, rv);

  // Get the recommended icon width and height, or if failure to obtain 
  // these settings, fall back to 16x16 ICOs.  These values can be different
  // if the user has a different DPI setting other than 100%.
  // Windows would scale the 16x16 icon themselves, but it's better
  // we let our ICO encoder do it.
  nsCOMPtr<nsIInputStream> iconStream;
  if (!mURLShortcut) {
    int32_t systemIconWidth = GetSystemMetrics(SM_CXSMICON);
    int32_t systemIconHeight = GetSystemMetrics(SM_CYSMICON);
    if ((systemIconWidth == 0 || systemIconHeight == 0)) {
      systemIconWidth = 16;
      systemIconHeight = 16;
    }
    // Scale the image to the needed size and in ICO format
    mMimeTypeOfInputData.AssignLiteral("image/vnd.microsoft.icon");
    rv = imgtool->EncodeScaledImage(container, mMimeTypeOfInputData,
                                    systemIconWidth,
                                    systemIconHeight,
                                    EmptyString(),
                                    getter_AddRefs(iconStream));
    } else {
      nsRefPtr<gfxASurface> s;
      rv = container->GetFrame(imgIContainer::FRAME_FIRST, 0, getter_AddRefs(s));
      NS_ENSURE_SUCCESS(rv, rv);

      gfxImageSurface* surface =
        new gfxImageSurface(gfxIntSize(48, 48),
                            gfxImageSurface::ImageFormatARGB32);
      gfxContext context(surface);
      context.SetOperator(gfxContext::OPERATOR_SOURCE);
      context.SetColor(gfxRGBA(1, 1, 1, 1));
      context.Rectangle(gfxRect(0, 0, 48, 48));
      context.Fill();

      context.Translate(gfxPoint(16, 16));
      context.SetOperator(gfxContext::OPERATOR_OVER);
      context.DrawSurface(s,  gfxSize(16, 16));
      gfxIntSize size = surface->GetSize();

      nsRefPtr<imgIEncoder> encoder = 
        do_CreateInstance("@mozilla.org/image/encoder;2?"
                          "type=image/vnd.microsoft.icon");
      NS_ENSURE_TRUE(encoder, NS_ERROR_FAILURE);
      rv = encoder->InitFromData(surface->Data(), surface->Stride() * size.height,
                            size.width, size.height, surface->Stride(),
                            imgIEncoder::INPUT_FORMAT_HOSTARGB, EmptyString());
      NS_ENSURE_SUCCESS(rv, rv);
      CallQueryInterface(encoder.get(), getter_AddRefs(iconStream));
      if (!iconStream) {
        return NS_ERROR_FAILURE;
      }
  }

  NS_ENSURE_SUCCESS(rv, rv);
  nsCOMPtr<nsIFile> icoFile
    = do_CreateInstance("@mozilla.org/file/local;1");
  NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
  rv = icoFile->InitWithPath(mIconPath);

  // Setup the output stream for the ICO file on disk
  nsCOMPtr<nsIOutputStream> outputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), icoFile);
  NS_ENSURE_SUCCESS(rv, rv);

  // Obtain the ICO buffer size from the re-encoded ICO stream
  uint64_t bufSize64;
  rv = iconStream->Available(&bufSize64);
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_TRUE(bufSize64 <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);

  uint32_t bufSize = (uint32_t)bufSize64;

  // Setup a buffered output stream from the stream object
  // so that we can simply use WriteFrom with the stream object
  nsCOMPtr<nsIOutputStream> bufferedOutputStream;
  rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
                                  outputStream, bufSize);
  NS_ENSURE_SUCCESS(rv, rv);

  // Write out the icon stream to disk and make sure we wrote everything
  uint32_t wrote;
  rv = bufferedOutputStream->WriteFrom(iconStream, bufSize, &wrote);
  NS_ASSERTION(bufSize == wrote, 
              "Icon wrote size should be equal to requested write size");

  // Cleanup
  bufferedOutputStream->Close();
  outputStream->Close();
  if (mURLShortcut) {
    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0);
  }
  return rv;
}