2 * @file miranda-utils.c
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
27 #include "newpluginapi.h"
28 #include "m_protosvc.h"
29 #include "m_protoint.h"
30 #include "m_database.h"
32 #include "m_langpack.h"
33 #include "m_protomod.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
)
62 DBCONTACTGETSETTING cgs
;
64 cgs
.szModule
= pr
->proto
.m_szModuleName
;
67 if(CallService(MS_DB_CONTACT_GETSETTING
,(WPARAM
)hContact
,(LPARAM
)&cgs
))
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
)
88 if (sipe_miranda_getDword( pr
, NULL
, name
, &ret
))
89 return ret
?TRUE
:FALSE
;
94 int sipe_miranda_getStaticString(const SIPPROTO
*pr
, HANDLE hContact
, const gchar
* valueName
, gchar
* dest
, unsigned dest_len
)
97 DBCONTACTGETSETTING sVal
;
100 dbv
.cchVal
= (WORD
)dest_len
;
101 dbv
.type
= DBVT_ASCIIZ
;
104 sVal
.szModule
= pr
->proto
.m_szModuleName
;
105 sVal
.szSetting
= valueName
;
106 if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC
, (WPARAM
)hContact
, (LPARAM
)&sVal
) != 0)
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
);
154 gchar
* sipe_miranda_eliminate_html(const gchar
*string
, int len
)
156 gchar
*tmp
= (char*)mir_alloc(len
+ 1);
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)))
177 else if (tag
&& string
[i
] == '>')
185 if ((string
[i
] == '&') && (tkend
= strstr((char*)&string
[i
], ";")))
191 rep
= (char*)g_hash_table_lookup(entities
, &string
[i
+1]);
195 strcpy(&tmp
[j
], rep
);
197 i
+= strlen(&string
[i
]);
216 // mir_free((void *)string);
217 // res = DemangleXml(tmp, strlennull(tmp));
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
;
237 TCHAR _tcharbuf
[32768];
238 TCHAR
* CHAR2TCHAR( const char *chr
) {
240 if (!chr
) return NULL
;
241 mbstowcs( _tcharbuf
, chr
, strlen(chr
)+1 );
248 char _charbuf
[32768];
249 char* TCHAR2CHAR( const TCHAR
*tchr
) {
251 if (!tchr
) return NULL
;
252 wcstombs( _charbuf
, tchr
, wcslen(tchr
)+1 );
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
;
267 dbei
.eventType
= wType
;
268 dbei
.cbBlob
= cbBlob
;
271 return (HANDLE
)CallService(MS_DB_EVENT_ADD
, (WPARAM
)hContact
, (LPARAM
)&dbei
);
279 static unsigned __stdcall
msgboxThread(void* arg
)
281 struct msgboxinfo
*err
= (struct msgboxinfo
*)arg
;
285 MessageBox(NULL
, err
->msg
, err
->caption
, MB_OK
);
287 mir_free(err
->caption
);
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
);
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
;
319 ack
->result
= result
;
320 ack
->hProcess
= hProcess
;
321 ack
->lParam
= lParam
;
323 if (pr
->main_thread_id
== GetCurrentThreadId())
326 SIPE_DEBUG_INFO("broadcasting result <%08x> par1 <%08x> par2 <%08x>", type
, hProcess
, lParam
);
327 ret
= CallServiceSync(MS_PROTO_BROADCASTACK
,0,(LPARAM
)ack
);
333 CloseHandle((HANDLE
) mir_forkthreadex( sendbroadcastThread
, ack
, 8192, NULL
));
338 struct sipe_miranda_connection_info
{
340 const gchar
*server_name
;
344 void (*callback
)(HANDLE fd
, void *data
, const gchar
*reason
);
347 /* Private. For locking only */
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";
381 SIPE_DEBUG_INFO("[C:%08x] connected <%d>", info
, (int)info
->fd
);
385 if (!CallService(MS_NETLIB_STARTSSL
, (WPARAM
)info
->fd
, 0))
387 Netlib_CloseHandle(info
->fd
);
389 info
->reason
= "Failed to enabled SSL";
391 SIPE_DEBUG_INFO("[C:%08x] SSL enabled", info
);
398 info
->hDoneEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
399 CallFunctionAsync(connection_cb_async
, info
);
400 WaitForSingleObject(info
->hDoneEvent
, INFINITE
);
401 CloseHandle(info
->hDoneEvent
);
407 struct sipe_miranda_connection_info
*
408 sipe_miranda_connect(SIPPROTO
*pr
,
413 void (*callback
)(HANDLE fd
, void *data
, const gchar
*reason
),
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
);
420 info
->server_name
= host
;
421 info
->server_port
= port
;
422 info
->timeout
= timeout
;
424 info
->callback
= callback
;
427 CloseHandle((HANDLE
) mir_forkthreadex( sipe_miranda_connected_callback
, info
, 65536, NULL
));
432 struct sipe_miranda_servicedata
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
);
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
));