Архив: Технология создания плагинов

Здесь обсуждаются технические аспекты создания дополнений.
adamix
Сообщения: 16
Зарегистрирован: 00:14, 06.02.2011

Re: Технология создания плагинов

Сообщение adamix »

Maxim Mirgorodsky писал(а):adamix
std::string fTextToAnsiString(std::wstring uText) //вспомогательная функция для упрощения работы с данными
{
//функция предназначена для ознакомительных целей,
//не рекомендуется для реального применения,
//так как при ее использовании проявляется избыточное копирование данных

std::string ret;
std::stringstream ss;
ss << uText.length();
ss << utf8_wcstombs(uText);
ss >> ret;
return ret;
}
Возможно, проблема в этом:

ss << utf8_wcstombs(uText);

Текст должен быть в формате UTF16, на каждый символ по 2 байта.
Т.е. в CommfortProcess нужно передавать массив wchar_t ?
ОреЛ
Сообщения: 376
Зарегистрирован: 11:18, 11.07.2008
Откуда: Ульяновск
Контактная информация:

Re: Технология создания плагинов

Сообщение ОреЛ »

adamix писал(а): Т.е. в CommfortProcess нужно передавать массив wchar_t ?
Нужно передавать wchar_t. Можно и просто wstring, но это как вам удобнее.
Когда пишете программу, всегда думайте о том, что её может затем поддерживать психопат и насильник, который знает где вы живёте.
— Martin Golding
adamix
Сообщения: 16
Зарегистрирован: 00:14, 06.02.2011

Re: Технология создания плагинов

Сообщение adamix »

Код: Выделить всё

//---------------------------------------------------------------------------

//#include <vcl.h>
#include <windows.h>
#include <string>
#include <time.h>
#include <iostream> 
#include <sstream>
#pragma hdrstop

void logprintf(char * format, ...)
{
	if(true)
	{
		char tmp_buf[512];
		va_list args;
		FILE* file;
		
		va_start(args, format);
		vsprintf(tmp_buf, format, args);
		va_end(args);
		puts(tmp_buf);
		file = fopen("plugin.log", "a");
		if(true)
		{
			time_t rawtime;
			struct tm * timeinfo;
			char sztime[80];
			//char *result = NULL;
			time(&rawtime);
			timeinfo = localtime(&rawtime);
			strftime(sztime, 80, "%H:%M:%S", timeinfo);
			//result = strtok(tmp_buf, "\n");
			fprintf(file, "[%s] %s\n", sztime, tmp_buf);
		}
		else
		{
			fprintf(file, "%s\n", tmp_buf);
		}
		fclose(file);
	}
}

#include "UTF8.h"

DWORD dwPluginID;

typedef VOID (__stdcall *typeCommFortProcess)(DWORD dwPluginID, DWORD dID, BYTE * bOutBuffer, DWORD dwOutBufferSize);
typedef DWORD (__stdcall *typeCommFortGetData)(DWORD dwPluginID, DWORD dwID, BYTE * bInBuffer, DWORD dwInBufferSize, BYTE * bOutBuffer, DWORD dwOutBufferSize);

typeCommFortProcess CommFortProcess;
typeCommFortGetData CommFortGetData;

extern "C" __declspec(dllexport) BOOL PluginStart(DWORD dwThisPluginID, typeCommFortProcess, typeCommFortGetData);
extern "C" __declspec(dllexport) VOID PluginStop();

extern "C" __declspec(dllexport) VOID PluginProcess(DWORD dwID, BYTE * bInBuffer, DWORD dwInBufferSize);
extern "C" __declspec(dllexport) DWORD PluginGetData(DWORD dwID, BYTE * bInBuffer, DWORD dwInBufferSize, BYTE * bOutBuffer, DWORD dwOutBufferSize);
extern "C" __declspec(dllexport) BOOL PluginPremoderation(DWORD dwID, wchar_t * wText, DWORD *dwTextLength);

extern "C" __declspec(dllexport) VOID PluginShowOptions();
extern "C" __declspec(dllexport) VOID PluginShowAbout();

//---------------------------------------------------------------------------
int WINAPI DllMain(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
	int iOffset, i2;
	memcpy(&iOffset,&i2,4);

	logprintf("DllMain");

	return 1;
}

