You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdenetwork/kopete/protocols/winpopup/libwinpopup/libwinpopup.cpp

364 lines
11 KiB

/***************************************************************************
libwinpopup.cpp - WP Library
-------------------
begin : Fri Apr 26 2002
copyright : (C) 2002 by Gav Wood
email : gav@kde.org
***************************************************************************
***************************************************************************
* *
* 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 <tqdir.h>
#include <tqfileinfo.h>
#include <tqregexp.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 TQString &smbClient,int groupFreq)
: smbClientBin(smbClient), groupCheckFreq(groupFreq)
{
connect(&updateGroupDataTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotUpdateGroupData()));
updateGroupDataTimer.start(1, true);
TQTimer::singleShot(1, this, TQT_SLOT(slotStartDirLister()));
}
WinPopupLib::~WinPopupLib()
{
}
void WinPopupLib::slotStartDirLister()
{
if (checkMessageDir()) {
dirLister = new KDirLister();
dirLister->setAutoUpdate(true);
connect(dirLister, TQT_SIGNAL(newItems(const KFileItemList &)), this, TQT_SLOT(slotNewMessages(const KFileItemList &)));
connect(dirLister, TQT_SIGNAL(completed()), this, TQT_SLOT(slotListCompleted()));
dirLister->openURL(KURL::fromPathOrURL(WP_POPUP_DIR));
}
}
/**
* return the group list
*/
const TQStringList WinPopupLib::getGroups()
{
TQStringList ret;
TQMap<TQString, WorkGroup>::ConstIterator end = theGroups.end();
for(TQMap<TQString, WorkGroup>::ConstIterator i = theGroups.begin(); i != end; i++)
ret += i.key();
return ret;
}
/**
* return the host list
*/
const TQStringList WinPopupLib::getHosts(const TQString &Group)
{
return theGroups[Group].Hosts();
}
/**
* return if a host is in the host list
*/
bool WinPopupLib::checkHost(const TQString &Name)
{
// kdDebug() << "WP checkHost: " << Name << endl;
bool ret = false;
TQMap<TQString, WorkGroup>::Iterator end = theGroups.end();
for(TQMap<TQString, WorkGroup>::Iterator i = theGroups.begin(); i != end && !ret; i++) {
if ((*i).Hosts().contains(Name.upper())) {
ret = true;
break;
}
}
return ret;
}
bool WinPopupLib::checkMessageDir()
{
TQDir 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)").tqarg(WP_POPUP_DIR),
TQString::tqfromLatin1("Winpopup"), i18n("Create Directory"), i18n("Do Not Create"));
if (tmpYesNo == KMessageBox::Yes) {
TQStringList tdesuArgs = TQStringList(TQString("-c mkdir -p -m 0777 " + WP_POPUP_DIR));
if (KApplication::tdeinitExecWait("tdesu", tdesuArgs) == 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)").tqarg(WP_POPUP_DIR),
TQString::tqfromLatin1("Winpopup"), i18n("Fix"), i18n("Do Not Fix"));
if (tmpYesNo == KMessageBox::Yes) {
TQStringList tdesuArgs = TQStringList(TQString("-c chmod 0777 " + WP_POPUP_DIR));
if (KApplication::tdeinitExecWait("tdesu", tdesuArgs) == 0) return true;
}
} else {
return true;
}
}
return false;
}
/**
* read the groups and their hosts
*/
void WinPopupLib::slotUpdateGroupData()
{
passedInitialHost = false;
todo.clear();
currentGroupsMap.clear();
currentHost = TQString::tqfromLatin1("LOCALHOST");
startReadProcess(currentHost);
}
void WinPopupLib::startReadProcess(const TQString &Host)
{
currentHosts.clear();
currentGroups.clear();
currentGroup = TQString();
// for Samba 3
KProcIO *reader = new KProcIO;
*reader << smbClientBin << "-N" << "-E" << "-g" << "-L" << Host << "-";
connect(reader, TQT_SIGNAL(readReady(KProcIO *)), this, TQT_SLOT(slotReadProcessReady(KProcIO *)));
connect(reader, TQT_SIGNAL(processExited(KProcess *)), this, TQT_SLOT(slotReadProcessExited(KProcess *)));
if (!reader->start(KProcess::NotifyOnExit, true)) {
// still to come
kdDebug(14170) << "ReadProcess not started!" << endl;
}
}
void WinPopupLib::slotReadProcessReady(KProcIO *r)
{
TQString tmpLine = TQString();
TQRegExp 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 == TQString::tqfromLatin1("LOCALHOST")) currentHost = TQString::tqfromLatin1("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()) {
TQMap<TQString, WorkGroup> newGroups;
//loop through the read groups and check for new ones
TQMap<TQString, TQString>::ConstIterator end = currentGroups.end();
for (TQMap<TQString, TQString>::ConstIterator i = currentGroups.begin(); i != end; i++) {
TQString 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()) {
TQMap<TQString, TQString>::ConstIterator end = currentGroups.end();
for (TQMap<TQString, TQString>::ConstIterator i = currentGroups.begin(); i != end; i++) {
TQString groupMaster = i.data();
todo += groupMaster;
}
} else {
if (currentHost == TQString::tqfromLatin1("failed"))
KMessageBox::error(Kopete::UI::Global::mainWidget(),
i18n("Connection to localhost failed!\n"
"Is your samba server running?"),
TQString::tqfromLatin1("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, TQT_SIGNAL(completed()), this, TQT_SLOT(slotListCompleted()));
readMessages(dirLister->items());
}
void WinPopupLib::slotNewMessages(const KFileItemList &items)
{
readMessages(items);
}
/**
* read new arrived messages
*/
void WinPopupLib::readMessages(const KFileItemList &items)
{
TQPtrListIterator<KFileItem> it(items);
KFileItem *tmpItem;
while ((tmpItem = it.current()) != 0) {
if (tmpItem->isFile()) {
TQFile messageFile(tmpItem->url().path());
if (messageFile.open(IO_ReadOnly)) {
TQTextStream stream(&messageFile);
TQString sender;
TQDateTime time;
TQString text;
// first line is sender, can this really be empty? GF
sender = stream.readLine();
sender = sender.upper();
// second line is time
TQString tmpTime = stream.readLine();
time = TQDateTime::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()) {
// TQFile::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)"),
TQString::tqfromLatin1("Winpopup"), i18n("Fix"), i18n("Do Not Fix"));
if (tmpYesNo == KMessageBox::Yes) {
TQStringList tdesuArgs = TQStringList(TQString("-c chmod 0666 " + tmpItem->url().path()));
if (KApplication::tdeinitExecWait("tdesu", tdesuArgs) == 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 TQString &Body, const TQString &Destination)
{
KProcess *sender = new KProcess(this);
*sender << smbClientBin << "-M" << Destination;
*sender << "-N" << "-";
connect(sender, TQT_SIGNAL(processExited(KProcess *)), this, TQT_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 TQString &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;