Ejemplo n.º 1
0
	KVIRC_API void printSSLCertificate(KviWindow * wnd, const char * description, KviSSLCertificate * c)
	{
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]: %c%s"), KviControlCodes::Bold, description);
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:  Version: %c%d"), KviControlCodes::Bold, c->version());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:  Serial number: %c%d"), KviControlCodes::Bold, c->serialNumber());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:  Subject:"));
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     Common name: %c%s"), KviControlCodes::Bold, c->subjectCommonName());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     Organization: %c%s"), KviControlCodes::Bold, c->subjectOrganization());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     Organizational unit: %c%s"), KviControlCodes::Bold, c->subjectOrganizationalUnit());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     Country: %c%s"), KviControlCodes::Bold, c->subjectCountry());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     State or province: %c%s"), KviControlCodes::Bold, c->subjectStateOrProvince());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     Locality: %c%s"), KviControlCodes::Bold, c->subjectLocality());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:   Issuer:"));
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     Common name: %c%s"), KviControlCodes::Bold, c->issuerCommonName());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     Organization: %c%s"), KviControlCodes::Bold, c->issuerOrganization());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     Organizational unit: %c%s"), KviControlCodes::Bold, c->issuerOrganizationalUnit());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     Country: %c%s"), KviControlCodes::Bold, c->issuerCountry());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     State or province: %c%s"), KviControlCodes::Bold, c->issuerStateOrProvince());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:     Locality: %c%s"), KviControlCodes::Bold, c->issuerLocality());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:   Public key: %c%s (%d bits)"), KviControlCodes::Bold, c->publicKeyType(), c->publicKeyBits());
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:   Signature type: %c%s"), KviControlCodes::Bold, c->signatureType());
		KviCString tmp = c->signatureContents();
		if(tmp.len() > 40)
		{
			tmp.cutRight(tmp.len() - 40);
			tmp.append("...");
		}
		wnd->output(KVI_OUT_SSL, __tr2qs("[SSL]:   Signature contents: %c%s"), KviControlCodes::Bold, tmp.ptr());
	}
Ejemplo n.º 2
0
	void bufferFromBlock(KviCString & szBuffer)
	{
		szBuffer.trim();

		if((*(szBuffer.ptr()) == '{') && szBuffer.lastCharIs('}'))
		{
			// leading and trailing { must be stripped
			szBuffer.cutLeft(1);
			szBuffer.cutRight(1);
		}

		unindent(szBuffer);

		szBuffer.trim();
	}