std::wstring fTextToAnsiStringW(std::wstring uText) //вспомогательная функция для упрощения работы с данными
{
	//функция предназначена для ознакомительных целей,
	//не рекомендуется для реального применения,
	//так как при ее использовании проявляется избыточное копирование данных

	std::wstring ret;
	std::wstringstream ss;
	ss << uText.length();
	ss << uText;
	ss >> ret;
	return ret;
}
//---------------------------------------------------------------------------
std::wstring fIntegerToAnsiStringW(int iValue) //вспомогательная функция для упрощения работы с данными
{
	std::wstring aReturn;
	std::wstringstream ss;
	ss << iValue;
	ss >> aReturn;

	return aReturn;
}

std::string fTextToAnsiString(std::wstring uText) //вспомогательная функция для упрощения работы с данными
{
	//функция предназначена для ознакомительных целей,
	//не рекомендуется для реального применения,
	//так как при ее использовании проявляется избыточное копирование данных

	std::string ret;
	std::stringstream ss;
	ss << uText.length();
	ss << utf8_wcstombs(uText);
	ss >> ret;
	return ret;
}
//---------------------------------------------------------------------------
std::string fIntegerToAnsiString(int iValue) //вспомогательная функция для упрощения работы с данными
{
	std::string aReturn;
	std::stringstream ss;
	ss << iValue;
	ss >> aReturn;

	return aReturn;
}

BYTE * fAnsiStringToByte(const char * szText)
{
	BYTE * out = new BYTE[strlen(szText)];
	for(int i = 0; i <= strlen(szText); i++)
	{
		out[i] = szText[i];
	}
	out[strlen(szText)] = '\0';
	return out;
}

