File indexing completed on 2025-01-12 04:20:12

0001 /// <summary>
0002 /// Snarl C++ interface implementation
0003 /// API version 42
0004 ///
0005 /// http://sourceforge.net/apps/mediawiki/snarlwin/index.php?title=Windows_API
0006 /// https://sourceforge.net/apps/mediawiki/snarlwin/index.php?title=Generic_API
0007 ///
0008 /// Written and maintained by Toke Noer Nøttrup (toke@noer.it)
0009 ///
0010 ///  Please note the following changes compared to the VB6 (official API) dokumentation:
0011 ///  - Function names doesn't have the prefix "sn". Naming of constants and variables are
0012 ///    generally changed to follow Microsoft C# standard. This naming convention is kept for
0013 ///    the C++ version, to keep them alike.
0014 ///  - Grouped variables like SNARL_LAUNCHED, SNARL_QUIT is enums in SnarlEnums namespace.
0015 ///  - Message events like SNARL_NOTIFICATION_CLICKED, is found in SnarlEnums::MessageEvent.
0016 ///  - Please note that string functions return NULL when they fail and not an empty string.
0017 ///  - Some functions in the VB API takes an appToken as first parameter. This token is a
0018 ///    member variable in C++ version, so it is omitted from the functions.
0019 ///    (Always call RegisterApp as first function!)
0020 ///  - Functions manipulating messages (Update, Hide etc.) still takes a message token as
0021 ///    parameter, but you can get the last message token calling GetLastMsgToken();
0022 ///    Example: snarl.Hide(snarl.GetLastMsgToken());
0023 ///
0024 /// The functions in SnarlInterface both have ANSI(UTF8) and UNICODE versions.
0025 /// If the LPCWSTR (unicode) version of the functions are called, the strings
0026 /// are converted to UTF8 by SnarlInterface before sent to Snarl. So using the
0027 /// ANSI/UTF8/LPCSTR versions of the functions are faster!
0028 ///
0029 /// See https://sourceforge.net/apps/mediawiki/snarlwin/index.php?title=Windows_API#C.2B.2B
0030 /// for example code etc.
0031 /// </summary>
0032 ///----------------------------------------------------------------------------
0033 /// <VersionHistory>
0034 ///  2011-07-31 : General update to match VB6 SVN rev. 232
0035 ///             : Added AppFlags and MessagePriority enums.
0036 ///  2011-07-12 : MingW64 fixes by Hannah von Reth
0037 ///  2011-07-07 : Some changes to compile under VS2008
0038 ///                 - Changed vector iterators to begin/end instead of cbegin/cend
0039 ///                 - Removed const in PairType
0040 ///  2011-02-09 : Fix for wrong parameters in AddClass
0041 ///  2011-02-06 : Updated to rev. 3 of the wiki documentation
0042 ///  2011-02-02 : First release of V42 Snarl API implementation
0043 /// </VersionHistory>
0044 ///
0045 /// <Todo>
0046 /// </Todo>
0047 
0048 #ifndef _CRT_SECURE_NO_WARNINGS
0049 #define _CRT_SECURE_NO_WARNINGS
0050 #endif
0051 
0052 #include "SnarlInterface.h"
0053 
0054 namespace Snarl
0055 {
0056 namespace V42
0057 {
0058 
0059 // workaround for mingw-w64 bug
0060 #ifdef __MINGW64_VERSION_MAJOR
0061 extern "C" {
0062     __declspec(dllimport) errno_t __cdecl strcpy_s(char *_Dst, size_t _SizeInBytes, const char *_Src);
0063     __declspec(dllimport) errno_t __cdecl wcscpy_s(wchar_t *_Dst, size_t _SizeInBytes, const wchar_t *_Src);
0064     __declspec(dllimport) errno_t __cdecl strncat_s(char *_Dst, size_t _DstSizeInChars, const char *_Src, size_t _MaxCount);
0065 }
0066 #endif //__MINGW64_VERSION_MAJOR
0067 
0068 // ----------------------------------------------------------------------------
0069 // Static Snarl interface functions
0070 // ----------------------------------------------------------------------------
0071 
0072 UINT SnarlInterface::AppMsg()
0073 {
0074     return RegisterWindowMessage(SnarlAppMsg);
0075 }
0076 
0077 UINT SnarlInterface::Broadcast()
0078 {
0079     return RegisterWindowMessage(SnarlGlobalMsg);
0080 }
0081 
0082 LONG32 SnarlInterface::DoRequest(LPCSTR request, UINT replyTimeout)
0083 {
0084     DWORD_PTR nResult = 0;
0085 
0086     HWND hWnd = GetSnarlWindow();
0087     if (!IsWindow(hWnd)) {
0088         return -SnarlEnums::ErrorNotRunning;
0089     }
0090 
0091     // Create COPYDATASTRUCT
0092     COPYDATASTRUCT cds;
0093     cds.dwData = 0x534E4C03;           // "SNL",3
0094     cds.cbData = (DWORD)strlen(request);      // No knowledge of max string length
0095     cds.lpData = const_cast<char *>(request);
0096 
0097     // Send message
0098     if (SendMessageTimeout(hWnd, WM_COPYDATA, (WPARAM)GetCurrentProcessId(), (LPARAM)&cds, SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, replyTimeout, &nResult) == 0) {
0099         // Handle error
0100         DWORD nError = GetLastError();
0101         LONG32 errorResult = 0;
0102         if (nError == ERROR_TIMEOUT) {
0103             errorResult = -SnarlEnums::ErrorTimedOut;
0104         } else {
0105             errorResult = -SnarlEnums::ErrorFailed;
0106         }
0107 
0108         return errorResult;
0109     } else {
0110         return (LONG32)nResult;
0111     }
0112 }
0113 
0114 LONG32 SnarlInterface::DoRequest(LPCWSTR request, UINT replyTimeout)
0115 {
0116     LONG32 nResult = 0;
0117 
0118     // Convert to UTF8
0119     LPSTR utf8Request = WideToUTF8(request);
0120     if (utf8Request == NULL) {
0121         return -SnarlEnums::ErrorCppInterface;
0122     }
0123 
0124     nResult = DoRequest(utf8Request, replyTimeout);
0125 
0126     // Cleanup and return result
0127     FreeString(utf8Request);
0128     return nResult;
0129 }
0130 
0131 std::basic_string<char> &SnarlInterface::Escape(std::basic_string<char> &str)
0132 {
0133     std::basic_string<char>::size_type strLength = str.length();
0134     for (std::basic_string<char>::size_type i = 0; i < strLength; ++i) {
0135         if (str.at(i) == '=') {
0136             str.insert(++i, "=");
0137             ++strLength;
0138         } else if (str[i] == '&') {
0139             str.insert(++i, "&");
0140             ++strLength;
0141         }
0142     }
0143 
0144     return str;
0145 }
0146 
0147 std::basic_string<wchar_t> &SnarlInterface::Escape(std::basic_string<wchar_t> &str)
0148 {
0149     std::basic_string<wchar_t>::size_type strLength = str.length();
0150     for (std::basic_string<wchar_t>::size_type i = 0; i < strLength; ++i) {
0151         if (str.at(i) == L'=') {
0152             str.insert(++i, L"=");
0153             ++strLength;
0154         } else if (str[i] == L'&') {
0155             str.insert(++i, L"&");
0156             ++strLength;
0157         }
0158     }
0159 
0160     return str;
0161 }
0162 
0163 LPCTSTR SnarlInterface::GetAppPath()
0164 {
0165     HWND hWnd = GetSnarlWindow();
0166     if (hWnd) {
0167         HWND hWndPath = FindWindowEx(hWnd, NULL, _T("static"), NULL);
0168         if (hWndPath) {
0169             TCHAR strTmp[MAX_PATH] = {0};
0170             int nReturn = GetWindowText(hWndPath, strTmp, MAX_PATH - 1);
0171             if (nReturn > 0) {
0172                 TCHAR *strReturn = AllocateString(nReturn + 1);
0173                 _tcsncpy(strReturn, strTmp, nReturn + 1);
0174                 strReturn[nReturn] = 0;
0175                 return strReturn;
0176             }
0177         }
0178     }
0179 
0180     return NULL;
0181 }
0182 
0183 LPCTSTR SnarlInterface::GetIconsPath()
0184 {
0185     TCHAR *szIconPath = NULL;
0186     LPCTSTR szPath = GetAppPath();
0187     if (!szPath) {
0188         return NULL;
0189     }
0190 
0191     size_t nLen = 0;
0192     nLen = _tcsnlen(szPath, MAX_PATH);
0193     if (nLen > 0) {
0194         nLen += 10 + 1; // etc\\icons\\ + NULL
0195         szIconPath = AllocateString(nLen);
0196 
0197         _tcsncpy(szIconPath, szPath, nLen);
0198         _tcsncat(szIconPath, _T("etc\\icons\\"), nLen);
0199     }
0200 
0201     FreeString(szPath);
0202 
0203     return szIconPath;
0204 }
0205 
0206 HWND SnarlInterface::GetSnarlWindow()
0207 {
0208     return FindWindow(SnarlWindowClass, SnarlWindowTitle);;
0209 }
0210 
0211 LONG32 SnarlInterface::GetVersion()
0212 {
0213     return DoRequest(Requests::VersionA());
0214 }
0215 
0216 BOOL SnarlInterface::IsSnarlRunning()
0217 {
0218     return IsWindow(GetSnarlWindow());
0219 }
0220 
0221 // --------------------------------------------------------------------------------------------
0222 // SnarlInterface member functions
0223 // --------------------------------------------------------------------------------------------
0224 
0225 SnarlInterface::SnarlInterface()
0226     : appToken(0), lastMsgToken(0), szPasswordA(NULL), szPasswordW(NULL)
0227 {
0228 }
0229 
0230 SnarlInterface::~SnarlInterface()
0231 {
0232     delete [] szPasswordA;
0233     delete [] szPasswordW;
0234 }
0235 
0236 //---------------------------------------------------------------------------------------------
0237 
0238 LONG32 SnarlInterface::AddAction(LONG32 msgToken, LPCSTR label, LPCSTR cmd)
0239 {
0240     // addaction?[token=<notification token>|app-sig=<signature>&uid=<uid>][&password=<password>]&label=<label>&cmd=<command>
0241 
0242     SnarlParameterList<char> spl(4);
0243     spl.Add("token", msgToken);
0244     spl.Add("password", szPasswordA);
0245 
0246     spl.Add("label", label);
0247     spl.Add("cmd", cmd);
0248 
0249     return DoRequest(Requests::AddActionA(), spl);
0250 }
0251 
0252 LONG32 SnarlInterface::AddAction(LONG32 msgToken, LPCWSTR label, LPCWSTR cmd)
0253 {
0254     SnarlParameterList<wchar_t> spl(4);
0255     spl.Add(L"token", msgToken);
0256     spl.Add(L"password", szPasswordW);
0257 
0258     spl.Add(L"label", label);
0259     spl.Add(L"cmd", cmd);
0260 
0261     return DoRequest(Requests::AddActionW(), spl);
0262 }
0263 
0264 LONG32 SnarlInterface::AddClass(LPCSTR classId, LPCSTR name, LPCSTR title, LPCSTR text, LPCSTR icon, LPCSTR sound, LONG32 duration, LPCSTR callback, bool enabled)
0265 {
0266     // addclass?[app-sig=<signature>|token=<application token>][&password=<password>]&id=<class identifier>&name=<class name>[&enabled=<0|1>][&callback=<callback>]
0267     //          [&title=<title>][&text=<text>][&icon=<icon>][&sound=<sound>][&duration=<duration>]
0268 
0269     SnarlParameterList<char> spl(11);
0270     spl.Add("token", appToken);
0271     spl.Add("password", szPasswordA);
0272 
0273     spl.Add("id", classId);
0274     spl.Add("name", name);
0275     spl.Add("enabled", enabled);
0276     spl.Add("callback", callback);
0277     spl.Add("title", title);
0278     spl.Add("text", text);
0279     spl.Add("icon", icon);
0280     spl.Add("sound", sound);
0281     if (duration != -1) {
0282         spl.Add("duration", duration);
0283     }
0284 
0285     return DoRequest(Requests::AddClassA(), spl);
0286 }
0287 
0288 LONG32 SnarlInterface::AddClass(LPCWSTR classId, LPCWSTR name, LPCWSTR title, LPCWSTR text, LPCWSTR icon, LPCWSTR sound, LONG32 duration, LPCWSTR callback, bool enabled)
0289 {
0290     SnarlParameterList<wchar_t> spl(11);
0291     spl.Add(L"token", appToken);
0292     spl.Add(L"password", szPasswordW);
0293 
0294     spl.Add(L"id", classId);
0295     spl.Add(L"name", name);
0296     spl.Add(L"enabled", enabled);
0297     spl.Add(L"callback", callback);
0298     spl.Add(L"title", title);
0299     spl.Add(L"text", text);
0300     spl.Add(L"icon", icon);
0301     spl.Add(L"sound", sound);
0302     if (duration != -1) {
0303         spl.Add(L"duration", duration);
0304     }
0305 
0306     return DoRequest(Requests::AddClassW(), spl);
0307 }
0308 
0309 LONG32 SnarlInterface::ClearActions(LONG32 msgToken)
0310 {
0311     // clearactions?[token=<notification token>|app-sig=<app-sig>&uid=<uid>][&password=<password>]
0312 
0313     SnarlParameterList<char> spl(2);
0314     spl.Add("token", msgToken);
0315     spl.Add("password", szPasswordA);
0316 
0317     return DoRequest(Requests::ClearActionsA(), spl);
0318 }
0319 
0320 LONG32 SnarlInterface::ClearClasses()
0321 {
0322     // clearclasses?[token=app-sig=<signature>|token=<application token>][&password=<password>]
0323 
0324     SnarlParameterList<char> spl(2);
0325     spl.Add("token", appToken);
0326     spl.Add("password", szPasswordA);
0327 
0328     return DoRequest(Requests::ClearClassesA(), spl);
0329 }
0330 
0331 LONG32 SnarlInterface::GetLastMsgToken() const
0332 {
0333     return lastMsgToken;
0334 }
0335 
0336 LONG32 SnarlInterface::Hide(LONG32 msgToken)
0337 {
0338     // hide?[token=<notification token>|app-sig=<app-sig>&uid=<uid>][&password=<password>]
0339 
0340     SnarlParameterList<char> spl(2);
0341     spl.Add("token", msgToken);
0342     spl.Add("password", szPasswordA);
0343 
0344     return DoRequest(Requests::HideA(), spl);
0345 }
0346 
0347 LONG32 SnarlInterface::IsVisible(LONG32 msgToken)
0348 {
0349     // isvisible?[token=<notification token>|app-sig=<app-sig>&uid=<uid>][&password=<password>]
0350 
0351     SnarlParameterList<char> spl(2);
0352     spl.Add("token", msgToken);
0353     spl.Add("password", szPasswordA);
0354 
0355     return DoRequest(Requests::IsVisibleA(), spl);
0356 }
0357 
0358 LONG32 SnarlInterface::Notify(LPCSTR classId, LPCSTR title, LPCSTR text, LONG32 timeout, LPCSTR iconPath, LPCSTR iconBase64, SnarlEnums::MessagePriority priority, LPCSTR uid, LPCSTR callback, LPCSTR value)
0359 {
0360     // notify?[app-sig=<signature>|token=<application token>][&password=<password>][&id=<class identifier>]
0361     //        [&title=<title>][&text=<text>][&timeout=<timeout>][&icon=<icon path>][&icon-base64=<MIME data>][&callback=<default callback>]
0362     //        [&priority=<priority>][&uid=<notification uid>][&value=<value>]
0363 
0364     SnarlParameterList<char> spl(12);
0365     spl.Add("token", appToken);
0366     spl.Add("password", szPasswordA);
0367 
0368     spl.Add("id", classId);
0369     spl.Add("title", title);
0370     spl.Add("text", text);
0371     spl.Add("icon", iconPath);
0372     spl.Add("icon-base64", iconBase64);
0373     spl.Add("uid", uid);
0374     spl.Add("callback", callback);
0375     spl.Add("value", value);
0376     if (timeout != -1) {
0377         spl.Add("timeout", timeout);
0378     }
0379     if (priority != SnarlEnums::PriorityUndefined) {
0380         spl.Add("priority", priority);    // -1 is a legal priority
0381     }
0382 
0383     LONG32 request = DoRequest(Requests::NotifyA(), spl);
0384     lastMsgToken = (request > 0) ? request : 0;
0385 
0386     return request;
0387 }
0388 
0389 LONG32 SnarlInterface::Notify(LPCWSTR classId, LPCWSTR title, LPCWSTR text, LONG32 timeout, LPCWSTR iconPath, LPCWSTR iconBase64, SnarlEnums::MessagePriority priority, LPCWSTR uid, LPCWSTR callback, LPCWSTR value)
0390 {
0391     SnarlParameterList<wchar_t> spl(12);
0392     spl.Add(L"token", appToken);
0393     spl.Add(L"password", szPasswordW);
0394 
0395     spl.Add(L"id", classId);
0396     spl.Add(L"title", title);
0397     spl.Add(L"text", text);
0398     spl.Add(L"icon", iconPath);
0399     spl.Add(L"icon-base64", iconBase64);
0400     spl.Add(L"uid", uid);
0401     spl.Add(L"callback", callback);
0402     spl.Add(L"value", value);
0403     if (timeout != -1) {
0404         spl.Add(L"timeout", timeout);
0405     }
0406     if (priority != SnarlEnums::PriorityUndefined) {
0407         spl.Add(L"priority", priority);    // -1 is a legal priority
0408     }
0409 
0410     LONG32 request = DoRequest(Requests::NotifyW(), spl);
0411     lastMsgToken = (request > 0) ? request : 0;
0412 
0413     return request;
0414 }
0415 
0416 LONG32 SnarlInterface::Register(LPCSTR signature, LPCSTR title, LPCSTR icon, LPCSTR password, HWND hWndReplyTo, LONG32 msgReply, SnarlEnums::AppFlags flags)
0417 {
0418     // register?app-sig=<signature>&title=<title>[&icon=<icon>][&password=<password>][&reply-to=<reply window>][&reply=<reply message>]
0419 
0420     SnarlParameterList<char> spl(6);
0421     spl.Add("app-sig", signature);
0422     spl.Add("title", title);
0423     spl.Add("icon", icon);
0424     spl.Add("password", password);
0425     spl.Add("reply-to", hWndReplyTo);
0426     spl.Add("reply", msgReply);
0427     spl.Add("flags", flags);
0428 
0429     // If password was given, save and use in all other functions requiring password
0430     if (password != NULL && strlen(password) > 0) {
0431         SetPassword(password);
0432     }
0433 
0434     LONG32 request = DoRequest(Requests::RegisterA(), spl);
0435     if (request > 0) {
0436         appToken = request;
0437     }
0438 
0439     return request;
0440 }
0441 
0442 LONG32 SnarlInterface::Register(LPCWSTR signature, LPCWSTR name, LPCWSTR icon, LPCWSTR password, HWND hWndReplyTo, LONG32 msgReply, SnarlEnums::AppFlags flags)
0443 {
0444     SnarlParameterList<wchar_t> spl(7);
0445     spl.Add(L"app-sig", signature);
0446     spl.Add(L"title", name);
0447     spl.Add(L"icon", icon);
0448     spl.Add(L"password", password);
0449     spl.Add(L"reply-to", hWndReplyTo);
0450     spl.Add(L"reply", msgReply);
0451     spl.Add(L"flags", flags);
0452 
0453     // If password was given, save and use in all other functions requiring password
0454     if (password != NULL && wcslen(password) > 0) {
0455         SetPassword(password);
0456     }
0457 
0458     LONG32 request = DoRequest(Requests::RegisterW(), spl);
0459     if (request > 0) {
0460         appToken = request;
0461     }
0462 
0463     return request;
0464 }
0465 
0466 LONG32 SnarlInterface::RemoveClass(LPCSTR classId)
0467 {
0468     // remclass?[app-sig=<signature>|token=<application token>][&password=<password>][&id=<class identifier>|&all=<0|1>]
0469 
0470     SnarlParameterList<char> spl(3);
0471     spl.Add("token", appToken);
0472     spl.Add("password", szPasswordA);
0473 
0474     spl.Add("id", classId);
0475     // instead of all, use ClearClasses
0476 
0477     return DoRequest(Requests::RemoveClassA(), spl);
0478 }
0479 
0480 LONG32 SnarlInterface::RemoveClass(LPCWSTR classId)
0481 {
0482     SnarlParameterList<wchar_t> spl(3);
0483     spl.Add(L"token", appToken);
0484     spl.Add(L"password", szPasswordW);
0485 
0486     spl.Add(L"id", classId);
0487 
0488     return DoRequest(Requests::RemoveClassW(), spl);
0489 }
0490 
0491 LONG32 SnarlInterface::Unregister(LPCSTR signature)
0492 {
0493     // unregister?[app-sig=<signature>|token=<application token>][&password=<password>]
0494 
0495     SnarlParameterList<char> spl(2);
0496     spl.Add("app-sig", signature);
0497     spl.Add("password", szPasswordA);
0498 
0499     appToken = 0;
0500     lastMsgToken = 0;
0501     ClearPassword();
0502 
0503     return DoRequest(Requests::UnregisterA(), spl);
0504 }
0505 
0506 LONG32 SnarlInterface::Unregister(LPCWSTR signature)
0507 {
0508     SnarlParameterList<wchar_t> spl(2);
0509     spl.Add(L"app-sig", signature);
0510     spl.Add(L"password", szPasswordW);
0511 
0512     appToken = 0;
0513     lastMsgToken = 0;
0514     ClearPassword();
0515 
0516     return DoRequest(Requests::UnregisterW(), spl);
0517 }
0518 
0519 LONG32 SnarlInterface::Update(LONG32 msgToken, LPCSTR classId, LPCSTR title, LPCSTR text, LONG32 timeout, LPCSTR iconPath, LPCSTR iconBase64, SnarlEnums::MessagePriority priority, LPCSTR callback, LPCSTR value)
0520 {
0521     // Made from best guess - no documentation available yet
0522     SnarlParameterList<char> spl(11);
0523     spl.Add("token", msgToken);
0524     spl.Add("password", szPasswordA);
0525 
0526     spl.Add("id", classId);
0527     spl.Add("title", title);
0528     spl.Add("text", text);
0529     spl.Add("icon", iconPath);
0530     spl.Add("icon-base64", iconBase64);
0531     spl.Add("callback", callback);
0532     spl.Add("value", value);
0533     if (timeout != -1) {
0534         spl.Add("timeout", timeout);
0535     }
0536     if (priority != SnarlEnums::PriorityUndefined) {
0537         spl.Add("priority", priority);    // -1 is a legal priority
0538     }
0539 
0540     return DoRequest(Requests::UpdateA(), spl);
0541 }
0542 
0543 LONG32 SnarlInterface::Update(LONG32 msgToken, LPCWSTR classId, LPCWSTR title, LPCWSTR text, LONG32 timeout, LPCWSTR iconPath, LPCWSTR iconBase64, SnarlEnums::MessagePriority priority, LPCWSTR callback, LPCWSTR value)
0544 {
0545     // Made from best guess - no documentation available yet
0546     SnarlParameterList<wchar_t> spl(11);
0547     spl.Add(L"token", msgToken);
0548     spl.Add(L"password", szPasswordW);
0549 
0550     spl.Add(L"id", classId);
0551     spl.Add(L"title", title);
0552     spl.Add(L"text", text);
0553     spl.Add(L"icon", iconPath);
0554     spl.Add(L"icon-base64", iconBase64);
0555     spl.Add(L"callback", callback);
0556     spl.Add(L"value", value);
0557     if (timeout != -1) {
0558         spl.Add(L"timeout", timeout);
0559     }
0560     if (priority != SnarlEnums::PriorityUndefined) {
0561         spl.Add(L"priority", priority);    // -1 is a legal priority
0562     }
0563 
0564     return DoRequest(Requests::UpdateW(), spl);
0565 }
0566 
0567 /*
0568 // Update app should not be used at this time, according to wiki
0569 LONG32 SnarlInterface::UpdateApp(LPCSTR title, LPCSTR icon)
0570 {
0571     SnarlParameterList<char> spl(3);
0572     spl.Add("token", appToken);
0573     spl.Add("title", title);
0574     spl.Add("icon", icon);
0575 
0576     return DoRequest(Requests::UpdateAppA(), spl);
0577 }
0578 
0579 LONG32 SnarlInterface::UpdateApp(LPCWSTR title, LPCWSTR icon)
0580 {
0581     SnarlParameterList<wchar_t> spl(2);
0582     spl.Add(L"token", appToken);
0583     spl.Add(L"title", title);
0584     spl.Add(L"icon", icon);
0585 
0586     return DoRequest(Requests::UpdateAppW(), spl);
0587 }*/
0588 
0589 //-----------------------------------------------------------------------------
0590 // Private functions
0591 //-----------------------------------------------------------------------------
0592 
0593 LONG32 SnarlInterface::DoRequest(LPCSTR request, SnarlParameterList<char> &spl, UINT replyTimeout)
0594 {
0595     // <action>[?<data>=<value>[&<data>=<value>]]
0596     const std::vector<SnarlParameterList<char>::PairType> &list = spl.GetList();
0597 
0598     if (list.size() > 0) {
0599         std::string requestStr = request;
0600         requestStr.append("?");
0601 
0602         std::vector<SnarlParameterList<char>::PairType>::const_iterator listEnd = list.end(); // cend();
0603         for (std::vector<SnarlParameterList<char>::PairType>::const_iterator iter = list.begin(); // cbegin();
0604                 iter != listEnd; ++iter) {
0605             SnarlParameterList<char>::PairType pair = *iter;
0606 
0607             if (iter->second.length() > 0) {
0608                 std::basic_string<char> &value = const_cast<std::basic_string<char>&>(iter->second);
0609                 requestStr.append(iter->first).append("=").append(Escape(value));
0610                 requestStr.append("&");
0611             }
0612         }
0613         // Delete last &
0614         requestStr.erase(requestStr.size() - 1);
0615 
0616         return DoRequest(requestStr.c_str(), replyTimeout);
0617     } else {
0618         return DoRequest(request, replyTimeout);
0619     }
0620 }
0621 
0622 LONG32 SnarlInterface::DoRequest(LPCWSTR request, SnarlParameterList<wchar_t> &spl, UINT replyTimeout)
0623 {
0624     // <action>[?<data>=<value>[&<data>=<value>]]
0625     const std::vector<SnarlParameterList<wchar_t>::PairType> &list = spl.GetList();
0626 
0627     if (list.size() > 0) {
0628         std::basic_string<wchar_t> requestStr = request;
0629         requestStr.append(L"?");
0630 
0631         std::vector<SnarlParameterList<wchar_t>::PairType>::const_iterator listEnd = list.end(); // cend();
0632         for (std::vector<SnarlParameterList<wchar_t>::PairType>::const_iterator iter = list.begin(); // cbegin();
0633                 iter != listEnd; ++iter) {
0634             if (iter->second.length() > 0) {
0635                 std::basic_string<wchar_t> &value = const_cast<std::basic_string<wchar_t>&>(iter->second);
0636                 requestStr.append(iter->first).append(L"=").append(Escape(value));
0637                 requestStr.append(L"&");
0638             }
0639         }
0640         // Delete last &
0641         requestStr.erase(requestStr.size() - 1);
0642 
0643         return DoRequest(requestStr.c_str(), replyTimeout);
0644     } else {
0645         return DoRequest(request, replyTimeout);
0646     }
0647 }
0648 
0649 // Remember to delete [] returned string
0650 LPSTR SnarlInterface::WideToUTF8(LPCWSTR szWideStr)
0651 {
0652     if (szWideStr == NULL) {
0653         return NULL;
0654     }
0655 
0656     int nSize = WideCharToMultiByte(CP_UTF8, 0, szWideStr, -1, NULL, 0, NULL, NULL);
0657     LPSTR szUTF8 = new char[nSize];
0658     WideCharToMultiByte(CP_UTF8, 0, szWideStr, -1, szUTF8, nSize, NULL, NULL);
0659 
0660     return szUTF8;
0661 }
0662 
0663 void SnarlInterface::SetPassword(LPCSTR password)
0664 {
0665     ClearPassword();
0666 
0667     if (password != NULL) {
0668         int bufSize = (int)strlen(password) + 1;
0669         szPasswordA = new char[bufSize];
0670         szPasswordW = new wchar_t[bufSize];
0671 
0672         // Copy ansi string
0673         strcpy_s(szPasswordA, bufSize, password);
0674 
0675         // Copy wide string
0676         MultiByteToWideChar(CP_ACP, 0, password, bufSize, szPasswordW, bufSize);
0677     }
0678 }
0679 
0680 void SnarlInterface::SetPassword(LPCWSTR password)
0681 {
0682     ClearPassword();
0683 
0684     if (password != NULL) {
0685         size_t bufSize = wcslen(password) + 1;
0686         szPasswordW = new wchar_t[bufSize];
0687 
0688         // Copy wide string
0689         wcscpy_s(szPasswordW, bufSize, password);
0690 
0691         // Copy ansi string
0692         szPasswordA = WideToUTF8(password);
0693     }
0694 }
0695 
0696 void SnarlInterface::ClearPassword()
0697 {
0698     // Safe to delete NULL
0699     delete [] szPasswordA;
0700     delete [] szPasswordW;
0701     szPasswordA = NULL;
0702     szPasswordW = NULL;
0703 }
0704 
0705 }
0706 } // namespace Snarl::V42
0707