purple: make it compile against 3.0.x API
[siplcs.git] / src / miranda / miranda-utils.c
blob978dc3331581a03b00f235edc5a673153b036f56
1 /**
2 * @file miranda-utils.c
4 * pidgin-sipe
6 * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #define MIRANDA_VER 0x900
25 #include <windows.h>
27 #include "newpluginapi.h"
28 #include "m_protosvc.h"
29 #include "m_protoint.h"
30 #include "m_database.h"
31 #include "m_netlib.h"
32 #include "m_langpack.h"
33 #include "m_protomod.h"
35 #include "glib.h"
36 #include "sipe-backend.h"
37 #include "miranda-private.h"
39 static GHashTable *entities = NULL;
41 #define ADDENT(a,b) g_hash_table_insert(entities, a, b)
44 gchar* sipe_miranda_getGlobalString(const gchar* name)
46 return DBGetString( NULL, SIPSIMPLE_PROTOCOL_NAME, name );
49 gchar* sipe_miranda_getContactString(const SIPPROTO *pr, HANDLE hContact, const gchar* name)
51 return DBGetString( hContact, pr->proto.m_szModuleName, name );
54 gchar* sipe_miranda_getString(const SIPPROTO *pr, const gchar* name)
56 return sipe_miranda_getContactString( pr, NULL, name );
59 DWORD sipe_miranda_getDword(const SIPPROTO *pr, HANDLE hContact, const gchar* name, DWORD* rv)
61 DBVARIANT dbv;
62 DBCONTACTGETSETTING cgs;
64 cgs.szModule = pr->proto.m_szModuleName;
65 cgs.szSetting = name;
66 cgs.pValue=&dbv;
67 if(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs))
68 return 0;
70 if (rv) {
71 *rv = dbv.dVal;
72 return 1;
73 } else {
74 return dbv.dVal;
79 int sipe_miranda_setWord(const SIPPROTO *pr, HANDLE hContact, const gchar* szSetting, WORD wValue)
81 return DBWriteContactSettingWord(hContact, pr->proto.m_szModuleName, szSetting, wValue);
84 gboolean sipe_miranda_get_bool(const SIPPROTO *pr, const gchar *name, gboolean defval)
86 DWORD ret;
88 if (sipe_miranda_getDword( pr, NULL, name, &ret ))
89 return ret?TRUE:FALSE;
91 return defval;
94 int sipe_miranda_getStaticString(const SIPPROTO *pr, HANDLE hContact, const gchar* valueName, gchar* dest, unsigned dest_len)
96 DBVARIANT dbv;
97 DBCONTACTGETSETTING sVal;
99 dbv.pszVal = dest;
100 dbv.cchVal = (WORD)dest_len;
101 dbv.type = DBVT_ASCIIZ;
103 sVal.pValue = &dbv;
104 sVal.szModule = pr->proto.m_szModuleName;
105 sVal.szSetting = valueName;
106 if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, (WPARAM)hContact, (LPARAM)&sVal) != 0)
107 return 1;
109 return (dbv.type != DBVT_ASCIIZ);
112 void sipe_miranda_setContactString(const SIPPROTO *pr, HANDLE hContact, const gchar* name, const gchar* value)
114 DBWriteContactSettingString(hContact, pr->proto.m_szModuleName, name, value);
117 void sipe_miranda_setContactStringUtf(const SIPPROTO *pr, HANDLE hContact, const gchar* valueName, const gchar* parValue )
119 DBWriteContactSettingStringUtf( hContact, pr->proto.m_szModuleName, valueName, parValue );
122 void sipe_miranda_setString(const SIPPROTO *pr, const gchar* name, const gchar* value)
124 sipe_miranda_setContactString( pr, NULL, name, value );
127 void sipe_miranda_setStringUtf(const SIPPROTO *pr, const gchar* name, const gchar* value)
129 sipe_miranda_setContactStringUtf( pr, NULL, name, value );
132 void sipe_miranda_setGlobalString(const gchar* name, const gchar* value)
134 DBWriteContactSettingString(NULL, SIPSIMPLE_PROTOCOL_NAME, name, value);
137 void sipe_miranda_setGlobalStringUtf(const gchar* valueName, const gchar* parValue )
139 DBWriteContactSettingStringUtf( NULL, SIPSIMPLE_PROTOCOL_NAME, valueName, parValue );
143 static void initEntities(void)
145 entities = g_hash_table_new(g_str_hash, g_str_equal);
147 ADDENT("nbsp"," ");
148 ADDENT("quot","\"");
149 ADDENT("lt","<");
150 ADDENT("gt",">");
151 ADDENT("apos","'");
154 gchar* sipe_miranda_eliminate_html(const gchar *string, int len)
156 gchar *tmp = (char*)mir_alloc(len + 1);
157 int i,j;
158 BOOL tag = FALSE;
159 gchar *res;
161 if (!entities)
162 initEntities();
164 for (i=0,j=0;i<len;i++)
166 if (!tag && string[i] == '<')
168 if ((i + 4 <= len) && (!_strnicmp(string + i, "<br>", 4) || !_strnicmp(string + i, "<br/>", 5)))
169 { // insert newline
170 tmp[j] = '\r';
171 j++;
172 tmp[j] = '\n';
173 j++;
175 tag = TRUE;
177 else if (tag && string[i] == '>')
179 tag = FALSE;
181 else if (!tag)
183 char *tkend;
185 if ((string[i] == '&') && (tkend = strstr((char*)&string[i], ";")))
187 gchar *rep;
188 gchar c = *tkend;
189 *tkend = '\0';
191 rep = (char*)g_hash_table_lookup(entities, &string[i+1]);
193 if (rep)
195 strcpy(&tmp[j], rep);
196 j += strlen(rep);
197 i += strlen(&string[i]);
198 *tkend = c;
200 else
202 *tkend = c;
203 tmp[j] = string[i];
204 j++;
208 else
210 tmp[j] = string[i];
211 j++;
214 tmp[j] = '\0';
216 // mir_free((void *)string);
217 // res = DemangleXml(tmp, strlennull(tmp));
218 // mir_free(tmp);
219 res = tmp;
221 return res;
224 unsigned short sipe_miranda_network_get_port_from_fd( HANDLE fd )
226 SOCKET sock = CallService(MS_NETLIB_GETSOCKET, (WPARAM)fd, (LPARAM)0);
228 struct sockaddr_in sockbuf;
229 int namelen = sizeof(sockbuf);
230 getsockname(sock, (struct sockaddr *)&sockbuf, &namelen);
231 SIPE_DEBUG_INFO("<%x> <%x><%x><%s>", namelen, sockbuf.sin_family, sockbuf.sin_port, inet_ntoa(sockbuf.sin_addr) );
233 return sockbuf.sin_port;
236 /* Misc functions */
237 TCHAR _tcharbuf[32768];
238 TCHAR* CHAR2TCHAR( const char *chr ) {
239 #ifdef UNICODE
240 if (!chr) return NULL;
241 mbstowcs( _tcharbuf, chr, strlen(chr)+1 );
242 return _tcharbuf;
243 #else
244 return chr;
245 #endif
248 char _charbuf[32768];
249 char* TCHAR2CHAR( const TCHAR *tchr ) {
250 #ifdef UNICODE
251 if (!tchr) return NULL;
252 wcstombs( _charbuf, tchr, wcslen(tchr)+1 );
253 return _charbuf;
254 #else
255 return tchr;
256 #endif
259 HANDLE sipe_miranda_AddEvent(const SIPPROTO *pr, HANDLE hContact, WORD wType, DWORD dwTime, DWORD flags, DWORD cbBlob, PBYTE pBlob)
261 DBEVENTINFO dbei = {0};
263 dbei.cbSize = sizeof(dbei);
264 dbei.szModule = pr->proto.m_szModuleName;
265 dbei.timestamp = dwTime;
266 dbei.flags = flags;
267 dbei.eventType = wType;
268 dbei.cbBlob = cbBlob;
269 dbei.pBlob = pBlob;
271 return (HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei);
274 struct msgboxinfo {
275 TCHAR *msg;
276 TCHAR *caption;
279 static unsigned __stdcall msgboxThread(void* arg)
281 struct msgboxinfo *err = (struct msgboxinfo*)arg;
282 if (!err)
283 return 0;
285 MessageBox(NULL, err->msg, err->caption, MB_OK);
286 mir_free(err->msg);
287 mir_free(err->caption);
288 g_free(err);
289 return 0;
292 void sipe_miranda_msgbox(const char *msg, const char *caption)
294 struct msgboxinfo *info = g_new(struct msgboxinfo,1);
296 info->msg = mir_a2t(msg);
297 info->caption = mir_a2t(caption);
299 CloseHandle((HANDLE) mir_forkthreadex( msgboxThread, info, 8192, NULL ));
302 static unsigned __stdcall sendbroadcastThread(void* arg)
304 ACKDATA *ack = (ACKDATA*)arg;
305 SIPE_DEBUG_INFO("delayed broadcasting result <%08x> par1 <%08x> par2 <%08x>", ack->type, ack->hProcess, ack->lParam);
306 CallServiceSync(MS_PROTO_BROADCASTACK,0,(LPARAM)ack);
307 g_free(ack);
308 return 0;
311 int sipe_miranda_SendBroadcast(SIPPROTO *pr, HANDLE hContact,int type,int result,HANDLE hProcess,LPARAM lParam)
313 ACKDATA *ack = g_new0(ACKDATA, 1);
315 ack->cbSize = sizeof(ACKDATA);
316 ack->szModule = pr->proto.m_szModuleName;
317 ack->hContact = hContact;
318 ack->type = type;
319 ack->result = result;
320 ack->hProcess = hProcess;
321 ack->lParam = lParam;
323 if (pr->main_thread_id == GetCurrentThreadId())
325 int ret;
326 SIPE_DEBUG_INFO("broadcasting result <%08x> par1 <%08x> par2 <%08x>", type, hProcess, lParam);
327 ret = CallServiceSync(MS_PROTO_BROADCASTACK,0,(LPARAM)ack);
328 g_free(ack);
329 return ret;
331 else
333 CloseHandle((HANDLE) mir_forkthreadex( sendbroadcastThread, ack, 8192, NULL ));
334 return 0;
338 struct sipe_miranda_connection_info {
339 SIPPROTO *pr;
340 const gchar *server_name;
341 int server_port;
342 int timeout;
343 gboolean tls;
344 void (*callback)(HANDLE fd, void *data, const gchar *reason);
345 void *data;
347 /* Private. For locking only */
348 HANDLE hDoneEvent;
349 HANDLE fd;
350 const gchar *reason;
353 static void __stdcall
354 connection_cb_async(void *data)
356 struct sipe_miranda_connection_info *entry = (struct sipe_miranda_connection_info*)data;
357 SIPE_DEBUG_INFO("[C:%08x] Calling real connected function", entry);
358 entry->callback(entry->fd, entry->data, entry->reason);
359 SetEvent(entry->hDoneEvent);
362 static unsigned __stdcall
363 sipe_miranda_connected_callback(void* data)
365 struct sipe_miranda_connection_info *info = (struct sipe_miranda_connection_info*)data;
366 SIPPROTO *pr = info->pr;
367 NETLIBOPENCONNECTION ncon = {0};
369 ncon.cbSize = sizeof(ncon);
370 ncon.flags = NLOCF_V2;
371 ncon.szHost = info->server_name;
372 ncon.wPort = info->server_port;
373 ncon.timeout = info->timeout;
375 info->fd = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)pr->m_hServerNetlibUser, (LPARAM)&ncon);
376 if (info->fd == NULL) {
377 SIPE_DEBUG_INFO("[C:%08x] Connection to <%s:%d> failed", info, info->server_name, info->server_port);
378 info->reason = "Connection failed";
380 } else {
381 SIPE_DEBUG_INFO("[C:%08x] connected <%d>", info, (int)info->fd);
383 if (info->tls)
385 if (!CallService(MS_NETLIB_STARTSSL, (WPARAM)info->fd, 0))
387 Netlib_CloseHandle(info->fd);
388 info->fd = NULL;
389 info->reason = "Failed to enabled SSL";
390 } else {
391 SIPE_DEBUG_INFO("[C:%08x] SSL enabled", info);
393 } else {
394 info->reason = NULL;
398 info->hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
399 CallFunctionAsync(connection_cb_async, info);
400 WaitForSingleObject(info->hDoneEvent, INFINITE);
401 CloseHandle(info->hDoneEvent);
403 g_free(info);
404 return 0;
407 struct sipe_miranda_connection_info *
408 sipe_miranda_connect(SIPPROTO *pr,
409 const gchar *host,
410 int port,
411 gboolean tls,
412 int timeout,
413 void (*callback)(HANDLE fd, void *data, const gchar *reason),
414 void *data)
416 struct sipe_miranda_connection_info *info = g_new0(struct sipe_miranda_connection_info, 1);
417 SIPE_DEBUG_INFO("[C:%08x] Connecting to <%s:%d> tls <%d> timeout <%d>", info, host, port, tls, timeout);
419 info->pr = pr;
420 info->server_name = host;
421 info->server_port = port;
422 info->timeout = timeout;
423 info->tls = tls;
424 info->callback = callback;
425 info->data = data;
427 CloseHandle((HANDLE) mir_forkthreadex( sipe_miranda_connected_callback, info, 65536, NULL ));
429 return info;
432 struct sipe_miranda_servicedata
434 const char *service;
435 WPARAM wParam;
436 LPARAM lParam;
439 static unsigned __stdcall
440 sipe_miranda_service_async_callback(void* data)
442 struct sipe_miranda_servicedata *svc = (struct sipe_miranda_servicedata *)data;
443 CallService(svc->service, svc->wParam, svc->lParam);
444 g_free(svc);
445 return 0;
448 void
449 CallServiceAsync(const char *service, WPARAM wParam, LPARAM lParam)
451 struct sipe_miranda_servicedata *svc = g_new(struct sipe_miranda_servicedata, 1);
452 svc->service = service;
453 svc->wParam = wParam;
454 svc->lParam = lParam;
455 CloseHandle((HANDLE) mir_forkthreadex( sipe_miranda_service_async_callback, svc, 65536, NULL ));
459 Local Variables:
460 mode: c
461 c-file-style: "bsd"
462 indent-tabs-mode: t
463 tab-width: 8
464 End: