svn copy of qmonitor draft
authorMarkus Bröker <mbroeker@largo.homelinux.org>
Sat, 13 Dec 2008 15:45:18 +0100
changeset 0 826dd5531eb0
child 1 9de88b525a59
svn copy of qmonitor
PacketParser.cpp
PacketReader.cpp
PacketWriter.cpp
build
debian/README.Debian
debian/changelog
debian/compat
debian/control
debian/copyright
debian/dirs
debian/rules
images/icon.png
images/sideBar.png
include/PacketParser.h
include/PacketReader.h
include/PacketWriter.h
include/monitor.h
include/readerthread.h
include/tools.h
include/version.h
main.cpp
man/man1/qMonitor.1
monitor.cpp
post-install
readerthread.cpp
tools.cpp
new file mode 100644
--- /dev/null
+++ b/PacketParser.cpp
@@ -0,0 +1,179 @@
+/*
+ *  $Id: PacketParser.cpp 54 2008-01-10 00:24:52Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/PacketParser.cpp $
+ */
+
+#include <PacketParser.h>
+#include <iomanip>
+
+PacketParser::PacketParser (int tm)
+:PacketReader (tm)
+{
+    protocol = IPPROTO_IP;
+    port = 0;
+}
+
+PacketParser::PacketParser (std::string filename)
+:  PacketReader (filename)
+{
+    protocol = IPPROTO_IP;
+    port = 0;
+}
+
+PacketParser::~PacketParser ()
+{
+}
+
+std::string PacketParser::getProtocol (int i)
+{
+    proto = getprotobynumber (i);
+    return ((proto != NULL) ? proto->p_name : "unknown");
+}
+
+std::string PacketParser::getPacket ()
+{
+    if (port != 0)
+        if ((sport != port) && (dport != port))
+            return "";
+
+    return str;
+}
+
+void PacketParser::setPort (unsigned short p)
+{
+    port = p;
+}
+
+void PacketParser::setProtocol (int proto)
+{
+    protocol = proto;
+}
+
+std::string PacketParser::read ()
+{
+    std::ostringstream s;
+    struct iphdr *iph;
+    struct tcphdr *tcph;
+    struct udphdr *udph;
+
+    struct in_addr src;
+    struct in_addr dst;
+
+    int size = 0;
+
+    uint i;
+
+    str = PacketReader::read ();
+
+    iph = (struct iphdr *)(str.c_str () + sizeof (struct ethhdr));
+
+    switch (iph->protocol) {
+    case IPPROTO_TCP:
+        size = sizeof (tcphdr);
+        break;
+    case IPPROTO_UDP:
+        size = sizeof (udphdr);
+        break;
+    case IPPROTO_ICMP:
+        size = sizeof (icmphdr);
+        break;
+    case IPPROTO_IP:
+        size += (sizeof (ethhdr) + sizeof (iphdr));
+        break;
+    default:
+        size += (sizeof (ethhdr) + sizeof (iphdr));
+    }
+
+    src.s_addr = (iph->saddr);
+    dst.s_addr = (iph->daddr);
+
+    dhost = inet_ntoa (dst);
+    shost = inet_ntoa (src);
+
+    s.str () = "";
+
+    if (protocol != iph->protocol) {
+        switch (protocol) {
+        case IPPROTO_IP:
+            /*
+             * filter the content later
+             */
+            break;
+
+        case IPPROTO_RAW:
+            for (i = size; i < str.length (); i++) {
+                if (!isgraph (str[i]))
+                    s << ".";
+                else
+                    s << str[i];
+            }
+            return s.str ();
+            break;
+        default:
+            /*
+             * discard packet
+             */
+            return s.str ();
+        }
+    }
+
+    switch (iph->protocol) {
+    case IPPROTO_IP:
+        s << getProtocol (iph->protocol) << " " << std::setw (15) << shost << " ==> " << std::setw (15) << dhost;
+        break;
+
+    case IPPROTO_ICMP:
+        s << getProtocol (iph->protocol) << " " << std::setw (15) << shost << " ==> " << std::setw (15) << dhost;
+
+        break;
+
+    case IPPROTO_TCP:
+        tcph = (struct tcphdr *)(str.c_str () + sizeof (struct ethhdr) + sizeof (struct iphdr));
+
+        sport = ntohs (tcph->source);
+        dport = ntohs (tcph->dest);
+
+        s << getProtocol (iph->protocol) << " "
+            << std::setw (15) << shost << ":" << std::setw (5) << sport
+            << " ==> " << std::setw (15) << dhost << ":" << std::setw (5) << dport;
+
+        if (tcph->urg)
+            s << (" urg ");
+        if (tcph->ack) {
+            s << (" ack ") << ntohl (tcph->ack_seq);
+        }
+        if (tcph->psh)
+            s << (" psh ");
+        if (tcph->rst)
+            s << (" rst ");
+        if (tcph->syn) {
+            s << (" syn ") << ntohl (tcph->seq);
+        }
+        if (tcph->fin)
+            s << (" fin ");
+
+        break;
+
+    case IPPROTO_UDP:
+        udph = (struct udphdr *)(str.c_str () + sizeof (struct ethhdr) + sizeof (struct iphdr));
+
+        sport = ntohs (udph->source);
+        dport = ntohs (udph->dest);
+
+        s << getProtocol (iph->protocol) << " "
+            << std::setw (15) << shost << ":" << std::setw (5) << sport
+            << " ==> " << std::setw (15) << dhost << ":" << std::setw (5) << dport;
+
+        break;
+
+    default:
+        s << getProtocol (iph->protocol);
+        break;
+    }
+
+    if (port != 0)
+        if ((sport != port) && (dport != port))
+            s.str ("");
+
+    return (s.str ());
+}
new file mode 100644
--- /dev/null
+++ b/PacketReader.cpp
@@ -0,0 +1,63 @@
+/*
+ *  $Id: PacketReader.cpp 54 2008-01-10 00:24:52Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/PacketReader.cpp $
+ */
+
+#include <PacketReader.h>
+
+PacketReader::PacketReader (int tm)
+{
+    timeout = tm;
+
+    if ((p_socket = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) == -1) {
+        perror ("SocketException");
+        throw std::runtime_error ("SocketException: root access required");
+    }
+}
+
+PacketReader::PacketReader (std::string filename)
+{
+    if ((p_socket = open (filename.c_str (), O_RDONLY)) == -1) {
+        throw std::runtime_error ("FileException");
+    }
+
+    timeout = -1;
+}
+
+PacketReader::~PacketReader ()
+{
+    close (p_socket);
+}
+
+std::string PacketReader::read ()
+{
+    static char s[IP_MAXPACKET + 1];
+    int c;
+
+    c =::read (p_socket, s, IP_MAXPACKET);
+    s[c] = 0;
+    return std::string (s, c);
+}
+
+bool PacketReader::ready ()
+{
+    if (p_socket)
+        return true;
+
+    return false;
+}
+
+bool PacketReader::dataAvailable ()
+{
+    pollfd fdin;
+    int event = 1;
+
+    fdin.fd = p_socket;
+    fdin.events = POLLIN;
+    fdin.revents = 0;
+
+    if (poll (&fdin, event, timeout) > 0)
+        return true;
+
+    return false;
+}
new file mode 100644
--- /dev/null
+++ b/PacketWriter.cpp
@@ -0,0 +1,48 @@
+/*
+ *  $Id: PacketWriter.cpp 54 2008-01-10 00:24:52Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/PacketWriter.cpp $
+ */
+
+#include <PacketWriter.h>
+
+extern "C" {
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+} PacketWriter::PacketWriter (char *hostname, int port)
+{
+    unsigned int size;
+    unsigned int fd;
+    struct hostent *host = gethostbyname (hostname);
+
+    if (host == NULL) {
+        perror ("GETHOSTBYNAME");
+        exit (0);
+    }
+
+    ca.sin_family = PF_INET;
+    ca.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
+    ca.sin_port = htons (port);
+
+    size = sizeof (ca);
+    fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    p_socket = connect (fd, (sockaddr *) & ca, size);
+}
+
+PacketWriter::~PacketWriter ()
+{
+    close (p_socket);
+}
+
+void PacketWriter::write (char s[], int len)
+{
+    int c;
+
+    c =::write (p_socket, s, len);
+}
+
+bool PacketWriter::ready ()
+{
+    return true;
+}
new file mode 100755
--- /dev/null
+++ b/build
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# This works for qmake version 4.x and fails for qmake version 3 !
+# 
+
+rm -rf .moc .obj Makefile
+find -name *~ -exec rm -f {} \;
+
+rm -f *.o
+qmake-qt4 -project .ui
+qmake-qt4 -makefile
+
+make all
+
+if [ ! -f /etc/gentoo-release ]
+then
+	./post-install;
+else
+	echo "Skipping post-install, handled by ebuild";
+fi
+
new file mode 100644
--- /dev/null
+++ b/debian/README.Debian
@@ -0,0 +1,6 @@
+qmonitor for Debian
+-------------------
+
+<possible notes regarding this package - if none, delete this file>
+
+ -- Markus Broeker <mbroeker@largo.homelinux.org>  Fri, 07 Mar 2008 00:36:15 +0100
new file mode 100644
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,6 @@
+qmonitor (0.10-1) unstable; urgency=low
+
+  * Initial release (Closes: #nnnn)  <nnnn is the bug number of your ITP>
+
+ -- Markus Broeker <mbroeker@largo.homelinux.org>  Fri, 07 Mar 2008 00:36:15 +0100
+
new file mode 100644
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1,1 @@
+5
new file mode 100644
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,12 @@
+Source: qmonitor
+Section: net
+Priority: extra
+Maintainer: Markus Broeker <mbroeker@largo.homelinux.org>
+Build-Depends: debhelper (>= 5)
+Standards-Version: 3.7.2
+
+Package: qmonitor
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: qmonitor is a full featured network sniffer
+ qmonitor is a network sniffer written in qt
new file mode 100644
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,24 @@
+This package was debianized by Markus Broeker <mbroeker@largo.homelinux.org> on
+Fri, 07 Mar 2008 00:36:15 +0100.
+
+It was downloaded from <url://example.com>
+
+Upstream Author(s): 
+
+    <put author's name and email here>
+    <likewise for another author>
+
+Copyright: 
+
+    <Copyright (C) YYYY Name OfAuthor>
+    <likewise for another author>
+
+License:
+
+    <Put the license of the package here indented by 4 spaces>
+
+The Debian packaging is (C) 2008, Markus Broeker <mbroeker@largo.homelinux.org> and
+is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
+
+# Please also look if there are files or directories which have a
+# different copyright/license attached and list them here.
new file mode 100644
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1,2 @@
+usr/share/icons
+usr/share/pixmaps
new file mode 100755
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,93 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+
+
+
+configure: configure-stamp
+configure-stamp:
+	dh_testdir
+	# Add here commands to configure the package.
+
+	touch configure-stamp
+
+
+build: build-stamp
+
+build-stamp: configure-stamp 
+	dh_testdir
+
+	# Add here commands to compile the package.
+	./build
+	#docbook-to-man debian/qmonitor.sgml > qmonitor.1
+
+	touch $@
+
+clean:
+	dh_testdir
+	dh_testroot
+	rm -f build-stamp configure-stamp
+
+	# Add here commands to clean up after the build process.
+	if [ -f Makefile ]; then $(MAKE) distclean; fi
+	rm -f qmonitor qmonitor-0.10.pro
+	dh_clean 
+
+install: build
+	dh_testdir
+	dh_testroot
+	dh_clean -k 
+	dh_installdirs
+
+	# Add here commands to install the package into debian/qmonitor.
+	mv qmonitor-0 qmonitor
+	install -d debian/qmonitor/usr/sbin/
+	install qmonitor debian/qmonitor/usr/sbin/
+	./post-install;
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+	dh_testdir
+	dh_testroot
+	dh_installchangelogs 
+	dh_installdocs
+	dh_installexamples
+#	dh_install
+#	dh_installmenu
+#	dh_installdebconf	
+#	dh_installlogrotate
+#	dh_installemacsen
+#	dh_installpam
+#	dh_installmime
+#	dh_python
+#	dh_installinit
+#	dh_installcron
+#	dh_installinfo
+	dh_installman
+	dh_link
+	dh_strip
+	dh_compress
+	dh_fixperms
+#	dh_perl
+#	dh_makeshlibs
+	dh_installdeb
+	dh_shlibdeps
+	dh_gencontrol
+	dh_md5sums
+	dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dc313bc91d62d9771051782bf19d1f4fac0d141c
GIT binary patch
literal 214
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Y)RhkE)4%caKYZ?lYt_f1s;*b
z3=G`DAk4@xYmNj^kiEpy*OmP`BdfTuUM}M@S)h<?iEBiObAE1aYF-J0b5UwyNotBh
zd1gt5LP$ocg1e`0!21-{JfK1=PZ!4!jq}M{^7fo`;7UkR5S*~4k@cKa(DF9-xxSZm
zOL$K#%3!#uQ}wHHf%%HW!vbGTxE=W~*nVVWIQoTOQ|+|tPoOCbp00i_>zopr0BFQN
Ang9R*
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..18d1764872ae89f5c35f9a9f22313b00239e74cc
GIT binary patch
literal 11300
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
a=>G!?Fhzt4b=1WG0000<MNUMnLSTYriyc7#
new file mode 100644
--- /dev/null
+++ b/include/PacketParser.h
@@ -0,0 +1,46 @@
+/*
+ *  $Id: PacketParser.h 2 2007-12-22 14:15:30Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/include/PacketParser.h $
+ */
+
+#ifndef PACKET_PARSER
+#define PACKET_PARSER
+
+#include <PacketReader.h>
+#include <sstream>
+#include <iomanip>
+#include <tools.h>
+
+extern "C" {
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_icmp.h>
+}
+
+class PacketParser : public PacketReader
+{
+ public:
+	PacketParser ( int tm=500 );
+	PacketParser ( std::string );
+	~PacketParser ();
+	std::string read();
+	std::string getPacket();
+	void setPort(unsigned short);
+	void setProtocol(int);
+	std::string getProtocol(int);
+
+ private:
+	std::string str;
+	int protocol;
+	unsigned short port;
+
+	std::string shost;
+	std::string dhost;
+	unsigned short sport, dport;
+	struct protoent *proto;
+};
+
+#endif
+
new file mode 100644
--- /dev/null
+++ b/include/PacketReader.h
@@ -0,0 +1,37 @@
+/*
+ *  $Id: PacketReader.h 2 2007-12-22 14:15:30Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/include/PacketReader.h $
+ */
+
+#ifndef PacketReader_H
+#define PacketReader_H
+
+#include <string>
+#include <stdexcept>
+#include <iostream>
+
+extern "C" {
+	#include <sys/socket.h>
+	#include <netinet/if_ether.h>
+	#include <netinet/ip.h>
+	#include <sys/poll.h>
+	#include <fcntl.h>
+	#include <sys/types.h>
+	#include <unistd.h>
+};
+
+class PacketReader {
+protected:
+	int p_socket;
+ private:
+	int timeout;
+public:
+	PacketReader ( int tm = 500 );
+	PacketReader ( std::string );
+	~PacketReader();
+	std::string read();
+	bool ready();
+	bool dataAvailable();
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/include/PacketWriter.h
@@ -0,0 +1,28 @@
+/*
+ *  $Id: PacketWriter.h 2 2007-12-22 14:15:30Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/include/PacketWriter.h $
+ */
+
+#ifndef PACKETWRITER_H
+#define PACKETWRITER_H 0x20053008
+#include <PacketReader.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+class PacketWriter : PacketReader {
+private:
+	struct sockaddr_in ca;
+
+public:
+	PacketWriter(char *, int);
+	~PacketWriter();
+
+	void write(char *s, int);
+	bool ready();
+};
+
+#endif
+
new file mode 100644
--- /dev/null
+++ b/include/monitor.h
@@ -0,0 +1,38 @@
+/*
+ *  $Id: monitor.h 2 2007-12-22 14:15:30Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/include/monitor.h $
+ */
+
+#ifndef MONITOR_H
+#define MONITOR_H
+
+#include <readerthread.h>
+#include <qevent.h>
+#include "../ui_monitor.h"
+
+class readerThread;
+
+class Monitor : public QWidget, private Ui::qMonitor
+{
+	Q_OBJECT
+
+    public:
+	Monitor(QWidget *parent = 0);
+	virtual ~Monitor();
+	int getPort();
+	int getProtocol();
+
+ protected:
+	virtual void customEvent( QEvent* );
+	std::map<QString, int> Protocol;
+
+ private:
+	readerThread *reader;
+
+     public slots:
+	virtual void startCapture();
+	virtual void stopCapture();
+
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/include/readerthread.h
@@ -0,0 +1,40 @@
+/*
+ *  $Id: readerthread.h 2 2007-12-22 14:15:30Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/include/readerthread.h $
+ */
+
+#ifndef READERTHREAD_H
+#define READERTHREAD_H
+
+#include "monitor.h"
+#include <qthread.h>
+#include <qevent.h>
+#include "PacketParser.h"
+
+#define MSG_EVENT 65432
+
+class Monitor;
+
+class DataChangeEvent : public QEvent {
+ public:
+	DataChangeEvent(QString msg_)
+		: QEvent((QEvent::Type)MSG_EVENT)
+		{
+			msg = msg_;
+
+		}
+
+	QString Text() const { return msg; }
+ private:
+	QString msg;
+};
+
+class readerThread : public QThread {
+ public:
+	readerThread(Monitor*);
+	virtual void run();
+ private:
+	Monitor *handle;
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/include/tools.h
@@ -0,0 +1,13 @@
+/*
+ *  $Id: tools.h 2 2007-12-22 14:15:30Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/include/tools.h $
+ */
+
+#ifndef TOOLS_H
+#define TOOLS_H
+
+#include <sstream>
+
+std::string itoa(const int& i);
+
+#endif
new file mode 100644
--- /dev/null
+++ b/include/version.h
@@ -0,0 +1,11 @@
+/*
+ *  $Id: version.h 2 2007-12-22 14:15:30Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/include/version.h $
+ */
+
+#ifndef VERSION_H
+#define VERSION_H
+
+#define VERSION_STRING "qMonitor Revision 0.90"
+#endif
+
new file mode 100644
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,41 @@
+/*
+ *  $Id: main.cpp 54 2008-01-10 00:24:52Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/main.cpp $
+ */
+
+#include <QApplication>
+
+#include "include/monitor.h"
+#include <version.h>
+
+int main (int argc, char *argv[])
+{
+    int i;
+
+    while ((i = getopt (argc, argv, "hv")) >= 0) {
+        switch (i) {
+        case 'h':
+            std::cout << "Usage: " << argv[0] << " [OPTIONS]" << std::endl;
+            std::cout << "qMonitor displays the online traffic." << std::endl << std::endl;
+            std::cout << "Options:" << std::endl << std::endl;
+            std::cout << "-h: \t\t\tShow this help" << std::endl;
+            std::cout << "-v: \t\t\tShow Version" << std::endl;
+
+            exit (0);
+            break;
+        case 'v':
+            std::cout << VERSION_STRING << std::endl;
+            exit (0);
+            break;
+
+        default:
+            ;
+        }
+    }
+
+    QApplication app (argc, argv);
+    Monitor *dialog = new Monitor;
+
+    dialog->show ();
+    return app.exec ();
+}
new file mode 100644
--- /dev/null
+++ b/man/man1/qMonitor.1
@@ -0,0 +1,14 @@
+.\" qMonitor.1
+.TH qMonitor 1 "Feb. 2005" "Markus Broeker"
+.SH Name
+qMonitor \- Ein qt-basierender Netzwerkmonitor
+.SH SYNTAX
+qMonitor
+.SH BESCHREIBUNG
+.fi
+Der auf qt-basierende Netzwerkmonitor \fBqMonitor\fR zeigt ihnen den 
+Traffic im Netz an.
+.nf
+.SH AUTOR
+Markus Broker ( broeker.markus@freenet.de )
+
new file mode 100644
--- /dev/null
+++ b/monitor.cpp
@@ -0,0 +1,104 @@
+/*
+ *  $Id: monitor.cpp 54 2008-01-10 00:24:52Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/monitor.cpp $
+ */
+
+#include "include/monitor.h"
+#include "include/readerthread.h"
+
+#ifndef ICON_PATH
+#define ICON_PATH "/usr/share/icons/qMonitor_icon.png"
+#endif
+
+#define HTML_MESSAGE \
+"<p align='center'><h1>qMonitor</h1><br></p>" \
+"<p align='center'>" \
+"<li>W&auml;hlen Sie das Protokoll</li>" \
+"<li>W&auml;hlen Sie einen Port (0=ALLE)</li>" \
+"<li>Dr&uuml;cken Sie Start</li>" \
+"<br><br>" \
+"<h5>Dieses Programm zeigt den Traffic im Netz an und unterst&uuml;tzt Sie bei t&auml;glichen Aufgaben:</h5><br><br>" \
+"<li>Kontrolle der TCP/UDP Verbindungen</li>" \
+"<li>&Uuml;berwachung von textbasierten Serverdiensten</li>" \
+"<li>Protokollanalyse</li>" \
+"</p>"
+
+Monitor::Monitor (QWidget * parent)
+{
+    setupUi ((QDialog *) this);
+    textEdit->setReadOnly (true);
+
+    listWidget1->insertItem (0, "TCP");
+    listWidget1->insertItem (1, "UDP");
+    listWidget1->insertItem (2, "ICMP");
+    listWidget1->insertItem (3, "RAW");
+    listWidget1->insertItem (4, "IP");
+
+    Protocol["TCP"] = IPPROTO_TCP;
+    Protocol["UDP"] = IPPROTO_UDP;
+    Protocol["ICMP"] = IPPROTO_ICMP;
+    Protocol["RAW"] = IPPROTO_RAW;
+    Protocol["IP"] = IPPROTO_IP;
+
+    listWidget1->setCurrentRow (0);
+    lineEdit1->setText ("0");
+
+    setWindowIcon (QPixmap (ICON_PATH));
+
+    textEdit->insertHtml (HTML_MESSAGE);
+
+    try {
+        reader = new readerThread (this);
+    }
+    catch (std::exception const &e) {
+        textEdit->append (e.what ());
+        reader = NULL;
+    }
+
+    connect (pushButton1, SIGNAL (clicked ()), this, SLOT (startCapture ()));
+    connect (pushButton2, SIGNAL (clicked ()), this, SLOT (stopCapture ()));
+
+}
+
+Monitor::~Monitor ()
+{
+    if (reader != NULL)
+        delete reader;
+}
+
+void Monitor::startCapture ()
+{
+    textEdit->clear ();
+
+    if (reader != NULL) {
+        if (!reader->isRunning ())
+            reader->start (QThread::NormalPriority);
+    }
+}
+
+void Monitor::stopCapture ()
+{
+    if (reader != NULL) {
+        if (reader->isRunning ())
+            reader->terminate ();
+    }
+}
+
+int Monitor::getProtocol ()
+{
+    return Protocol[listWidget1->item (listWidget1->currentRow ())->text ()];
+}
+
+int Monitor::getPort ()
+{
+    return lineEdit1->text ().toInt ();
+}
+
+void Monitor::customEvent (QEvent * e)
+{
+    if (e->type () == MSG_EVENT) {
+        DataChangeEvent *me = (DataChangeEvent *) e;
+
+        textEdit->append (me->Text ());
+    }
+}
new file mode 100755
--- /dev/null
+++ b/post-install
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+PDIRECTORY=/usr/share/pixmaps
+IDIRECTORY=/usr/share/icons
+
+FILE=qMonitor_sideBar.png
+ICON=qMonitor_icon.png
+
+echo -n "Checking, whether ${PDIRECTORY} exists...                      [ "
+if [ ! -d ${PDIRECTORY} ]
+then
+	install -d ${PDIRECTORY};
+	echo "creating ]";
+else 
+	echo "yes ]";
+fi
+
+echo -n "Checking, whether ${PDIRECTORY}/${FILE} exists... [ "
+if [ ! -r ${PDIRECTORY}/${FILE} ]
+then
+	install -m 644 images/sideBar.png \
+		${PDIRECTORY}/${FILE};
+	echo "installing ]"
+	else
+		echo "yes ]";
+fi
+
+echo -n "Checking, whether ${IDIRECTORY} exists...                        [ "
+if [ ! -d ${IDIRECTORY} ]
+then
+	install -d ${IDIRECTORY};
+	echo "creating ]";
+else 
+	echo "yes ]";
+fi
+
+echo -n "Checking, whether ${IDIRECTORY}/${ICON} exists...      [ "
+if [ ! -r ${IDIRECTORY}/${ICON} ]
+then
+	install -m 644 images/icon.png \
+		${IDIRECTORY}/${ICON};
+	echo "installing ]"
+	else
+		echo "yes ]";
+fi
new file mode 100644
--- /dev/null
+++ b/readerthread.cpp
@@ -0,0 +1,41 @@
+/*
+ *  $Id: readerthread.cpp 54 2008-01-10 00:24:52Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/readerthread.cpp $
+ */
+
+#include "include/readerthread.h"
+#include <exception>
+
+readerThread::readerThread (Monitor * parent)
+{
+    handle = parent;
+}
+
+void readerThread::run ()
+{
+    std::string s;
+    DataChangeEvent *dce;
+
+    try {
+        PacketParser reader (-1);
+
+        for (;;) {
+            while (reader.dataAvailable ()) {
+                reader.setProtocol (handle->getProtocol ());
+                reader.setPort (handle->getPort ());
+
+                s = reader.read ();
+
+                if (s != "") {
+                    dce = new DataChangeEvent (s.c_str ());
+                    QApplication::postEvent ((QObject *) handle, (QEvent *) dce);
+                }
+            }
+        }
+    }
+    catch (std::exception const &e) {
+        dce = new DataChangeEvent (e.what ());
+        QApplication::postEvent ((QObject *) handle, (QEvent *) dce);
+        std::cerr << e.what () << std::endl;
+    }
+}
new file mode 100644
--- /dev/null
+++ b/tools.cpp
@@ -0,0 +1,15 @@
+/*
+ *  $Id: tools.cpp 54 2008-01-10 00:24:52Z mbroeker $
+ * $URL: http://localhost/svn/cpp/qMonitor/trunk/tools.cpp $
+ */
+
+#include <tools.h>
+
+std::string itoa (const int &i)
+{
+    std::stringstream o;
+
+    if (!(o << i))
+        return "ERROR";
+    return o.str ();
+}