diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 02:13:59 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 02:13:59 +0000 |
commit | a6d58bb6052ac8cb01805a48c4ad2f129126116f (patch) | |
tree | dd867a099fcbb263a8009a9fb22695b87855dad6 /src/modules/http | |
download | kvirc-a6d58bb6052ac8cb01805a48c4ad2f129126116f.tar.gz kvirc-a6d58bb6052ac8cb01805a48c4ad2f129126116f.zip |
Added KDE3 version of kvirc
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kvirc@1095341 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/modules/http')
-rw-r--r-- | src/modules/http/Makefile.am | 26 | ||||
-rw-r--r-- | src/modules/http/httpfiletransfer.cpp | 489 | ||||
-rw-r--r-- | src/modules/http/httpfiletransfer.h | 104 | ||||
-rw-r--r-- | src/modules/http/kvi_httpicons.png | bin | 0 -> 19630 bytes | |||
-rw-r--r-- | src/modules/http/libkvihttp.cpp | 324 |
5 files changed, 943 insertions, 0 deletions
diff --git a/src/modules/http/Makefile.am b/src/modules/http/Makefile.am new file mode 100644 index 00000000..ab7fe3b2 --- /dev/null +++ b/src/modules/http/Makefile.am @@ -0,0 +1,26 @@ +############################################################################### +# KVirc IRC client Makefile - 31.01.2002 Szymon Stefanek <[email protected]> +############################################################################### + +tmpdir=$(picsdir) + +tmp_DATA=kvi_httpicons.png + +EXTRA_DIST=kvi_httpicons.png + +AM_CPPFLAGS = -I$(SS_TOPSRCDIR)/src/kvilib/include/ -I$(SS_TOPSRCDIR)/src/kvirc/include/ \ +$(SS_INCDIRS) $(SS_CPPFLAGS) -DGLOBAL_KVIRC_DIR=\"$(globalkvircdir)\" + +pluglib_LTLIBRARIES = libkvihttp.la + +libkvihttp_la_LDFLAGS = -module -avoid-version $(SS_LDFLAGS) $(SS_LIBDIRS) + +libkvihttp_la_SOURCES = libkvihttp.cpp httpfiletransfer.cpp +libkvihttp_la_LIBADD = $(SS_LIBLINK) ../../kvilib/build/libkvilib.la + +noinst_HEADERS= httpfiletransfer.h + +m_%.moc: %.h + $(SS_QT_MOC) $< -o $@ + +httpfiletransfer.cpp: m_httpfiletransfer.moc diff --git a/src/modules/http/httpfiletransfer.cpp b/src/modules/http/httpfiletransfer.cpp new file mode 100644 index 00000000..09c3b1f9 --- /dev/null +++ b/src/modules/http/httpfiletransfer.cpp @@ -0,0 +1,489 @@ +//================================================================================== +// +// File : httpfiletransfer.h +// Creation date : Tue Apr 22 2003 02:00:12 GMT by Szymon Stefanek +// +// This config is part of the KVirc irc client distribution +// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot net) +// +// 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 opinion) 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 "httpfiletransfer.h" + +#include "kvi_app.h" +#include "kvi_out.h" +#include "kvi_locale.h" +#include "kvi_window.h" +#include "kvi_iconmanager.h" +#include "kvi_netutils.h" +#include "kvi_kvs_eventtriggers.h" +#include "kvi_console.h" + +#include "kvi_kvs_script.h" + +#include "kvi_tal_popupmenu.h" +#include <qpainter.h> + +static KviPointerList<KviHttpFileTransfer> * g_pHttpFileTransfers = 0; +static QPixmap * g_pHttpIcon = 0; + + +KviHttpFileTransfer::KviHttpFileTransfer() +: KviFileTransfer() +{ + init(); // ensure we're initialized + g_pHttpFileTransfers->append(this); + + m_tStartTime = kvi_unixTime(); + m_tTransferStartTime = 0; + m_tTransferEndTime = 0; + + m_bNotifyCompletion = true; + m_bAutoClean = false; + m_pAutoCleanTimer = 0; + m_bNoOutput = false; + + m_pHttpRequest = new KviHttpRequest(); + + connect(m_pHttpRequest,SIGNAL(status(const QString &)),this,SLOT(statusMessage(const QString &))); + connect(m_pHttpRequest,SIGNAL(terminated(bool)),this,SLOT(transferTerminated(bool))); + connect(m_pHttpRequest,SIGNAL(header(KviPointerHashTable<const char *,KviStr> *)),this,SLOT(headersReceived(KviPointerHashTable<const char *,KviStr> *))); + connect(m_pHttpRequest,SIGNAL(resolvingHost(const QString &)),this,SLOT(resolvingHost(const QString &))); + connect(m_pHttpRequest,SIGNAL(requestSent(const QStringList &)),this,SLOT(requestSent(const QStringList &))); + connect(m_pHttpRequest,SIGNAL(contactingHost(const QString &)),this,SLOT(contactingHost(const QString &))); + connect(m_pHttpRequest,SIGNAL(receivedResponse(const QString &)),this,SLOT(receivedResponse(const QString &))); + connect(m_pHttpRequest,SIGNAL(connectionEstabilished()),this,SLOT(connectionEstabilished())); + + m_eGeneralStatus = Initializing; + m_szStatusString = __tr2qs_ctx("Initializing","http"); +} + +KviHttpFileTransfer::~KviHttpFileTransfer() +{ + g_pHttpFileTransfers->removeRef(this); + delete m_pHttpRequest; + if(m_pAutoCleanTimer) + { + m_pAutoCleanTimer->stop(); + delete m_pAutoCleanTimer; + } +} + +void KviHttpFileTransfer::autoClean() +{ + die(); +} + +void KviHttpFileTransfer::die() +{ + delete this; +} + +QString KviHttpFileTransfer::localFileName() +{ + return m_pHttpRequest->fileName(); +} + +void KviHttpFileTransfer::abort() +{ + m_pHttpRequest->abort(); +} + +void KviHttpFileTransfer::fillContextPopup(KviTalPopupMenu * m,int column) +{ + int id = m->insertItem(__tr2qs_ctx("Abort","http"),this,SLOT(abort())); + if(!active())m->setItemEnabled(id,false); +} + +bool KviHttpFileTransfer::active() +{ + return ((m_eGeneralStatus == Connecting) || (m_eGeneralStatus == Downloading)); +} + +void KviHttpFileTransfer::displayPaint(QPainter * p,int column,int width,int height) +{ + QString txt; + bool bIsTerminated = ((m_eGeneralStatus == Success) || (m_eGeneralStatus == Failure)); + + switch(column) + { + case COLUMN_TRANSFERTYPE: + { + int offset = 0; + switch(m_eGeneralStatus) + { + case Initializing: offset = 0; break; + case Connecting: offset = 0; break; + case Downloading: offset = 48; break; + case Success: offset = 96; break; + case Failure: offset = 144; break; + } + p->drawPixmap(3,3,*g_pHttpIcon,offset,0,48,64); + } + break; + case COLUMN_FILEINFO: + { + QFontMetrics fm(p->font()); + + QString szFrom = __tr2qs_ctx("From: ","http"); + QString szTo = __tr2qs_ctx("To: ","http"); + + int daW1 = fm.width(szFrom); + int daW2 = fm.width(szTo); + if(daW1 < daW2)daW1 = daW2; + int iLineSpacing = fm.lineSpacing(); + + p->setPen(Qt::black); + + int iY = 4; + + p->drawText(4 + daW1,iY,width - (8 + daW1),height - 8,Qt::AlignTop | Qt::AlignLeft,m_pHttpRequest->url().url().ptr()); + iY += iLineSpacing; + if(!(m_pHttpRequest->fileName().isEmpty())) + { + p->drawText(4 + daW1,iY,width - (8 + daW1),height - 8,Qt::AlignTop | Qt::AlignLeft,m_pHttpRequest->fileName()); + } + iY += iLineSpacing; + + + p->setPen(Qt::darkGray); + + p->drawText(4,4,width - 8,height - 8,Qt::AlignTop | Qt::AlignLeft,szFrom); + p->drawText(4,4 + iLineSpacing,width - 8,height - 8,Qt::AlignTop | Qt::AlignLeft,szTo); + + p->setPen(QColor(180,180,200)); + + iLineSpacing += 2; + + p->drawRect(4,height - (iLineSpacing + 4),width - 8,iLineSpacing); + p->fillRect(5,height - (iLineSpacing + 3),width - 10,iLineSpacing - 2,bIsTerminated ? QColor(210,210,210) : QColor(190,190,240)); + p->setPen(Qt::black); + p->drawText(7,height - (iLineSpacing + 4),width - 14,iLineSpacing,Qt::AlignVCenter | Qt::AlignLeft,m_szStatusString); + } + break; + case COLUMN_PROGRESS: + { + QFontMetrics fm(p->font()); + + unsigned int uTotal = m_pHttpRequest->totalSize(); + unsigned int uRecvd = m_pHttpRequest->receivedSize(); + int iW = width - 8; + + p->setPen(bIsTerminated ? Qt::lightGray : QColor(210,210,240)); + p->drawRect(4,4,iW,12); + + int iAvgSpeed = -1; + int iEta = -1; + + if(m_tTransferStartTime > 0) + { + int tSpan = kvi_timeSpan(m_tTransferEndTime > 0 ? m_tTransferEndTime : kvi_unixTime(),m_tTransferStartTime); + if(tSpan > 0) + { + //debug("SPAN: %d (%d - %d)",tSpan,m_tTransferEndTime > 0 ? m_tTransferEndTime : kvi_unixTime(),m_tTransferStartTime); + iAvgSpeed = uRecvd / tSpan; + if(!bIsTerminated && (uTotal >= uRecvd)) + { + unsigned int uRemaining = uTotal - uRecvd; + iEta = uRemaining / iAvgSpeed; + } + } + } + + if(uTotal > 0) + { + double dPerc = (double)(((double)uRecvd) * 100.0) / (double)uTotal; + iW -= 2; + int iL = (int) ((((double)iW) * dPerc) / 100.0); + //iR = iW - iL; + p->fillRect(5,5,iL,10,bIsTerminated ? QColor(140,110,110) : QColor(200,100,100)); + + txt = QString(__tr2qs_ctx("%1 of %2 (%3 %)","http")).arg(KviQString::makeSizeReadable(uRecvd)) + .arg(KviQString::makeSizeReadable(uTotal)).arg(dPerc,0,'f',2); + } else { + txt = KviQString::makeSizeReadable(m_pHttpRequest->receivedSize()); + } + + p->setPen(Qt::black); + + p->drawText(4,19,width - 8,height - 8,Qt::AlignTop | Qt::AlignLeft,txt); + + int iLeftHalf = (iW - 2) / 2; + int iRightHalf = iW - (iLeftHalf + 1); + int iLineSpacing = fm.lineSpacing() + 2; + + /* + txt = __tr2qs_ctx("Spd:","dcc"); + txt += " "; + if(iInstantSpeed >= 0) + { + QString tmpisp; + KviNetUtils::formatNetworkBandwidthString(tmpisp,iAvgSpeed); + txt += tmpisp; + } else { + txt += "? B/s"; + } + */ + + txt = __tr2qs_ctx("Avg:","dcc"); + txt += " "; + if(iAvgSpeed >= 0) + { + QString tmpspd; + KviNetUtils::formatNetworkBandwidthString(tmpspd,iAvgSpeed); + txt += tmpspd; + } else { + txt += "? B/s"; + } + + + + int iDaH = height - (iLineSpacing + 4); + + p->setPen(QColor(180,180,200)); + p->drawRect(4,iDaH,iLeftHalf,iLineSpacing); + p->fillRect(5,iDaH + 1,iLeftHalf - 2,iLineSpacing - 2,bIsTerminated ? QColor(210,210,210) : QColor(190,190,240)); + p->setPen(bIsTerminated ? Qt::darkGray : Qt::black); + p->drawText(6,iDaH,iLeftHalf - 4,iLineSpacing,Qt::AlignLeft | Qt::AlignVCenter,txt); + + unsigned int uD,uH,uM,uS; + + if(bIsTerminated) + { + KviTimeUtils::secondsToDaysHoursMinsSecs(kvi_timeSpan(m_tTransferEndTime,m_tTransferStartTime),&uD,&uH,&uM,&uS); + txt = "TOT: "; + if(uD > 0)txt += QString(__tr2qs_ctx("%1d %2h %3m %4s","http")).arg(uD).arg(uH).arg(uM).arg(uS); + else if(uH > 0)txt += QString(__tr2qs_ctx("%2h %3m %4s","http")).arg(uH).arg(uM).arg(uS); + else txt += QString(__tr2qs_ctx("%3m %4s","http")).arg(uM).arg(uS); + } else { + if(iEta >= 0) + { + KviTimeUtils::secondsToDaysHoursMinsSecs(iEta,&uD,&uH,&uM,&uS); + txt = "ETA: "; + if(uD > 0)txt += QString(__tr2qs_ctx("%1d %2h %3m %4s","http")).arg(uD).arg(uH).arg(uM).arg(uS); + else if(uH > 0)txt += QString(__tr2qs_ctx("%2h %3m %4s","http")).arg(uH).arg(uM).arg(uS); + else txt += QString(__tr2qs_ctx("%3m %4s","http")).arg(uM).arg(uS); + } else { + txt = "ETA: Unknown"; + } + } + + p->setPen(QColor(180,180,200)); + p->drawRect(width - (4 + iRightHalf),iDaH,iRightHalf,iLineSpacing); + p->fillRect(width - (3 + iRightHalf),iDaH + 1,iRightHalf - 2,iLineSpacing - 2,bIsTerminated ? QColor(210,210,210) : QColor(190,190,240)); + p->setPen(bIsTerminated ? Qt::darkGray : Qt::black); + p->drawText(width - (2 + iRightHalf),iDaH,iRightHalf - 4,iLineSpacing,Qt::AlignLeft | Qt::AlignVCenter,txt); + + } + break; + } +} + +int KviHttpFileTransfer::displayHeight(int iLineSpacing) +{ + int iH = (iLineSpacing * 3) + 10; + return iH >= 70 ? iH : 70; +} + +QString KviHttpFileTransfer::tipText() +{ + QString s; + s = QString("<table><tr><td bgcolor=\"#000000\"><font color=\"#FFFFFF\"><b>HTTP Transfer (ID %1)</b></font></td></tr>").arg(id()); + + if(m_lRequest.count() > 0) + { + s += "<tr><td bgcolor=\"#404040\"><font color=\"#FFFFFF\">Request Headers</font></td></tr>"; + s += "<tr><td bgcolor=\"#C0C0C0\">"; + for(QStringList::ConstIterator it = m_lRequest.begin();it != m_lRequest.end();++it) + { + s += " "; + s += *it; + s += "<br>"; + } + s += "</td></tr>"; + } + + if(m_lHeaders.count() > 0) + { + s += "<tr><td bgcolor=\"#404040\"><font color=\"#FFFFFF\">Response Headers</font></td></tr>"; + s += "<tr><td bgcolor=\"#C0C0C0\">"; + for(QStringList::ConstIterator it = m_lHeaders.begin();it != m_lHeaders.end();++it) + { + s += " "; + s += *it; + s += "<br>"; + } + s += "</td></tr>"; + } + + s += "<table>"; + + return s; +} + +void KviHttpFileTransfer::init() +{ + if(g_pHttpFileTransfers)return; + g_pHttpFileTransfers = new KviPointerList<KviHttpFileTransfer>; + g_pHttpFileTransfers->setAutoDelete(false); + + QPixmap * pix = g_pIconManager->getImage("kvi_httpicons.png"); + if(pix)g_pHttpIcon = new QPixmap(*pix); + else g_pHttpIcon = new QPixmap(192,48); +} + +void KviHttpFileTransfer::done() +{ + if(!g_pHttpFileTransfers)return; + while(KviHttpFileTransfer * t = g_pHttpFileTransfers->first()) + delete t; + delete g_pHttpFileTransfers; + g_pHttpFileTransfers = 0; + delete g_pHttpIcon; + g_pHttpIcon = 0; +} + +unsigned int KviHttpFileTransfer::runningTransfers() +{ + if(!g_pHttpFileTransfers)return 0; + return g_pHttpFileTransfers->count(); +} + +void KviHttpFileTransfer::requestSent(const QStringList &requestHeaders) +{ + m_szStatusString = __tr2qs_ctx("Request sent, waiting for reply...","http"); + displayUpdate(); + + KviWindow * out = transferWindow(); + if(!out)return; + + if(!m_bNoOutput) + out->output(KVI_OUT_GENERICSTATUS,__tr2qs_ctx("[HTTP %d]: Request data sent:","http"),id()); + + for(QStringList::ConstIterator it = requestHeaders.begin();it != requestHeaders.end();++it) + { + if(!m_bNoOutput) + out->output(KVI_OUT_GENERICSTATUS,"[HTTP %d]: %s",id(),(*it).utf8().data()); + } + + m_lRequest = requestHeaders; +} + +void KviHttpFileTransfer::connectionEstabilished() +{ + m_szStatusString = __tr2qs_ctx("Connection established, sending request","http"); + displayUpdate(); +} + +void KviHttpFileTransfer::resolvingHost(const QString &hostname) +{ + m_szStatusString = __tr2qs_ctx("Resolving host %1","http").arg(hostname); + displayUpdate(); +} + +void KviHttpFileTransfer::contactingHost(const QString &ipandport) +{ + m_szStatusString = __tr2qs_ctx("Contacting host %1","http").arg(ipandport); + displayUpdate(); +} + +void KviHttpFileTransfer::receivedResponse(const QString &response) +{ + m_lHeaders.clear(); + m_lHeaders.append(response); + m_szStatusString = __tr2qs_ctx("Transferring data (%1)","http").arg(response); + m_tTransferStartTime = kvi_unixTime(); + m_eGeneralStatus = Downloading; + displayUpdate(); +} + +void KviHttpFileTransfer::statusMessage(const QString &txt) +{ + KviWindow * out = transferWindow(); + if(out && (!m_bNoOutput)) + out->output(KVI_OUT_GENERICSTATUS,"[HTTP %d]: %Q",id(),&txt); +} + +void KviHttpFileTransfer::transferTerminated(bool bSuccess) +{ + KviWindow * out = transferWindow(); + + m_tTransferEndTime = kvi_unixTime(); + + KviKvsVariantList vParams; + vParams.append(new KviKvsVariant(bSuccess)); + vParams.append(new KviKvsVariant(m_pHttpRequest->url().url())); + vParams.append(new KviKvsVariant(m_pHttpRequest->fileName())); + vParams.append(new KviKvsVariant(m_vMagicIdentifier)); + + if(m_szCompletionCallback.isNull()) + { + KVS_TRIGGER_EVENT(KviEvent_OnHTTPGetTerminated,out ? out : (KviWindow *)(g_pApp->activeConsole()),&vParams) + } else { + KviKvsScript::run(m_szCompletionCallback,out ? out : (KviWindow *)(g_pApp->activeConsole()),&vParams); + } + + if(bSuccess) + { + m_szStatusString = __tr2qs_ctx("Transfer completed","http"); + m_eGeneralStatus = Success; + displayUpdate(); + if(out && (!m_bNoOutput))out->output(KVI_OUT_GENERICSUCCESS,__tr2qs_ctx("[HTTP %d]: Transfer completed","http"),id()); + g_pApp->fileDownloadTerminated(true,m_pHttpRequest->url().url().ptr(),m_pHttpRequest->fileName(),QString::null,QString::null,!m_bNotifyCompletion); + } else { + m_szStatusString = __tr2qs_ctx("Transfer failed","http"); + m_szStatusString += ": "; + m_szStatusString += m_pHttpRequest->lastError(); + m_eGeneralStatus = Failure; + displayUpdate(); + if(out && (!m_bNoOutput))out->output(KVI_OUT_GENERICERROR,__tr2qs_ctx("[HTTP %d]: Transfer failed: %Q","http"),id(),&(m_pHttpRequest->lastError())); + g_pApp->fileDownloadTerminated(false,m_pHttpRequest->url().url().ptr(),m_pHttpRequest->fileName(),QString::null,m_pHttpRequest->lastError(),!m_bNotifyCompletion); + } + + if(m_bAutoClean) + { + if(m_pAutoCleanTimer)delete m_pAutoCleanTimer; + m_pAutoCleanTimer = new QTimer(); + connect(m_pAutoCleanTimer,SIGNAL(timeout()),this,SLOT(autoClean())); + m_pAutoCleanTimer->start(100,true); + } +} + +void KviHttpFileTransfer::headersReceived(KviPointerHashTable<const char *,KviStr> *h) +{ + if(!h)return; + KviWindow * out = transferWindow(); + + if(out && (!m_bNoOutput))out->output(KVI_OUT_GENERICSTATUS,__tr2qs_ctx("[HTTP %d]: Response headers:","http"),id()); + KviPointerHashTableIterator<const char *,KviStr> it(*h); + while(KviStr * s = it.current()) + { + QString szHeader = it.currentKey(); + szHeader += ": "; + szHeader += s->ptr(); + m_lHeaders.append(szHeader); + if(out && (!m_bNoOutput))out->output(KVI_OUT_GENERICSTATUS,"[HTTP %d]: %s: %s",id(),it.currentKey(),s->ptr()); + ++it; + } +} + +bool KviHttpFileTransfer::startDownload() +{ + m_eGeneralStatus = Connecting; + return m_pHttpRequest->start(); +} + +#include "m_httpfiletransfer.moc" diff --git a/src/modules/http/httpfiletransfer.h b/src/modules/http/httpfiletransfer.h new file mode 100644 index 00000000..e6c5006e --- /dev/null +++ b/src/modules/http/httpfiletransfer.h @@ -0,0 +1,104 @@ +#ifndef _HTTPFILETRANSFER_H_ +#define _HTTPFILETRANSFER_H_ +//================================================================================== +// +// File : httpfiletransfer.h +// Creation date : Tue Apr 22 2003 02:00:12 GMT by Szymon Stefanek +// +// This config is part of the KVirc irc client distribution +// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot net) +// +// 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 opinion) 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 "kvi_filetransfer.h" +#include "kvi_http.h" +#include "kvi_time.h" + +#include "kvi_kvs_variant.h" + +#include <qstringlist.h> +#include <qtimer.h> + +class QPainter; +class KviTalPopupMenu; + +class KviHttpFileTransfer : public KviFileTransfer +{ + enum GeneralStatus { Initializing, Connecting, Downloading, Success, Failure }; + Q_OBJECT +public: + KviHttpFileTransfer(); + ~KviHttpFileTransfer(); +private: + KviHttpRequest * m_pHttpRequest; + GeneralStatus m_eGeneralStatus; + QString m_szStatusString; + + QStringList m_lHeaders; + QStringList m_lRequest; + + kvi_time_t m_tStartTime; + kvi_time_t m_tTransferStartTime; + kvi_time_t m_tTransferEndTime; + + KviKvsVariant m_vMagicIdentifier; + bool m_bNotifyCompletion; + bool m_bAutoClean; + bool m_bNoOutput; + + QTimer * m_pAutoCleanTimer; + + QString m_szCompletionCallback; +public: + KviHttpRequest * request(){ return m_pHttpRequest; }; + static unsigned int runningTransfers(); + static void init(); + static void done(); + + virtual bool startDownload(); + + void setCompletionCallback(const QString &szCallback){ m_szCompletionCallback = szCallback; }; + void setMagicIdentifier(const KviKvsVariant &vIdentifier){ m_vMagicIdentifier = vIdentifier; }; + void setNotifyCompletion(bool bNotify){ m_bNotifyCompletion = bNotify; }; + void setAutoClean(bool bAutoClean){ m_bAutoClean = bAutoClean; }; + void setNoOutput(bool bNoOutput){ m_bNoOutput = bNoOutput; }; + + virtual void displayPaint(QPainter * p,int column,int width,int height); + virtual int displayHeight(int iLineSpacing); + virtual void fillContextPopup(KviTalPopupMenu * m,int column); + virtual bool active(); + virtual void die(); + virtual QString tipText(); + virtual QString localFileName(); +protected slots: + void statusMessage(const QString &txt); + void transferTerminated(bool bSuccess); + void headersReceived(KviPointerHashTable<const char *,KviStr> *h); + void requestSent(const QStringList &sl); + + void resolvingHost(const QString &hostname); + void contactingHost(const QString &ipandport); + void receivedResponse(const QString &response); + void connectionEstabilished(); + + void abort(); + + void autoClean(); +}; + + +#endif //!_HTTPFILETRANSFER_H_ diff --git a/src/modules/http/kvi_httpicons.png b/src/modules/http/kvi_httpicons.png Binary files differnew file mode 100644 index 00000000..30776c0f --- /dev/null +++ b/src/modules/http/kvi_httpicons.png diff --git a/src/modules/http/libkvihttp.cpp b/src/modules/http/libkvihttp.cpp new file mode 100644 index 00000000..eb6f28fb --- /dev/null +++ b/src/modules/http/libkvihttp.cpp @@ -0,0 +1,324 @@ +//================================================================================== +// +// File : libkvihttp.cpp +// Creation date : Tue Apr 22 2003 02:00:12 GMT by Szymon Stefanek +// +// This config is part of the KVirc irc client distribution +// Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot net) +// +// 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 opinion) 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 "kvi_module.h" +#include "kvi_string.h" + + +#include "kvi_app.h" +#include "kvi_locale.h" +#include "kvi_filedialog.h" +#include "kvi_window.h" +#include "kvi_error.h" +#include "kvi_cmdformatter.h" + +#include "httpfiletransfer.h" + + +static bool http_kvs_complete_get(KviKvsModuleCommandCall * c,QString &szUrl,QString &szFileName,const QString &szCallback) +{ + if(szUrl.isEmpty()) + { + c->warning(__tr2qs_ctx("No url specified","http")); + return true; + } + + KviUrl url(szUrl); + + QString tmp; + + if(szFileName.isEmpty()) + { + if(c->switches()->find('a',"auto-file-name")) + { + tmp = szUrl; + tmp.replace('/',"_"); + tmp.replace(':',"_"); + tmp.replace('@',"_"); + tmp.replace('?',"_"); + // http____path_path2_path3_filename.ext + g_pApp->getLocalKvircDirectory(szFileName,KviApp::Incoming,tmp); + } else { + if(!KviFileDialog::askForSaveFileName(szFileName,__tr2qs_ctx("Choose a save file name","http"))) + return true; + if(szFileName.isEmpty())return true; + } + } + + KviHttpFileTransfer * hft = new KviHttpFileTransfer(); + + bool bHead = c->switches()->find('h',"head"); + + if(c->switches()->getAsStringIfExisting('p',"post-data",tmp)) + { + if(bHead) + { + c->warning(__tr2qs_ctx("The switch -p is incompatible with -h: -p takes precedence","http")); + bHead = false; + } + hft->request()->setPostData(tmp); + } + + hft->request()->setUrl(url); + hft->request()->setProcessingType(bHead ? KviHttpRequest::HeadersOnly : KviHttpRequest::StoreToFile); + hft->request()->setFileName(szFileName); + + if(c->switches()->getAsStringIfExisting('e',"existing-file-action",tmp)) + { + if(KviQString::equalCI(tmp,"e")) + hft->request()->setExistingFileAction(KviHttpRequest::RenameExisting); + else if(KviQString::equalCI(tmp,"i")) + hft->request()->setExistingFileAction(KviHttpRequest::RenameIncoming); + else if(KviQString::equalCI(tmp,"o")) + hft->request()->setExistingFileAction(KviHttpRequest::Overwrite); + else if(KviQString::equalCI(tmp,"r")) + hft->request()->setExistingFileAction(KviHttpRequest::Resume); + } + + // FIXME: this should be numeric + if(c->switches()->getAsStringIfExisting('m',"max-len",tmp)) + { + bool bOk; + unsigned int uContentLength = tmp.toUInt(&bOk); + if(bOk)hft->request()->setMaxContentLength(uContentLength); + } + + // FIXME: this should be numeric + if(c->switches()->getAsStringIfExisting('o',"offset",tmp)) + { + bool bOk; + unsigned int uContentOffset = tmp.toUInt(&bOk); + if(bOk)hft->request()->setContentOffset(uContentOffset); + } + + if(c->switches()->getAsStringIfExisting('w',"winctrl",tmp)) + { + if(!tmp.contains('h'))hft->invokeTransferWindow(c->window(),tmp.contains('m'),tmp.contains('n')); + } else { + hft->invokeTransferWindow(c->window(),false,false); + } + + KviKvsVariant * v = c->switches()->find('i',"identifier"); + if(v) + hft->setMagicIdentifier(*v); + + if(c->switches()->find('q',"quiet")) + hft->setNotifyCompletion(false); + + if(c->switches()->find('y',"no-output")) + hft->setNoOutput(true); + + if(!szCallback.isEmpty()) + hft->setCompletionCallback(szCallback); + + if(c->switches()->find('c',"clear")) + hft->setAutoClean(true); + + if(!hft->startDownload()) + { + tmp = hft->request()->lastError(); + c->warning(__tr2qs_ctx("Failed to start the get request: %Q","http"),&tmp); + delete hft; + } + + return true; +} + + +/* + @doc: http.get + @type: + command + @title: + http.get + @keyterms: + HTTP extension + @short: + Retrieves a file via HTTP GET + @syntax: + http.get [switches] <http_url> [save_file_name] + @description: + Attempts to download the file at <http_url> by using the HTTP GET or POST protocol.[br] + If [save_file_name] is specified, then is is used as save file name, otherwise + a save file dialog is displayed (unless -a is used).[br] + The event OnHTTPGetTerminated is triggered upon the download completion (both + in case of success or failure). If you want a callback command to be triggered + instead please use [cmd]http.asyncGet[/cmd]. + If the url contains a https:// prefix then a SSL connection will be used. + @switches: + !sw: -a=<auto_file_name> | --auto-file-name=<auto_file_name> + Don't show the savefile dialog but determine automatically a file name. + The file is put in the KVIrc incoming directory and the file name + is the processed url.[br] + + !sw: -e=<existing_file_action> | --existing-file-action=<existing_file_action> + Specifies the action to be taken when the local file already exists.[br] + The action can be one of "i","e","o" or "r".[br] + "i" causes the incoming file to be automatically renamed by appending a + non colliding suffix. "e" causes the existing file to be renamed + by appending a non colliding suffix (the incoming file will then have its name preserved). + "o" causes the existing file to be overwritten and "r" will attempt to resume + a interrupted transfer.[br] + The default is to rename the incoming file.[br] + + !sw: -m=<max_content_length> | --max-len=<max_content_length> + Causes content longer than <max_content_length> to be discarded.[br] + This is mainly to prevent you from automatically downloading 300 MB files + and to prevent DOS attacks from malicious servers that do not report the Content-length header.[br] + If the Content-length header is reported by the server then the transfer is aborted + if the length exceedes <max_content_length>.[br] + If the Content-length header is missing then the transfer is interrupted when + the received data length exceeds <max_content_length>.[br] + -m=0 means "accept any content length" (which is the default).[br] + + !sw: -o=<content_offset> | --offset=<content_offset> + Causes the download to start from position <content offset>.[br] + This can be used to download only a part of the file starting at byte <content_offset>.[br] + <content_offset> is used regardless if the file is resumed or not. + Please note that you don't need to specify the content offset when using + -e=r : the offset is automatically calculated. If you specify both -o=<content_offset> + and -e=r then the file will be resumed, the transfer will start at the specified offset + and the received stream will be appended to the existing file.(avoid it unless you know what you're doing: + it's easy to download broken files).[br] + + !sw: -h | --head + Causes the connection to use the HTTP HEAD method that effectively + does not transfer real data. The server sends only the response headers. + This might be used in conjunction with the -v option to print the headers to the + active window.[br] + + !sw: -w=<flags> | --winctrl + This switch controls the creation and visualization of the transfer window. + <flags> can be any combination of 'm','n' and 'h'. + The flag 'h' causes the window to not be created. The transfer will simply run in background. + Note that with 'h' the user has no possibility to interact with the transfer. + The flag 'm' causes the transfer window to be created as "minimized". 'm' does nothing + if the window alread exists. The flag 'n' causes the window to be NOT activated (brought to top). + + !sw: -i=<magic identifier> | --identifier=<magic identifier> + This identifier is passed as $3 parameter to the [event]OnHTTPGetTerminated[/event] + when this transfer terminates. If this switch is not present then an empty string is used. + With [cmd]http.asyngGet[/cmd] this parameter is passed to the callback command instead. + + !sw: -p=<post data> | --post-data=<post data> + The request is sent in form of a POST request. <post data> is the urlencoded payload of + the request. -p is incompatible with -h. + + !sw: -q | --quiet + Do not notify download completion in the notifier window nor in the console. + + !sw: -y | --no-output + Supress any output in the file transfer window. This will effectively disable + the file transfer window highlighting (so the user will not be alerted by a failed + download unless he's really watching the window). This is useful when you're notifying + failures in some other way... + + !sw: -c | --clear + Automatically remove the transfer from the transfer list when terminated + @seealso: + [cmd]http.asyncGet[/cmd] +*/ + +static bool http_kvs_cmd_get(KviKvsModuleCommandCall * c) +{ + QString szUrl,szFileName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("url",KVS_PT_NONEMPTYSTRING,0,szUrl) + KVSM_PARAMETER("filename",KVS_PT_STRING,KVS_PF_OPTIONAL,szFileName) + KVSM_PARAMETERS_END(c) + + return http_kvs_complete_get(c,szUrl,szFileName,QString::null); +} +/* + @doc: http.asyncGet + @type: + command + @title: + http.asyncGet + @keyterms: + HTTP extension + @short: + Retrieves a file via HTTP GET and triggers a callback + @syntax: + http.asyncGet [switches] (<http_url> [,save_file_name]) + { + <callback command> + } + @description: + Attempts to download the file at <http_url> by using the HTTP GET or POST protocol.[br] + If [save_file_name] is specified, then is is used as save file name, otherwise + a save file dialog is displayed (unless -a is used).[br] + This command is really similar to [cmd]http.get[/cmd]: it has exactly the same + parameters and switches (so also refer to its documentation). + The only difference is that asyncGet triggers the <callback command> upon completion + instead of the global OnHTTPGetTerminated event. + The parameters passed to the callback are exactly the same. + If the url contains a https:// prefix then a SSL connection will be used. + @seealso: + [cmd]http.get[/cmd] +*/ + +static bool http_kvs_cmd_asyncGet(KviKvsModuleCallbackCommandCall * c) +{ + QString szUrl,szFileName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("url",KVS_PT_NONEMPTYSTRING,0,szUrl) + KVSM_PARAMETER("filename",KVS_PT_STRING,KVS_PF_OPTIONAL,szFileName) + KVSM_PARAMETERS_END(c) + + return http_kvs_complete_get(c,szUrl,szFileName,c->callback()->code()); +} + + +static bool http_module_init(KviModule * m) +{ + KviHttpFileTransfer::init(); + + KVSM_REGISTER_SIMPLE_COMMAND(m,"get",http_kvs_cmd_get); + KVSM_REGISTER_CALLBACK_COMMAND(m,"asyncGet",http_kvs_cmd_asyncGet); + + return true; +} + +static bool http_module_cleanup(KviModule *m) +{ + KviHttpFileTransfer::done(); + return true; +} + +static bool http_module_can_unload(KviModule *m) +{ + return (KviHttpFileTransfer::runningTransfers() == 0); +} + +KVIRC_MODULE( + "Http", // module name + "1.0.0", // module version + "Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot net)", // author & (C) + "HTTP interface for KVIrc", + http_module_init, + http_module_can_unload, + 0, + http_module_cleanup +) |