зеркало из https://github.com/mozilla/gecko-dev.git
Prioritize data-sniffing over extension-sniffing for ftp and http. Bug
177026, r=rpotts, sr=darin
This commit is contained in:
Родитель
6892e100cf
Коммит
74a9b1ed3e
|
@ -39,6 +39,7 @@ REQUIRES = xpcom \
|
|||
unicharutil \
|
||||
js \
|
||||
necko \
|
||||
mimetype \
|
||||
webshell \
|
||||
xul \
|
||||
htmlparser \
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "nsIConsoleService.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsMimeTypes.h"
|
||||
|
||||
#ifdef INCLUDE_XUL
|
||||
#include "nsIXULPrototypeCache.h"
|
||||
|
@ -969,12 +970,13 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
|||
if (channel) {
|
||||
channel->GetContentType(contentType);
|
||||
}
|
||||
if (mLoader->mCompatMode == eCompatibility_NavQuirks ||
|
||||
contentType.Equals(NS_LITERAL_CSTRING("text/css")) ||
|
||||
contentType.IsEmpty()) {
|
||||
|
||||
if (!contentType.IsEmpty() &&
|
||||
contentType != NS_LITERAL_CSTRING("text/css")) {
|
||||
|
||||
PRBool validType = contentType.Equals(NS_LITERAL_CSTRING("text/css")) ||
|
||||
contentType.Equals(NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE)) ||
|
||||
contentType.IsEmpty();
|
||||
|
||||
if (mLoader->mCompatMode == eCompatibility_NavQuirks || validType) {
|
||||
if (!validType) {
|
||||
nsCAutoString spec;
|
||||
if (channel) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "nsIConsoleService.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsMimeTypes.h"
|
||||
|
||||
#ifdef INCLUDE_XUL
|
||||
#include "nsIXULPrototypeCache.h"
|
||||
|
@ -969,12 +970,13 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader,
|
|||
if (channel) {
|
||||
channel->GetContentType(contentType);
|
||||
}
|
||||
if (mLoader->mCompatMode == eCompatibility_NavQuirks ||
|
||||
contentType.Equals(NS_LITERAL_CSTRING("text/css")) ||
|
||||
contentType.IsEmpty()) {
|
||||
|
||||
if (!contentType.IsEmpty() &&
|
||||
contentType != NS_LITERAL_CSTRING("text/css")) {
|
||||
|
||||
PRBool validType = contentType.Equals(NS_LITERAL_CSTRING("text/css")) ||
|
||||
contentType.Equals(NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE)) ||
|
||||
contentType.IsEmpty();
|
||||
|
||||
if (mLoader->mCompatMode == eCompatibility_NavQuirks || validType) {
|
||||
if (!validType) {
|
||||
nsCAutoString spec;
|
||||
if (channel) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
|
|
|
@ -39,13 +39,13 @@
|
|||
#include "nsFTPChannel.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "nsIMIMEService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIProxyObjectManager.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
extern PRLogModuleInfo* gFTPLog;
|
||||
|
@ -410,22 +410,13 @@ nsFTPChannel::GetContentType(nsACString &aContentType)
|
|||
{
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
aContentType.Truncate();
|
||||
if (mContentType.IsEmpty()) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMIMEService> MIMEService (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsXPIDLCString mimeType;
|
||||
rv = MIMEService->GetTypeFromURI(mURL, getter_Copies(mimeType));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mContentType = mimeType;
|
||||
else
|
||||
mContentType = NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE);
|
||||
aContentType = NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE);
|
||||
} else {
|
||||
aContentType = mContentType;
|
||||
}
|
||||
|
||||
aContentType = mContentType;
|
||||
|
||||
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::GetContentType() returned %s\n", mContentType.get()));
|
||||
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::GetContentType() returned %s\n", PromiseFlatCString(aContentType).get()));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -676,6 +667,24 @@ nsFTPChannel::OnStartRequest(nsIRequest *request, nsISupports *aContext)
|
|||
|
||||
nsresult rv = NS_OK;
|
||||
if (mListener) {
|
||||
if (mContentType.IsEmpty()) {
|
||||
// Time to sniff!
|
||||
nsCOMPtr<nsIStreamConverterService> serv =
|
||||
do_GetService("@mozilla.org/streamConverters;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ConvertASCIItoUCS2 from(UNKNOWN_CONTENT_TYPE);
|
||||
nsCOMPtr<nsIStreamListener> converter;
|
||||
rv = serv->AsyncConvertData(from.get(),
|
||||
NS_LITERAL_STRING("*/*").get(),
|
||||
mListener,
|
||||
mUserContext,
|
||||
getter_AddRefs(converter));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mListener = converter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = mListener->OnStartRequest(this, mUserContext);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIIDNService.h"
|
||||
#include "nsIStreamListenerTee.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "nsCPasswordManager.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
@ -554,6 +553,42 @@ nsHttpChannel::ApplyContentConversions()
|
|||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpChannel::CallOnStartRequest()
|
||||
{
|
||||
if (mResponseHead && mResponseHead->ContentType().IsEmpty()) {
|
||||
// Uh-oh. We had better find out what type we are!
|
||||
|
||||
// XXX This does not work with content-encodings... but
|
||||
// neither does applying the conversion from the URILoader
|
||||
|
||||
nsCOMPtr<nsIStreamConverterService> serv;
|
||||
nsresult rv = nsHttpHandler::get()->
|
||||
GetStreamConverterService(getter_AddRefs(serv));
|
||||
// If we failed, we just fall through to the "normal" case
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ConvertASCIItoUCS2 from(UNKNOWN_CONTENT_TYPE);
|
||||
nsCOMPtr<nsIStreamListener> converter;
|
||||
rv = serv->AsyncConvertData(from.get(),
|
||||
NS_LITERAL_STRING("*/*").get(),
|
||||
mListener,
|
||||
mListenerContext,
|
||||
getter_AddRefs(converter));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mListener = converter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = mListener->OnStartRequest(this, mListenerContext);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// install stream converter if required
|
||||
ApplyContentConversions();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpChannel::ProcessResponse()
|
||||
{
|
||||
|
@ -670,12 +705,9 @@ nsHttpChannel::ProcessNormal()
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
rv = mListener->OnStartRequest(this, mListenerContext);
|
||||
rv = CallOnStartRequest();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// install stream converter if required
|
||||
ApplyContentConversions();
|
||||
|
||||
// install cache listener if we still have a cache entry open
|
||||
if (mCacheEntry)
|
||||
rv = InstallCacheListener();
|
||||
|
@ -2305,61 +2337,22 @@ nsHttpChannel::GetSecurityInfo(nsISupports **securityInfo)
|
|||
NS_IMETHODIMP
|
||||
nsHttpChannel::GetContentType(nsACString &value)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!mResponseHead) {
|
||||
// We got no data, we got no headers, we got nothing
|
||||
value.Truncate();
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
value.Truncate();
|
||||
|
||||
if (mResponseHead && !mResponseHead->ContentType().IsEmpty()) {
|
||||
if (!mResponseHead->ContentType().IsEmpty()) {
|
||||
value = mResponseHead->ContentType();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// else if the there isn't a response yet or if the response does not
|
||||
// contain a content-type header, try to determine the content type
|
||||
// from the file extension of the URI...
|
||||
|
||||
// We had to do this same hack in 4.x. Sometimes, we run an http url that
|
||||
// ends in special extensions like .dll, .exe, etc and the server doesn't
|
||||
// provide a specific content type for the document. In actuality the
|
||||
// document is really text/html (sometimes). For these cases, we don't want
|
||||
// to ask the mime service for the content type because it will make
|
||||
// incorrect conclusions based on the file extension. Instead, set the
|
||||
// content type to unknown and allow our unknown content type decoder a
|
||||
// chance to sniff the data stream and conclude a content type.
|
||||
|
||||
PRBool doMimeLookup = PR_TRUE;
|
||||
nsCOMPtr<nsIURL> url = do_QueryInterface(mURI);
|
||||
if (url) {
|
||||
nsCAutoString ext;
|
||||
url->GetFileExtension(ext);
|
||||
if (!nsCRT::strcasecmp(ext.get(), "dll") ||
|
||||
!nsCRT::strcasecmp(ext.get(), "exe"))
|
||||
doMimeLookup = PR_FALSE;
|
||||
}
|
||||
if (doMimeLookup) {
|
||||
nsCOMPtr<nsIMIMEService> mime;
|
||||
nsHttpHandler::get()->GetMimeService(getter_AddRefs(mime));
|
||||
if (mime) {
|
||||
nsXPIDLCString mimeType;
|
||||
rv = mime->GetTypeFromURI(mURI, getter_Copies(mimeType));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// cache this result if possible
|
||||
if (mResponseHead)
|
||||
mResponseHead->SetContentType(mimeType);
|
||||
value = mimeType;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the content-type can only be set to application/x-unknown-content-type
|
||||
// if there is data from which to infer a content-type.
|
||||
if (!mResponseHead)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
|
||||
value = NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::SetContentType(const nsACString &value)
|
||||
{
|
||||
|
@ -2725,7 +2718,8 @@ nsHttpChannel::SetUploadFile(nsIFile *file, const char* contentType, PRInt32 con
|
|||
if (contentType)
|
||||
return SetUploadStream(stream, contentType, contentLength);
|
||||
|
||||
nsCOMPtr<nsIMIMEService> MIMEService (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));
|
||||
nsCOMPtr<nsIMIMEService> MIMEService;
|
||||
rv = nsHttpHandler::get()->GetMimeService(getter_AddRefs(MIMEService));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsXPIDLCString mimeType;
|
||||
rv = MIMEService->GetTypeFromFile(file, getter_Copies(mimeType));
|
||||
|
@ -2935,13 +2929,7 @@ nsHttpChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// there won't be a response head if we've been cancelled
|
||||
nsresult rv = mListener->OnStartRequest(this, mListenerContext);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// install stream converter if required
|
||||
ApplyContentConversions();
|
||||
return NS_OK;
|
||||
return CallOnStartRequest();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -113,6 +113,7 @@ private:
|
|||
void HandleAsyncNotModified();
|
||||
nsresult SetupTransaction();
|
||||
void ApplyContentConversions();
|
||||
nsresult CallOnStartRequest();
|
||||
nsresult ProcessResponse();
|
||||
nsresult ProcessNormal();
|
||||
nsresult ProcessNotModified();
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#include "nsIPref.h"
|
||||
#include "imgILoader.h"
|
||||
|
||||
#include "nsIMIMEService.h"
|
||||
|
||||
#include "nsIViewSourceChannel.h"
|
||||
|
||||
#include "prcpucfg.h" // To get IS_LITTLE_ENDIAN / IS_BIG_ENDIAN
|
||||
|
@ -325,7 +327,7 @@ void nsUnknownDecoder::DetermineContentType(nsIRequest* request)
|
|||
PRBool isLocalFile = PR_FALSE;
|
||||
if (request) {
|
||||
nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(request);
|
||||
if (!request) { NS_WARNING("QI failed"); return; }
|
||||
if (!aChannel) { NS_WARNING("QI failed"); return; }
|
||||
|
||||
nsCOMPtr<nsIURI> pURL;
|
||||
if (NS_SUCCEEDED(aChannel->GetURI(getter_AddRefs(pURL))))
|
||||
|
@ -376,6 +378,27 @@ void nsUnknownDecoder::DetermineContentType(nsIRequest* request)
|
|||
// we don't need to check for isLocalFile here..
|
||||
SniffForImageMimeType((const char*)mBuffer, mBufferLen);
|
||||
}
|
||||
|
||||
if (mContentType.IsEmpty()) {
|
||||
// We don't know what this is yet. Before we just give up, try
|
||||
// the URI from the request.
|
||||
nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1"));
|
||||
if (mimeService) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
if (channel) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult result = channel->GetURI(getter_AddRefs(uri));
|
||||
if (NS_SUCCEEDED(result) && uri) {
|
||||
nsXPIDLCString type;
|
||||
result = mimeService->GetTypeFromURI(uri, getter_Copies(type));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
mContentType = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// See if the buffer has any embedded nulls. If not, then lets just
|
||||
// call it text/plain...
|
||||
|
|
|
@ -2012,59 +2012,56 @@ NS_IMETHODIMP nsExternalHelperAppService::GetTypeFromExtension(const char *aFile
|
|||
|
||||
NS_IMETHODIMP nsExternalHelperAppService::GetTypeFromURI(nsIURI *aURI, char **aContentType)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
// first try to get a url out of the uri so we can skip post
|
||||
// filename stuff (i.e. query string)
|
||||
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI, &rv);
|
||||
|
||||
#if defined(XP_MAC) || defined (XP_MACOSX)
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsresult rv2;
|
||||
nsCOMPtr<nsIFileURL> fileurl = do_QueryInterface( url, &rv2 );
|
||||
if ( NS_SUCCEEDED ( rv2 ) )
|
||||
{
|
||||
nsCOMPtr <nsIFile> file;
|
||||
rv2 = fileurl->GetFile(getter_AddRefs(file));
|
||||
if (NS_SUCCEEDED(rv2))
|
||||
{
|
||||
rv2 = GetTypeFromFile(file, aContentType);
|
||||
if (NS_SUCCEEDED(rv2))
|
||||
return rv2;
|
||||
NS_PRECONDITION(aContentType, "Null out param!");
|
||||
nsresult rv = NS_ERROR_NOT_AVAILABLE;
|
||||
*aContentType = nsnull;
|
||||
|
||||
// First look for a file to use. If we have one, we just use that.
|
||||
nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(aURI);
|
||||
if (fileUrl) {
|
||||
nsCOMPtr<nsIFile> file;
|
||||
rv = fileUrl->GetFile(getter_AddRefs(file));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = GetTypeFromFile(file, aContentType);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// we got something!
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCAutoString ext;
|
||||
rv = url->GetFileExtension(ext);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (ext.IsEmpty()) {
|
||||
*aContentType = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = GetTypeFromExtension(ext.get(), aContentType);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCAutoString specStr;
|
||||
// Now try to get an nsIURL so we don't have to do our own parsing
|
||||
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
|
||||
if (url) {
|
||||
nsCAutoString ext;
|
||||
rv = url->GetFileExtension(ext);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (ext.IsEmpty()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
return GetTypeFromExtension(ext.get(), aContentType);
|
||||
}
|
||||
|
||||
// no url, let's give the raw spec a shot
|
||||
nsCAutoString specStr;
|
||||
rv = aURI->GetSpec(specStr);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// find the file extension (if any)
|
||||
nsCAutoString extStr;
|
||||
PRInt32 extLoc = specStr.RFindChar('.');
|
||||
if (-1 != extLoc)
|
||||
if (-1 != extLoc &&
|
||||
extLoc != specStr.Length() - 1 &&
|
||||
// nothing over 20 chars long can be sanely considered an
|
||||
// extension.... Dat dere would be just data.
|
||||
specStr.Length() - extLoc < 20)
|
||||
{
|
||||
specStr.Right(extStr, specStr.Length() - extLoc - 1);
|
||||
rv = GetTypeFromExtension(extStr.get(), aContentType);
|
||||
return GetTypeFromExtension(PromiseFlatCString(
|
||||
Substring(specStr, extLoc, specStr.Length() - extLoc - 1)
|
||||
).get(), aContentType);
|
||||
}
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
return rv;
|
||||
|
||||
// We found no information; say so.
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsExternalHelperAppService::GetTypeFromFile( nsIFile* aFile, char **aContentType )
|
||||
|
|
Загрузка…
Ссылка в новой задаче