fixed URL in WebSMS driver
[public/netxms.git] / src / smsdrv / websms / main.cpp
CommitLineData
31b0f68b
VK
1/*
2** NetXMS - Network Management System
3** SMS driver for websms.ru service
e6a585b9 4** Copyright (C) 2014-2016 Raden Solutions
31b0f68b
VK
5**
6** This program is free software; you can redistribute it and/or modify
7** it under the terms of the GNU Lesser General Public License as published by
8** the Free Software Foundation; either version 3 of the License, or
9** (at your option) any later version.
10**
11** This program is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14** GNU General Public License for more details.
15**
16** You should have received a copy of the GNU Lesser General Public License
17** along with this program; if not, write to the Free Software
18** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19**
20** File: main.cpp
21**
22**/
23
24#include <nms_common.h>
31b0f68b 25#include <nms_util.h>
623e2f0e 26#include <nxconfig.h>
31b0f68b
VK
27#include <curl/curl.h>
28
29#ifdef _WIN32
30#define EXPORT __declspec(dllexport)
31#else
32#define EXPORT
33#endif
34
35#ifndef CURL_MAX_HTTP_HEADER
36// workaround for older cURL versions
37#define CURL_MAX_HTTP_HEADER CURL_MAX_WRITE_SIZE
38#endif
39
40/**
41 * Request data for cURL call
42 */
43struct RequestData
44{
45 size_t size;
46 size_t allocated;
47 char *data;
48};
49
50/**
51 * Configuration
52 */
53static char s_login[128] = "user";
54static char s_password[128] = "password";
e6a585b9 55static char s_fromPhone[64] = "";
31b0f68b
VK
56
57/**
58 * Init driver
59 */
f19168bd 60extern "C" bool EXPORT SMSDriverInit(const TCHAR *initArgs, Config *config)
31b0f68b
VK
61{
62 if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
63 {
623e2f0e 64 nxlog_debug(1, _T("WebSMS: cURL initialization failed"));
f19168bd 65 return false;
31b0f68b
VK
66 }
67
623e2f0e
VK
68 nxlog_debug(1, _T("WebSMS: driver loaded"));
69 nxlog_debug(3, _T("cURL version: %hs"), curl_version());
31b0f68b
VK
70#if defined(_WIN32) || HAVE_DECL_CURL_VERSION_INFO
71 curl_version_info_data *version = curl_version_info(CURLVERSION_NOW);
72 char protocols[1024] = {0};
73 const char * const *p = version->protocols;
74 while (*p != NULL)
75 {
76 strncat(protocols, *p, strlen(protocols) - 1);
77 strncat(protocols, " ", strlen(protocols) - 1);
78 p++;
79 }
623e2f0e 80 nxlog_debug(3, _T("cURL supported protocols: %hs"), protocols);
31b0f68b
VK
81#endif
82
83#ifdef UNICODE
84 WCHAR buffer[128];
85
86 ExtractNamedOptionValue(initArgs, _T("login"), buffer, 128);
87 WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, buffer, -1, s_login, 128, NULL, NULL);
88
89 ExtractNamedOptionValue(initArgs, _T("password"), buffer, 128);
90 WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, buffer, -1, s_password, 128, NULL, NULL);
e6a585b9
VK
91
92 ExtractNamedOptionValue(initArgs, _T("fromPhone"), buffer, 128);
93 WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, buffer, -1, s_fromPhone, 64, NULL, NULL);
31b0f68b
VK
94#else
95 ExtractNamedOptionValue(initArgs, _T("login"), s_login, 128);
96 ExtractNamedOptionValue(initArgs, _T("password"), s_password, 128);
e6a585b9 97 ExtractNamedOptionValue(initArgs, _T("fromPhone"), s_fromPhone, 64);
31b0f68b
VK
98#endif
99
f19168bd 100 return true;
31b0f68b
VK
101}
102
103/**
104 * Callback for processing data received from cURL
105 */
106static size_t OnCurlDataReceived(char *ptr, size_t size, size_t nmemb, void *userdata)
107{
108 RequestData *data = (RequestData *)userdata;
109 if ((data->allocated - data->size) < (size * nmemb))
110 {
111 char *newData = (char *)realloc(data->data, data->allocated + CURL_MAX_HTTP_HEADER);
112 if (newData == NULL)
113 {
114 return 0;
115 }
116 data->data = newData;
117 data->allocated += CURL_MAX_HTTP_HEADER;
118 }
119
120 memcpy(data->data + data->size, ptr, size * nmemb);
121 data->size += size * nmemb;
122
123 return size * nmemb;
124}
125
126/**
127 * Send SMS
128 */
f19168bd 129extern "C" bool EXPORT SMSDriverSend(const TCHAR *phoneNumber, const TCHAR *text)
31b0f68b 130{
f19168bd 131 bool success = false;
31b0f68b 132
623e2f0e 133 nxlog_debug(4, _T("WebSMS: phone=\"%s\", text=\"%s\""), phoneNumber, text);
31b0f68b
VK
134
135 CURL *curl = curl_easy_init();
136 if (curl != NULL)
137 {
138#if HAVE_DECL_CURLOPT_NOSIGNAL
139 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, (long)1);
140#endif
141
142 curl_easy_setopt(curl, CURLOPT_HEADER, (long)0); // do not include header in data
143 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
144 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &OnCurlDataReceived);
145 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
146
147 RequestData *data = (RequestData *)malloc(sizeof(RequestData));
148 memset(data, 0, sizeof(RequestData));
149 curl_easy_setopt(curl, CURLOPT_WRITEDATA, data);
150
151#ifdef UNICODE
152 char *mbphone = MBStringFromWideString(phoneNumber);
153 char *mbmsg = MBStringFromWideString(text);
154 char *phone = curl_easy_escape(curl, mbphone, 0);
155 char *msg = curl_easy_escape(curl, mbmsg, 0);
156 free(mbphone);
157 free(mbmsg);
158#else
159 char *phone = curl_easy_escape(curl, phoneNumber, 0);
160 char *msg = curl_easy_escape(curl, text, 0);
161#endif
162
163 char url[4096];
88db10cc 164 snprintf(url, 4096, "https://cab.websms.ru/http_in5.asp?http_username=%s&http_password=%s&phone_list=%s%s%s&format=xml&message=%s",
e6a585b9 165 s_login, s_password, phone, (s_fromPhone[0] != 0) ? "&fromPhone=" : "", (s_fromPhone[0] != 0) ? s_fromPhone : "", msg);
623e2f0e 166 nxlog_debug(4, _T("WebSMS: URL set to \"%hs\""), url);
31b0f68b
VK
167
168 curl_free(phone);
169 curl_free(msg);
170
171 if (curl_easy_setopt(curl, CURLOPT_URL, url) == CURLE_OK)
172 {
173 if (curl_easy_perform(curl) == CURLE_OK)
174 {
623e2f0e 175 nxlog_debug(4, _T("WebSMS: %d bytes received"), data->size);
31b0f68b
VK
176 if (data->allocated > 0)
177 {
178 data->data[data->size] = 0;
179
180 Config *response = new Config;
181 response->loadXmlConfigFromMemory(data->data, (int)strlen(data->data), _T("WEBSMS"), "XML");
182 ConfigEntry *e = response->getEntry(_T("/httpIn"));
183 if (e != NULL)
184 {
185 int status = e->getAttributeAsInt(_T("error_num"), -1);
186 if (status == 0)
187 {
623e2f0e 188 nxlog_debug(4, _T("WebSMS: SMS successfully sent"));
31b0f68b
VK
189 success = TRUE;
190 }
191 else
192 {
623e2f0e 193 nxlog_debug(4, _T("WebSMS: send error %d"), status);
31b0f68b
VK
194 }
195 }
196 else
197 {
623e2f0e 198 nxlog_debug(4, _T("WebSMS: malformed response\n%hs"), data->data);
31b0f68b
VK
199 }
200 }
201 }
202 else
203 {
623e2f0e 204 nxlog_debug(4, _T("WebSMS: call to curl_easy_perform() failed"));
31b0f68b
VK
205 }
206 }
207 else
208 {
623e2f0e 209 nxlog_debug(4, _T("WebSMS: call to curl_easy_setopt(CURLOPT_URL) failed"));
31b0f68b
VK
210 }
211 safe_free(data->data);
212 free(data);
213 curl_easy_cleanup(curl);
214 }
215 else
216 {
623e2f0e 217 nxlog_debug(4, _T("WebSMS: call to curl_easy_init() failed"));
31b0f68b
VK
218 }
219
220 return success;
221}
222
223/**
224 * Unload driver
225 */
226extern "C" void EXPORT SMSDriverUnload()
227{
228}
229
230#ifdef _WIN32
231
232/**
233 * DLL Entry point
234 */
235BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
236{
237 if (dwReason == DLL_PROCESS_ATTACH)
238 DisableThreadLibraryCalls(hInstance);
239 return TRUE;
240}
241
242#endif