Ejemplo n.º 3
0
bool KviIsOnNotifyListManager::handleUserhost(KviIrcMessage * msg)
{
	if(!m_bExpectingUserhost)
		return false;
	// first check for consistency: all the replies must be on the USERHOST list
	KviPointerList<KviIrcMask> tmplist;
	tmplist.setAutoDelete(true);

	KviCString nk;
	const char * aux = msg->trailing();

	while(*aux)
	{
		nk = "";
		aux = kvi_extractToken(nk, aux, ' ');
		if(nk.hasData())
		{
			// split it in a mask
			KviCString nick;
			KviCString user;
			KviCString host;

			int idx = nk.findFirstIdx('=');
			if(idx != -1)
			{
				nick = nk.left(idx);
				if(nick.lastCharIs('*'))
					nick.cutRight(1);
				nk.cutLeft(idx + 1);
				if(nk.firstCharIs('+') || nk.firstCharIs('-'))
					nk.cutLeft(1);

				idx = nk.findFirstIdx('@');
				if(idx != -1)
				{
					user = nk.left(idx);
					nk.cutLeft(idx + 1);
					host = nk;
				}
				else
				{
					user = "******";
					host = nk;
				}

				bool bGotIt = false;
				QString szNick = m_pConnection->decodeText(nick.ptr());
				QString szUser = m_pConnection->decodeText(user.ptr());
				QString szHost = m_pConnection->decodeText(host.ptr());

				for(QString * s = m_pUserhostList->first(); s && (!bGotIt); s = m_pUserhostList->next())
				{
					if(KviQString::equalCI(*s, szNick))
					{
						KviIrcMask * mk = new KviIrcMask(szNick, szUser, szHost);
						tmplist.append(mk);
						bGotIt = true;
						m_pUserhostList->removeRef(s);
					}
				}

				if(!bGotIt)
				{
					// ops...not my userhost!
					if(_OUTPUT_VERBOSE)
						m_pConsole->output(KVI_OUT_SYSTEMWARNING, __tr2qs("Notify list: Hey! You've used USERHOST behind my back? (I might be confused now...)"));
					return false;
				}
			}
			else
			{
				if(_OUTPUT_VERBOSE)
					m_pConsole->output(KVI_OUT_SYSTEMWARNING, __tr2qs("Notify list: Broken USERHOST reply from the server? (%s)"), nk.ptr());
			}
		}
	}

	// Ok...looks to be my usershot (still not sure at 100%, but can't do better)

	if(m_pConnection->lagMeter())
		m_pConnection->lagMeter()->lagCheckComplete("@notify_userhost");

	m_bExpectingUserhost = false;

	for(KviIrcMask * mk = tmplist.first(); mk; mk = tmplist.next())
	{
		if(!doMatchUser(mk->nick(), *mk))
			return true; // have to restart!!!
	}

	if(!(m_pUserhostList->isEmpty()))
	{
		// ops...someone is no longer online ?
		while(QString * s = m_pUserhostList->first())
		{
			if(_OUTPUT_VERBOSE)
				m_pConsole->output(KVI_OUT_SYSTEMMESSAGE, __tr2qs("Notify list: \r!n\r%Q\r appears to have gone offline before USERHOST reply was received, will recheck in the next loop"), s);
			m_pUserhostList->removeFirst();
		}
	}

	if(m_pOnlineList->isEmpty())
	{
		if(m_pNotifyList->isEmpty())
			delayedNotifySession();
		else
			delayedIsOnSession();
	}
	else
		delayedUserhostSession();

	return true;
}
Ejemplo n.º 4
0
bool DccChatThread::handleIncomingData(KviDccThreadIncomingData * data, bool bCritical)
{
	KVI_ASSERT(data->iLen);
	KVI_ASSERT(data->buffer);
	char * aux = data->buffer;
	char * end = data->buffer + data->iLen;
	while(aux != end)
	{
		if((*aux == '\n') || (*aux == '\0'))
		{
			KviThreadDataEvent<KviCString> * e = new KviThreadDataEvent<KviCString>(KVI_DCC_THREAD_EVENT_DATA);
			// The left part is len chars long
			int len = aux - data->buffer;
			//			qDebug("LEN = %d, iLen = %d",len,data->iLen);
			//#warning "DO IT BETTER (the \r cutting)"
			KviCString * s = new KviCString(data->buffer, len);
			if(s->lastCharIs('\r'))
				s->cutRight(1);
			e->setData(s);
			// but we cut also \n (or \0)
			++aux;
			// so len += 1; --> new data->iLen -= len;
			data->iLen -= (len + 1);
			//			qDebug("iLen now = %d",data->iLen);
			KVI_ASSERT(data->iLen >= 0);
			if(data->iLen > 0)
			{
				// memmove the remaining part to the beginning
				// aux points after \n or \0
				KviMemory::move(data->buffer, aux, data->iLen);
				data->buffer = (char *)KviMemory::reallocate(data->buffer, data->iLen);
				end = data->buffer + data->iLen;
				aux = data->buffer;
			}
			else
			{
				// no more data in the buffer
				KVI_ASSERT(data->iLen == 0);
				KviMemory::free(data->buffer);
				data->buffer = end = aux = nullptr;
			}
			postEvent(parent(), e);
		}
		else
			aux++;
		//		qDebug("PASSING CHAR %c",*aux);
	}
	// now aux == end
	if(bCritical)
	{
		// need to flush everything...
		if(data->iLen > 0)
		{
			// in the last part there are no NULL and \n chars
			KviThreadDataEvent<KviCString> * e = new KviThreadDataEvent<KviCString>(KVI_DCC_THREAD_EVENT_DATA);
			KviCString * s = new KviCString(data->buffer, data->iLen);
			if(s->lastCharIs('\r'))
				s->cutRight(1);
			e->setData(s);
			data->iLen = 0;
			KviMemory::free(data->buffer);
			data->buffer = nullptr;
			postEvent(parent(), e);
		}
	}
	return true;
}
Ejemplo n.º 5
0
bool DccChatWindow::event(QEvent * e)
{
	if(e->type() == KVI_THREAD_EVENT)
	{
		switch(((KviThreadEvent *)e)->id())
		{
			case KVI_DCC_THREAD_EVENT_ERROR:
			{
				KviError::Code * pError = ((KviThreadDataEvent<KviError::Code> *)e)->getData();
				QString szErr = KviError::getDescription(*pError);
				if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatError, this, szErr, m_pDescriptor->idString()))
					output(KVI_OUT_DCCERROR, __tr2qs_ctx("ERROR: %Q", "dcc"), &szErr);
				KVS_TRIGGER_EVENT_1(KviEvent_OnDCCChatDisconnected, this, m_pDescriptor->idString());
				delete pError;
				return true;
			}
			break;
			case KVI_DCC_THREAD_EVENT_DATA:
			{
				KviCString * encoded = ((KviThreadDataEvent<KviCString> *)e)->getData();
				KviCString d = KviCString(decodeText(encoded->ptr()));
				if(d.firstCharIs(0x01))
				{
					d.cutLeft(1);
					if(d.lastCharIs(0x01))
						d.cutRight(1);
					if(kvi_strEqualCIN("ACTION", d.ptr(), 6))
						d.cutLeft(6);
					d.stripLeftWhiteSpace();
					output(KVI_OUT_ACTION, "%Q %s", &(m_pDescriptor->szNick), d.ptr());
					if(!hasAttention(KviWindow::MainWindowIsVisible))
					{
						if(KVI_OPTION_BOOL(KviOption_boolFlashDccChatWindowOnNewMessages))
						{
							demandAttention();
						}
						if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnNewDccChatMessages))
						{
							QString szMsg = "<b>";
							szMsg += m_pDescriptor->szNick;
							szMsg += "</b> ";
							szMsg += KviQString::toHtmlEscaped(QString(d.ptr()));
							//qDebug("KviIrcServerParser_ctcp.cpp:975 debug: %s",szMsg.data());
							g_pApp->notifierMessage(this, KVI_OPTION_MSGTYPE(KVI_OUT_ACTION).pixId(), szMsg, KVI_OPTION_UINT(KviOption_uintNotifierAutoHideTime));
						}
					}
				}
				else
				{

#ifdef COMPILE_CRYPT_SUPPORT
					if(KviCryptSessionInfo * cinf = cryptSessionInfo())
					{
						if(cinf->m_bDoDecrypt)
						{
							KviCString decryptedStuff;
							switch(cinf->m_pEngine->decrypt(d.ptr(), decryptedStuff))
							{
								case KviCryptEngine::DecryptOkWasEncrypted:
								case KviCryptEngine::DecryptOkWasEncoded:
								case KviCryptEngine::DecryptOkWasPlainText:
									if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatMessage, this, QString(decryptedStuff.ptr()), m_pDescriptor->idString()))
									{
										g_pMainWindow->firstConsole()->outputPrivmsg(this, KVI_OUT_DCCCHATMSG,
										    m_pDescriptor->szNick.toUtf8().data(), m_pDescriptor->szUser.toUtf8().data(),
										    m_pDescriptor->szHost.toUtf8().data(), decryptedStuff.ptr());
									}
									delete encoded;
									return true;
									break;

								default: // also case KviCryptEngine::DecryptError
								{
									QString szErr = cinf->m_pEngine->lastError();
									output(KVI_OUT_SYSTEMERROR,
									    __tr2qs_ctx("The following message appears to be encrypted, but the encryption engine failed to decode it: %Q", "dcc"),
									    &szErr);
								}
								break;
							}
						}
					}
					else
					{
#endif
						// FIXME!
						if(!KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnDCCChatMessage, this, QString(d.ptr()), m_pDescriptor->idString()))
						{
							g_pMainWindow->firstConsole()->outputPrivmsg(this, KVI_OUT_DCCCHATMSG,
							    m_pDescriptor->szNick.toUtf8().data(), m_pDescriptor->szUser.toUtf8().data(),
							    m_pDescriptor->szHost.toUtf8().data(), d.ptr());
							if(!hasAttention(KviWindow::MainWindowIsVisible))
							{
								if(KVI_OPTION_BOOL(KviOption_boolFlashDccChatWindowOnNewMessages))
								{
									demandAttention();
								}
								if(KVI_OPTION_BOOL(KviOption_boolPopupNotifierOnNewDccChatMessages))
								{
									QString szMsg = KviQString::toHtmlEscaped(QString(d.ptr()));
									g_pApp->notifierMessage(this, KviIconManager::DccChatMsg, szMsg, KVI_OPTION_UINT(KviOption_uintNotifierAutoHideTime));
								}
							}
						}
