summaryrefslogtreecommitdiffstats
path: root/libktorrent/util
diff options
context:
space:
mode:
Diffstat (limited to 'libktorrent/util')
-rw-r--r--libktorrent/util/Makefile.am18
-rw-r--r--libktorrent/util/array.cpp27
-rw-r--r--libktorrent/util/array.h73
-rw-r--r--libktorrent/util/autorotatelogjob.cpp88
-rw-r--r--libktorrent/util/autorotatelogjob.h59
-rw-r--r--libktorrent/util/bitset.cpp111
-rw-r--r--libktorrent/util/bitset.h157
-rw-r--r--libktorrent/util/constants.h96
-rw-r--r--libktorrent/util/error.cpp33
-rw-r--r--libktorrent/util/error.h44
-rw-r--r--libktorrent/util/file.cpp150
-rw-r--r--libktorrent/util/file.h114
-rw-r--r--libktorrent/util/fileops.cpp466
-rw-r--r--libktorrent/util/fileops.h165
-rw-r--r--libktorrent/util/functions.cpp239
-rw-r--r--libktorrent/util/functions.h72
-rw-r--r--libktorrent/util/httprequest.cpp122
-rw-r--r--libktorrent/util/httprequest.h98
-rw-r--r--libktorrent/util/log.cpp249
-rw-r--r--libktorrent/util/log.h209
-rw-r--r--libktorrent/util/mmapfile.cpp294
-rw-r--r--libktorrent/util/mmapfile.h146
-rw-r--r--libktorrent/util/profiler.cpp138
-rw-r--r--libktorrent/util/profiler.h108
-rw-r--r--libktorrent/util/ptrmap.cpp24
-rw-r--r--libktorrent/util/ptrmap.h181
-rw-r--r--libktorrent/util/sha1hash.cpp131
-rw-r--r--libktorrent/util/sha1hash.h148
-rw-r--r--libktorrent/util/sha1hashgen.cpp340
-rw-r--r--libktorrent/util/sha1hashgen.h90
-rw-r--r--libktorrent/util/timer.cpp64
-rw-r--r--libktorrent/util/timer.h49
-rw-r--r--libktorrent/util/urlencoder.cpp92
-rw-r--r--libktorrent/util/urlencoder.h40
-rw-r--r--libktorrent/util/waitjob.cpp86
-rw-r--r--libktorrent/util/waitjob.h78
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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 <joris.guisson@gmail.com>
+
+ 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 <joris.guisson@gmail.com>
+ *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 *
+ * joris.guisson@gmail.com *
+ * *
+ * 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 <joris.guisson@gmail.com>
+ *
+ * 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