//---------------------------------------------------------------------------
int fReadInteger(BYTE * bInBuffer, int * iOffset) //вспомогательная функция для упрощения работы с чтением данных
{
	int iLength;
	memcpy(&iLength, bInBuffer + (*iOffset),4);
	(*iOffset)+=4;
	return iLength;
}
//---------------------------------------------------------------------------
std::wstring fReadText(BYTE * bInBuffer, int * iOffset) //вспомогательная функция для упрощения работы с чтением данных
{
	int iLength;
	memcpy(&iLength, bInBuffer + (*iOffset),4);
	(*iOffset)+=4;
	wchar_t * uRet = new wchar_t[iLength+1];
	for(int i = 0; i < iLength; i++)
	{
		memcpy(&uRet[i],  bInBuffer + (*iOffset)+(i*2), 2);
	}
	(*iOffset)+=iLength*2;
	uRet[iLength] = '\0';
	std::wstring str = uRet;
	std::string s = utf8_wcstombs(str);
	return str;
}
//---------------------------------------------------------------------------
void fWriteInteger(BYTE * bOutBuffer, int iOffset, int iValue) //вспомогательная функция для упрощения работы с записью данных
{
	memcpy(bOutBuffer + iOffset, &iValue, 4);
	iOffset+=4;
}
//---------------------------------------------------------------------------
void fWriteText(BYTE * bOutBuffer, int * iOffset, std::wstring uValue) //вспомогательная функция для упрощения работы с записью данных
{
	int iLength = uValue.length();

	memcpy(bOutBuffer + (*iOffset),&iLength,4);
	(*iOffset)+=4;

	memcpy(bOutBuffer + (*iOffset),uValue.c_str(),iLength*2);
	(*iOffset)+=iLength*2;
}
//---------------------------------------------------------------------------
BOOL PluginStart(DWORD dwThisPluginID, typeCommFortProcess func1, typeCommFortGetData func2)
{
	dwPluginID = dwThisPluginID;
	//При инициализации планину присваивается уникальный идентификатор
	//его необходимо обязательно сохранить, и указывать
	//в качестве первого параметра при инициировании событий

	CommFortProcess = func1;
        //указываем функцию обратного вызова,
	//с помощью которой плагин сможет инициировать события

	CommFortGetData = func2;
        //указываем функцию обратного вызова,
	//с помощью которой можно будет запрашивать необходимые данные от программы



	//Пример получения данных от программы (получение типа программы):
	int iSize = (*CommFortGetData)(dwPluginID, 2000, NULL, NULL, NULL, NULL); //получаем объем буфера
	BYTE * cData = new BYTE[iSize];
	(*CommFortGetData)(dwPluginID, 2000,cData,iSize, NULL, NULL);//заполняем буфер

	int iProgramType;
	memcpy(&iProgramType,cData,4);//копируем число

	if(iProgramType==0)
	logprintf("Плагин успешно запущен на сервере CommFort");
	else if(iProgramType==1)
	logprintf("Плагин успешно запущен на клиенте CommFort");

	logprintf("Plugin started.");



	//Возвращаемые значения:
	//TRUE - запуск прошел успешно
	//FALSE - запуск невозможен

	return TRUE;
}
//---------------------------------------------------------------------------
VOID PluginStop()
{
	logprintf("Plugin stopped.");
	//данная функция вызывается при завершении работы плагина
}
//---------------------------------------------------------------------------
VOID PluginProcess(DWORD dwID, BYTE * bInBuffer, DWORD dwInBufferSize)
{
	logprintf("PluginProcess: [%d] [%s] [%d]", dwID, bInBuffer, dwInBufferSize);
	//Функция приема событий
	//Параметры:
	//dwID - идентификатор события
	//bInBuffer - указатель на данные
	//dwInBufferSize - объем данных в байтах
	int iReadOffset = 0;

	if(dwID==5) //личное сообщение
	{
		std::wstring userName = fReadText(bInBuffer, &iReadOffset);
		std::wstring ip = fReadText(bInBuffer, &iReadOffset);
		int userType = fReadInteger(bInBuffer, &iReadOffset);
		std::wstring chanName = fReadText(bInBuffer, &iReadOffset);
		int type = fReadInteger(bInBuffer, &iReadOffset);
		std::wstring text = fReadText(bInBuffer, &iReadOffset);

		std::wstring send = fTextToAnsiStringW(L"unix-net") + fIntegerToAnsiStringW(0) + fTextToAnsiStringW(text);
		logprintf("send: %s", send.c_str(), sizeof(BYTE));
		(*CommFortProcess)(dwPluginID,50,(BYTE*)send.c_str(),send.length());
	}

}
//---------------------------------------------------------------------------
DWORD PluginGetData(DWORD dwID, BYTE * bInBuffer, DWORD dwInBufferSize, BYTE * bOutBuffer, DWORD dwOutBufferSize)
{
        //функция передачи данных программе

	int iReadOffset = 0; //вспомогательные переменные для упрощения работы с блоком данных
	int iWriteOffset = 0;

	//при значении dwOutBufferSize равным нулю функция должна вернуть объем данных, ничего не записывая

	if(dwID==2800) //предназначение плагина
	{
		if(dwOutBufferSize==0)
		return 4; //объем памяти в байтах, которую необходимо выделить программе

		fWriteInteger(bOutBuffer,iWriteOffset,0);  //плагин подходит как для клиента, так и для сервера

		return 4;//объем заполненного буфера в байтах

	}
	else if(dwID==2810) //название плагина (отображается в списке)
	{
		std::wstring uName(L"NULL: тест");//название плагина
		int iSize = uName.length()*2+4;

		if(dwOutBufferSize==0)
		return iSize; //объем памяти в байтах, которую необходимо выделить программе

		fWriteText(bOutBuffer, &iWriteOffset, uName);

		return iSize;//объем заполненного буфера в байтах
	}


	return 0;//возвращаемое значение - объем записанных данных
}
//---------------------------------------------------------------------------
VOID PluginShowOptions()
{
	//данная функция вызывается при нажатии кнопки "Настроить" в списке плагинов
	//если Вы не желаете чтобы активировалась кнопка "Настроить", просто сотрите данную функцию

//	ShowMessage(L"Options dialog");
		std::wstring send2 = fIntegerToAnsiStringW(2) + fIntegerToAnsiStringW(0) + fIntegerToAnsiStringW(0) + fTextToAnsiStringW(L"stest");
		(*CommFortProcess)(dwPluginID,100,(BYTE*)send2.c_str(),send2.length()*2);
}
//---------------------------------------------------------------------------
VOID PluginShowAbout()
{
	//данная функция вызывается при нажатии кнопки "О плагине" в списке плагинов
	//если Вы не желаете чтобы активировалась кнопка "Настроить", просто сотрите данную функцию

//	ShowMessage(L"Test plugin for CommFort 5\n\nCreated by CommFort software Ltd.");
}
//---------------------------------------------------------------------------

Эта версия не вызывает никаких ошибок и так же не работает( не выводит сообщение ).
adamix
Сообщения: 16
Зарегистрирован: 00:14, 06.02.2011