#ifdef COMPILE_CRYPT_SUPPORT
					}
#endif
				}
				delete encoded;
				return true;
			}
			break;
		}
	}
	return KviWindow::event(e);
}
Ejemplo n.º 6
0
bool KviIsOnNotifyListManager::handleUserhost(KviIrcMessage * msg)
{
	if(!m_bExpectingUserhost)
		return false;
	// first check for consistency: all the replies must be on the USERHOST list

	std::map<std::size_t, std::unique_ptr<KviIrcMask>> tmplist;

	KviCString nk;
	const char * aux = msg->trailing();

	while(*aux)
	{
		nk = "";
		aux = kvi_extractToken(nk, aux, ' ');
		if(nk.hasData())
		{
			// split it in a mask
			KviCString nick;
			KviCString user;
			KviCString host;

			int idx = nk.findFirstIdx('=');
			if(idx != -1)
			{
				nick = nk.left(idx);
				if(nick.lastCharIs('*'))
					nick.cutRight(1);
				nk.cutLeft(idx + 1);
				if(nk.firstCharIs('+') || nk.firstCharIs('-'))
					nk.cutLeft(1);

				idx = nk.findFirstIdx('@');
				if(idx != -1)
				{
					user = nk.left(idx);
					nk.cutLeft(idx + 1);
					host = nk;
				}
				else
				{
					user = "******";
					host = nk;
				}

				bool bGotIt = false;
				QString szNick = m_pConnection->decodeText(nick.ptr());
				QString szUser = m_pConnection->decodeText(user.ptr());
				QString szHost = m_pConnection->decodeText(host.ptr());

				std::size_t i = 0;
				for(const auto & s : m_UserhostList)
				{
					if(KviQString::equalCI(s, szNick))
					{
						tmplist.emplace(i, std::make_unique<KviIrcMask>(szNick, szUser, szHost));
						bGotIt = true;
						break;
					}
				}

				if(!bGotIt)
				{
					// oops... not my userhost!
					if(_OUTPUT_VERBOSE)
						m_pConsole->output(KVI_OUT_SYSTEMWARNING, __tr2qs("Notify list: Hey! You've used USERHOST behind my back? (I might be confused now...)"));
					return false;
				}
			}
			else
			{
				if(_OUTPUT_VERBOSE)
					m_pConsole->output(KVI_OUT_SYSTEMWARNING, __tr2qs("Notify list: Broken USERHOST reply from the server? (%s)"), nk.ptr());
			}
		}
	}

	// Ok... looks to be my usershot (still not sure at 100%, but can't do better)

	if(m_pConnection->lagMeter())
		m_pConnection->lagMeter()->lagCheckComplete("@notify_userhost");

	m_bExpectingUserhost = false;

	for(auto & pair : tmplist)
	{
		KviIrcMask * mk = pair.second.get();

		if(!doMatchUser(mk->nick(), *mk))
			return true; // have to restart!!!
	}

	for(auto i = tmplist.rbegin(); i != tmplist.rend(); ++i)
		m_UserhostList.erase(m_UserhostList.begin() + i->first);

	for(const auto & s : m_UserhostList)
	{
		// oops... someone is no longer online ?
		if(_OUTPUT_VERBOSE)
			m_pConsole->output(KVI_OUT_SYSTEMMESSAGE, __tr2qs("Notify list: \r!n\r%Q\r appears to have gone offline before USERHOST reply was received, will recheck in the next loop"), &s);
	}

	m_UserhostList.clear();

	if(m_OnlineList.empty())
	{
		if(m_NotifyList.empty())
			delayedNotifySession();
		else
			delayedIsOnSession();
	}
	else
	{
		delayedUserhostSession();
	}

	return true;
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
static void dccModuleParseDccRSend(KviDccRequest * dcc)
{
	// DCC RSEND <filename> <filesize>
	//#warning "Ignore files depending on file type ? (MediaType ?)"
	//
	// We have received a DCC RSEND request in the following form
	//
	//      DCC [ST]RSEND <filename> <filesize>
	//
	dcc->szParam1 = dcc->pConsole->decodeText(dcc->szParam1);
	if(!dcc_module_check_limits(dcc))
		return;
	if(!dcc_module_check_concurrent_transfers_limit(dcc))
		return;

	if(!(dcc->szParam2.isUnsignedNum()))
	{
		if(!dcc->ctcpMsg->msg->haltOutput())
		{
			dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
			    __tr2qs_ctx("The above request is broken: the fourth parameter should be the file size but doesn't appear to be an unsigned number; trying to continue", "dcc"), dcc->szParam2.ptr());
		}
		dcc->szParam2 = __tr_ctx("<unknown size>", "dcc");
	}

	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 SEND

	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 RSEND is not available", "dcc"));
		return;
	}
