[prev in list] [next in list] [prev in thread] [next in thread]
List: kfm-devel
Subject: Re: HTTPPostJob
From: "Dawit A." <adawit () kde ! org>
Date: 2003-02-14 2:26:30
[Download RAW message or body]
Hello,
Okay. Here is the class. It is only a rough draft and meant to get ideas on
how to improve it. It is going to require the end applications provide a
pointer to a QIODevice.
Regards,
Dawit A.
["postjob.cpp" (text/x-c++src)]
#define KIO_DEFAULT_BLOCK_SIZE 1024*256
PostJob::PostJob (const KURL& url, int command, const QByteArray& packedArgs,
QIODevice * source, bool showProgressInfo)
:TransferJob (url, command, packedArgs, QByteArray(), showProgressInfo),
_bytesSent(0), _blockSize (KIO_DEFAULT_BLOCK_SIZE),
_autoDeleteSource (false), _dataSource(source)
{
}
PostJob::PostJob (const KURL& url, int command, const QByteArray& packedArgs,
const QByteArray& data, bool showProgressInfo)
:TransferJob (url, command, packedArgs, QByteArray(), showProgressInfo),
_bytesSent(0), _blockSize (KIO_DEFAULT_BLOCK_SIZE),
_autoDeleteSource (true)
{
// If the data is larger than the default block size use a temp file
// to save the data and send it in segments to the io-slave. Otherwise,
// simply use a QBuffer to store and transmit the data...
if (data.size() < KIO_DEFAULT_BLOCK_SIZE)
{
_dataSource = new QBuffer (data);
}
else
{
KTempFile temp (QString::null, QString::null, 0600);
temp.close ();
_tempfile = temp.name ();
_dataSource = new QFile (_tempfile);
if (_dataSource->open (IO_WriteOnly))
{
KIO::filesize_t offset = 0;
KIO::filesize_t segment;
while (offset < data.size())
{
segment = (data.size () < _blockSize) ? data.size ():_blockSize;
_dataSource->writeBlock (data.data() + offset, segment);
offset += segment;
}
// Close it to force a flush. It will be re-opened when
// start is invoked...
_dataSource->close();
}
}
}
PostJob::~PostJob ()
{
if (_autoDeleteSource && _dataSource)
{
kdDebug(7007) << "PostJob dtor: Deleting pointer to data source" << endl;
_dataSource->close ();
delete _dataSource;
_dataSource = 0;
}
// Unlink the tempfile if it exists.
if (!_tempfile.isEmpty())
QFile::remove (_tempfile);
}
bool PostJob::isPortSafe()
{
bool valid = true;
// filter out non https? protocols
if ((m_url.protocol() != "http") && (m_url.protocol() != "https" ))
valid = false;
// filter out some malicious ports
static const int bad_ports[] =
{
1, // tcpmux
7, // echo
9, // discard
11, // systat
13, // daytime
15, // netstat
17, // qotd
19, // chargen
20, // ftp-data
21, // ftp-cntl
22, // ssh
23, // telnet
25, // smtp
37, // time
42, // name
43, // nicname
53, // domain
77, // priv-rjs
79, // finger
87, // ttylink
95, // supdup
101, // hostriame
102, // iso-tsap
103, // gppitnp
104, // acr-nema
109, // pop2
110, // pop3
111, // sunrpc
113, // auth
115, // sftp
117, // uucp-path
119, // nntp
123, // NTP
135, // loc-srv / epmap
139, // netbios
143, // imap2
179, // BGP
389, // ldap
512, // print / exec
513, // login
514, // shell
515, // printer
526, // tempo
530, // courier
531, // Chat
532, // netnews
540, // uucp
556, // remotefs
587, // sendmail
601, //
989, // ftps data
990, // ftps
992, // telnets
993, // imap/SSL
995, // pop3/SSL
1080, // SOCKS
2049, // nfs
4045, // lockd
6000, // x11
6667, // irc
0
};
for (int cnt=0; bad_ports[cnt]; ++cnt)
{
if (m_url.port() == bad_ports[cnt])
{
valid = false;
break;
}
}
if( !valid )
{
static bool override_loaded = false;
static QValueList< int >* overriden_ports = NULL;
if( !override_loaded )
{
KConfig cfg( "kio_httprc", true );
overriden_ports = new QValueList< int >;
*overriden_ports = cfg.readIntListEntry( "OverriddenPorts" );
override_loaded = true;
}
for (QValueList< int >::ConstIterator it = overriden_ports->begin();
it != overriden_ports->end(); ++it)
{
if( overriden_ports->contains(m_url.port()))
valid = true;
}
}
// if request is not valid, return an invalid transfer job
if (!valid)
{
m_error = KIO::ERR_POST_DENIED;
m_errorText = m_url.url();
}
return valid;
}
void PostJob::setBlockSize (KIO::filesize_t size)
{
_blockSize = size;
}
KIO::filesize_t PostJob::blockSize () const
{
return _blockSize;
}
void PostJob::start (Slave* slave)
{
assert (_dataSource);
if (_validatePort && !isPortSafe())
{
slotFinished ();
return;
}
// Open the source device if it is currently not opened.
if (!_dataSource->isOpen() && !_dataSource->open (IO_ReadOnly))
{
kdDebug (7007) << "PostJob::slotDataReq: Unable to open the post data source!!" << endl;
m_error = KIO::ERR_INTERNAL;
m_errorText = m_url.url();
slotFinished();
return;
}
m_totalSize = _dataSource->size();
if (m_totalSize == 0)
{
kdDebug (7007) << "PostJob::slotDataReq: Hmmm... the post data source is empty!!" << endl;
m_error = KIO::ERR_INTERNAL;
m_errorText = m_url.url();
slotFinished();
return;
}
addMetaData ("content-length", KIO::number (m_totalSize));
TransferJob::start (slave);
}
void PostJob::slotDataReq()
{
assert(_dataSource);
// If we reached the end of the device, indicate the condition
// to the io-slave and reset the device position to 0 so that
// the data can be re-transmitted if the io-slave requests it
// again...
if (_dataSource->atEnd())
{
_dataSource->reset();
staticData = QByteArray();
_bytesSent = 0;
kdDebug (7007) << "PostJob::slotDataReq: DONE => resetting data buffer..." << endl;
}
else
{
KIO::filesize_t dataSize = _blockSize;
if ((m_totalSize - _bytesSent) < dataSize)
dataSize = m_totalSize - _bytesSent;
staticData.fill (0, dataSize);
if (_dataSource->readBlock (staticData.data(), dataSize) < 0)
{
m_error = ERR_INTERNAL;
m_errorText = i18n("PostJob::slotDataReq: Could not read POST data from source.");
slotFinished ();
kdDebug(7007) << "PostJob::slotDataReq: Error reading data..." << endl;
return;
}
_bytesSent += dataSize;
kdDebug (7007) << "PostJob::slotDataReq: Sent " << KIO::number(_bytesSent)
<< "/" << KIO::number(m_totalSize) << " bytes..." << endl;
}
TransferJob::slotDataReq();
}
void PostJob::setEnablePortCheck (bool enable)
{
_validatePort = enable;
}
bool PostJob::isPortCheckEnabled () const
{
return _validatePort;
}
["postjob.hpp" (text/x-c++src)]
/**
* A job to stream data to the remote machine.
*
* @author Dawit Alemayehu <adawit@kde.org>
*/
class PostJob : public TransferJob {
Q_OBJECT
public:
PostJob (const KURL& url, int command, const QByteArray& packedArgs,
QIODevice * device, bool showProgressInfo);
/**
* @deprecated. This ctor is only provided for compatability sake
* until all protocols that use KIO::http_post are ported to use
* the newer API above. Use the above ctor instead.
*/
PostJob (const KURL& url, int command, const QByteArray& packedArgs,
const QByteArray& data, bool showProgressInfo);
~PostJob ();
/**
* Set the size at which data is streamed (sent) to the io-slave.
* The default block size (segement) is 256K. Due to the limitation
* in the underlying framework (copying of data), the maximum size
* allowed 1 MB. Any value above that will be truncated.
*
* @param size segement in bytes at which data should be sent to the
* io-slave.
*/
void setBlockSize (KIO::filesize_t size);
/**
* @return the size in bytes of the data segement sent to an io-slave
* at one time.
*/
KIO::filesize_t blockSize () const;
/**
* Re-implemented for internal reasons. API is unaffected.
*
* Note that the job will fail and return error if the POST action
* is being done to a non-safe port. This of course depends on whether
* non-safe port checking has been enabled or not.
*/
virtual void start (Slave* slave);
/**
* Enable/disable port verification to avoid maclicious posting.
* Default is enabled. The default might not be applicable to all
* protocols. If you rather do the checking yourself internally,
* disable the check using this function.
*
* @param enable if true perform port check before starting a job. Do
* not perform any checks otherwise.
*/
void setEnablePortCheck (bool enable);
/**
* @return true if non-safe port checking has been enabled. False otherwise.
*/
bool isPortCheckEnabled () const;
protected:
/**
* Verifies whether or not the POST action is being done to a "safe"
* (non-malicious) port number.
*
* @return true if port number is safe, false otherwise.
*/
virtual bool isPortSafe ();
protected slots:
/**
* Re-implemented for internal reasons. API remains unaffected.
*/
virtual void slotDataReq ();
private:
KIO::filesize_t _bytesSent;
KIO::filesize_t _blockSize;
bool _autoDeleteSource;
bool _validatePort;
QIODevice* _dataSource;
QString _tempfile;
class HTTPPostPrivate* d;
};
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic