/********************************************************************** The IO DCC Window $$Id$$ Display DCC progress, etc. This in the future should be expanded. **********************************************************************/ #include "ioDCC.h" #include "ksircprocess.h" #include "displayMgr.h" #include "control_message.h" #include <kdebug.h> #include <tdelocale.h> #include <kpassivepopup.h> #include <tqregexp.h> extern DisplayMgr *displayMgr; KSircIODCC::KSircIODCC(KSircProcess *_proc) : TQObject(), KSircMessageReceiver(_proc) { proc = _proc; setBroadcast(FALSE); mgr = new dccTopLevel(0x0, "dccTopLevel Manager"); displayMgr->newTopLevel(mgr, FALSE); displayMgr->setCaption(mgr, proc->serverName() + i18n(" DCC Controller")); connect(mgr->mgr(), TQ_SIGNAL(dccConnectClicked(dccItem *)), this, TQ_SLOT(dccConnectClicked(dccItem *))); connect(mgr->mgr(), TQ_SIGNAL(dccResumeClicked(dccItem *)), this, TQ_SLOT(dccResumeClicked(dccItem *))); connect(mgr->mgr(), TQ_SIGNAL(dccRenameClicked(dccItem *)), this, TQ_SLOT(dccRenameClicked(dccItem *))); connect(mgr->mgr(), TQ_SIGNAL(dccAbortClicked(dccItem *)), this, TQ_SLOT(dccAbortClicked(dccItem *))); connect(mgr->mgr(), TQ_SIGNAL(outputLine(TQCString)), this, TQ_SIGNAL(outputLine(TQCString))); } KSircIODCC::~KSircIODCC() { // displayMgr->removeTopLevel(mgr); if(mgr) delete (dccTopLevel *) mgr; } void KSircIODCC::sirc_receive(TQCString str, bool ) { if(!mgr) return; // Parse the string to find out what type it is. // Note the order here. // Most people tend to receive files, so let's // parse the byte xfered messages first since there's lot's of them. // The we get lots of send bytexfer messages so parse them second. // Then we look at the one time start/stop messages. They only arrive // once in a long long time (compared to the byte messages) so if it takes // a few extra clock cycles to find them, who cares? if(str.find("DCC GET read:", 0) != -1){ /*fold01*/ TQRegExp rx("read: (.+) who: (.+) bytes: (.*)"); if(rx.search(str)){ TQString key = TQString("%1/%2").arg(rx.cap(1)).arg(rx.cap(2)); uint bytesXfer = rx.cap(3).toUInt(); // // Only update the display for 1% intervals. // LastSize + 1%Size must be less than the total xfered bytes. // if(DCCGetItems[key]){ DCCGetItems[key]->setReceivedBytes(bytesXfer/1024); } } } else if(str.find("DCC SEND write:", 0) != -1){ /*fold01*/ TQRegExp rx("write: (.+) who: (.+) bytes: (.*)"); if(rx.search(str)){ TQString key = TQString("%1/%2").arg(rx.cap(1)).arg(rx.cap(2)); uint bytesXfer = rx.cap(3).toUInt(); if(DCCSendItems[key]){ DCCSendItems[key]->setReceivedBytes(bytesXfer/1024); } } } else if(str.find("INBOUND DCC SEND", 0) != -1){ /*FOLD01*/ TQRegExp rx("who: (.+) file: (.+) size: (.*) ip: (.+) port: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); TQString size = rx.cap(3); TQString ip = rx.cap(4); //TQSTring port = rx.cap(5); int fileSize = size.toInt(); // Bytes per step fileSize /= 1024; // setup dcc dialog displayMgr->show(mgr); dccItem *it = mgr->mgr()->newGetItem(filename, who, dccItem::dccGotOffer, fileSize); connect(it, TQ_SIGNAL(itemRenamed(dccItem *, TQString, TQString)), this, TQ_SLOT(dccRenameDone(dccItem *, TQString, TQString))); it->setWhoPostfix("(" + ip + ")"); TQString key = TQString("%1/%2").arg(filename).arg(who); if(DCCGetItems[key]){ /* * don't add duplicates, this cuases real headaches * for both us and the user. */ TQString renamed; dccItem *old = DCCGetItems.take(key); int i; for(i = 0; i <= (int) DCCGetItems.count()+1; i++){ renamed = TQString("%1 (finished %2)/%3").arg(filename).arg(i+1).arg(old->who()); if( DCCGetItems[renamed] == 0x0) break; } old->changeFilename(TQString("%1 (finished %2)").arg(filename).arg(i+1)); DCCGetItems.insert(renamed, it); } DCCGetItems.insert(key, it); } else { kdDebug(5008) << "DCC SEND was unable to parse: " << str << endl; } } else if(str.find("Sent DCC SEND", 0) != -1){ /*FOLD01*/ TQRegExp rx("who: (.+) file: (.+) size: (.*)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); TQString size = rx.cap(3); int fileSize = size.toInt(); // Bytes per step fileSize /= 1024; // setup dcc dialog displayMgr->show(mgr); dccItem *it = mgr->mgr()->newSendItem(filename, who, dccItem::dccSentOffer, fileSize); TQString key = TQString("%1/%2").arg(filename).arg(who); if(DCCSendItems[key]){ /* * don't add duplicates, this cuases real headaches * for both us and the user. * We can get these on repeated sends or old files, * just renamed them, their finished anyways */ TQString renamed; dccItem *old = DCCSendItems.take(key); int i; for(i = 0; i <= (int) DCCSendItems.count()+1; i++){ renamed = TQString("%1 (sent %2)/%3").arg(filename).arg(i+1).arg(old->who()); if( DCCSendItems[renamed] == 0x0) break; } old->changeFilename(TQString("%1 (sent %2)").arg(filename).arg(i+1)); DCCSendItems.insert(renamed, it); } DCCSendItems.insert(key, it); } else { kdDebug(5008) << "DCC SENT was unable to parse: " << str << endl; } } else if(str.find("DCC CHAT OFFERED", 0) != -1){ /*FOLD01*/ TQRegExp rx("who: (.+) ip: (.+) port: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString ip = rx.cap(2); TQString port = rx.cap(3); // setup dcc dialog displayMgr->show(mgr); dccItem *it = mgr->mgr()->newChatItem(who, dccItem::dccGotOffer); connect(it, TQ_SIGNAL(itemRenamed(dccItem *, TQString, TQString)), this, TQ_SLOT(dccRenameDone(dccItem *, TQString, TQString))); it->setWhoPostfix("(" + ip + ")"); DCCChatItems.insert(who, it); } else { kdDebug(5008) << "DCC CHAT SEND was unable to parse: " << str << endl; } } else if(str.find("DCC CHAT SEND", 0) != -1){ /*FOLD01*/ TQRegExp rx("who: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); // setup dcc dialog displayMgr->show(mgr); dccItem *it = mgr->mgr()->newChatItem(who, dccItem::dccSentOffer); connect(it, TQ_SIGNAL(itemRenamed(dccItem *, TQString, TQString)), this, TQ_SLOT(dccRenameDone(dccItem *, TQString, TQString))); DCCChatItems.insert(who, it); } else { kdDebug(5008) << "DCC CHAT SEND was unable to parse: " << str << endl; } } else if(str.find("DCC SEND terminated") != -1){ /*FOLD01*/ TQRegExp rx("who: (.+) file: (.+) reason: (.*)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); TQString error = rx.cap(3); enum dccItem::dccStatus status = dccItem::dccDone; if(error == "CLOSE"){ status = dccItem::dccCancel; } if(error != "OK"){ status = dccItem::dccError; KPassivePopup::message(i18n("DCC SEND with %1 for %2 failed because of %3").arg(who).arg(filename).arg(error), mgr->mgr()); } TQString key = TQString("%1/%2").arg(filename).arg(who); if(DCCSendItems[key]){ kdDebug(5008) << "SendPercent: " << DCCSendItems[key]->getPercent() << endl; if((status == dccItem::dccDone) && (DCCSendItems[key]->getPercent() < 100)) status = dccItem::dccError; DCCSendItems[key]->changeStatus(status); } } } else if(str.find ("DCC GET terminated") != -1){ /*fold01*/ kdDebug(5008) << "Term: " << str << endl; TQRegExp rx("who: (.+) file: (.+) reason: (.*)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); TQString error = rx.cap(3); enum dccItem::dccStatus status = dccItem::dccDone; if(error != "OK"){ status = dccItem::dccError; KPassivePopup::message(i18n("DCC GET with %1 for %2 failed because of %3").arg(who).arg(filename).arg(error), mgr->mgr()); } TQString key = TQString("%1/%2").arg(filename).arg(who); if(DCCGetItems[key]){ kdDebug(5008) << "GetPercent: " << DCCGetItems[key]->getPercent() << endl; if((status == dccItem::dccDone) && (DCCGetItems[key]->getPercent() < 100)) status = dccItem::dccError; DCCGetItems[key]->changeStatus(status); } } else { kdDebug(5008) << "DCC Get term failed to parse: " << str << endl; } } else if(str.find("DCC GET resumed") != -1){ /*fold01*/ TQRegExp rx("who: (.+) file: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); TQString key = TQString("%1/%2").arg(filename).arg(who); if(DCCGetItems[key]){ dccItem *it = DCCGetItems[key]; kdDebug(5008) << "Got DCC GET resumed message..." << it->file() << endl; if(it->status() == dccItem::dccWaitOnResume) dccConnectClicked(it); it->changeStatus(dccItem::dccResumed); } } } else if(str.find("DCC SEND resumed") != -1){ /*fold01*/ TQRegExp rx("who: (.+) file: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); TQString key = TQString("%1/%2").arg(filename).arg(who); if(DCCSendItems[key]){ DCCSendItems[key]->changeStatus(dccItem::dccResumed); } } } else if(str.find("DCC GET established") != -1){ /*fold01*/ TQRegExp rx("who: (.+) file: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); TQString key = TQString("%1/%2").arg(filename).arg(who); if(DCCGetItems[key]){ DCCGetItems[key]->changeStatus(dccItem::dccRecving); } } } else if(str.find("DCC SEND established") != -1){ /*fold01*/ TQRegExp rx("who: (.+) file: (.+) ip: (\\S+)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); TQString ip = rx.cap(3); TQString key = TQString("%1/%2").arg(filename).arg(who); if(DCCSendItems[key]){ DCCSendItems[key]->setWhoPostfix("(" + ip + ")"); DCCSendItems[key]->changeStatus(dccItem::dccSending); } } } else if(str.find("DCC CHAT established") != -1){ /*FOLD01*/ TQRegExp rx("who: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); if(DCCChatItems[who]){ DCCChatItems[who]->changeStatus(dccItem::dccOpen); proc->new_toplevel(KSircChannel(proc->serverName(), TQString("=") + who.lower())); } } } else if(str.find("DCC CHAT inbound established") != -1){ /*FOLD01*/ TQRegExp rx("who: (.+) ip: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString ip = rx.cap(2); if(DCCChatItems[who]){ DCCChatItems[who]->setWhoPostfix("(" + ip + ")"); DCCChatItems[who]->changeStatus(dccItem::dccOpen); proc->new_toplevel(KSircChannel(proc->serverName(), TQString("=") + who.lower())); } } } else if(str.find("DCC GET failed") != -1){ /*fold01*/ TQRegExp rx("who: (.+) file: (.+) reason: (.*)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); TQString error = rx.cap(3); TQString key = TQString("%1/%2").arg(filename).arg(who); if(DCCGetItems[key]){ DCCGetItems[key]->changeStatus(dccItem::dccError); } KPassivePopup::message(i18n("DCC Get with %1 for %2 failed because of %3").arg(who).arg(filename).arg(error), mgr->mgr()); } } else if(str.find("DCC CHAT failed") != -1){ /*FOLD01*/ TQRegExp rx("who: (.+) reason: (.*)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString error = rx.cap(2); if(DCCChatItems[who]){ DCCChatItems[who]->changeStatus(dccItem::dccError); } KPassivePopup::message(i18n("DCC Chat with %1 failed because of %2").arg(who).arg(error), mgr->mgr()); } } else if(str.find("DCC CHAT renamed") != -1){ /*FOLD01*/ TQRegExp rx("who: (.+) to: (.+)"); if(rx.search(str)){ TQString oldwho = rx.cap(1); TQString newwho = rx.cap(2); TQString oldwin = "=" + oldwho; if(proc->getWindowList().find(oldwin)){ proc->getWindowList().find(oldwin)->control_message(CHANGE_CHANNEL,TQString("=" +newwho).lower()); } } } else if(str.find("Closing DCC GET") != -1){ /*fold01*/ TQRegExp rx("who: (.+) file: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); TQString key = TQString("%1/%2").arg(filename).arg(who); if(DCCGetItems[key]){ DCCGetItems[key]->changeStatus(dccItem::dccCancel); } } } // else if(str.find("Closing DCC SEND") != -1){ /*FOLD01*/ // TQRegExp rx("who: (.+) file: (.+)"); // if(rx.search(str)){ // TQString who = rx.cap(1); // TQString filename = rx.cap(2); // TQString key = TQString("%1/%2").arg(filename).arg(who); // if(DCCSendItems[key]){ // DCCSendItems[key]->changeStatus(dccItem::dccCancel); // } // } // } else if(str.find("Closing DCC CHAT") != -1){ /*fold01*/ TQRegExp rx("who: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); if(DCCChatItems[who]){ DCCChatItems[who]->changeStatus(dccItem::dccDone); } } } else if(str.find("No DCC SEND") != -1){ /*fold01*/ TQRegExp rx("who: (.+) file: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); //TQString key = TQString("%1/%2").arg(filename).arg(who); TQPtrList<dccItem> toDel; TQDict<dccItem> new_list; TQDictIterator<dccItem> it( DCCSendItems ); for(;it.current(); ++it){ if((it.current()->who() == who) && (it.current()->file() == filename) ){ toDel.append(it.current()); } else { new_list.insert(it.currentKey(), it.current()); } } DCCSendItems = new_list; toDel.setAutoDelete(true); toDel.clear(); } } else if(str.find("No DCC GET") != -1){ /*fold01*/ TQRegExp rx("who: (.+) file: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); TQString filename = rx.cap(2); TQPtrList<dccItem> toDel; TQDict<dccItem> new_list; TQDictIterator<dccItem> it( DCCGetItems ); for(;it.current(); ++it){ if((it.current()->who() == who) && (it.current()->file() == filename) ){ toDel.append(it.current()); } else { new_list.insert(it.currentKey(), it.current()); } } DCCGetItems = new_list; toDel.setAutoDelete(true); toDel.clear(); } } else if(str.find("No DCC CHAT") != -1){ /*fold01*/ TQRegExp rx("who: (.+)"); if(rx.search(str)){ TQString who = rx.cap(1); TQPtrList<dccItem> toDel; TQDict<dccItem> new_list; TQDictIterator<dccItem> it( DCCChatItems ); for(;it.current(); ++it){ if(it.current()->who() == who){ toDel.append(it.current()); } else { new_list.insert(it.currentKey(), it.current()); } } DCCChatItems = new_list; toDel.setAutoDelete(true); toDel.clear(); } } else{ /*FOLD01*/ proc->getWindowList()["!default"]->sirc_receive(str); } } void KSircIODCC::control_message(int, TQString) { } void KSircIODCC::cancelTransfer(TQString filename) { //if(DlgList[filename]){ //emit outputLine(DCCStatus[filename]->cancelMessage.ascii()); //delete DlgList[filename]; //DlgList.remove(filename); //delete DCCStatus[filename]; //DCCStatus.remove(filename); //} } void KSircIODCC::getFile() { /* TQString text = pending->fileListing()->text(pending->fileListing()->currentItem()); int pos = text.find(" ", 0); TQString nick = text.mid(0, pos); pos = text.find(" ", pos+1) + 1; TQString filename = text.mid(pos, text.length() - pos); //if(DlgList[filename]->isVisible() == FALSE) // DlgList[filename]->show(); TQString command = "/dcc get " + nick + " " + filename + "\n"; emit outputLine(command.ascii()); for(uint i = 0; i < pending->fileListing()->count(); i++) if(TQString(pending->fileListing()->text(i)) == (nick + " offered " + filename)) pending->fileListing()->removeItem(i); if(pending->fileListing()->count() == 0) pending->hide(); */ } void KSircIODCC::forgetFile() { /* TQString text = pending->fileListing()->text(pending->fileListing()->currentItem()); int pos = text.find(" ", 0); TQString nick = text.mid(0, pos); pos = text.find(" ", pos+1) + 1; TQString filename = text.mid(pos, text.length() - pos); TQString command = "/dcc close get " + nick + " " + filename + "\n"; emit outputLine(command.ascii()); for(uint i = 0; i < pending->fileListing()->count(); i++) if(TQString(pending->fileListing()->text(i)) == (nick + " offered " + filename)) pending->fileListing()->removeItem(i); if(pending->fileListing()->count() == 0) pending->hide(); */ } filterRuleList *KSircIODCC::defaultRules() { // filterRule *fr; filterRuleList *frl = new filterRuleList(); frl->setAutoDelete(TRUE); /* fr = new filterRule(); fr->desc = "Capture DCC IO Messages"; fr->search = "^\\*D\\*"; fr->from = "^"; fr->to = "~!dcc~"; frl->append(fr); */ return frl; } void KSircIODCC::dccConnectClicked(dccItem *it) { TQString str; kdDebug(5008) << "Got connect click on " << it->who() << " " << it->type() << endl; switch(it->type()){ case dccItem::dccGet: str = "/dcc get " + it->who() + " " + it->file() + "\n"; emit outputLine(str.ascii()); break; case dccItem::dccChat: str = "/dcc chat " + it->who() + "\n"; emit outputLine(str.ascii()); break; default: break; } } void KSircIODCC::dccResumeClicked(dccItem *it) { TQString str; kdDebug(5008) << "Got resume click on " << it->who() << " " << it->type() << endl; switch(it->type()){ case dccItem::dccGet: it->changeStatus(dccItem::dccWaitOnResume); str = "/resume " + it->who() + " " + it->file() + "\n"; emit outputLine(str.ascii()); break; default: break; } } void KSircIODCC::dccRenameClicked(dccItem *it) { it->doRename(); } void KSircIODCC::dccAbortClicked(dccItem *it) { TQString str; switch(it->status()){ case dccItem::dccDone: case dccItem::dccCancel: case dccItem::dccError: switch(it->type()) { case dccItem::dccGet: DCCGetItems.remove(TQString("%1/%2").arg(it->file()).arg(it->who())); break; case dccItem::dccSend: DCCSendItems.remove(TQString("%1/%2").arg(it->file()).arg(it->who())); break; case dccItem::dccChat: DCCChatItems.remove(it->who()); break; } delete it; break; default: switch(it->type()) { case dccItem::dccGet: str = "/dcc close get " + it->who() + " " + it->file() + "\n"; emit outputLine(str.ascii()); break; case dccItem::dccSend: str = "/dcc close send " + it->who() + " " + it->file() + "\n"; emit outputLine(str.ascii()); break; case dccItem::dccChat: str = "/dcc close chat " + it->who() + "\n"; emit outputLine(str.ascii()); break; } } } void KSircIODCC::dccRenameDone(dccItem *it, TQString oldWho, TQString oldFile) { if(it->type() == dccItem::dccGet){ TQString str = TQString("/dcc rename %1 %2 %3\n").arg(oldWho).arg(oldFile).arg(it->file()); TQString key = TQString("%1/%2").arg(oldFile).arg(oldWho); if(DCCGetItems[key]){ DCCGetItems.take(key); TQString newkey = TQString("%1/%2").arg(it->file()).arg(it->who()); DCCGetItems.insert(newkey, it); } emit outputLine(str.ascii()); } else if(it->type() == dccItem::dccChat){ if(DCCChatItems[oldWho]){ DCCChatItems.take(oldWho); DCCChatItems.insert(it->who(), it); } TQString str = TQString("/dcc rchat %1 %2\n").arg(oldWho).arg(it->who()); emit outputLine(str.ascii()); } } void KSircIODCC::showMgr() { displayMgr->show(mgr); } #include "ioDCC.moc"