#endif //!COMPILE_SSL_SUPPORT

	//#warning "When behind a firewall, we should reply an error message and avoid setting up the listening connection"

	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->szIp = __tr2qs_ctx("(unknown)", "dcc");
	d->szPort = d->szIp;
	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);

	d->szListenPort = "0";
	dcc_fill_local_nick_user_host(d, dcc);

	d->szFileName = dcc->szParam1.ptr();
	d->szFileSize = dcc->szParam2.ptr();
	d->bActive = false; // we have to listen!
	d->bResume = false;
	d->bRecvFile = true; // we have to receive the file!

#ifdef COMPILE_SSL_SUPPORT
	d->bIsSSL = bSSLExtension;
#endif
	d->bIsTdcc = bTurboExtension;
	d->bSendRequest = true; // we have to send the [ST]RECV request back
	d->bNoAcks = d->bIsTdcc;
	d->bOverrideMinimize = false;
	d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccSend);
	d->bIsIncomingAvatar = g_pApp->findPendingAvatarChange(dcc->pConsole, d->szNick.toUtf8().data(), d->szFileName.toUtf8().data());

	if(KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault))
	{
		d->szFakeIp = KVI_OPTION_STRING(KviOption_stringDefaultDccFakeAddress);
		if(d->szFakeIp.isEmpty())
			KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault) = false;
	}

	if(KVI_OPTION_BOOL(KviOption_boolAutoAcceptIncomingAvatars))
		d->bAutoAccept = d->bAutoAccept || d->bIsIncomingAvatar;

	dcc_module_set_dcc_type(d, "RECV");
	d->triggerCreationEvent();
	g_pDccBroker->recvFileManage(d);
}
Ejemplo n.º 9
0
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);
	}
}
Ejemplo n.º 10
0
static void dccModuleParseDccSend(KviDccRequest * dcc)
{
	//#warning "Ignore files depending on file type ? (MediaType ?)"
	//
	// We have received a DCC SEND request in the following form
	//
	//      DCC [ST]SEND <filename> <ipaddress> <port> <filesize>
	//
	// Now the things are a bit tricky... we eventually can
	// reply with a DCC RESUME and receive a DCC ACCEPT then
	// The format of these requests is:
	//
	//      DCC RESUME <filename> <port> <resumepos>
	//      ACCEPT <filename> <port> <resumepos>
	//
	// There is a mIrc extension that allows <port> to be 0
	// and adds a last parameter that seems to be a random number (thnx YaP :)
	// that is used to keep track of the connection.
	// This extension is used by firewalled machines to initiate a DCC SEND:
	// the receiving side should respond with a DCC SEND offer
	// with the same random number appended, listen for a connection, and receive the file
	// instead of sending it.
	//
	// when a zero port request is initiated by another party we get
	//      DCC SEND <filename> <fakeipaddress> 0 <filesize> <tag>
	// if (and only if) we want to resume we reply with
	//      DCC RESUME <filename> 0 <resumesize> <tag>
	// in this case the remote part replies again with
	//      DCC ACCEPT <filename> 0 <resumesize> <tag>
	// and we finally reply with
	//      DCC SEND <filename> <ourip> <ourport> <filesize> <tag>
	//
	// when a zero port request is initiated by us we send out
	//      DCC SEND <filename> <fakeipaddress> 0 <filesize> <tag>
	// and if the remote party wants to resume then we get
	//      DCC RESUME <filename> 0 <resumesize> <tag>
	// and we eventually reply with
	//      DCC ACCEPT <filename> 0 <resumesize> <tag>
	// and we finally get
	//      DCC SEND <filename> <remoteip> <remoteport> <filesize> <tag>
	//
	// Thus if there is a <tag> and the port is 0, then the remote party
	// is trying to send a file to us, but if the port is nonzero then
	// we have sent out a zero port request and the remote party acked it
	//

	if((!kvi_strEqualCS(dcc->szParam3.ptr(), "0")) && dcc->szParam5.hasData())
	{
		// DCC SEND <filename> <remoteip> <remoteport> <filesize> <tag>
		// zero port acknowledge: treat as a RECV that should look like
		// DCC [TS]RECV <filename> <remoteip> <remoteport> <resume-filesize>
		// but since we have stored the sharedfile with the name <tag>
		// we do exchange the params :)

		KviDccZeroPortTag * t = g_pDccBroker->findZeroPortTag(dcc->szParam5.ptr());
		if(t)
		{
			// FIXME: #warning "%u will not support 64-bit numbers and won't work as intended here"
			dcc->szParam4.sprintf("%u", t->m_uResumePosition);
			g_pDccBroker->removeZeroPortTag(dcc->szParam5.ptr());
		}
		else
		{
			// this should never happen since we always add
			// a zero port tag for out outgoing requests
			// but well... maybe the user did something behind our back...
			dcc->szParam4 = "0"; // no resume possible in this case
		}

		// swap the tag and the filename (we have added a fileoffer with this tag)
		dcc->szParam1 = dcc->szParam5;
		dcc->szParam5 = "";

		dccModuleParseDccRecv(dcc);
		return;
	}

	// First of all we check the transfer limits
	dcc->szParam1 = dcc->pConsole->decodeText(dcc->szParam1);
	if(!dcc_module_check_limits(dcc))
		return;
	if(!dcc_module_check_concurrent_transfers_limit(dcc))
		return;

	// Then we ensure that the data that the remote end has sent are valid
	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()->output(KVI_OUT_DCCMSG,
			    __tr2qs_ctx("The above request is broken: the fourth parameter should be the file size but doesn't appear to be an unsigned number; trying to continue", "dcc"), dcc->szParam4.ptr());
		}
		dcc->szParam4 = __tr2qs_ctx("<unknown size>", "dcc");
	}

	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('/');
	}

	if(dcc->szParam1.contains("%2F"))
	{
		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("%2F");
	}

	KviCString szExtensions = dcc->szType;
	szExtensions.cutRight(4); // cut off SEND

	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 SEND is not available", "dcc"));
		return;
	}
