nsresult nsFileChannel::MakeFileInputStream(nsIFile *file, nsCOMPtr<nsIInputStream> &stream, nsCString &contentType) { // we accept that this might result in a disk hit to stat the file bool isDir; nsresult rv = file->IsDirectory(&isDir); if (NS_FAILED(rv)) { // canonicalize error message if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) rv = NS_ERROR_FILE_NOT_FOUND; return rv; } if (isDir) { rv = nsDirectoryIndexStream::Create(file, getter_AddRefs(stream)); if (NS_SUCCEEDED(rv) && !HasContentTypeHint()) contentType.AssignLiteral(APPLICATION_HTTP_INDEX_FORMAT); } else { rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file); if (NS_SUCCEEDED(rv) && !HasContentTypeHint()) { // Use file extension to infer content type nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1", &rv); if (NS_SUCCEEDED(rv)) { mime->GetTypeFromFile(file, contentType); } } } return rv; }
nsresult nsFileChannel::MakeFileInputStream(nsIFile *file, nsCOMPtr<nsIInputStream> &stream, nsCString &contentType, bool async) { // we accept that this might result in a disk hit to stat the file bool isDir; nsresult rv = file->IsDirectory(&isDir); if (NS_FAILED(rv)) { // canonicalize error message if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) rv = NS_ERROR_FILE_NOT_FOUND; if (async && (NS_ERROR_FILE_NOT_FOUND == rv)) { // We don't return "Not Found" errors here. Since we could not find // the file, it's not a directory anyway. isDir = false; } else { return rv; } } if (isDir) { rv = nsDirectoryIndexStream::Create(file, getter_AddRefs(stream)); if (NS_SUCCEEDED(rv) && !HasContentTypeHint()) contentType.AssignLiteral(APPLICATION_HTTP_INDEX_FORMAT); } else { rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file, -1, -1, async? nsIFileInputStream::DEFER_OPEN : 0); if (NS_SUCCEEDED(rv) && !HasContentTypeHint()) { // Use file extension to infer content type nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1", &rv); if (NS_SUCCEEDED(rv)) { mime->GetTypeFromFile(file, contentType); } } } return rv; }
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; }