diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 02:37:40 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 02:37:40 +0000 |
commit | 9ad5c7b5e23b4940e7a3ea3ca3a6fb77e6a8fab0 (patch) | |
tree | d088b5210e77d9fa91d954d8550e00e372b47378 /libktorrent/util | |
download | ktorrent-9ad5c7b5e23b4940e7a3ea3ca3a6fb77e6a8fab0.tar.gz ktorrent-9ad5c7b5e23b4940e7a3ea3ca3a6fb77e6a8fab0.zip |
Updated to final KDE3 ktorrent release (2.2.6)
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/ktorrent@1077377 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'libktorrent/util')
36 files changed, 4599 insertions, 0 deletions
diff --git a/libktorrent/util/Makefile.am b/libktorrent/util/Makefile.am new file mode 100644 index 0000000..c7f46ae --- /dev/null +++ b/libktorrent/util/Makefile.am @@ -0,0 +1,18 @@ +INCLUDES = -I$(srcdir)/../../libktorrent $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libutil.la +libutil_la_LDFLAGS = $(all_libraries) + + +libutil_la_SOURCES = array.cpp autorotatelogjob.cpp bitset.cpp error.cpp \ + file.cpp fileops.cpp functions.cpp httprequest.cpp log.cpp mmapfile.cpp \ + profiler.cpp ptrmap.cpp sha1hash.cpp sha1hashgen.cpp timer.cpp urlencoder.cpp \ + waitjob.cpp + + + + +KDE_CXXFLAGS = $(USE_EXCEPTIONS) $(USE_RTTI) +noinst_HEADERS = autorotatelogjob.h profiler.h diff --git a/libktorrent/util/array.cpp b/libktorrent/util/array.cpp new file mode 100644 index 0000000..e57091d --- /dev/null +++ b/libktorrent/util/array.cpp @@ -0,0 +1,27 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 "array.h" + +namespace bt +{ + + + +} diff --git a/libktorrent/util/array.h b/libktorrent/util/array.h new file mode 100644 index 0000000..1694e2a --- /dev/null +++ b/libktorrent/util/array.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTARRAY_H +#define BTARRAY_H + +#include "constants.h" + +namespace bt +{ + + /** + * @author Joris Guisson + * + * Template array classes, makes creating dynamic buffers easier + * and safer. + */ + template<class T> + class Array + { + Uint32 num; + T* data; + public: + Array(Uint32 num = 0) : num(num),data(0) + { + if (num > 0) + data = new T[num]; + } + + ~Array() + { + delete [] data; + } + + T & operator [] (Uint32 i) {return data[i];} + const T & operator [] (Uint32 i) const {return data[i];} + + operator const T* () const {return data;} + operator T* () {return data;} + + /// Get the number of elements in the array + Uint32 size() const {return num;} + + /** + * Fill the array with a value + * @param val The value + */ + void fill(T val) + { + for (Uint32 i = 0;i < num;i++) + data[i] = val; + } + }; + +} + +#endif diff --git a/libktorrent/util/autorotatelogjob.cpp b/libktorrent/util/autorotatelogjob.cpp new file mode 100644 index 0000000..c43e304 --- /dev/null +++ b/libktorrent/util/autorotatelogjob.cpp @@ -0,0 +1,88 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 <kurl.h> +#include <kprocess.h> +#include <util/fileops.h> +#include "autorotatelogjob.h" +#include "log.h" + +namespace bt +{ + + AutoRotateLogJob::AutoRotateLogJob(const QString & file,Log* lg) + : KIO::Job(false),file(file),cnt(10),lg(lg) + { + update(); + } + + + AutoRotateLogJob::~AutoRotateLogJob() + {} + + void AutoRotateLogJob::kill(bool) + { + m_error = 0; + emitResult(); + } + + void AutoRotateLogJob::update() + { + while (cnt > 1) + { + QString prev = QString("%1-%2.gz").arg(file).arg(cnt - 1); + QString curr = QString("%1-%2.gz").arg(file).arg(cnt); + if (bt::Exists(prev)) // if file exists start the move job + { + KIO::Job* sj = KIO::file_move(KURL::fromPathOrURL(prev),KURL::fromPathOrURL(curr),-1,true,false,false); + connect(sj,SIGNAL(result(KIO::Job*)),this,SLOT(moveJobDone(KIO::Job* ))); + return; + } + else + { + cnt--; + } + } + + if (cnt == 1) + { + // move current log to 1 and zip it + bt::Move(file,file + "-1",true); + KIO::Job* sj = KIO::file_move(KURL::fromPathOrURL(file),KURL::fromPathOrURL(file + "-1"),-1,true,false,false); + connect(sj,SIGNAL(result(KIO::Job*)),this,SLOT(moveJobDone(KIO::Job* ))); + } + else + { + // final log file is moved, now zip it and end the job + std::system(QString("gzip " + KProcess::quote(file + "-1")).local8Bit()); + m_error = 0; + lg->logRotateDone(); + emitResult(); + } + } + + + void AutoRotateLogJob::moveJobDone(KIO::Job*) + { + cnt--; // decrease counter so the newt file will be moved in update + update(); // don't care about result of job + } + +} +#include "autorotatelogjob.moc" diff --git a/libktorrent/util/autorotatelogjob.h b/libktorrent/util/autorotatelogjob.h new file mode 100644 index 0000000..11cf06a --- /dev/null +++ b/libktorrent/util/autorotatelogjob.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTAUTOROTATELOGJOB_H +#define BTAUTOROTATELOGJOB_H + +#include <kio/job.h> +#include <cstdlib> + +namespace bt +{ + class Log; + + /** + @author Joris Guisson <[email protected]> + + Job which handles the rotation of the log file. + This Job must do several move jobs which must be done sequentially. + */ + class AutoRotateLogJob : public KIO::Job + { + Q_OBJECT + public: + AutoRotateLogJob(const QString & file,Log* lg); + virtual ~AutoRotateLogJob(); + + virtual void kill(bool quietly=true); + + private slots: + void moveJobDone(KIO::Job*); + + private: + void update(); + + private: + QString file; + int cnt; + Log* lg; + }; + +} + +#endif diff --git a/libktorrent/util/bitset.cpp b/libktorrent/util/bitset.cpp new file mode 100644 index 0000000..6139e01 --- /dev/null +++ b/libktorrent/util/bitset.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 <algorithm> +#include "bitset.h" +#include <string.h> + +namespace bt +{ + BitSet BitSet::null; + + BitSet::BitSet(Uint32 num_bits) : num_bits(num_bits),data(0) + { + num_bytes = (num_bits / 8) + ((num_bits % 8 > 0) ? 1 : 0); + data = new Uint8[num_bytes]; + std::fill(data,data+num_bytes,0x00); + num_on = 0; + } + + BitSet::BitSet(const Uint8* d,Uint32 num_bits) : num_bits(num_bits),data(0) + { + num_bytes = (num_bits / 8) + ((num_bits % 8 > 0) ? 1 : 0); + data = new Uint8[num_bytes]; + memcpy(data,d,num_bytes); + num_on = 0; + Uint32 i = 0; + while (i < num_bits) + { + if (get(i)) + num_on++; + i++; + } + } + + BitSet::BitSet(const BitSet & bs) : num_bits(bs.num_bits),num_bytes(bs.num_bytes),data(0),num_on(bs.num_on) + { + data = new Uint8[num_bytes]; + std::copy(bs.data,bs.data+num_bytes,data); + } + + BitSet::~BitSet() + { + delete [] data; + } + + + + BitSet & BitSet::operator = (const BitSet & bs) + { + if (data) + delete [] data; + num_bytes = bs.num_bytes; + num_bits = bs.num_bits; + data = new Uint8[num_bytes]; + std::copy(bs.data,bs.data+num_bytes,data); + num_on = bs.num_on; + return *this; + } + + void BitSet::setAll(bool on) + { + std::fill(data,data+num_bytes,on ? 0xFF : 0x00); + num_on = on ? num_bits : 0; + } + + void BitSet::clear() + { + setAll(false); + } + + void BitSet::orBitSet(const BitSet & other) + { + Uint32 i = 0; + while (i < num_bits) + { + bool val = get(i) || other.get(i); + set(i,val); + i++; + } + } + + bool BitSet::allOn() const + { + return num_on == num_bits; + } + + bool BitSet::operator == (const BitSet & bs) + { + if (this->getNumBits() != bs.getNumBits()) + return false; + + return memcmp(data,bs.data,num_bytes) == 0; + } +} + diff --git a/libktorrent/util/bitset.h b/libktorrent/util/bitset.h new file mode 100644 index 0000000..32e7e48 --- /dev/null +++ b/libktorrent/util/bitset.h @@ -0,0 +1,157 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTBITSET_H +#define BTBITSET_H + +#include "constants.h" + +namespace bt +{ + + /** + * @author Joris Guisson + * @brief Simple implementation of a BitSet + * + * Simple implementation of a BitSet, can only turn on and off bits. + * BitSet's are used to indicate which chunks we have or not. + */ + class BitSet + { + Uint32 num_bits,num_bytes; + Uint8* data; + Uint32 num_on; + public: + /** + * Constructor. + * @param num_bits The number of bits + */ + BitSet(Uint32 num_bits = 8); + + /** + * Manually set data. + * @param data The data + * @param num_bits The number of bits + */ + BitSet(const Uint8* data,Uint32 num_bits); + + /** + * Copy constructor. + * @param bs BitSet to copy + * @return + */ + BitSet(const BitSet & bs); + virtual ~BitSet(); + + /// See if the BitSet is null + bool isNull() const {return num_bits == 0;} + + /** + * Get the value of a bit, false means 0, true 1. + * @param i Index of Bit + */ + bool get(Uint32 i) const; + + /** + * Set the value of a bit, false means 0, true 1. + * @param i Index of Bit + * @param on False means 0, true 1 + */ + void set(Uint32 i,bool on); + + /// Set all bits on or off + void setAll(bool on); + + Uint32 getNumBytes() const {return num_bytes;} + Uint32 getNumBits() const {return num_bits;} + const Uint8* getData() const {return data;} + Uint8* getData() {return data;} + + /// Get the number of on bits + Uint32 numOnBits() const {return num_on;} + + /** + * Set all bits to 0 + */ + void clear(); + + /** + * or this BitSet with another. + * @param other The other BitSet + */ + void orBitSet(const BitSet & other); + + /** + * Assignment operator. + * @param bs BitSet to copy + * @return *this + */ + BitSet & operator = (const BitSet & bs); + + /// Check if all bit are set to 1 + bool allOn() const; + + /** + * Check for equality of bitsets + * @param bs BitSet to compare + * @return true if equal + */ + bool operator == (const BitSet & bs); + + /** + * Opposite of operator == + */ + bool operator != (const BitSet & bs) {return ! operator == (bs);} + + static BitSet null; + }; + + inline bool BitSet::get(Uint32 i) const + { + if (i >= num_bits) + return false; + + Uint32 byte = i / 8; + Uint32 bit = i % 8; + Uint8 b = data[byte] & (0x01 << (7 - bit)); + return b != 0x00; + } + + inline void BitSet::set(Uint32 i,bool on) + { + if (i >= num_bits) + return; + + Uint32 byte = i / 8; + Uint32 bit = i % 8; + if (on && !get(i)) + { + num_on++; + data[byte] |= (0x01 << (7 - bit)); + } + else if (!on && get(i)) + { + num_on--; + Uint8 b = (0x01 << (7 - bit)); + data[byte] &= (~b); + } + } +} + +#endif diff --git a/libktorrent/util/constants.h b/libktorrent/util/constants.h new file mode 100644 index 0000000..e663978 --- /dev/null +++ b/libktorrent/util/constants.h @@ -0,0 +1,96 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTCONSTANTS_H +#define BTCONSTANTS_H + +#include <qglobal.h> + +namespace bt +{ + typedef Q_UINT64 Uint64; + typedef Q_UINT32 Uint32; + typedef Q_UINT16 Uint16; + typedef Q_UINT8 Uint8; + + typedef Q_INT64 Int64; + typedef Q_INT32 Int32; + typedef Q_INT16 Int16; + typedef Q_INT8 Int8; + + typedef Uint64 TimeStamp; + + typedef enum + { + /* These are the old values, for compatability reasons with old chunk_info files we leave them here : + PREVIEW_PRIORITY = 4, + FIRST_PRIORITY = 3, + NORMAL_PRIORITY = 2, + LAST_PRIORITY = 1, + EXCLUDED = 0, + ONLY_SEED_PRIORITY = -1 + */ + // make sure new values are different from old values + // also leave some room if we want to add new priorities in the future + PREVIEW_PRIORITY = 60, + FIRST_PRIORITY = 50, + NORMAL_PRIORITY = 40, + LAST_PRIORITY = 30, + ONLY_SEED_PRIORITY = 20, + EXCLUDED = 10 + }Priority; + + enum ConfirmationResult + { + KEEP_DATA, + THROW_AWAY_DATA, + CANCELED + }; + + const Uint32 MAX_MSGLEN = 9 + 131072; + const Uint16 MIN_PORT = 6881; + const Uint16 MAX_PORT = 6889; + const Uint32 MAX_PIECE_LEN = 16384; + + const Uint8 CHOKE = 0; + const Uint8 UNCHOKE = 1; + const Uint8 INTERESTED = 2; + const Uint8 NOT_INTERESTED = 3; + const Uint8 HAVE = 4; + const Uint8 BITFIELD = 5; + const Uint8 REQUEST = 6; + const Uint8 PIECE = 7; + const Uint8 CANCEL = 8; + const Uint8 PORT = 9; + const Uint8 SUGGEST_PIECE = 13; + const Uint8 HAVE_ALL = 14; + const Uint8 HAVE_NONE = 15; + const Uint8 REJECT_REQUEST = 16; + const Uint8 ALLOWED_FAST = 17; + const Uint8 EXTENDED = 20; // extension protocol message + + + // flags for things which a peer supports + const Uint32 DHT_SUPPORT = 0x01; + const Uint32 EXT_PROT_SUPPORT = 0x10; + const Uint32 FAST_EXT_SUPPORT = 0x04; +} + + +#endif diff --git a/libktorrent/util/error.cpp b/libktorrent/util/error.cpp new file mode 100644 index 0000000..bb981db --- /dev/null +++ b/libktorrent/util/error.cpp @@ -0,0 +1,33 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 "error.h" + +namespace bt +{ + + Error::Error(const QString & msg) : msg(msg) + {} + + + Error::~Error() + {} + + +} diff --git a/libktorrent/util/error.h b/libktorrent/util/error.h new file mode 100644 index 0000000..8b089e4 --- /dev/null +++ b/libktorrent/util/error.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTERROR_H +#define BTERROR_H + +#include <qstring.h> + +namespace bt +{ + + /** + @author Joris Guisson + */ + class Error + { + QString msg; + public: + Error(const QString & msg); + virtual ~Error(); + + QString toString() const {return msg;} + + }; + +} + +#endif diff --git a/libktorrent/util/file.cpp b/libktorrent/util/file.cpp new file mode 100644 index 0000000..b898e07 --- /dev/null +++ b/libktorrent/util/file.cpp @@ -0,0 +1,150 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qfile.h> +#include "config.h" +#include <klocale.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include <torrent/globals.h> +#include "file.h" +#include "error.h" +#include "log.h" + +namespace bt +{ + + File::File() : fptr(0) + {} + + + File::~File() + { + close(); + } + + bool File::open(const QString & file,const QString & mode) + { + this->file = file; + if (fptr) + close(); +#if HAVE_FOPEN64 + fptr = fopen64(QFile::encodeName(file),mode.ascii()); +#else + fptr = fopen(QFile::encodeName(file),mode.ascii()); +#endif + return fptr != 0; + } + + void File::close() + { + if (fptr) + { + fclose(fptr); + fptr = 0; + } + } + + void File::flush() + { + if (fptr) + fflush(fptr); + } + + Uint32 File::write(const void* buf,Uint32 size) + { + if (!fptr) + return 0; + + Uint32 ret = fwrite(buf,1,size,fptr); + if (ret != size) + { + if (errno == ENOSPC) + Out() << "Disk full !" << endl; + + throw Error(i18n("Cannot write to %1 : %2").arg(file).arg(strerror(errno))); + } + return ret; + } + + Uint32 File::read(void* buf,Uint32 size) + { + if (!fptr) + return 0; + + Uint32 ret = fread(buf,1,size,fptr); + if (ferror(fptr)) + { + clearerr(fptr); + throw Error(i18n("Cannot read from %1").arg(file)); + } + return ret; + } + + Uint64 File::seek(SeekPos from,Int64 num) + { + // printf("sizeof(off_t) = %i\n",sizeof(__off64_t)); + if (!fptr) + return 0; + + int p = SEEK_CUR; // use a default to prevent compiler warning + switch (from) + { + case BEGIN : p = SEEK_SET; break; + case END : p = SEEK_END; break; + case CURRENT : p = SEEK_CUR; break; + default: + break; + } +#if HAVE_FSEEKO64 + fseeko64(fptr,num,p); + return ftello64(fptr); +#else + fseeko(fptr,num,p); + return ftello(fptr); +#endif + } + + bool File::eof() const + { + if (!fptr) + return true; + + return feof(fptr) != 0; + } + + Uint64 File::tell() const + { + if (!fptr) + return 0; + + return ftello(fptr); + } + + QString File::errorString() const + { + return QString(strerror(errno)); + } +} diff --git a/libktorrent/util/file.h b/libktorrent/util/file.h new file mode 100644 index 0000000..323a3a7 --- /dev/null +++ b/libktorrent/util/file.h @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTFILE_H +#define BTFILE_H + +#include <stdio.h> +#include <qstring.h> +#include "constants.h" + +namespace bt +{ + + /** + * @author Joris Guisson + * @brief Wrapper class for stdio's FILE + * + * Wrapper class for stdio's FILE. + */ + class File + { + FILE* fptr; + QString file; + public: + /** + * Constructor. + */ + File(); + + /** + * Destructor, closes the file. + */ + virtual ~File(); + + /** + * Open the file similar to fopen + * @param file Filename + * @param mode Mode + * @return true upon succes + */ + bool open(const QString & file,const QString & mode); + + /** + * Close the file. + */ + void close(); + + /** + * Flush the file. + */ + void flush(); + + /** + * Write a bunch of data. If anything goes wrong + * an Error will be thrown. + * @param buf The data + * @param size Size of the data + * @return The number of bytes written + */ + Uint32 write(const void* buf,Uint32 size); + + /** + * Read a bunch of data. If anything goes wrong + * an Error will be thrown. + * @param buf The buffer to store the data + * @param size Size of the buffer + * @return The number of bytes read + */ + Uint32 read(void* buf,Uint32 size); + + enum SeekPos + { + BEGIN, + END, + CURRENT + }; + + /** + * Seek in the file. + * @param from Position to seek from + * @param num Number of bytes to move + * @return New position + */ + Uint64 seek(SeekPos from,Int64 num); + + /// Check to see if we are at the end of the file. + bool eof() const; + + /// Get the current position in the file. + Uint64 tell() const; + + /// Get the error string. + QString errorString() const; + }; + +} + +#endif diff --git a/libktorrent/util/fileops.cpp b/libktorrent/util/fileops.cpp new file mode 100644 index 0000000..3fcf03d --- /dev/null +++ b/libktorrent/util/fileops.cpp @@ -0,0 +1,466 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <klocale.h> +#include <kio/netaccess.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <qdir.h> +#include <qfile.h> +#include <qstringlist.h> +#include "fileops.h" +#include "error.h" +#include "log.h" +#include <torrent/globals.h> +#include "file.h" +#include "array.h" + +#ifdef HAVE_XFS_XFS_H + +#if !defined(HAVE___S64) || !defined(HAVE___U64) +#include <stdint.h> +#endif + +#ifndef HAVE___U64 +typedef uint64_t __u64; +#endif + +#ifndef HAVE___S64 +typedef int64_t __s64; +#endif + +#include <xfs/xfs.h> +#endif + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + +#if HAVE_STATVFS +#include <sys/statvfs.h> +#else +#include <sys/param.h> +#include <sys/mount.h> +#endif + +namespace bt +{ + void MakeDir(const QString & dir,bool nothrow) + { + if (mkdir(QFile::encodeName(dir),0777) < -1) + { + if (!nothrow) + throw Error(i18n("Cannot create directory %1: %2") + .arg(dir).arg(strerror(errno))); + else + { + Out() << QString("Error : Cannot create directory %1 : %2").arg(dir).arg(strerror(errno))<< endl; + } + } + } + + void SymLink(const QString & link_to,const QString & link_url,bool nothrow) + { + if (symlink(QFile::encodeName(link_to),QFile::encodeName(link_url)) != 0) + { + if (!nothrow) + throw Error(i18n("Cannot symlink %1 to %2: %3") + .arg(link_url.utf8()).arg(link_to.utf8()) + .arg(strerror(errno))); + else + Out() << QString("Error : Cannot symlink %1 to %2: %3") + .arg(link_url.utf8()).arg(link_to.utf8()) + .arg(strerror(errno)) << endl; + } + } + + void Move(const QString & src,const QString & dst,bool nothrow) + { + // Out() << "Moving " << src << " -> " << dst << endl; + if (!KIO::NetAccess::move(KURL::fromPathOrURL(src),KURL::fromPathOrURL(dst),0)) + { + if (!nothrow) + throw Error(i18n("Cannot move %1 to %2: %3") + .arg(src).arg(dst) + .arg(KIO::NetAccess::lastErrorString())); + else + Out() << QString("Error : Cannot move %1 to %2: %3") + .arg(src).arg(dst) + .arg(KIO::NetAccess::lastErrorString()) << endl; + + } + } + + void CopyFile(const QString & src,const QString & dst,bool nothrow) + { + if (!KIO::NetAccess::file_copy(KURL::fromPathOrURL(src),KURL::fromPathOrURL(dst))) + { + if (!nothrow) + throw Error(i18n("Cannot copy %1 to %2: %3") + .arg(src).arg(dst) + .arg(KIO::NetAccess::lastErrorString())); + else + Out() << QString("Error : Cannot copy %1 to %2: %3") + .arg(src).arg(dst) + .arg(KIO::NetAccess::lastErrorString()) << endl; + + } + } + + void CopyDir(const QString & src,const QString & dst,bool nothrow) + { + if (!KIO::NetAccess::dircopy(KURL::fromPathOrURL(src),KURL::fromPathOrURL(dst),0)) + { + if (!nothrow) + throw Error(i18n("Cannot copy %1 to %2: %3") + .arg(src).arg(dst) + .arg(KIO::NetAccess::lastErrorString())); + else + Out() << QString("Error : Cannot copy %1 to %2: %3") + .arg(src).arg(dst) + .arg(KIO::NetAccess::lastErrorString()) << endl; + + } + } + + bool Exists(const QString & url) + { + // Out() << "Testing if " << url << " exists " << endl; + if (access(QFile::encodeName(url),F_OK) < 0) + { + // Out() << "No " << endl; + return false; + } + else + { + // Out() << "Yes " << endl; + return true; + } + } + + static bool DelDir(const QString & fn) + { + QDir d(fn); + QStringList subdirs = d.entryList(QDir::Dirs); + + for (QStringList::iterator i = subdirs.begin(); i != subdirs.end();i++) + { + QString entry = *i; + + if (entry == ".." || entry == ".") + continue; + + if (!DelDir(d.absFilePath(entry))) + { + Out(SYS_GEN|LOG_DEBUG) << "Delete of " << fn << "/" << entry << " failed !" << endl; + return false; + } + } + + QStringList files = d.entryList(QDir::Files | QDir::System | QDir::Hidden); + for (QStringList::iterator i = files.begin(); i != files.end();i++) + { + QString entry = *i; + + if (remove(QFile::encodeName(d.absFilePath(entry))) < 0) + { + Out(SYS_GEN|LOG_DEBUG) << "Delete of " << fn << "/" << entry << " failed !" << endl; + return false; + } + } + + if (!d.rmdir(d.absPath())) + { + Out(SYS_GEN|LOG_DEBUG) << "Failed to remove " << d.absPath() << endl; + return false; + } + + return true; + } + + void Delete(const QString & url,bool nothrow) + { + QCString fn = QFile::encodeName(url); +#if HAVE_STAT64 + struct stat64 statbuf; + if (lstat64(fn, &statbuf) < 0) + return; +#else + struct stat statbuf; + if (lstat(fn, &statbuf) < 0) + return; +#endif + + bool ok = true; + // first see if it is a directory + if (S_ISDIR(statbuf.st_mode)) + { + ok = DelDir(url); + } + else + { + ok = remove(fn) >= 0; + } + + if (!ok) + { + QString err = i18n("Cannot delete %1: %2") + .arg(url) + .arg(strerror(errno)); + if (!nothrow) + throw Error(err); + else + Out() << "Error : " << err << endl; + } + } + + void Touch(const QString & url,bool nothrow) + { + if (Exists(url)) + return; + + File fptr; + if (!fptr.open(url,"wb")) + { + if (!nothrow) + throw Error(i18n("Cannot create %1: %2") + .arg(url) + .arg(fptr.errorString())); + else + Out() << "Error : Cannot create " << url << " : " + << fptr.errorString() << endl; + + } + } + + Uint64 FileSize(const QString & url) + { + int ret = 0; +#if HAVE_STAT64 + struct stat64 sb; + ret = stat64(QFile::encodeName(url),&sb); +#else + struct stat sb; + ret = stat(QFile::encodeName(url),&sb); +#endif + if (ret < 0) + throw Error(i18n("Cannot calculate the filesize of %1: %2") + .arg(url).arg(strerror(errno))); + + return (Uint64)sb.st_size; + } + + Uint64 FileSize(int fd) + { + int ret = 0; +#if HAVE_STAT64 + struct stat64 sb; + ret = fstat64(fd,&sb); +#else + struct stat sb; + ret = fstat(fd,&sb); +#endif + if (ret < 0) + throw Error(i18n("Cannot calculate the filesize : %2").arg(strerror(errno))); + + return (Uint64)sb.st_size; + } + + bool FatPreallocate(int fd,Uint64 size) + { + try + { + SeekFile(fd, size - 1, SEEK_SET); + char zero = 0; + if (write(fd, &zero, 1) == -1) + return false; + + TruncateFile(fd,size,true); + } + catch (bt::Error & e) + { + Out() << e.toString() << endl; + return false; + } + return true; + } + + bool FatPreallocate(const QString & path,Uint64 size) + { + int fd = ::open(QFile::encodeName(path),O_RDWR | O_LARGEFILE); + if (fd < 0) + throw Error(i18n("Cannot open %1 : %2").arg(path).arg(strerror(errno))); + + bool ret = FatPreallocate(fd,size); + close(fd); + return ret; + } + +#ifdef HAVE_XFS_XFS_H + + bool XfsPreallocate(int fd, Uint64 size) + { + if( ! platform_test_xfs_fd(fd) ) + { + return false; + } + + xfs_flock64_t allocopt; + allocopt.l_whence = 0; + allocopt.l_start = 0; + allocopt.l_len = size; + + return (! static_cast<bool>(xfsctl(0, fd, XFS_IOC_RESVSP64, &allocopt)) ); + + } + + bool XfsPreallocate(const QString & path, Uint64 size) + { + int fd = ::open(QFile::encodeName(path), O_RDWR | O_LARGEFILE); + if (fd < 0) + throw Error(i18n("Cannot open %1 : %2").arg(path).arg(strerror(errno))); + + bool ret = XfsPreallocate(fd,size); + close(fd); + return ret; + } + +#endif + + void TruncateFile(int fd,Uint64 size,bool quick) + { + if (FileSize(fd) == size) + return; + + if (quick) + { +#if HAVE_FTRUNCATE64 + if (ftruncate64(fd,size) == -1) +#else + if (ftruncate(fd,size) == -1) +#endif + throw Error(i18n("Cannot expand file : %1").arg(strerror(errno))); + } + else + { +#if HAVE_POSIX_FALLOCATE64 + if (posix_fallocate64(fd,0,size) != 0) + throw Error(i18n("Cannot expand file : %1").arg(strerror(errno))); +#elif HAVE_POSIX_FALLOCATE + if (posix_fallocate(fd,0,size) != 0) + throw Error(i18n("Cannot expand file : %1").arg(strerror(errno))); +#else + SeekFile(fd,0,SEEK_SET); + bt::Array<Uint8> buf(4096); + buf.fill(0); + + Uint64 written = 0; + while (written < size) + { + int to_write = size - written; + if (to_write > 4096) + to_write = 4096; + + int ret = write(fd,buf,to_write); + if (ret < 0) + throw Error(i18n("Cannot expand file : %1").arg(strerror(errno))); + else if (ret == 0 || ret != (int)to_write) + throw Error(i18n("Cannot expand file").arg(strerror(errno))); + else + written += to_write; + } +#endif + } + } + + void TruncateFile(const QString & path,Uint64 size) + { + int fd = ::open(QFile::encodeName(path),O_RDWR | O_LARGEFILE); + if (fd < 0) + throw Error(i18n("Cannot open %1 : %2").arg(path).arg(strerror(errno))); + + try + { + TruncateFile(fd,size,true); + close(fd); + } + catch (...) + { + close(fd); + throw; + } + } + + void SeekFile(int fd,Int64 off,int whence) + { +#if HAVE_LSEEK64 + if (lseek64(fd,off,whence) == -1) +#else + if (lseek(fd,off,whence) == -1) +#endif + throw Error(i18n("Cannot seek in file : %1").arg(strerror(errno))); + } + + bool FreeDiskSpace(const QString & path,Uint64 & bytes_free) + { +#if HAVE_STATVFS +#if HAVE_STATVFS64 + struct statvfs64 stfs; + if (statvfs64(path.local8Bit(), &stfs) == 0) +#else + struct statvfs stfs; + if (statvfs(path.local8Bit(), &stfs) == 0) +#endif + { + bytes_free = ((Uint64)stfs.f_bavail) * ((Uint64)stfs.f_frsize); + return true; + } + else + { + Out(SYS_GEN|LOG_DEBUG) << "Error : statvfs for " << path << " failed : " + << QString(strerror(errno)) << endl; + + return false; + } +#else + struct statfs stfs; + if (statfs(path.local8Bit(), &stfs) == 0) + { + bytes_free = ((Uint64)stfs.f_bavail) * ((Uint64)stfs.f_bsize); + return true; + } + else + { + Out(SYS_GEN|LOG_DEBUG) << "Error : statfs for " << path << " failed : " + << QString(strerror(errno)) << endl; + + return false; + } +#endif + } +} diff --git a/libktorrent/util/fileops.h b/libktorrent/util/fileops.h new file mode 100644 index 0000000..253ee96 --- /dev/null +++ b/libktorrent/util/fileops.h @@ -0,0 +1,165 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTFILEOPS_H +#define BTFILEOPS_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <util/constants.h> +class QString; + +namespace bt +{ + + /** + * Creates a directory. Convenience function around + * KIO::NetAccess::mkdir . + * @param dir The url of the dir + * @param nothrow wether or not we shouldn't throw an Error upon failure + * @throw Error upon error + */ + void MakeDir(const QString & dir,bool nothrow = false); + + /** + * Create a symbolic link @a link_url which links to @a link_to + * @param link_to The file to link to + * @param link_url The link url + * @param nothrow wether or not we shouldn't throw an Error upon failure + */ + void SymLink(const QString & link_to,const QString & link_url,bool nothrow = false); + + /** + * Move a file/dir from one location to another + * @param src The source file + * @param dst The destination file / directory + * @param nothrow wether or not we shouldn't throw an Error upon failure + */ + void Move(const QString & src,const QString & dst,bool nothrow = false); + + /** + * Copy a file. + * @param src The source file + * @param dst The destination dir/file + * @param nothrow wether or not we shouldn't throw an Error upon failure + */ + void CopyFile(const QString & src,const QString & dst,bool nothrow = false); + + /** + * Copy a file or directory + * @param src The source file + * @param dst The destination dir/file + * @param nothrow wether or not we shouldn't throw an Error upon failure + */ + void CopyDir(const QString & src,const QString & dst,bool nothrow = false); + + /** + * Check wether a file/dir exists + * @param url The file/dir + * @return true if it exits + */ + bool Exists(const QString & url); + + /** + * Delete a file or directory. + * @param url The url of the file/dir + * @param nothrow wether or not we shouldn't throw an Error upon failure + */ + void Delete(const QString & url,bool nothrow = false); + + /** + * Try to create a file. Doesn't do anything if the file + * already exists. + * @param url The url of the file + * @param nothrow wether or not we shouldn't throw an Error upon failure + */ + void Touch(const QString & url,bool nothrow = false); + + /** + * Calculates the size of a file + * @param url Name of the file + * @return The size of the file + * @throw Error if the file doesn't exist, or something else goes wrong + */ + Uint64 FileSize(const QString & url); + + /** + * Get the size of a file. + * @param fd The file descriptor of the file + * @return The size + * @throw Error if the file doesn't exist, or something else goes wrong + */ + Uint64 FileSize(int fd); + + /** + * Truncate a file (wrapper around ftruncate) + * @param fd The file descriptor of the file + * @param size The size to truncate to + * @throw Error if the file doesn't exist, or something else goes wrong + */ + void TruncateFile(int fd,Uint64 size,bool quick); + + /** + * Truncate a file (wrapper around ftruncate) + * @param fd Path of the file + * @param size The size to truncate to + * @param quick Use the quick way (doesn't prevent fragmentationt) + * @throw Error if the file doesn't exist, or something else goes wrong + */ + void TruncateFile(const QString & path,Uint64 size); + + /** + * Special truncate for FAT file systems. + */ + bool FatPreallocate(int fd,Uint64 size); + + /** + * Special truncate for FAT file systems. + */ + bool FatPreallocate(const QString & path,Uint64 size); + +#ifdef HAVE_XFS_XFS_H + /** + * Special truncate for XFS file systems. + */ + bool XfsPreallocate(int fd,Uint64 size); + + /** + * Special truncate for XFS file systems. + */ + bool XfsPreallocate(const QString & path,Uint64 size); + +#endif + + /** + * Seek in a file, wrapper around lseek + * @param fd The file descriptor + * @param off Offset + * @param whence Position to seek from + * @throw Error if something else goes wrong + */ + void SeekFile(int fd,Int64 off,int whence); + + /// Calculate the number of bytes free on the filesystem path is located + bool FreeDiskSpace(const QString & path,Uint64 & bytes_free); +} + +#endif diff --git a/libktorrent/util/functions.cpp b/libktorrent/util/functions.cpp new file mode 100644 index 0000000..744bf43 --- /dev/null +++ b/libktorrent/util/functions.cpp @@ -0,0 +1,239 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 <qdir.h> +#include <qhostaddress.h> +#include <errno.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <kio/netaccess.h> +#include <klocale.h> +#include <kmimetype.h> +#include <kglobal.h> +#include "functions.h" +#include "error.h" +#include "log.h" + +namespace bt +{ + + bool IsMultimediaFile(const QString & filename) + { + KMimeType::Ptr ptr = KMimeType::findByPath(filename); + QString name = ptr->name(); + return name.startsWith("audio") || name.startsWith("video") || name == "application/ogg"; + } + + QHostAddress LookUpHost(const QString & host) + { + struct hostent * he = gethostbyname(host.ascii()); + QHostAddress addr; + if (he) + { + addr.setAddress(inet_ntoa(*((struct in_addr *)he->h_addr))); + } + return addr; + } + + QString DirSeparator() + { + QString tmp; + tmp.append(QDir::separator()); + return tmp; + } + + void WriteUint64(Uint8* buf,Uint32 off,Uint64 val) + { + buf[off + 0] = (Uint8) ((val & 0xFF00000000000000ULL) >> 56); + buf[off + 1] = (Uint8) ((val & 0x00FF000000000000ULL) >> 48); + buf[off + 2] = (Uint8) ((val & 0x0000FF0000000000ULL) >> 40); + buf[off + 3] = (Uint8) ((val & 0x000000FF00000000ULL) >> 32); + buf[off + 4] = (Uint8) ((val & 0x00000000FF000000ULL) >> 24); + buf[off + 5] = (Uint8) ((val & 0x0000000000FF0000ULL) >> 16); + buf[off + 6] = (Uint8) ((val & 0x000000000000FF00ULL) >> 8); + buf[off + 7] = (Uint8) ((val & 0x00000000000000FFULL) >> 0); + } + + Uint64 ReadUint64(const Uint8* buf,Uint64 off) + { + Uint64 tmp = + ((Uint64)buf[off] << 56) | + ((Uint64)buf[off+1] << 48) | + ((Uint64)buf[off+2] << 40) | + ((Uint64)buf[off+3] << 32) | + ((Uint64)buf[off+4] << 24) | + ((Uint64)buf[off+5] << 16) | + ((Uint64)buf[off+6] << 8) | + ((Uint64)buf[off+7] << 0); + + return tmp; + } + + void WriteUint32(Uint8* buf,Uint32 off,Uint32 val) + { + buf[off + 0] = (Uint8) ((val & 0xFF000000) >> 24); + buf[off + 1] = (Uint8) ((val & 0x00FF0000) >> 16); + buf[off + 2] = (Uint8) ((val & 0x0000FF00) >> 8); + buf[off + 3] = (Uint8) (val & 0x000000FF); + } + + Uint32 ReadUint32(const Uint8* buf,Uint32 off) + { + return (buf[off] << 24) | (buf[off+1] << 16) | (buf[off+2] << 8) | buf[off + 3]; + } + + void WriteUint16(Uint8* buf,Uint32 off,Uint16 val) + { + buf[off + 0] = (Uint8) ((val & 0xFF00) >> 8); + buf[off + 1] = (Uint8) (val & 0x000FF); + } + + Uint16 ReadUint16(const Uint8* buf,Uint32 off) + { + return (buf[off] << 8) | buf[off + 1]; + } + + + void WriteInt64(Uint8* buf,Uint32 off,Int64 val) + { + buf[off + 0] = (Uint8) ((val & 0xFF00000000000000ULL) >> 56); + buf[off + 1] = (Uint8) ((val & 0x00FF000000000000ULL) >> 48); + buf[off + 2] = (Uint8) ((val & 0x0000FF0000000000ULL) >> 40); + buf[off + 3] = (Uint8) ((val & 0x000000FF00000000ULL) >> 32); + buf[off + 4] = (Uint8) ((val & 0x00000000FF000000ULL) >> 24); + buf[off + 5] = (Uint8) ((val & 0x0000000000FF0000ULL) >> 16); + buf[off + 6] = (Uint8) ((val & 0x000000000000FF00ULL) >> 8); + buf[off + 7] = (Uint8) ((val & 0x00000000000000FFULL) >> 0); + } + + Int64 ReadInt64(const Uint8* buf,Uint32 off) + { + Int64 tmp = + ((Int64)buf[off] << 56) | + ((Int64)buf[off+1] << 48) | + ((Int64)buf[off+2] << 40) | + ((Int64)buf[off+3] << 32) | + ((Int64)buf[off+4] << 24) | + ((Int64)buf[off+5] << 16) | + ((Int64)buf[off+6] << 8) | + ((Int64)buf[off+7] << 0); + + return tmp; + } + + void WriteInt32(Uint8* buf,Uint32 off,Int32 val) + { + buf[off + 0] = (Uint8) ((val & 0xFF000000) >> 24); + buf[off + 1] = (Uint8) ((val & 0x00FF0000) >> 16); + buf[off + 2] = (Uint8) ((val & 0x0000FF00) >> 8); + buf[off + 3] = (Uint8) (val & 0x000000FF); + } + + Int32 ReadInt32(const Uint8* buf,Uint32 off) + { + return (Int32)(buf[off] << 24) | (buf[off+1] << 16) | (buf[off+2] << 8) | buf[off + 3]; + } + + void WriteInt16(Uint8* buf,Uint32 off,Int16 val) + { + buf[off + 0] = (Uint8) ((val & 0xFF00) >> 8); + buf[off + 1] = (Uint8) (val & 0x000FF); + } + + Int16 ReadInt16(const Uint8* buf,Uint32 off) + { + return (Int16)(buf[off] << 8) | buf[off + 1]; + } + + void UpdateCurrentTime() + { + global_time_stamp = Now(); + } + + TimeStamp global_time_stamp = 0; + + Uint64 Now() + { + struct timeval tv; + gettimeofday(&tv,0); + global_time_stamp = (Uint64)tv.tv_sec * 1000 + (Uint64)tv.tv_usec * 0.001; + return global_time_stamp; + } + + Uint32 MaxOpenFiles() + { + struct rlimit lim; + getrlimit(RLIMIT_NOFILE,&lim); + return lim.rlim_cur; + } + + bool MaximizeLimits() + { + // first get the current limits + struct rlimit lim; + getrlimit(RLIMIT_NOFILE,&lim); + + if (lim.rlim_cur != lim.rlim_max) + { + Out(SYS_GEN|LOG_DEBUG) << "Current limit for number of files : " << lim.rlim_cur + << " (" << lim.rlim_max << " max)" << endl; + lim.rlim_cur = lim.rlim_max; + if (setrlimit(RLIMIT_NOFILE,&lim) < 0) + { + Out(SYS_GEN|LOG_DEBUG) << "Failed to maximize file limit : " + << QString(strerror(errno)) << endl; + return false; + } + } + else + { + Out(SYS_GEN|LOG_DEBUG) << "File limit allready at maximum " << endl; + } + + getrlimit(RLIMIT_DATA,&lim); + if (lim.rlim_cur != lim.rlim_max) + { + Out(SYS_GEN|LOG_DEBUG) << "Current limit for data size : " << lim.rlim_cur + << " (" << lim.rlim_max << " max)" << endl; + lim.rlim_cur = lim.rlim_max; + if (setrlimit(RLIMIT_DATA,&lim) < 0) + { + Out(SYS_GEN|LOG_DEBUG) << "Failed to maximize data limit : " + << QString(strerror(errno)) << endl; + return false; + } + } + else + { + Out(SYS_GEN|LOG_DEBUG) << "Data limit allready at maximum " << endl; + } + + return true; + } + + + + +} diff --git a/libktorrent/util/functions.h b/libktorrent/util/functions.h new file mode 100644 index 0000000..4ace51b --- /dev/null +++ b/libktorrent/util/functions.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTFUNCTIONS_H +#define BTFUNCTIONS_H + +#include "constants.h" + +class QString; +class QHostAddress; +class KURL; + +namespace bt +{ + + void WriteUint64(Uint8* buf,Uint32 off,Uint64 val); + Uint64 ReadUint64(const Uint8* buf,Uint64 off); + + void WriteUint32(Uint8* buf,Uint32 off,Uint32 val); + Uint32 ReadUint32(const Uint8* buf,Uint32 off); + + void WriteUint16(Uint8* buf,Uint32 off,Uint16 val); + Uint16 ReadUint16(const Uint8* buf,Uint32 off); + + + void WriteInt64(Uint8* buf,Uint32 off,Int64 val); + Int64 ReadInt64(const Uint8* buf,Uint32 off); + + void WriteInt32(Uint8* buf,Uint32 off,Int32 val); + Int32 ReadInt32(const Uint8* buf,Uint32 off); + + void WriteInt16(Uint8* buf,Uint32 off,Int16 val); + Int16 ReadInt16(const Uint8* buf,Uint32 off); + + void UpdateCurrentTime(); + + extern TimeStamp global_time_stamp; + + inline TimeStamp GetCurrentTime() {return global_time_stamp;} + + TimeStamp Now(); + + QHostAddress LookUpHost(const QString & host); + QString DirSeparator(); + bool IsMultimediaFile(const QString & filename); + + /** + * Maximize the file and memory limits using setrlimit. + */ + bool MaximizeLimits(); + + /// Get the maximum number of open files + Uint32 MaxOpenFiles(); +} + +#endif diff --git a/libktorrent/util/httprequest.cpp b/libktorrent/util/httprequest.cpp new file mode 100644 index 0000000..d0652bc --- /dev/null +++ b/libktorrent/util/httprequest.cpp @@ -0,0 +1,122 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 <qstringlist.h> +#include <torrent/globals.h> +#include "httprequest.h" +#include "array.h" +#include "log.h" + + +namespace bt +{ + + HTTPRequest::HTTPRequest(const QString & hdr,const QString & payload,const QString & host,Uint16 port,bool verbose) : hdr(hdr),payload(payload),verbose(verbose) + { + sock = new KNetwork::KStreamSocket(host,QString::number(port),this,0); + sock->enableRead(true); + sock->enableWrite(true); + sock->setTimeout(30000); + sock->setBlocking(false); + connect(sock,SIGNAL(readyRead()),this,SLOT(onReadyRead())); + connect(sock,SIGNAL(gotError(int)),this,SLOT(onError(int ))); + connect(sock,SIGNAL(timedOut()),this,SLOT(onTimeout())); + connect(sock,SIGNAL(connected(const KResolverEntry&)), + this, SLOT(onConnect( const KResolverEntry& ))); + } + + + HTTPRequest::~HTTPRequest() + { + sock->close(); + delete sock; + } + + void HTTPRequest::start() + { + sock->connect(); + } + + void HTTPRequest::onConnect(const KResolverEntry&) + { + payload = payload.replace("$LOCAL_IP",sock->localAddress().nodeName()); + hdr = hdr.replace("$CONTENT_LENGTH",QString::number(payload.length())); + + QString req = hdr + payload; + if (verbose) + { + Out(SYS_PNP|LOG_DEBUG) << "Sending " << endl; + Out(SYS_PNP|LOG_DEBUG) << hdr << payload << endl; + } + sock->writeBlock(req.ascii(),req.length()); + } + + void HTTPRequest::onReadyRead() + { + Uint32 ba = sock->bytesAvailable(); + if (ba == 0) + { + error(this,false); + sock->close(); + return; + } + + Array<char> data(ba); + ba = sock->readBlock(data,ba); + QString strdata((const char*)data); + QStringList sl = QStringList::split("\r\n",strdata,false); + + if (verbose) + { + Out(SYS_PNP|LOG_DEBUG) << "Got reply : " << endl; + Out(SYS_PNP|LOG_DEBUG) << strdata << endl; + } + + if (sl.first().contains("HTTP") && sl.first().contains("200")) + { + // emit reply OK + replyOK(this,sl.last()); + } + else + { + // emit reply error + replyError(this,sl.last()); + } + operationFinished(this); + } + + void HTTPRequest::onError(int) + { + Out() << "HTTPRequest error : " << sock->errorString() << endl; + error(this,false); + sock->close(); + operationFinished(this); + } + + void HTTPRequest::onTimeout() + { + Out() << "HTTPRequest timeout" << endl; + error(this,true); + sock->close(); + operationFinished(this); + } + + +} +#include "httprequest.moc" diff --git a/libktorrent/util/httprequest.h b/libktorrent/util/httprequest.h new file mode 100644 index 0000000..348a84e --- /dev/null +++ b/libktorrent/util/httprequest.h @@ -0,0 +1,98 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTHTTPREQUEST_H +#define BTHTTPREQUEST_H + +#include <qobject.h> +#include <kurl.h> +#include <kstreamsocket.h> +#include <interfaces/exitoperation.h> +#include "constants.h" + +using KNetwork::KResolverEntry; + +namespace bt +{ + + /** + * @author Joris Guisson + * + * Just create one, fill in the fields, + * connect to the right signals and forget about it. After the reply has been received or + * an error occurred, the appropriate signal will be emitted. + */ + class HTTPRequest : public kt::ExitOperation + { + Q_OBJECT + public: + /** + * Constructor, set the url and the request header. + * @param hdr The http request header + * @param payload The payload + * @param host The host + * @param port THe port + * @param verbose Print traffic to the log + */ + HTTPRequest(const QString & hdr,const QString & payload,const QString & host, + Uint16 port,bool verbose); + virtual ~HTTPRequest(); + + /** + * Open a connetion and send the request. + */ + void start(); + + signals: + /** + * An OK reply was sent. + * @param r The sender of the request + * @param data The data of the reply + */ + void replyOK(bt::HTTPRequest* r,const QString & data); + + /** + * Anything else but an 200 OK was sent. + * @param r The sender of the request + * @param data The data of the reply + */ + void replyError(bt::HTTPRequest* r,const QString & data); + + /** + * No reply was sent and an error or timeout occurred. + * @param r The sender of the request + * @param timeout Wether or not a timeout occurred + */ + void error(bt::HTTPRequest* r,bool timeout); + + private slots: + void onReadyRead(); + void onError(int); + void onTimeout(); + void onConnect(const KResolverEntry&); + + private: + KNetwork::KStreamSocket* sock; + QString hdr,payload; + bool verbose; + }; + +} + +#endif diff --git a/libktorrent/util/log.cpp b/libktorrent/util/log.cpp new file mode 100644 index 0000000..05682a8 --- /dev/null +++ b/libktorrent/util/log.cpp @@ -0,0 +1,249 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 <kurl.h> +#include <kprocess.h> +#include <klocale.h> +#include <qdatetime.h> +#include <qtextstream.h> +#include <qfile.h> +#include <qptrlist.h> +#include <iostream> +#include <stdlib.h> +#include <torrent/globals.h> +#include <interfaces/logmonitorinterface.h> +#include <qmutex.h> +#include <util/fileops.h> +#include <stdlib.h> +#include "log.h" +#include "error.h" +#include "autorotatelogjob.h" + +using namespace kt; + +namespace bt +{ + const Uint32 MAX_LOG_FILE_SIZE = 10 * 1024 * 1024; // 10 MB + + class Log::Private + { + public: + Log* parent; + QTextStream* out; + QFile fptr; + bool to_cout; + QPtrList<LogMonitorInterface> monitors; + QString tmp; + QMutex mutex; + unsigned int m_filter; + AutoRotateLogJob* rotate_job; + public: + Private(Log* parent) : parent(parent),out(0),to_cout(false),rotate_job(0) + { + out = new QTextStream(); + } + + ~Private() + { + delete out; + } + + + void setFilter(unsigned int filter) + { + m_filter = filter; + } + + void rotateLogs(const QString & file) + { + if (bt::Exists(file + "-10.gz")) + bt::Delete(file + "-10.gz",true); + + // move all log files one up + for (Uint32 i = 10;i > 1;i--) + { + QString prev = QString("%1-%2.gz").arg(file).arg(i - 1); + QString curr = QString("%1-%2.gz").arg(file).arg(i); + if (bt::Exists(prev)) + bt::Move(prev,curr,true); + } + + // move current log to 1 and zip it + bt::Move(file,file + "-1",true); + system(QString("gzip " + KProcess::quote(file + "-1")).local8Bit()); + } + + void setOutputFile(const QString & file) + { + if (fptr.isOpen()) + fptr.close(); + + if (bt::Exists(file)) + rotateLogs(file); + + fptr.setName(file); + if (!fptr.open(IO_WriteOnly)) + throw Error(i18n("Cannot open log file %1 : %2").arg(file).arg(fptr.errorString())); + + out->setDevice(&fptr); + } + + void write(const QString & line) + { + tmp += line; + } + + void finishLine() + { + // only add stuff when we are not rotating the logs + // this could result in the loss of some messages + if (!rotate_job) + { + *out << QDateTime::currentDateTime().toString() << ": " << tmp << ::endl; + fptr.flush(); + if (to_cout) + std::cout << tmp.local8Bit() << std::endl; + + if (monitors.count() > 0) + { + QPtrList<LogMonitorInterface>::iterator i = monitors.begin(); + while (i != monitors.end()) + { + kt::LogMonitorInterface* lmi = *i; + lmi->message(tmp,m_filter); + i++; + } + } + } + tmp = ""; + } + + void endline() + { + finishLine(); + if (fptr.size() > MAX_LOG_FILE_SIZE && !rotate_job) + { + tmp = "Log larger then 10 MB, rotating"; + finishLine(); + QString file = fptr.name(); + fptr.close(); // close the log file + out->setDevice(0); + // start the rotate job + rotate_job = new AutoRotateLogJob(file,parent); + } + } + + void logRotateDone() + { + fptr.open(IO_WriteOnly); + out->setDevice(&fptr); + rotate_job = 0; + } + }; + + Log::Log() + { + priv = new Private(this); + } + + + Log::~Log() + { + delete priv; + } + + + void Log::setOutputFile(const QString & file) + { + priv->setOutputFile(file); + } + + void Log::addMonitor(kt::LogMonitorInterface* m) + { + priv->monitors.append(m); + } + + void Log::removeMonitor(kt::LogMonitorInterface* m) + { + priv->monitors.remove(m); + } + + void Log::setOutputToConsole(bool on) + { + priv->to_cout = on; + } + + Log & endl(Log & lg) + { + lg.priv->endline(); + lg.priv->mutex.unlock(); // unlock after end of line + return lg; + } + + Log & Log::operator << (const KURL & url) + { + priv->write(url.prettyURL()); + return *this; + } + + Log & Log::operator << (const QString & s) + { + priv->write(s); + return *this; + } + + Log & Log::operator << (const char* s) + { + priv->write(s); + return *this; + } + + Log & Log::operator << (Uint64 v) + { + return operator << (QString::number(v)); + } + + Log & Log::operator << (Int64 v) + { + return operator << (QString::number(v)); + } + + void Log::setFilter(unsigned int filter) + { + priv->setFilter(filter); + } + + void Log::lock() + { + priv->mutex.lock(); + } + + void Log::logRotateDone() + { + priv->logRotateDone(); + } + + Log & Out(unsigned int arg) + { + Log & lg = Globals::instance().getLog(arg); + lg.lock(); + return lg; + } +} diff --git a/libktorrent/util/log.h b/libktorrent/util/log.h new file mode 100644 index 0000000..2fe0ba6 --- /dev/null +++ b/libktorrent/util/log.h @@ -0,0 +1,209 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ + +#ifndef JORISLOG_H +#define JORISLOG_H + + +#include "constants.h" +#include <qstring.h> + +// LOG MESSAGES CONSTANTS +#define LOG_NONE 0x00 +#define LOG_IMPORTANT 0x01 +#define LOG_NOTICE 0x03 +#define LOG_DEBUG 0x07 +#define LOG_ALL 0x0F + +#define SYS_GEN 0x0010 // Genereral info messages +#define SYS_CON 0x0020 // Connections +#define SYS_TRK 0x0040 // Tracker +#define SYS_DHT 0x0080 // DHT +#define SYS_DIO 0x0100 // Disk IO related stuff, saving and loading of chunks ... + +//plugins +#define SYS_IPF 0x1000 // IPFilter +#define SYS_SRC 0x2000 // Search plugin +#define SYS_PNP 0x4000 // UPnP plugin +#define SYS_INW 0x8000 // InfoWidget +#define SYS_SNF 0x10000 // ScanFolder plugin +#define SYS_PFI 0x20000 // Part file import +#define SYS_SCD 0x40000 // Scheduler plugin +#define SYS_RSS 0x80000 // RSS plugin +#define SYS_WEB 0x100000 // WebInterface plugin +#define SYS_ZCO 0x200000 // ZeroConf plugin + +class KURL; + + +namespace kt +{ + class LogMonitorInterface; +} + +namespace bt +{ + + + /** + * @author Joris Guisson + * @brief Class which writes messages to a logfile + * + * This class writes messages to a logfile. To use it, create an instance, + * set the output file and write stuff with the << operator. + * + * By default all messages will also be printed on the standard output. This + * can be turned down using the @a setOutputToConsole function. + * + * There is also the possibility to monitor what is written to the log using + * the LogMonitorInterface class. + */ + class Log + { + class Private; + + Private* priv; + public: + /** + * Constructor. + */ + Log(); + + /** + * Destructor, closes the file. + */ + virtual ~Log(); + + /** + * Enable or disable the printing of log messages to the standard + * output. + * @param on Enable or disable + */ + void setOutputToConsole(bool on); + + /** + * Add a log monitor. + * @param m The log monitor + */ + void addMonitor(kt::LogMonitorInterface* m); + + /** + * Remove a log monitor. + * @param m The log monitor + */ + void removeMonitor(kt::LogMonitorInterface* m); + + /** + * Set the output logfile. + * @param file The name of the file + * @throw Exception if the file can't be opened + */ + void setOutputFile(const QString & file); + + /** + * Write a number to the log file. + * Anything which can be passed to QString::number will do. + * @param val The value + * @return This Log + */ + template <class T> + Log & operator << (T val) + { + return operator << (QString::number(val)); + } + + /** + * Apply a function to the Log. + * @param func The function + * @return This Log + */ + Log & operator << (Log & (*func)(Log & )) + { + return func(*this); + } + + + /** + * Output a QString to the log. + * @param s The QString + * @return This Log + */ + Log & operator << (const char* s); + + /** + * Output a QString to the log. + * @param s The QString + * @return This Log + */ + Log & operator << (const QString & s); + + /** + * Output a 64 bit integer to the log. + * @param v The integer + * @return This Log + */ + Log & operator << (Uint64 v); + + /** + * Output a 64 bit integer to the log. + * @param v The integer + * @return This Log + */ + Log & operator << (Int64 v); + + /** + * Prints and endline character to the Log and flushes it. + * @param lg The Log + * @return @a lg + */ + friend Log & endl(Log & lg); + + /** + * Write an URL to the file. + * @param text The KURL + * @return This Log + */ + Log & operator << (const KURL & url); + + /** + * Sets a filter for log messages. Applies only to listeners via LogMonitorInterface! + * @param filter SYS & LOG flags combined with bitwise OR. + */ + void setFilter(unsigned int filter); + + /// Lock the mutex of the log, should be called in Out() + void lock(); + + /// Called by the auto log rotate job when it has finished + void logRotateDone(); + }; + + Log & endl(Log & lg); + + + Log & Out(unsigned int arg = 0x00); + inline Log & GenOut(unsigned int arg) {return Out(SYS_GEN|arg);} + inline Log & DHTOut(unsigned int arg) {return Out(SYS_DHT|arg);} + inline Log & ConOut(unsigned int arg) {return Out(SYS_CON|arg);} + inline Log & TrkOut(unsigned int arg) {return Out(SYS_TRK|arg);} + +} + +#endif diff --git a/libktorrent/util/mmapfile.cpp b/libktorrent/util/mmapfile.cpp new file mode 100644 index 0000000..579c67a --- /dev/null +++ b/libktorrent/util/mmapfile.cpp @@ -0,0 +1,294 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <errno.h> +#include <qfile.h> +#include <kfileitem.h> +#include <kio/netaccess.h> +#include <klocale.h> +#include <util/error.h> +#include <util/log.h> +#include <torrent/globals.h> +#include "mmapfile.h" + +namespace bt +{ + + MMapFile::MMapFile() : fd(-1),data(0),size(0),file_size(0),ptr(0),mode(READ) + {} + + + MMapFile::~MMapFile() + { + if (fd > 0) + close(); + } + + bool MMapFile::open(const QString & file,Mode mode) + { +#if HAVE_STAT64 + struct stat64 sb; + stat64(QFile::encodeName(file),&sb); +#else + struct stat sb; + stat(QFile::encodeName(file),&sb); +#endif + + return open(file,mode,(Uint64)sb.st_size); + } + + bool MMapFile::open(const QString & file,Mode mode,Uint64 size) + { + // close already open file + if (fd > 0) + close(); + + // setup flags + int flag = 0,mmap_flag = 0; + switch (mode) + { + case READ: + flag = O_RDONLY; + mmap_flag = PROT_READ; + break; + case WRITE: + flag = O_WRONLY | O_CREAT; + mmap_flag = PROT_WRITE; + break; + case RW: + flag = O_RDWR | O_CREAT; + mmap_flag = PROT_READ|PROT_WRITE; + break; + } + + // Not all systems have O_LARGEFILE as an explicit flag + // (for instance, FreeBSD. Solaris does, but only if + // _LARGEFILE_SOURCE is defined in the compile). + // So OR it in if it is defined. +#ifdef O_LARGEFILE + flag |= O_LARGEFILE; +#endif + + // open the file + fd = ::open(QFile::encodeName(file) , flag);//(int)flag); + if (fd == -1) + return false; + + // read the file size + this->size = size; + this->mode = mode; + +#if HAVE_STAT64 + struct stat64 sb; + stat64(QFile::encodeName(file),&sb); +#else + struct stat sb; + stat(QFile::encodeName(file),&sb); +#endif + file_size = (Uint64)sb.st_size; + filename = file; + + // mmap the file +#if HAVE_MMAP64 + data = (Uint8*)mmap64(0, size, mmap_flag, MAP_SHARED, fd, 0); +#else + data = (Uint8*)mmap(0, size, mmap_flag, MAP_SHARED, fd, 0); +#endif + if (data == MAP_FAILED) + { + ::close(fd); + data = 0; + fd = -1; + ptr = 0; + return false; + } + ptr = 0; + return true; + } + + void MMapFile::close() + { + if (fd > 0) + { +#if HAVE_MUNMAP64 + munmap64(data,size); +#else + munmap(data,size); +#endif + ::close(fd); + ptr = size = 0; + data = 0; + fd = -1; + filename = QString::null; + } + } + + void MMapFile::flush() + { + if (fd > 0) + msync(data,size,MS_SYNC); + } + + Uint32 MMapFile::write(const void* buf,Uint32 buf_size) + { + if (fd == -1 || mode == READ) + return 0; + + // check if data fits in memory mapping + if (ptr + buf_size > size) + throw Error(i18n("Cannot write beyond end of the mmap buffer!")); + + Out() << "MMapFile::write : " << (ptr + buf_size) << " " << file_size << endl; + // enlarge the file if necessary + if (ptr + buf_size > file_size) + { + growFile(ptr + buf_size); + } + + // memcpy data + memcpy(&data[ptr],buf,buf_size); + // update ptr + ptr += buf_size; + // update file size if necessary + if (ptr >= size) + size = ptr; + + return buf_size; + } + + void MMapFile::growFile(Uint64 new_size) + { + Out() << "Growing file to " << new_size << " bytes " << endl; + Uint64 to_write = new_size - file_size; + ssize_t written; + // jump to the end of the file + lseek(fd,0,SEEK_END); + + Uint8 buf[1024]; + memset(buf,0,1024); + // write data until to_write is 0 + while (to_write > 0) + { + ssize_t w = ::write(fd,buf, to_write > 1024 ? 1024 : to_write); + if (w > 0) + to_write -= w; + else if (w < 0) + break; + } + file_size = new_size; + } + + Uint32 MMapFile::read(void* buf,Uint32 buf_size) + { + if (fd == -1 || mode == WRITE) + return 0; + + // check if we aren't going to read past the end of the file + Uint32 to_read = ptr + buf_size >= size ? size - ptr : buf_size; + // read data + memcpy(buf,data+ptr,to_read); + ptr += to_read; + return to_read; + } + + Uint64 MMapFile::seek(SeekPos from,Int64 num) + { + switch (from) + { + case BEGIN: + if (num > 0) + ptr = num; + if (ptr >= size) + ptr = size - 1; + break; + case END: + { + Int64 np = (size - 1) + num; + if (np < 0) + { + ptr = 0; + break; + } + if (np >= (Int64) size) + { + ptr = size - 1; + break; + } + ptr = np; + } + break; + case CURRENT: + { + Int64 np = ptr + num; + if (np < 0) + { + ptr = 0; + break; + } + if (np >= (Int64) size) + { + ptr = size - 1; + break; + } + ptr = np; + } + break; + } + return ptr; + } + + bool MMapFile::eof() const + { + return ptr >= size; + } + + Uint64 MMapFile::tell() const + { + return ptr; + } + + QString MMapFile::errorString() const + { + return strerror(errno); + } + + Uint64 MMapFile::getSize() const + { + return size; + } + + Uint8* MMapFile::getData(Uint64 off) + { + if (off >= size) + return 0; + return &data[off]; + } +} + diff --git a/libktorrent/util/mmapfile.h b/libktorrent/util/mmapfile.h new file mode 100644 index 0000000..ca0d782 --- /dev/null +++ b/libktorrent/util/mmapfile.h @@ -0,0 +1,146 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTMMAPFILE_H +#define BTMMAPFILE_H + + +#include <qstring.h> +#include <util/constants.h> + +namespace bt +{ + + /** + * @author Joris Guisson + * @brief Memory mapped file + * + * This class allows to access memory mapped files. It's pretty similar to + * File. + * TODO: make sure large files work (not really needed for the blocklist) + */ + class MMapFile + { + public: + MMapFile(); + virtual ~MMapFile(); + + enum Mode + { + READ,WRITE, RW + }; + /** + * Open the file. If mode is write and the file doesn't exist, it will + * be created. + * @param file Filename + * @param mode Mode (READ, WRITE or RW) + * @return true upon succes + */ + bool open(const QString & file,Mode mode); + + /** + * Open the file. If mode is write and the file doesn't exist, it will + * be created. + * @param file Filename + * @param mode Mode (READ, WRITE or RW) + * @param size Size of the memory mapping (the file will be enlarged to this value) + * @return true upon succes + */ + bool open(const QString & file,Mode mode,Uint64 size); + + /** + * Close the file. Undoes the memory mapping. + */ + void close(); + + /** + * Flush the file. + */ + void flush(); + + /** + * Write a bunch of data. + * @param buf The data + * @param size Size of the data + * @return The number of bytes written + */ + Uint32 write(const void* buf,Uint32 size); + + /** + * Read a bunch of data + * @param buf The buffer to store the data + * @param size Size of the buffer + * @return The number of bytes read + */ + Uint32 read(void* buf,Uint32 size); + + enum SeekPos + { + BEGIN, + END, + CURRENT + }; + + /** + * Seek in the file. + * @param from Position to seek from + * @param num Number of bytes to move + * @return New position + */ + Uint64 seek(SeekPos from,Int64 num); + + /// Check to see if we are at the end of the file. + bool eof() const; + + /// Get the current position in the file. + Uint64 tell() const; + + /// Get the error string. + QString errorString() const; + + /// Get the file size + Uint64 getSize() const; + + + /** + * Get a pointer to the mmapped region of data. + * @param off Offset into buffer, if invalid 0 will be returned + * @return Pointer to a location in the mmapped region + */ + Uint8* getData(Uint64 off); + + /// Gets the data pointer + void* getDataPointer() { return data; } + private: + void growFile(Uint64 new_size); + + private: + int fd; + Uint8* data; + Uint64 size; // size of mmapping + Uint64 file_size; // size of file + Uint64 ptr; + QString filename; + Mode mode; + }; + +} + + +#endif diff --git a/libktorrent/util/profiler.cpp b/libktorrent/util/profiler.cpp new file mode 100644 index 0000000..05c53bd --- /dev/null +++ b/libktorrent/util/profiler.cpp @@ -0,0 +1,138 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifdef KT_PROFILE +#include <qfile.h> +#include <qtextstream.h> +#include <sys/time.h> +#include "profiler.h" + +namespace bt +{ + Profile::Profile(Profile* parent,const QString & name) : parent(parent),name(name) + { + min = max = avg = 0.0; + count = 0; + start_time = 0.0; + children.setAutoDelete(true); + } + + Profile::~Profile() + { + } + + void Profile::start() + { + struct timeval tv; + gettimeofday(&tv,0); + start_time = tv.tv_sec * 1000.0 + tv.tv_usec * 0.001; + } + + void Profile::end() + { + struct timeval tv; + gettimeofday(&tv,0); + double end_time = tv.tv_sec * 1000.0 + tv.tv_usec * 0.001; + double d = end_time - start_time; + // update stuff + + if (d < min || count == 0) + min = d; + if (d > max || count == 0) + max = d; + + avg = (avg * count + d) / (count + 1); + count++; + } + + Profile* Profile::child(const QString & name) + { + QPtrList<Profile>::iterator i = children.begin(); + while (i != children.end()) + { + Profile* p = *i; + if (p->name == name) + return p; + i++; + } + + Profile* p = new Profile(this,name); + children.append(p); + return p; + } + + void Profile::save(QTextStream & out,const QString & base) + { + QString nb = base + "/" + name; + + out.precision(5); + out << qSetW(60) << nb << qSetW(10) << min << qSetW(10) << max << qSetW(10) << avg << qSetW(10) << count << endl; + + QPtrList<Profile>::iterator i = children.begin(); + while (i != children.end()) + { + Profile* p = *i; + p->save(out,nb); + i++; + } + } + + ///////////////////// + + Profiler Profiler::inst; + + Profiler::Profiler() : curr(0),root(0) + { + root = new Profile(0,"root"); + curr = root; + } + + + Profiler::~Profiler() + { + delete root; + } + + void Profiler::start(const QString & s) + { + curr = curr->child(s); + curr->start(); + } + + void Profiler::end() + { + curr->end(); + curr = curr->getParent(); + } + + void Profiler::saveToFile(const QString & fn) + { + QFile fptr(fn); + if (!fptr.open(IO_WriteOnly)) + return; + + QTextStream out(&fptr); + + out << qSetW(60) << "code" << qSetW(10) << "min" << qSetW(10) << "max" << qSetW(10) << "avg" << qSetW(10) << "count" << endl; + out << endl; + + root->save(out,QString::null); + } +} +#endif diff --git a/libktorrent/util/profiler.h b/libktorrent/util/profiler.h new file mode 100644 index 0000000..6ab06e7 --- /dev/null +++ b/libktorrent/util/profiler.h @@ -0,0 +1,108 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTPROFILER_H +#define BTPROFILER_H + +#ifdef KT_PROFILE +#include <qptrlist.h> +#include <util/constants.h> + +class QTextStream; + + +namespace bt +{ + /** + * Profile of one function or section of code. + */ + class Profile + { + Profile* parent; + QPtrList<Profile> children; + + QString name; + double min,max,avg; + Uint32 count; + double start_time; + public: + Profile(Profile* parent,const QString & name); + virtual ~Profile(); + + /** + * We just entered the function and will profile it. + */ + void start(); + + /** + * We just left the function, internal variables will now be updated + */ + void end(); + + /** + * Get a child, if it doesn't exist it will be created. + * @param name The name of the child + * @return The child + */ + Profile* child(const QString & name); + + /** + * Get the parent of the current profile. + */ + Profile* getParent() const {return parent;} + + /** + * Save profile information to a file. + * @param out Text stream to write to + * @param base Base path of the profiles + */ + void save(QTextStream & out,const QString & base); + }; + + /** + * @author Joris Guisson <[email protected]> + * + * Class used to profile ktorrent + */ + class Profiler + { + Profile* curr; + Profile* root; + + static Profiler inst; + + Profiler(); + public: + virtual ~Profiler(); + + void start(const QString & s); + void end(); + void saveToFile(const QString & fn); + + static Profiler & instance() {return inst;} + }; +} +#define KT_PROF_START(S) bt::Profiler::instance().start(S) +#define KT_PROF_END() bt::Profiler::instance().end() +#else +#define KT_PROF_START(S) +#define KT_PROF_END() +#endif + +#endif diff --git a/libktorrent/util/ptrmap.cpp b/libktorrent/util/ptrmap.cpp new file mode 100644 index 0000000..28a4340 --- /dev/null +++ b/libktorrent/util/ptrmap.cpp @@ -0,0 +1,24 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 "ptrmap.h" + + + + diff --git a/libktorrent/util/ptrmap.h b/libktorrent/util/ptrmap.h new file mode 100644 index 0000000..36e1c20 --- /dev/null +++ b/libktorrent/util/ptrmap.h @@ -0,0 +1,181 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTPTRMAP_H +#define BTPTRMAP_H + +#include <map> + +namespace bt +{ + /** + * @author Joris Guisson + * @brief Map of pointers + * + * A Map where the data is a pointer. The PtrMap has an autodeletion feature. + * When autodelete is on, every time we remove something from the map, the data + * will be deleted. + */ + template <class Key,class Data> + class PtrMap + { + bool autodel; + std::map<Key,Data*> pmap; + public: + /** + * Constructor. + * @param auto_del Wether or not to enable auto deletion + */ + PtrMap(bool autodel = false) : autodel(autodel) + {} + + /** + * Destructor. Will delete all objects, if auto deletion is on. + */ + virtual ~PtrMap() + { + clear(); + } + + + /** + * Return the number of key data pairs in the map. + */ + unsigned int count() const {return pmap.size();} + + /** + * Enable or disable auto deletion. + * @param yes Enable if true, disable if false + */ + void setAutoDelete(bool yes) + { + autodel = yes; + } + + typedef typename std::map<Key,Data*>::iterator iterator; + typedef typename std::map<Key,Data*>::const_iterator const_iterator; + + iterator begin() {return pmap.begin();} + iterator end() {return pmap.end();} + + const_iterator begin() const {return pmap.begin();} + const_iterator end() const {return pmap.end();} + + /** + * Remove all objects, will delete them if autodelete is on. + */ + void clear() + { + if (autodel) + { + for (iterator i = pmap.begin();i != pmap.end();i++) + { + delete i->second; + i->second = 0; + } + } + pmap.clear(); + } + + /** + * Insert a key data pair. + * @param k The key + * @param d The data + * @param overwrite Wether or not to overwrite + * @return true if the insertion took place + */ + bool insert(const Key & k,Data* d,bool overwrite = true) + { + iterator itr = pmap.find(k); + if (itr != pmap.end()) + { + if (overwrite) + { + if (autodel) + delete itr->second; + itr->second = d; + return true; + } + else + { + return false; + } + } + else + { + pmap[k] = d; + return true; + } + } + + /** + * Find a key in the map and returns it's data. + * @param k The key + * @return The data of the key, 0 if the key isn't in the map + */ + Data* find(const Key & k) + { + iterator i = pmap.find(k); + return (i == pmap.end()) ? 0 : i->second; + } + + /** + * Find a key in the map and returns it's data. + * @param k The key + * @return The data of the key, 0 if the key isn't in the map + */ + const Data* find(const Key & k) const + { + const_iterator i = pmap.find(k); + return (i == pmap.end()) ? 0 : i->second; + } + + /** + * Check to see if a key is in the map. + * @param k The key + * @return true if it is part of the map + */ + bool contains(const Key & k) const + { + const_iterator i = pmap.find(k); + return i != pmap.end(); + } + + /** + * Erase a key from the map. Will delete + * the data if autodelete is on. + * @param key The key + * @return true if an erase took place + */ + bool erase(const Key & key) + { + iterator i = pmap.find(key); + if (i == pmap.end()) + return false; + + if (autodel) + delete i->second; + pmap.erase(i); + return true; + } + }; + +} + +#endif diff --git a/libktorrent/util/sha1hash.cpp b/libktorrent/util/sha1hash.cpp new file mode 100644 index 0000000..c7b151c --- /dev/null +++ b/libktorrent/util/sha1hash.cpp @@ -0,0 +1,131 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 <qurl.h> +#include <string.h> +#include <algorithm> +#include "log.h" +#include "sha1hash.h" +#include "sha1hashgen.h" +#include "urlencoder.h" + +#include <stdio.h> + +namespace bt +{ + SHA1Hash::SHA1Hash() + { + std::fill(hash,hash+20,'\0'); + } + + SHA1Hash::SHA1Hash(const SHA1Hash & other) + { + for (int i = 0;i < 20;i++) + hash[i] = other.hash[i]; + } + + SHA1Hash::SHA1Hash(const Uint8* h) + { + memcpy(hash,h,20); + } + + + SHA1Hash::~SHA1Hash() + {} + + SHA1Hash & SHA1Hash::operator = (const SHA1Hash & other) + { + for (int i = 0;i < 20;i++) + hash[i] = other.hash[i]; + return *this; + } + + bool SHA1Hash::operator == (const SHA1Hash & other) const + { + for (int i = 0;i < 20;i++) + if (hash[i] != other.hash[i]) + return false; + + return true; + } + + SHA1Hash SHA1Hash::generate(const Uint8* data,Uint32 len) + { + SHA1HashGen hg; + + return hg.generate(data,len); + } + + QString SHA1Hash::toString() const + { + char tmp[41]; + QString fmt; + for (int i = 0;i < 20;i++) + fmt += "%02x"; + tmp[40] = '\0'; + snprintf(tmp,41,fmt.ascii(), + hash[0],hash[1],hash[2],hash[3],hash[4], + hash[5],hash[6],hash[7],hash[8],hash[9], + hash[10],hash[11],hash[12],hash[13],hash[14], + hash[15],hash[16],hash[17],hash[18],hash[19]); + return QString(tmp); + } + + QByteArray SHA1Hash::toByteArray() const + { + QByteArray arr(20); + arr.duplicate((const char*)hash,20); + return arr; + } + + QString SHA1Hash::toURLString() const + { + return URLEncoder::encode((const char*)hash,20); + } + + Log & operator << (Log & out,const SHA1Hash & h) + { + out << h.toString(); + return out; + } + + SHA1Hash operator ^ (const SHA1Hash & a,const SHA1Hash & b) + { + SHA1Hash k; + for (int i = 0;i < 20;i++) + { + k.hash[i] = a.hash[i] ^ b.hash[i]; + } + return k; + } + + bool operator < (const SHA1Hash & a,const SHA1Hash & b) + { + for (int i = 0;i < 20;i++) + { + if (a.hash[i] < b.hash[i]) + return true; + else if (a.hash[i] > b.hash[i]) + return false; + } + + return false; + } +} + diff --git a/libktorrent/util/sha1hash.h b/libktorrent/util/sha1hash.h new file mode 100644 index 0000000..a831d2d --- /dev/null +++ b/libktorrent/util/sha1hash.h @@ -0,0 +1,148 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTSHA1HASH_H +#define BTSHA1HASH_H + +#include <qcstring.h> +#include "constants.h" + +class QString; + +namespace bt +{ + class Log; + + /** + * @author Joris Guisson + * @brief Stores a SHA1 hash + * + * This class keeps track of a SHA1 hash. A SHA1 hash is a 20 byte + * array of bytes. + */ + class SHA1Hash + { + protected: + Uint8 hash[20]; + public: + /** + * Constructor, sets every byte in the hash to 0. + */ + SHA1Hash(); + + /** + * Copy constructor. + * @param other Hash to copy + */ + SHA1Hash(const SHA1Hash & other); + + /** + * Directly set the hash data. + * @param h The hash data must be 20 bytes large + */ + SHA1Hash(const Uint8* h); + + /** + * Destructor. + */ + virtual ~SHA1Hash(); + + /// Get the idx'th byte of the hash. + Uint8 operator [] (const Uint32 idx) const {return idx < 20 ? hash[idx] : 0;} + + /** + * Assignment operator. + * @param other Hash to copy + */ + SHA1Hash & operator = (const SHA1Hash & other); + + /** + * Test wether another hash is equal to this one. + * @param other The other hash + * @return true if equal, false otherwise + */ + bool operator == (const SHA1Hash & other) const; + + /** + * Test wether another hash is not equal to this one. + * @param other The other hash + * @return true if not equal, false otherwise + */ + bool operator != (const SHA1Hash & other) const {return !operator ==(other);} + + /** + * Generate an SHA1 hash from a bunch of data. + * @param data The data + * @param len Size in bytes of data + * @return The generated SHA1 hash + */ + static SHA1Hash generate(const Uint8* data,Uint32 len); + + /** + * Convert the hash to a printable string. + * @return The string + */ + QString toString() const; + + /** + * Convert the hash to a string, usable in http get requests. + * @return The string + */ + QString toURLString() const; + + /** + * Directly get pointer to the data. + * @return The data + */ + const Uint8* getData() const {return hash;} + + /** + * Function to print a SHA1Hash to the Log. + * @param out The Log + * @param h The hash + * @return out + */ + friend Log & operator << (Log & out,const SHA1Hash & h); + + + /** + * XOR two SHA1Hashes + * @param a The first hash + * @param b The second + * @return a xor b + */ + friend SHA1Hash operator ^ (const SHA1Hash & a,const SHA1Hash & b); + + /** + * Function to compare 2 hashes + * @param a The first hash + * @param h The second hash + * @return wether a is smaller then b + */ + friend bool operator < (const SHA1Hash & a,const SHA1Hash & b); + + /** + * Convert the hash to a byte array. + */ + QByteArray toByteArray() const; + }; + +} + +#endif diff --git a/libktorrent/util/sha1hashgen.cpp b/libktorrent/util/sha1hashgen.cpp new file mode 100644 index 0000000..5c0d9f5 --- /dev/null +++ b/libktorrent/util/sha1hashgen.cpp @@ -0,0 +1,340 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 <string.h> +#include <arpa/inet.h> +#include "sha1hashgen.h" +#include "functions.h" + + + +namespace bt +{ + static inline Uint32 LeftRotate(Uint32 x,Uint32 n) + { + return ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))); + } + + + + SHA1HashGen::SHA1HashGen() : tmp_len(0),total_len(0) + { + + } + + + SHA1HashGen::~SHA1HashGen() + {} + + SHA1Hash SHA1HashGen::generate(const Uint8* data,Uint32 len) + { + h0 = 0x67452301; + h1 = 0xEFCDAB89; + h2 = 0x98BADCFE; + h3 = 0x10325476; + h4 = 0xC3D2E1F0; + + Uint32 num_64_byte_chunks = len / 64; + Uint32 left_over = len % 64; + // proces regular data + for (Uint32 i = 0;i < num_64_byte_chunks;i++) + { + processChunk(data + (64*i)); + } + + // calculate the low and high byte of the data length + Uint32 total[2] = {0,0}; + total[0] += len; + total[0] &= 0xFFFFFFFF; + + if (total[0] < len) + total[1]++; + + Uint32 high = ( total[0] >> 29 ) | ( total[1] << 3 ); + Uint32 low = ( total[0] << 3 ); + + if (left_over == 0) + { + tmp[0] = 0x80; + for (Uint32 i = 1;i < 56;i++) + tmp[i] = 0; + + // put in the length as 64-bit integer (BIG-ENDIAN) + WriteUint32(tmp,56,high); + WriteUint32(tmp,60,low); + // process the padding + processChunk(tmp); + } + else if (left_over < 56) + { + Uint32 off = num_64_byte_chunks * 64; + // copy left over bytes in tmp + memcpy(tmp,data + off, left_over); + tmp[left_over] = 0x80; + for (Uint32 i = left_over + 1;i < 56;i++) + tmp[i] = 0; + + // put in the length as 64-bit integer (BIG-ENDIAN) + WriteUint32(tmp,56,high); + WriteUint32(tmp,60,low); + // process the padding + processChunk(tmp); + } + else + { + // now we need to process 2 chunks + Uint32 off = num_64_byte_chunks * 64; + // copy left over bytes in tmp + memcpy(tmp,data + off, left_over); + tmp[left_over] = 0x80; + for (Uint32 i = left_over + 1;i < 64;i++) + tmp[i] = 0; + + // process first chunk + processChunk(tmp); + + for (Uint32 i = 0;i < 56;i++) + tmp[i] = 0; + + // put in the length as 64-bit integer (BIG-ENDIAN) + WriteUint32(tmp,56,high); + WriteUint32(tmp,60,low); + // process the second chunk + processChunk(tmp); + } + + // construct final message + Uint8 hash[20]; + WriteUint32(hash,0,h0); + WriteUint32(hash,4,h1); + WriteUint32(hash,8,h2); + WriteUint32(hash,12,h3); + WriteUint32(hash,16,h4); + + return SHA1Hash(hash); + } + + + + void SHA1HashGen::processChunk(const Uint8* chunk) + { + Uint32 w[80]; + for (int i = 0;i < 80;i++) + { + if (i < 16) + { + w[i] = ntohl(*(const Uint32*)(chunk + (4*i))); + /* w[i] = (chunk[4*i] << 24) | + (chunk[4*i + 1] << 16) | + (chunk[4*i + 2] << 8) | + chunk[4*i + 3]; + */ + } + else + { + w[i] = LeftRotate(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16],1); + } + } + + Uint32 a = h0; + Uint32 b = h1; + Uint32 c = h2; + Uint32 d = h3; + Uint32 e = h4; + + for (int i = 0;i < 80;i++) + { + Uint32 f,k; + if (i < 20) + { + f = (b & c) | ((~b) & d); + k = 0x5A827999; + } + else if (i < 40) + { + f = b ^ c ^ d; + k = 0x6ED9EBA1; + } + else if (i < 60) + { + f = (b & c) | (b & d) | (c & d); + k = 0x8F1BBCDC; + } + else + { + f = b ^ c ^ d; + k = 0xCA62C1D6; + } + + Uint32 temp = LeftRotate(a,5) + f + e + k + w[i]; + e = d; + d = c; + c = LeftRotate(b,30); + b = a; + a = temp; + } + h0 = (h0 + a) & 0xffffffff; + h1 = (h1 + b) & 0xffffffff; + h2 = (h2 + c) & 0xffffffff; + h3 = (h3 + d) & 0xffffffff; + h4 = (h4 + e) & 0xffffffff; + } + + + void SHA1HashGen::start() + { + h0 = 0x67452301; + h1 = 0xEFCDAB89; + h2 = 0x98BADCFE; + h3 = 0x10325476; + h4 = 0xC3D2E1F0; + tmp_len = total_len = 0; + memset(tmp,0,64); + } + + void SHA1HashGen::update(const Uint8* data,Uint32 len) + { + if (tmp_len == 0) + { + Uint32 num_64_byte_chunks = len / 64; + Uint32 left_over = len % 64; + // proces data in chunks of 64 byte + for (Uint32 i = 0;i < num_64_byte_chunks;i++) + { + processChunk(data + (64*i)); + } + + if (left_over > 0) + { + // if there is anything left over, copy it in tmp + memcpy(tmp,data + (64 * num_64_byte_chunks),left_over); + tmp_len = left_over; + } + total_len += len; + } + else + { + + if (tmp_len + len < 64) + { + // special case, not enough of data to fill tmp completely + memcpy(tmp + tmp_len,data,len); + tmp_len += len; + total_len += len; + } + else + { + // copy start of data in tmp and process it + Uint32 off = 64 - tmp_len; + memcpy(tmp + tmp_len,data, 64 - tmp_len); + processChunk(tmp); + tmp_len = 0; + + Uint32 num_64_byte_chunks = (len - off) / 64; + Uint32 left_over = (len - off) % 64; + + for (Uint32 i = 0;i < num_64_byte_chunks;i++) + { + processChunk(data + (off + (64*i))); + } + + if (left_over > 0) + { + // if there is anything left over, copy it in tmp + memcpy(tmp,data + (off + 64 * num_64_byte_chunks),left_over); + tmp_len = left_over; + } + total_len += len; + } + } + } + + + void SHA1HashGen::end() + { + // calculate the low and high byte of the data length + Uint32 total[2] = {0,0}; + total[0] += total_len; + total[0] &= 0xFFFFFFFF; + + if (total[0] < total_len) + total[1]++; + + Uint32 high = ( total[0] >> 29 ) | ( total[1] << 3 ); + Uint32 low = ( total[0] << 3 ); + + if (tmp_len == 0) + { + tmp[0] = 0x80; + for (Uint32 i = 1;i < 56;i++) + tmp[i] = 0; + + // put in the length as 64-bit integer (BIG-ENDIAN) + WriteUint32(tmp,56,high); + WriteUint32(tmp,60,low); + // process the padding + processChunk(tmp); + } + else if (tmp_len < 56) + { + tmp[tmp_len] = 0x80; + for (Uint32 i = tmp_len + 1;i < 56;i++) + tmp[i] = 0; + + // put in the length as 64-bit integer (BIG-ENDIAN) + WriteUint32(tmp,56,high); + WriteUint32(tmp,60,low); + // process the padding + processChunk(tmp); + } + else + { + // now we need to process 2 chunks + tmp[tmp_len] = 0x80; + for (Uint32 i = tmp_len + 1;i < 56;i++) + tmp[i] = 0; + + // process first chunk + processChunk(tmp); + + for (Uint32 i = 0;i < 56;i++) + tmp[i] = 0; + + // put in the length as 64-bit integer (BIG-ENDIAN) + WriteUint32(tmp,56,high); + WriteUint32(tmp,60,low); + // process the second chunk + processChunk(tmp); + } + } + + + SHA1Hash SHA1HashGen::get() const + { + // construct final message + Uint8 hash[20]; + WriteUint32(hash,0,h0); + WriteUint32(hash,4,h1); + WriteUint32(hash,8,h2); + WriteUint32(hash,12,h3); + WriteUint32(hash,16,h4); + + return SHA1Hash(hash); + } +} diff --git a/libktorrent/util/sha1hashgen.h b/libktorrent/util/sha1hashgen.h new file mode 100644 index 0000000..08cc3ad --- /dev/null +++ b/libktorrent/util/sha1hashgen.h @@ -0,0 +1,90 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTSHA1HASHGEN_H +#define BTSHA1HASHGEN_H + +#include "constants.h" +#include "sha1hash.h" + +namespace bt +{ + + /** + * @author Joris Guisson + * + * Generates a SHA1 hash, code based on wikipedia's pseudocode + * There are 2 ways to use this class : + * - generate : all data is present from the start + * - start, update and end : data can be delivered in chunks + * + * Mixing the 2, is not a good idea + */ + class SHA1HashGen + { + Uint32 h0; + Uint32 h1; + Uint32 h2; + Uint32 h3; + Uint32 h4; + Uint8 tmp[64]; + Uint32 tmp_len; + Uint32 total_len; + public: + SHA1HashGen(); + ~SHA1HashGen(); + + /** + * Generate a hash from a bunch of data. + * @param data The data + * @param len The length + * @return The SHA1 hash + */ + SHA1Hash generate(const Uint8* data,Uint32 len); + + /** + * Start SHA1 hash generation in chunks. + */ + void start(); + + /** + * Update the hash. + * @param data The data + * @param len Length of the data + */ + void update(const Uint8* data,Uint32 len); + + + /** + * All data has been delivered, calculate the final hash. + * @return + */ + void end(); + + /** + * Get the hash generated. + */ + SHA1Hash get() const; + private: + void processChunk(const Uint8* c); + }; + +} + +#endif diff --git a/libktorrent/util/timer.cpp b/libktorrent/util/timer.cpp new file mode 100644 index 0000000..c06b728 --- /dev/null +++ b/libktorrent/util/timer.cpp @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 "timer.h" + +namespace bt +{ + + Timer::Timer() : elapsed(0) + { + last = QTime::currentTime(); + } + + Timer::Timer(const Timer & t) : last(t.last),elapsed(t.elapsed) + {} + + Timer::~Timer() + {} + + + void Timer::update() + { + QTime now = QTime::currentTime(); + + int d = last.msecsTo(now); + if (d < 0) + d = 0; + elapsed = d; + last = now; + } + + Uint32 Timer::getElapsedSinceUpdate() const + { + QTime now = QTime::currentTime(); + int d = last.msecsTo(now); + if (d < 0) + d = 0; + return d; + } + + Timer & Timer::operator = (const Timer & t) + { + last = t.last; + elapsed = t.elapsed; + return *this; + } +} diff --git a/libktorrent/util/timer.h b/libktorrent/util/timer.h new file mode 100644 index 0000000..3277185 --- /dev/null +++ b/libktorrent/util/timer.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTTIMER_H +#define BTTIMER_H + +#include <qdatetime.h> +#include "constants.h" + +namespace bt +{ + + /** + @author Joris Guisson + */ + class Timer + { + QTime last; + Uint32 elapsed; + public: + Timer(); + Timer(const Timer & t); + virtual ~Timer(); + + void update(); + Uint32 getElapsed() const {return elapsed;} + Uint32 getElapsedSinceUpdate() const; + Timer & operator = (const Timer & t); + }; + +} + +#endif diff --git a/libktorrent/util/urlencoder.cpp b/libktorrent/util/urlencoder.cpp new file mode 100644 index 0000000..c1776de --- /dev/null +++ b/libktorrent/util/urlencoder.cpp @@ -0,0 +1,92 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 "urlencoder.h" + + +namespace bt +{ + QString hex[] = { + "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", + "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f", + "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", + "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f", + "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27", + "%28", "%29", "%2a", "%2b", "%2c", "%2d", "%2e", "%2f", + "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37", + "%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f", + "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47", + "%48", "%49", "%4a", "%4b", "%4c", "%4d", "%4e", "%4f", + "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57", + "%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f", + "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67", + "%68", "%69", "%6a", "%6b", "%6c", "%6d", "%6e", "%6f", + "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77", + "%78", "%79", "%7a", "%7b", "%7c", "%7d", "%7e", "%7f", + "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87", + "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f", + "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97", + "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f", + "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7", + "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af", + "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7", + "%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf", + "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7", + "%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf", + "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", + "%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df", + "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7", + "%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef", + "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", + "%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff" + }; + + + QString URLEncoder::encode(const char* buf,Uint32 size) + { + QString res = ""; + + for (Uint32 i = 0; i < size; i++) + { + Uint8 ch = buf[i]; + if (('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z') || ('0' <= ch && ch <= '9')) + { // 'A'..'Z' + res.append((char)ch); + } + else if (ch == ' ') + { // space + res.append("%20"); + } + else if (ch == '-' || ch == '_' // unreserved + || ch == '.' || ch == '!' + || ch == '~' || ch == '*' + || ch == '\'' || ch == '(' + || ch == ')') + { + res.append((char)ch); + } + else + { // other ASCII + res.append(hex[ch]); + } + } + return res; + } + +} diff --git a/libktorrent/util/urlencoder.h b/libktorrent/util/urlencoder.h new file mode 100644 index 0000000..edac33a --- /dev/null +++ b/libktorrent/util/urlencoder.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTURLENCODER_H +#define BTURLENCODER_H + +#include <qstring.h> +#include "constants.h" + +namespace bt +{ + + /** + @author Joris Guisson + */ + class URLEncoder + { + public: + static QString encode(const char* buf,Uint32 size); + }; + +} + +#endif diff --git a/libktorrent/util/waitjob.cpp b/libktorrent/util/waitjob.cpp new file mode 100644 index 0000000..d11fa14 --- /dev/null +++ b/libktorrent/util/waitjob.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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 <torrent/globals.h> +#include <kio/netaccess.h> +#include "waitjob.h" +#include "log.h" + +namespace bt +{ + + WaitJob::WaitJob(Uint32 millis) : KIO::Job(false) + { + connect(&timer,SIGNAL(timeout()),this,SLOT(timerDone())); + timer.start(millis,true); + } + + + WaitJob::~WaitJob() + {} + + void WaitJob::kill(bool) + { + m_error = 0; + emitResult(); + } + + void WaitJob::timerDone() + { + // set the error to null and emit the result + m_error = 0; + emitResult(); + } + + void WaitJob::addExitOperation(kt::ExitOperation* op) + { + exit_ops.append(op); + connect(op,SIGNAL(operationFinished( kt::ExitOperation* )), + this,SLOT(operationFinished( kt::ExitOperation* ))); + } + + void WaitJob::operationFinished(kt::ExitOperation* op) + { + if (exit_ops.count() > 0) + { + exit_ops.remove(op); + if (op->deleteAllowed()) + op->deleteLater(); + + if (exit_ops.count() == 0) + timerDone(); + } + } + + void WaitJob::execute(WaitJob* job) + { + KIO::NetAccess::synchronousRun(job,0); + } + + void SynchronousWait(Uint32 millis) + { + Out() << "SynchronousWait" << endl; + WaitJob* j = new WaitJob(millis); + KIO::NetAccess::synchronousRun(j,0); + } + +} + +#include "waitjob.moc" + diff --git a/libktorrent/util/waitjob.h b/libktorrent/util/waitjob.h new file mode 100644 index 0000000..a85ba63 --- /dev/null +++ b/libktorrent/util/waitjob.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * [email protected] * + * * + * 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. * + ***************************************************************************/ +#ifndef BTWAITJOB_H +#define BTWAITJOB_H + +#include <qtimer.h> +#include <kio/job.h> +#include <qvaluelist.h> +#include <interfaces/exitoperation.h> +#include "constants.h" + +namespace bt +{ + + /** + * @author Joris Guisson <[email protected]> + * + * Job to wait for a certain amount of time or until one or more ExitOperation's have + * finished. + */ + class WaitJob : public KIO::Job + { + Q_OBJECT + public: + WaitJob(Uint32 millis); + virtual ~WaitJob(); + + virtual void kill(bool quietly=true); + + /** + * Add an ExitOperation; + * @param op The operation + */ + void addExitOperation(kt::ExitOperation* op); + + + /** + * Execute a WaitJob + * @param job The Job + */ + static void execute(WaitJob* job); + + /// Are there any ExitOperation's we need to wait for + bool needToWait() const {return exit_ops.count() > 0;} + + private slots: + void timerDone(); + void operationFinished(kt::ExitOperation* op); + + private: + QTimer timer; + QValueList<kt::ExitOperation*> exit_ops; + }; + + void SynchronousWait(Uint32 millis); + + + +} + +#endif |