#endif //!COMPILE_SSL_SUPPORT

	DccDescriptor * d = new DccDescriptor(dcc->pConsole);
	d->szNick = dcc->ctcpMsg->pSource->nick();
	d->szUser = dcc->ctcpMsg->pSource->user();
	d->szHost = dcc->ctcpMsg->pSource->host();
	dcc_fill_local_nick_user_host(d, dcc);

	d->szIp = dcc->szParam2.ptr();
	d->szPort = dcc->szParam3.ptr();
	d->szFileName = dcc->szParam1.ptr();
	d->szFileSize = dcc->szParam4.ptr();

	if(d->szPort == "0" && dcc->szParam5.hasData())
	{
		if(KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault))
		{
			d->szFakeIp = KVI_OPTION_STRING(KviOption_stringDefaultDccFakeAddress);
			if(d->szFakeIp.isEmpty())
				KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault) = false;
		}
		d->setZeroPortRequestTag(dcc->szParam5.ptr());
		QString tmp;
		if(!dcc_kvs_get_listen_ip_address(nullptr, d->console(), tmp))
			d->szListenIp = "0.0.0.0";
		else
			d->szListenIp = QString(tmp);
		d->szListenPort = "0"; // any port is OK
		d->bSendRequest = true;
		d->szLocalFileSize = d->szFileSize;
	}

	d->bActive = !d->isZeroPortRequest(); // we have to connect unless it is a zero port request

	d->bResume = false;
	d->bRecvFile = true;
	d->bIsTdcc = bTurboExtension;
	d->bNoAcks = d->bIsTdcc;
