diff --git a/DB/.db b/DB/.db
new file mode 100644
index 0000000..e69de29
diff --git a/dllsource/compile.bat b/dllsource/compile.bat
index bfd0edd..f5dd05f 100644
--- a/dllsource/compile.bat
+++ b/dllsource/compile.bat
@@ -1,7 +1,12 @@
-@if "%1"=="" GOTO :EOF
-@if "%1"=="dllplugin" GOTO :EOF
-@echo Compile to %1.dll
-@copy dllplugin.c %1.c 1>nul
-@..\tcc\tcc -shared %1.c
-@del %1.def
-@del %1.c
\ No newline at end of file
+@echo OFF
+%~d0
+cd %~dp0
+set FULLPATH=%~dp0
+
+if "%1"=="" GOTO :EOF
+if "%1"=="dllplugin" GOTO :EOF
+echo Compile to %1.dll
+copy dllplugin.c %1.c 1>nul
+..\tcc\tcc -shared %FULLPATH%%1.c
+del %1.def
+del %1.c
\ No newline at end of file
diff --git a/dllsource/compile_all_p.bat b/dllsource/compile_all_p.bat
index 6018e7d..44d0866 100644
--- a/dllsource/compile_all_p.bat
+++ b/dllsource/compile_all_p.bat
@@ -1,6 +1,7 @@
-%~d0
-cd %~p0
+@ECHO OFF
+%~d0
+cd %~dp0
-@C:\mbplugin\python\python -c "import os,glob;fl=[os.system(f'compile.bat p_{os.path.splitext(os.path.split(fn)[1])[0]}') for fn in glob.glob('..\\plugin\\*.py') if 'def get_balance(' in open(fn,encoding='utf8').read()]"
-move C:\mbplugin\dllsource\*.dll C:\mbplugin\dllplugin
+@..\python\python -c "import os,glob;fl=[os.system(f'compile.bat p_{os.path.splitext(os.path.split(fn)[1])[0]}') for fn in glob.glob('..\\plugin\\*.py') if 'def get_balance(' in open(fn,encoding='utf8').read()]"
+move ..\dllsource\*.dll ..\dllplugin
diff --git a/dllsource/dllplugin.c b/dllsource/dllplugin.c
index 2e3c082..9bbd056 100644
--- a/dllsource/dllplugin.c
+++ b/dllsource/dllplugin.c
@@ -11,9 +11,17 @@
#define MAXBUF 10000
#define BUFFSZ 4096
+// from https://stackoverflow.com/questions/8487986/file-macro-shows-full-path
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
//from https://stackoverflow.com/questions/35969730/how-to-read-output-from-cmd-exe-using-createprocess-and-createpipe
int callInterpreter(char *request, char *dllname, char *response, int responseSize)
{
+ char dllpath[MAX_PATH] = {0};
+ char mbpluginpath[MAX_PATH] = {0};
+ strncpy(dllpath, __FILE__, strlen(__FILE__)-strlen(__FILENAME__)-1); // get path
+ strncpy(mbpluginpath, dllpath, strlen(dllpath)-strlen(strrchr(dllpath, '/'))); // get path/..
+ for(int i=0;mbpluginpath[i]!='\0';i++){mbpluginpath[i] = mbpluginpath[i]=='/' ? '\\' : mbpluginpath[i];} // replace '/' -> '\\'
// Set RequestVariable environment
char RequestVariable[MAXBUF]={0};
snprintf(RequestVariable, MAXBUF, "RequestVariable=%s", request);
@@ -43,7 +51,7 @@ int callInterpreter(char *request, char *dllname, char *response, int responseSi
PROCESS_INFORMATION pi = { };
char lpCommandLine[MAXBUF] = {0};
- snprintf(lpCommandLine, MAXBUF, "c:\\mbplugin\\plugin\\mbplugin.bat %s", dllname);
+ snprintf(lpCommandLine, MAXBUF, "%s\\plugin\\mbplugin.bat %s", mbpluginpath, dllname);
ok = CreateProcess(NULL, lpCommandLine, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
if (ok == FALSE) return -1;
@@ -80,8 +88,8 @@ __declspec(dllexport) void IssaPlugin (char *cmd, char *request, char *result, l
char buf[MAXBUF]={0};
char resultInfo[MAXBUF]={0};
char dllname[MAX_PATH]={0};
- strncpy(dllname,__FILE__,strlen(__FILE__)-2);
- snprintf(resultInfo, MAXBUF, "\nDLL %s\n%s\nArtyLa\n21.05.2020\n", dllname, dllname);
+ strncpy(dllname, __FILENAME__ , strlen(__FILENAME__)-2);
+ snprintf(resultInfo, MAXBUF, "\nDLL %s\n%s\nArtyLa\n%s\n", dllname, dllname, __DATE__);
if(strcmp(cmd,"Info")==0){
snprintf(result, resultsize, "%s" ,resultInfo); // cmd==Info
}
diff --git a/dllsource/tst.bat b/dllsource/tst.bat
index f961cd0..ba851ea 100644
--- a/dllsource/tst.bat
+++ b/dllsource/tst.bat
@@ -1,10 +1,15 @@
+%~d0
+cd %~dp0
+set FULLPATH=%~dp0
+
if "%1"=="" GOTO :EOF
if "%1"=="dllplugin" GOTO :EOF
del *.d*
del test_dllplugin.exe
copy dllplugin.c %1.c
-..\tcc\tcc -shared %1.c
-..\tcc\tcc test_dllplugin.c %1.def
+..\tcc\tcc -shared %FULLPATH%%1.c
+..\tcc\tcc %FULLPATH%test_dllplugin.c %1.def
test_dllplugin.exe
+del %1.c
del *.d*
del test_dllplugin.exe
diff --git a/plugin/dll_call_test.py b/plugin/dll_call_test.py
new file mode 100644
index 0000000..69e0813
--- /dev/null
+++ b/plugin/dll_call_test.py
@@ -0,0 +1,35 @@
+import rlcompleter, readline;readline.parse_and_bind('tab:complete')
+import os, sys, platform, ctypes
+
+def dll_call(plugin, cmd, login, password):
+ dllpath = f"..\\dllplugin\\{plugin}.dll"
+ if not os.path.exists(dllpath):
+ return f'{dllpath} not found'
+ if platform.architecture()[0] != '32bit':
+ return f'You are use python not a 32bit: {platform.architecture()[0]}'
+ dll = ctypes.CDLL(dllpath)
+ request = f'''\n
+ \n
+ 007F09DA\n
+ {login}\n
+ {password}\n
+ '''
+
+ buf = ctypes.create_string_buffer(1024)
+ dll.IssaPlugin.argtypes = [ctypes.c_char_p,ctypes.c_char_p,ctypes.c_char_p,ctypes.c_long]
+ dll.IssaPlugin.restype = None
+ dll.IssaPlugin(ctypes.c_char_p(cmd.encode('cp1251')),ctypes.c_char_p(request.encode('cp1251')),buf,len(buf))
+
+ return buf.value.decode('cp1251')
+
+if __name__ == '__main__':
+
+ if len(sys.argv) != 1+4:
+ print(f'usage: {sys.argv[0]} plugin cmd(Info or Execute) login passw')
+ sys.exit()
+ plugin = sys.argv[1]
+ cmd = sys.argv[2]
+ login = sys.argv[3]
+ password = sys.argv[4]
+
+ print(dll_call(plugin, cmd, login, password))
diff --git a/plugin/mbplugin.bat b/plugin/mbplugin.bat
index 273585a..d74d70d 100644
--- a/plugin/mbplugin.bat
+++ b/plugin/mbplugin.bat
@@ -1,2 +1,5 @@
@echo off
-C:\mbplugin\python\python C:\mbplugin\plugin\mbplugin.py %1
\ No newline at end of file
+%~d0
+cd %~dp0
+
+..\python\python ..\plugin\mbplugin.py %1
\ No newline at end of file
diff --git a/plugin/mbplugin.py b/plugin/mbplugin.py
index 0fd7681..81fb72e 100644
--- a/plugin/mbplugin.py
+++ b/plugin/mbplugin.py
@@ -19,7 +19,7 @@ def result_to_xml(result):
def main():
- logging.basicConfig(filename="c:\\mbplugin\\log\\mbplugin.log", level=logging.INFO,
+ logging.basicConfig(filename="..\\log\\mbplugin.log", level=logging.INFO,
format=u'[%(asctime)s] %(levelname)s %(funcName)s %(message)s')
# В коммандной строке указан плагин ?
if len(sys.argv) < 2:
diff --git a/plugin/personalsetting.py.example b/plugin/personalsetting.py.example
index 2e575bc..8459bd4 100644
--- a/plugin/personalsetting.py.example
+++ b/plugin/personalsetting.py.example
@@ -5,4 +5,5 @@ stocks= {
'BROKER_RU': {'STOCKS':(('AAPL',1,'Y'),('TATNP',16,'M'),('FXIT',1,'M')), 'REMAIN': {'USD':5, 'RUB':536}, 'CURRENC': 'USD'}
}
-SQLITESTORE = False # Сохранять параллельно балансы в БД SQLITE ?
\ No newline at end of file
+SQLITESTORE = not False # Сохранять параллельно балансы в БД SQLITE ?
+SQLITEPATH = r'..\DB\BalanceHistory.sqlite'
diff --git a/plugin/store.py b/plugin/store.py
index 241f887..40c273e 100644
--- a/plugin/store.py
+++ b/plugin/store.py
@@ -2,8 +2,8 @@
import sys;sys.dont_write_bytecode = True
import os,sys, pickle, requests
-storefolder = 'C:\\mbplugin\\store'
-storename = 'C:\\mbplugin\\store\\persistent_store'
+storefolder = '..\\store'
+storename = '..\\store\\persistent_store'
def get_from_store(key):
diff --git a/plugin/test2.py b/plugin/test2.py
index a1ae8d9..9691957 100644
--- a/plugin/test2.py
+++ b/plugin/test2.py
@@ -33,8 +33,8 @@ def get_balance(login, password, storename=None):
captcha_text = ''
response1_text = ''
url = 'https://lk.megafon.ru/login/'
- cap_urls = [i for i in bs4.BeautifulSoup(
- response1_text).findAll('img') if i['alt'] == 'CAPTCHA']
+ img_tag = bs4.BeautifulSoup(response1_text, 'html.parser').findAll('img')
+ cap_urls = [i for i in img_tag if i['alt'] == 'CAPTCHA']
if len(cap_urls) > 0:
captcha_url = urlparse.urljoin(url, cap_urls[0]['src'])
buffer = session.get(captcha_url).content
diff --git a/plugin/test_mbplugin_dll_call.bat b/plugin/test_mbplugin_dll_call.bat
new file mode 100644
index 0000000..7b52201
--- /dev/null
+++ b/plugin/test_mbplugin_dll_call.bat
@@ -0,0 +1,16 @@
+@ECHO OFF
+%~d0
+cd %~dp0
+
+if "%~1"=="" goto NOPARAM
+if "%~2"=="" goto NOPARAM
+if "%~3"=="" goto NOPARAM
+echo INFO:
+..\python\python.exe ..\plugin\dll_call_test.py %1 Info %2 %3
+echo EXECUTE:
+..\python\python.exe ..\plugin\dll_call_test.py %1 Execute %2 %3
+pause
+
+goto :EOF
+:NOPARAM
+ECHO Use %0 p_plugin login pass
\ No newline at end of file
diff --git a/plugin/test_mbplugin_login_pass.bat b/plugin/test_mbplugin_login_pass.bat
index 33e0e9b..95c5051 100644
--- a/plugin/test_mbplugin_login_pass.bat
+++ b/plugin/test_mbplugin_login_pass.bat
@@ -1,9 +1,12 @@
@ECHO OFF
+%~d0
+cd %~dp0
+
if "%~1"=="" goto NOPARAM
if "%~2"=="" goto NOPARAM
if "%~3"=="" goto NOPARAM
SET RequestVariable="007F09DA%2%3"
-call C:\mbplugin\plugin\mbplugin.bat %1
+call ..\plugin\mbplugin.bat %1
pause
goto :EOF
diff --git a/plugin/test_mbplugin_set.bat b/plugin/test_mbplugin_set.bat
index 431d2f8..e69f6c8 100644
--- a/plugin/test_mbplugin_set.bat
+++ b/plugin/test_mbplugin_set.bat
@@ -1,2 +1,6 @@
+@echo OFF
+%~d0
+cd %~dp0
+
@SET RequestVariable="007F09DAloginloginpassword123456"
-@C:\mbplugin\plugin\mbplugin.bat p_test
\ No newline at end of file
+@..\plugin\mbplugin.bat p_test
\ No newline at end of file
diff --git a/python/get_python.bat b/python/get_python.bat
index de8ada7..dfd0648 100644
--- a/python/get_python.bat
+++ b/python/get_python.bat
@@ -1,21 +1,24 @@
-c:
-mkdir C:\mbplugin\python
-cd C:\mbplugin\python
+%~d0
+cd %~dp0
-@REM C:\mbplugin\python:https://www.python.org/ftp/python/3.8.3/python-3.8.3-embed-win32.zip
-curl -LOk https://www.python.org/ftp/python/3.8.3/python-3.8.3-embed-win32.zip
-7z x python-3.8.3-embed-win32.zip
+@REM python __pycache__
+set PYTHONDONTWRITEBYTECODE=x
-@REM https://bootstrap.pypa.io/get-pip.py C:\mbplugin\python
-curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
+@REM mbplugin\python:https://www.python.org/ftp/python/3.8.3/python-3.8.3-embed-win32.zip
+if not exist python38.zip curl -LOk https://www.python.org/ftp/python/3.8.3/python-3.8.3-embed-win32.zip
+if not exist python38.zip 7z x python-3.8.3-embed-win32.zip
+if exist python-3.8.3-embed-win32.zip del python-3.8.3-embed-win32.zip
-@REM C:\mbplugin\python
-python get-pip.py
+@REM https://bootstrap.pypa.io/get-pip.py mbplugin\python
+if not exist get-pip.py curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
-@REM C:\mbplugin\python\python38._pth ( #) import site
+@REM mbplugin\python
+if not exist Scripts\pip.exe python get-pip.py
+
+@REM mbplugin\python\python38._pth ( #) import site
python -c "d=open('python38._pth').read();open('python38._pth','w').write(d.replace('#import site','import site'))"
-@REM C:\mbplugin\python
+@REM mbplugin\python
python -m pip install requests pillow beautifulsoup4 pyodbc pyreadline
@REM tkinter python
diff --git a/readme.md b/readme.md
index 319c043..fcd6826 100644
--- a/readme.md
+++ b/readme.md
@@ -6,37 +6,41 @@ DLL шлюз дает возможность писать собственные
## Установка Вариант 1 Готовый архив (простой)
Архив можно найти в [releases](https://github.com/artyl/mbplugin/releases) на github или в форуме на [4pda](https://4pda.ru/forum/index.php?showtopic=985296) посвященном MobileBalance.
-Архив распаковать в папку C:\mbplugin
+Архив распаковать, после распаковки если путь отличается от c:\mbplugin необходимо запустить dllsource\compile_all_p.bat, после этого текущие пути будут прописаны в DLL
## Установка Вариант 2 Из github
-Склонировать репозиторий в папку C:\mbplugin
-git clone C:\mbplugin
+Склонировать репозиторий c github
+```
+git clone
+```
загрузить и распаковать tcc и python:
-TCC: C:\mbplugin\tcc\get_tcc.bat
-PYTHON: C:\mbplugin\python\get_python.bat
-tkinter для python, если нужен ввод капчи для python к сожалению автоматом поставить не получиться, нашел только [такой](https://stackoverflow.com/questions/37710205/python-embeddable-zip-install-tkinter)
-Сборка всех DLL: C:\mbplugin\dllsource\compile_all_p.bat
-После этого все DLL будут находится в папке C:\mbplugin\dllplugin
-Если есть желание использовать свой питон, тогда можно поменять вызов в C:\mbplugin\plugin\mbplugin.bat
+```
+tcc\get_tcc.bat
+python\get_python.bat
+```
+tkinter для python, если нужен ввод капчи для python к сожалению автоматом поставить не получиться, нашел только [такой способ](https://stackoverflow.com/questions/37710205/python-embeddable-zip-install-tkinter)
+Сборка всех DLL: dllsource\compile_all_p.bat
+После этого все DLL будут находится в папке mbplugin\dllplugin
+Если есть желание использовать свой питон, тогда можно поменять вызов в mbplugin\plugin\mbplugin.bat
## Использование.
-Пути, по крайней мере пока, жестко захардкожены и все должно лежать именно в такой структуре в папке C:\mbplugin
+Пути, жестко прописываются в DLL, в готовой сборке они смотрят в C:\mbplugin, если ваша папка отличается от этой, то запустите dllsource\compile_all_p.bat
Подключить DLL для нужных провайдеров (Настройки\Плагины\Операторы Добавить и выбрать DLL для нужных операторов)
В настройках для соответсвующего телефона выбрать провайдера соответствующей DLL
## На данный момент реализованы плагины:
(Источником информации послужили как собственное изучение так и существующие плагины, так что пользуясь случаем хочу выразить благодарность всем авторам
leha3d Pasha comprech y-greek и другим, кто тратил свои силы и время на реверс сайтов операторов и разработку)
-test1 - Простой тест с демонстрацией всех полей (правда оказалось, что MB из DLL принимает только Balance Expired Min Internet TarifPlan BlockStatus AnyString)
+test1 - Простой тест с демонстрацией всех полей (MB из DLL принимает далеко не все Balance Expired Min Internet TarifPlan BlockStatus AnyString)
test2 - Пример реализации ввода капчи
+mts - МТС
beeline - Билайн
-cardtel - Cardtel (IP телефония)
megafon - Мегафон
-mts - МТС
-sodexo - Получение баланса карты Sodexo (подарочные карты)
-strelka - Баланс карты стрелка
tele2 - ТЕЛЕ2
+strelka - Баланс карты стрелка
zadarma - Zadarma.com (IP телефония)
+cardtel - Cardtel (IP телефония)
+sodexo - Получение баланса карты Sodexo (подарочные карты)
usd - Курс доллара с RBC
eur - Курс евро с RBC
financeyahoo - Курс ценных бумаг с finance.yahoo.com
@@ -45,36 +49,46 @@ stock - Рассчет цены портфеля ценных бумаг
sipnet - Sipnet (IP телефония)
avtodor-tr - Автодор транспондер
-## Как проверить вручную
-запустите из C:\mbplugin\plugin:
-C:\mbplugin\plugin\test_mbplugin_login_pass.bat p_test login password
+## Как проверить что все работает
+### ВАЖНО!
+DLL собраны 32 битном компиляторе, и вызываться должны из 32 битного приложения 32 битную DLL вызвать из 64 битного приложения нельзя.
+### Проверка самих плагинов
+запустите из mbplugin\plugin:
+test_mbplugin_login_pass.bat p_test1 login password
Если в консоль будет выведен XML, то скорее всего у вас все работает:
```
124.45 ....
```
Таким же образом можно проверить любой плагин:
C:\mbplugin\plugin\test_mbplugin_login_pass.bat p_[имя плагина на python] [логин] [пароль]
+### Проверка DLL
+запустите из mbplugin\plugin:
+plugin\test_mbplugin_dll_call.bat test1 123 456
+Должен выдать XML с инфо о плагине и XML с балансом
+При желании так можно проверить любую DLL но учитывая, что они собираются пачкой, то и с остальными все ок.
+Если возникли ошибки, попробуйте выполнить dllsource\compile_all_p.bat
## Как это работает
Mobilebalance вызывает DLL передавая ей логин и пароль через xml строку
-DLL вызывает C:\mbplugin\plugin\mbplugin.bat передавая ему имя плагина в качестве параметра, а переданный XML через переменную окружения RequestVariable
-mbplugin.bat вызывает mbplugin.py в котором вызывается соответсвующий DLL плагин.
+В самой DLL никакого функционала нет, она служит лишь оберткой для передачи вызова в mbplugin\plugin\mbplugin.bat
+DLL вызывает mbplugin\plugin\mbplugin.bat передавая ему имя плагина в качестве параметра, а переданный XML через переменную окружения RequestVariable
+mbplugin.bat вызывает mbplugin.py в котором вызывается соответсвующий python плагин.
mbplugin.bat возвращает результат через stdout.
## Почему так сделано.
Данные по параметрам вызова DLL были получены с помощью реверса существующего DLL плагина.
Я постарался сделать все так, чтобы все можно было собрать за 10 минут не устанавливая 10 гигабайтные компиляторы, минималистичная DLL весь код вынесен в скрипты.
Конечно DLL можно собрать и на vc и gpp и на Delphi и много на чем еще,
-но для этого нужно много возни с установкой среды, в моем варианте все можно собрать с нуля за 10 минут скачав несколько десятков мегабайт.
-DLL мог без труда любой желающий и убедится что в ней нет закладок.
+но для этого нужно много возни с установкой среды, в моем варианте все можно собрать с нуля за 10 минут скачав несколько десятков мегабайт.
+Количество кода для DLL минимум, чтобы любой желающий мог без труда убедится что в нем нет закладок.
+
Остальной код на скриптах, и его можно проверить в любой момент.
C я знаю не очень хорошо, поэтому единственный простой способ передать request я нашел через переменную окружения, а возврат осуществляется через поток вывода.
-Пути прописаны абсолютными, потому что из DLL выяснить по какому пути она находится оказалось очень нетривиальной задачей, даже имя ее узнать очень непросто.
-Хотел сохранить настройки путя в реестре, но из реестра прочитать оказалось тоже не просто.
-В у меня получилось сделать только так, код на C получился достаточно корявый, но у меня вроде работоспособен.
+Пути в папке mbplugin внутри DLL приходится прописывать абсолютными, потому что из DLL выяснить по какому пути она находится оказалось очень нетривиальной задачей, даже имя DLL узнать очень непросто. В принципе это проблема небольшая на tcc все пересобирается за пару секунд.
+Хотел сохранить настройки для путей в реестре, но из реестра прочитать оказалось тоже не просто.
+В результате у меня получилось сделать только так, код на C получился не очень хороший, но работоспособный.
Если кто в состоянии причесать сишный код, буду признателен.
-Вызов bat файла а не python сделан для того чтобы если будет желание отвязаться от python
-с минимумом изменений в остальном коде.
+Вызов bat файла а не напрямую скрипта python сделан для того чтобы если будет желание отвязаться от python, с минимумом изменений в остальном коде.
Т.к. в запросе передается только логин и пароль, то нам приходится сделать по отдельной DLL для каждого сервиса
Чтобы оставить задел на будущее я для плагинов добавил еще префиксы, для питона это p_
@@ -83,27 +97,22 @@ C я знаю не очень хорошо, поэтому единственн
tele2 - имя модуля на python который получает баланс
p_tele2.dll - dll которую мы подключаем в mobilebalance
-Не все поля оказывается понимает, как оказалось, например не понимает SMS,
-Насколько я понял воспринимает только:
+В процессе эксплуатации выяснилось, что mobilebalance оказывается все поля принимает из результата, как оказалось, например не понимает SMS,
+Список принимаемых полей достаточно короткий:
Balance Expired Min Internet TarifPlan BlockStatus AnyString
Все кроме этого будет проигнорировано
-Несмотря на то что на первый взгляд это все идет не через браузер mobilebalance все равно перед стартом DLL
-дергает движок IE (res://ieframe.dll/navcancl.htm и about:blank) - это видно по логу и появлению файлов
-в папке кэша IE, так что не исключаю, что часть каких-то глюков может по прежнему лечиться чисткой кэша
-браузера, хотя это и маловероятно.
-
-Все это добро выложил на [github](https://github.com/artyl/mbplugin)
-Там только исходники, после загрузки проекта поместить его в папку C:\mbplugin
+Несмотря на то что на первый взгляд это все идет не через браузер mobilebalance все равно перед стартом DLL дергает движок IE (res://ieframe.dll/navcancl.htm и about:blank) - это видно по логу и появлению файлов в папке кэша IE, так что не исключаю, что часть каких-то глюков может по прежнему лечиться чисткой кэша браузера, хотя это и маловероятно.
## Как написать свой плагин
Если на python, то это файл с функцией get_balance(login, password, storename)
-storename нужен для хранения сессии, формируется как имя плагина + login
+storename это строка, используемая как ключ для хранения сессии. Формируется как имя плагина + login
Функция возвращяет результат в виде словаря.
-После того как плагин будет готов запускаем C:\mbplugin\dllsource\compile_all_p.bat и будут пересобраны DLL для всех имеющихся в папке C:\mbplugin\plugin плагинов
+Можно посмотреть как сделаны другие плагины, также есть простые тестовые.
+После того как плагин будет готов запускаем C:\mbplugin\dllsource\compile_all_p.bat и будут пересобраны DLL для всех имеющихся в папке C:\mbplugin\plugin плагинов.
Подключаем полученную DLL в MobileBalance и используем ее для получения баланса.
-ВАЖНО. В xml который возвращает плагин поля case sensitive, так что если будет balance вместо Balance
-MB будет писать что баланс равен нулю.
+
+ВАЖНО. В xml который возвращает плагин поля case sensitive, так что если будет balance вместо Balance MB будет писать что баланс равен нулю.
--- Структура request который приходит из mobilebalance через переменную окружения ----------
```
diff --git a/tcc/get_tcc.bat b/tcc/get_tcc.bat
index 74497f8..465d795 100644
--- a/tcc/get_tcc.bat
+++ b/tcc/get_tcc.bat
@@ -1,6 +1,6 @@
-c:
-mkdir C:\mbplugin\tcc
-cd C:\mbplugin\tcc
+%~d0
+cd %~dp0
+
curl -LOk http://download.savannah.gnu.org/releases/tinycc/tcc-0.9.27-win32-bin.zip
7z x tcc-0.9.27-win32-bin.zip -o..
del tcc-0.9.27-win32-bin.zip
\ No newline at end of file