Re: Технология создания плагинов

Сообщение adamix »

Проблема решена. Спасибо пользователю ОреЛ. Так же есть небольшая просьба, сделайте отдельный сигнал плагину при каждой итерации основного потока чата. Чтоб не приходилось прикручивать многопоточность.
Аватара пользователя
supermet
Сообщения: 245
Зарегистрирован: 02:35, 19.07.2009

Re: Технология создания плагинов

Сообщение supermet »

dark писал(а):
@serg@ писал(а):dark, в какой среде компилишь?
NetBeans. Что использую написал выше. Последний раз вообще собрал из консольки, т.ч. среда не при чем. Результат тот же.
Нужно код переделать примерно так:

Код: Выделить всё

DWORD dwPluginID;
typedef VOID (__stdcall *typeCommFortProcess)(DWORD dwPluginID, DWORD dID, BYTE * bOutBuffer, DWORD dwOutBufferSize);
typedef DWORD (__stdcall *typeCommFortGetData)(DWORD dwPluginID, DWORD dwID, BYTE * bInBuffer, DWORD dwInBufferSize, BYTE * bOutBuffer, DWORD dwOutBufferSize);
typeCommFortProcess CommFortProcess;
typeCommFortGetData CommFortGetData;

#ifdef __cplusplus
extern "C" {
#endif
	__declspec(dllexport) BOOL __stdcall PluginStart(DWORD dwThisPluginID, typeCommFortProcess, typeCommFortGetData);
	__declspec(dllexport) VOID __stdcall PluginStop();
	__declspec(dllexport) VOID __stdcall PluginProcess(DWORD dwID, BYTE * bInBuffer, DWORD dwInBufferSize);
	__declspec(dllexport) DWORD __stdcall PluginGetData(DWORD dwID, BYTE * bInBuffer, DWORD dwInBufferSize, BYTE * bOutBuffer, DWORD dwOutBufferSize);
	__declspec(dllexport) VOID __stdcall PluginShowOptions();
	__declspec(dllexport) VOID __stdcall PluginShowAbout();
#ifdef __cplusplus
}
#endif

//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
	return 1;
}
//---------------------------------------------------------------------------
BOOL __stdcall PluginStart (DWORD dwThisPluginID, typeCommFortProcess func1, typeCommFortGetData func2)
{
	dwPluginID = dwThisPluginID;
//... дальше реализация
В настройках компилятора Mingw задать опции линкера -Wl,--kill-at чтобы убрать символы @XXX в именах функций. И проверить программой Dependency Walker чтобы было так - рисунок
А еще можно скачать мои исходники плагина под VC++ и переделать
ZigZagkms
Сообщения: 109
Зарегистрирован: 08:23, 11.12.2008
Откуда: Комсомольск-на-Амуре
Контактная информация:

Re: Технология создания плагинов

Сообщение ZigZagkms »

Сделайте пожалуйста чтобы можно было считывать информацию с анкеты пользователя, очень желательно вместе с картинкой...
Также очень нужна возможность получать картинки публикуемые в каналах/ЛС
Также желательно чтобы можно было виртуальному пользователя входить указывая ID компьютера, хочется учитывать этот параметр везде для контроля за подключаемым виртуальными пользователями

Пожалуйста!
Забросил, всем спасибо, исходники раздаю кому надо https://github.com/ZigZagkms
Phat D
Сообщения: 2
Зарегистрирован: 03:40, 18.02.2011

Re: Технология создания плагинов

Сообщение Phat D »

Уважаемые админы и программеры,
немогли бы вы мне написать пример Рипитера на языке C#?


Заранее очень вам благодарен :)
ZigZagkms
Сообщения: 109
Зарегистрирован: 08:23, 11.12.2008
Откуда: Комсомольск-на-Амуре
Контактная информация:

Re: Технология создания плагинов

Сообщение ZigZagkms »

Phat D писал(а):Уважаемые админы и программеры,
немогли бы вы мне написать пример Рипитера на языке C#?


Заранее очень вам благодарен :)
Никак не написать. Это .NET и тут нет DLL - тут есть сборки и импортировать их функционал из неуправляемого кода нельзя, за исключением COM-объектов. Не люблю я этот .NET, чтобы запустить программу требуется гора дополнительных файлов, взамен сильного упрощению написания кода теряются возможности, пишите на С++ и будет Вам счастье =)