#ifdef COMPILE_SSL_SUPPORT
	d->bIsSSL = bSSLExtension;
#endif
	d->bOverrideMinimize = false;
	d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccSend);

	d->bIsIncomingAvatar = g_pApp->findPendingAvatarChange(dcc->pConsole, d->szNick, d->szFileName);
	dcc_module_set_dcc_type(d, "RECV");
	if(KVI_OPTION_BOOL(KviOption_boolAutoAcceptIncomingAvatars))
		d->bAutoAccept = d->bAutoAccept || d->bIsIncomingAvatar;
	d->triggerCreationEvent();

	g_pDccBroker->recvFileManage(d);
}
Ejemplo n.º 11
0
static void dccModuleParseDccChat(KviDccRequest * dcc)
{
	//
	// We have received a DCC CHAT request in the following form:
	//
	//     DCC CHAT chat <ipaddress> <port>
	//
	// This means that we're requested to setup an ACTIVE chat connection
	// ... Easy task :)
	//
	// Anybody understands the meaning of the secondo "chat" in there ?
	// It was meant to simplify the parsing ? :DDD
	//
	// There is a mIrc extension that allows <port> to be 0
	// and adds a last parameter that seems to be a random number (thnx YaP :)
	// that is used to keep track of the connection.
	// This extension is used by firewalled machines to initiate a DCC CHAT:
	// the receiving side should respond with a DCC CHAT offer
	// with the same random number appended, and then should listen for a connection.
	//
	// when a zero port request is initiated by another party we get
	//
	//      DCC CHAT chat <fakeipaddress> 0 <tag>
	//
	// and we reply with
	//
	//      DCC CHAT chat <ourip> <ourport> <tag>
	//
	// when a zero port request is initiated by us we send out
	//
	//      DCC CHAT chat <fakeipaddress> 0 <tag>
	//
	// and we get
	//
	//      DCC CHAT chat <remoteip> <remoteport> <tag>
	//
	// Thus if there is a <tag> and the port is 0, then the remote party
	// wanted to estabilish a dcc with us and wants us to listen, but if the port is nonzero then
	// we have sent out a zero port request and the remote party acked it
	// thus we have to connect instead!
	//

	// First of all we check the dcc slot limits
	if(!dcc_module_check_limits(dcc))
		return;

	// Then we check the target host data
	if(!dcc_module_normalize_target_data(dcc, dcc->szParam2, dcc->szParam3))
		return;

	if(!kvi_strEqualCI(dcc->szParam1.ptr(), "chat"))
	{
		if(!dcc->ctcpMsg->msg->haltOutput())
		{
			dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
			    __tr2qs_ctx("The above request is broken: the second parameter is '%s' and should be 'chat', trying to continue", "dcc"), dcc->szParam1.ptr());
		}
	}

	KviCString szExtensions = dcc->szType;
	szExtensions.cutRight(4); // cut off CHAT

