bool nsUnknownDecoder::SniffURI(nsIRequest* aRequest) { nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1")); if (mimeService) { nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); if (channel) { nsCOMPtr<nsIURI> uri; nsresult result = channel->GetURI(getter_AddRefs(uri)); if (NS_SUCCEEDED(result) && uri) { nsAutoCString type; result = mimeService->GetTypeFromURI(uri, type); if (NS_SUCCEEDED(result)) { mContentType = type; return true; } } } } return false; }
/* This function is copied almost verbatim from * * mozilla/xpfe/communicator/resources/content/contentAreaUtils.js * * It is designed to get the most appropriate file extension * for a saved file. */ NS_IMETHODIMP HeaderSniffer::GetDefaultExtension (const GulCString &aFilename, const GulCString &aContentType, PRBool get_text_mime, GulCString &_retval) { nsresult rv; GulCString scheme; mFinalURL->GetScheme (scheme); /* Don't return default extensions for random files, or ftp */ if (aContentType.Equals ("application/octet-stream") || scheme.Equals ("ftp")) { return NS_OK; } /* Unless asked, don't return one for text/plain, it is the * web server's default mime type */ if (!get_text_mime && aContentType.Equals ("text/plain")) { return NS_OK; } /* First, extact the current extension from the filename */ nsCOMPtr<nsIURL> url (do_CreateInstance(NS_STANDARDURL_CONTRACTID)); url->SetFilePath( aFilename ); GulCString extension; url->GetFileExtension( extension ); /* See if this is an appropriate extension for this mime * type, this mirros some code in mozilla's * nsExternalHelperAppService::DoContent */ nsCOMPtr<nsIMIMEService> mimeService (do_GetService(NS_MIMESERVICE_CONTRACTID)); nsCOMPtr<nsIMIMEInfo> mimeInfo; mimeService->GetFromTypeAndExtension (aContentType, extension, getter_AddRefs (mimeInfo)); if (extension.Length() && mimeInfo) { PRBool exists = PR_FALSE; mimeInfo->ExtensionExists (extension, &exists); if (exists) { _retval = extension; return NS_OK; } } /* If that didn't work, try the URI */ url = do_QueryInterface (mFinalURL); GulCString urlExtension; if (url) { url->GetFileExtension (urlExtension); } if (urlExtension.Length() && mimeInfo) { PRBool exists = PR_FALSE; mimeInfo->ExtensionExists (urlExtension, &exists); if (exists) { _retval = urlExtension; return NS_OK; } } /* Well, that didn't work, so just return the * primary extension if the mime type has one */ if( mimeInfo ) { rv = mimeInfo->GetPrimaryExtension (_retval); if (NS_SUCCEEDED (rv)) { return NS_OK; } } _retval = extension.Length() ? extension : urlExtension; return NS_OK; }
NS_IMETHODIMP HeaderSniffer::OnStopRequest (nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode) { nsresult rv; LOG ("HeaderSniffer::OnStopRequest"); if (aStatusCode != NS_BINDING_SUCCEEDED) { GtkWidget *parent, *dialog; parent = galeon_embed_persist_get_fc_parent (mEmbedPersist); dialog = hig_alert_new (parent ? GTK_WINDOW (parent) : NULL, GTK_DIALOG_DESTROY_WITH_PARENT, HIG_ALERT_ERROR, _("Unable to save link."), _("The web page might have been removed " "or had its name changed."), GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); g_signal_connect (dialog, "response", (GCallback)gtk_widget_destroy, NULL); gtk_widget_show (dialog); return NS_OK; } nsCOMPtr<nsIURIChecker> checker = do_QueryInterface (aRequest); NS_ENSURE_TRUE (checker, NS_ERROR_FAILURE); nsCOMPtr<nsIChannel> channel; checker->GetBaseChannel (getter_AddRefs(channel)); NS_ENSURE_TRUE (channel, NS_ERROR_FAILURE); /* Get the final URL of the request */ channel->GetURI (getter_AddRefs(mFinalURL)); /* Get the Content-Disposition header, it might give us a * hint on the filename */ nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); GulCString contentDisposition; if (httpChannel) { httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-disposition"), contentDisposition); } /* Get the document encoding */ nsCOMPtr<nsIEncodedChannel> encodedChannel(do_QueryInterface(channel)); GulCString contentEncoding; if (encodedChannel) { nsCOMPtr<nsIUTF8StringEnumerator> enumerator; encodedChannel->GetContentEncodings (getter_AddRefs (enumerator)); if (enumerator) { PRBool more = PR_FALSE; enumerator->HasMore (&more); if (more) { enumerator->GetNext (contentEncoding); } } } /* Get the Content-Type header */ GulCString contentType; channel->GetContentType(contentType); if (contentType.Equals ("application/x-unknown-content-type")) { contentType = ""; } /* If no Content-Type, try and get it from the document */ if (contentType.IsEmpty() && mDocument) { nsCOMPtr<nsIDOMNSDocument> doc = do_QueryInterface(mDocument); if (doc) { GulString type; doc->GetContentType (type); contentType = type; } } /* Failing that, guess from the url */ if (contentType.IsEmpty()) { nsCOMPtr<nsIMIMEService> mimeService (do_GetService(NS_MIMESERVICE_CONTRACTID)); mimeService->GetTypeFromURI (mFinalURL, contentType); } /* Calculate whether we whould decode */ mShouldDecode = PR_FALSE; if (contentEncoding.Length ()) { nsCOMPtr<nsIExternalHelperAppService> helperService = do_GetService (NS_EXTERNALHELPERAPPSERVICE_CONTRACTID); nsCOMPtr<nsIURL> resultURL = do_QueryInterface (mFinalURL); if (resultURL) { GulCString extension; resultURL->GetFileExtension (extension); rv = helperService->ApplyDecodingForExtension (extension, contentEncoding, &mShouldDecode); if (NS_FAILED (rv)) { mShouldDecode = PR_FALSE; } } } if (!mDocument && !mShouldDecode && contentEncoding.Length()) { // The data is encoded, we are not going to decode it, // and this is not a document save so just set our // content type to correspond to the outermost // encoding so we get extensions and the like right. contentType = contentEncoding; } GulCString filename; rv = GetFilename (contentDisposition, contentType, filename); NS_ENSURE_TRUE (NS_SUCCEEDED (rv), NS_ERROR_FAILURE); PerformSave (filename); return NS_OK; }
nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, PRBool nonBlocking) { nsXPIDLCString contentType; nsCAutoString filePath; nsCAutoString fileExtension; nsCOMPtr<nsIFile> localFile; // File we want an icon for PRUint32 desiredImageSize; nsresult rv = ExtractIconInfoFromUrl(getter_AddRefs(localFile), &desiredImageSize, contentType, fileExtension); NS_ENSURE_SUCCESS(rv, rv); PRUint32 iconSize = 16; if (desiredImageSize > 16) iconSize = 32; PRUint32 alphaBytesPerRow = (iconSize / 8); if (iconSize % 32 != 0) alphaBytesPerRow = ((iconSize / 32) + 1) * 4; PRBool fileExists = PR_FALSE; if (localFile) { localFile->GetNativePath(filePath); localFile->Exists(&fileExists); } // Get the native icon. // 1) If it is for an actual local file, BNodeInfo::GetTrackerIcon. // 2) If the local file does not exist, use the content type // and BMimeType::GetIcon BBitmap nativeIcon(BRect(0, 0, iconSize - 1, iconSize - 1), B_CMAP8); if (!nativeIcon.IsValid()) return NS_ERROR_OUT_OF_MEMORY; PRBool gotBitmap = PR_FALSE; if (fileExists) { BNode localNode(filePath.get()); // BeOS doesn't MIME type foreign files immediately - // If there is no type attribute then we can force an identify if (localNode.ReadAttr("BEOS:TYPE", B_STRING_TYPE, 0, NULL, 0) != B_OK) update_mime_info(filePath.get(), 0, 1, 1); BNodeInfo localNodeInfo(&localNode); if (iconSize == 16) { if (localNodeInfo.GetTrackerIcon(&nativeIcon, B_MINI_ICON) == B_OK) gotBitmap = PR_TRUE; } else { if (localNodeInfo.GetTrackerIcon(&nativeIcon, B_LARGE_ICON) == B_OK) gotBitmap = PR_TRUE; } } // If we haven't got a bitmap yet, use the content type if (!gotBitmap) { // If no content type specified, use mozilla's mime service to guess a mime type if (contentType.IsEmpty()) { nsCOMPtr<nsIMIMEService> mimeService (do_GetService("@mozilla.org/mime;1", &rv)); if (NS_SUCCEEDED(rv)) mimeService->GetTypeFromExtension(fileExtension, contentType); // If unrecognised extension - set to generic file if (contentType.IsEmpty()) contentType = "application/octet-stream"; } // Create BeOS-Native MIME type info - if unheard of, set to generic file BMimeType mimeType(contentType.get()); if (!mimeType.IsInstalled()) mimeType.SetTo("application/octet-stream"); if (iconSize == 16) { if (mimeType.GetIcon(&nativeIcon, B_MINI_ICON) == B_OK) gotBitmap = PR_TRUE; } else { if (mimeType.GetIcon(&nativeIcon, B_LARGE_ICON) == B_OK) gotBitmap = PR_TRUE; } } if (!gotBitmap) return NS_ERROR_NOT_AVAILABLE; BScreen mainScreen(B_MAIN_SCREEN_ID); if (!mainScreen.IsValid()) return NS_ERROR_NOT_AVAILABLE; // Got a bitmap and color space info - convert data to mozilla's icon format PRUint32 iconLength = 2 + iconSize * iconSize * 4; uint8 *buffer = new uint8[iconLength]; if (!buffer) return NS_ERROR_OUT_OF_MEMORY; uint8* destByte = buffer; *(destByte++) = iconSize; *(destByte++) = iconSize; // RGB data uint8* sourceByte = (uint8*)nativeIcon.Bits(); for(PRUint32 iconRow = 0; iconRow < iconSize; iconRow++) { sourceByte = (uint8*)nativeIcon.Bits() + nativeIcon.BytesPerRow() * iconRow; for(PRUint32 iconCol = 0; iconCol < iconSize; iconCol++) { if (*sourceByte != B_TRANSPARENT_MAGIC_CMAP8) { rgb_color colorVal = mainScreen.ColorForIndex(*sourceByte); #ifdef IS_LITTLE_ENDIAN *(destByte++) = colorVal.blue; *(destByte++) = colorVal.green; *(destByte++) = colorVal.red; *(destByte++) = uint8(255); #else *(destByte++) = uint8(255); *(destByte++) = colorVal.red; *(destByte++) = colorVal.green; *(destByte++) = colorVal.blue; #endif } else { *destByte++ = 0; *destByte++ = 0; *destByte++ = 0; *destByte++ = 0; } // original code had a conditional here: // if (iconCol < iconSize - 1) // Leaving this comment in case complications arise later sourceByte++; } } NS_ASSERTION(buffer + iconLength == destByte, "size miscalculation"); // Now, create a pipe and stuff our data into it nsCOMPtr<nsIInputStream> inStream; nsCOMPtr<nsIOutputStream> outStream; rv = NS_NewPipe(getter_AddRefs(inStream), getter_AddRefs(outStream), iconLength, iconLength, nonBlocking); if (NS_SUCCEEDED(rv)) { PRUint32 written; rv = outStream->Write((char*)buffer, iconLength, &written); if (NS_SUCCEEDED(rv)) NS_ADDREF(*_retval = inStream); } delete [] buffer; return rv; }