Что такое managed и unmanaged код можно почитать тут http://www.gotdotnet.ru/forums/2/124760 ... post588378
Забросил, всем спасибо, исходники раздаю кому надо https://github.com/ZigZagkms
Phat D
Сообщения: 2
Зарегистрирован: 03:40, 18.02.2011

Re: Технология создания плагинов

Сообщение Phat D »

ZigZagkms писал(а):
Phat D писал(а):Уважаемые админы и программеры,
немогли бы вы мне написать пример Рипитера на языке C#?


Заранее очень вам благодарен :)
Никак не написать. Это .NET и тут нет DLL - тут есть сборки и импортировать их функционал из неуправляемого кода нельзя, за исключением COM-объектов. Не люблю я этот .NET, чтобы запустить программу требуется гора дополнительных файлов, взамен сильного упрощению написания кода теряются возможности, пишите на С++ и будет Вам счастье =)

Что такое managed и unmanaged код можно почитать тут http://www.gotdotnet.ru/forums/2/124760 ... post588378
Это конечно все хорошо, но вот проблема в том что я только учусь программировать, и учусь именно на системе C#...

Ну значит придется делфи вспоминать......:)
Cilvay
Сообщения: 816
Зарегистрирован: 14:55, 16.06.2008

Re: Технология создания плагинов

Сообщение Cilvay »

Как получить адрес сервера на котором запущен плагин (или к какому серверу подключен чат)
Аватара пользователя
SV
Сообщения: 797
Зарегистрирован: 00:11, 06.09.2010
Откуда: Киров

Re: Технология создания плагинов

Сообщение SV »

Думаю можно вытащить адрес сервера из канала события
Cilvay
Сообщения: 816
Зарегистрирован: 14:55, 16.06.2008

Re: Технология создания плагинов

Сообщение Cilvay »

хм... точно
Аватара пользователя
Alawar
Сообщения: 4
Зарегистрирован: 20:04, 06.02.2011
Откуда: Беларусь. Гомель. 4local.ru

Re: Технология создания плагинов

Сообщение Alawar »

Подскажите, пожалуйста, как изменить приветсвие канала и наложить ограничение
Аватара пользователя
SV
Сообщения: 797
Зарегистрирован: 00:11, 06.09.2010
Откуда: Киров

Re: Технология создания плагинов

Сообщение SV »

Alawar писал(а):Подскажите, пожалуйста, как изменить приветсвие канала и наложить ограничение
Изменить приветствие канала

ID: 62
Блок данных: текст(название канала) + текст(новое приветствие)

Пользователь должен быть подключен к данному каналу и иметь право его модерирования.
Наложить ограничение

ID: 52
Блок данных: число(тип идентификации) + текст(объект идентификации) + число(тип ограничения) + текст(канал ограничения) + срок() + текст(причина ограничения) + число(тип анонимности)

Типы идентификации:
0 - IP-адрес
1 - диапазон IP-адресов (пример написания объекта идентификации: 192.168.0.0-192.168.0.255)
2 - ID компьютера
3 - учетная запись (по имени)
4 - учетная запись (по IP-адресу)
5 - учетная запись (по ID компьютера)
6 - учетная запись (по имени и IP-адресу)
7 - учетная запись (по имени и ID компьютера)
8 - учетная запись (по IP-адресу и ID компьютера)
9 - учетная запись (по имени и IP-адресу, и ID компьютера)

Типы ограничения:
0 - Запретить доступ к серверу
1 - Запретить приватную переписку
2 - Запретить доступ к каналу
3 - Запретить публикацию в канале
4 - Запретить публикацию картинок в канале
5 - Запретить публикацию в доске объявлений

Канал ограничения игнорируется в случае если тип ограничения соответствует значению 0, 1 или 5. Текст с нулевой длиной соответствует всем общим каналам.

Типы анонимности:
0 - обычное ограничение
1 - анонимное ограничение

Пользователь должен иметь соответствующие права для наложения ограничений.
Написал бы сам код но не знаю на чём вы пишите.
Maxim Mirgorodsky
Администратор
Сообщения: 6869
Зарегистрирован: 09:56, 27.06.2005

Re: Технология создания плагинов

Сообщение Maxim Mirgorodsky »

В связи с изменением структуры форума данную тему закрываем. Теперь если возникли вопросы по технологии создания плагинов - вы можете просто создать новую тему в этом разделе.
Закрыто