KviSharedFile * KviSharedFilesManager::lookupSharedFile(const QString & szName, KviIrcMask * mask, unsigned int uFileSize) { KviSharedFileList * l = m_pSharedListDict->find(szName); if(!l) return nullptr; for(KviSharedFile * o = l->first(); o; o = l->next()) { bool bMatch; if(mask) { KviIrcMask umask(o->userMask()); bMatch = mask->matchedBy(umask); } else bMatch = KviQString::equalCS(o->userMask(), "*!*@*"); if(bMatch) { if(uFileSize > 0) { if(uFileSize == o->fileSize()) return o; } else return o; } } return nullptr; }
bool KviSharedFilesManager::removeSharedFile(const QString &szName,const QString &szMask,unsigned int uFileSize) { KviSharedFileList * l = m_pSharedListDict->find(szName); if(!l)return false; for(KviSharedFile * o = l->first();o;o = l->next()) { if(KviQString::equalCI(szMask,o->userMask())) { bool bMatch = uFileSize > 0 ? uFileSize == o->fileSize() : true; if(bMatch) { QString save = szName; // <-- szName MAY Be a pointer to o->name() l->removeRef(o); if(l->count() == 0)m_pSharedListDict->remove(save); emit sharedFileRemoved(o); return true; } } } return false; }
static void dccModuleParseDccGet(KviDccRequest * dcc) { // DCC [TS]GET <filename> [filesize] // -> DCC [TS]SEND <filename> <ipaddr> <port> <filesize> // ... dcc->szParam1 = dcc->pConsole->decodeText(dcc->szParam1); bool bOk; unsigned int uSize = dcc->szParam2.toUInt(&bOk); if(!bOk) uSize = 0; if(!dcc_module_check_limits(dcc)) return; if(!dcc_module_check_concurrent_transfers_limit(dcc)) return; KviCString szExtensions = dcc->szType; szExtensions.cutRight(3); // cut off GET bool bTurboExtension = szExtensions.contains('T', false); #ifdef COMPILE_SSL_SUPPORT bool bSSLExtension = szExtensions.contains('S', false); #else //!COMPILE_SSL_SUPPORT if(szExtensions.contains('S', false)) { dcc_module_request_error(dcc, __tr2qs_ctx("This executable has been compiled without SSL support, the SSL extension to DCC GET is not available", "dcc")); return; } #endif //!COMPILE_SSL_SUPPORT KviSharedFile * o = g_pSharedFilesManager->lookupSharedFile(dcc->szParam1.ptr(), dcc->ctcpMsg->pSource, uSize); if(!o) { if(!dcc->ctcpMsg->msg->haltOutput()) { QString szError = QString(__tr2qs_ctx("No file offer named '%1' (with size %2) available for %3 [%4@%5]", "dcc")).arg(dcc->szParam1.ptr()).arg(uSize > 0 ? dcc->szParam2.ptr() : __tr_ctx("\"any\"", "dcc")).arg(dcc->ctcpMsg->pSource->nick(), dcc->ctcpMsg->pSource->user(), dcc->ctcpMsg->pSource->host()); dcc_module_request_error(dcc, szError); } return; } //#warning "IF NOT IGNORE DCC GET!" //#warning "CREATE IT MINIMIZED ETC..." //#warning "MAYBE USE A DIALOG TO ACCEPT THE REQUEST ?" //#warning "DO NOT ACCEPT /etc/* requests..." if(KVI_OPTION_BOOL(KviOption_boolCantAcceptIncomingDccConnections)) { // we have to use DCC RSEND, otherwise it will not work KviCString szSubproto("RSEND"); szSubproto.prepend(szExtensions); QString szFileName = QFileInfo(o->absFilePath()).fileName(); if(o->name() != szFileName) { // BUG // If the file offer was added with a name that is senseless (like "mediaXYZ" for an *.mp3 file) // then we would be going to RSEND that name here: the remote user woulnd't be // able to recognize the file. // Here we add another temporary offer with the right filename. // now add a file offer, so he we will accept it automatically // 120 secs is a reasonable timeout QString szMask; dcc->ctcpMsg->pSource->mask(szMask, KviIrcMask::NickUserHost); KviSharedFile * pOld = o; o = g_pSharedFilesManager->addSharedFile(szFileName, o->absFilePath(), szMask, 120); if(!o) o = pOld; // give up (FIXME: should we notify that ?) } if(!dcc->ctcpMsg->msg->haltOutput()) { dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG, __tr2qs_ctx("Accepting file request from %Q [%Q@%Q] for '%s' (real file: %Q), offering DCC %s since we can't accept incoming connections (user option)", "dcc"), &(dcc->ctcpMsg->pSource->nick()), &(dcc->ctcpMsg->pSource->user()), &(dcc->ctcpMsg->pSource->host()), dcc->szParam1.ptr(), &(o->absFilePath()), szSubproto.ptr()); } dcc->pConsole->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s %s%c", dcc->pConsole->connection()->encodeText(dcc->ctcpMsg->pSource->nick()).data(), 0x01, szSubproto.ptr(), dcc->pConsole->connection()->encodeText(dcc->szParam1.ptr()).data(), dcc->pConsole->connection()->encodeText(QString::number(o->fileSize())).data(), 0x01); return; } DccDescriptor * d = new DccDescriptor(dcc->pConsole); d->szNick = dcc->ctcpMsg->pSource->nick(); d->szLocalFileName = o->absFilePath(); d->szUser = dcc->ctcpMsg->pSource->user(); d->szHost = dcc->ctcpMsg->pSource->host(); d->bRecvFile = false; dcc_fill_local_nick_user_host(d, dcc); QString tmp; if(!dcc_kvs_get_listen_ip_address(nullptr, d->console(), tmp)) { d->console()->output(KVI_OUT_DCCMSG, __tr2qs_ctx("No suitable interface to listen on, trying to continue anyway...", "dcc")); d->szListenIp = "0.0.0.0"; } else d->szListenIp = QString(tmp); //#warning "DO STH WITH THIS PORT (HOW TO SPECIFY IT ?)" d->szListenPort = "0"; // any port is ok if(KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault)) { d->szFakeIp = KVI_OPTION_STRING(KviOption_stringDefaultDccFakeAddress); if(d->szFakeIp.isEmpty()) KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault) = false; } d->bDoTimeout = true; d->szIp = __tr2qs_ctx("(unknown)", "dcc"); d->szPort = d->szIp; d->bActive = false; d->bSendRequest = true; d->bIsTdcc = bTurboExtension; #ifdef COMPILE_SSL_SUPPORT d->bIsSSL = bSSLExtension; #endif d->bNoAcks = d->bIsTdcc; d->bOverrideMinimize = false; dcc_module_set_dcc_type(d, "SEND"); if(!dcc->ctcpMsg->msg->haltOutput()) { dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG, __tr2qs_ctx("Accepting file request from %Q [%Q@%Q] for '%s' (real file: %Q), offering DCC %Q", "dcc"), &(dcc->ctcpMsg->pSource->nick()), &(dcc->ctcpMsg->pSource->user()), &(dcc->ctcpMsg->pSource->host()), dcc->szParam1.ptr(), &(o->absFilePath()), &(d->szType)); } d->triggerCreationEvent(); g_pDccBroker->sendFileExecute(nullptr, d); }
static void dccModuleParseDccRecv(KviDccRequest * dcc) { // DCC [TS]RECV <filename> <ipaddr> <port> <resume-filesize> if(!dcc_module_check_limits(dcc)) return; if(!dcc_module_check_concurrent_transfers_limit(dcc)) return; if(!dcc_module_normalize_target_data(dcc, dcc->szParam2, dcc->szParam3)) return; if(!(dcc->szParam4.isUnsignedNum())) { if(!dcc->ctcpMsg->msg->haltOutput()) { dcc->ctcpMsg->msg->console()->outputNoFmt(KVI_OUT_DCCMSG, __tr2qs_ctx("The above request has resume file size missing, assuming a resume file size of 0", "dcc")); } dcc->szParam4 = "0"; } if(dcc->szParam1.contains('/')) { if(!dcc->ctcpMsg->msg->haltOutput()) { dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG, __tr2qs_ctx("The above request is broken: the filename contains path components, stripping the leading path and trying to continue", "dcc"), dcc->szParam1.ptr()); } dcc->szParam1.cutToLast('/'); } KviCString szExtensions = dcc->szType; szExtensions.cutRight(4); // cut off RECV bool bTurboExtension = szExtensions.contains('T', false); #ifdef COMPILE_SSL_SUPPORT bool bSSLExtension = szExtensions.contains('S', false); #else //!COMPILE_SSL_SUPPORT if(szExtensions.contains('S', false)) { dcc_module_request_error(dcc, __tr2qs_ctx("This executable has been compiled without SSL support, the SSL extension to DCC RECV is not available", "dcc")); return; } #endif //!COMPILE_SSL_SUPPORT // If we have a file offer for this...do it automatically KviSharedFile * o = g_pSharedFilesManager->lookupSharedFile(dcc->szParam1.ptr(), dcc->ctcpMsg->pSource, 0); if(o) { unsigned int uResumeSize = dcc->szParam4.toUInt(); // this will NEVER fail if(uResumeSize >= o->fileSize()) { // senseless request QString szError = QString(__tr2qs_ctx("Invalid RECV request: position %1 is larger than file size", "dcc")).arg(uResumeSize); dcc_module_request_error(dcc, szError); return; } // ok...we have requested this send // #warning "Maybe remove this file offer now ?" DccDescriptor * d = new DccDescriptor(dcc->pConsole); d->szNick = dcc->ctcpMsg->pSource->nick(); d->szUser = dcc->ctcpMsg->pSource->user(); d->szHost = dcc->ctcpMsg->pSource->host(); d->szFileName = dcc->szParam1.ptr(); d->szFileSize = dcc->szParam4.ptr(); //d->bResume = false; // This is actually useless d->szLocalFileName = o->absFilePath(); d->szLocalFileSize.setNum(o->fileSize()); // Should we look it up again ? d->bRecvFile = false; d->bNoAcks = bTurboExtension; d->bAutoAccept = true; d->bIsIncomingAvatar = false; d->bIsTdcc = bTurboExtension; #ifdef COMPILE_SSL_SUPPORT d->bIsSSL = bSSLExtension; #endif d->bOverrideMinimize = false; // We know everything dcc_fill_local_nick_user_host(d, dcc); d->bDoTimeout = true; d->szIp = dcc->szParam2.ptr(); d->szPort = dcc->szParam3.ptr(); d->bActive = true; dcc_module_set_dcc_type(d, "SEND"); d->triggerCreationEvent(); g_pDccBroker->sendFileExecute(nullptr, d); return; } else { dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG, __tr2qs_ctx("%Q [%Q@%Q] is ready to receive the file \"%s\"", "dcc"), &(dcc->ctcpMsg->pSource->nick()), &(dcc->ctcpMsg->pSource->user()), &(dcc->ctcpMsg->pSource->host()), dcc->szParam1.ptr()); dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG, __tr2qs_ctx("The remote client is listening on interface %s and port %s", "dcc"), dcc->szParam2.ptr(), dcc->szParam3.ptr()); KviCString szSwitches = "-c"; if(bTurboExtension) szSwitches.prepend("-t "); #ifdef COMPILE_SSL_SUPPORT if(bSSLExtension) szSwitches.prepend("-s "); #endif dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG, __tr2qs_ctx("Use %c\r![!dbl]dcc.send %s -i=%s -p=%s %Q\r/dcc.send %s -i=%s -p=%s %Q\r%c to send the file (or double-click on the socket)", "dcc"), KviControlCodes::Bold, szSwitches.ptr(), dcc->szParam2.ptr(), dcc->szParam3.ptr(), &(dcc->ctcpMsg->pSource->nick()), szSwitches.ptr(), dcc->szParam2.ptr(), dcc->szParam3.ptr(), &(dcc->ctcpMsg->pSource->nick()), KviControlCodes::Bold); } }