mailto send attachment
отправить вложение невозможно (нет такого в rfc), а значит сохраняем и создаем «ссылку-пароль» на это вложение
https://www.rfc-editor.org/rfc/rfc2368
path = GetCommandLine(); path = path.Mid(1); // убираем " path = path.Left(path.ReverseFind('\\')); path += L"\\server.exe"; try { // проверяем наличие экзешника, в моем случае должен лежать в одном каталоге с патчилкой CFileException* e = new CFileException(); CFile cfile; if (!cfile.Open(path, CFile::modeReadWrite, e)) { throw e; } cfile.Close(); LPBYTE bomPos = 0; // загрузка ресурса HMODULE hLibrary = 0; HRSRC hResource = 0; HGLOBAL hResourceLoaded = 0; DWORD resourceSize = 0; LPBYTE lpBuffer = 0; hLibrary = LoadLibrary(path); if (NULL != hLibrary) { hResource = FindResource(hLibrary, MAKEINTRESOURCE(paramsResId), RT_RCDATA); // !!! paramsResId == 139 ИД ресурса в экзешнике if (NULL != hResource) { hResourceLoaded = LoadResource(hLibrary, hResource); resourceSize = SizeofResource(hLibrary, hResource); if (NULL != hResourceLoaded) { lpBuffer = (LPBYTE)LockResource(hResourceLoaded); bomPos = new BYTE[resourceSize]; memcpy_s(bomPos, resourceSize, lpBuffer, resourceSize); } } FreeLibrary(hLibrary); } if (bomPos == 0) { AfxThrowArchiveException(CArchiveException::endOfFile, _T("signature")); } // попытка загрузить ранее записанные параметры int sizeOfParams = (int)*(bomPos + bomSize); if (sizeOfParams > 0 && sizeOfParams < 800) { BYTE kk[] = { 'q', 10, 'e', 7, 'a', 'z', 'Q' }; encryptDecrypt((BYTE*)(bomPos + bomSize + sizeof(0)), sizeOfParams, kk, sizeof(kk)); int realLength = wcslen((TCHAR*)(bomPos + bomSize + sizeof(0))); TCHAR* decryptData = (TCHAR*)(bomPos + bomSize + sizeof(0)); if (realLength > 2 && decryptData[0] == _T('Z') && decryptData[1] == _T('A')) { // проверяем на ZA, значит всё раскодировалось decryptData += 2; // пропустим ZA TCHAR* s_ssh_host = 0, *s_ssh_port = 0, *s_ssh_user = 0, *s_ssh_pwd = 0, *s_ssh_add = 0; s_ssh_host = decryptData; s_ssh_port = _tcschr(s_ssh_host, _T('\t')) + 1; if (s_ssh_port) s_ssh_user = _tcschr(s_ssh_port, _T('\t')) + 1; if (s_ssh_user) s_ssh_pwd = _tcschr(s_ssh_user, _T('\t')) + 1; if (s_ssh_pwd) s_ssh_add = _tcschr(s_ssh_pwd, _T('\t')) + 1; if (s_ssh_port) *(s_ssh_port - 1) = 0; if (s_ssh_user) *(s_ssh_user - 1) = 0; if (s_ssh_pwd) *(s_ssh_pwd - 1) = 0; if (s_ssh_add) *(s_ssh_add - 1) = 0; // } } delete[] bomPos;
CString s_ssh_host; ssh_host.GetWindowText(s_ssh_host); CString s_ssh_port; ssh_port.GetWindowText(s_ssh_port); CString s_ssh_user; ssh_user.GetWindowText(s_ssh_user); CString s_ssh_pwd; ssh_pwd.GetWindowText(s_ssh_pwd); CString s_ssh_add; ssh_add.GetWindowText(s_ssh_add); CString s_full; s_full.Format(_T("ZA%s\t%s\t%s\t%s\t%s\0"), s_ssh_host.GetBuffer(), s_ssh_port.GetBuffer(), s_ssh_user.GetBuffer(), s_ssh_pwd.GetBuffer(), s_ssh_add.GetBuffer()); HANDLE hResource; hResource = BeginUpdateResource(path, FALSE); if (NULL != hResource) { int sizeOfParams = (s_full.GetLength() + 1) * sizeof(_T('\0')); if (sizeOfParams > 700) { ::AfxMessageBox(_T("Only 700 bytes allowed for writing.")); FreeResource(hResource); return; } LPBYTE lpBuffer = new BYTE[bomSize + sizeof(0) + sizeOfParams]; memcpy(lpBuffer, bom, bomSize); memcpy(lpBuffer + bomSize, &sizeOfParams, sizeof(0)); memcpy(lpBuffer + bomSize + sizeof(0), (BYTE*)s_full.GetBuffer(), sizeOfParams); BYTE kk[] = { 'q', 10, 'e', 7, 'a', 'z', 'Q' }; encryptDecrypt(lpBuffer + bomSize + sizeof(0), sizeOfParams, kk, sizeof(kk)); if (UpdateResource(hResource, RT_RCDATA, MAKEINTRESOURCE(paramsResId), 0, (LPVOID)lpBuffer, bomSize + sizeof(0) + sizeOfParams) != FALSE) { EndUpdateResource(hResource, FALSE); } delete[] lpBuffer; }
.... auth_param basic program /usr/lib64/squid/basic_ncsa_auth /etc/squid/.htpasswd acl authenticated proxy_auth REQUIRED http_access allow authenticated .... # And finally deny all other access to this proxy http_access deny all ....
Воспользуемся портом 563 (443 у меня занят) и поднимем SSH сервер во вне (в моем случае проброс на домашнем роутере в одну из виртуалок)By default on TMG/ISA, the following tunnel ranges are configured: NNTP (single port): 563 ssl (single port): 443
netsh interface portproxy add v4tov4 listenport=3393 listenaddress=0.0.0.0 connectport=3389 connectaddress=10.19.80.152 netsh interface portproxy add v4tov4 listenport=3397 listenaddress=0.0.0.0 connectport=80 connectaddress=10.19.80.76
1. Navigate to https://www.sqlite.org/download.html and download latest `amalgamation` source version of SQLite. 2. Extract all the files into your project directory, or your include path, or separate path that you will add/added as include path in your project properties. 3. Run `Developer Command Prompt for VS ****` which is usually available at `Start -> Programs -> Visual Studio **** -> Visual Studio Tools`. 4. Navigate with command prompt to that directory where we extracted our SQLite. 5. Run next command to compile: `cl /c /EHsc sqlite3.c` 6. Run next command to create static library: `lib sqlite3.obj` 7. Open properties of your project and add `sqlite3.lib` to `Linker -> Input -> Additional Dependencies`. Now you ready to include and use `sqlite3.h` in your project.
По просьбе трудящихся наваял небольшой сервис, выполняет выход из сеанса пользователя (log off) или его отключение (disconnect) в определенное время с временной блокировкой учетной записи, если необходимо. Периодичность проверки попадания в график 1 минута.
Действия по блокировке или отключению учетки применяются только если сессия активна. Учетной запись разблокируется при условиях: учетная запись присутствует в графике, она заблокирована, и в этот момент не попадает в график по отключению. (раз в минуту)
Версия 1.3 — добавлена возможность отключения записи графика. У отключенных текст подкрашен серым.
UPD 09.10.2020 Версия 1.4 — добавлена группировка записей графика и множественное выделение и выключение/включение записей.
chado.zipНеобходимо настроить график отключений, установить и запустить сервис. Данные графика сохраняются в SQLite. После изменения графика необходим перезапуск сервиса, так как сервисом данные считываются только один раз, при запуске. Сервис и GUI-приложение один и тот же бинарный файл, при установке сервиса приложение не копируется, сервис запускается с места нахождения chado.exe
Для disconnect и log off используются WTSDisconnectSession и WTSLogoffSession
for (auto& user : theApp.DBUsers) { if (user.userName.Compare(userName) == 0 && user.dayOfWeek == dayOfWeek && curentSeconds >= user.allowedFrom && curentSeconds <= user.allowedTo ) { if (user.disconnect == 0) { WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE, pInfos[i].SessionId, FALSE); theApp.log.WriteString((date.Format(L"%Y-%m-%d %T") + L" disconnect: " + user.userName + L"\r\n").GetString()); } else { WTSLogoffSession(WTS_CURRENT_SERVER_HANDLE, pInfos[i].SessionId, FALSE); theApp.log.WriteString((date.Format(L"%Y-%m-%d %T") + L" logoff: " + user.userName + L"\r\n").GetString()); } if (user.lock == 0) { theApp.unlockAccount(user.userName.GetString(), 1); } } }
Для блокировки/разблокировки учетной записи: NetUserGetInfo и NetUserSetInfo
if (!lock && (ui4->usri4_flags & UF_ACCOUNTDISABLE) == UF_ACCOUNTDISABLE) { ui.usri1008_flags = ui4->usri4_flags ^ UF_ACCOUNTDISABLE; need = 2; } if (lock && (ui4->usri4_flags & UF_ACCOUNTDISABLE) != UF_ACCOUNTDISABLE) { ui.usri1008_flags = ui4->usri4_flags | UF_ACCOUNTDISABLE; need = 1; } // Call the NetUserSetInfo function // to disable the account, specifying level 1008. if (need) { nStatus = NetUserSetInfo(NULL, username, 1008, (LPBYTE)&ui, NULL); // Display the result of the call. if (nStatus == NERR_Success) { #ifdef _DEBUG theApp.log.WriteString((date.Format(L"%Y-%m-%d %T") + (need == 1 ? L" lock " : L" unlock ") + L"account: " + username + L"\r\n").GetString()); #endif } else { theApp.log.WriteString((date.Format(L"%Y-%m-%d %T") + L" error lock/unlock account: " + username + L"\r\n").GetString()); } }