Exemple #1
0
void KviLagMeter::lagCheckAbort(const char * key)
{
	KviPointerList<KviLagCheck> l;
	l.setAutoDelete(false);
	KviLagCheck * c;

	if(_OUTPUT_PARANOIC)
		m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Lag check aborted (%s)"),key);

	for(c = m_pCheckList->first();c;c = m_pCheckList->next())
		if(kvi_strEqualCS(c->szKey.ptr(),key))l.append(c);
	for(c = l.first();c;c = l.next())m_pCheckList->removeRef(c);
}
Exemple #2
0
static bool perlcore_module_ctrl(KviModule *,const char * cmd,void * param)
{
#ifdef COMPILE_PERL_SUPPORT
	if(kvi_strEqualCS(cmd,KVI_PERLCORECTRLCOMMAND_EXECUTE))
	{
		KviPerlCoreCtrlCommand_execute * ex = (KviPerlCoreCtrlCommand_execute *)param;
		if(ex->uSize != sizeof(KviPerlCoreCtrlCommand_execute))return false;
		g_pCurrentKvsContext = ex->pKvsContext;
		g_bExecuteQuiet = ex->bQuiet;
		if(ex->szContext.isEmpty())
		{
			KviPerlInterpreter * m = new KviPerlInterpreter("temporary");
			if(!m->init())
			{
				delete m;
				return false;
			}
			ex->bExitOk = m->execute(ex->szCode,ex->lArgs,ex->szRetVal,ex->szError,ex->lWarnings);
			m->done();
			delete m;
		} else {
			KviPerlInterpreter * m = perlcore_get_interpreter(ex->szContext);
			ex->bExitOk = m->execute(ex->szCode,ex->lArgs,ex->szRetVal,ex->szError,ex->lWarnings);
		}
		return true;
	}
	if(kvi_strEqualCS(cmd,KVI_PERLCORECTRLCOMMAND_DESTROY))
	{
		KviPerlCoreCtrlCommand_destroy * de = (KviPerlCoreCtrlCommand_destroy *)param;
		if(de->uSize != sizeof(KviPerlCoreCtrlCommand_destroy))return false;
		perlcore_destroy_interpreter(de->szContext);
		return true;
	}
#endif // COMPILE_PERL_SUPPORT
	return false;
}
Exemple #3
0
bool KviLagMeter::lagCheckComplete(const char * key)
{
	// find this lag check
	KviLagCheck * c;
	for(c = m_pCheckList->first();c;c = m_pCheckList->next())
	{
		if(kvi_strEqualCS(c->szKey.ptr(),key))break;
	}
	if(!c)return false; // not found
	// kill any earlier lag checks (IRC is a sequential proto)
	while(m_pCheckList->first() != c)m_pCheckList->removeFirst();

	if(_OUTPUT_PARANOIC)
		m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Lag check completed (%s)"),key);

	struct timeval tv;
	kvi_gettimeofday(&tv,0);

	unsigned int uLag = ((tv.tv_sec - c->lSecs) * 1000);
	if(tv.tv_usec < c->lUSecs)uLag -= ((c->lUSecs - tv.tv_usec) / 1000);
	else uLag += ((tv.tv_usec - c->lUSecs) / 1000);
	
	// now check the reliability

	if(m_uLastReliability > c->uReliability)
	{
		// the actual data is more reliable than the new one :/
		// change the real lag only by a certain amount
		// c->uRel : 100 = uLag : m_uLag
		m_uLag = ((uLag * c->uReliability) + (m_uLag * m_uLastReliability)) / (c->uReliability + m_uLastReliability);
	} else {
		// the actual data is less reliable than the new one
		m_uLag = uLag;
	}

	m_tLastCompleted = tv.tv_sec; // now
	m_tLastOwnCheck = 0;
	m_tFirstOwnCheck = 0;
	m_uLastReliability = c->uReliability;

	m_pCheckList->removeFirst();
	
	return true;
}
Exemple #4
0
KVIMODULEEXPORTFUNC void dccModuleCtcpDccParseRoutine(KviDccRequest * dcc)
{
	dcc->szType.toUpper();

	for(auto & i : dccParseProcTable)
	{
		if(kvi_strEqualCS(i.type, dcc->szType.ptr()))
		{
			(i.proc)(dcc);
			return;
		}
	}
	// ops...we don't know this dcc type
	if(!dcc->ctcpMsg->msg->haltOutput())
	{
		QString szError = QString(__tr2qs_ctx("Unknown DCC type '%1'", "dcc")).arg(dcc->szType.ptr());
		dcc_module_request_error(dcc, szError);
	}
}
bool KviModuleManager::loadModule(const QString &modName)
{
	if(findModule(modName))
	{
		//qDebug("MODULE %s ALREADY IN CORE MEMORY",modName);
		return true;
	}
	QString tmp;
	QString szName;
#if defined(COMPILE_ON_WINDOWS)
	KviQString::appendFormatted(szName,"kvi%Q.dll",&modName);
#elif defined(COMPILE_ON_MINGW)
	KviQString::appendFormatted(szName,"libkvi%Q.dll",&modName);
#else
	KviQString::appendFormatted(szName,"libkvi%Q.so",&modName);
#endif
	szName=szName.toLower();

	g_pApp->getLocalKvircDirectory(tmp,KviApplication::Modules,szName);
	if(!KviFileUtils::fileExists(tmp))
	{
		g_pApp->getGlobalKvircDirectory(tmp,KviApplication::Modules,szName);
	}

	QLibrary* pLibrary = new QLibrary(tmp);
	pLibrary->setLoadHints(QLibrary::ExportExternalSymbolsHint);

	if(!pLibrary->load())
	{
		m_szLastError = pLibrary->errorString();
		delete pLibrary;
		return false;
	}
	KviModuleInfo * info = (KviModuleInfo *)pLibrary->resolve(KVIRC_MODULE_STRUCTURE_SYMBOL);
	if(!info)
	{
		m_szLastError = __tr2qs("No " KVIRC_MODULE_STRUCTURE_SYMBOL " symbol exported: not a kvirc module ?");
		pLibrary->unload();
		delete pLibrary;
		return false;
	}
	if(!info->szKVIrcVersion)
	{
		m_szLastError = __tr2qs("This module has no version information: refusing to load it");
		pLibrary->unload();
		delete pLibrary;
		return false;
	}
	if(!KVI_OPTION_BOOL(KviOption_boolIgnoreModuleVersions))
	{
		if(!kvi_strEqualCS(info->szKVIrcVersion,KVI_VERSION))
		{
			m_szLastError = __tr2qs("This module was compiled for a different KVIrc version and can't be loaded");
			m_szLastError += " (";
			m_szLastError += info->szKVIrcVersion;
			m_szLastError += ")";
			pLibrary->unload();
			delete pLibrary;
			return false;
		}
	}
	KviModule * module = new KviModule(pLibrary,info,modName,szName.toUtf8().data());

	// the module is probably up.. the only thing can fail is the init_routine now
	
	// load the message catalogue if any
	if(info->szModuleContext)
	{
		QString szDir;
		// it's more probable to have the translations in the global directory
		// try it as first... (yes, catalogue overriding is impossible this way.. but, anybody cares ?)
		g_pApp->getGlobalKvircDirectory(szDir,KviApplication::Locale);

		if(!KviLocale::instance()->loadCatalogue(info->szModuleContext,szDir))
		{
			// try the local directory then
			g_pApp->getLocalKvircDirectory(szDir,KviApplication::Locale);
			KviLocale::instance()->loadCatalogue(info->szModuleContext,szDir);
		}
	}
	
	if(info->init_routine)
	{
		if(!((info->init_routine)(module)))
		{
			m_szLastError = __tr2qs("Failed to execute the init routine");
			//qDebug("ERROR IN LOADING MODULE %s (%s): failed to execute the init routine",modName,szName.ptr());
			delete module;
			// kill the message catalogue too then
			KviLocale::instance()->unloadCatalogue(modName);
			return false;
		}
	}
	m_pModuleDict->insert(modName,module);

	/*
	registerDefaultCommands(module);
	*/
	module->registerDefaultCommands();

	if(KVI_OPTION_BOOL(KviOption_boolCleanupUnusedModules))
	{
		if(!m_pCleanupTimer->isActive())
		{
			if(KVI_OPTION_UINT(KviOption_uintModuleCleanupTimerInterval) < 30)
				KVI_OPTION_UINT(KviOption_uintModuleCleanupTimerInterval) = 30;
			m_pCleanupTimer->start(KVI_OPTION_UINT(KviOption_uintModuleCleanupTimerInterval) * 1000);
		}
	}
	// be verbose if needed....just make sure that we're not shutting down...
	if(_OUTPUT_VERBOSE && !g_pApp->kviClosingDown())
	{
		if(g_pMainWindow)
		{
			KviConsoleWindow * pWnd = g_pMainWindow->firstConsole();
			if(pWnd) // this may be NULL when the app is starting up
				pWnd->output(
						KVI_OUT_VERBOSE,
						__tr2qs("Loaded module '%s' (%s)"),
						modName.toUtf8().data(),
						szName.toUtf8().data()
					);
		}
	}
	return true;
}
Exemple #6
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);
}