From 331dc8a506295972df1fcd23279f0adea7f32406 Mon Sep 17 00:00:00 2001 From: "rjc%netscape.com" Date: Wed, 15 Sep 1999 06:14:45 +0000 Subject: [PATCH] (Not part of build yet) Moving find/search into its own component. --- suite/browser/public/nsISearchService.idl | 58 + suite/browser/src/nsInternetSearchService.cpp | 2568 +++++++++++++++++ suite/browser/src/nsLocalSearchService.cpp | 937 ++++++ xpfe/components/search/macbuild/Search.mcp | Bin 0 -> 73078 bytes xpfe/components/search/macbuild/SearchIDL.mcp | Bin 0 -> 65030 bytes .../components/search/macbuild/SearchPrefix.h | 22 + .../search/macbuild/SearchPrefix_debug.h | 22 + .../search/public/nsISearchService.idl | 58 + .../search/src/nsInternetSearchService.cpp | 2568 +++++++++++++++++ .../search/src/nsLocalSearchService.cpp | 937 ++++++ .../search/src/nsRegisterSearch.cpp | 137 + 11 files changed, 7307 insertions(+) create mode 100755 suite/browser/public/nsISearchService.idl create mode 100755 suite/browser/src/nsInternetSearchService.cpp create mode 100755 suite/browser/src/nsLocalSearchService.cpp create mode 100755 xpfe/components/search/macbuild/Search.mcp create mode 100755 xpfe/components/search/macbuild/SearchIDL.mcp create mode 100755 xpfe/components/search/macbuild/SearchPrefix.h create mode 100755 xpfe/components/search/macbuild/SearchPrefix_debug.h create mode 100755 xpfe/components/search/public/nsISearchService.idl create mode 100755 xpfe/components/search/src/nsInternetSearchService.cpp create mode 100755 xpfe/components/search/src/nsLocalSearchService.cpp create mode 100755 xpfe/components/search/src/nsRegisterSearch.cpp diff --git a/suite/browser/public/nsISearchService.idl b/suite/browser/public/nsISearchService.idl new file mode 100755 index 000000000000..f97ac0ee05c4 --- /dev/null +++ b/suite/browser/public/nsISearchService.idl @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + + The Browser Search service + +*/ + +#include "nsISupports.idl" + +[scriptable, uuid(1222e6f0-a5e3-11d2-8b7c-00805f8a7db6)] +interface nsILocalSearchService : nsISupports +{ +}; + +[scriptable, uuid(6bd1d803-1c67-11d3-9820-ed1b357eb3c4)] +interface nsInternetSearchService : nsISupports +{ +}; + +%{C++ + +#define NS_IINTERNETSEARCHDATASOURCECALLBACK_IID \ +{ 0x88774583, 0x1edd, 0x11d3, { 0x98, 0x20, 0xbf, 0x1b, 0xe7, 0x7e, 0x61, 0xc4 } } + +#define NS_IINTERNETSEARCHDATAOURCE_IID \ +{ 0x6bd1d803, 0x1c67, 0x11d3, { 0x98, 0x20, 0xed, 0x1b, 0x35, 0x7e, 0xb3, 0xc4 } } + +#define NS_ILOCALSEARCHDATASOURCE_IID \ +{ 0x1222e6f0, 0xa5e3, 0x11d2, { 0x8b, 0x7c, 0x00, 0x80, 0x5f, 0x8a, 0x7d, 0xb6 } } + +#define NS_LOCALSEARCH_SERVICE_PROGID \ + "component://netscape/browser/localsearch-service" +#define NS_LOCALSEARCH_DATASOURCE_PROGID \ + "component://netscape/rdf/datasource?name=localsearch" + +#define NS_INTERNETSEARCH_SERVICE_PROGID \ + "component://netscape/browser/internetsearch-service" +#define NS_INTERNETSEARCH_DATASOURCE_PROGID \ + "component://netscape/rdf/datasource?name=internetsearch" + +%} diff --git a/suite/browser/src/nsInternetSearchService.cpp b/suite/browser/src/nsInternetSearchService.cpp new file mode 100755 index 000000000000..d0e033597040 --- /dev/null +++ b/suite/browser/src/nsInternetSearchService.cpp @@ -0,0 +1,2568 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-file-style: "stroustrup" -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + Implementation for an internet search RDF data store. + */ + +#include // for toupper() +#include +#include "nscore.h" +#include "nsCOMPtr.h" +#include "nsIEnumerator.h" +#include "nsIRDFDataSource.h" +#include "nsIRDFNode.h" +#include "nsIRDFObserver.h" +#include "nsIServiceManager.h" +#include "nsString.h" +#include "nsVoidArray.h" // XXX introduces dependency on raptorbase +#include "nsXPIDLString.h" +#include "nsRDFCID.h" +//#include "rdfutil.h" +#include "nsIRDFService.h" +#include "xp_core.h" +#include "plhash.h" +#include "plstr.h" +#include "prmem.h" +#include "prprf.h" +#include "prio.h" +#include "rdf.h" +#include "nsFileSpec.h" +#include "nsFileStream.h" +#include "nsSpecialSystemDirectory.h" +#include "nsEnumeratorUtils.h" + +#include "nsIRDFRemoteDataSource.h" + +#include "nsEscape.h" + +#include "nsIURL.h" +#ifdef NECKO +#include "nsNeckoUtil.h" +#include "nsIChannel.h" +#include "nsIHTTPChannel.h" +#include "nsHTTPEnums.h" +#else +#include "nsIPostToServer.h" +#endif // NECKO +#include "nsIInputStream.h" +#include "nsIStreamListener.h" +#include "nsISearchService.h" + +#ifdef XP_MAC +#include "Files.h" +#endif + +#ifdef XP_WIN +#include "windef.h" +#include "winbase.h" +#endif + + +#define POSTHEADER_PREFIX "Content-type: application/x-www-form-urlencoded; charset=ISO-8859-1\r\nContent-Length: " +#define POSTHEADER_SUFFIX "\r\n\r\n" + + +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); +static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +static const char kURINC_SearchRoot[] = "NC:SearchEngineRoot"; +static const char kURINC_SearchResultsSitesRoot[] = "NC:SearchResultsSitesRoot"; +static const char kURINC_LastSearchRoot[] = "NC:LastSearchRoot"; +static const char kURINC_SearchResultsAnonymous[] = "NC:SearchResultsAnonymous"; + + + +class InternetSearchDataSourceCallback : public nsIStreamListener +{ +private: + nsIRDFDataSource *mDataSource; + nsIRDFResource *mParent; + nsIRDFResource *mEngine; + static PRInt32 gRefCnt; + + // pseudo-constants + static nsIRDFResource *kNC_LastSearchRoot; + static nsIRDFResource *kNC_loading; + static nsIRDFResource *kNC_Child; + static nsIRDFResource *kNC_URL; + static nsIRDFResource *kNC_Name; + static nsIRDFResource *kNC_Data; + static nsIRDFResource *kNC_Relevance; + static nsIRDFResource *kNC_RelevanceSort; + static nsIRDFResource *kNC_Site; + static nsIRDFResource *kNC_Engine; + static nsIRDFResource *kNC_HTML; + static nsIRDFResource *kNC_Banner; + + char *mLine; + + nsresult CreateAnonymousResource(nsCOMPtr* aResult); + +public: + + NS_DECL_ISUPPORTS + + InternetSearchDataSourceCallback(nsIRDFDataSource *ds, nsIRDFResource *parent, nsIRDFResource *engine); + virtual ~InternetSearchDataSourceCallback(void); + +#ifdef NECKO + // nsIStreamObserver methods: + NS_DECL_NSISTREAMOBSERVER + + // nsIStreamListener methods: + NS_DECL_NSISTREAMLISTENER +#else + // stream observer + + NS_IMETHOD OnStartRequest(nsIURI *aURL, const char *aContentType); + NS_IMETHOD OnProgress(nsIURI* aURL, PRUint32 aProgress, PRUint32 aProgressMax); + NS_IMETHOD OnStatus(nsIURI* aURL, const PRUnichar* aMsg); + NS_IMETHOD OnStopRequest(nsIURI* aURL, nsresult aStatus, const PRUnichar* aMsg); + + // stream listener + NS_IMETHOD GetBindInfo(nsIURI* aURL, nsStreamBindingInfo* aInfo); + NS_IMETHOD OnDataAvailable(nsIURI* aURL, nsIInputStream *aIStream, + PRUint32 aLength); +#endif +}; + + + +class InternetSearchDataSource : public nsIRDFDataSource +{ +private: + static PRInt32 gRefCnt; + + // pseudo-constants + static nsIRDFResource *kNC_SearchRoot; + static nsIRDFResource *kNC_LastSearchRoot; + static nsIRDFResource *kNC_SearchResultsSitesRoot; + static nsIRDFResource *kNC_Ref; + static nsIRDFResource *kNC_Child; + static nsIRDFResource *kNC_Data; + static nsIRDFResource *kNC_Name; + static nsIRDFResource *kNC_URL; + static nsIRDFResource *kRDF_InstanceOf; + static nsIRDFResource *kRDF_type; + static nsIRDFResource *kNC_loading; + static nsIRDFResource *kNC_HTML; + +protected: + static nsIRDFDataSource *mInner; + +friend NS_IMETHODIMP NS_NewInternetSearchService(nsISupports* aOuter, REFNSIID aIID, void** aResult); + +public: + +friend class InternetSearchDataSourceCallback; + + NS_DECL_ISUPPORTS + + InternetSearchDataSource(void); + virtual ~InternetSearchDataSource(void); + nsresult Init(); + + // nsIRDFDataSource methods + + NS_IMETHOD GetURI(char **uri); + NS_IMETHOD GetSource(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsIRDFResource **source /* out */); + NS_IMETHOD GetSources(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsISimpleEnumerator **sources /* out */); + NS_IMETHOD GetTarget(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsIRDFNode **target /* out */); + NS_IMETHOD GetTargets(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsISimpleEnumerator **targets /* out */); + NS_IMETHOD Assert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv); + NS_IMETHOD Unassert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target); + NS_IMETHOD Change(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aOldTarget, + nsIRDFNode* aNewTarget); + NS_IMETHOD Move(nsIRDFResource* aOldSource, + nsIRDFResource* aNewSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget); + NS_IMETHOD HasAssertion(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + PRBool *hasAssertion /* out */); + NS_IMETHOD ArcLabelsIn(nsIRDFNode *node, + nsISimpleEnumerator **labels /* out */); + NS_IMETHOD ArcLabelsOut(nsIRDFResource *source, + nsISimpleEnumerator **labels /* out */); + NS_IMETHOD GetAllResources(nsISimpleEnumerator** aResult); + NS_IMETHOD AddObserver(nsIRDFObserver *n); + NS_IMETHOD RemoveObserver(nsIRDFObserver *n); + NS_IMETHOD GetAllCommands(nsIRDFResource* source, + nsIEnumerator/**/** commands); + NS_IMETHOD GetAllCmds(nsIRDFResource* source, + nsISimpleEnumerator/**/** commands); + + NS_IMETHOD IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult); + + NS_IMETHOD DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments); + + + // helper methods +static PRBool isEngineURI(nsIRDFResource* aResource); +static PRBool isSearchURI(nsIRDFResource* aResource); +static nsresult BeginSearchRequest(nsIRDFResource *source, PRBool doNetworkRequest); +static nsresult DoSearch(nsIRDFResource *source, nsIRDFResource *engine, nsString text); +static nsresult GetSearchEngineList(nsFileSpec spec); +static nsresult GetSearchFolder(nsFileSpec &spec); +static nsresult ReadFileContents(nsFileSpec baseFilename, nsString & sourceContents); +static nsresult GetData(nsString data, char *sectionToFind, char *attribToFind, nsString &value); +static nsresult GetInputs(nsString data, nsString text, nsString &input); +static nsresult GetURL(nsIRDFResource *source, nsIRDFLiteral** aResult); +static PRBool isVisible(const nsNativeFileSpec& file); + +}; + + + +static nsIRDFService *gRDFService = nsnull; +static InternetSearchDataSource *gInternetSearchDataSource = nsnull; + +PRInt32 InternetSearchDataSource::gRefCnt; +nsIRDFDataSource *InternetSearchDataSource::mInner = nsnull; + +nsIRDFResource *InternetSearchDataSource::kNC_SearchRoot; +nsIRDFResource *InternetSearchDataSource::kNC_LastSearchRoot; +nsIRDFResource *InternetSearchDataSource::kNC_SearchResultsSitesRoot; +nsIRDFResource *InternetSearchDataSource::kNC_Ref; +nsIRDFResource *InternetSearchDataSource::kNC_Child; +nsIRDFResource *InternetSearchDataSource::kNC_Data; +nsIRDFResource *InternetSearchDataSource::kNC_Name; +nsIRDFResource *InternetSearchDataSource::kNC_URL; +nsIRDFResource *InternetSearchDataSource::kRDF_InstanceOf; +nsIRDFResource *InternetSearchDataSource::kRDF_type; +nsIRDFResource *InternetSearchDataSource::kNC_loading; +nsIRDFResource *InternetSearchDataSource::kNC_HTML; + +PRInt32 InternetSearchDataSourceCallback::gRefCnt; + +nsIRDFResource *InternetSearchDataSourceCallback::kNC_LastSearchRoot; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Child; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_URL; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Name; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Data; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Relevance; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_RelevanceSort; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Site; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Engine; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_loading; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_HTML; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Banner; + +static const char kEngineProtocol[] = "engine://"; +static const char kSearchProtocol[] = "internetsearch:"; + + + +PRBool +InternetSearchDataSource::isEngineURI(nsIRDFResource *r) +{ + PRBool isEngineURIFlag = PR_FALSE; + const char *uri = nsnull; + + r->GetValueConst(&uri); + if ((uri) && (!strncmp(uri, kEngineProtocol, sizeof(kEngineProtocol) - 1))) + { + isEngineURIFlag = PR_TRUE; + } + return(isEngineURIFlag); +} + + + +PRBool +InternetSearchDataSource::isSearchURI(nsIRDFResource *r) +{ + PRBool isSearchURIFlag = PR_FALSE; + const char *uri = nsnull; + + r->GetValueConst(&uri); + if ((uri) && (!strncmp(uri, kSearchProtocol, sizeof(kSearchProtocol) - 1))) + { + isSearchURIFlag = PR_TRUE; + } + return(isSearchURIFlag); +} + + + +InternetSearchDataSource::InternetSearchDataSource(void) +{ + NS_INIT_REFCNT(); + + if (gRefCnt++ == 0) + { + nsresult rv = nsServiceManager::GetService(kRDFServiceCID, + nsIRDFService::GetIID(), (nsISupports**) &gRDFService); + + PR_ASSERT(NS_SUCCEEDED(rv)); + + gRDFService->GetResource(kURINC_SearchRoot, &kNC_SearchRoot); + gRDFService->GetResource(kURINC_LastSearchRoot, &kNC_LastSearchRoot); + gRDFService->GetResource(kURINC_SearchResultsSitesRoot, &kNC_SearchResultsSitesRoot); + gRDFService->GetResource(NC_NAMESPACE_URI "ref", &kNC_Ref); + gRDFService->GetResource(NC_NAMESPACE_URI "child", &kNC_Child); + gRDFService->GetResource(NC_NAMESPACE_URI "data", &kNC_Data); + gRDFService->GetResource(NC_NAMESPACE_URI "Name", &kNC_Name); + gRDFService->GetResource(NC_NAMESPACE_URI "URL", &kNC_URL); + gRDFService->GetResource(RDF_NAMESPACE_URI "instanceOf", &kRDF_InstanceOf); + gRDFService->GetResource(RDF_NAMESPACE_URI "type", &kRDF_type); + gRDFService->GetResource(NC_NAMESPACE_URI "loading", &kNC_loading); + gRDFService->GetResource(NC_NAMESPACE_URI "HTML", &kNC_HTML); + + gInternetSearchDataSource = this; + } +} + + + +InternetSearchDataSource::~InternetSearchDataSource (void) +{ + if (--gRefCnt == 0) + { + NS_RELEASE(kNC_SearchRoot); + NS_RELEASE(kNC_LastSearchRoot); + NS_RELEASE(kNC_SearchResultsSitesRoot); + NS_RELEASE(kNC_Ref); + NS_RELEASE(kNC_Child); + NS_RELEASE(kNC_Data); + NS_RELEASE(kNC_Name); + NS_RELEASE(kNC_URL); + NS_RELEASE(kRDF_InstanceOf); + NS_RELEASE(kRDF_type); + NS_RELEASE(kNC_loading); + NS_RELEASE(kNC_HTML); + + NS_IF_RELEASE(mInner); + + gInternetSearchDataSource = nsnull; + nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService); + gRDFService = nsnull; + } +} + + + +NS_IMPL_ISUPPORTS(InternetSearchDataSource, InternetSearchDataSource::GetIID()); + + + +nsresult +InternetSearchDataSource::Init() +{ + nsresult rv = NS_ERROR_OUT_OF_MEMORY; + + if (NS_FAILED(rv = nsComponentManager::CreateInstance(kRDFInMemoryDataSourceCID, + nsnull, nsIRDFDataSource::GetIID(), (void **)&mInner))) + return(rv); + + // register this as a named data source with the service manager + if (NS_FAILED(rv = gRDFService->RegisterDataSource(this, PR_FALSE))) + return(rv); + + // get available search engines + nsFileSpec nativeDir; + if (NS_SUCCEEDED(rv = GetSearchFolder(nativeDir))) + { + rv = GetSearchEngineList(nativeDir); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetURI(char **uri) +{ + NS_PRECONDITION(uri != nsnull, "null ptr"); + if (! uri) + return NS_ERROR_NULL_POINTER; + + if ((*uri = nsXPIDLCString::Copy("rdf:search")) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + return NS_OK; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetSource(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFResource** source /* out */) +{ + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + *source = nsnull; + return NS_RDF_NO_VALUE; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetSources(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsISimpleEnumerator **sources /* out */) +{ + NS_NOTYETIMPLEMENTED("write me"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetTarget(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsIRDFNode **target /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_RDF_NO_VALUE; + + // we only have positive assertions in the internet search data source. + if (! tv) + return(rv); + + if (mInner) + { + rv = mInner->GetTarget(source, property, tv, target); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetTargets(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsISimpleEnumerator **targets /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(targets != nsnull, "null ptr"); + if (! targets) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_RDF_NO_VALUE; + + // we only have positive assertions in the internet search data source. + if (! tv) + return(rv); + + if (mInner) + { + rv = mInner->GetTargets(source, property, tv, targets); + } + if (isSearchURI(source)) + { + if (property == kNC_Child) + { + PRBool doNetworkRequest = PR_TRUE; + if (NS_SUCCEEDED(rv) && (targets)) + { + // check and see if we already have data for the search in question; + // if we do, BeginSearchRequest() won't bother doing the search again, + // otherwise it will kickstart it + PRBool hasResults = PR_FALSE; + if (NS_SUCCEEDED((*targets)->HasMoreElements(&hasResults)) && (hasResults == PR_TRUE)) + { + doNetworkRequest = PR_FALSE; + } + } + BeginSearchRequest(source, doNetworkRequest); + } + } + return(rv); + +#if 0 + if ((source == kNC_SearchRoot) || (source == kNC_LastSearchRoot)) + { + if (property == kNC_Child) + { + if (mInner) + { + rv = mInner->GetTargets(source, property,tv, targets); + } + return(rv); + } + return(NS_RDF_NO_VALUE); + } + else if (isSearchURI(source)) + { + if (property == kNC_Child) + { + if (mInner) + { + rv = mInner->GetTargets(source, property, tv, targets); + } + PRBool doNetworkRequest = PR_TRUE; + if (NS_SUCCEEDED(rv) && (targets)) + { + // check and see if we already have data for the search in question; + // if we do, don't bother doing the search again, otherwise kickstart it + PRBool hasResults = PR_FALSE; + if (NS_SUCCEEDED((*targets)->HasMoreElements(&hasResults)) && (hasResults == PR_TRUE)) + { + doNetworkRequest = PR_FALSE; + } + } + BeginSearchRequest(source, doNetworkRequest); +// return(rv); + } + return(NS_RDF_NO_VALUE); + } + if (mInner) + { + rv = mInner->GetTargets(source, property, tv, targets); + } + return NS_NewEmptyEnumerator(targets); +#endif + +} + + + +NS_IMETHODIMP +InternetSearchDataSource::Assert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::Unassert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::Change(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aOldTarget, + nsIRDFNode* aNewTarget) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::Move(nsIRDFResource* aOldSource, + nsIRDFResource* aNewSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::HasAssertion(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + PRBool *hasAssertion /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(hasAssertion != nsnull, "null ptr"); + if (! hasAssertion) + return NS_ERROR_NULL_POINTER; + + // we only have positive assertions in the internet search data source. + if (! tv) + { + *hasAssertion = PR_FALSE; + return NS_OK; + } + nsresult rv = NS_RDF_NO_VALUE; + + if (mInner) + { + rv = mInner->HasAssertion(source, property, target, tv, hasAssertion); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::ArcLabelsIn(nsIRDFNode *node, + nsISimpleEnumerator ** labels /* out */) +{ + NS_NOTYETIMPLEMENTED("write me"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::ArcLabelsOut(nsIRDFResource *source, + nsISimpleEnumerator **labels /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(labels != nsnull, "null ptr"); + if (! labels) + return NS_ERROR_NULL_POINTER; + + nsresult rv; + + if ((source == kNC_SearchRoot) || (source == kNC_LastSearchRoot) || isSearchURI(source)) + { + nsCOMPtr array; + rv = NS_NewISupportsArray(getter_AddRefs(array)); + if (NS_FAILED(rv)) return rv; + + array->AppendElement(kNC_Child); + + nsISimpleEnumerator* result = new nsArrayEnumerator(array); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(result); + *labels = result; + return(NS_OK); + } + + if (mInner) + { + rv = mInner->ArcLabelsOut(source, labels); + return(rv); + } + + return NS_NewEmptyEnumerator(labels); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetAllResources(nsISimpleEnumerator** aCursor) +{ + nsresult rv = NS_RDF_NO_VALUE; + + if (mInner) + { + rv = mInner->GetAllResources(aCursor); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::AddObserver(nsIRDFObserver *aObserver) +{ + nsresult rv = NS_OK; + + if (mInner) + { + rv = mInner->AddObserver(aObserver); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::RemoveObserver(nsIRDFObserver *aObserver) +{ + nsresult rv = NS_OK; + + if (mInner) + { + rv = mInner->RemoveObserver(aObserver); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetAllCommands(nsIRDFResource* source, + nsIEnumerator/**/** commands) +{ + NS_NOTYETIMPLEMENTED("write me!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetAllCmds(nsIRDFResource* source, + nsISimpleEnumerator/**/** commands) +{ + return(NS_NewEmptyEnumerator(commands)); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult) +{ + return(NS_ERROR_NOT_IMPLEMENTED); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments) +{ + return(NS_ERROR_NOT_IMPLEMENTED); +} + + + +NS_IMETHODIMP +NS_NewInternetSearchService(nsISupports* aOuter, REFNSIID aIID, void** aResult) +{ + NS_PRECONDITION(aResult != nsnull, "null ptr"); + if (! aResult) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(aOuter == nsnull, "no aggregation"); + if (aOuter) + return NS_ERROR_NO_AGGREGATION; + + nsresult rv = NS_OK; + + InternetSearchDataSource* result = new InternetSearchDataSource(); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + rv = result->Init(); + if (NS_SUCCEEDED(rv)) + rv = result->QueryInterface(aIID, aResult); + + if (NS_FAILED(rv)) { + delete result; + *aResult = nsnull; + return rv; + } + + return rv; +} + + + +nsresult +InternetSearchDataSource::BeginSearchRequest(nsIRDFResource *source, PRBool doNetworkRequest) +{ + nsresult rv = NS_OK; + char *sourceURI = nsnull; + + if (NS_FAILED(rv = source->GetValue(&sourceURI))) + return(rv); + nsAutoString uri(sourceURI); + if (uri.Find("internetsearch:") != 0) + return(NS_ERROR_FAILURE); + + // remember the last search query + + nsCOMPtr localstore; + rv = gRDFService->GetDataSource("rdf:local-store", getter_AddRefs(localstore)); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr lastTarget; + if (NS_SUCCEEDED(rv = localstore->GetTarget(kNC_LastSearchRoot, kNC_Ref, + PR_TRUE, getter_AddRefs(lastTarget)))) + { + if (rv != NS_RDF_NO_VALUE) + { +#ifdef DEBUG + nsCOMPtr lastLit = do_QueryInterface(lastTarget); + if (lastLit) + { + const PRUnichar *lastUni = nsnull; + lastLit->GetValueConst(&lastUni); + nsAutoString lastStr(lastUni); + char *lastC = lastStr.ToNewCString(); + if (lastC) + { + printf("\nLast Search: '%s'\n", lastC); + nsCRT::free(lastC); + lastC = nsnull; + } + } +#endif + rv = localstore->Unassert(kNC_LastSearchRoot, kNC_Ref, lastTarget); + } + } + if (uri.Length() > 0) + { + const PRUnichar *uriUni = uri.GetUnicode(); + nsCOMPtr uriLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(uriUni, getter_AddRefs(uriLiteral)))) + { + rv = localstore->Assert(kNC_LastSearchRoot, kNC_Ref, uriLiteral, PR_TRUE); + } + } + + // XXX Currently, need to flush localstore as its being leaked + // and thus never written out to disk otherwise + + // gotta love the name "remoteLocalStore" + nsCOMPtr remoteLocalStore = do_QueryInterface(localstore); + if (remoteLocalStore) + { + remoteLocalStore->Flush(); + } + } + + // forget about any previous search results + + if (mInner) + { + nsCOMPtr arcs; + if (NS_SUCCEEDED(rv = mInner->GetTargets(kNC_LastSearchRoot, kNC_Child, PR_TRUE, getter_AddRefs(arcs)))) + { + PRBool hasMore = PR_TRUE; + while (hasMore == PR_TRUE) + { + if (NS_FAILED(arcs->HasMoreElements(&hasMore)) || (hasMore == PR_FALSE)) + break; + nsCOMPtr arc; + if (NS_FAILED(arcs->GetNext(getter_AddRefs(arc)))) + break; + nsCOMPtr child = do_QueryInterface(arc); + if (child) + { + mInner->Unassert(kNC_LastSearchRoot, kNC_Child, child); + } + } + } + } + +#if 0 + nsCOMPtr lastTarget; + if (NS_SUCCEEDED(rv = mInner->GetTarget(kNC_LastSearchRoot, kNC_Ref, + PR_TRUE, getter_AddRefs(lastTarget)))) + { + if (rv != NS_RDF_NO_VALUE) + { + rv = mInner->Unassert(kNC_LastSearchRoot, kNC_Ref, lastTarget); + } + } + if (uri.Length() > 0) + { + const PRUnichar *uriUni = uri.GetUnicode(); + nsCOMPtr uriLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(uriUni, getter_AddRefs(uriLiteral)))) + { + rv = mInner->Assert(kNC_LastSearchRoot, kNC_Ref, uriLiteral, PR_TRUE); + } + } + } +#endif + + // forget about any previous search sites + + if (mInner) + { + nsCOMPtr arcs; + if (NS_SUCCEEDED(rv = mInner->GetTargets(kNC_SearchResultsSitesRoot, kNC_Child, PR_TRUE, getter_AddRefs(arcs)))) + { + PRBool hasMore = PR_TRUE; + while (hasMore == PR_TRUE) + { + if (NS_FAILED(arcs->HasMoreElements(&hasMore)) || (hasMore == PR_FALSE)) + break; + nsCOMPtr arc; + if (NS_FAILED(arcs->GetNext(getter_AddRefs(arc)))) + break; + nsCOMPtr child = do_QueryInterface(arc); + if (child) + { + mInner->Unassert(kNC_SearchResultsSitesRoot, kNC_Child, child); + } + } + } + } + + uri.Cut(0, strlen("internetsearch:")); + + nsVoidArray *engineArray = new nsVoidArray; + if (!engineArray) + return(NS_ERROR_FAILURE); + + nsAutoString text(""); + + // parse up attributes + + while(uri.Length() > 0) + { + nsAutoString item(""); + + PRInt32 andOffset = uri.Find("&"); + if (andOffset >= 0) + { + uri.Left(item, andOffset); + uri.Cut(0, andOffset + 1); + } + else + { + item = uri; + uri.Truncate(); + } + + PRInt32 equalOffset = item.Find("="); + if (equalOffset < 0) break; + + nsAutoString attrib(""), value(""); + item.Left(attrib, equalOffset); + value = item; + value.Cut(0, equalOffset + 1); + + if ((attrib.Length() > 0) && (value.Length() > 0)) + { + if (attrib.EqualsIgnoreCase("engine")) + { + if (value.Find(kEngineProtocol) == 0) + { + char *val = value.ToNewCString(); + if (val) + { + engineArray->AppendElement(val); + } + } + } + else if (attrib.EqualsIgnoreCase("text")) + { + text = value; + } + } + } + + // loop over specified search engines + while (engineArray->Count() > 0) + { + char *baseFilename = (char *)(engineArray->ElementAt(0)); + engineArray->RemoveElementAt(0); + if (!baseFilename) continue; + +#ifdef DEBUG + printf("Search engine to query: '%s'\n", baseFilename); +#endif + + nsCOMPtr engine; + gRDFService->GetResource(baseFilename, getter_AddRefs(engine)); + nsCRT::free(baseFilename); + baseFilename = nsnull; + if (!engine) continue; + + // mark this as a search site + if (mInner) + { + mInner->Assert(kNC_SearchResultsSitesRoot, kNC_Child, engine, PR_TRUE); + } + + if (doNetworkRequest == PR_TRUE) + { + DoSearch(source, engine, text); + } + } + + delete engineArray; + engineArray = nsnull; + + return(rv); +} + + + +nsresult +InternetSearchDataSource::DoSearch(nsIRDFResource *source, nsIRDFResource *engine, nsString text) +{ + nsresult rv; + + if (!source) + return(NS_ERROR_NULL_POINTER); + if (!engine) + return(NS_ERROR_NULL_POINTER); + + if (!mInner) + { + return(NS_RDF_NO_VALUE); + } + + // get data + nsAutoString data(""); + nsCOMPtr dataTarget = nsnull; + if (NS_SUCCEEDED((rv = mInner->GetTarget(engine, kNC_Data, PR_TRUE, getter_AddRefs(dataTarget)))) && (dataTarget)) + { + nsCOMPtr dataLiteral = do_QueryInterface(dataTarget); + if (!dataLiteral) + return(rv); + PRUnichar *dataUni; + if (NS_FAILED(rv = dataLiteral->GetValue(&dataUni))) + return(rv); + data = dataUni; + } + else + { + const char *engineURI = nsnull; + if (NS_FAILED(rv = engine->GetValueConst(&engineURI))) + return(rv); + nsAutoString engineStr(engineURI); + if (engineStr.Find(kEngineProtocol) != 0) + return(rv); + engineStr.Cut(0, sizeof(kEngineProtocol) - 1); + char *baseFilename = engineStr.ToNewCString(); + if (!baseFilename) + return(rv); + baseFilename = nsUnescape(baseFilename); + if (!baseFilename) + return(rv); + + nsFileSpec engineSpec(baseFilename); + rv = ReadFileContents(engineSpec, data); +// rv = NS_ERROR_UNEXPECTED; // XXX rjc: fix this + + nsCRT::free(baseFilename); + baseFilename = nsnull; + if (NS_FAILED(rv)) + { + return(rv); + } + + // save file contents + nsCOMPtr dataLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(data.GetUnicode(), getter_AddRefs(dataLiteral)))) + { + if (mInner) + { + mInner->Assert(engine, kNC_Data, dataLiteral, PR_TRUE); + } + } + } + if (data.Length() < 1) + return(NS_RDF_NO_VALUE); + + nsAutoString action, method, input; + + if (NS_FAILED(rv = GetData(data, "search", "action", action))) + return(rv); + if (NS_FAILED(rv = GetData(data, "search", "method", method))) + return(rv); + if (NS_FAILED(rv = GetInputs(data, text, input))) + return(rv); + +#ifdef DEBUG + char *cAction = action.ToNewCString(); + char *cMethod = method.ToNewCString(); + char *cInput = input.ToNewCString(); + printf("Search Action: '%s'\n", cAction); + printf("Search Method: '%s'\n", cMethod); + printf(" Search Input: '%s'\n\n", cInput); + if (cAction) + { + nsCRT::free(cAction); + cAction = nsnull; + } + if (cMethod) + { + nsCRT::free(cMethod); + cMethod = nsnull; + } + if (cInput) + { + nsCRT::free(cInput); + cInput = nsnull; + } +#endif + + if (input.Length() < 1) + return(NS_ERROR_UNEXPECTED); + + if (method.EqualsIgnoreCase("get")) + { + // HTTP Get method support + action += "?"; + action += input; + } + + char *searchURL = action.ToNewCString(); + if (!searchURL) + return(NS_ERROR_NULL_POINTER); + +#ifdef NECKO + InternetSearchDataSourceCallback *callback = new InternetSearchDataSourceCallback(mInner, source, engine); + if (nsnull != callback) + { + nsCOMPtr url; + if (NS_SUCCEEDED(rv = NS_NewURI(getter_AddRefs(url), (const char*) searchURL))) + { + if (method.EqualsIgnoreCase("post")) + { + nsCOMPtr channel; + // XXX: Null LoadGroup ? + if (NS_SUCCEEDED(rv = NS_OpenURI(getter_AddRefs(channel), url, nsnull))) + { + nsCOMPtr httpChannel = do_QueryInterface(channel); + if (httpChannel) + { + httpChannel->SetRequestMethod(HM_POST); + + // construct post data to send + nsAutoString postStr(POSTHEADER_PREFIX); + postStr.Append(input.Length(), 10); + postStr += POSTHEADER_SUFFIX; + postStr += input; + + char *postData = postStr.ToNewCString(); + if (postData) + { + nsCOMPtr postDataStream; + if (NS_SUCCEEDED(rv = NS_NewPostDataStream(PR_FALSE, postData, + 0, getter_AddRefs(postDataStream)))) + { + httpChannel->SetPostDataStream(postDataStream); + /* postData is now owned by the postDataStream instance... ? */ + rv = channel->AsyncRead(0, -1, nsnull, callback); + } + else + { + nsCRT::free(postData); + postData = nsnull; + } + } + } + } + } + else if (method.EqualsIgnoreCase("get")) + { + // XXX: Null LoadGroup? + rv = NS_OpenURI(NS_STATIC_CAST(nsIStreamListener *, callback), nsnull, url, nsnull); + } + } + } +#endif + + // dispose of any last HTML results page + if (mInner) + { + nsCOMPtr htmlNode; + if (NS_SUCCEEDED(rv = mInner->GetTarget(engine, kNC_HTML, PR_TRUE, getter_AddRefs(htmlNode))) + && (rv != NS_RDF_NO_VALUE)) + { + rv = mInner->Unassert(engine, kNC_HTML, htmlNode); + } + } + + // start "loading" animation for this search engine + if (NS_SUCCEEDED(rv) && (mInner)) + { + nsAutoString trueStr("true"); + nsCOMPtr literal; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(trueStr.GetUnicode(), getter_AddRefs(literal)))) + { + mInner->Assert(engine, kNC_loading, literal, PR_TRUE); + } + } + + nsCRT::free(searchURL); + searchURL = nsnull; + return(rv); +} + + + +nsresult +InternetSearchDataSource::GetSearchFolder(nsFileSpec &spec) +{ +#ifdef XP_MAC + // on Mac, use system's search files + nsSpecialSystemDirectory searchSitesDir(nsSpecialSystemDirectory::Mac_InternetSearchDirectory); +#else + // on other platforms, use our search files + nsSpecialSystemDirectory searchSitesDir(nsSpecialSystemDirectory::OS_CurrentProcessDirectory); + searchSitesDir += "res"; + searchSitesDir += "rdf"; + searchSitesDir += "datasets"; +#endif + spec = searchSitesDir; + return(NS_OK); +} + + + +nsresult +InternetSearchDataSource::GetSearchEngineList(nsFileSpec nativeDir) +{ + nsresult rv = NS_OK; + + if (!mInner) + { + return(NS_RDF_NO_VALUE); + } + + for (nsDirectoryIterator i(nativeDir, PR_FALSE); i.Exists(); i++) + { + const nsFileSpec fileSpec = (const nsFileSpec &)i; + if (fileSpec.IsHidden()) + { + continue; + } + + const char *childURL = fileSpec; + + if (fileSpec.IsDirectory()) + { + GetSearchEngineList(fileSpec); + } + else + if (childURL != nsnull) + { + nsAutoString uri(childURL); + PRInt32 len = uri.Length(); + if (len > 4) + { +#ifdef XP_MAC + // be sure to resolve aliases in case we encounter one + CInfoPBRec cInfo; + OSErr err; +// PRBool wasAliased = PR_FALSE; +// fileSpec.ResolveSymlink(wasAliased); + err = fileSpec.GetCatInfo(cInfo); + if ((!err) && (cInfo.hFileInfo.ioFlFndrInfo.fdType == 'issp') && + (cInfo.hFileInfo.ioFlFndrInfo.fdCreator == 'fndf')) +#else + // else just check the extension + nsAutoString extension; + if ((uri.Right(extension, 4) == 4) && (extension.EqualsIgnoreCase(".src"))) +#endif + { + char c; +#ifdef XP_WIN + c = '\\'; +#elif XP_MAC + c = ':'; +#else + c = '/'; +#endif + PRInt32 separatorOffset = uri.RFindChar(PRUnichar(c)); + if (separatorOffset > 0) + { +// uri.Cut(0, separatorOffset+1); + + nsAutoString searchURL(kEngineProtocol); + + char *uriC = uri.ToNewCString(); + if (!uriC) continue; + char *uriCescaped = nsEscape(uriC, url_Path); + nsCRT::free(uriC); + if (!uriCescaped) continue; +// searchURL += uri; + searchURL += uriCescaped; + nsCRT::free(uriCescaped); + +/* + char *baseFilename = uri.ToNewCString(); + if (!baseFilename) continue; + baseFilename = nsUnescape(baseFilename); + if (!baseFilename) continue; +*/ + nsAutoString data(""); + rv = ReadFileContents(fileSpec, data); +// nsCRT::free(baseFilename); +// baseFilename = nsnull; + if (NS_FAILED(rv)) continue; + + nsCOMPtr searchRes; + char *searchURI = searchURL.ToNewCString(); + if (searchURI) + { + if (NS_SUCCEEDED(rv = gRDFService->GetResource(searchURI, getter_AddRefs(searchRes)))) + { + mInner->Assert(kNC_SearchRoot, kNC_Child, searchRes, PR_TRUE); + + // save name of search engine (as specified in file) + nsAutoString nameValue; + if (NS_SUCCEEDED(rv = GetData(data, "search", "name", nameValue))) + { + nsCOMPtr nameLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(nameValue.GetUnicode(), getter_AddRefs(nameLiteral)))) + { + mInner->Assert(searchRes, kNC_Name, nameLiteral, PR_TRUE); + } + } + } + nsCRT::free(searchURI); + searchURI = nsnull; + } +// nsCRT::free(baseFilename); +// baseFilename = nsnull; + } + } + } + } + } + return(rv); +} + + + +PRBool +InternetSearchDataSource::isVisible(const nsNativeFileSpec& file) +{ + PRBool isVisible = PR_TRUE; + +#ifdef XP_MAC + CInfoPBRec cInfo; + OSErr err; + + nsFileSpec fileSpec(file); + if (!(err = fileSpec.GetCatInfo(cInfo))) + { + if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) + { + isVisible = PR_FALSE; + } + } +#else + char *baseFilename = file.GetLeafName(); + if (nsnull != baseFilename) + { + if ((!strcmp(baseFilename, ".")) || (!strcmp(baseFilename, ".."))) + { + isVisible = PR_FALSE; + } + nsCRT::free(baseFilename); + } +#endif + + return(isVisible); +} + + + +nsresult +InternetSearchDataSource::ReadFileContents(nsFileSpec baseFilename, nsString& sourceContents) +{ + nsresult rv = NS_OK; + +/* + nsFileSpec searchEngine; + if (NS_FAILED(rv = GetSearchFolder(searchEngine))) + { + return(rv); + } + searchEngine += baseFilename; + +#ifdef XP_MAC + // be sure to resolve aliases in case we encounter one + PRBool wasAliased = PR_FALSE; + searchEngine.ResolveSymlink(wasAliased); +#endif + nsInputFileStream searchFile(searchEngine); +*/ + + nsInputFileStream searchFile(baseFilename); + +/* +#ifdef XP_MAC + if (!searchFile.is_open()) + { + // on Mac, nsDirectoryIterator resolves aliases before returning them currently; + // so, if we can't open the file directly, walk the directory and see if we then + // find a match + + // on Mac, use system's search files + nsSpecialSystemDirectory searchSitesDir(nsSpecialSystemDirectory::Mac_InternetSearchDirectory); + nsFileSpec nativeDir(searchSitesDir); + for (nsDirectoryIterator i(nativeDir, PR_FALSE); i.Exists(); i++) + { + const nsFileSpec fileSpec = (const nsFileSpec &)i; + const char *childURL = fileSpec; + if (fileSpec.isHidden()) + { + continue; + } + if (childURL != nsnull) + { + // be sure to resolve aliases in case we encounter one + PRBool wasAliased = PR_FALSE; + fileSpec.ResolveSymlink(wasAliased); + nsAutoString childPath(childURL); + PRInt32 separatorOffset = childPath.RFindChar(PRUnichar(':')); + if (separatorOffset > 0) + { + childPath.Cut(0, separatorOffset+1); + } + if (childPath.EqualsIgnoreCase(baseFilename)) + { + searchFile = fileSpec; + } + } + } + } +#endif +*/ + + if (searchFile.is_open()) + { + nsRandomAccessInputStream stream(searchFile); + char buffer[1024]; + while (!stream.eof()) + { + stream.readline(buffer, sizeof(buffer)-1 ); + sourceContents += buffer; + sourceContents += "\n"; + } + } + else + { + rv = NS_ERROR_FAILURE; + } + return(rv); +} + + + +nsresult +InternetSearchDataSource::GetData(nsString data, char *sectionToFind, char *attribToFind, nsString &value) +{ + nsAutoString buffer(data); + nsresult rv = NS_RDF_NO_VALUE; + PRBool inSection = PR_FALSE; + + while(buffer.Length() > 0) + { + PRInt32 eol = buffer.FindCharInSet("\r\n", 0); + if (eol < 0) break; + nsAutoString line(""); + if (eol > 0) + { + buffer.Left(line, eol); + } + buffer.Cut(0, eol+1); + if (line.Length() < 1) continue; // skip empty lines + if (line[0] == PRUnichar('#')) continue; // skip comments + line = line.Trim(" \t"); + if (inSection == PR_FALSE) + { + nsAutoString section("<"); + section += sectionToFind; + PRInt32 sectionOffset = line.Find(section, PR_TRUE); + if (sectionOffset < 0) continue; + line.Cut(0, sectionOffset + section.Length() + 1); + inSection = PR_TRUE; + + } + line = line.Trim(" \t"); + PRInt32 len = line.Length(); + if (len > 0) + { + if (line[len-1] == PRUnichar('>')) + { + inSection = PR_FALSE; + line.SetLength(len-1); + } + } + PRInt32 equal = line.Find("="); + if (equal < 0) continue; // skip lines with no equality + + nsAutoString attrib(""); + if (equal > 0) + { + line.Left(attrib, equal /* - 1 */); + } + attrib = attrib.Trim(" \t"); + if (attrib.EqualsIgnoreCase(attribToFind)) + { + line.Cut(0, equal+1); + value = line.Trim(" \t"); + + // strip of any enclosing quotes + if (value[0] == PRUnichar('\"')) + { + value.Cut(0,1); + } + len = value.Length(); + if (len > 0) + { + if (value[len-1] == PRUnichar('\"')) + { + value.SetLength(len-1); + } + } + rv = NS_OK; + break; + } + } + return(rv); +} + + + +nsresult +InternetSearchDataSource::GetInputs(nsString data, nsString text, nsString &input) +{ + nsAutoString buffer(data); // , eolStr("\r\n"); + nsresult rv = NS_OK; + PRBool inSection = PR_FALSE; + + while(buffer.Length() > 0) + { + PRInt32 eol = buffer.FindCharInSet("\r\n", 0); + if (eol < 0) break; + nsAutoString line(""); + if (eol > 0) + { + buffer.Left(line, eol); + } + buffer.Cut(0, eol+1); + if (line.Length() < 1) continue; // skip empty lines + if (line[0] == PRUnichar('#')) continue; // skip comments + line = line.Trim(" \t"); + if (inSection == PR_FALSE) + { + nsAutoString section("<"); + PRInt32 sectionOffset = line.Find(section, PR_TRUE); + if (sectionOffset < 0) continue; + if (sectionOffset == 0) + { + line.Cut(0, sectionOffset + section.Length()); + inSection = PR_TRUE; + } + } + PRInt32 len = line.Length(); + if (len > 0) + { + if (line[len-1] == PRUnichar('>')) + { + inSection = PR_FALSE; + line.SetLength(len-1); + } + } + if (inSection == PR_TRUE) continue; + + // look for inputs + if (line.Find("input", PR_TRUE) == 0) + { + line.Cut(0, 6); + line = line.Trim(" \t"); + + // first look for name attribute + nsAutoString nameAttrib(""); + + PRInt32 nameOffset = line.Find("name", PR_TRUE); + if (nameOffset >= 0) + { + PRInt32 equal = line.FindChar(PRUnichar('='), PR_TRUE, nameOffset); + if (equal >= 0) + { + PRInt32 startQuote = line.FindChar(PRUnichar('\"'), PR_TRUE, equal + 1); + if (startQuote >= 0) + { + PRInt32 endQuote = line.FindChar(PRUnichar('\"'), PR_TRUE, startQuote + 1); + if (endQuote > 0) + { + line.Mid(nameAttrib, startQuote+1, endQuote-startQuote-1); + } + } + else + { + nameAttrib = line; + nameAttrib.Cut(0, equal+1); + nameAttrib = nameAttrib.Trim(" \t"); + PRInt32 space = nameAttrib.FindCharInSet(" \t", 0); + if (space > 0) + { + nameAttrib.Truncate(space); + } + } + } + } + if (nameAttrib.Length() <= 0) continue; + + // first look for value attribute + nsAutoString valueAttrib(""); + + PRInt32 valueOffset = line.Find("value", PR_TRUE); + if (valueOffset >= 0) + { + PRInt32 equal = line.FindChar(PRUnichar('='), PR_TRUE, valueOffset); + if (equal >= 0) + { + PRInt32 startQuote = line.FindChar(PRUnichar('\"'), PR_TRUE, equal + 1); + if (startQuote >= 0) + { + PRInt32 endQuote = line.FindChar(PRUnichar('\"'), PR_TRUE, startQuote + 1); + if (endQuote >= 0) + { + line.Mid(valueAttrib, startQuote+1, endQuote-startQuote-1); + } + } + else + { + // if value attribute's "value" isn't quoted, get the first word... ? + valueAttrib = line; + valueAttrib.Cut(0, equal+1); + valueAttrib = valueAttrib.Trim(" \t"); + PRInt32 space = valueAttrib.FindCharInSet(" \t>", 0); + if (space > 0) + { + valueAttrib.Truncate(space); + } + } + } + } + else if (line.Find("user", PR_TRUE) >= 0) + { + valueAttrib = text; + } + + // XXX should ignore if mode=browser is specified + // XXX need to do this better + if (line.RFind("mode=browser", PR_TRUE) >= 0) + continue; + + if ((nameAttrib.Length() > 0) && (valueAttrib.Length() > 0)) + { + if (input.Length() > 0) + { + input += "&"; + } + input += nameAttrib; + input += "="; + input += valueAttrib; + } + } + } + return(rv); +} + + + +nsresult +InternetSearchDataSource::GetURL(nsIRDFResource *source, nsIRDFLiteral** aResult) +{ + const char *uri = nsnull; + source->GetValueConst( &uri ); + nsAutoString url(uri); + nsIRDFLiteral *literal; + gRDFService->GetLiteral(url.GetUnicode(), &literal); + *aResult = literal; + return NS_OK; +} + + + +// Search class for Netlib callback + + + +InternetSearchDataSourceCallback::InternetSearchDataSourceCallback(nsIRDFDataSource *ds, nsIRDFResource *parent, nsIRDFResource *engine) + : mDataSource(ds), + mParent(parent), + mEngine(engine), + mLine(nsnull) +{ + NS_INIT_REFCNT(); + NS_IF_ADDREF(mDataSource); + NS_IF_ADDREF(mParent); + NS_IF_ADDREF(mEngine); + + if (gRefCnt++ == 0) + { + nsresult rv = nsServiceManager::GetService(kRDFServiceCID, + nsIRDFService::GetIID(), + (nsISupports**) &gRDFService); + + PR_ASSERT(NS_SUCCEEDED(rv)); + + gRDFService->GetResource(kURINC_LastSearchRoot, &kNC_LastSearchRoot); + gRDFService->GetResource(NC_NAMESPACE_URI "child", &kNC_Child); + gRDFService->GetResource(NC_NAMESPACE_URI "URL", &kNC_URL); + gRDFService->GetResource(NC_NAMESPACE_URI "Name", &kNC_Name); + gRDFService->GetResource(NC_NAMESPACE_URI "data", &kNC_Data); + gRDFService->GetResource(NC_NAMESPACE_URI "Relevance", &kNC_Relevance); + gRDFService->GetResource(NC_NAMESPACE_URI "Relevance?sort=true", &kNC_RelevanceSort); + gRDFService->GetResource(NC_NAMESPACE_URI "Site", &kNC_Site); + gRDFService->GetResource(NC_NAMESPACE_URI "Engine", &kNC_Engine); + gRDFService->GetResource(NC_NAMESPACE_URI "loading", &kNC_loading); + gRDFService->GetResource(NC_NAMESPACE_URI "HTML", &kNC_HTML); + gRDFService->GetResource(NC_NAMESPACE_URI "Banner", &kNC_Banner); + } +} + + + +InternetSearchDataSourceCallback::~InternetSearchDataSourceCallback() +{ + NS_IF_RELEASE(mDataSource); + NS_IF_RELEASE(mParent); + NS_IF_RELEASE(mEngine); + + if (mLine) + { + nsCRT::free(mLine); + mLine = nsnull; + } + + if (--gRefCnt == 0) + { + NS_RELEASE(kNC_LastSearchRoot); + NS_RELEASE(kNC_Child); + NS_RELEASE(kNC_URL); + NS_RELEASE(kNC_Name); + NS_RELEASE(kNC_Data); + NS_RELEASE(kNC_Relevance); + NS_RELEASE(kNC_RelevanceSort); + NS_RELEASE(kNC_Site); + NS_RELEASE(kNC_Engine); + NS_RELEASE(kNC_loading); + NS_RELEASE(kNC_HTML); + NS_RELEASE(kNC_Banner); + } +} + + + +nsresult +InternetSearchDataSourceCallback::CreateAnonymousResource(nsCOMPtr* aResult) +{ + static PRInt32 gNext = 0; + + if (! gNext) + { + LL_L2I(gNext, PR_Now()); + } + + nsresult rv; + nsAutoString uri(kURINC_SearchResultsAnonymous); + uri.Append("#$"); + uri.Append(++gNext, 16); + + char *uriC = uri.ToNewCString(); + if (uriC) + { + rv = gRDFService->GetResource(uriC, getter_AddRefs(*aResult)); + nsCRT::free(uriC); + } + else + { + rv = NS_ERROR_NULL_POINTER; + } + return(rv); +} + + + +// stream observer methods + + + +NS_IMETHODIMP +#ifdef NECKO +InternetSearchDataSourceCallback::OnStartRequest(nsIChannel* channel, nsISupports *ctxt) +#else +InternetSearchDataSourceCallback::OnStartRequest(nsIURI *aURL, const char *aContentType) +#endif +{ + nsAutoString trueStr("true"); + nsIRDFLiteral *literal = nsnull; + nsresult rv; + +#ifdef DEBUG + printf("InternetSearchDataSourceCallback::OnStartRequest entered.\n"); +#endif + + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(trueStr.GetUnicode(), &literal))) + { + mDataSource->Assert(mParent, kNC_loading, literal, PR_TRUE); + + // Don't starting loading animation for engine here. + // Instead, we now do it when the URI is initially opened + // which gives a longer and more accurate animation period + +// mDataSource->Assert(mEngine, kNC_loading, literal, PR_TRUE); + NS_RELEASE(literal); + } + return(NS_OK); +} + + + +#ifndef NECKO +NS_IMETHODIMP +InternetSearchDataSourceCallback::OnProgress(nsIURI* aURL, PRUint32 aProgress, PRUint32 aProgressMax) +{ + return(NS_OK); +} + + + +NS_IMETHODIMP +InternetSearchDataSourceCallback::OnStatus(nsIURI* aURL, const PRUnichar* aMsg) +{ + return(NS_OK); +} +#endif + + + +NS_IMETHODIMP +#ifdef NECKO +InternetSearchDataSourceCallback::OnStopRequest(nsIChannel* channel, nsISupports *ctxt, + nsresult status, const PRUnichar *errorMsg) +#else +InternetSearchDataSourceCallback::OnStopRequest(nsIURI* aURL, nsresult aStatus, const PRUnichar* aMsg) +#endif +{ + nsAutoString trueStr("true"); + nsIRDFLiteral *literal = nsnull; + nsresult rv; +#ifdef NECKO + nsCOMPtr aURL; + rv = channel->GetURI(getter_AddRefs(aURL)); + if (NS_FAILED(rv)) return rv; +#endif + + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(trueStr.GetUnicode(), &literal))) + { + mDataSource->Unassert(mParent, kNC_loading, literal); + mDataSource->Unassert(mEngine, kNC_loading, literal); + NS_RELEASE(literal); + } + + if (!mLine) + { +#ifdef DEBUG + printf(" *** InternetSearchDataSourceCallback::OnStopRequest: no data.\n\n"); +#endif + + return(NS_OK); + } + +#if 0 + printf("\n\n%s\n\n", mLine); +#endif + + nsAutoString htmlResults(mLine); + nsCRT::free(mLine); + mLine = nsnull; + + // save HTML result page for this engine + const PRUnichar *htmlUni = htmlResults.GetUnicode(); + if (htmlUni) + { + nsCOMPtr htmlLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(htmlUni, getter_AddRefs(htmlLiteral)))) + { + rv = mDataSource->Assert(mEngine, kNC_HTML, htmlLiteral, PR_TRUE); + } + } + + // get data out of graph + nsAutoString data(""); + nsCOMPtr dataNode; + if (NS_FAILED(rv = mDataSource->GetTarget(mEngine, kNC_Data, PR_TRUE, getter_AddRefs(dataNode)))) + { + return(rv); + } + nsCOMPtr 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(""); + + 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); + +#if 0 + 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 + + // look for banner once in entire document + nsCOMPtr 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.Find(resultListEndStr, PR_TRUE); + if (resultListEnd >= 0) + { + htmlResults.Truncate(resultListEnd); + } + } + + PRBool trimItemEnd = PR_TRUE; + // if resultItemEndStr is not specified, try making it the same as resultItemStartStr + if (resultItemEndStr.Length() < 1) + { + resultItemEndStr = resultItemStartStr; + trimItemEnd = PR_FALSE; + } + + while(PR_TRUE) + { + PRInt32 resultItemStart; + resultItemStart = htmlResults.Find(resultItemStartStr, PR_TRUE); + if (resultItemStart < 0) break; + + htmlResults.Cut(0, resultItemStart + resultItemStartStr.Length()); + + PRInt32 resultItemEnd = htmlResults.Find(resultItemEndStr, PR_TRUE ); + 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); + } + +#if 0 + char *results = resultItem.ToNewCString(); + if (results) + { + printf("\n----- Search result: '%s'\n\n", results); + nsCRT::free(results); + results = nsnull; + } +#endif + + // look for href + PRInt32 hrefOffset = resultItem.Find("HREF=", PR_TRUE); + if (hrefOffset < 0) + { +#ifdef DEBUG + printf("\n***** Unable to find HREF!\n\n"); +#endif + continue; + } + + nsAutoString hrefStr(""); + PRInt32 quoteStartOffset = resultItem.FindCharInSet("\"\'>", hrefOffset); + PRInt32 quoteEndOffset; + if (quoteStartOffset < hrefOffset) + { + // handle case where HREF isn't quoted + quoteStartOffset = hrefOffset + nsCRT::strlen("HREF="); + quoteEndOffset = resultItem.FindCharInSet(">", quoteStartOffset); + if (quoteEndOffset < quoteStartOffset) continue; + } + else + { + if (resultItem[quoteStartOffset] == PRUnichar('>')) + { + // handle case where HREF isn't quoted + 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; + + // check to see if this needs to be an absolute URL + if (hrefStr[0] == PRUnichar('/')) + { +#ifdef NECKO + char *host = nsnull, *protocol = nsnull; +#else + const char *host = nsnull, *protocol = nsnull; +#endif + aURL->GetHost(&host); +#ifdef NECKO + aURL->GetScheme(&protocol); +#else + aURL->GetProtocol(&protocol); +#endif + if (host && protocol) + { + nsAutoString temp; + temp += protocol; + temp += "://"; + temp += host; + temp += hrefStr; + + hrefStr = temp; + } +#ifdef NECKO + if (host) nsCRT::free(host); + if (protocol) nsCRT::free(protocol); +#endif + } + + char *href = hrefStr.ToNewCString(); + if (!href) continue; + + nsAutoString site(href); + +#if 0 + printf("HREF: '%s'\n", href); +#endif + + nsCOMPtr res; + +// #define OLDWAY +#ifdef OLDWAY + rv = gRDFService->GetResource(href, getter_AddRefs(res)); +#else + const char *parentURI = nsnull; + mParent->GetValueConst(&parentURI); + if (!parentURI) break; + + // save HREF attribute as URL + if (NS_SUCCEEDED(rv = CreateAnonymousResource(&res))) + { + const PRUnichar *hrefUni = hrefStr.GetUnicode(); + if (hrefUni) + { + nsCOMPtr hrefLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(hrefUni, getter_AddRefs(hrefLiteral)))) + { + mDataSource->Assert(res, kNC_URL, hrefLiteral, PR_TRUE); + } + } + } +#endif + + nsCRT::free(href); + href = nsnull; + if (NS_FAILED(rv)) continue; + + // set HTML response chunk + const PRUnichar *htmlResponseUni = resultItem.GetUnicode(); + if (htmlResponseUni) + { + nsCOMPtr htmlResponseLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(htmlResponseUni, getter_AddRefs(htmlResponseLiteral)))) + { + if (htmlResponseLiteral) + { + mDataSource->Assert(res, kNC_HTML, htmlResponseLiteral, PR_TRUE); + } + } + } + + // set banner (if we have one) + if (bannerLiteral) + { + mDataSource->Assert(res, kNC_Banner, bannerLiteral, PR_TRUE); + } + + // look for Site (if it isn't already set) + nsCOMPtr oldSiteRes = nsnull; + mDataSource->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 siteLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(siteUni, getter_AddRefs(siteLiteral)))) + { + if (siteLiteral) + { + mDataSource->Assert(res, kNC_Site, siteLiteral, PR_TRUE); + } + } + } + } + } + } + + // look for name + PRInt32 anchorEnd = resultItem.FindCharInSet(">", quoteEndOffset); + if (anchorEnd < quoteEndOffset) + { +#ifdef DEBUG + printf("\n\nSearch: Unable to find ending > when computing name.\n\n"); +#endif + continue; + } +// PRInt32 anchorStop = resultItem.FindChar(PRUnichar('<'), PR_TRUE, quoteEndOffset); + PRInt32 anchorStop = resultItem.Find("", PR_TRUE, quoteEndOffset); + if (anchorStop < anchorEnd) + { +#ifdef DEBUG + printf("\n\nSearch: Unable to find tag to compute name.\n\n"); +#endif + continue; + } + + nsAutoString nameStr; + resultItem.Mid(nameStr, anchorEnd + 1, anchorStop - anchorEnd - 1); + + // munge any """ in name + PRInt32 quotOffset; + while ((quotOffset = nameStr.Find(""", PR_TRUE)) >= 0) + { + nameStr.Cut(quotOffset, strlen(""")); + nameStr.Insert(PRUnichar('\"'), quotOffset); + } + + // munge any "&" in name + PRInt32 ampOffset; + while ((ampOffset = nameStr.Find("&", PR_TRUE)) >= 0) + { + nameStr.Cut(ampOffset, strlen("&")); + nameStr.Insert(PRUnichar('&'), ampOffset); + } + + // munge any " " in name + PRInt32 nbspOffset; + while ((nbspOffset = nameStr.Find(" ", PR_TRUE)) >= 0) + { + nameStr.Cut(nbspOffset, strlen(" ")); + nameStr.Insert(PRUnichar(' '), nbspOffset); + } + + // munge any "<" in name + PRInt32 ltOffset; + while ((ltOffset = nameStr.Find("<", PR_TRUE)) >= 0) + { + nameStr.Cut(ltOffset, strlen("<")); + nameStr.Insert(PRUnichar('<'), ltOffset); + } + + // munge any ">" in name + PRInt32 gtOffset; + while ((gtOffset = nameStr.Find(">", PR_TRUE)) >= 0) + { + nameStr.Cut(gtOffset, strlen(">")); + nameStr.Insert(PRUnichar('>'), gtOffset); + } + + // munge out anything inside of HTML "<" / ">" tags + PRInt32 tagStartOffset; + while ((tagStartOffset = nameStr.FindCharInSet("<", 0)) >= 0) + { + PRInt32 tagEndOffset = nameStr.FindCharInSet(">", tagStartOffset); + if (tagEndOffset <= tagStartOffset) break; + nameStr.Cut(tagStartOffset, tagEndOffset - tagStartOffset + 1); + } + + // cut out any CRs or LFs + PRInt32 eolOffset; + while ((eolOffset = nameStr.FindCharInSet("\n\r", 0)) >= 0) + { + nameStr.Cut(eolOffset, 1); + } + // and trim name + nameStr = nameStr.Trim(" \t"); + + // look for Name (if it isn't already set) + nsCOMPtr oldNameRes = nsnull; + mDataSource->GetTarget(res, kNC_Name, PR_TRUE, getter_AddRefs(oldNameRes)); + if (!oldNameRes) + { + if (nameStr.Length() > 0) + { + const PRUnichar *nameUni = nameStr.GetUnicode(); + if (nameUni) + { + nsCOMPtr nameLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(nameUni, getter_AddRefs(nameLiteral)))) + { + if (nameLiteral) + { + mDataSource->Assert(res, kNC_Name, nameLiteral, PR_TRUE); + } + } + } + } + } + + // look for relevance + nsAutoString relItem; + PRInt32 relStart; + if ((relStart = resultItem.Find(relevanceStartStr, PR_TRUE)) >= 0) + { + PRInt32 relEnd = resultItem.Find(relevanceEndStr, PR_TRUE); + if (relEnd > relStart) + { + resultItem.Mid(relItem, relStart + relevanceStartStr.Length(), + relEnd - relStart - relevanceStartStr.Length()); + } + } + + // look for Relevance (if it isn't already set) + nsCOMPtr oldRelRes = nsnull; + mDataSource->GetTarget(res, kNC_Relevance, PR_TRUE, getter_AddRefs(oldRelRes)); + if (!oldRelRes) + { + if (relItem.Length() > 0) + { + // save real relevance + const PRUnichar *relUni = relItem.GetUnicode(); + if (relUni) + { + // take out any characters that aren't numeric or "%" + nsAutoString relStr(relUni); + PRInt32 len = relStr.Length(); + for (PRInt32 x=len-1; x>=0; x--) + { + PRUnichar ch; + ch = relStr.CharAt(x); + if ((ch != PRUnichar('%')) && + ((ch < PRUnichar('0')) || (ch > PRUnichar('9')))) + { + relStr.Cut(x, 1); + } + } + // make sure it ends with a "%" + len = relStr.Length(); + if (len > 0) + { + PRUnichar ch; + ch = relStr.CharAt(len - 1); + if (ch != PRUnichar('%')) + { + relStr += PRUnichar('%'); + } + } + else + { + relStr = "-"; + } + + relUni = relStr.GetUnicode(); + + nsCOMPtr relLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(relUni, getter_AddRefs(relLiteral)))) + { + if (relLiteral) + { + mDataSource->Assert(res, kNC_Relevance, relLiteral, PR_TRUE); + } + } + } + + // If its a percentage, remove "%" + if (relItem[relItem.Length()-1] == PRUnichar('%')) + { + relItem.Cut(relItem.Length()-1, 1); + } + + // left-pad with "0"s and set special sorting value + nsAutoString zero("000"); + if (relItem.Length() < 3) + { + relItem.Insert(zero, 0, 3-relItem.Length()); + } + + const PRUnichar *relSortUni = relItem.GetUnicode(); + if (relSortUni) + { + nsCOMPtr relSortLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(relSortUni, getter_AddRefs(relSortLiteral)))) + { + if (relSortLiteral) + { + mDataSource->Assert(res, kNC_RelevanceSort, relSortLiteral, PR_TRUE); + } + } + } + } + } + + // set reference to engine this came from (if it isn't already set) + nsCOMPtr oldEngineRes = nsnull; + mDataSource->GetTarget(res, kNC_Engine, PR_TRUE, getter_AddRefs(oldEngineRes)); + if (!oldEngineRes) + { + nsAutoString engineStr; + if (NS_SUCCEEDED(rv = InternetSearchDataSource::GetData(data, "search", "name", engineStr))) + { + const PRUnichar *engineUni = engineStr.GetUnicode(); + nsCOMPtr engineLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(engineUni, getter_AddRefs(engineLiteral)))) + { + if (engineLiteral) + { + mDataSource->Assert(res, kNC_Engine, engineLiteral, PR_TRUE); + } + } + } + } +#ifdef OLDWAY + // Note: always add in parent-child relationship last! (if it isn't already set) + PRBool parentHasChildFlag = PR_FALSE; + mDataSource->HasAssertion(mParent, kNC_Child, res, PR_TRUE, &parentHasChildFlag); + if (parentHasChildFlag == PR_FALSE) +#endif + { + rv = mDataSource->Assert(mParent, kNC_Child, res, PR_TRUE); + } + + // Persist this under kNC_LastSearchRoot + if (mDataSource) + { + rv = mDataSource->Assert(kNC_LastSearchRoot, kNC_Child, res, PR_TRUE); + } + + } + return(NS_OK); +} + + + +// stream listener methods + + + +NS_IMPL_ISUPPORTS(InternetSearchDataSourceCallback, InternetSearchDataSourceCallback::GetIID()); + + + +NS_IMETHODIMP +InternetSearchDataSourceCallback::OnDataAvailable(nsIChannel* channel, nsISupports *ctxt, + nsIInputStream *aIStream, PRUint32 sourceOffset, PRUint32 aLength) +{ + nsresult rv = NS_OK; + + if (aLength > 0) + { + nsAutoString line; + if (mLine) + { + line += mLine; + nsCRT::free(mLine); + mLine = nsnull; + } + + char buffer[257]; + while (aLength > 0) + { + PRUint32 count=0, numBytes = (aLength > sizeof(buffer)-1 ? sizeof(buffer)-1 : aLength); + if (NS_FAILED(rv = aIStream->Read(buffer, numBytes, &count)) || count == 0) + { +#ifdef DEBUG + printf("Search datasource read failure.\n"); +#endif + break; + } + if (numBytes != count) + { +#ifdef DEBUG + printf("Search datasource read # of bytes failure.\n"); +#endif + break; + } + buffer[count] = '\0'; + line += buffer; + aLength -= count; + } + mLine = line.ToNewCString(); + } + return(rv); +} diff --git a/suite/browser/src/nsLocalSearchService.cpp b/suite/browser/src/nsLocalSearchService.cpp new file mode 100755 index 000000000000..9323563277ff --- /dev/null +++ b/suite/browser/src/nsLocalSearchService.cpp @@ -0,0 +1,937 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8; c-file-style: "stroustrup" -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + Implementation for a find RDF data store. + */ + +#include // for toupper() +#include +#include "nscore.h" +#include "nsCOMPtr.h" +#include "nsIRDFDataSource.h" +#include "nsIRDFNode.h" +#include "nsIRDFObserver.h" +#include "nsIServiceManager.h" +#include "nsISupportsArray.h" +#include "nsEnumeratorUtils.h" +#include "nsString.h" +#include "nsVoidArray.h" // XXX introduces dependency on raptorbase +#include "nsXPIDLString.h" +#include "nsRDFCID.h" +//#include "rdfutil.h" +#include "nsIRDFService.h" +#include "xp_core.h" +#include "plhash.h" +#include "plstr.h" +#include "prmem.h" +#include "prprf.h" +#include "prio.h" +#include "rdf.h" +#include "nsISearchService.h" + +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID); + + +typedef struct _findTokenStruct +{ + char *token; + char *value; +} findTokenStruct, *findTokenPtr; + + + +class LocalSearchDataSource : public nsILocalSearchService +{ +private: + nsCOMPtr mObservers; + + static PRInt32 gRefCnt; + + // pseudo-constants + static nsIRDFResource *kNC_Child; + static nsIRDFResource *kNC_Name; + static nsIRDFResource *kNC_URL; + static nsIRDFResource *kNC_FindObject; + static nsIRDFResource *kNC_pulse; + static nsIRDFResource *kRDF_InstanceOf; + static nsIRDFResource *kRDF_type; + +friend NS_IMETHODIMP NS_NewLocalSearchService(nsISupports* aOuter, REFNSIID aIID, void** aResult); + + NS_METHOD getFindResults(nsIRDFResource *source, nsISimpleEnumerator** aResult); + + NS_METHOD getFindName(nsIRDFResource *source, nsIRDFLiteral** aResult); + + NS_METHOD parseResourceIntoFindTokens(nsIRDFResource *u, + findTokenPtr tokens); + NS_METHOD doMatch(nsIRDFLiteral *literal, char *matchMethod, + char *matchText); + NS_METHOD parseFindURL(nsIRDFResource *u, + nsISupportsArray *array); + +public: + + NS_DECL_ISUPPORTS + + LocalSearchDataSource(void); + virtual ~LocalSearchDataSource(void); + + nsresult Init(); + + // nsIRDFDataSource methods + + NS_IMETHOD GetURI(char **uri); + NS_IMETHOD GetSource(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsIRDFResource **source /* out */); + NS_IMETHOD GetSources(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsISimpleEnumerator **sources /* out */); + NS_IMETHOD GetTarget(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsIRDFNode **target /* out */); + NS_IMETHOD GetTargets(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsISimpleEnumerator **targets /* out */); + NS_IMETHOD Assert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv); + NS_IMETHOD Unassert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target); + NS_IMETHOD Change(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aOldTarget, + nsIRDFNode* aNewTarget); + NS_IMETHOD Move(nsIRDFResource* aOldSource, + nsIRDFResource* aNewSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget); + NS_IMETHOD HasAssertion(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + PRBool *hasAssertion /* out */); + NS_IMETHOD ArcLabelsIn(nsIRDFNode *node, + nsISimpleEnumerator **labels /* out */); + NS_IMETHOD ArcLabelsOut(nsIRDFResource *source, + nsISimpleEnumerator **labels /* out */); + NS_IMETHOD GetAllResources(nsISimpleEnumerator** aCursor); + NS_IMETHOD AddObserver(nsIRDFObserver *n); + NS_IMETHOD RemoveObserver(nsIRDFObserver *n); + NS_IMETHOD GetAllCommands(nsIRDFResource* source, + nsIEnumerator/**/** commands); + NS_IMETHOD GetAllCmds(nsIRDFResource* source, + nsISimpleEnumerator/**/** commands); + NS_IMETHOD IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult); + NS_IMETHOD DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments); +}; + + + +static nsIRDFService *gRDFService = nsnull; +static LocalSearchDataSource *gLocalSearchDataSource = nsnull; + +PRInt32 LocalSearchDataSource::gRefCnt; + +nsIRDFResource *LocalSearchDataSource::kNC_Child; +nsIRDFResource *LocalSearchDataSource::kNC_Name; +nsIRDFResource *LocalSearchDataSource::kNC_URL; +nsIRDFResource *LocalSearchDataSource::kNC_FindObject; +nsIRDFResource *LocalSearchDataSource::kNC_pulse; +nsIRDFResource *LocalSearchDataSource::kRDF_InstanceOf; +nsIRDFResource *LocalSearchDataSource::kRDF_type; + +static const char kFindProtocol[] = "find:"; + + + +static PRBool +isFindURI(nsIRDFResource *r) +{ + PRBool isFindURIFlag = PR_FALSE; + const char *uri = nsnull; + + r->GetValueConst(&uri); + if ((uri) && (!strncmp(uri, kFindProtocol, sizeof(kFindProtocol) - 1))) + { + isFindURIFlag = PR_TRUE; + } + return(isFindURIFlag); +} + + + +LocalSearchDataSource::LocalSearchDataSource(void) +{ + NS_INIT_REFCNT(); + + if (gRefCnt++ == 0) + { + nsresult rv = nsServiceManager::GetService(kRDFServiceCID, + nsIRDFService::GetIID(), + (nsISupports**) &gRDFService); + + PR_ASSERT(NS_SUCCEEDED(rv)); + + gRDFService->GetResource(NC_NAMESPACE_URI "child", &kNC_Child); + gRDFService->GetResource(NC_NAMESPACE_URI "Name", &kNC_Name); + gRDFService->GetResource(NC_NAMESPACE_URI "URL", &kNC_URL); + gRDFService->GetResource(NC_NAMESPACE_URI "FindObject", &kNC_FindObject); + gRDFService->GetResource(NC_NAMESPACE_URI "pulse", &kNC_pulse); + + gRDFService->GetResource(RDF_NAMESPACE_URI "instanceOf", &kRDF_InstanceOf); + gRDFService->GetResource(RDF_NAMESPACE_URI "type", &kRDF_type); + + gLocalSearchDataSource = this; + } +} + + + +LocalSearchDataSource::~LocalSearchDataSource (void) +{ + if (--gRefCnt == 0) + { + NS_RELEASE(kNC_Child); + NS_RELEASE(kNC_Name); + NS_RELEASE(kNC_URL); + NS_RELEASE(kNC_FindObject); + NS_RELEASE(kNC_pulse); + NS_RELEASE(kRDF_InstanceOf); + NS_RELEASE(kRDF_type); + + gLocalSearchDataSource = nsnull; + nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService); + gRDFService = nsnull; + } +} + + + +nsresult +LocalSearchDataSource::Init() +{ + nsresult rv = NS_ERROR_OUT_OF_MEMORY; + +#if 0 + // register this as a named data source with the service manager + if (NS_FAILED(rv = gRDFService->RegisterDataSource(this, PR_FALSE))) + return(rv); +#endif + + return(rv); +} + + + +NS_IMPL_ISUPPORTS(LocalSearchDataSource, nsIRDFDataSource::GetIID()); + + + +NS_IMETHODIMP +LocalSearchDataSource::GetURI(char **uri) +{ + NS_PRECONDITION(uri != nsnull, "null ptr"); + if (! uri) + return NS_ERROR_NULL_POINTER; + + if ((*uri = nsXPIDLCString::Copy("rdf:find")) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + return NS_OK; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetSource(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFResource** source /* out */) +{ + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + *source = nsnull; + return NS_RDF_NO_VALUE; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetSources(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsISimpleEnumerator **sources /* out */) +{ + NS_NOTYETIMPLEMENTED("write me"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetTarget(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsIRDFNode **target /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_RDF_NO_VALUE; + + // we only have positive assertions in the find data source. + if (! tv) + return rv; + + if (isFindURI(source)) + { + if (property == kNC_Name) + { +// rv = GetName(source, &array); + } + else if (property == kNC_URL) + { + // note: lie and say there is no URL +// rv = GetURL(source, &array); + nsAutoString url(""); + nsIRDFLiteral *literal; + gRDFService->GetLiteral(url.GetUnicode(), &literal); + *target = literal; + rv = NS_OK; + } + else if (property == kRDF_type) + { + const char *uri = nsnull; + rv = kNC_FindObject->GetValueConst(&uri); + if (NS_FAILED(rv)) return rv; + + nsAutoString url(uri); + nsIRDFLiteral *literal; + gRDFService->GetLiteral(url.GetUnicode(), &literal); + + *target = literal; + return NS_OK; + } + else if (property == kNC_pulse) + { + nsAutoString pulse("15"); + nsIRDFLiteral *pulseLiteral; + rv = gRDFService->GetLiteral(pulse.GetUnicode(), &pulseLiteral); + if (NS_FAILED(rv)) return rv; + + *target = pulseLiteral; + return NS_OK; + } + } + return NS_RDF_NO_VALUE; +} + + + +NS_METHOD +LocalSearchDataSource::parseResourceIntoFindTokens(nsIRDFResource *u, findTokenPtr tokens) +{ + const char *uri = nsnull; + char *id, *token, *value; + int loop; + nsresult rv; + + if (NS_FAILED(rv = u->GetValueConst(&uri))) return(rv); + +#ifdef DEBUG + printf("Find: %s\n", (const char*) uri); +#endif + + if (!(id = PL_strdup(uri + sizeof(kFindProtocol) - 1))) + return(NS_ERROR_OUT_OF_MEMORY); + + /* parse ID, build up token list */ + if ((token = strtok(id, "&")) != NULL) + { + while (token != NULL) + { + if ((value = strstr(token, "=")) != NULL) + { + *value++ = '\0'; + } + for (loop=0; tokens[loop].token != NULL; loop++) + { + if (!strcmp(token, tokens[loop].token)) + { + tokens[loop].value = PL_strdup(value); + break; + } + } + token = strtok(NULL, "&"); + } + } + PL_strfree(id); + return(NS_OK); +} + + + +NS_METHOD +LocalSearchDataSource::doMatch(nsIRDFLiteral *literal, char *matchMethod, char *matchText) +{ + PRBool found = PR_FALSE; + + if ((nsnull == literal) || (nsnull == matchMethod) || (nsnull == matchText)) + return(found); + + nsXPIDLString str; + literal->GetValue( getter_Copies(str) ); + if (! str) return(found); + nsAutoString value(str); + + if (!PL_strcmp(matchMethod, "contains")) + { + if (value.Find(matchText, PR_TRUE) >= 0) + found = PR_TRUE; + } + else if (!PL_strcmp(matchMethod, "startswith")) + { + if (value.Find(matchText, PR_TRUE) == 0) + found = PR_TRUE; + } + else if (!PL_strcmp(matchMethod, "endswith")) + { + PRInt32 pos = value.RFind(matchText, PR_TRUE); + if ((pos >= 0) && (pos == (value.Length() - PRInt32(strlen(matchText))))) + found = PR_TRUE; + } + else if (!PL_strcmp(matchMethod, "is")) + { + if (value.EqualsIgnoreCase(matchText)) + found = PR_TRUE; + } + else if (!PL_strcmp(matchMethod, "isnot")) + { + if (!value.EqualsIgnoreCase(matchText)) + found = PR_TRUE; + } + else if (!PL_strcmp(matchMethod, "doesntcontain")) + { + if (value.Find(matchText, PR_TRUE) < 0) + found = PR_TRUE; + } + return(found); +} + + + +NS_METHOD +LocalSearchDataSource::parseFindURL(nsIRDFResource *u, nsISupportsArray *array) +{ + findTokenStruct tokens[5]; + nsresult rv; + int loop; + + /* build up a token list */ + tokens[0].token = "datasource"; tokens[0].value = NULL; + tokens[1].token = "match"; tokens[1].value = NULL; + tokens[2].token = "method"; tokens[2].value = NULL; + tokens[3].token = "text"; tokens[3].value = NULL; + tokens[4].token = NULL; tokens[4].value = NULL; + + // parse find URI, get parameters, search in appropriate datasource(s), return results + if (NS_SUCCEEDED(rv = parseResourceIntoFindTokens(u, tokens))) + { + nsIRDFDataSource *datasource; + if (NS_SUCCEEDED(rv = gRDFService->GetDataSource(tokens[0].value, &datasource))) + { + nsISimpleEnumerator *cursor = nsnull; + if (NS_SUCCEEDED(rv = datasource->GetAllResources(&cursor))) + { + while (1) + { + PRBool hasMore; + rv = cursor->HasMoreElements(&hasMore); + if (NS_FAILED(rv)) + break; + + if (! hasMore) + break; + + nsCOMPtr isupports; + rv = cursor->GetNext(getter_AddRefs(isupports)); + if (NS_SUCCEEDED(rv)) + { + nsIRDFResource *source = nsnull; + if (NS_SUCCEEDED(rv = isupports->QueryInterface(nsIRDFResource::GetIID(), (void **)&source))) + { + const char *uri = nsnull; + source->GetValueConst(&uri); + + // never match against a "find:" URI + if ((uri) && (PL_strncmp(uri, kFindProtocol, sizeof(kFindProtocol) - 1))) + { + nsIRDFResource *property = nsnull; + if (NS_SUCCEEDED(rv = gRDFService->GetResource(tokens[1].value, &property)) && + (rv != NS_RDF_NO_VALUE) && (nsnull != property)) + { + nsIRDFNode *value = nsnull; + if (NS_SUCCEEDED(rv = datasource->GetTarget(source, property, PR_TRUE, &value)) && + (rv != NS_RDF_NO_VALUE) && (nsnull != value)) + { + nsIRDFLiteral *literal = nsnull; + if (NS_SUCCEEDED(rv = value->QueryInterface(nsIRDFLiteral::GetIID(), (void **)&literal)) && + (rv != NS_RDF_NO_VALUE) && (nsnull != literal)) + { + if (PR_TRUE == doMatch(literal, tokens[2].value, tokens[3].value)) + { + array->AppendElement(source); + } + NS_RELEASE(literal); + } + } + NS_RELEASE(property); + } + } + NS_RELEASE(source); + } + } + } + if (rv == NS_RDF_CURSOR_EMPTY) + { + rv = NS_OK; + } + NS_RELEASE(cursor); + } + NS_RELEASE(datasource); + } + } + /* free values in token list */ + for (loop=0; tokens[loop].token != NULL; loop++) + { + if (tokens[loop].value != NULL) + { + PL_strfree(tokens[loop].value); + tokens[loop].value = NULL; + } + } + return(rv); +} + + + +NS_METHOD +LocalSearchDataSource::getFindResults(nsIRDFResource *source, nsISimpleEnumerator** aResult) +{ + nsresult rv; + nsCOMPtr nameArray; + rv = NS_NewISupportsArray( getter_AddRefs(nameArray) ); + if (NS_FAILED(rv)) return rv; + + rv = parseFindURL(source, nameArray); + if (NS_FAILED(rv)) return rv; + + nsISimpleEnumerator* result = new nsArrayEnumerator(nameArray); + if (! result) + return(NS_ERROR_OUT_OF_MEMORY); + + NS_ADDREF(result); + *aResult = result; + + return NS_OK; +} + + + +NS_METHOD +LocalSearchDataSource::getFindName(nsIRDFResource *source, nsIRDFLiteral** aResult) +{ + // XXX construct find URI human-readable name + *aResult = nsnull; + return(NS_OK); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetTargets(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsISimpleEnumerator **targets /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(targets != nsnull, "null ptr"); + if (! targets) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_ERROR_FAILURE; + + // we only have positive assertions in the find data source. + if (! tv) + return rv; + + if (isFindURI(source)) + { + if (property == kNC_Child) + { + return getFindResults(source, targets); + } + else if (property == kNC_Name) + { + nsCOMPtr name; + rv = getFindName(source, getter_AddRefs(name)); + if (NS_FAILED(rv)) return rv; + + nsISimpleEnumerator* result = + new nsSingletonEnumerator(name); + + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(result); + *targets = result; + return NS_OK; + } + else if (property == kRDF_type) + { + nsXPIDLCString uri; + rv = kNC_FindObject->GetValue( getter_Copies(uri) ); + if (NS_FAILED(rv)) return rv; + + nsAutoString url(uri); + nsIRDFLiteral *literal; + rv = gRDFService->GetLiteral(url.GetUnicode(), &literal); + if (NS_FAILED(rv)) return rv; + + nsISimpleEnumerator* result = new nsSingletonEnumerator(literal); + + NS_RELEASE(literal); + + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(result); + *targets = result; + return NS_OK; + } + else if (property == kNC_pulse) + { + nsAutoString pulse("15"); + nsIRDFLiteral *pulseLiteral; + rv = gRDFService->GetLiteral(pulse.GetUnicode(), &pulseLiteral); + if (NS_FAILED(rv)) return rv; + + nsISimpleEnumerator* result = new nsSingletonEnumerator(pulseLiteral); + + NS_RELEASE(pulseLiteral); + + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(result); + *targets = result; + return NS_OK; + } + } + + return NS_NewEmptyEnumerator(targets); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::Assert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::Unassert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::Change(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aOldTarget, + nsIRDFNode* aNewTarget) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::Move(nsIRDFResource* aOldSource, + nsIRDFResource* aNewSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::HasAssertion(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + PRBool *hasAssertion /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(hasAssertion != nsnull, "null ptr"); + if (! hasAssertion) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + + *hasAssertion = PR_FALSE; + + // we only have positive assertions in the find data source. + if (! tv) + return rv; + + if (isFindURI(source)) + { + if (property == kRDF_type) + { + if ((nsIRDFResource *)target == kRDF_type) + { + *hasAssertion = PR_TRUE; + } + } + } + return (rv); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::ArcLabelsIn(nsIRDFNode *node, + nsISimpleEnumerator ** labels /* out */) +{ + NS_NOTYETIMPLEMENTED("write me"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::ArcLabelsOut(nsIRDFResource *source, + nsISimpleEnumerator **labels /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(labels != nsnull, "null ptr"); + if (! labels) + return NS_ERROR_NULL_POINTER; + + nsresult rv; + + if (isFindURI(source)) + { + nsCOMPtr array; + rv = NS_NewISupportsArray( getter_AddRefs(array) ); + if (NS_FAILED(rv)) return rv; + + array->AppendElement(kNC_Child); + array->AppendElement(kNC_pulse); + + nsISimpleEnumerator* result = new nsArrayEnumerator(array); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(result); + *labels = result; + return(NS_OK); + } + return(NS_NewEmptyEnumerator(labels)); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetAllResources(nsISimpleEnumerator** aCursor) +{ + NS_NOTYETIMPLEMENTED("sorry!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::AddObserver(nsIRDFObserver *n) +{ + NS_PRECONDITION(n != nsnull, "null ptr"); + if (! n) + return NS_ERROR_NULL_POINTER; + + if (! mObservers) + { + nsresult rv; + rv = NS_NewISupportsArray(getter_AddRefs(mObservers)); + if (NS_FAILED(rv)) return rv; + } + return mObservers->AppendElement(n) ? NS_OK : NS_ERROR_FAILURE; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::RemoveObserver(nsIRDFObserver *n) +{ + NS_PRECONDITION(n != nsnull, "null ptr"); + if (! n) + return NS_ERROR_NULL_POINTER; + + if (! mObservers) + return(NS_OK); + + NS_VERIFY(mObservers->RemoveElement(n), "observer not present"); + return(NS_OK); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetAllCommands(nsIRDFResource* source,nsIEnumerator/**/** commands) +{ + NS_NOTYETIMPLEMENTED("write me!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetAllCmds(nsIRDFResource* source, nsISimpleEnumerator/**/** commands) +{ + return(NS_NewEmptyEnumerator(commands)); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult) +{ + return(NS_ERROR_NOT_IMPLEMENTED); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments) +{ + return(NS_ERROR_NOT_IMPLEMENTED); +} + + + +nsresult +NS_NewLocalSearchService(nsISupports* aOuter, REFNSIID aIID, void** aResult) +{ + NS_PRECONDITION(aResult != nsnull, "null ptr"); + if (! aResult) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(aOuter == nsnull, "no aggregation"); + if (aOuter) + return NS_ERROR_NO_AGGREGATION; + + nsresult rv = NS_OK; + + LocalSearchDataSource* result = new LocalSearchDataSource(); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + rv = result->Init(); + if (NS_SUCCEEDED(rv)) + rv = result->QueryInterface(aIID, aResult); + + if (NS_FAILED(rv)) { + delete result; + *aResult = nsnull; + return rv; + } + + return rv; +} diff --git a/xpfe/components/search/macbuild/Search.mcp b/xpfe/components/search/macbuild/Search.mcp new file mode 100755 index 0000000000000000000000000000000000000000..d70b7173c86060620e97762f9646547f2662c72c GIT binary patch literal 73078 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 qyjSx%Q!;6L-_o5{SH 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 literal 0 HcmV?d00001 diff --git a/xpfe/components/search/macbuild/SearchPrefix.h b/xpfe/components/search/macbuild/SearchPrefix.h new file mode 100755 index 000000000000..1e1cf92bc5eb --- /dev/null +++ b/xpfe/components/search/macbuild/SearchPrefix.h @@ -0,0 +1,22 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* Defining the following causes NS_APPSHELL to be defined as NS_EXPORT. */ +#define _IMPL_NS_APPSHELL + +#include "MacSharedPrefix.h" diff --git a/xpfe/components/search/macbuild/SearchPrefix_debug.h b/xpfe/components/search/macbuild/SearchPrefix_debug.h new file mode 100755 index 000000000000..04a443c3f5d8 --- /dev/null +++ b/xpfe/components/search/macbuild/SearchPrefix_debug.h @@ -0,0 +1,22 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* Defining the following causes NS_APPSHELL to be defined as NS_EXPORT. */ +#define _IMPL_NS_APPSHELL + +#include "MacSharedPrefix_debug.h" diff --git a/xpfe/components/search/public/nsISearchService.idl b/xpfe/components/search/public/nsISearchService.idl new file mode 100755 index 000000000000..f97ac0ee05c4 --- /dev/null +++ b/xpfe/components/search/public/nsISearchService.idl @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + + The Browser Search service + +*/ + +#include "nsISupports.idl" + +[scriptable, uuid(1222e6f0-a5e3-11d2-8b7c-00805f8a7db6)] +interface nsILocalSearchService : nsISupports +{ +}; + +[scriptable, uuid(6bd1d803-1c67-11d3-9820-ed1b357eb3c4)] +interface nsInternetSearchService : nsISupports +{ +}; + +%{C++ + +#define NS_IINTERNETSEARCHDATASOURCECALLBACK_IID \ +{ 0x88774583, 0x1edd, 0x11d3, { 0x98, 0x20, 0xbf, 0x1b, 0xe7, 0x7e, 0x61, 0xc4 } } + +#define NS_IINTERNETSEARCHDATAOURCE_IID \ +{ 0x6bd1d803, 0x1c67, 0x11d3, { 0x98, 0x20, 0xed, 0x1b, 0x35, 0x7e, 0xb3, 0xc4 } } + +#define NS_ILOCALSEARCHDATASOURCE_IID \ +{ 0x1222e6f0, 0xa5e3, 0x11d2, { 0x8b, 0x7c, 0x00, 0x80, 0x5f, 0x8a, 0x7d, 0xb6 } } + +#define NS_LOCALSEARCH_SERVICE_PROGID \ + "component://netscape/browser/localsearch-service" +#define NS_LOCALSEARCH_DATASOURCE_PROGID \ + "component://netscape/rdf/datasource?name=localsearch" + +#define NS_INTERNETSEARCH_SERVICE_PROGID \ + "component://netscape/browser/internetsearch-service" +#define NS_INTERNETSEARCH_DATASOURCE_PROGID \ + "component://netscape/rdf/datasource?name=internetsearch" + +%} diff --git a/xpfe/components/search/src/nsInternetSearchService.cpp b/xpfe/components/search/src/nsInternetSearchService.cpp new file mode 100755 index 000000000000..d0e033597040 --- /dev/null +++ b/xpfe/components/search/src/nsInternetSearchService.cpp @@ -0,0 +1,2568 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-file-style: "stroustrup" -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + Implementation for an internet search RDF data store. + */ + +#include // for toupper() +#include +#include "nscore.h" +#include "nsCOMPtr.h" +#include "nsIEnumerator.h" +#include "nsIRDFDataSource.h" +#include "nsIRDFNode.h" +#include "nsIRDFObserver.h" +#include "nsIServiceManager.h" +#include "nsString.h" +#include "nsVoidArray.h" // XXX introduces dependency on raptorbase +#include "nsXPIDLString.h" +#include "nsRDFCID.h" +//#include "rdfutil.h" +#include "nsIRDFService.h" +#include "xp_core.h" +#include "plhash.h" +#include "plstr.h" +#include "prmem.h" +#include "prprf.h" +#include "prio.h" +#include "rdf.h" +#include "nsFileSpec.h" +#include "nsFileStream.h" +#include "nsSpecialSystemDirectory.h" +#include "nsEnumeratorUtils.h" + +#include "nsIRDFRemoteDataSource.h" + +#include "nsEscape.h" + +#include "nsIURL.h" +#ifdef NECKO +#include "nsNeckoUtil.h" +#include "nsIChannel.h" +#include "nsIHTTPChannel.h" +#include "nsHTTPEnums.h" +#else +#include "nsIPostToServer.h" +#endif // NECKO +#include "nsIInputStream.h" +#include "nsIStreamListener.h" +#include "nsISearchService.h" + +#ifdef XP_MAC +#include "Files.h" +#endif + +#ifdef XP_WIN +#include "windef.h" +#include "winbase.h" +#endif + + +#define POSTHEADER_PREFIX "Content-type: application/x-www-form-urlencoded; charset=ISO-8859-1\r\nContent-Length: " +#define POSTHEADER_SUFFIX "\r\n\r\n" + + +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); +static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +static const char kURINC_SearchRoot[] = "NC:SearchEngineRoot"; +static const char kURINC_SearchResultsSitesRoot[] = "NC:SearchResultsSitesRoot"; +static const char kURINC_LastSearchRoot[] = "NC:LastSearchRoot"; +static const char kURINC_SearchResultsAnonymous[] = "NC:SearchResultsAnonymous"; + + + +class InternetSearchDataSourceCallback : public nsIStreamListener +{ +private: + nsIRDFDataSource *mDataSource; + nsIRDFResource *mParent; + nsIRDFResource *mEngine; + static PRInt32 gRefCnt; + + // pseudo-constants + static nsIRDFResource *kNC_LastSearchRoot; + static nsIRDFResource *kNC_loading; + static nsIRDFResource *kNC_Child; + static nsIRDFResource *kNC_URL; + static nsIRDFResource *kNC_Name; + static nsIRDFResource *kNC_Data; + static nsIRDFResource *kNC_Relevance; + static nsIRDFResource *kNC_RelevanceSort; + static nsIRDFResource *kNC_Site; + static nsIRDFResource *kNC_Engine; + static nsIRDFResource *kNC_HTML; + static nsIRDFResource *kNC_Banner; + + char *mLine; + + nsresult CreateAnonymousResource(nsCOMPtr* aResult); + +public: + + NS_DECL_ISUPPORTS + + InternetSearchDataSourceCallback(nsIRDFDataSource *ds, nsIRDFResource *parent, nsIRDFResource *engine); + virtual ~InternetSearchDataSourceCallback(void); + +#ifdef NECKO + // nsIStreamObserver methods: + NS_DECL_NSISTREAMOBSERVER + + // nsIStreamListener methods: + NS_DECL_NSISTREAMLISTENER +#else + // stream observer + + NS_IMETHOD OnStartRequest(nsIURI *aURL, const char *aContentType); + NS_IMETHOD OnProgress(nsIURI* aURL, PRUint32 aProgress, PRUint32 aProgressMax); + NS_IMETHOD OnStatus(nsIURI* aURL, const PRUnichar* aMsg); + NS_IMETHOD OnStopRequest(nsIURI* aURL, nsresult aStatus, const PRUnichar* aMsg); + + // stream listener + NS_IMETHOD GetBindInfo(nsIURI* aURL, nsStreamBindingInfo* aInfo); + NS_IMETHOD OnDataAvailable(nsIURI* aURL, nsIInputStream *aIStream, + PRUint32 aLength); +#endif +}; + + + +class InternetSearchDataSource : public nsIRDFDataSource +{ +private: + static PRInt32 gRefCnt; + + // pseudo-constants + static nsIRDFResource *kNC_SearchRoot; + static nsIRDFResource *kNC_LastSearchRoot; + static nsIRDFResource *kNC_SearchResultsSitesRoot; + static nsIRDFResource *kNC_Ref; + static nsIRDFResource *kNC_Child; + static nsIRDFResource *kNC_Data; + static nsIRDFResource *kNC_Name; + static nsIRDFResource *kNC_URL; + static nsIRDFResource *kRDF_InstanceOf; + static nsIRDFResource *kRDF_type; + static nsIRDFResource *kNC_loading; + static nsIRDFResource *kNC_HTML; + +protected: + static nsIRDFDataSource *mInner; + +friend NS_IMETHODIMP NS_NewInternetSearchService(nsISupports* aOuter, REFNSIID aIID, void** aResult); + +public: + +friend class InternetSearchDataSourceCallback; + + NS_DECL_ISUPPORTS + + InternetSearchDataSource(void); + virtual ~InternetSearchDataSource(void); + nsresult Init(); + + // nsIRDFDataSource methods + + NS_IMETHOD GetURI(char **uri); + NS_IMETHOD GetSource(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsIRDFResource **source /* out */); + NS_IMETHOD GetSources(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsISimpleEnumerator **sources /* out */); + NS_IMETHOD GetTarget(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsIRDFNode **target /* out */); + NS_IMETHOD GetTargets(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsISimpleEnumerator **targets /* out */); + NS_IMETHOD Assert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv); + NS_IMETHOD Unassert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target); + NS_IMETHOD Change(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aOldTarget, + nsIRDFNode* aNewTarget); + NS_IMETHOD Move(nsIRDFResource* aOldSource, + nsIRDFResource* aNewSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget); + NS_IMETHOD HasAssertion(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + PRBool *hasAssertion /* out */); + NS_IMETHOD ArcLabelsIn(nsIRDFNode *node, + nsISimpleEnumerator **labels /* out */); + NS_IMETHOD ArcLabelsOut(nsIRDFResource *source, + nsISimpleEnumerator **labels /* out */); + NS_IMETHOD GetAllResources(nsISimpleEnumerator** aResult); + NS_IMETHOD AddObserver(nsIRDFObserver *n); + NS_IMETHOD RemoveObserver(nsIRDFObserver *n); + NS_IMETHOD GetAllCommands(nsIRDFResource* source, + nsIEnumerator/**/** commands); + NS_IMETHOD GetAllCmds(nsIRDFResource* source, + nsISimpleEnumerator/**/** commands); + + NS_IMETHOD IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult); + + NS_IMETHOD DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments); + + + // helper methods +static PRBool isEngineURI(nsIRDFResource* aResource); +static PRBool isSearchURI(nsIRDFResource* aResource); +static nsresult BeginSearchRequest(nsIRDFResource *source, PRBool doNetworkRequest); +static nsresult DoSearch(nsIRDFResource *source, nsIRDFResource *engine, nsString text); +static nsresult GetSearchEngineList(nsFileSpec spec); +static nsresult GetSearchFolder(nsFileSpec &spec); +static nsresult ReadFileContents(nsFileSpec baseFilename, nsString & sourceContents); +static nsresult GetData(nsString data, char *sectionToFind, char *attribToFind, nsString &value); +static nsresult GetInputs(nsString data, nsString text, nsString &input); +static nsresult GetURL(nsIRDFResource *source, nsIRDFLiteral** aResult); +static PRBool isVisible(const nsNativeFileSpec& file); + +}; + + + +static nsIRDFService *gRDFService = nsnull; +static InternetSearchDataSource *gInternetSearchDataSource = nsnull; + +PRInt32 InternetSearchDataSource::gRefCnt; +nsIRDFDataSource *InternetSearchDataSource::mInner = nsnull; + +nsIRDFResource *InternetSearchDataSource::kNC_SearchRoot; +nsIRDFResource *InternetSearchDataSource::kNC_LastSearchRoot; +nsIRDFResource *InternetSearchDataSource::kNC_SearchResultsSitesRoot; +nsIRDFResource *InternetSearchDataSource::kNC_Ref; +nsIRDFResource *InternetSearchDataSource::kNC_Child; +nsIRDFResource *InternetSearchDataSource::kNC_Data; +nsIRDFResource *InternetSearchDataSource::kNC_Name; +nsIRDFResource *InternetSearchDataSource::kNC_URL; +nsIRDFResource *InternetSearchDataSource::kRDF_InstanceOf; +nsIRDFResource *InternetSearchDataSource::kRDF_type; +nsIRDFResource *InternetSearchDataSource::kNC_loading; +nsIRDFResource *InternetSearchDataSource::kNC_HTML; + +PRInt32 InternetSearchDataSourceCallback::gRefCnt; + +nsIRDFResource *InternetSearchDataSourceCallback::kNC_LastSearchRoot; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Child; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_URL; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Name; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Data; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Relevance; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_RelevanceSort; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Site; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Engine; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_loading; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_HTML; +nsIRDFResource *InternetSearchDataSourceCallback::kNC_Banner; + +static const char kEngineProtocol[] = "engine://"; +static const char kSearchProtocol[] = "internetsearch:"; + + + +PRBool +InternetSearchDataSource::isEngineURI(nsIRDFResource *r) +{ + PRBool isEngineURIFlag = PR_FALSE; + const char *uri = nsnull; + + r->GetValueConst(&uri); + if ((uri) && (!strncmp(uri, kEngineProtocol, sizeof(kEngineProtocol) - 1))) + { + isEngineURIFlag = PR_TRUE; + } + return(isEngineURIFlag); +} + + + +PRBool +InternetSearchDataSource::isSearchURI(nsIRDFResource *r) +{ + PRBool isSearchURIFlag = PR_FALSE; + const char *uri = nsnull; + + r->GetValueConst(&uri); + if ((uri) && (!strncmp(uri, kSearchProtocol, sizeof(kSearchProtocol) - 1))) + { + isSearchURIFlag = PR_TRUE; + } + return(isSearchURIFlag); +} + + + +InternetSearchDataSource::InternetSearchDataSource(void) +{ + NS_INIT_REFCNT(); + + if (gRefCnt++ == 0) + { + nsresult rv = nsServiceManager::GetService(kRDFServiceCID, + nsIRDFService::GetIID(), (nsISupports**) &gRDFService); + + PR_ASSERT(NS_SUCCEEDED(rv)); + + gRDFService->GetResource(kURINC_SearchRoot, &kNC_SearchRoot); + gRDFService->GetResource(kURINC_LastSearchRoot, &kNC_LastSearchRoot); + gRDFService->GetResource(kURINC_SearchResultsSitesRoot, &kNC_SearchResultsSitesRoot); + gRDFService->GetResource(NC_NAMESPACE_URI "ref", &kNC_Ref); + gRDFService->GetResource(NC_NAMESPACE_URI "child", &kNC_Child); + gRDFService->GetResource(NC_NAMESPACE_URI "data", &kNC_Data); + gRDFService->GetResource(NC_NAMESPACE_URI "Name", &kNC_Name); + gRDFService->GetResource(NC_NAMESPACE_URI "URL", &kNC_URL); + gRDFService->GetResource(RDF_NAMESPACE_URI "instanceOf", &kRDF_InstanceOf); + gRDFService->GetResource(RDF_NAMESPACE_URI "type", &kRDF_type); + gRDFService->GetResource(NC_NAMESPACE_URI "loading", &kNC_loading); + gRDFService->GetResource(NC_NAMESPACE_URI "HTML", &kNC_HTML); + + gInternetSearchDataSource = this; + } +} + + + +InternetSearchDataSource::~InternetSearchDataSource (void) +{ + if (--gRefCnt == 0) + { + NS_RELEASE(kNC_SearchRoot); + NS_RELEASE(kNC_LastSearchRoot); + NS_RELEASE(kNC_SearchResultsSitesRoot); + NS_RELEASE(kNC_Ref); + NS_RELEASE(kNC_Child); + NS_RELEASE(kNC_Data); + NS_RELEASE(kNC_Name); + NS_RELEASE(kNC_URL); + NS_RELEASE(kRDF_InstanceOf); + NS_RELEASE(kRDF_type); + NS_RELEASE(kNC_loading); + NS_RELEASE(kNC_HTML); + + NS_IF_RELEASE(mInner); + + gInternetSearchDataSource = nsnull; + nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService); + gRDFService = nsnull; + } +} + + + +NS_IMPL_ISUPPORTS(InternetSearchDataSource, InternetSearchDataSource::GetIID()); + + + +nsresult +InternetSearchDataSource::Init() +{ + nsresult rv = NS_ERROR_OUT_OF_MEMORY; + + if (NS_FAILED(rv = nsComponentManager::CreateInstance(kRDFInMemoryDataSourceCID, + nsnull, nsIRDFDataSource::GetIID(), (void **)&mInner))) + return(rv); + + // register this as a named data source with the service manager + if (NS_FAILED(rv = gRDFService->RegisterDataSource(this, PR_FALSE))) + return(rv); + + // get available search engines + nsFileSpec nativeDir; + if (NS_SUCCEEDED(rv = GetSearchFolder(nativeDir))) + { + rv = GetSearchEngineList(nativeDir); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetURI(char **uri) +{ + NS_PRECONDITION(uri != nsnull, "null ptr"); + if (! uri) + return NS_ERROR_NULL_POINTER; + + if ((*uri = nsXPIDLCString::Copy("rdf:search")) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + return NS_OK; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetSource(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFResource** source /* out */) +{ + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + *source = nsnull; + return NS_RDF_NO_VALUE; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetSources(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsISimpleEnumerator **sources /* out */) +{ + NS_NOTYETIMPLEMENTED("write me"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetTarget(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsIRDFNode **target /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_RDF_NO_VALUE; + + // we only have positive assertions in the internet search data source. + if (! tv) + return(rv); + + if (mInner) + { + rv = mInner->GetTarget(source, property, tv, target); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetTargets(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsISimpleEnumerator **targets /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(targets != nsnull, "null ptr"); + if (! targets) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_RDF_NO_VALUE; + + // we only have positive assertions in the internet search data source. + if (! tv) + return(rv); + + if (mInner) + { + rv = mInner->GetTargets(source, property, tv, targets); + } + if (isSearchURI(source)) + { + if (property == kNC_Child) + { + PRBool doNetworkRequest = PR_TRUE; + if (NS_SUCCEEDED(rv) && (targets)) + { + // check and see if we already have data for the search in question; + // if we do, BeginSearchRequest() won't bother doing the search again, + // otherwise it will kickstart it + PRBool hasResults = PR_FALSE; + if (NS_SUCCEEDED((*targets)->HasMoreElements(&hasResults)) && (hasResults == PR_TRUE)) + { + doNetworkRequest = PR_FALSE; + } + } + BeginSearchRequest(source, doNetworkRequest); + } + } + return(rv); + +#if 0 + if ((source == kNC_SearchRoot) || (source == kNC_LastSearchRoot)) + { + if (property == kNC_Child) + { + if (mInner) + { + rv = mInner->GetTargets(source, property,tv, targets); + } + return(rv); + } + return(NS_RDF_NO_VALUE); + } + else if (isSearchURI(source)) + { + if (property == kNC_Child) + { + if (mInner) + { + rv = mInner->GetTargets(source, property, tv, targets); + } + PRBool doNetworkRequest = PR_TRUE; + if (NS_SUCCEEDED(rv) && (targets)) + { + // check and see if we already have data for the search in question; + // if we do, don't bother doing the search again, otherwise kickstart it + PRBool hasResults = PR_FALSE; + if (NS_SUCCEEDED((*targets)->HasMoreElements(&hasResults)) && (hasResults == PR_TRUE)) + { + doNetworkRequest = PR_FALSE; + } + } + BeginSearchRequest(source, doNetworkRequest); +// return(rv); + } + return(NS_RDF_NO_VALUE); + } + if (mInner) + { + rv = mInner->GetTargets(source, property, tv, targets); + } + return NS_NewEmptyEnumerator(targets); +#endif + +} + + + +NS_IMETHODIMP +InternetSearchDataSource::Assert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::Unassert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::Change(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aOldTarget, + nsIRDFNode* aNewTarget) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::Move(nsIRDFResource* aOldSource, + nsIRDFResource* aNewSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::HasAssertion(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + PRBool *hasAssertion /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(hasAssertion != nsnull, "null ptr"); + if (! hasAssertion) + return NS_ERROR_NULL_POINTER; + + // we only have positive assertions in the internet search data source. + if (! tv) + { + *hasAssertion = PR_FALSE; + return NS_OK; + } + nsresult rv = NS_RDF_NO_VALUE; + + if (mInner) + { + rv = mInner->HasAssertion(source, property, target, tv, hasAssertion); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::ArcLabelsIn(nsIRDFNode *node, + nsISimpleEnumerator ** labels /* out */) +{ + NS_NOTYETIMPLEMENTED("write me"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::ArcLabelsOut(nsIRDFResource *source, + nsISimpleEnumerator **labels /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(labels != nsnull, "null ptr"); + if (! labels) + return NS_ERROR_NULL_POINTER; + + nsresult rv; + + if ((source == kNC_SearchRoot) || (source == kNC_LastSearchRoot) || isSearchURI(source)) + { + nsCOMPtr array; + rv = NS_NewISupportsArray(getter_AddRefs(array)); + if (NS_FAILED(rv)) return rv; + + array->AppendElement(kNC_Child); + + nsISimpleEnumerator* result = new nsArrayEnumerator(array); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(result); + *labels = result; + return(NS_OK); + } + + if (mInner) + { + rv = mInner->ArcLabelsOut(source, labels); + return(rv); + } + + return NS_NewEmptyEnumerator(labels); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetAllResources(nsISimpleEnumerator** aCursor) +{ + nsresult rv = NS_RDF_NO_VALUE; + + if (mInner) + { + rv = mInner->GetAllResources(aCursor); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::AddObserver(nsIRDFObserver *aObserver) +{ + nsresult rv = NS_OK; + + if (mInner) + { + rv = mInner->AddObserver(aObserver); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::RemoveObserver(nsIRDFObserver *aObserver) +{ + nsresult rv = NS_OK; + + if (mInner) + { + rv = mInner->RemoveObserver(aObserver); + } + return(rv); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetAllCommands(nsIRDFResource* source, + nsIEnumerator/**/** commands) +{ + NS_NOTYETIMPLEMENTED("write me!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +InternetSearchDataSource::GetAllCmds(nsIRDFResource* source, + nsISimpleEnumerator/**/** commands) +{ + return(NS_NewEmptyEnumerator(commands)); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult) +{ + return(NS_ERROR_NOT_IMPLEMENTED); +} + + + +NS_IMETHODIMP +InternetSearchDataSource::DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments) +{ + return(NS_ERROR_NOT_IMPLEMENTED); +} + + + +NS_IMETHODIMP +NS_NewInternetSearchService(nsISupports* aOuter, REFNSIID aIID, void** aResult) +{ + NS_PRECONDITION(aResult != nsnull, "null ptr"); + if (! aResult) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(aOuter == nsnull, "no aggregation"); + if (aOuter) + return NS_ERROR_NO_AGGREGATION; + + nsresult rv = NS_OK; + + InternetSearchDataSource* result = new InternetSearchDataSource(); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + rv = result->Init(); + if (NS_SUCCEEDED(rv)) + rv = result->QueryInterface(aIID, aResult); + + if (NS_FAILED(rv)) { + delete result; + *aResult = nsnull; + return rv; + } + + return rv; +} + + + +nsresult +InternetSearchDataSource::BeginSearchRequest(nsIRDFResource *source, PRBool doNetworkRequest) +{ + nsresult rv = NS_OK; + char *sourceURI = nsnull; + + if (NS_FAILED(rv = source->GetValue(&sourceURI))) + return(rv); + nsAutoString uri(sourceURI); + if (uri.Find("internetsearch:") != 0) + return(NS_ERROR_FAILURE); + + // remember the last search query + + nsCOMPtr localstore; + rv = gRDFService->GetDataSource("rdf:local-store", getter_AddRefs(localstore)); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr lastTarget; + if (NS_SUCCEEDED(rv = localstore->GetTarget(kNC_LastSearchRoot, kNC_Ref, + PR_TRUE, getter_AddRefs(lastTarget)))) + { + if (rv != NS_RDF_NO_VALUE) + { +#ifdef DEBUG + nsCOMPtr lastLit = do_QueryInterface(lastTarget); + if (lastLit) + { + const PRUnichar *lastUni = nsnull; + lastLit->GetValueConst(&lastUni); + nsAutoString lastStr(lastUni); + char *lastC = lastStr.ToNewCString(); + if (lastC) + { + printf("\nLast Search: '%s'\n", lastC); + nsCRT::free(lastC); + lastC = nsnull; + } + } +#endif + rv = localstore->Unassert(kNC_LastSearchRoot, kNC_Ref, lastTarget); + } + } + if (uri.Length() > 0) + { + const PRUnichar *uriUni = uri.GetUnicode(); + nsCOMPtr uriLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(uriUni, getter_AddRefs(uriLiteral)))) + { + rv = localstore->Assert(kNC_LastSearchRoot, kNC_Ref, uriLiteral, PR_TRUE); + } + } + + // XXX Currently, need to flush localstore as its being leaked + // and thus never written out to disk otherwise + + // gotta love the name "remoteLocalStore" + nsCOMPtr remoteLocalStore = do_QueryInterface(localstore); + if (remoteLocalStore) + { + remoteLocalStore->Flush(); + } + } + + // forget about any previous search results + + if (mInner) + { + nsCOMPtr arcs; + if (NS_SUCCEEDED(rv = mInner->GetTargets(kNC_LastSearchRoot, kNC_Child, PR_TRUE, getter_AddRefs(arcs)))) + { + PRBool hasMore = PR_TRUE; + while (hasMore == PR_TRUE) + { + if (NS_FAILED(arcs->HasMoreElements(&hasMore)) || (hasMore == PR_FALSE)) + break; + nsCOMPtr arc; + if (NS_FAILED(arcs->GetNext(getter_AddRefs(arc)))) + break; + nsCOMPtr child = do_QueryInterface(arc); + if (child) + { + mInner->Unassert(kNC_LastSearchRoot, kNC_Child, child); + } + } + } + } + +#if 0 + nsCOMPtr lastTarget; + if (NS_SUCCEEDED(rv = mInner->GetTarget(kNC_LastSearchRoot, kNC_Ref, + PR_TRUE, getter_AddRefs(lastTarget)))) + { + if (rv != NS_RDF_NO_VALUE) + { + rv = mInner->Unassert(kNC_LastSearchRoot, kNC_Ref, lastTarget); + } + } + if (uri.Length() > 0) + { + const PRUnichar *uriUni = uri.GetUnicode(); + nsCOMPtr uriLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(uriUni, getter_AddRefs(uriLiteral)))) + { + rv = mInner->Assert(kNC_LastSearchRoot, kNC_Ref, uriLiteral, PR_TRUE); + } + } + } +#endif + + // forget about any previous search sites + + if (mInner) + { + nsCOMPtr arcs; + if (NS_SUCCEEDED(rv = mInner->GetTargets(kNC_SearchResultsSitesRoot, kNC_Child, PR_TRUE, getter_AddRefs(arcs)))) + { + PRBool hasMore = PR_TRUE; + while (hasMore == PR_TRUE) + { + if (NS_FAILED(arcs->HasMoreElements(&hasMore)) || (hasMore == PR_FALSE)) + break; + nsCOMPtr arc; + if (NS_FAILED(arcs->GetNext(getter_AddRefs(arc)))) + break; + nsCOMPtr child = do_QueryInterface(arc); + if (child) + { + mInner->Unassert(kNC_SearchResultsSitesRoot, kNC_Child, child); + } + } + } + } + + uri.Cut(0, strlen("internetsearch:")); + + nsVoidArray *engineArray = new nsVoidArray; + if (!engineArray) + return(NS_ERROR_FAILURE); + + nsAutoString text(""); + + // parse up attributes + + while(uri.Length() > 0) + { + nsAutoString item(""); + + PRInt32 andOffset = uri.Find("&"); + if (andOffset >= 0) + { + uri.Left(item, andOffset); + uri.Cut(0, andOffset + 1); + } + else + { + item = uri; + uri.Truncate(); + } + + PRInt32 equalOffset = item.Find("="); + if (equalOffset < 0) break; + + nsAutoString attrib(""), value(""); + item.Left(attrib, equalOffset); + value = item; + value.Cut(0, equalOffset + 1); + + if ((attrib.Length() > 0) && (value.Length() > 0)) + { + if (attrib.EqualsIgnoreCase("engine")) + { + if (value.Find(kEngineProtocol) == 0) + { + char *val = value.ToNewCString(); + if (val) + { + engineArray->AppendElement(val); + } + } + } + else if (attrib.EqualsIgnoreCase("text")) + { + text = value; + } + } + } + + // loop over specified search engines + while (engineArray->Count() > 0) + { + char *baseFilename = (char *)(engineArray->ElementAt(0)); + engineArray->RemoveElementAt(0); + if (!baseFilename) continue; + +#ifdef DEBUG + printf("Search engine to query: '%s'\n", baseFilename); +#endif + + nsCOMPtr engine; + gRDFService->GetResource(baseFilename, getter_AddRefs(engine)); + nsCRT::free(baseFilename); + baseFilename = nsnull; + if (!engine) continue; + + // mark this as a search site + if (mInner) + { + mInner->Assert(kNC_SearchResultsSitesRoot, kNC_Child, engine, PR_TRUE); + } + + if (doNetworkRequest == PR_TRUE) + { + DoSearch(source, engine, text); + } + } + + delete engineArray; + engineArray = nsnull; + + return(rv); +} + + + +nsresult +InternetSearchDataSource::DoSearch(nsIRDFResource *source, nsIRDFResource *engine, nsString text) +{ + nsresult rv; + + if (!source) + return(NS_ERROR_NULL_POINTER); + if (!engine) + return(NS_ERROR_NULL_POINTER); + + if (!mInner) + { + return(NS_RDF_NO_VALUE); + } + + // get data + nsAutoString data(""); + nsCOMPtr dataTarget = nsnull; + if (NS_SUCCEEDED((rv = mInner->GetTarget(engine, kNC_Data, PR_TRUE, getter_AddRefs(dataTarget)))) && (dataTarget)) + { + nsCOMPtr dataLiteral = do_QueryInterface(dataTarget); + if (!dataLiteral) + return(rv); + PRUnichar *dataUni; + if (NS_FAILED(rv = dataLiteral->GetValue(&dataUni))) + return(rv); + data = dataUni; + } + else + { + const char *engineURI = nsnull; + if (NS_FAILED(rv = engine->GetValueConst(&engineURI))) + return(rv); + nsAutoString engineStr(engineURI); + if (engineStr.Find(kEngineProtocol) != 0) + return(rv); + engineStr.Cut(0, sizeof(kEngineProtocol) - 1); + char *baseFilename = engineStr.ToNewCString(); + if (!baseFilename) + return(rv); + baseFilename = nsUnescape(baseFilename); + if (!baseFilename) + return(rv); + + nsFileSpec engineSpec(baseFilename); + rv = ReadFileContents(engineSpec, data); +// rv = NS_ERROR_UNEXPECTED; // XXX rjc: fix this + + nsCRT::free(baseFilename); + baseFilename = nsnull; + if (NS_FAILED(rv)) + { + return(rv); + } + + // save file contents + nsCOMPtr dataLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(data.GetUnicode(), getter_AddRefs(dataLiteral)))) + { + if (mInner) + { + mInner->Assert(engine, kNC_Data, dataLiteral, PR_TRUE); + } + } + } + if (data.Length() < 1) + return(NS_RDF_NO_VALUE); + + nsAutoString action, method, input; + + if (NS_FAILED(rv = GetData(data, "search", "action", action))) + return(rv); + if (NS_FAILED(rv = GetData(data, "search", "method", method))) + return(rv); + if (NS_FAILED(rv = GetInputs(data, text, input))) + return(rv); + +#ifdef DEBUG + char *cAction = action.ToNewCString(); + char *cMethod = method.ToNewCString(); + char *cInput = input.ToNewCString(); + printf("Search Action: '%s'\n", cAction); + printf("Search Method: '%s'\n", cMethod); + printf(" Search Input: '%s'\n\n", cInput); + if (cAction) + { + nsCRT::free(cAction); + cAction = nsnull; + } + if (cMethod) + { + nsCRT::free(cMethod); + cMethod = nsnull; + } + if (cInput) + { + nsCRT::free(cInput); + cInput = nsnull; + } +#endif + + if (input.Length() < 1) + return(NS_ERROR_UNEXPECTED); + + if (method.EqualsIgnoreCase("get")) + { + // HTTP Get method support + action += "?"; + action += input; + } + + char *searchURL = action.ToNewCString(); + if (!searchURL) + return(NS_ERROR_NULL_POINTER); + +#ifdef NECKO + InternetSearchDataSourceCallback *callback = new InternetSearchDataSourceCallback(mInner, source, engine); + if (nsnull != callback) + { + nsCOMPtr url; + if (NS_SUCCEEDED(rv = NS_NewURI(getter_AddRefs(url), (const char*) searchURL))) + { + if (method.EqualsIgnoreCase("post")) + { + nsCOMPtr channel; + // XXX: Null LoadGroup ? + if (NS_SUCCEEDED(rv = NS_OpenURI(getter_AddRefs(channel), url, nsnull))) + { + nsCOMPtr httpChannel = do_QueryInterface(channel); + if (httpChannel) + { + httpChannel->SetRequestMethod(HM_POST); + + // construct post data to send + nsAutoString postStr(POSTHEADER_PREFIX); + postStr.Append(input.Length(), 10); + postStr += POSTHEADER_SUFFIX; + postStr += input; + + char *postData = postStr.ToNewCString(); + if (postData) + { + nsCOMPtr postDataStream; + if (NS_SUCCEEDED(rv = NS_NewPostDataStream(PR_FALSE, postData, + 0, getter_AddRefs(postDataStream)))) + { + httpChannel->SetPostDataStream(postDataStream); + /* postData is now owned by the postDataStream instance... ? */ + rv = channel->AsyncRead(0, -1, nsnull, callback); + } + else + { + nsCRT::free(postData); + postData = nsnull; + } + } + } + } + } + else if (method.EqualsIgnoreCase("get")) + { + // XXX: Null LoadGroup? + rv = NS_OpenURI(NS_STATIC_CAST(nsIStreamListener *, callback), nsnull, url, nsnull); + } + } + } +#endif + + // dispose of any last HTML results page + if (mInner) + { + nsCOMPtr htmlNode; + if (NS_SUCCEEDED(rv = mInner->GetTarget(engine, kNC_HTML, PR_TRUE, getter_AddRefs(htmlNode))) + && (rv != NS_RDF_NO_VALUE)) + { + rv = mInner->Unassert(engine, kNC_HTML, htmlNode); + } + } + + // start "loading" animation for this search engine + if (NS_SUCCEEDED(rv) && (mInner)) + { + nsAutoString trueStr("true"); + nsCOMPtr literal; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(trueStr.GetUnicode(), getter_AddRefs(literal)))) + { + mInner->Assert(engine, kNC_loading, literal, PR_TRUE); + } + } + + nsCRT::free(searchURL); + searchURL = nsnull; + return(rv); +} + + + +nsresult +InternetSearchDataSource::GetSearchFolder(nsFileSpec &spec) +{ +#ifdef XP_MAC + // on Mac, use system's search files + nsSpecialSystemDirectory searchSitesDir(nsSpecialSystemDirectory::Mac_InternetSearchDirectory); +#else + // on other platforms, use our search files + nsSpecialSystemDirectory searchSitesDir(nsSpecialSystemDirectory::OS_CurrentProcessDirectory); + searchSitesDir += "res"; + searchSitesDir += "rdf"; + searchSitesDir += "datasets"; +#endif + spec = searchSitesDir; + return(NS_OK); +} + + + +nsresult +InternetSearchDataSource::GetSearchEngineList(nsFileSpec nativeDir) +{ + nsresult rv = NS_OK; + + if (!mInner) + { + return(NS_RDF_NO_VALUE); + } + + for (nsDirectoryIterator i(nativeDir, PR_FALSE); i.Exists(); i++) + { + const nsFileSpec fileSpec = (const nsFileSpec &)i; + if (fileSpec.IsHidden()) + { + continue; + } + + const char *childURL = fileSpec; + + if (fileSpec.IsDirectory()) + { + GetSearchEngineList(fileSpec); + } + else + if (childURL != nsnull) + { + nsAutoString uri(childURL); + PRInt32 len = uri.Length(); + if (len > 4) + { +#ifdef XP_MAC + // be sure to resolve aliases in case we encounter one + CInfoPBRec cInfo; + OSErr err; +// PRBool wasAliased = PR_FALSE; +// fileSpec.ResolveSymlink(wasAliased); + err = fileSpec.GetCatInfo(cInfo); + if ((!err) && (cInfo.hFileInfo.ioFlFndrInfo.fdType == 'issp') && + (cInfo.hFileInfo.ioFlFndrInfo.fdCreator == 'fndf')) +#else + // else just check the extension + nsAutoString extension; + if ((uri.Right(extension, 4) == 4) && (extension.EqualsIgnoreCase(".src"))) +#endif + { + char c; +#ifdef XP_WIN + c = '\\'; +#elif XP_MAC + c = ':'; +#else + c = '/'; +#endif + PRInt32 separatorOffset = uri.RFindChar(PRUnichar(c)); + if (separatorOffset > 0) + { +// uri.Cut(0, separatorOffset+1); + + nsAutoString searchURL(kEngineProtocol); + + char *uriC = uri.ToNewCString(); + if (!uriC) continue; + char *uriCescaped = nsEscape(uriC, url_Path); + nsCRT::free(uriC); + if (!uriCescaped) continue; +// searchURL += uri; + searchURL += uriCescaped; + nsCRT::free(uriCescaped); + +/* + char *baseFilename = uri.ToNewCString(); + if (!baseFilename) continue; + baseFilename = nsUnescape(baseFilename); + if (!baseFilename) continue; +*/ + nsAutoString data(""); + rv = ReadFileContents(fileSpec, data); +// nsCRT::free(baseFilename); +// baseFilename = nsnull; + if (NS_FAILED(rv)) continue; + + nsCOMPtr searchRes; + char *searchURI = searchURL.ToNewCString(); + if (searchURI) + { + if (NS_SUCCEEDED(rv = gRDFService->GetResource(searchURI, getter_AddRefs(searchRes)))) + { + mInner->Assert(kNC_SearchRoot, kNC_Child, searchRes, PR_TRUE); + + // save name of search engine (as specified in file) + nsAutoString nameValue; + if (NS_SUCCEEDED(rv = GetData(data, "search", "name", nameValue))) + { + nsCOMPtr nameLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(nameValue.GetUnicode(), getter_AddRefs(nameLiteral)))) + { + mInner->Assert(searchRes, kNC_Name, nameLiteral, PR_TRUE); + } + } + } + nsCRT::free(searchURI); + searchURI = nsnull; + } +// nsCRT::free(baseFilename); +// baseFilename = nsnull; + } + } + } + } + } + return(rv); +} + + + +PRBool +InternetSearchDataSource::isVisible(const nsNativeFileSpec& file) +{ + PRBool isVisible = PR_TRUE; + +#ifdef XP_MAC + CInfoPBRec cInfo; + OSErr err; + + nsFileSpec fileSpec(file); + if (!(err = fileSpec.GetCatInfo(cInfo))) + { + if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible) + { + isVisible = PR_FALSE; + } + } +#else + char *baseFilename = file.GetLeafName(); + if (nsnull != baseFilename) + { + if ((!strcmp(baseFilename, ".")) || (!strcmp(baseFilename, ".."))) + { + isVisible = PR_FALSE; + } + nsCRT::free(baseFilename); + } +#endif + + return(isVisible); +} + + + +nsresult +InternetSearchDataSource::ReadFileContents(nsFileSpec baseFilename, nsString& sourceContents) +{ + nsresult rv = NS_OK; + +/* + nsFileSpec searchEngine; + if (NS_FAILED(rv = GetSearchFolder(searchEngine))) + { + return(rv); + } + searchEngine += baseFilename; + +#ifdef XP_MAC + // be sure to resolve aliases in case we encounter one + PRBool wasAliased = PR_FALSE; + searchEngine.ResolveSymlink(wasAliased); +#endif + nsInputFileStream searchFile(searchEngine); +*/ + + nsInputFileStream searchFile(baseFilename); + +/* +#ifdef XP_MAC + if (!searchFile.is_open()) + { + // on Mac, nsDirectoryIterator resolves aliases before returning them currently; + // so, if we can't open the file directly, walk the directory and see if we then + // find a match + + // on Mac, use system's search files + nsSpecialSystemDirectory searchSitesDir(nsSpecialSystemDirectory::Mac_InternetSearchDirectory); + nsFileSpec nativeDir(searchSitesDir); + for (nsDirectoryIterator i(nativeDir, PR_FALSE); i.Exists(); i++) + { + const nsFileSpec fileSpec = (const nsFileSpec &)i; + const char *childURL = fileSpec; + if (fileSpec.isHidden()) + { + continue; + } + if (childURL != nsnull) + { + // be sure to resolve aliases in case we encounter one + PRBool wasAliased = PR_FALSE; + fileSpec.ResolveSymlink(wasAliased); + nsAutoString childPath(childURL); + PRInt32 separatorOffset = childPath.RFindChar(PRUnichar(':')); + if (separatorOffset > 0) + { + childPath.Cut(0, separatorOffset+1); + } + if (childPath.EqualsIgnoreCase(baseFilename)) + { + searchFile = fileSpec; + } + } + } + } +#endif +*/ + + if (searchFile.is_open()) + { + nsRandomAccessInputStream stream(searchFile); + char buffer[1024]; + while (!stream.eof()) + { + stream.readline(buffer, sizeof(buffer)-1 ); + sourceContents += buffer; + sourceContents += "\n"; + } + } + else + { + rv = NS_ERROR_FAILURE; + } + return(rv); +} + + + +nsresult +InternetSearchDataSource::GetData(nsString data, char *sectionToFind, char *attribToFind, nsString &value) +{ + nsAutoString buffer(data); + nsresult rv = NS_RDF_NO_VALUE; + PRBool inSection = PR_FALSE; + + while(buffer.Length() > 0) + { + PRInt32 eol = buffer.FindCharInSet("\r\n", 0); + if (eol < 0) break; + nsAutoString line(""); + if (eol > 0) + { + buffer.Left(line, eol); + } + buffer.Cut(0, eol+1); + if (line.Length() < 1) continue; // skip empty lines + if (line[0] == PRUnichar('#')) continue; // skip comments + line = line.Trim(" \t"); + if (inSection == PR_FALSE) + { + nsAutoString section("<"); + section += sectionToFind; + PRInt32 sectionOffset = line.Find(section, PR_TRUE); + if (sectionOffset < 0) continue; + line.Cut(0, sectionOffset + section.Length() + 1); + inSection = PR_TRUE; + + } + line = line.Trim(" \t"); + PRInt32 len = line.Length(); + if (len > 0) + { + if (line[len-1] == PRUnichar('>')) + { + inSection = PR_FALSE; + line.SetLength(len-1); + } + } + PRInt32 equal = line.Find("="); + if (equal < 0) continue; // skip lines with no equality + + nsAutoString attrib(""); + if (equal > 0) + { + line.Left(attrib, equal /* - 1 */); + } + attrib = attrib.Trim(" \t"); + if (attrib.EqualsIgnoreCase(attribToFind)) + { + line.Cut(0, equal+1); + value = line.Trim(" \t"); + + // strip of any enclosing quotes + if (value[0] == PRUnichar('\"')) + { + value.Cut(0,1); + } + len = value.Length(); + if (len > 0) + { + if (value[len-1] == PRUnichar('\"')) + { + value.SetLength(len-1); + } + } + rv = NS_OK; + break; + } + } + return(rv); +} + + + +nsresult +InternetSearchDataSource::GetInputs(nsString data, nsString text, nsString &input) +{ + nsAutoString buffer(data); // , eolStr("\r\n"); + nsresult rv = NS_OK; + PRBool inSection = PR_FALSE; + + while(buffer.Length() > 0) + { + PRInt32 eol = buffer.FindCharInSet("\r\n", 0); + if (eol < 0) break; + nsAutoString line(""); + if (eol > 0) + { + buffer.Left(line, eol); + } + buffer.Cut(0, eol+1); + if (line.Length() < 1) continue; // skip empty lines + if (line[0] == PRUnichar('#')) continue; // skip comments + line = line.Trim(" \t"); + if (inSection == PR_FALSE) + { + nsAutoString section("<"); + PRInt32 sectionOffset = line.Find(section, PR_TRUE); + if (sectionOffset < 0) continue; + if (sectionOffset == 0) + { + line.Cut(0, sectionOffset + section.Length()); + inSection = PR_TRUE; + } + } + PRInt32 len = line.Length(); + if (len > 0) + { + if (line[len-1] == PRUnichar('>')) + { + inSection = PR_FALSE; + line.SetLength(len-1); + } + } + if (inSection == PR_TRUE) continue; + + // look for inputs + if (line.Find("input", PR_TRUE) == 0) + { + line.Cut(0, 6); + line = line.Trim(" \t"); + + // first look for name attribute + nsAutoString nameAttrib(""); + + PRInt32 nameOffset = line.Find("name", PR_TRUE); + if (nameOffset >= 0) + { + PRInt32 equal = line.FindChar(PRUnichar('='), PR_TRUE, nameOffset); + if (equal >= 0) + { + PRInt32 startQuote = line.FindChar(PRUnichar('\"'), PR_TRUE, equal + 1); + if (startQuote >= 0) + { + PRInt32 endQuote = line.FindChar(PRUnichar('\"'), PR_TRUE, startQuote + 1); + if (endQuote > 0) + { + line.Mid(nameAttrib, startQuote+1, endQuote-startQuote-1); + } + } + else + { + nameAttrib = line; + nameAttrib.Cut(0, equal+1); + nameAttrib = nameAttrib.Trim(" \t"); + PRInt32 space = nameAttrib.FindCharInSet(" \t", 0); + if (space > 0) + { + nameAttrib.Truncate(space); + } + } + } + } + if (nameAttrib.Length() <= 0) continue; + + // first look for value attribute + nsAutoString valueAttrib(""); + + PRInt32 valueOffset = line.Find("value", PR_TRUE); + if (valueOffset >= 0) + { + PRInt32 equal = line.FindChar(PRUnichar('='), PR_TRUE, valueOffset); + if (equal >= 0) + { + PRInt32 startQuote = line.FindChar(PRUnichar('\"'), PR_TRUE, equal + 1); + if (startQuote >= 0) + { + PRInt32 endQuote = line.FindChar(PRUnichar('\"'), PR_TRUE, startQuote + 1); + if (endQuote >= 0) + { + line.Mid(valueAttrib, startQuote+1, endQuote-startQuote-1); + } + } + else + { + // if value attribute's "value" isn't quoted, get the first word... ? + valueAttrib = line; + valueAttrib.Cut(0, equal+1); + valueAttrib = valueAttrib.Trim(" \t"); + PRInt32 space = valueAttrib.FindCharInSet(" \t>", 0); + if (space > 0) + { + valueAttrib.Truncate(space); + } + } + } + } + else if (line.Find("user", PR_TRUE) >= 0) + { + valueAttrib = text; + } + + // XXX should ignore if mode=browser is specified + // XXX need to do this better + if (line.RFind("mode=browser", PR_TRUE) >= 0) + continue; + + if ((nameAttrib.Length() > 0) && (valueAttrib.Length() > 0)) + { + if (input.Length() > 0) + { + input += "&"; + } + input += nameAttrib; + input += "="; + input += valueAttrib; + } + } + } + return(rv); +} + + + +nsresult +InternetSearchDataSource::GetURL(nsIRDFResource *source, nsIRDFLiteral** aResult) +{ + const char *uri = nsnull; + source->GetValueConst( &uri ); + nsAutoString url(uri); + nsIRDFLiteral *literal; + gRDFService->GetLiteral(url.GetUnicode(), &literal); + *aResult = literal; + return NS_OK; +} + + + +// Search class for Netlib callback + + + +InternetSearchDataSourceCallback::InternetSearchDataSourceCallback(nsIRDFDataSource *ds, nsIRDFResource *parent, nsIRDFResource *engine) + : mDataSource(ds), + mParent(parent), + mEngine(engine), + mLine(nsnull) +{ + NS_INIT_REFCNT(); + NS_IF_ADDREF(mDataSource); + NS_IF_ADDREF(mParent); + NS_IF_ADDREF(mEngine); + + if (gRefCnt++ == 0) + { + nsresult rv = nsServiceManager::GetService(kRDFServiceCID, + nsIRDFService::GetIID(), + (nsISupports**) &gRDFService); + + PR_ASSERT(NS_SUCCEEDED(rv)); + + gRDFService->GetResource(kURINC_LastSearchRoot, &kNC_LastSearchRoot); + gRDFService->GetResource(NC_NAMESPACE_URI "child", &kNC_Child); + gRDFService->GetResource(NC_NAMESPACE_URI "URL", &kNC_URL); + gRDFService->GetResource(NC_NAMESPACE_URI "Name", &kNC_Name); + gRDFService->GetResource(NC_NAMESPACE_URI "data", &kNC_Data); + gRDFService->GetResource(NC_NAMESPACE_URI "Relevance", &kNC_Relevance); + gRDFService->GetResource(NC_NAMESPACE_URI "Relevance?sort=true", &kNC_RelevanceSort); + gRDFService->GetResource(NC_NAMESPACE_URI "Site", &kNC_Site); + gRDFService->GetResource(NC_NAMESPACE_URI "Engine", &kNC_Engine); + gRDFService->GetResource(NC_NAMESPACE_URI "loading", &kNC_loading); + gRDFService->GetResource(NC_NAMESPACE_URI "HTML", &kNC_HTML); + gRDFService->GetResource(NC_NAMESPACE_URI "Banner", &kNC_Banner); + } +} + + + +InternetSearchDataSourceCallback::~InternetSearchDataSourceCallback() +{ + NS_IF_RELEASE(mDataSource); + NS_IF_RELEASE(mParent); + NS_IF_RELEASE(mEngine); + + if (mLine) + { + nsCRT::free(mLine); + mLine = nsnull; + } + + if (--gRefCnt == 0) + { + NS_RELEASE(kNC_LastSearchRoot); + NS_RELEASE(kNC_Child); + NS_RELEASE(kNC_URL); + NS_RELEASE(kNC_Name); + NS_RELEASE(kNC_Data); + NS_RELEASE(kNC_Relevance); + NS_RELEASE(kNC_RelevanceSort); + NS_RELEASE(kNC_Site); + NS_RELEASE(kNC_Engine); + NS_RELEASE(kNC_loading); + NS_RELEASE(kNC_HTML); + NS_RELEASE(kNC_Banner); + } +} + + + +nsresult +InternetSearchDataSourceCallback::CreateAnonymousResource(nsCOMPtr* aResult) +{ + static PRInt32 gNext = 0; + + if (! gNext) + { + LL_L2I(gNext, PR_Now()); + } + + nsresult rv; + nsAutoString uri(kURINC_SearchResultsAnonymous); + uri.Append("#$"); + uri.Append(++gNext, 16); + + char *uriC = uri.ToNewCString(); + if (uriC) + { + rv = gRDFService->GetResource(uriC, getter_AddRefs(*aResult)); + nsCRT::free(uriC); + } + else + { + rv = NS_ERROR_NULL_POINTER; + } + return(rv); +} + + + +// stream observer methods + + + +NS_IMETHODIMP +#ifdef NECKO +InternetSearchDataSourceCallback::OnStartRequest(nsIChannel* channel, nsISupports *ctxt) +#else +InternetSearchDataSourceCallback::OnStartRequest(nsIURI *aURL, const char *aContentType) +#endif +{ + nsAutoString trueStr("true"); + nsIRDFLiteral *literal = nsnull; + nsresult rv; + +#ifdef DEBUG + printf("InternetSearchDataSourceCallback::OnStartRequest entered.\n"); +#endif + + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(trueStr.GetUnicode(), &literal))) + { + mDataSource->Assert(mParent, kNC_loading, literal, PR_TRUE); + + // Don't starting loading animation for engine here. + // Instead, we now do it when the URI is initially opened + // which gives a longer and more accurate animation period + +// mDataSource->Assert(mEngine, kNC_loading, literal, PR_TRUE); + NS_RELEASE(literal); + } + return(NS_OK); +} + + + +#ifndef NECKO +NS_IMETHODIMP +InternetSearchDataSourceCallback::OnProgress(nsIURI* aURL, PRUint32 aProgress, PRUint32 aProgressMax) +{ + return(NS_OK); +} + + + +NS_IMETHODIMP +InternetSearchDataSourceCallback::OnStatus(nsIURI* aURL, const PRUnichar* aMsg) +{ + return(NS_OK); +} +#endif + + + +NS_IMETHODIMP +#ifdef NECKO +InternetSearchDataSourceCallback::OnStopRequest(nsIChannel* channel, nsISupports *ctxt, + nsresult status, const PRUnichar *errorMsg) +#else +InternetSearchDataSourceCallback::OnStopRequest(nsIURI* aURL, nsresult aStatus, const PRUnichar* aMsg) +#endif +{ + nsAutoString trueStr("true"); + nsIRDFLiteral *literal = nsnull; + nsresult rv; +#ifdef NECKO + nsCOMPtr aURL; + rv = channel->GetURI(getter_AddRefs(aURL)); + if (NS_FAILED(rv)) return rv; +#endif + + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(trueStr.GetUnicode(), &literal))) + { + mDataSource->Unassert(mParent, kNC_loading, literal); + mDataSource->Unassert(mEngine, kNC_loading, literal); + NS_RELEASE(literal); + } + + if (!mLine) + { +#ifdef DEBUG + printf(" *** InternetSearchDataSourceCallback::OnStopRequest: no data.\n\n"); +#endif + + return(NS_OK); + } + +#if 0 + printf("\n\n%s\n\n", mLine); +#endif + + nsAutoString htmlResults(mLine); + nsCRT::free(mLine); + mLine = nsnull; + + // save HTML result page for this engine + const PRUnichar *htmlUni = htmlResults.GetUnicode(); + if (htmlUni) + { + nsCOMPtr htmlLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(htmlUni, getter_AddRefs(htmlLiteral)))) + { + rv = mDataSource->Assert(mEngine, kNC_HTML, htmlLiteral, PR_TRUE); + } + } + + // get data out of graph + nsAutoString data(""); + nsCOMPtr dataNode; + if (NS_FAILED(rv = mDataSource->GetTarget(mEngine, kNC_Data, PR_TRUE, getter_AddRefs(dataNode)))) + { + return(rv); + } + nsCOMPtr 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(""); + + 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); + +#if 0 + 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 + + // look for banner once in entire document + nsCOMPtr 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.Find(resultListEndStr, PR_TRUE); + if (resultListEnd >= 0) + { + htmlResults.Truncate(resultListEnd); + } + } + + PRBool trimItemEnd = PR_TRUE; + // if resultItemEndStr is not specified, try making it the same as resultItemStartStr + if (resultItemEndStr.Length() < 1) + { + resultItemEndStr = resultItemStartStr; + trimItemEnd = PR_FALSE; + } + + while(PR_TRUE) + { + PRInt32 resultItemStart; + resultItemStart = htmlResults.Find(resultItemStartStr, PR_TRUE); + if (resultItemStart < 0) break; + + htmlResults.Cut(0, resultItemStart + resultItemStartStr.Length()); + + PRInt32 resultItemEnd = htmlResults.Find(resultItemEndStr, PR_TRUE ); + 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); + } + +#if 0 + char *results = resultItem.ToNewCString(); + if (results) + { + printf("\n----- Search result: '%s'\n\n", results); + nsCRT::free(results); + results = nsnull; + } +#endif + + // look for href + PRInt32 hrefOffset = resultItem.Find("HREF=", PR_TRUE); + if (hrefOffset < 0) + { +#ifdef DEBUG + printf("\n***** Unable to find HREF!\n\n"); +#endif + continue; + } + + nsAutoString hrefStr(""); + PRInt32 quoteStartOffset = resultItem.FindCharInSet("\"\'>", hrefOffset); + PRInt32 quoteEndOffset; + if (quoteStartOffset < hrefOffset) + { + // handle case where HREF isn't quoted + quoteStartOffset = hrefOffset + nsCRT::strlen("HREF="); + quoteEndOffset = resultItem.FindCharInSet(">", quoteStartOffset); + if (quoteEndOffset < quoteStartOffset) continue; + } + else + { + if (resultItem[quoteStartOffset] == PRUnichar('>')) + { + // handle case where HREF isn't quoted + 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; + + // check to see if this needs to be an absolute URL + if (hrefStr[0] == PRUnichar('/')) + { +#ifdef NECKO + char *host = nsnull, *protocol = nsnull; +#else + const char *host = nsnull, *protocol = nsnull; +#endif + aURL->GetHost(&host); +#ifdef NECKO + aURL->GetScheme(&protocol); +#else + aURL->GetProtocol(&protocol); +#endif + if (host && protocol) + { + nsAutoString temp; + temp += protocol; + temp += "://"; + temp += host; + temp += hrefStr; + + hrefStr = temp; + } +#ifdef NECKO + if (host) nsCRT::free(host); + if (protocol) nsCRT::free(protocol); +#endif + } + + char *href = hrefStr.ToNewCString(); + if (!href) continue; + + nsAutoString site(href); + +#if 0 + printf("HREF: '%s'\n", href); +#endif + + nsCOMPtr res; + +// #define OLDWAY +#ifdef OLDWAY + rv = gRDFService->GetResource(href, getter_AddRefs(res)); +#else + const char *parentURI = nsnull; + mParent->GetValueConst(&parentURI); + if (!parentURI) break; + + // save HREF attribute as URL + if (NS_SUCCEEDED(rv = CreateAnonymousResource(&res))) + { + const PRUnichar *hrefUni = hrefStr.GetUnicode(); + if (hrefUni) + { + nsCOMPtr hrefLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(hrefUni, getter_AddRefs(hrefLiteral)))) + { + mDataSource->Assert(res, kNC_URL, hrefLiteral, PR_TRUE); + } + } + } +#endif + + nsCRT::free(href); + href = nsnull; + if (NS_FAILED(rv)) continue; + + // set HTML response chunk + const PRUnichar *htmlResponseUni = resultItem.GetUnicode(); + if (htmlResponseUni) + { + nsCOMPtr htmlResponseLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(htmlResponseUni, getter_AddRefs(htmlResponseLiteral)))) + { + if (htmlResponseLiteral) + { + mDataSource->Assert(res, kNC_HTML, htmlResponseLiteral, PR_TRUE); + } + } + } + + // set banner (if we have one) + if (bannerLiteral) + { + mDataSource->Assert(res, kNC_Banner, bannerLiteral, PR_TRUE); + } + + // look for Site (if it isn't already set) + nsCOMPtr oldSiteRes = nsnull; + mDataSource->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 siteLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(siteUni, getter_AddRefs(siteLiteral)))) + { + if (siteLiteral) + { + mDataSource->Assert(res, kNC_Site, siteLiteral, PR_TRUE); + } + } + } + } + } + } + + // look for name + PRInt32 anchorEnd = resultItem.FindCharInSet(">", quoteEndOffset); + if (anchorEnd < quoteEndOffset) + { +#ifdef DEBUG + printf("\n\nSearch: Unable to find ending > when computing name.\n\n"); +#endif + continue; + } +// PRInt32 anchorStop = resultItem.FindChar(PRUnichar('<'), PR_TRUE, quoteEndOffset); + PRInt32 anchorStop = resultItem.Find("", PR_TRUE, quoteEndOffset); + if (anchorStop < anchorEnd) + { +#ifdef DEBUG + printf("\n\nSearch: Unable to find tag to compute name.\n\n"); +#endif + continue; + } + + nsAutoString nameStr; + resultItem.Mid(nameStr, anchorEnd + 1, anchorStop - anchorEnd - 1); + + // munge any """ in name + PRInt32 quotOffset; + while ((quotOffset = nameStr.Find(""", PR_TRUE)) >= 0) + { + nameStr.Cut(quotOffset, strlen(""")); + nameStr.Insert(PRUnichar('\"'), quotOffset); + } + + // munge any "&" in name + PRInt32 ampOffset; + while ((ampOffset = nameStr.Find("&", PR_TRUE)) >= 0) + { + nameStr.Cut(ampOffset, strlen("&")); + nameStr.Insert(PRUnichar('&'), ampOffset); + } + + // munge any " " in name + PRInt32 nbspOffset; + while ((nbspOffset = nameStr.Find(" ", PR_TRUE)) >= 0) + { + nameStr.Cut(nbspOffset, strlen(" ")); + nameStr.Insert(PRUnichar(' '), nbspOffset); + } + + // munge any "<" in name + PRInt32 ltOffset; + while ((ltOffset = nameStr.Find("<", PR_TRUE)) >= 0) + { + nameStr.Cut(ltOffset, strlen("<")); + nameStr.Insert(PRUnichar('<'), ltOffset); + } + + // munge any ">" in name + PRInt32 gtOffset; + while ((gtOffset = nameStr.Find(">", PR_TRUE)) >= 0) + { + nameStr.Cut(gtOffset, strlen(">")); + nameStr.Insert(PRUnichar('>'), gtOffset); + } + + // munge out anything inside of HTML "<" / ">" tags + PRInt32 tagStartOffset; + while ((tagStartOffset = nameStr.FindCharInSet("<", 0)) >= 0) + { + PRInt32 tagEndOffset = nameStr.FindCharInSet(">", tagStartOffset); + if (tagEndOffset <= tagStartOffset) break; + nameStr.Cut(tagStartOffset, tagEndOffset - tagStartOffset + 1); + } + + // cut out any CRs or LFs + PRInt32 eolOffset; + while ((eolOffset = nameStr.FindCharInSet("\n\r", 0)) >= 0) + { + nameStr.Cut(eolOffset, 1); + } + // and trim name + nameStr = nameStr.Trim(" \t"); + + // look for Name (if it isn't already set) + nsCOMPtr oldNameRes = nsnull; + mDataSource->GetTarget(res, kNC_Name, PR_TRUE, getter_AddRefs(oldNameRes)); + if (!oldNameRes) + { + if (nameStr.Length() > 0) + { + const PRUnichar *nameUni = nameStr.GetUnicode(); + if (nameUni) + { + nsCOMPtr nameLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(nameUni, getter_AddRefs(nameLiteral)))) + { + if (nameLiteral) + { + mDataSource->Assert(res, kNC_Name, nameLiteral, PR_TRUE); + } + } + } + } + } + + // look for relevance + nsAutoString relItem; + PRInt32 relStart; + if ((relStart = resultItem.Find(relevanceStartStr, PR_TRUE)) >= 0) + { + PRInt32 relEnd = resultItem.Find(relevanceEndStr, PR_TRUE); + if (relEnd > relStart) + { + resultItem.Mid(relItem, relStart + relevanceStartStr.Length(), + relEnd - relStart - relevanceStartStr.Length()); + } + } + + // look for Relevance (if it isn't already set) + nsCOMPtr oldRelRes = nsnull; + mDataSource->GetTarget(res, kNC_Relevance, PR_TRUE, getter_AddRefs(oldRelRes)); + if (!oldRelRes) + { + if (relItem.Length() > 0) + { + // save real relevance + const PRUnichar *relUni = relItem.GetUnicode(); + if (relUni) + { + // take out any characters that aren't numeric or "%" + nsAutoString relStr(relUni); + PRInt32 len = relStr.Length(); + for (PRInt32 x=len-1; x>=0; x--) + { + PRUnichar ch; + ch = relStr.CharAt(x); + if ((ch != PRUnichar('%')) && + ((ch < PRUnichar('0')) || (ch > PRUnichar('9')))) + { + relStr.Cut(x, 1); + } + } + // make sure it ends with a "%" + len = relStr.Length(); + if (len > 0) + { + PRUnichar ch; + ch = relStr.CharAt(len - 1); + if (ch != PRUnichar('%')) + { + relStr += PRUnichar('%'); + } + } + else + { + relStr = "-"; + } + + relUni = relStr.GetUnicode(); + + nsCOMPtr relLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(relUni, getter_AddRefs(relLiteral)))) + { + if (relLiteral) + { + mDataSource->Assert(res, kNC_Relevance, relLiteral, PR_TRUE); + } + } + } + + // If its a percentage, remove "%" + if (relItem[relItem.Length()-1] == PRUnichar('%')) + { + relItem.Cut(relItem.Length()-1, 1); + } + + // left-pad with "0"s and set special sorting value + nsAutoString zero("000"); + if (relItem.Length() < 3) + { + relItem.Insert(zero, 0, 3-relItem.Length()); + } + + const PRUnichar *relSortUni = relItem.GetUnicode(); + if (relSortUni) + { + nsCOMPtr relSortLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(relSortUni, getter_AddRefs(relSortLiteral)))) + { + if (relSortLiteral) + { + mDataSource->Assert(res, kNC_RelevanceSort, relSortLiteral, PR_TRUE); + } + } + } + } + } + + // set reference to engine this came from (if it isn't already set) + nsCOMPtr oldEngineRes = nsnull; + mDataSource->GetTarget(res, kNC_Engine, PR_TRUE, getter_AddRefs(oldEngineRes)); + if (!oldEngineRes) + { + nsAutoString engineStr; + if (NS_SUCCEEDED(rv = InternetSearchDataSource::GetData(data, "search", "name", engineStr))) + { + const PRUnichar *engineUni = engineStr.GetUnicode(); + nsCOMPtr engineLiteral; + if (NS_SUCCEEDED(rv = gRDFService->GetLiteral(engineUni, getter_AddRefs(engineLiteral)))) + { + if (engineLiteral) + { + mDataSource->Assert(res, kNC_Engine, engineLiteral, PR_TRUE); + } + } + } + } +#ifdef OLDWAY + // Note: always add in parent-child relationship last! (if it isn't already set) + PRBool parentHasChildFlag = PR_FALSE; + mDataSource->HasAssertion(mParent, kNC_Child, res, PR_TRUE, &parentHasChildFlag); + if (parentHasChildFlag == PR_FALSE) +#endif + { + rv = mDataSource->Assert(mParent, kNC_Child, res, PR_TRUE); + } + + // Persist this under kNC_LastSearchRoot + if (mDataSource) + { + rv = mDataSource->Assert(kNC_LastSearchRoot, kNC_Child, res, PR_TRUE); + } + + } + return(NS_OK); +} + + + +// stream listener methods + + + +NS_IMPL_ISUPPORTS(InternetSearchDataSourceCallback, InternetSearchDataSourceCallback::GetIID()); + + + +NS_IMETHODIMP +InternetSearchDataSourceCallback::OnDataAvailable(nsIChannel* channel, nsISupports *ctxt, + nsIInputStream *aIStream, PRUint32 sourceOffset, PRUint32 aLength) +{ + nsresult rv = NS_OK; + + if (aLength > 0) + { + nsAutoString line; + if (mLine) + { + line += mLine; + nsCRT::free(mLine); + mLine = nsnull; + } + + char buffer[257]; + while (aLength > 0) + { + PRUint32 count=0, numBytes = (aLength > sizeof(buffer)-1 ? sizeof(buffer)-1 : aLength); + if (NS_FAILED(rv = aIStream->Read(buffer, numBytes, &count)) || count == 0) + { +#ifdef DEBUG + printf("Search datasource read failure.\n"); +#endif + break; + } + if (numBytes != count) + { +#ifdef DEBUG + printf("Search datasource read # of bytes failure.\n"); +#endif + break; + } + buffer[count] = '\0'; + line += buffer; + aLength -= count; + } + mLine = line.ToNewCString(); + } + return(rv); +} diff --git a/xpfe/components/search/src/nsLocalSearchService.cpp b/xpfe/components/search/src/nsLocalSearchService.cpp new file mode 100755 index 000000000000..9323563277ff --- /dev/null +++ b/xpfe/components/search/src/nsLocalSearchService.cpp @@ -0,0 +1,937 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8; c-file-style: "stroustrup" -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + Implementation for a find RDF data store. + */ + +#include // for toupper() +#include +#include "nscore.h" +#include "nsCOMPtr.h" +#include "nsIRDFDataSource.h" +#include "nsIRDFNode.h" +#include "nsIRDFObserver.h" +#include "nsIServiceManager.h" +#include "nsISupportsArray.h" +#include "nsEnumeratorUtils.h" +#include "nsString.h" +#include "nsVoidArray.h" // XXX introduces dependency on raptorbase +#include "nsXPIDLString.h" +#include "nsRDFCID.h" +//#include "rdfutil.h" +#include "nsIRDFService.h" +#include "xp_core.h" +#include "plhash.h" +#include "plstr.h" +#include "prmem.h" +#include "prprf.h" +#include "prio.h" +#include "rdf.h" +#include "nsISearchService.h" + +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID); + + +typedef struct _findTokenStruct +{ + char *token; + char *value; +} findTokenStruct, *findTokenPtr; + + + +class LocalSearchDataSource : public nsILocalSearchService +{ +private: + nsCOMPtr mObservers; + + static PRInt32 gRefCnt; + + // pseudo-constants + static nsIRDFResource *kNC_Child; + static nsIRDFResource *kNC_Name; + static nsIRDFResource *kNC_URL; + static nsIRDFResource *kNC_FindObject; + static nsIRDFResource *kNC_pulse; + static nsIRDFResource *kRDF_InstanceOf; + static nsIRDFResource *kRDF_type; + +friend NS_IMETHODIMP NS_NewLocalSearchService(nsISupports* aOuter, REFNSIID aIID, void** aResult); + + NS_METHOD getFindResults(nsIRDFResource *source, nsISimpleEnumerator** aResult); + + NS_METHOD getFindName(nsIRDFResource *source, nsIRDFLiteral** aResult); + + NS_METHOD parseResourceIntoFindTokens(nsIRDFResource *u, + findTokenPtr tokens); + NS_METHOD doMatch(nsIRDFLiteral *literal, char *matchMethod, + char *matchText); + NS_METHOD parseFindURL(nsIRDFResource *u, + nsISupportsArray *array); + +public: + + NS_DECL_ISUPPORTS + + LocalSearchDataSource(void); + virtual ~LocalSearchDataSource(void); + + nsresult Init(); + + // nsIRDFDataSource methods + + NS_IMETHOD GetURI(char **uri); + NS_IMETHOD GetSource(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsIRDFResource **source /* out */); + NS_IMETHOD GetSources(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsISimpleEnumerator **sources /* out */); + NS_IMETHOD GetTarget(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsIRDFNode **target /* out */); + NS_IMETHOD GetTargets(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsISimpleEnumerator **targets /* out */); + NS_IMETHOD Assert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv); + NS_IMETHOD Unassert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target); + NS_IMETHOD Change(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aOldTarget, + nsIRDFNode* aNewTarget); + NS_IMETHOD Move(nsIRDFResource* aOldSource, + nsIRDFResource* aNewSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget); + NS_IMETHOD HasAssertion(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + PRBool *hasAssertion /* out */); + NS_IMETHOD ArcLabelsIn(nsIRDFNode *node, + nsISimpleEnumerator **labels /* out */); + NS_IMETHOD ArcLabelsOut(nsIRDFResource *source, + nsISimpleEnumerator **labels /* out */); + NS_IMETHOD GetAllResources(nsISimpleEnumerator** aCursor); + NS_IMETHOD AddObserver(nsIRDFObserver *n); + NS_IMETHOD RemoveObserver(nsIRDFObserver *n); + NS_IMETHOD GetAllCommands(nsIRDFResource* source, + nsIEnumerator/**/** commands); + NS_IMETHOD GetAllCmds(nsIRDFResource* source, + nsISimpleEnumerator/**/** commands); + NS_IMETHOD IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult); + NS_IMETHOD DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments); +}; + + + +static nsIRDFService *gRDFService = nsnull; +static LocalSearchDataSource *gLocalSearchDataSource = nsnull; + +PRInt32 LocalSearchDataSource::gRefCnt; + +nsIRDFResource *LocalSearchDataSource::kNC_Child; +nsIRDFResource *LocalSearchDataSource::kNC_Name; +nsIRDFResource *LocalSearchDataSource::kNC_URL; +nsIRDFResource *LocalSearchDataSource::kNC_FindObject; +nsIRDFResource *LocalSearchDataSource::kNC_pulse; +nsIRDFResource *LocalSearchDataSource::kRDF_InstanceOf; +nsIRDFResource *LocalSearchDataSource::kRDF_type; + +static const char kFindProtocol[] = "find:"; + + + +static PRBool +isFindURI(nsIRDFResource *r) +{ + PRBool isFindURIFlag = PR_FALSE; + const char *uri = nsnull; + + r->GetValueConst(&uri); + if ((uri) && (!strncmp(uri, kFindProtocol, sizeof(kFindProtocol) - 1))) + { + isFindURIFlag = PR_TRUE; + } + return(isFindURIFlag); +} + + + +LocalSearchDataSource::LocalSearchDataSource(void) +{ + NS_INIT_REFCNT(); + + if (gRefCnt++ == 0) + { + nsresult rv = nsServiceManager::GetService(kRDFServiceCID, + nsIRDFService::GetIID(), + (nsISupports**) &gRDFService); + + PR_ASSERT(NS_SUCCEEDED(rv)); + + gRDFService->GetResource(NC_NAMESPACE_URI "child", &kNC_Child); + gRDFService->GetResource(NC_NAMESPACE_URI "Name", &kNC_Name); + gRDFService->GetResource(NC_NAMESPACE_URI "URL", &kNC_URL); + gRDFService->GetResource(NC_NAMESPACE_URI "FindObject", &kNC_FindObject); + gRDFService->GetResource(NC_NAMESPACE_URI "pulse", &kNC_pulse); + + gRDFService->GetResource(RDF_NAMESPACE_URI "instanceOf", &kRDF_InstanceOf); + gRDFService->GetResource(RDF_NAMESPACE_URI "type", &kRDF_type); + + gLocalSearchDataSource = this; + } +} + + + +LocalSearchDataSource::~LocalSearchDataSource (void) +{ + if (--gRefCnt == 0) + { + NS_RELEASE(kNC_Child); + NS_RELEASE(kNC_Name); + NS_RELEASE(kNC_URL); + NS_RELEASE(kNC_FindObject); + NS_RELEASE(kNC_pulse); + NS_RELEASE(kRDF_InstanceOf); + NS_RELEASE(kRDF_type); + + gLocalSearchDataSource = nsnull; + nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService); + gRDFService = nsnull; + } +} + + + +nsresult +LocalSearchDataSource::Init() +{ + nsresult rv = NS_ERROR_OUT_OF_MEMORY; + +#if 0 + // register this as a named data source with the service manager + if (NS_FAILED(rv = gRDFService->RegisterDataSource(this, PR_FALSE))) + return(rv); +#endif + + return(rv); +} + + + +NS_IMPL_ISUPPORTS(LocalSearchDataSource, nsIRDFDataSource::GetIID()); + + + +NS_IMETHODIMP +LocalSearchDataSource::GetURI(char **uri) +{ + NS_PRECONDITION(uri != nsnull, "null ptr"); + if (! uri) + return NS_ERROR_NULL_POINTER; + + if ((*uri = nsXPIDLCString::Copy("rdf:find")) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + return NS_OK; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetSource(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFResource** source /* out */) +{ + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + *source = nsnull; + return NS_RDF_NO_VALUE; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetSources(nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + nsISimpleEnumerator **sources /* out */) +{ + NS_NOTYETIMPLEMENTED("write me"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetTarget(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsIRDFNode **target /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_RDF_NO_VALUE; + + // we only have positive assertions in the find data source. + if (! tv) + return rv; + + if (isFindURI(source)) + { + if (property == kNC_Name) + { +// rv = GetName(source, &array); + } + else if (property == kNC_URL) + { + // note: lie and say there is no URL +// rv = GetURL(source, &array); + nsAutoString url(""); + nsIRDFLiteral *literal; + gRDFService->GetLiteral(url.GetUnicode(), &literal); + *target = literal; + rv = NS_OK; + } + else if (property == kRDF_type) + { + const char *uri = nsnull; + rv = kNC_FindObject->GetValueConst(&uri); + if (NS_FAILED(rv)) return rv; + + nsAutoString url(uri); + nsIRDFLiteral *literal; + gRDFService->GetLiteral(url.GetUnicode(), &literal); + + *target = literal; + return NS_OK; + } + else if (property == kNC_pulse) + { + nsAutoString pulse("15"); + nsIRDFLiteral *pulseLiteral; + rv = gRDFService->GetLiteral(pulse.GetUnicode(), &pulseLiteral); + if (NS_FAILED(rv)) return rv; + + *target = pulseLiteral; + return NS_OK; + } + } + return NS_RDF_NO_VALUE; +} + + + +NS_METHOD +LocalSearchDataSource::parseResourceIntoFindTokens(nsIRDFResource *u, findTokenPtr tokens) +{ + const char *uri = nsnull; + char *id, *token, *value; + int loop; + nsresult rv; + + if (NS_FAILED(rv = u->GetValueConst(&uri))) return(rv); + +#ifdef DEBUG + printf("Find: %s\n", (const char*) uri); +#endif + + if (!(id = PL_strdup(uri + sizeof(kFindProtocol) - 1))) + return(NS_ERROR_OUT_OF_MEMORY); + + /* parse ID, build up token list */ + if ((token = strtok(id, "&")) != NULL) + { + while (token != NULL) + { + if ((value = strstr(token, "=")) != NULL) + { + *value++ = '\0'; + } + for (loop=0; tokens[loop].token != NULL; loop++) + { + if (!strcmp(token, tokens[loop].token)) + { + tokens[loop].value = PL_strdup(value); + break; + } + } + token = strtok(NULL, "&"); + } + } + PL_strfree(id); + return(NS_OK); +} + + + +NS_METHOD +LocalSearchDataSource::doMatch(nsIRDFLiteral *literal, char *matchMethod, char *matchText) +{ + PRBool found = PR_FALSE; + + if ((nsnull == literal) || (nsnull == matchMethod) || (nsnull == matchText)) + return(found); + + nsXPIDLString str; + literal->GetValue( getter_Copies(str) ); + if (! str) return(found); + nsAutoString value(str); + + if (!PL_strcmp(matchMethod, "contains")) + { + if (value.Find(matchText, PR_TRUE) >= 0) + found = PR_TRUE; + } + else if (!PL_strcmp(matchMethod, "startswith")) + { + if (value.Find(matchText, PR_TRUE) == 0) + found = PR_TRUE; + } + else if (!PL_strcmp(matchMethod, "endswith")) + { + PRInt32 pos = value.RFind(matchText, PR_TRUE); + if ((pos >= 0) && (pos == (value.Length() - PRInt32(strlen(matchText))))) + found = PR_TRUE; + } + else if (!PL_strcmp(matchMethod, "is")) + { + if (value.EqualsIgnoreCase(matchText)) + found = PR_TRUE; + } + else if (!PL_strcmp(matchMethod, "isnot")) + { + if (!value.EqualsIgnoreCase(matchText)) + found = PR_TRUE; + } + else if (!PL_strcmp(matchMethod, "doesntcontain")) + { + if (value.Find(matchText, PR_TRUE) < 0) + found = PR_TRUE; + } + return(found); +} + + + +NS_METHOD +LocalSearchDataSource::parseFindURL(nsIRDFResource *u, nsISupportsArray *array) +{ + findTokenStruct tokens[5]; + nsresult rv; + int loop; + + /* build up a token list */ + tokens[0].token = "datasource"; tokens[0].value = NULL; + tokens[1].token = "match"; tokens[1].value = NULL; + tokens[2].token = "method"; tokens[2].value = NULL; + tokens[3].token = "text"; tokens[3].value = NULL; + tokens[4].token = NULL; tokens[4].value = NULL; + + // parse find URI, get parameters, search in appropriate datasource(s), return results + if (NS_SUCCEEDED(rv = parseResourceIntoFindTokens(u, tokens))) + { + nsIRDFDataSource *datasource; + if (NS_SUCCEEDED(rv = gRDFService->GetDataSource(tokens[0].value, &datasource))) + { + nsISimpleEnumerator *cursor = nsnull; + if (NS_SUCCEEDED(rv = datasource->GetAllResources(&cursor))) + { + while (1) + { + PRBool hasMore; + rv = cursor->HasMoreElements(&hasMore); + if (NS_FAILED(rv)) + break; + + if (! hasMore) + break; + + nsCOMPtr isupports; + rv = cursor->GetNext(getter_AddRefs(isupports)); + if (NS_SUCCEEDED(rv)) + { + nsIRDFResource *source = nsnull; + if (NS_SUCCEEDED(rv = isupports->QueryInterface(nsIRDFResource::GetIID(), (void **)&source))) + { + const char *uri = nsnull; + source->GetValueConst(&uri); + + // never match against a "find:" URI + if ((uri) && (PL_strncmp(uri, kFindProtocol, sizeof(kFindProtocol) - 1))) + { + nsIRDFResource *property = nsnull; + if (NS_SUCCEEDED(rv = gRDFService->GetResource(tokens[1].value, &property)) && + (rv != NS_RDF_NO_VALUE) && (nsnull != property)) + { + nsIRDFNode *value = nsnull; + if (NS_SUCCEEDED(rv = datasource->GetTarget(source, property, PR_TRUE, &value)) && + (rv != NS_RDF_NO_VALUE) && (nsnull != value)) + { + nsIRDFLiteral *literal = nsnull; + if (NS_SUCCEEDED(rv = value->QueryInterface(nsIRDFLiteral::GetIID(), (void **)&literal)) && + (rv != NS_RDF_NO_VALUE) && (nsnull != literal)) + { + if (PR_TRUE == doMatch(literal, tokens[2].value, tokens[3].value)) + { + array->AppendElement(source); + } + NS_RELEASE(literal); + } + } + NS_RELEASE(property); + } + } + NS_RELEASE(source); + } + } + } + if (rv == NS_RDF_CURSOR_EMPTY) + { + rv = NS_OK; + } + NS_RELEASE(cursor); + } + NS_RELEASE(datasource); + } + } + /* free values in token list */ + for (loop=0; tokens[loop].token != NULL; loop++) + { + if (tokens[loop].value != NULL) + { + PL_strfree(tokens[loop].value); + tokens[loop].value = NULL; + } + } + return(rv); +} + + + +NS_METHOD +LocalSearchDataSource::getFindResults(nsIRDFResource *source, nsISimpleEnumerator** aResult) +{ + nsresult rv; + nsCOMPtr nameArray; + rv = NS_NewISupportsArray( getter_AddRefs(nameArray) ); + if (NS_FAILED(rv)) return rv; + + rv = parseFindURL(source, nameArray); + if (NS_FAILED(rv)) return rv; + + nsISimpleEnumerator* result = new nsArrayEnumerator(nameArray); + if (! result) + return(NS_ERROR_OUT_OF_MEMORY); + + NS_ADDREF(result); + *aResult = result; + + return NS_OK; +} + + + +NS_METHOD +LocalSearchDataSource::getFindName(nsIRDFResource *source, nsIRDFLiteral** aResult) +{ + // XXX construct find URI human-readable name + *aResult = nsnull; + return(NS_OK); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetTargets(nsIRDFResource *source, + nsIRDFResource *property, + PRBool tv, + nsISimpleEnumerator **targets /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(targets != nsnull, "null ptr"); + if (! targets) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_ERROR_FAILURE; + + // we only have positive assertions in the find data source. + if (! tv) + return rv; + + if (isFindURI(source)) + { + if (property == kNC_Child) + { + return getFindResults(source, targets); + } + else if (property == kNC_Name) + { + nsCOMPtr name; + rv = getFindName(source, getter_AddRefs(name)); + if (NS_FAILED(rv)) return rv; + + nsISimpleEnumerator* result = + new nsSingletonEnumerator(name); + + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(result); + *targets = result; + return NS_OK; + } + else if (property == kRDF_type) + { + nsXPIDLCString uri; + rv = kNC_FindObject->GetValue( getter_Copies(uri) ); + if (NS_FAILED(rv)) return rv; + + nsAutoString url(uri); + nsIRDFLiteral *literal; + rv = gRDFService->GetLiteral(url.GetUnicode(), &literal); + if (NS_FAILED(rv)) return rv; + + nsISimpleEnumerator* result = new nsSingletonEnumerator(literal); + + NS_RELEASE(literal); + + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(result); + *targets = result; + return NS_OK; + } + else if (property == kNC_pulse) + { + nsAutoString pulse("15"); + nsIRDFLiteral *pulseLiteral; + rv = gRDFService->GetLiteral(pulse.GetUnicode(), &pulseLiteral); + if (NS_FAILED(rv)) return rv; + + nsISimpleEnumerator* result = new nsSingletonEnumerator(pulseLiteral); + + NS_RELEASE(pulseLiteral); + + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(result); + *targets = result; + return NS_OK; + } + } + + return NS_NewEmptyEnumerator(targets); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::Assert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::Unassert(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::Change(nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode* aOldTarget, + nsIRDFNode* aNewTarget) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::Move(nsIRDFResource* aOldSource, + nsIRDFResource* aNewSource, + nsIRDFResource* aProperty, + nsIRDFNode* aTarget) +{ + return NS_RDF_ASSERTION_REJECTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::HasAssertion(nsIRDFResource *source, + nsIRDFResource *property, + nsIRDFNode *target, + PRBool tv, + PRBool *hasAssertion /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(property != nsnull, "null ptr"); + if (! property) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(hasAssertion != nsnull, "null ptr"); + if (! hasAssertion) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + + *hasAssertion = PR_FALSE; + + // we only have positive assertions in the find data source. + if (! tv) + return rv; + + if (isFindURI(source)) + { + if (property == kRDF_type) + { + if ((nsIRDFResource *)target == kRDF_type) + { + *hasAssertion = PR_TRUE; + } + } + } + return (rv); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::ArcLabelsIn(nsIRDFNode *node, + nsISimpleEnumerator ** labels /* out */) +{ + NS_NOTYETIMPLEMENTED("write me"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::ArcLabelsOut(nsIRDFResource *source, + nsISimpleEnumerator **labels /* out */) +{ + NS_PRECONDITION(source != nsnull, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(labels != nsnull, "null ptr"); + if (! labels) + return NS_ERROR_NULL_POINTER; + + nsresult rv; + + if (isFindURI(source)) + { + nsCOMPtr array; + rv = NS_NewISupportsArray( getter_AddRefs(array) ); + if (NS_FAILED(rv)) return rv; + + array->AppendElement(kNC_Child); + array->AppendElement(kNC_pulse); + + nsISimpleEnumerator* result = new nsArrayEnumerator(array); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(result); + *labels = result; + return(NS_OK); + } + return(NS_NewEmptyEnumerator(labels)); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetAllResources(nsISimpleEnumerator** aCursor) +{ + NS_NOTYETIMPLEMENTED("sorry!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::AddObserver(nsIRDFObserver *n) +{ + NS_PRECONDITION(n != nsnull, "null ptr"); + if (! n) + return NS_ERROR_NULL_POINTER; + + if (! mObservers) + { + nsresult rv; + rv = NS_NewISupportsArray(getter_AddRefs(mObservers)); + if (NS_FAILED(rv)) return rv; + } + return mObservers->AppendElement(n) ? NS_OK : NS_ERROR_FAILURE; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::RemoveObserver(nsIRDFObserver *n) +{ + NS_PRECONDITION(n != nsnull, "null ptr"); + if (! n) + return NS_ERROR_NULL_POINTER; + + if (! mObservers) + return(NS_OK); + + NS_VERIFY(mObservers->RemoveElement(n), "observer not present"); + return(NS_OK); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetAllCommands(nsIRDFResource* source,nsIEnumerator/**/** commands) +{ + NS_NOTYETIMPLEMENTED("write me!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +LocalSearchDataSource::GetAllCmds(nsIRDFResource* source, nsISimpleEnumerator/**/** commands) +{ + return(NS_NewEmptyEnumerator(commands)); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult) +{ + return(NS_ERROR_NOT_IMPLEMENTED); +} + + + +NS_IMETHODIMP +LocalSearchDataSource::DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments) +{ + return(NS_ERROR_NOT_IMPLEMENTED); +} + + + +nsresult +NS_NewLocalSearchService(nsISupports* aOuter, REFNSIID aIID, void** aResult) +{ + NS_PRECONDITION(aResult != nsnull, "null ptr"); + if (! aResult) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(aOuter == nsnull, "no aggregation"); + if (aOuter) + return NS_ERROR_NO_AGGREGATION; + + nsresult rv = NS_OK; + + LocalSearchDataSource* result = new LocalSearchDataSource(); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + rv = result->Init(); + if (NS_SUCCEEDED(rv)) + rv = result->QueryInterface(aIID, aResult); + + if (NS_FAILED(rv)) { + delete result; + *aResult = nsnull; + return rv; + } + + return rv; +} diff --git a/xpfe/components/search/src/nsRegisterSearch.cpp b/xpfe/components/search/src/nsRegisterSearch.cpp new file mode 100755 index 000000000000..9473649b2936 --- /dev/null +++ b/xpfe/components/search/src/nsRegisterSearch.cpp @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8; c-file-style: "stroustrup" -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "nsRDFCID.h" +#include "nscore.h" +#include "nsCOMPtr.h" +#include "nsIFactory.h" +#include "nsIGenericFactory.h" +#include "nsIComponentManager.h" +#include "nsIServiceManager.h" +#include "nsIRDFDataSource.h" +#include "nsISearchService.h" + +static NS_DEFINE_CID(kLocalSearchServiceCID, NS_RDFFINDDATASOURCE_CID); +static NS_DEFINE_CID(kInternetSearchServiceCID, NS_RDFSEARCHDATASOURCE_CID); +static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID); +static NS_DEFINE_CID(kGenericFactoryCID, NS_GENERICFACTORY_CID); + +nsresult NS_NewLocalSearchService(nsISupports* aOuter, REFNSIID aIID, void** aResult); +nsresult NS_NewInternetSearchService(nsISupports* aOuter, REFNSIID aIID, void** aResult); + + + +//////////////////////////////////////////////////////////////////////// +// Component Exports + + + +extern "C" PR_IMPLEMENT(nsresult) +NSGetFactory(nsISupports* aServiceMgr, + const nsCID &aClass, + const char *aClassName, + const char *aProgID, + nsIFactory **aFactory) +{ + NS_PRECONDITION(aFactory != nsnull, "null ptr"); + if (! aFactory) + return NS_ERROR_NULL_POINTER; + + nsIGenericFactory::ConstructorProcPtr constructor; + + if (aClass.Equals(kInternetSearchServiceCID)) { + constructor = NS_NewInternetSearchService; + } + else if (aClass.Equals(kLocalSearchServiceCID)) { + constructor = NS_NewLocalSearchService; + } + else { + *aFactory = nsnull; + return NS_NOINTERFACE; // XXX + } + + nsresult rv; + NS_WITH_SERVICE1(nsIComponentManager, compMgr, aServiceMgr, kComponentManagerCID, &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr factory; + rv = compMgr->CreateInstance(kGenericFactoryCID, + nsnull, + nsIGenericFactory::GetIID(), + getter_AddRefs(factory)); + + if (NS_FAILED(rv)) return rv; + + rv = factory->SetConstructor(constructor); + if (NS_FAILED(rv)) return rv; + + *aFactory = factory; + NS_ADDREF(*aFactory); + return NS_OK; +} + + + +extern "C" PR_IMPLEMENT(nsresult) +NSRegisterSelf(nsISupports* aServMgr , const char* aPath) +{ + nsresult rv; + + nsCOMPtr servMgr(do_QueryInterface(aServMgr, &rv)); + if (NS_FAILED(rv)) return rv; + + NS_WITH_SERVICE1(nsIComponentManager, compMgr, servMgr, kComponentManagerCID, &rv); + if (NS_FAILED(rv)) return rv; + + rv = compMgr->RegisterComponent(kLocalSearchServiceCID, "LocalSearch", + NS_LOCALSEARCH_SERVICE_PROGID, + aPath, PR_TRUE, PR_TRUE); + + rv = compMgr->RegisterComponent(kLocalSearchServiceCID, "LocalSearch", + NS_LOCALSEARCH_DATASOURCE_PROGID, + aPath, PR_TRUE, PR_TRUE); + + rv = compMgr->RegisterComponent(kInternetSearchServiceCID, "InternetSearch", + NS_INTERNETSEARCH_SERVICE_PROGID, + aPath, PR_TRUE, PR_TRUE); + + rv = compMgr->RegisterComponent(kInternetSearchServiceCID, "InternetSearch", + NS_INTERNETSEARCH_DATASOURCE_PROGID, + aPath, PR_TRUE, PR_TRUE); + + return NS_OK; +} + + + +extern "C" PR_IMPLEMENT(nsresult) +NSUnregisterSelf(nsISupports* aServMgr, const char* aPath) +{ + nsresult rv; + + nsCOMPtr servMgr(do_QueryInterface(aServMgr, &rv)); + if (NS_FAILED(rv)) return rv; + + NS_WITH_SERVICE1(nsIComponentManager, compMgr, servMgr, kComponentManagerCID, &rv); + if (NS_FAILED(rv)) return rv; + + rv = compMgr->UnregisterComponent(kLocalSearchServiceCID, aPath); + rv = compMgr->UnregisterComponent(kInternetSearchServiceCID, aPath); + + return NS_OK; +}