#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 CHAT is not available", "dcc"));
		return;
	}
#endif //!COMPILE_SSL_SUPPORT

	DccDescriptor * d = new DccDescriptor(dcc->pConsole);

	d->szNick = dcc->ctcpMsg->pSource->nick();
	d->szUser = dcc->ctcpMsg->pSource->user();
	d->szHost = dcc->ctcpMsg->pSource->host();

	dcc_fill_local_nick_user_host(d, dcc);

	d->szIp = dcc->szParam2.ptr();
	d->szPort = dcc->szParam3.ptr();

	if(dcc->szParam4.hasData())
	{
		// zero port tag ?
		if(d->szPort == "0")
		{
			// zero port request
			if(KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault))
			{
				d->szFakeIp = KVI_OPTION_STRING(KviOption_stringDefaultDccFakeAddress);
				if(d->szFakeIp.isEmpty())
					KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault) = false;
			}
			d->setZeroPortRequestTag(dcc->szParam4.ptr());
			QString tmp;
			if(!dcc_kvs_get_listen_ip_address(nullptr, d->console(), tmp))
				d->szListenIp = "0.0.0.0";
			else
				d->szListenIp = tmp;
			d->szListenPort = "0"; // any port is OK
			d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccChat);
			d->bActive = false; // we must listen then...
		}
		else
		{
			// zero port acknowledge
			// check if this is a tag that we have sent out
			QString szTag = QString(dcc->szParam4.ptr());
			KviDccZeroPortTag * t = g_pDccBroker->findZeroPortTag(szTag);
			if(!t)
			{
				// hum.. not our tag

				// FIXME: As signalled by PRAEDO, ezbounce seems to send a fourth parameter in response to /quote ezb log
				// Pragma: That's a bug in ezbounce, it sends the filesize of the log as a DCC CHAT parameter...
				//         The author probably copied and pasted the CTCP line from DCC SEND and forgot to remove the filesize.
				//         We *could* add an option to ignore the last parameter and treat it as a standard DCC chat
				//         request, but since we don't encourage bugs, we don't do it :D
				//         Mail me at pragma at kvirc dot net if you really think it's necessary.
				dcc->ctcpMsg->msg->console()->output(KVI_OUT_DCCMSG,
				    __tr2qs_ctx("The above request is broken: it looks like a zero port tag acknowledge but I have either never seen this tag or it was sent more than 120 seconds ago", "dcc"));
				dcc_module_request_error(dcc, __tr2qs_ctx("It seems that I haven't requested this DCC chat", "dcc"));
				delete d;
				return;
			}
			else
			{
				g_pDccBroker->removeZeroPortTag(szTag);
			}

			d->bAutoAccept = true; // auto-accept it (we have sent it out)
			d->bActive = true;
		}
	}
	else
	{
		d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccChat);
		d->bActive = true; // we have to connect (standard active chat)
	}

#ifdef COMPILE_SSL_SUPPORT
	d->bIsSSL = bSSLExtension;
#endif

	dcc_module_set_dcc_type(d, "CHAT");
	d->triggerCreationEvent();

	g_pDccBroker->handleChatRequest(d);
}