nsresult	rv; PRUint32	contextType = 0; if (NS_FAILED(rv = context->GetContextType(&contextType)))		return(rv);  if (contextType == 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);   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   busySchedule = PR_FALSE; busyResource = nsnull;   nsCOMPtr<nsIHttpChannel> httpChannel (do_QueryInterface(channel)); if (!httpChannel)	return(NS_ERROR_UNEXPECTED);   PRUint32	httpStatus = 0; if (NS_FAILED(rv = httpChannel->GetResponseStatus(&httpStatus))) return(rv); if (httpStatus != 200)	return(NS_ERROR_UNEXPECTED);   nsCAutoString			lastModValue, contentLengthValue;  if (NS_FAILED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Last-Modified"), lastModValue))) lastModValue.Truncate(); if (NS_FAILED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Length"), contentLengthValue))) contentLengthValue.Truncate();   PRBool		updateSearchEngineFile = PR_FALSE;   PRBool			tempDirty = PR_FALSE; nsCOMPtr<nsIRDFLiteral>	newValue; if (lastModValue.Length() > 0) { gRDFService->GetLiteral(NS_ConvertASCIItoUCS2(lastModValue).get(), 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).get(), getter_AddRefs(newValue)); if (newValue) { updateAtom(mLocalstore, theEngine, kWEB_LastPingContentLen, newValue, &tempDirty); if (tempDirty == PR_TRUE) { updateSearchEngineFile = PR_TRUE; } else {  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))
nsresult			rv; nsCOMPtr<nsIRDFResource>	mParent; if (NS_FAILED(rv = context->GetParent(getter_AddRefs(mParent))))	return(rv); if (!mParent)	return(NS_ERROR_NO_INTERFACE);  nsCOMPtr<nsIRDFResource>	mEngine; if (NS_FAILED(rv = context->GetEngine(getter_AddRefs(mEngine))))	return(rv); if (!mEngine)	return(NS_ERROR_NO_INTERFACE);  nsCOMPtr<nsIURI> aURL; rv = channel->GetURI(getter_AddRefs(aURL)); if (NS_FAILED(rv)) return rv;  nsCOMPtr<nsIRDFLiteral>	trueLiteral; if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(nsAutoString("true").GetUnicode(), getter_AddRefs(trueLiteral)))) { mInner->Unassert(mEngine, kNC_loading, trueLiteral);  if (mConnections) { PRUint32	count=0; mConnections->Count(&count); if (count <= 1) { mInner->Unassert(mParent, kNC_loading, trueLiteral); } } }   nsCOMPtr<nsIRDFNode>		engineIconStatusNode = nsnull; mInner->GetTarget(mEngine, kNC_Icon, PR_TRUE, getter_AddRefs(engineIconStatusNode)); if (engineIconStatusNode) { rv = mInner->Assert(mEngine, kNC_StatusIcon, engineIconStatusNode, PR_TRUE); }  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);   const PRUnichar	*htmlUni = htmlResults.GetUnicode(); if (htmlUni) { nsCOMPtr<nsIRDFLiteral>	htmlLiteral; if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(htmlUni, getter_AddRefs(htmlLiteral)))) { rv = mInner->Assert(mEngine, kNC_HTML, htmlLiteral, PR_TRUE); } }   nsAutoString		data(""); nsCOMPtr<nsIRDFNode>	dataNode; if (NS_FAILED(rv = mInner->GetTarget(mEngine, kNC_Data, PR_TRUE, getter_AddRefs(dataNode)))) { return(rv); } nsCOMPtr<nsIRDFLiteral>	dataLiteral = do_QueryInterface(dataNode); if (!dataLiteral)	return(NS_ERROR_NULL_POINTER);  PRUnichar	*dataUni = nsnull; if (NS_FAILED(rv = dataLiteral->GetValue(&dataUni))) return(rv); if (!dataUni)	return(NS_ERROR_NULL_POINTER); data = dataUni; if (data.Length() < 1) return(rv);  nsAutoString	resultListStartStr(""), resultListEndStr(""); nsAutoString	resultItemStartStr(""), resultItemEndStr(""); nsAutoString	relevanceStartStr(""), relevanceEndStr(""); nsAutoString	bannerStartStr(""), bannerEndStr(""), skiplocalStr(""); PRBool		skipLocalFlag = PR_FALSE;  InternetSearchDataSource::GetData(data, "interpret", "resultListStart", resultListStartStr); InternetSearchDataSource::GetData(data, "interpret", "resultListEnd", resultListEndStr); InternetSearchDataSource::GetData(data, "interpret", "resultItemStart", resultItemStartStr); InternetSearchDataSource::GetData(data, "interpret", "resultItemEnd", resultItemEndStr); InternetSearchDataSource::GetData(data, "interpret", "relevanceStart", relevanceStartStr); InternetSearchDataSource::GetData(data, "interpret", "relevanceEnd", relevanceEndStr); InternetSearchDataSource::GetData(data, "interpret", "bannerStart", bannerStartStr); InternetSearchDataSource::GetData(data, "interpret", "bannerEnd", bannerEndStr); InternetSearchDataSource::GetData(data, "interpret", "skiplocal", skiplocalStr); if (skiplocalStr.EqualsIgnoreCase("true")) { skipLocalFlag = PR_TRUE; }  #ifdef	DEBUG_SEARCH_OUTPUT char *cStr; cStr = resultListStartStr.ToNewCString(); if (cStr) { printf("resultListStart: '%s'\n", cStr); nsCRT::free(cStr); cStr = nsnull; } cStr = resultListEndStr.ToNewCString(); if (cStr) { printf("resultListEnd: '%s'\n", cStr); nsCRT::free(cStr); cStr = nsnull; } cStr = resultItemStartStr.ToNewCString(); if (cStr) { printf("resultItemStart: '%s'\n", cStr); nsCRT::free(cStr); cStr = nsnull; } cStr = resultItemEndStr.ToNewCString(); if (cStr) { printf("resultItemEnd: '%s'\n", cStr); nsCRT::free(cStr); cStr = nsnull; } cStr = relevanceStartStr.ToNewCString(); if (cStr) { printf("relevanceStart: '%s'\n", cStr); nsCRT::free(cStr); cStr = nsnull; } cStr = relevanceEndStr.ToNewCString(); if (cStr) { printf("relevanceEnd: '%s'\n", cStr); nsCRT::free(cStr); cStr = nsnull; } #endif   nsAutoString	serverPathStr; char *serverPath = nsnull; aURL->GetPath(&serverPath); if (serverPath) { serverPathStr = serverPath; nsCRT::free(serverPath); serverPath = nsnull;  PRInt32 serverOptionsOffset = serverPathStr.FindChar(PRUnichar('?')); if (serverOptionsOffset >= 0)	serverPathStr.Truncate(serverOptionsOffset); }   nsCOMPtr<nsIRDFLiteral>	bannerLiteral; if ((bannerStartStr.Length() > 0) && (bannerEndStr.Length() > 0)) { PRInt32	bannerStart = htmlResults.Find(bannerStartStr, PR_TRUE); if (bannerStart >= 0) { nsAutoString	htmlCopy(htmlResults); htmlCopy.Cut(0, bannerStart + bannerStartStr.Length());  PRInt32	bannerEnd = htmlCopy.Find(bannerEndStr, PR_TRUE); if (bannerEnd > 0) { htmlCopy.Truncate(bannerEnd); if (htmlCopy.Length() > 0) { const PRUnichar	*bannerUni = htmlCopy.GetUnicode(); if (bannerUni) { gRDFService->GetLiteral(bannerUni, getter_AddRefs(bannerLiteral)); } } } } }  if (resultListStartStr.Length() > 0) { PRInt32	resultListStart = htmlResults.Find(resultListStartStr, PR_TRUE); if (resultListStart >= 0) { htmlResults.Cut(0, resultListStart + resultListStartStr.Length()); } } if (resultListEndStr.Length() > 0) {  PRInt32	resultListEnd = htmlResults.RFind(resultListEndStr, PR_TRUE); if (resultListEnd >= 0) { htmlResults.Truncate(resultListEnd); } }  PRBool	trimItemStart = PR_TRUE; PRBool	trimItemEnd = PR_FALSE;   if (resultItemStartStr.Length() < 1) { resultItemStartStr = "HREF="; trimItemStart = PR_FALSE; }   if (resultItemEndStr.Length() < 1) { resultItemEndStr = resultItemStartStr; trimItemEnd = PR_FALSE; }  while(PR_TRUE) { PRInt32	resultItemStart; resultItemStart = htmlResults.Find(resultItemStartStr, PR_TRUE); if (resultItemStart < 0)	break;  PRInt32	resultItemEnd; if (trimItemStart == PR_TRUE) { htmlResults.Cut(0, resultItemStart + resultItemStartStr.Length()); resultItemEnd = htmlResults.Find(resultItemEndStr, PR_TRUE ); } else { htmlResults.Cut(0, resultItemStart); resultItemEnd = htmlResults.Find(resultItemEndStr, PR_TRUE, resultItemStartStr.Length() ); }  if (resultItemEnd < 0) { resultItemEnd = htmlResults.Length()-1; }  nsAutoString	resultItem(""); htmlResults.Left(resultItem, resultItemEnd);  if (resultItem.Length() < 1)	break; if (trimItemEnd == PR_TRUE) { htmlResults.Cut(0, resultItemEnd + resultItemEndStr.Length()); } else { htmlResults.Cut(0, resultItemEnd); }  #ifdef	DEBUG_SEARCH_OUTPUT char	*results = resultItem.ToNewCString(); if (results) { printf("\n----- Search result: '%s'\n\n", results); nsCRT::free(results); results = nsnull; } #endif   PRInt32	hrefOffset = resultItem.Find("HREF=", PR_TRUE); if (hrefOffset < 0) { #ifdef	DEBUG_SEARCH_OUTPUT printf("\n***** Unable to find HREF!\n\n"); #endif continue; }  nsAutoString	hrefStr(""); PRInt32		quoteStartOffset = resultItem.FindCharInSet("\"\'>", hrefOffset); PRInt32		quoteEndOffset; if (quoteStartOffset < hrefOffset) {  quoteStartOffset = hrefOffset + nsCRT::strlen("HREF="); quoteEndOffset = resultItem.FindCharInSet(">", quoteStartOffset); if (quoteEndOffset < quoteStartOffset)	continue; } else { if (resultItem[quoteStartOffset] == PRUnichar('>')) {  quoteEndOffset = quoteStartOffset; quoteStartOffset = hrefOffset + nsCRT::strlen("HREF=") -1; } else { quoteEndOffset = resultItem.FindCharInSet("\"\'", quoteStartOffset + 1); if (quoteEndOffset < hrefOffset)	continue; } } resultItem.Mid(hrefStr, quoteStartOffset + 1, quoteEndOffset - quoteStartOffset - 1); if (hrefStr.Length() < 1)	continue;   if (hrefStr[0] == PRUnichar('/')) { if (skipLocalFlag == PR_TRUE)	continue;  char *host = nsnull, *protocol = nsnull; aURL->GetHost(&host); aURL->GetScheme(&protocol); if (host && protocol) { nsAutoString	temp; temp += protocol; temp += ": temp += host; temp += hrefStr;  hrefStr = temp; } if (host) nsCRT::free(host); if (protocol) nsCRT::free(protocol); } else if (serverPathStr.Length() > 0) {  nsAutoString	tempHREF = hrefStr; tempHREF.Insert("/", 0);  PRInt32	optionsOffset = tempHREF.FindChar(PRUnichar('?')); if (optionsOffset >= 0)	tempHREF.Truncate(optionsOffset);  if (tempHREF.EqualsIgnoreCase(serverPathStr))	continue; }  char	*href = hrefStr.ToNewCString(); if (!href)	continue;  nsAutoString	site(href);  #ifdef	DEBUG_SEARCH_OUTPUT printf("HREF: '%s'\n", href); #endif  nsCOMPtr<nsIRDFResource>	res;   #ifdef	OLDWAY rv = gRDFService->GetResource(href, getter_AddRefs(res)); #else const char			*parentURI = nsnull; mParent->GetValueConst(&parentURI); if (!parentURI)	break;   if (NS_SUCCEEDED(rv = CreateAnonymousResource(&res))) { const PRUnichar	*hrefUni = hrefStr.GetUnicode(); if (hrefUni) { nsCOMPtr<nsIRDFLiteral>	hrefLiteral; if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(hrefUni, getter_AddRefs(hrefLiteral)))) { mInner->Assert(res, kNC_URL, hrefLiteral, PR_TRUE); } } } #endif  nsCRT::free(href); href = nsnull; if (NS_FAILED(rv))	continue;   const PRUnichar	*htmlResponseUni = resultItem.GetUnicode(); if (htmlResponseUni) { nsCOMPtr<nsIRDFLiteral>	htmlResponseLiteral; if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(htmlResponseUni, getter_AddRefs(htmlResponseLiteral)))) { if (htmlResponseLiteral) { mInner->Assert(res, kNC_HTML, htmlResponseLiteral, PR_TRUE); } } }   if (bannerLiteral) { mInner->Assert(res, kNC_Banner, bannerLiteral, PR_TRUE); }   nsCOMPtr<nsIRDFNode>		oldSiteRes = nsnull; mInner->GetTarget(res, kNC_Site, PR_TRUE, getter_AddRefs(oldSiteRes)); if (!oldSiteRes) { PRInt32	protocolOffset = site.FindCharInSet(":", 0); if (protocolOffset >= 0) { site.Cut(0, protocolOffset+1); while (site[0] == PRUnichar('/')) { site.Cut(0, 1); } PRInt32	slashOffset = site.FindCharInSet("/", 0); if (slashOffset >= 0) { site.Truncate(slashOffset); } if (site.Length() > 0) { const PRUnichar	*siteUni = site.GetUnicode(); if (siteUni) { nsCOMPtr<nsIRDFLiteral>	siteLiteral; if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(siteUni, getter_AddRefs(siteLiteral))))
InternetSearchDataSource::OnStopRequest(nsIRequest *request, nsISupports *ctxt,                                        nsresult status){	if (!mInner)	return(NS_OK);  nsCOMPtr<nsIChannel> channel (do_QueryInterface(request));	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;        if (NS_FAILED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Last-Modified"), lastModValue)))            lastModValue.Truncate();        if (NS_FAILED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Length"), contentLengthValue)))            contentLengthValue.Truncate();		// 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).get(),				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).get(),				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.get(), updateIconURL.get(), 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);}