/* This file is part of KHelpCenter. Copyright (c) 2005 Cornelius Schumacher <schumacher@kde.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "searchhandler.h" #include "searchengine.h" #include "prefs.h" #include "docentry.h" #include <kdesktopfile.h> #include <kprocess.h> #include <kdebug.h> #include <kmessagebox.h> #include <klocale.h> #include <kstandarddirs.h> #include <stdlib.h> using namespace KHC; SearchHandler::SearchHandler() { mLang = KGlobal::locale()->language().left( 2 ); } SearchHandler *SearchHandler::initFromFile( const TQString &filename ) { SearchHandler *handler = new SearchHandler; KDesktopFile file( filename ); handler->mSearchCommand = file.readEntry( "SearchCommand" ); handler->mSearchUrl = file.readEntry( "SearchUrl" ); handler->mIndexCommand = file.readEntry( "IndexCommand" ); handler->mDocumentTypes = file.readListEntry( "DocumentTypes" ); return handler; } TQStringList SearchHandler::documentTypes() const { return mDocumentTypes; } TQString SearchHandler::indexCommand( const TQString &identifier ) { TQString cmd = mIndexCommand; cmd.replace( "%i", identifier ); cmd.replace( "%d", Prefs::indexDirectory() ); cmd.replace( "%l", mLang ); return cmd; } bool SearchHandler::checkPaths() const { if ( !mSearchCommand.isEmpty() && !checkBinary( mSearchCommand ) ) return false; if ( !mIndexCommand.isEmpty() && !checkBinary( mIndexCommand ) ) return false; return true; } bool SearchHandler::checkBinary( const TQString &cmd ) const { TQString binary; int pos = cmd.find( ' ' ); if ( pos < 0 ) binary = cmd; else binary = cmd.left( pos ); return !KStandardDirs::findExe( binary ).isEmpty(); } void SearchHandler::search( DocEntry *entry, const TQStringList &words, int maxResults, SearchEngine::Operation operation ) { kdDebug() << "SearchHandler::search(): " << entry->identifier() << endl; if ( !mSearchCommand.isEmpty() ) { TQString cmdString = SearchEngine::substituteSearchQuery( mSearchCommand, entry->identifier(), words, maxResults, operation, mLang ); kdDebug() << "SearchHandler::search() CMD: " << cmdString << endl; KProcess *proc = new KProcess(); TQStringList cmd = TQStringList::split( " ", cmdString ); TQStringList::ConstIterator it; for( it = cmd.begin(); it != cmd.end(); ++it ) { TQString arg = *it; if ( arg.left( 1 ) == "\"" && arg.right( 1 ) =="\"" ) { arg = arg.mid( 1, arg.length() - 2 ); } *proc << arg.utf8(); } connect( proc, TQT_SIGNAL( receivedStdout( KProcess *, char *, int ) ), TQT_SLOT( searchStdout( KProcess *, char *, int ) ) ); connect( proc, TQT_SIGNAL( receivedStderr( KProcess *, char *, int ) ), TQT_SLOT( searchStderr( KProcess *, char *, int ) ) ); connect( proc, TQT_SIGNAL( processExited( KProcess * ) ), TQT_SLOT( searchExited( KProcess * ) ) ); SearchJob *searchJob = new SearchJob; searchJob->mEntry = entry; searchJob->mProcess = proc; searchJob->mCmd = cmdString; mProcessJobs.insert( proc, searchJob ); if ( !proc->start( KProcess::NotifyOnExit, KProcess::All ) ) { TQString txt = i18n("Error executing search command '%1'.").arg( cmdString ); emit searchFinished( this, entry, txt ); } } else if ( !mSearchUrl.isEmpty() ) { TQString urlString = SearchEngine::substituteSearchQuery( mSearchUrl, entry->identifier(), words, maxResults, operation, mLang ); kdDebug() << "SearchHandler::search() URL: " << urlString << endl; KIO::TransferJob *job = KIO::get( KURL( urlString ) ); connect( job, TQT_SIGNAL( result( KIO::Job * ) ), TQT_SLOT( slotJobResult( KIO::Job * ) ) ); connect( job, TQT_SIGNAL( data( KIO::Job *, const TQByteArray & ) ), TQT_SLOT( slotJobData( KIO::Job *, const TQByteArray & ) ) ); SearchJob *searchJob = new SearchJob; searchJob->mEntry = entry; searchJob->mKioJob = job; mKioJobs.insert( job, searchJob ); } else { TQString txt = i18n("No search command or URL specified."); emit searchFinished( this, entry, txt ); return; } } void SearchHandler::searchStdout( KProcess *proc, char *buffer, int len ) { if ( !buffer || len == 0 ) return; TQString bufferStr; char *p; p = (char*) malloc( sizeof(char) * ( len + 1 ) ); p = strncpy( p, buffer, len ); p[len] = '\0'; TQMap<KProcess *, SearchJob *>::ConstIterator it = mProcessJobs.find( proc ); if ( it != mProcessJobs.end() ) { (*it)->mResult += bufferStr.fromUtf8( p ); } free( p ); } void SearchHandler::searchStderr( KProcess *proc, char *buffer, int len ) { if ( !buffer || len == 0 ) return; TQMap<KProcess *, SearchJob *>::ConstIterator it = mProcessJobs.find( proc ); if ( it != mProcessJobs.end() ) { (*it)->mError += TQString::fromUtf8( buffer, len ); } } void SearchHandler::searchExited( KProcess *proc ) { // kdDebug() << "SearchHandler::searchExited()" << endl; TQString result; TQString error; DocEntry *entry = 0; TQMap<KProcess *, SearchJob *>::ConstIterator it = mProcessJobs.find( proc ); if ( it != mProcessJobs.end() ) { SearchJob *j = *it; entry = j->mEntry; result = j->mResult; error = "<em>" + j->mCmd + "</em>\n" + j->mError; mProcessJobs.remove( proc ); delete j; } else { kdError() << "No search job for exited process found." << endl; } if ( proc->normalExit() && proc->exitStatus() == 0 ) { emit searchFinished( this, entry, result ); } else { emit searchError( this, entry, error ); } } void SearchHandler::slotJobResult( KIO::Job *job ) { TQString result; DocEntry *entry = 0; TQMap<KIO::Job *, SearchJob *>::ConstIterator it = mKioJobs.find( job ); if ( it != mKioJobs.end() ) { SearchJob *j = *it; entry = j->mEntry; result = j->mResult; mKioJobs.remove( job ); delete j; } if ( job->error() ) { emit searchError( this, entry, i18n("Error: %1").arg( job->errorString() ) ); } else { emit searchFinished( this, entry, result ); } } void SearchHandler::slotJobData( KIO::Job *job, const TQByteArray &data ) { // kdDebug() << "SearchHandler::slotJobData()" << endl; TQMap<KIO::Job *, SearchJob *>::ConstIterator it = mKioJobs.find( job ); if ( it != mKioJobs.end() ) { (*it)->mResult += data.data(); } } #include "searchhandler.moc"