/* * loader.cpp * * Copyright (c) 2001, 2002, 2003, 2004 Frerich Raabe * * 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. For licensing and distribution details, check the * accompanying file 'COPYING'. */ #include "loader.h" #include "document.h" #include #include #include #include #include #include using namespace RSS; DataRetriever::DataRetriever() { } DataRetriever::~DataRetriever() { } struct FileRetriever::Private { Private() : buffer(NULL), lastError(0) { } ~Private() { delete buffer; } TQBuffer *buffer; int lastError; }; FileRetriever::FileRetriever() : d(new Private) { } FileRetriever::~FileRetriever() { delete d; } void FileRetriever::retrieveData(const KURL &url) { if (d->buffer) return; d->buffer = new TQBuffer; d->buffer->open(IO_WriteOnly); TDEIO::Job *job = TDEIO::get(url, false, false); connect(job, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)), TQ_SLOT(slotData(TDEIO::Job *, const TQByteArray &))); connect(job, TQ_SIGNAL(result(TDEIO::Job *)), TQ_SLOT(slotResult(TDEIO::Job *))); connect(job, TQ_SIGNAL(permanentRedirection(TDEIO::Job *, const KURL &, const KURL &)), TQ_SLOT(slotPermanentRedirection(TDEIO::Job *, const KURL &, const KURL &))); } int FileRetriever::errorCode() const { return d->lastError; } void FileRetriever::slotData(TDEIO::Job *, const TQByteArray &data) { d->buffer->writeBlock(data.data(), data.size()); } void FileRetriever::slotResult(TDEIO::Job *job) { TQByteArray data = d->buffer->buffer(); data.detach(); delete d->buffer; d->buffer = NULL; d->lastError = job->error(); emit dataRetrieved(data, d->lastError == 0); } void FileRetriever::slotPermanentRedirection(TDEIO::Job *, const KURL &, const KURL &newUrl) { emit permanentRedirection(newUrl); } struct OutputRetriever::Private { Private() : process(NULL), buffer(NULL), lastError(0) { } ~Private() { delete process; delete buffer; } KShellProcess *process; TQBuffer *buffer; int lastError; }; OutputRetriever::OutputRetriever() : d(new Private) { } OutputRetriever::~OutputRetriever() { delete d; } void OutputRetriever::retrieveData(const KURL &url) { // Ignore subsequent calls if we didn't finish the previous job yet. if (d->buffer || d->process) return; d->buffer = new TQBuffer; d->buffer->open(IO_WriteOnly); d->process = new KShellProcess(); connect(d->process, TQ_SIGNAL(processExited(TDEProcess *)), TQ_SLOT(slotExited(TDEProcess *))); connect(d->process, TQ_SIGNAL(receivedStdout(TDEProcess *, char *, int)), TQ_SLOT(slotOutput(TDEProcess *, char *, int))); *d->process << url.path(); d->process->start(TDEProcess::NotifyOnExit, TDEProcess::Stdout); } int OutputRetriever::errorCode() const { return d->lastError; } void OutputRetriever::slotOutput(TDEProcess *, char *data, int length) { d->buffer->writeBlock(data, length); } void OutputRetriever::slotExited(TDEProcess *p) { if (!p->normalExit()) d->lastError = p->exitStatus(); TQByteArray data = d->buffer->buffer(); data.detach(); delete d->buffer; d->buffer = NULL; delete d->process; d->process = NULL; emit dataRetrieved(data, p->normalExit() && p->exitStatus() == 0); } struct Loader::Private { Private() : retriever(NULL), lastError(0) { } ~Private() { delete retriever; } DataRetriever *retriever; int lastError; }; Loader *Loader::create() { return new Loader; } Loader *Loader::create(TQObject *object, const char *slot) { Loader *loader = create(); connect(loader, TQ_SIGNAL(loadingComplete(Loader *, Document, Status)), object, slot); return loader; } Loader::Loader() : d(new Private) { } Loader::~Loader() { delete d; } void Loader::loadFrom(const KURL &url, DataRetriever *retriever) { if (d->retriever != NULL) return; d->retriever = retriever; connect(d->retriever, TQ_SIGNAL(dataRetrieved(const TQByteArray &, bool)), this, TQ_SLOT(slotRetrieverDone(const TQByteArray &, bool))); d->retriever->retrieveData(url); } int Loader::errorCode() const { return d->lastError; } void Loader::slotRetrieverDone(const TQByteArray &data, bool success) { d->lastError = d->retriever->errorCode(); delete d->retriever; d->retriever = NULL; Document rssDoc; Status status = Success; if (success) { TQDomDocument doc; /* Some servers insert whitespace before the declaration. * TQDom doesn't tolerate that (and it's right, that's invalid XML), * so we strip that. */ const char *charData = data.data(); int len = data.count(); while (len && TQChar(*charData).isSpace()) { --len; ++charData; } /* It seems that some Microsoft-developed code generates UTF-8 files * with the three leading unicode characters 0357, 0273, 0277. For * an example, check http://msdn.microsoft.com/rss.xml */ if (len > 3 && TQChar(*charData) == TQChar(0357)) { len -= 3; charData += 3; } TQByteArray tmpData; tmpData.setRawData(charData, len); if (doc.setContent(tmpData)) rssDoc = Document(doc); else status = ParseError; tmpData.resetRawData(charData, len); } else status = RetrieveError; emit loadingComplete(this, rssDoc, status); delete this; } #include "loader.moc"