Prioritize data-sniffing over extension-sniffing for ftp and http. Bug

177026, r=rpotts, sr=darin
This commit is contained in:
bzbarsky%mit.edu 2002-11-06 22:29:17 +00:00
Родитель 6892e100cf
Коммит 74a9b1ed3e
8 изменённых файлов: 151 добавлений и 128 удалений

Просмотреть файл

@ -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 )