PRBool			tempDirty = PR_FALSE; nsCOMPtr<nsIRDFLiteral>	newValue; if (lastModValue.Length() > 0)
PRUnichar	*uniBuf = nsnull; if (NS_FAILED(rv = context->GetBuffer(&uniBuf)))	return(rv); if (!uniBuf)	return(NS_ERROR_UNEXPECTED);  nsAutoString	htmlResults(uniBuf);  if (htmlResults.Length() < 1) { #ifdef	DEBUG_SEARCH_OUTPUT printf(" *** InternetSearchDataSourceCallback::OnStopRequest:  no data.\n\n"); #endif return(NS_OK); }  if (NS_FAILED(rv = context->Truncate()))	return(rv);  if (mParent) {  const PRUnichar	*htmlUni = htmlResults.GetUnicode(); if (htmlUni)
InternetSearchDataSource::OnStopRequest(nsIChannel* channel, nsISupports *ctxt,					nsresult status, const PRUnichar *errorMsg) {	if (!mInner)	return(NS_OK);	nsCOMPtr<nsIInternetSearchContext>	context = do_QueryInterface(ctxt);	if (!ctxt)	return(NS_ERROR_NO_INTERFACE);	nsresult	rv;	PRUint32	contextType = 0;	if (NS_FAILED(rv = context->GetContextType(&contextType)))		return(rv);	if (contextType == nsIInternetSearchContext::WEB_SEARCH_CONTEXT)	{		// continue to process nsIInternetSearchContext::WEB_SEARCH_CONTEXT		rv = webSearchFinalize(channel, context);	}	else if (contextType == nsIInternetSearchContext::ENGINE_DOWNLOAD_CONTEXT ||		 contextType == nsIInternetSearchContext::ICON_DOWNLOAD_CONTEXT)	{		nsCOMPtr<nsIHTTPChannel>	httpChannel = do_QueryInterface(channel);		if (!httpChannel)	return(NS_ERROR_UNEXPECTED);		// check HTTP status to ensure success		PRUint32	httpStatus = 0;		if (NS_SUCCEEDED(rv = httpChannel->GetResponseStatus(&httpStatus)) &&			(httpStatus == 200))		{			rv = saveContents(channel, context, contextType);		}	}	else if (contextType == nsIInternetSearchContext::ENGINE_UPDATE_CONTEXT)	{		nsCOMPtr<nsIRDFResource>	theEngine;		if (NS_FAILED(rv = context->GetEngine(getter_AddRefs(theEngine))))	return(rv);		if (!theEngine)	return(NS_ERROR_NO_INTERFACE);#ifdef	DEBUG_SEARCH_UPDATES		const char	*engineURI = nsnull;		theEngine->GetValueConst(&engineURI);#endif		// free up "busy" info now & mark as non-busy		busySchedule = PR_FALSE;		busyResource = nsnull;		// we only have HTTP "HEAD" information when doing updates		nsCOMPtr<nsIHTTPChannel>	httpChannel = do_QueryInterface(channel);		if (!httpChannel)	return(NS_ERROR_UNEXPECTED);		// check HTTP status to ensure success		PRUint32	httpStatus = 0;		if (NS_FAILED(rv = httpChannel->GetResponseStatus(&httpStatus)))			return(rv);		if (httpStatus != 200)	return(NS_ERROR_UNEXPECTED);		// get last-modified & content-length info		nsCAutoString			lastModValue, contentLengthValue;		nsCOMPtr<nsISimpleEnumerator>	enumerator;		if (NS_FAILED(rv = httpChannel->GetResponseHeaderEnumerator(getter_AddRefs(enumerator))))			return(rv);		PRBool			bMoreHeaders;		while (NS_SUCCEEDED(rv = enumerator->HasMoreElements(&bMoreHeaders))			&& (bMoreHeaders == PR_TRUE))		{			nsCOMPtr<nsISupports>   item;			enumerator->GetNext(getter_AddRefs(item));			nsCOMPtr<nsIHTTPHeader>	header = do_QueryInterface(item);			NS_ASSERTION(header, "InternetSearchDataSource::OnStopRequest - Bad HTTP header.");			if (!header)	return(NS_ERROR_UNEXPECTED);			nsCOMPtr<nsIAtom>       headerAtom;			header->GetField(getter_AddRefs(headerAtom));			nsAutoString		headerStr;			headerAtom->ToString(headerStr);			char	*val = nsnull;						if (headerStr.EqualsIgnoreCase("Last-Modified"))			{				header->GetValue(&val);				if (val)				{#ifdef	DEBUG_SEARCH_UPDATES				    PRINTF("    Search engine='%s' Last-Modified='%s'\n", engineURI, val);#endif					lastModValue = val;					nsCRT::free(val);				}			}			else if (headerStr.EqualsIgnoreCase("Content-Length"))			{				header->GetValue(&val);				if (val)				{#ifdef	DEBUG_SEARCH_UPDATES				    PRINTF("    Search engine='%s' Content-Length='%s'\n", engineURI, val);#endif					contentLengthValue = val;					nsCRT::free(val);				}			}		}		// should we fetch the entire file?		PRBool		updateSearchEngineFile = PR_FALSE;		// save out new search engine state data into localstore		PRBool			tempDirty = PR_FALSE;		nsCOMPtr<nsIRDFLiteral>	newValue;		if (lastModValue.Length() > 0)		{			gRDFService->GetLiteral(NS_ConvertASCIItoUCS2(lastModValue).GetUnicode(),				getter_AddRefs(newValue));			if (newValue)			{				updateAtom(mLocalstore, theEngine, kWEB_LastPingModDate, newValue,					&tempDirty);				if (tempDirty == PR_TRUE)	updateSearchEngineFile = PR_TRUE;			}		}		if (contentLengthValue.Length() > 0)		{			gRDFService->GetLiteral(NS_ConvertASCIItoUCS2(contentLengthValue).GetUnicode(),				getter_AddRefs(newValue));			if (newValue)			{				updateAtom(mLocalstore, theEngine, kWEB_LastPingContentLen, newValue,					&tempDirty);				if (tempDirty == PR_TRUE)				{					updateSearchEngineFile = PR_TRUE;				}				else				{					// worst case: compare local data size vs. remote content size					nsCOMPtr<nsIRDFLiteral>	dataLit;					if (NS_SUCCEEDED(rv = FindData(theEngine, getter_AddRefs(dataLit))) &&						(rv != NS_RDF_NO_VALUE))					{						const PRUnichar	*dataUni = nsnull;						dataLit->GetValueConst(&dataUni);						nsAutoString	dataStr(dataUni);						PRInt32		dataLen=dataStr.Length();#ifdef	DEBUG_SEARCH_UPDATES						PRINTF("    Search engine='%s' data length='%d'\n", engineURI, dataLen);#endif						PRInt32	contentLen=0, err=0;						contentLen = contentLengthValue.ToInteger(&err);						if ((!err) && (dataLen != contentLen))						{#ifdef	DEBUG_SEARCH_UPDATES							PRINTF("    Search engine '%s' data length != remote content length, so update\n",							       engineURI, dataLen);#endif							updateSearchEngineFile = PR_TRUE;						}					}				}			}		}		// mark now as the last time we stat'ted the search engine		validateEngineNow(theEngine);		if (updateSearchEngineFile == PR_TRUE)		{#ifdef	DEBUG_SEARCH_UPDATES		    PRINTF("    Search engine='%s' needs updating, so fetching it\n", engineURI);#endif			// get update URL			nsCString		updateURL;			nsCOMPtr<nsIRDFNode>	aNode;			if (NS_SUCCEEDED(rv = mInner->GetTarget(theEngine, kNC_Update, PR_TRUE, getter_AddRefs(aNode)))				&& (rv != NS_RDF_NO_VALUE))			{				nsCOMPtr<nsIRDFLiteral>	aLiteral = do_QueryInterface(aNode);				if (aLiteral)				{					const PRUnichar	*updateUni = nsnull;					aLiteral->GetValueConst(&updateUni);					if (updateUni)					{						updateURL.AssignWithConversion(updateUni);					}				}			}			// get update icon			nsCString		updateIconURL;			if (NS_SUCCEEDED(rv = mInner->GetTarget(theEngine, kNC_UpdateIcon, PR_TRUE, getter_AddRefs(aNode)))				&& (rv != NS_RDF_NO_VALUE))			{				nsCOMPtr<nsIRDFLiteral>	aIconLiteral = do_QueryInterface(aNode);				if (aIconLiteral)				{					const PRUnichar	*updateIconUni = nsnull;					aIconLiteral->GetValueConst(&updateIconUni);					if (updateIconUni)					{						updateIconURL.AssignWithConversion(updateIconUni);					}				}			}			// download it!			AddSearchEngine(updateURL, updateIconURL, nsnull, nsnull);		}		else		{#ifdef	DEBUG_SEARCH_UPDATES		    PRINTF("    Search engine='%s' is current and requires no updating\n", engineURI);#endif		}	}	else	{		rv = NS_ERROR_UNEXPECTED;	}	return(rv);}