diff options
Diffstat (limited to 'kopete/protocols/winpopup/libwinpopup')
-rw-r--r-- | kopete/protocols/winpopup/libwinpopup/Makefile.am | 9 | ||||
-rw-r--r-- | kopete/protocols/winpopup/libwinpopup/libwinpopup.cpp | 363 | ||||
-rw-r--r-- | kopete/protocols/winpopup/libwinpopup/libwinpopup.h | 92 |
3 files changed, 464 insertions, 0 deletions
diff --git a/kopete/protocols/winpopup/libwinpopup/Makefile.am b/kopete/protocols/winpopup/libwinpopup/Makefile.am new file mode 100644 index 00000000..e9c5836e --- /dev/null +++ b/kopete/protocols/winpopup/libwinpopup/Makefile.am @@ -0,0 +1,9 @@ +METASOURCES = AUTO + +noinst_LTLIBRARIES = libwinpopup.la +AM_CPPFLAGS = $(KOPETE_INCLUDES) \ + -I$(srcdir)/..\ + $(all_includes) + +libwinpopup_la_SOURCES = libwinpopup.cpp + diff --git a/kopete/protocols/winpopup/libwinpopup/libwinpopup.cpp b/kopete/protocols/winpopup/libwinpopup/libwinpopup.cpp new file mode 100644 index 00000000..d26e461c --- /dev/null +++ b/kopete/protocols/winpopup/libwinpopup/libwinpopup.cpp @@ -0,0 +1,363 @@ +/*************************************************************************** + libwinpopup.cpp - WP Library + ------------------- + begin : Fri Apr 26 2002 + copyright : (C) 2002 by Gav Wood + email : [email protected] + *************************************************************************** + + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +// QT Includes +#include <qdir.h> +#include <qfileinfo.h> +#include <qregexp.h> + +// KDE Includes +#include <kapplication.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kdirlister.h> + +// Kopete Includes +#include "kopeteuiglobal.h" + +// Local Includes +#include "libwinpopup.h" + +WinPopupLib::WinPopupLib(const QString &smbClient,int groupFreq) + : smbClientBin(smbClient), groupCheckFreq(groupFreq) +{ + connect(&updateGroupDataTimer, SIGNAL(timeout()), this, SLOT(slotUpdateGroupData())); + + updateGroupDataTimer.start(1, true); + QTimer::singleShot(1, this, SLOT(slotStartDirLister())); +} + +WinPopupLib::~WinPopupLib() +{ +} + +void WinPopupLib::slotStartDirLister() +{ + if (checkMessageDir()) { + dirLister = new KDirLister(); + dirLister->setAutoUpdate(true); + connect(dirLister, SIGNAL(newItems(const KFileItemList &)), this, SLOT(slotNewMessages(const KFileItemList &))); + connect(dirLister, SIGNAL(completed()), this, SLOT(slotListCompleted())); + dirLister->openURL(KURL::fromPathOrURL(WP_POPUP_DIR)); + } +} + +/** + * return the group list + */ +const QStringList WinPopupLib::getGroups() +{ + QStringList ret; + QMap<QString, WorkGroup>::ConstIterator end = theGroups.end(); + for(QMap<QString, WorkGroup>::ConstIterator i = theGroups.begin(); i != end; i++) + ret += i.key(); + + return ret; +} + +/** + * return the host list + */ +const QStringList WinPopupLib::getHosts(const QString &Group) +{ + return theGroups[Group].Hosts(); +} + +/** + * return if a host is in the host list + */ +bool WinPopupLib::checkHost(const QString &Name) +{ +// kdDebug() << "WP checkHost: " << Name << endl; + bool ret = false; + + QMap<QString, WorkGroup>::Iterator end = theGroups.end(); + for(QMap<QString, WorkGroup>::Iterator i = theGroups.begin(); i != end && !ret; i++) { + if ((*i).Hosts().contains(Name.upper())) { + ret = true; + break; + } + } + + return ret; +} + + +bool WinPopupLib::checkMessageDir() +{ + QDir dir(WP_POPUP_DIR); + if (! dir.exists()) { + int tmpYesNo = KMessageBox::warningYesNo(Kopete::UI::Global::mainWidget(), + i18n("Working directory %1 does not exist.\n" + "If you have not configured anything yet (samba) please see\n" + "Install Into Samba (Configure... -> Account -> Edit) information\n" + "on how to do this.\n" + "Should the directory be created? (May need root password)").arg(WP_POPUP_DIR), + QString::fromLatin1("Winpopup"), i18n("Create Directory"), i18n("Do Not Create")); + if (tmpYesNo == KMessageBox::Yes) { + QStringList kdesuArgs = QStringList(QString("-c mkdir -p -m 0777 " + WP_POPUP_DIR)); + if (KApplication::kdeinitExecWait("kdesu", kdesuArgs) == 0) return true; + } + } else { + KFileItem tmpFileItem = KFileItem(KFileItem::Unknown, KFileItem::Unknown, KURL::fromPathOrURL(WP_POPUP_DIR)); + mode_t tmpPerms = tmpFileItem.permissions(); + + if (tmpPerms != 0777) { + + kdDebug(14170) << "Perms not ok!" << endl; + + int tmpYesNo = KMessageBox::warningYesNo(Kopete::UI::Global::mainWidget(), + i18n("Permissions of the working directory " + "%1 are wrong!\n" + "You will not receive messages if you say no.\n" + "You can also correct it manually (chmod 0777 %1) and restart kopete.\n" + "Fix? (May need root password)").arg(WP_POPUP_DIR), + QString::fromLatin1("Winpopup"), i18n("Fix"), i18n("Do Not Fix")); + if (tmpYesNo == KMessageBox::Yes) { + QStringList kdesuArgs = QStringList(QString("-c chmod 0777 " + WP_POPUP_DIR)); + if (KApplication::kdeinitExecWait("kdesu", kdesuArgs) == 0) return true; + } + } else { + return true; + } + } + + return false; +} + +/** + * read the groups and their hosts + */ +void WinPopupLib::slotUpdateGroupData() +{ + passedInitialHost = false; + todo.clear(); + currentGroupsMap.clear(); + currentHost = QString::fromLatin1("LOCALHOST"); + startReadProcess(currentHost); +} + +void WinPopupLib::startReadProcess(const QString &Host) +{ + currentHosts.clear(); + currentGroups.clear(); + currentGroup = QString(); + + // for Samba 3 + KProcIO *reader = new KProcIO; + *reader << smbClientBin << "-N" << "-E" << "-g" << "-L" << Host << "-"; + + connect(reader, SIGNAL(readReady(KProcIO *)), this, SLOT(slotReadProcessReady(KProcIO *))); + connect(reader, SIGNAL(processExited(KProcess *)), this, SLOT(slotReadProcessExited(KProcess *))); + + if (!reader->start(KProcess::NotifyOnExit, true)) { + // still to come + kdDebug(14170) << "ReadProcess not started!" << endl; + } +} + +void WinPopupLib::slotReadProcessReady(KProcIO *r) +{ + QString tmpLine = QString::null; + QRegExp group("^Workgroup\\|(.*)\\|(.*)$"), host("^Server\\|(.*)\\|(.*)$"), + info("^Domain=\\[([^\\]]+)\\] OS=\\[([^\\]]+)\\] Server=\\[([^\\]]+)\\]"), + error("Connection.*failed"); + + while (r->readln(tmpLine) > -1) { + if (info.search(tmpLine) != -1) currentGroup = info.cap(1); + if (host.search(tmpLine) != -1) currentHosts += host.cap(1); + if (group.search(tmpLine) != -1) currentGroups[group.cap(1)] = group.cap(2); + if (error.search(tmpLine) != -1) { + kdDebug(14170) << "Connection to " << currentHost << " failed!" << endl; + if (currentHost == QString::fromLatin1("LOCALHOST")) currentHost = QString::fromLatin1("failed"); // to be sure + } + } +} + +void WinPopupLib::slotReadProcessExited(KProcess *r) +{ + delete r; + + // Drop the first cycle - it's only the initial search host, + // the next round are the real masters. GF + + if (passedInitialHost) { + + // move currentHost from todo to done + todo.remove(currentHost); + done += currentHost; + + if (!currentGroups.isEmpty()) { + QMap<QString, WorkGroup> newGroups; + //loop through the read groups and check for new ones + QMap<QString, QString>::ConstIterator end = currentGroups.end(); + for (QMap<QString, QString>::ConstIterator i = currentGroups.begin(); i != end; i++) { + QString groupMaster = i.data(); + if (!done.contains(groupMaster)) todo += groupMaster; + } + } + + if (!currentGroup.isEmpty() && !currentHosts.isEmpty()) { + // create a workgroup object and put the hosts in + WorkGroup nWG; + nWG.addHosts(currentHosts); + + currentGroupsMap.insert(currentGroup, nWG, true); + } + + } else { + passedInitialHost = true; + if (!currentGroups.isEmpty()) { + QMap<QString, QString>::ConstIterator end = currentGroups.end(); + for (QMap<QString, QString>::ConstIterator i = currentGroups.begin(); i != end; i++) { + QString groupMaster = i.data(); + todo += groupMaster; + } + } else { + if (currentHost == QString::fromLatin1("failed")) + KMessageBox::error(Kopete::UI::Global::mainWidget(), + i18n("Connection to localhost failed!\n" + "Is your samba server running?"), + QString::fromLatin1("Winpopup")); + } + } + + // maybe restart cycle + if (todo.count()) { + currentHost = todo[0]; + startReadProcess(currentHost); + } else { + theGroups = currentGroupsMap; + updateGroupDataTimer.start(groupCheckFreq * 1000, true); + } +} + +void WinPopupLib::slotListCompleted() +{ + /// only to check received messages during start up, then we use newItems. GF + disconnect(dirLister, SIGNAL(completed()), this, SLOT(slotListCompleted())); + readMessages(dirLister->items()); +} + +void WinPopupLib::slotNewMessages(const KFileItemList &items) +{ + readMessages(items); +} + +/** + * read new arrived messages + */ +void WinPopupLib::readMessages(const KFileItemList &items) +{ + QPtrListIterator<KFileItem> it(items); + KFileItem *tmpItem; + while ((tmpItem = it.current()) != 0) { + if (tmpItem->isFile()) { + QFile messageFile(tmpItem->url().path()); + + if (messageFile.open(IO_ReadOnly)) { + QTextStream stream(&messageFile); + QString sender; + QDateTime time; + QString text; + + // first line is sender, can this really be empty? GF + sender = stream.readLine(); + sender = sender.upper(); + + // second line is time + QString tmpTime = stream.readLine(); + time = QDateTime::fromString(tmpTime, Qt::ISODate); + + while (!stream.atEnd()) { + text.append(stream.readLine()); + text.append('\n'); + } + + // remove trailing CR + text = text.stripWhiteSpace(); + + messageFile.close(); + + // delete file + if (!messageFile.remove()) { + // QFile::remove() seems to be very persistent, it removes even files with 0444 owned by root + // if the directory permissions are 0777 - so this is just for safety. GF + kdDebug(14170) << "Message file not removed - how that?" << endl; + int tmpYesNo = KMessageBox::warningYesNo(Kopete::UI::Global::mainWidget(), + i18n("A message file could not be removed; " + "maybe the permissions are wrong.\n" + "Fix? (May need root password)"), + QString::fromLatin1("Winpopup"), i18n("Fix"), i18n("Do Not Fix")); + if (tmpYesNo == KMessageBox::Yes) { + QStringList kdesuArgs = QStringList(QString("-c chmod 0666 " + tmpItem->url().path())); + if (KApplication::kdeinitExecWait("kdesu", kdesuArgs) == 0) { + if (!messageFile.remove()) + KMessageBox::error(Kopete::UI::Global::mainWidget(), i18n("Still cannot remove it; please fix manually.")); + } + } + } + if (!sender.isEmpty() && time.isValid()) + emit signalNewMessage(text, time, sender); + else + kdDebug(14170) << "Received invalid message!" << endl; + } + } // isFile + ++it; + } // while +} + +/** + * send a message + */ +void WinPopupLib::sendMessage(const QString &Body, const QString &Destination) +{ + KProcess *sender = new KProcess(this); + *sender << smbClientBin << "-M" << Destination; + *sender << "-N" << "-"; + + connect(sender, SIGNAL(processExited(KProcess *)), this, SLOT(slotSendProcessExited(KProcess *))); + + if (sender->start(KProcess::NotifyOnExit, KProcess::Stdin)) { + sender->writeStdin(Body.local8Bit(), Body.local8Bit().length()); + if (!sender->closeStdin()) { + delete sender; + } + } else { + delete sender; + } +} + +void WinPopupLib::slotSendProcessExited(KProcess *p) +{ +// emit sendJobDone(p->pid()); + delete p; +} + +void WinPopupLib::settingsChanged(const QString &smbClient, int groupFreq) +{ + smbClientBin = smbClient; + groupCheckFreq = groupFreq; + + if (updateGroupDataTimer.isActive()) updateGroupDataTimer.changeInterval(groupCheckFreq * 1000); +} + +#include "libwinpopup.moc" + +// vim: set noet ts=4 sts=4 sw=4: +// kate: tab-width 4; indent-width 4; replace-trailing-space-save on; diff --git a/kopete/protocols/winpopup/libwinpopup/libwinpopup.h b/kopete/protocols/winpopup/libwinpopup/libwinpopup.h new file mode 100644 index 00000000..77f8b8a6 --- /dev/null +++ b/kopete/protocols/winpopup/libwinpopup/libwinpopup.h @@ -0,0 +1,92 @@ +/*************************************************************************** + libwinpopup.h - Base class for the WinPopup protocol + ------------------- + begin : Fri Apr 26 2002 + copyright : (C) 2002 by Gav Wood + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef LIBWINPOPUP_H +#define LIBWINPOPUP_H + +//QT includes +#include <qobject.h> +#include <qmap.h> +#include <qstringlist.h> +#include <qtimer.h> +#include <qdatetime.h> + +// KDE Includes +#include <kprocio.h> +#include <kfileitem.h> + +const QString WP_POPUP_DIR = QString::fromLatin1("/var/lib/winpopup"); + +class KDirLister; + +typedef QMap<QString, QString> stringMap; + +class WorkGroup +{ + QStringList groupHosts; + +public: + const QStringList &Hosts() { return groupHosts; } + void addHosts(const QStringList &newHosts) { groupHosts = newHosts; } +}; + +class WinPopupLib : public QObject +{ + Q_OBJECT + +public: + WinPopupLib(const QString &smbClient,int groupFreq); + ~WinPopupLib(); + + const QStringList getGroups(); + const QStringList getHosts(const QString &Group); + bool checkHost(const QString &Name); + void settingsChanged(const QString &smbClient, int groupFreq); + void sendMessage(const QString &Body, const QString &Destination); + +private: + bool passedInitialHost; + QMap<QString, WorkGroup> theGroups, currentGroupsMap; + QString currentGroup, currentHost; + QStringList todo, done, currentHosts; + stringMap currentGroups; + QTimer updateGroupDataTimer; + QString smbClientBin; + int groupCheckFreq; + KDirLister *dirLister; + + void readMessages(const KFileItemList &items); + bool checkMessageDir(); + +private slots: + void slotUpdateGroupData(); + void startReadProcess(const QString &Host); + void slotReadProcessReady(KProcIO *r); + void slotReadProcessExited(KProcess *r); + void slotSendProcessExited(KProcess *p); + void slotStartDirLister(); + void slotListCompleted(); + void slotNewMessages(const KFileItemList &items); + +signals: + void signalNewMessage(const QString &, const QDateTime &, const QString &); +}; + +#endif + +// vim: set noet ts=4 sts=4 sw=4: +// kate: tab-width 4; indent-width 4; replace-trailing-space-save on; |