/*************************************************************************** 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)").arg(WP_POPUP_DIR), TQString::fromLatin1("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 (TDEApplication::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)").arg(WP_POPUP_DIR), TQString::fromLatin1("Winpopup"), i18n("Fix"), i18n("Do Not Fix")); if (tmpYesNo == KMessageBox::Yes) { TQStringList tdesuArgs = TQStringList(TQString("-c chmod 0777 " + WP_POPUP_DIR)); if (TDEApplication::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::fromLatin1("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(TDEProcess *)), this, TQT_SLOT(slotReadProcessExited(TDEProcess *))); if (!reader->start(TDEProcess::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::fromLatin1("LOCALHOST")) currentHost = TQString::fromLatin1("failed"); // to be sure } } } void WinPopupLib::slotReadProcessExited(TDEProcess *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::fromLatin1("failed")) KMessageBox::error(Kopete::UI::Global::mainWidget(), i18n("Connection to localhost failed!\n" "Is your samba server running?"), TQString::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, 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::fromLatin1("Winpopup"), i18n("Fix"), i18n("Do Not Fix")); if (tmpYesNo == KMessageBox::Yes) { TQStringList tdesuArgs = TQStringList(TQString("-c chmod 0666 " + tmpItem->url().path())); if (TDEApplication::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) { TDEProcess *sender = new TDEProcess(this); *sender << smbClientBin << "-M" << Destination; *sender << "-N" << "-"; connect(sender, TQT_SIGNAL(processExited(TDEProcess *)), this, TQT_SLOT(slotSendProcessExited(TDEProcess *))); if (sender->start(TDEProcess::NotifyOnExit, TDEProcess::Stdin)) { sender->writeStdin(Body.local8Bit(), Body.local8Bit().length()); if (!sender->closeStdin()) { delete sender; } } else { delete sender; } } void WinPopupLib::slotSendProcessExited(TDEProcess *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;