1 #define MIRANDA_VER 0x900
10 #include "newpluginapi.h"
11 #include "m_protosvc.h"
12 #include "m_protoint.h"
14 #include "m_database.h"
15 #include "m_langpack.h"
16 #include "m_options.h"
20 #include "m_protomod.h"
23 #include "sipe-core.h"
25 #include "sipe-core-private.h"
26 #include "sipe-backend.h"
27 #include "sipe-utils.h"
28 #include "sipe-conf.h"
29 #include "sipe-chat.h"
30 #include "sipe-session.h"
31 #include "miranda-private.h"
32 #include "miranda-resource.h"
34 #define _NI(string) _debuglog( __FILE__, __FUNCTION__, "(%d) ##NOT IMPLEMENTED## %s\n", __LINE__, #string )
36 /* Status identifiers (see also: sipe_status_types()) */
37 #define SIPE_STATUS_ID_UNKNOWN "unset" /* Unset (primitive) */
38 #define SIPE_STATUS_ID_OFFLINE "offline" /* Offline (primitive) */
39 #define SIPE_STATUS_ID_AVAILABLE "available" /* Online */
40 /* PURPLE_STATUS_UNAVAILABLE: */
41 #define SIPE_STATUS_ID_BUSY "busy" /* Busy */
42 #define SIPE_STATUS_ID_BUSYIDLE "busyidle" /* BusyIdle */
43 #define SIPE_STATUS_ID_DND "do-not-disturb" /* Do Not Disturb */
44 #define SIPE_STATUS_ID_IN_MEETING "in-a-meeting" /* In a meeting */
45 #define SIPE_STATUS_ID_IN_CONF "in-a-conference" /* In a conference */
46 #define SIPE_STATUS_ID_ON_PHONE "on-the-phone" /* On the phone */
47 #define SIPE_STATUS_ID_INVISIBLE "invisible" /* Appear Offline */
48 /* PURPLE_STATUS_AWAY: */
49 #define SIPE_STATUS_ID_IDLE "idle" /* Idle/Inactive */
50 #define SIPE_STATUS_ID_BRB "be-right-back" /* Be Right Back */
51 #define SIPE_STATUS_ID_AWAY "away" /* Away (primitive) */
52 /** Reuters status (user settable) */
53 #define SIPE_STATUS_ID_LUNCH "out-to-lunch" /* Out To Lunch */
54 /* ??? PURPLE_STATUS_EXTENDED_AWAY */
55 /* ??? PURPLE_STATUS_MOBILE */
56 /* ??? PURPLE_STATUS_TUNE */
58 /* Plugin information structure */
59 PLUGININFOEX pluginInfo
= {
61 "SIP/Simple Protocol",
62 PLUGIN_MAKE_VERSION(9,12,19,12),
63 "Support for SIP/Simple as used by Communicator 2007.",
64 "Miranda support by Jochen De Smet, for core sipe support see homepage",
65 "jochen.libsipe@leahnim.org",
67 "https://sourceforge.net/projects/sipe",
69 0, //doesn't replace anything built-in
70 #if defined( _UNICODE )
71 { 0x842395ed, 0x4e56, 0x40e5, { 0x94, 0x25, 0x28, 0x29, 0xd8, 0xab, 0xae, 0xa5 } } // {842395ED-4E56-40e5-9425-2829D8ABAEA5}
73 { 0x1ef8af37, 0xdec1, 0x4757, { 0x89, 0x78, 0xe8, 0xad, 0xd0, 0xd8, 0x6e, 0x7f } } // {1EF8AF37-DEC1-4757-8978-E8ADD0D86E7F}
77 /* Miranda interface globals */
78 #define ENTRY_SIG 0x88442211
81 PLUGINLINK
* pluginLink
;
82 struct MM_INTERFACE mmi
;
83 static NETLIBSELECTEX m_select
= {0};
84 static GHashTable
*m_readhash
= NULL
;
85 static GHashTable
*m_writehash
= NULL
;
86 static GList
*m_entries
= NULL
;
87 static HANDLE wake_up_semaphore
= NULL
;
89 static BOOL (WINAPI
*pfnEnableThemeDialogTexture
)(HANDLE
, DWORD
) = 0;
92 TCHAR _tcharbuf
[32768];
93 TCHAR
* CHAR2TCHAR( const char *chr
) {
95 mbstowcs( _tcharbuf
, chr
, strlen(chr
)+1 );
102 char _charbuf
[32768];
103 char* TCHAR2CHAR( const TCHAR
*tchr
) {
105 wcstombs( _charbuf
, tchr
, wcslen(tchr
)+1 );
112 void CreateProtoService(const SIPPROTO
*pr
, const char* szService
, SipSimpleServiceFunc serviceProc
)
114 char str
[ MAXMODULELABELLENGTH
];
116 mir_snprintf(str
, sizeof(str
), "%s%s", pr
->proto
.m_szModuleName
, szService
);
117 CreateServiceFunctionObj(str
, (MIRANDASERVICEOBJ
)*(void**)&serviceProc
, pr
);
120 HANDLE
HookProtoEvent(const SIPPROTO
*pr
, const char* szEvent
, SipSimpleEventFunc pFunc
)
122 return HookEventObj(szEvent
, (MIRANDAHOOKOBJ
)*(void**)&pFunc
, pr
);
125 void ProtocolAckThread(struct miranda_sipe_ack_args
* pArguments
)
127 ProtoBroadcastAck(pArguments
->pr
->proto
.m_szModuleName
, pArguments
->hContact
, pArguments
->nAckType
, pArguments
->nAckResult
, pArguments
->hSequence
, pArguments
->pszMessage
);
129 if (pArguments
->nAckResult
== ACKRESULT_SUCCESS
)
130 SIPE_DEBUG_INFO_NOFORMAT("ProtocolAckThread: Sent ACK");
131 else if (pArguments
->nAckResult
== ACKRESULT_FAILED
)
132 SIPE_DEBUG_INFO_NOFORMAT("ProtocolAckThread: Sent NACK");
134 g_free((gpointer
)pArguments
->pszMessage
);
138 void ForkThread( SIPPROTO
*pr
, SipSimpleThreadFunc pFunc
, void* arg
)
141 CloseHandle(( HANDLE )mir_forkthreadowner(( pThreadFuncOwner )*( void** )&pFunc, pr, arg, NULL ));
145 void SendProtoAck( SIPPROTO
*pr
, HANDLE hContact
, DWORD dwCookie
, int nAckResult
, int nAckType
, char* pszMessage
)
147 struct miranda_sipe_ack_args
* pArgs
= (struct miranda_sipe_ack_args
*)g_malloc(sizeof(struct miranda_sipe_ack_args
)); // This will be freed in the new thread
148 pArgs
->hContact
= hContact
;
149 pArgs
->hSequence
= (HANDLE
)dwCookie
;
150 pArgs
->nAckResult
= nAckResult
;
151 pArgs
->nAckType
= nAckType
;
152 pArgs
->pszMessage
= (LPARAM
)g_strdup(pszMessage
);
155 ForkThread( pr
, ( SipSimpleThreadFunc
)&ProtocolAckThread
, pArgs
);
158 void set_buddies_offline(const SIPPROTO
* pr
)
162 hContact
= (HANDLE
)CallService(MS_DB_CONTACT_FINDFIRST
, 0, 0);
164 char* szProto
= (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO
, (WPARAM
)hContact
, 0);
165 if (szProto
!= NULL
&& !lstrcmpA(szProto
, pr
->proto
.m_szModuleName
)) {
166 if (DBGetContactSettingByte(hContact
, pr
->proto
.m_szModuleName
, "ChatRoom", 0) == 0)
167 DBWriteContactSettingWord(hContact
, pr
->proto
.m_szModuleName
, "Status", ID_STATUS_OFFLINE
);
169 hContact
= (HANDLE
)CallService(MS_DB_CONTACT_FINDNEXT
, (WPARAM
)hContact
, 0);
174 const char *MirandaStatusToSipe(int status
) {
178 case ID_STATUS_OFFLINE
:
179 return SIPE_STATUS_ID_OFFLINE
;
181 case ID_STATUS_ONLINE
:
182 case ID_STATUS_FREECHAT
:
183 return SIPE_STATUS_ID_AVAILABLE
;
185 case ID_STATUS_ONTHEPHONE
:
186 return SIPE_STATUS_ID_ON_PHONE
;
189 return SIPE_STATUS_ID_DND
;
192 return SIPE_STATUS_ID_AWAY
;
195 return SIPE_STATUS_ID_BRB
;
197 case ID_STATUS_OUTTOLUNCH
:
198 return SIPE_STATUS_ID_LUNCH
;
200 case ID_STATUS_OCCUPIED
:
201 return SIPE_STATUS_ID_BUSY
;
203 case ID_STATUS_INVISIBLE
:
204 return SIPE_STATUS_ID_INVISIBLE
;
207 return SIPE_STATUS_ID_UNKNOWN
;
212 int SendBroadcast(SIPPROTO
*pr
, HANDLE hContact
,int type
,int result
,HANDLE hProcess
,LPARAM lParam
)
216 ack
.cbSize
= sizeof(ACKDATA
);
217 ack
.szModule
= pr
->proto
.m_szModuleName
;
218 ack
.hContact
= hContact
;
221 ack
.hProcess
= hProcess
;
223 return CallService(MS_PROTO_BROADCASTACK
,0,(LPARAM
)&ack
);
227 /* Protocol interface support functions */
229 _debuglog(const char *filename
, const char *funcname
, const char *fmt
,...)
236 for ( tmp
=filename
; *tmp
; tmp
++ )
238 if ((*tmp
== '/') || (*tmp
== '\\')) filename
=tmp
+1;
242 vsnprintf(szText
,sizeof(szText
),fmt
,va
);
245 if (!fopen_s(&fh
,"c:/sipsimple.log","a")) {
246 fprintf(fh
, "[%d] %22s %s: %s", _getpid(), filename
, funcname
, szText
);
251 typedef struct _time_entry
254 GSourceFunc function
;
259 static INT_PTR
StartChat(SIPPROTO
*pr
, WPARAM wParam
, LPARAM lParam
)
261 HANDLE hContact
= (HANDLE
)wParam
;
262 struct sipe_core_public
*sipe_public
= pr
->sip
;
263 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
266 if ( !DBGetContactSettingString( hContact
, pr
->proto
.m_szModuleName
, SIP_UNIQUEID
, &dbv
)) {
267 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007
))
269 sipe_conf_add(sipe_private
, dbv
.pszVal
);
271 else /* 2005- multiparty chat */
273 gchar
*self
= sip_uri_self(sipe_private
);
274 struct sip_session
*session
;
276 session
= sipe_session_add_chat(sipe_private
,
280 session
->chat_session
->backend
= sipe_backend_chat_create(SIPE_CORE_PUBLIC
,
281 session
->chat_session
,
282 session
->chat_session
->title
,
286 sipe_invite(sipe_private
, session
, dbv
.pszVal
, NULL
, NULL
, NULL
, FALSE
);
288 DBFreeVariant( &dbv
);
295 static void OnModulesLoaded(SIPPROTO
*pr
)
297 TCHAR descr
[MAX_PATH
];
298 NETLIBUSER nlu
= {0};
299 char service_name
[200];
301 CLISTMENUITEM mi
= {0};
303 SIPE_DEBUG_INFO_NOFORMAT("OnEvent::OnModulesLoaded");
305 nlu
.cbSize
= sizeof(nlu
);
306 nlu
.flags
= NUF_OUTGOING
| NUF_TCHAR
;
307 nlu
.szSettingsModule
= pr
->proto
.m_szModuleName
;
308 _sntprintf(descr
, SIZEOF(descr
), TranslateT("%s server connection"), pr
->proto
.m_tszUserName
);
309 nlu
.ptszDescriptiveName
= descr
;
311 pr
->m_hServerNetlibUser
= (HANDLE
)CallService(MS_NETLIB_REGISTERUSER
, 0, (LPARAM
)&nlu
);
313 mi
.cbSize
= sizeof( mi
);
314 mi
.pszContactOwner
= pr
->proto
.m_szModuleName
;
315 mi
.pszService
= service_name
;
317 mir_snprintf(service_name
, sizeof(service_name
), "%s%s", pr
->proto
.m_szModuleName
, "/StartChat");
318 CreateProtoService(pr
, "/StartChat",&StartChat
);
319 mi
.position
=-2000005060;
320 mi
.icolibItem
= NULL
; //GetIconHandle("block");
321 mi
.pszName
= LPGEN("&Start Chat");
322 mi
.flags
=0; //CMIF_ICONFROMICOLIB|CMIF_HIDDEN;
323 CallService(MS_CLIST_ADDCONTACTMENUITEM
,0,(LPARAM
)&mi
);
325 gcr
.cbSize
= sizeof(gcr
);
327 gcr
.pszModule
= pr
->proto
.m_szModuleName
;
328 gcr
.pszModuleDispName
= "Sip/Simple";
332 if (CallService(MS_GC_REGISTER
, 0, (LPARAM
)&gcr
))
334 SIPE_DEBUG_INFO_NOFORMAT("OnEvent::OnModulesLoaded Failed to register chat");
339 static unsigned __stdcall
340 inputloop(void* data
)
343 struct sipe_miranda_sel_entry
*entry
;
346 m_select
.cbSize
= sizeof(m_select
);
347 m_select
.dwTimeout
= 6000;
349 while( m_select
.hReadConns
[0] || m_select
.hWriteConns
[0])
352 SIPE_DEBUG_INFO_NOFORMAT("About to run select");
353 lstRes
= CallService(MS_NETLIB_SELECTEX
, 0, (LPARAM
)&m_select
);
354 SIPE_DEBUG_INFO_NOFORMAT("Back from select");
357 SIPE_DEBUG_INFO_NOFORMAT("Connection failed while waiting.");
360 else if (lstRes
== 0)
362 SIPE_DEBUG_INFO_NOFORMAT("Receive Timeout.");
363 lstRes
= SOCKET_ERROR
;
368 for ( cnt
=0 ; m_select
.hReadConns
[cnt
] ; cnt
++ )
370 if (!m_select
.hReadStatus
[cnt
]) continue;
371 SIPE_DEBUG_INFO("FD at position <%d> ready to read.", cnt
);
372 entry
= (struct sipe_miranda_sel_entry
*)g_hash_table_lookup(m_readhash
, (gconstpointer
)m_select
.hReadConns
[cnt
]);
375 SIPE_DEBUG_INFO_NOFORMAT("ERROR: no read handler found.");
378 SIPE_DEBUG_INFO_NOFORMAT("About to call read function.");
379 entry
->func( entry
->user_data
, (gint
)m_select
.hReadConns
[cnt
], SIPE_MIRANDA_INPUT_READ
);
380 SIPE_DEBUG_INFO_NOFORMAT("read function returned.");
383 for ( cnt
=0 ; m_select
.hWriteConns
[cnt
] ; cnt
++ )
385 if (!m_select
.hWriteStatus
[cnt
]) continue;
386 SIPE_DEBUG_INFO("FD at position <%d> ready to write.", cnt
);
387 entry
= (struct sipe_miranda_sel_entry
*)g_hash_table_lookup(m_writehash
, (gconstpointer
)m_select
.hWriteConns
[cnt
]);
390 SIPE_DEBUG_INFO_NOFORMAT("ERROR: no write handler found.");
393 SIPE_DEBUG_INFO_NOFORMAT("About to call write function.");
394 entry
->func( entry
->user_data
, (gint
)m_select
.hWriteConns
[cnt
], SIPE_MIRANDA_INPUT_WRITE
);
395 SIPE_DEBUG_INFO_NOFORMAT("write function returned.");
399 /* Free all removed entries */
400 while (m_entries
) g_list_delete_link(m_entries
, g_list_last(m_entries
));
406 /* libsipe interface functions */
408 miranda_sipe_get_current_status(struct sipe_core_private
*sip
, const char* name
)
410 SIPPROTO
*pr
= sip
->public.backend_private
;
411 char *module
= pr
->proto
.m_szModuleName
;
415 return g_strdup(MirandaStatusToSipe(pr
->proto
.m_iStatus
));
417 hContact
= sipe_backend_find_buddy(sip
, name
, NULL
);
418 return g_strdup(MirandaStatusToSipe(DBGetContactSettingWord( hContact
, module
, "Status", ID_STATUS_OFFLINE
)));
421 struct sipe_miranda_sel_entry
*
422 sipe_miranda_input_add(HANDLE fd
, sipe_miranda_input_condition cond
, sipe_miranda_input_function func
, gpointer user_data
)
426 struct sipe_miranda_sel_entry
*entry
;
429 m_readhash
= g_hash_table_new(NULL
, NULL
);
432 m_writehash
= g_hash_table_new(NULL
, NULL
);
434 if ((cond
!= SIPE_MIRANDA_INPUT_READ
) && (cond
!= SIPE_MIRANDA_INPUT_WRITE
))
436 SIPE_DEBUG_INFO("Invalid input condition <%d> cond.", cond
);
440 entry
= g_new0(struct sipe_miranda_sel_entry
,1);
441 entry
->sig
= ENTRY_SIG
;
443 entry
->user_data
= user_data
;
446 if (cond
== SIPE_MIRANDA_INPUT_READ
)
448 for ( rcnt
=0 ; m_select
.hReadConns
[rcnt
] && m_select
.hReadConns
[rcnt
]!=(HANDLE
)fd
; rcnt
++ );
449 m_select
.hReadConns
[rcnt
] = (HANDLE
)fd
;
450 g_hash_table_replace( m_readhash
, (gpointer
)fd
, entry
);
452 else if (cond
== SIPE_MIRANDA_INPUT_WRITE
)
454 for ( wcnt
=0 ; m_select
.hWriteConns
[wcnt
] && m_select
.hWriteConns
[wcnt
]!=(HANDLE
)fd
; wcnt
++ );
455 m_select
.hWriteConns
[rcnt
] = (HANDLE
)fd
;
456 g_hash_table_replace( m_writehash
, (gpointer
)fd
, entry
);
460 CloseHandle((HANDLE
) mir_forkthreadex( inputloop
, NULL
, 8192, NULL
));
462 SIPE_DEBUG_INFO_NOFORMAT("Added input handler.");
467 sipe_miranda_input_remove(struct sipe_miranda_sel_entry
*entry
)
473 SIPE_DEBUG_INFO_NOFORMAT("Not a valid entry. NULL.");
477 if (entry
->sig
!= ENTRY_SIG
)
479 SIPE_DEBUG_INFO("Not a valid entry. Sig is <%08x>.", entry
->sig
);
483 if (g_hash_table_lookup(m_readhash
, (gconstpointer
)entry
->fd
) == entry
)
485 for ( cnt
=0 ; m_select
.hReadConns
[cnt
] && m_select
.hReadConns
[cnt
]!=(HANDLE
)entry
->fd
; cnt
++ );
486 for ( ; m_select
.hReadConns
[cnt
] ; cnt
++ ) m_select
.hReadConns
[cnt
] = m_select
.hReadConns
[cnt
+1];
487 g_hash_table_remove(m_readhash
, (gconstpointer
)entry
->fd
);
490 if (g_hash_table_lookup(m_writehash
, (gconstpointer
)entry
->fd
) == entry
)
492 for ( cnt
=0 ; m_select
.hWriteConns
[cnt
] && m_select
.hWriteConns
[cnt
]!=(HANDLE
)entry
->fd
; cnt
++ );
493 for ( ; m_select
.hWriteConns
[cnt
] ; cnt
++ ) m_select
.hWriteConns
[cnt
] = m_select
.hWriteConns
[cnt
+1];
494 g_hash_table_remove(m_writehash
, (gconstpointer
)entry
->fd
);
497 /* Add it to the list of entries that can be freed after the next select
498 * loop in the thread that's handling the actual select
500 g_list_append( m_entries
, entry
);
506 miranda_sipe_request_authorization(struct sipe_core_private
*sip
, const char *who
, const char *alias
,
507 sipe_request_authorization_cb auth_cb
, sipe_request_authorization_cb deny_cb
, void *data
)
509 SIPPROTO
*pr
= sip
->public.backend_private
;
511 PROTORECVEVENT pre
= {0};
516 hContact
= sipe_backend_find_buddy( sip
, who
, NULL
);
519 hContact
= ( HANDLE
)CallService( MS_DB_CONTACT_ADD
, 0, 0 );
520 CallService( MS_PROTO_ADDTOCONTACT
, ( WPARAM
)hContact
,( LPARAM
)pr
->proto
.m_szModuleName
);
521 DBWriteContactSettingByte( hContact
, "CList", "NotOnList", 1 );
522 sipe_miranda_setContactString( pr
, hContact
, SIP_UNIQUEID
, who
); // name
523 sipe_miranda_setContactStringUtf( pr
, hContact
, "Nick", alias
); // server_alias
526 ccs
.szProtoService
= PSR_AUTH
;
528 ccs
.lParam
= (LPARAM
)&pre
;
529 ccs
.hContact
=hContact
= hContact
;
531 pre
.timestamp
= time(NULL
);
532 pre
.lParam
=sizeof(DWORD
)+sizeof(HANDLE
)+strlen(who
)+1+strlen(alias
)+1+1+5;
534 /*blob is: uin(DWORD), hcontact(HANDLE), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ), reason(ASCIIZ)*/
535 pCurBlob
=szBlob
=(char *)_alloca(pre
.lParam
);
536 memset(pCurBlob
, 0, sizeof(DWORD
)); pCurBlob
+=sizeof(DWORD
);
537 memcpy(pCurBlob
,&hContact
,sizeof(HANDLE
)); pCurBlob
+=sizeof(HANDLE
);
538 strcpy((char *)pCurBlob
,who
); pCurBlob
+=strlen((char *)pCurBlob
)+1;
539 *pCurBlob
= '\0'; pCurBlob
++;
540 strcpy((char *)pCurBlob
,alias
); pCurBlob
+=strlen((char *)pCurBlob
)+1;
541 *pCurBlob
= '\0'; pCurBlob
++;
542 *pCurBlob
= '\0'; pCurBlob
++;
543 pre
.szMessage
=(char *)szBlob
;
545 CallService(MS_PROTO_CHAINRECV
,0,(LPARAM
)&ccs
);
547 /* TODO: Store callbacks somewhere since miranda has no way to pass them on */
552 miranda_sipe_connection_cleanup(struct sipe_core_private
*sip
)
554 SIPPROTO
*pr
= sip
->public.backend_private
;
559 miranda_sipe_notify_user(SIP_HANDLE sip
, const char *name
, sipe_message_flags flags
, const gchar
*message
)
565 __debuglog(sipe_debug_level level
, const char *fmt
,...)
570 char *str
= DBGetString( NULL
, SIPSIMPLE_PROTOCOL_NAME
, "debuglog");
573 vsnprintf(szText
,sizeof(szText
),fmt
,va
);
577 str
= mir_strdup("c:/sipsimple.log");
579 if (!fopen_s(&fh
, str
, "a")) {
580 fprintf(fh
, "<[%d]> %s", _getpid(), szText
);
587 /****************************************************************************
588 * Struct that defines our interface with libsipe
589 ****************************************************************************/
590 /* Protocol interface functions */
591 HANDLE
AddToListByEvent( SIPPROTO
*pr
, int flags
, int iContact
, HANDLE hDbEvent
)
594 SIPE_DEBUG_INFO("AddToListByEvent: flags <%x> iContact <%x>", flags
, iContact
);
598 int Authorize( SIPPROTO
*pr
, HANDLE hContact
)
601 SIPE_DEBUG_INFO_NOFORMAT("Authorize");
605 int AuthDeny( SIPPROTO
*pr
, HANDLE hContact
, const PROTOCHAR
* szReason
)
608 SIPE_DEBUG_INFO("AuthDeny: reason <%s>", szReason
);
612 int AuthRecv( SIPPROTO
*pr
, HANDLE hContact
, PROTORECVEVENT
* evt
)
615 SIPE_DEBUG_INFO_NOFORMAT("AuthRecv");
619 int AuthRequest( SIPPROTO
*pr
, HANDLE hContact
, const PROTOCHAR
* szMessage
)
622 SIPE_DEBUG_INFO("AuthRequest: message <%s>", szMessage
);
626 HANDLE
ChangeInfo( SIPPROTO
*pr
, int iInfoType
, void* pInfoData
)
629 SIPE_DEBUG_INFO("ChangeInfo: infotype <%x>", iInfoType
);
633 HANDLE
FileAllow( SIPPROTO
*pr
, HANDLE hContact
, HANDLE hTransfer
, const PROTOCHAR
* szPath
)
636 SIPE_DEBUG_INFO("FileAllow: path <%s>", szPath
);
640 int FileCancel( SIPPROTO
*pr
, HANDLE hContact
, HANDLE hTransfer
)
643 SIPE_DEBUG_INFO_NOFORMAT("FileCancel");
647 int FileDeny( SIPPROTO
*pr
, HANDLE hContact
, HANDLE hTransfer
, const PROTOCHAR
* szReason
)
650 SIPE_DEBUG_INFO("FileDeny: reason <%s>", szReason
);
654 int FileResume( SIPPROTO
*pr
, HANDLE hTransfer
, int* action
, const PROTOCHAR
** szFilename
)
657 SIPE_DEBUG_INFO("FileResume: action <%x>", action
);
661 static void set_if_defined(SIPPROTO
*pr
, GHashTable
*store
, HANDLE hContact
, sipe_info_fields field
, char *label
)
663 char *value
= (char *)g_hash_table_lookup(store
, (gpointer
)field
);
665 sipe_miranda_setContactStringUtf(pr
, hContact
, label
, value
);
669 miranda_sipe_get_info_cb(struct sipe_core_public
*sipe_public
, const char* uri
, GHashTable
*results
, void* data
)
671 SIPPROTO
*pr
= sipe_public
->backend_private
;
672 HANDLE hContact
= (HANDLE
) data
;
675 const char *id
, *value
;
677 g_hash_table_iter_init( &iter
, results
);
678 while (g_hash_table_iter_next (&iter
, (gpointer
*)&id
, (gpointer
*)&value
)) {
679 SIPE_DEBUG_INFO("miranda_sipe_get_info_cb: user info field <%d> = <%s>", id
, value
? value
: "(none)");
681 set_if_defined(pr
, results
, hContact
, SIPE_INFO_EMAIL
, "e-mail");
682 set_if_defined(pr
, results
, hContact
, SIPE_INFO_CITY
, "City");
683 set_if_defined(pr
, results
, hContact
, SIPE_INFO_STATE
, "State");
684 set_if_defined(pr
, results
, hContact
, SIPE_INFO_COUNTRY
, "Country");
685 set_if_defined(pr
, results
, hContact
, SIPE_INFO_COMPANY
, "Company");
686 set_if_defined(pr
, results
, hContact
, SIPE_INFO_JOB_TITLE
, "CompanyPosition");
687 set_if_defined(pr
, results
, hContact
, SIPE_INFO_WORK_PHONE
, "CompanyPhone");
688 set_if_defined(pr
, results
, hContact
, SIPE_INFO_STREET
, "CompanyStreet");
689 set_if_defined(pr
, results
, hContact
, SIPE_INFO_ZIPCODE
, "CompanyZIP");
690 set_if_defined(pr
, results
, hContact
, SIPE_INFO_DEPARTMENT
, "CompanyDepartment");
692 SendBroadcast(pr
, hContact
, ACKTYPE_GETINFO
, ACKRESULT_SUCCESS
, (HANDLE
) 1, (LPARAM
) 0);
696 int GetInfo( SIPPROTO
*pr
, HANDLE hContact
, int infoType
)
700 SIPE_DEBUG_INFO("GetInfo: infotype <%x>", infoType
);
702 if ( !DBGetContactSettingString( hContact
, pr
->proto
.m_szModuleName
, SIP_UNIQUEID
, &dbv
)) {
703 sipe_get_info(pr
->sip
, dbv
.pszVal
, miranda_sipe_get_info_cb
, hContact
);
704 DBFreeVariant( &dbv
);
710 void sipsimple_search_contact_cb( GList
*columns
, GList
*results
, GHashTable
*opts
, void *data
)
712 SIPPROTO
*pr
= (SIPPROTO
*)data
;
714 HANDLE hProcess
= g_hash_table_lookup(opts
, "searchid");
715 PROTOSEARCHRESULT psr
= { 0 };
717 psr
.cbSize
= sizeof(psr
);
722 col
= (GList
*)row
->data
;
723 psr
.nick
= (PROTOCHAR
*)col
->data
;
725 col
= g_list_next(col
);
726 psr
.lastName
= (PROTOCHAR
*)col
->data
;
728 col
= g_list_next(col
);
731 col
= g_list_next(col
);
734 col
= g_list_next(col
);
735 psr
.email
= (PROTOCHAR
*)col
->data
;
737 row
= g_list_next(row
);
738 SendBroadcast(pr
, NULL
, ACKTYPE_SEARCH
, ACKRESULT_DATA
, hProcess
, (LPARAM
) & psr
);
741 SendBroadcast(pr
, NULL
, ACKTYPE_SEARCH
, ACKRESULT_SUCCESS
, hProcess
, 0);
745 HANDLE
SearchBasic( SIPPROTO
*pr
, const PROTOCHAR
* id
)
750 HWND
SearchAdvanced( SIPPROTO
*pr
, HWND owner
)
756 HWND
CreateExtendedSearchUI( SIPPROTO
*pr
, HWND owner
)
762 HANDLE
SearchByEmail( SIPPROTO
*pr
, const PROTOCHAR
* email
)
764 GHashTable
*query
= g_hash_table_new(NULL
,NULL
);
766 SIPE_DEBUG_INFO("SearchByEmail: email <%s>", email
);
768 g_hash_table_insert(query
, "email", (gpointer
)email
);
770 return (HANDLE
)sipe_search_contact_with_cb( pr
->sip
, query
, sipsimple_search_contact_cb
, pr
);
774 HANDLE
SearchByName( SIPPROTO
*pr
, const PROTOCHAR
* nick
, const PROTOCHAR
* firstName
, const PROTOCHAR
* lastName
)
776 GHashTable
*query
= g_hash_table_new(NULL
,NULL
);
778 SIPE_DEBUG_INFO("SearchByName: nick <%s> firstname <%s> lastname <%s>", nick
, firstName
, lastName
);
780 g_hash_table_insert(query
, "givenName", (gpointer
)mir_t2a(firstName
));
781 g_hash_table_insert(query
, "sn", (gpointer
)mir_t2a(lastName
));
783 return (HANDLE
)sipe_search_contact_with_cb( pr
->sip
, query
, sipsimple_search_contact_cb
, pr
);
786 HANDLE
AddToList( SIPPROTO
*pr
, int flags
, PROTOSEARCHRESULT
* psr
)
789 gchar
*nick
= g_strdup(mir_t2a(psr
->nick
));
791 /* Prepend sip: if needed */
792 if (strncmp("sip:", nick
, 4)) {
794 nick
= sip_uri_from_name(tmp
);
798 hContact
= sipe_backend_find_buddy(pr
->sip
, nick
, NULL
);
804 hContact
= ( HANDLE
)CallService( MS_DB_CONTACT_ADD
, 0, 0 );
805 CallService( MS_PROTO_ADDTOCONTACT
, (WPARAM
)hContact
, (LPARAM
)pr
->proto
.m_szModuleName
);
806 sipe_miranda_setString( hContact
, SIP_UNIQUEID
, nick
); // name
807 if (psr
->lastName
) sipe_miranda_setStringUtf( hContact
, "Nick", mir_t2a(psr
->lastName
) ); // server_alias
813 int RecvMsg(SIPPROTO
*pr
, HANDLE hContact
, PROTORECVEVENT
* pre
)
815 // // stop contact from typing - some clients do not sent stop notify
816 // if (CheckContactCapabilities(hContact, CAPF_TYPING))
817 // CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact, PROTOTYPE_CONTACTTYPING_OFF);
818 // char *msg = EliminateHtml( pre->szMessage, strlen(pre->szMessage));
819 // mir_free(pre->szMessage);
820 // pre->szMessage = msg;
822 CCSDATA ccs
= { hContact
, PSR_MESSAGE
, 0, ( LPARAM
)pre
};
823 return CallService( MS_PROTO_RECVMSG
, 0, ( LPARAM
)&ccs
);
826 int SendMsg( SIPPROTO
*pr
, HANDLE hContact
, int flags
, const char* msg
)
830 SIPE_DEBUG_INFO("SendMsg: flags <%x> msg <%s>", flags
, msg
);
832 if ( !DBGetContactSettingString( hContact
, pr
->proto
.m_szModuleName
, SIP_UNIQUEID
, &dbv
)) {
833 // SendProtoAck( pr, hContact, 1, ACKRESULT_SENTREQUEST, ACKTYPE_MESSAGE, NULL );
834 sipe_im_send(pr
->sip
, dbv
.pszVal
, msg
, SIPE_MESSAGE_SEND
);
835 SendProtoAck( pr
, hContact
, 1, ACKRESULT_SUCCESS
, ACKTYPE_MESSAGE
, NULL
);
838 SendProtoAck( pr
, hContact
, 1, ACKRESULT_FAILED
, ACKTYPE_MESSAGE
, NULL
);
843 int UserIsTyping( SIPPROTO
*pr
, HANDLE hContact
, int type
)
845 SIPE_DEBUG_INFO("UserIsTyping: type <%x>", type
);
851 if ( !DBGetContactSettingString( hContact
, pr
->proto
.m_szModuleName
, SIP_UNIQUEID
, &dbv
)) {
852 name
= g_strdup(dbv
.pszVal
);
859 case PROTOTYPE_SELFTYPING_ON
:
860 sipe_core_user_feedback_typing(pr
->sip
, name
);
864 case PROTOTYPE_SELFTYPING_OFF
:
865 /* Not supported anymore? */
876 static void sipe_miranda_login(SIPPROTO
*pr
) {
877 gchar
*username
= sipe_miranda_getString(pr
, "username");
878 gchar
*login
= sipe_miranda_getString(pr
, "login");
879 gchar
*email
= sipe_miranda_getString(pr
, "email");
880 gchar
*email_url
= sipe_miranda_getString(pr
, "email_url");
881 gchar
**domain_user
= g_strsplit_set(login
, "/\\", 2);
884 char *tmp
= (char*)mir_calloc(1024);
886 if (sipe_miranda_getStaticString(pr
, NULL
, "password", tmp
, 1024 )) tmp
[0] = '\0';
887 CallService(MS_DB_CRYPT_DECODESTRING
, sizeof(tmp
),(LPARAM
)tmp
);
888 password
= g_strdup(tmp
);
891 pr
->sip
= sipe_core_allocate(username
,
892 domain_user
[0], domain_user
[1],
898 pr
->sip
->backend_private
= pr
;
904 g_strfreev(domain_user
);
908 /* FIXME: Flag connection error */
912 //sipe_miranda_chat_setup_rejoin(pr);
915 // if (purple_account_get_bool(account, "krb5", FALSE))
916 // SIPE_CORE_FLAG_SET(KRB5);
918 // /* @TODO: is this correct?
919 // "sso" is only available when Kerberos support is compiled in */
920 // if (purple_account_get_bool(account, "sso", TRUE))
921 // SIPE_CORE_FLAG_SET(SSO);
923 /* Set display name */
924 sipe_miranda_setStringUtf(pr
, "Nick", pr
->sip
->sip_name
);
926 /* Update connection progress */
927 pr
->proto
.m_iStatus
= ID_STATUS_CONNECTING
;
928 SendBroadcast(pr
, NULL
, ACKTYPE_STATUS
, ACKRESULT_SUCCESS
, (HANDLE
)pr
->proto
.m_iStatus
, ID_STATUS_CONNECTING
);
931 username_split = g_strsplit(purple_account_get_string(account, "server", ""), ":", 2);
932 if (sipe_strequal(transport, "auto")) {
933 type = (username_split[0] == NULL) ?
934 SIPE_TRANSPORT_AUTO : SIPE_TRANSPORT_TLS;
935 } else if (sipe_strequal(transport, "tls")) {
936 type = SIPE_TRANSPORT_TLS;
938 type = SIPE_TRANSPORT_TCP;
941 sipe_core_transport_sip_connect(pr->sip,
944 username_split[0] ? username_split[1] : NULL);
945 g_strfreev(username_split);
947 sipe_core_transport_sip_connect(pr
->sip
,
953 static void sipe_miranda_close( SIPPROTO
*pr
)
955 struct sipe_core_public
*sipe_public
= pr
->sip
;
958 sipe_core_deallocate(sipe_public
);
960 // sipe_purple_chat_destroy_rejoin(purple_private);
961 // g_free(purple_private);
965 static int SetStatus( SIPPROTO
*pr
, int iNewStatus
)
968 if (!pr
->m_hServerNetlibUser
) return 0;
969 if (pr
->proto
.m_iDesiredStatus
== iNewStatus
) return 0;
971 oldStatus
= pr
->proto
.m_iStatus
;
972 pr
->proto
.m_iDesiredStatus
= iNewStatus
;
974 SIPE_DEBUG_INFO("SetStatus: newstatus <%x>", iNewStatus
);
976 if (iNewStatus
== ID_STATUS_OFFLINE
) {
977 sipe_miranda_close(pr
);
978 set_buddies_offline(pr
);
979 pr
->proto
.m_iStatus
= iNewStatus
;
980 SendBroadcast(pr
, NULL
, ACKTYPE_STATUS
, ACKRESULT_SUCCESS
, (HANDLE
)oldStatus
, iNewStatus
);
982 if (pr
->proto
.m_iStatus
== ID_STATUS_OFFLINE
) {
983 sipe_miranda_login(pr
);
984 pr
->proto
.m_iStatus
= pr
->proto
.m_iDesiredStatus
;
985 sipe_set_status(pr
->sip
, MirandaStatusToSipe(iNewStatus
));
986 SendBroadcast(pr
, NULL
, ACKTYPE_STATUS
, ACKRESULT_SUCCESS
, (HANDLE
)oldStatus
, pr
->proto
.m_iStatus
);
988 pr
->proto
.m_iStatus
= iNewStatus
;
989 sipe_set_status(pr
->sip
, MirandaStatusToSipe(iNewStatus
));
990 SendBroadcast(pr
, NULL
, ACKTYPE_STATUS
, ACKRESULT_SUCCESS
, (HANDLE
)pr
->proto
.m_iStatus
, iNewStatus
);
996 //Will send an ack with:
997 //type=ACKTYPE_STATUS, result=ACKRESULT_SUCCESS, hProcess=(HANDLE)previousMode, lParam=newMode
998 //when the change completes. This ack is sent for all changes, not just ones
999 //caused by calling this function.
1000 //Note that newMode can be ID_STATUS_CONNECTING<=newMode<ID_STATUS_CONNECTING+
1001 //MAX_CONNECT_RETRIES to signify that it's connecting and it's the nth retry.
1002 //Protocols are initially always in offline mode.
1003 //Non-network-level protocol modules do not have the concept of a status and
1004 //should leave this service unimplemented
1005 //If a protocol doesn't support the specific status mode, it should pick the
1011 static DWORD_PTR
GetCaps( SIPPROTO
*pr
, int type
, HANDLE hContact
)
1015 return PF1_IM
| PF1_CHAT
| PF1_USERIDISEMAIL
| PF1_SEARCHBYNAME
1016 | PF1_AUTHREQ
| PF1_SERVERCLIST
| PF1_ADDSEARCHRES
;
1019 return PF2_ONLINE
| PF2_INVISIBLE
| PF2_SHORTAWAY
| PF2_LONGAWAY
| PF2_LIGHTDND
| PF2_HEAVYDND
1020 | PF2_OUTTOLUNCH
| PF2_ONTHEPHONE
;
1026 return PF4_NOCUSTOMAUTH
| PF4_IMSENDUTF
| PF4_SUPPORTTYPING
;
1031 case PFLAG_UNIQUEIDSETTING
:
1032 return (DWORD_PTR
) SIP_UNIQUEID
;
1035 SIPE_DEBUG_INFO("GetCaps: unknown type <%x>", type
);
1042 static HICON
GetIcon( SIPPROTO
*pr
, int iconIndex
)
1044 SIPE_DEBUG_INFO("GetIcon: unknown index <%x>", iconIndex
);
1048 int RecvContacts( SIPPROTO
*pr
, HANDLE hContact
, PROTORECVEVENT
* evt
)
1054 int RecvFile( SIPPROTO
*pr
, HANDLE hContact
, PROTOFILEEVENT
* evt
)
1060 int RecvUrl( SIPPROTO
*pr
, HANDLE hContact
, PROTORECVEVENT
* evt
)
1066 int SendContacts( SIPPROTO
*pr
, HANDLE hContact
, int flags
, int nContacts
, HANDLE
* hContactsList
)
1069 SIPE_DEBUG_INFO("SendContacts: flags <%x> ncontacts <%x>", flags
, nContacts
);
1073 HANDLE
SendFile( SIPPROTO
*pr
, HANDLE hContact
, const PROTOCHAR
* szDescription
, PROTOCHAR
** ppszFiles
)
1076 SIPE_DEBUG_INFO("SendFile: desc <%s>", szDescription
);
1080 int SendUrl( SIPPROTO
*pr
, HANDLE hContact
, int flags
, const char* url
)
1083 SIPE_DEBUG_INFO("SendUrl: iflags <%x> url <%s>", flags
, url
);
1087 int SetApparentMode( SIPPROTO
*pr
, HANDLE hContact
, int mode
)
1090 SIPE_DEBUG_INFO("SetApparentMode: mode <%x>", mode
);
1094 HANDLE
GetAwayMsg( SIPPROTO
*pr
, HANDLE hContact
)
1097 SIPE_DEBUG_INFO_NOFORMAT("GetAwayMsg");
1101 int RecvAwayMsg( SIPPROTO
*pr
, HANDLE hContact
, int mode
, PROTORECVEVENT
* evt
)
1104 SIPE_DEBUG_INFO("RecvAwayMsg: mode <%x>", mode
);
1108 int SendAwayMsg( SIPPROTO
*pr
, HANDLE hContact
, HANDLE hProcess
, const char* msg
)
1111 SIPE_DEBUG_INFO("SendAwayMsg: msg <%s>", msg
);
1115 int SetAwayMsg( SIPPROTO
*pr
, int m_iStatus
, const PROTOCHAR
* msg
)
1118 SIPE_DEBUG_INFO("SetAwayMsg: status <%x> msg <%s>", m_iStatus
, msg
);
1122 INT_PTR CALLBACK
DlgProcSipSimpleOpts(HWND hwndDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1130 const SIPPROTO
*pr
= (const SIPPROTO
*)lParam
;
1133 TranslateDialogDefault(hwndDlg
);
1135 SetWindowLongPtr(hwndDlg
, GWLP_USERDATA
, lParam
);
1139 str
= DBGetString( NULL
, SIPSIMPLE_PROTOCOL_NAME
, "debuglog");
1140 SetDlgItemTextA(hwndDlg
, IDC_DEBUGLOG
, str
);
1141 SendDlgItemMessage(hwndDlg
, IDC_DEBUGLOG
, EM_SETLIMITTEXT
, 100, 0);
1144 str
= sipe_miranda_getString(pr
, "username");
1145 SetDlgItemTextA(hwndDlg
, IDC_HANDLE
, str
);
1146 SendDlgItemMessage(hwndDlg
, IDC_HANDLE
, EM_SETLIMITTEXT
, 50, 0);
1149 str
= sipe_miranda_getString(pr
, "login");
1150 SetDlgItemTextA(hwndDlg
, IDC_LOGIN
, str
);
1151 SendDlgItemMessage(hwndDlg
, IDC_LOGIN
, EM_SETLIMITTEXT
, 50, 0);
1154 str
= sipe_miranda_getString(pr
, "password");
1155 if (str
) CallService(MS_DB_CRYPT_DECODESTRING
, strlen(str
),(LPARAM
)str
);
1156 SetDlgItemTextA(hwndDlg
, IDC_PASSWORD
, str
);
1157 SendDlgItemMessage(hwndDlg
, IDC_PASSWORD
, EM_SETLIMITTEXT
, 16, 0);
1160 SendDlgItemMessage(hwndDlg
, IDC_CONNTYPE
, CB_ADDSTRING
, 0, (LPARAM
)_T("Auto"));
1161 SendDlgItemMessage(hwndDlg
, IDC_CONNTYPE
, CB_ADDSTRING
, 0, (LPARAM
)_T("SSL/TLS"));
1162 SendDlgItemMessage(hwndDlg
, IDC_CONNTYPE
, CB_ADDSTRING
, 0, (LPARAM
)_T("TCP"));
1164 str
= sipe_miranda_getString(pr
, "transport");
1165 if (!str
|| !strcmp(str
, "auto"))
1166 SendDlgItemMessage(hwndDlg
, IDC_CONNTYPE
, CB_SELECTSTRING
, -1, (LPARAM
)_T("Auto"));
1167 else if (!strcmp(str
, "tls"))
1168 SendDlgItemMessage(hwndDlg
, IDC_CONNTYPE
, CB_SELECTSTRING
, -1, (LPARAM
)_T("SSL/TLS"));
1169 else if (!strcmp(str
, "tcp"))
1170 SendDlgItemMessage(hwndDlg
, IDC_CONNTYPE
, CB_SELECTSTRING
, -1, (LPARAM
)_T("TCP"));
1178 int code
= wParam
>> 16;
1179 int id
= wParam
& 0xffff;
1181 if (!lock
&& (code
== EN_CHANGE
|| code
== CBN_SELCHANGE
)) {
1182 SendMessage(GetParent(hwndDlg
), PSM_CHANGED
, 0, 0);
1189 if (((LPNMHDR
)lParam
)->code
== (UINT
)PSN_APPLY
)
1194 const SIPPROTO
*pr
= (const SIPPROTO
*)GetWindowLongPtr(hwndDlg
, GWLP_USERDATA
);
1196 GetDlgItemTextA(hwndDlg
, IDC_DEBUGLOG
, buf
, sizeof(buf
));
1197 DBWriteContactSettingString(NULL
, SIPSIMPLE_PROTOCOL_NAME
, "debuglog", buf
);
1199 GetDlgItemTextA(hwndDlg
, IDC_HANDLE
, buf
, sizeof(buf
));
1200 sipe_miranda_setString(pr
, "username", buf
);
1202 GetDlgItemTextA(hwndDlg
, IDC_LOGIN
, buf
, sizeof(buf
));
1203 sipe_miranda_setString(pr
, "login", buf
);
1205 GetDlgItemTextA(hwndDlg
, IDC_PASSWORD
, buf
, sizeof(buf
));
1206 CallService(MS_DB_CRYPT_ENCODESTRING
, sizeof(buf
),(LPARAM
)buf
);
1207 sipe_miranda_setString(pr
, "password", buf
);
1209 SendDlgItemMessage(hwndDlg
, IDC_CONNTYPE
, WM_GETTEXT
, 100, (LPARAM
)tbuf
);
1211 if (!_tcscmp(tbuf
, _T("Auto")))
1212 sipe_miranda_setString(pr
, "transport", "auto");
1213 else if (!_tcscmp(tbuf
, _T("SSL/TLS")))
1214 sipe_miranda_setString(pr
, "transport", "tls");
1215 else if (!_tcscmp(tbuf
, _T("TCP")))
1216 sipe_miranda_setString(pr
, "transport", "tcp");
1228 static const char *about_txt
=
1229 "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fswiss\\fcharset0 Arial;}{\\f1\\fnil\fcharset2 Symbol;}}"
1230 "{\\*\\generator Msftedit 5.41.15.1507;}\\viewkind4\\uc1\\pard\\b\\f0\\fs24 Sipe" SIPE_VERSION
"\\fs20\\par"
1232 "A third-party plugin implementing extended version of SIP/SIMPLE used by various products:\\par"
1233 "\\pard{\\pntext\\f1\\'B7\\tab}{\\*\\pn\\pnlvlblt\\pnf1\\pnindent0{\\pntxtb\'B7}}\\fi-720"
1234 "\\li720 MS Office Communications Server 2007 (R2)\\par"
1235 "{\\pntext\\f1\\'B7\\tab}MS Live Communications Server 2005/2003\\par"
1236 "{\\pntext\\f1\\'B7\\tab}Reuters Messaging\\par"
1238 "Home: http://sipe.sourceforge.net\\par "
1239 "Support: http://sourceforge.net/projects/sipe/forums/forum/68853\\par "
1240 "License: GPLv2\\par "
1242 "\\b Authors:\\b0\\par"
1243 " - Anibal Avelar\\par"
1244 " - Gabriel Burt\\par"
1245 " - Stefan Becker\\par"
1249 INT_PTR CALLBACK
DlgProcSipSimpleOptsAbout(HWND hwndDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1256 const SIPPROTO
*pr
= (const SIPPROTO
*)lParam
;
1259 TranslateDialogDefault(hwndDlg
);
1261 SetWindowLongPtr(hwndDlg
, GWLP_USERDATA
, lParam
);
1263 tex
.flags
= ST_DEFAULT
;
1266 SendDlgItemMessage(hwndDlg
, IDC_ABOUTSIPE
, EM_SETTEXTEX
, (WPARAM
)&tex
, (LPARAM
)about_txt
);
1274 int OnOptionsInit(const SIPPROTO
*pr
, WPARAM wParam
, LPARAM lParam
)
1276 OPTIONSDIALOGPAGE odp
= {0};
1277 HMODULE hUxTheme
= 0;
1279 if (IsWinVerXPPlus())
1281 hUxTheme
= GetModuleHandleA("uxtheme.dll");
1283 pfnEnableThemeDialogTexture
= (BOOL (WINAPI
*)(HANDLE
, DWORD
))GetProcAddress(hUxTheme
, "EnableThemeDialogTexture");
1286 odp
.cbSize
= sizeof(odp
);
1287 odp
.position
= -800000000;
1288 odp
.hInstance
= hInst
;
1289 odp
.ptszGroup
= LPGENT("Network");
1290 odp
.dwInitParam
= (LPARAM
)pr
;
1291 odp
.ptszTitle
= pr
->proto
.m_tszUserName
;
1292 odp
.flags
= ODPF_BOLDGROUPS
| ODPF_TCHAR
;
1294 odp
.ptszTab
= LPGENT("Account");
1295 odp
.pszTemplate
= MAKEINTRESOURCEA(IDD_OPT_SIPSIMPLE
);
1296 odp
.pfnDlgProc
= DlgProcSipSimpleOpts
;
1297 CallService( MS_OPT_ADDPAGE
, wParam
, ( LPARAM
)&odp
);
1299 odp
.ptszTab
= LPGENT("About");
1300 odp
.pszTemplate
= MAKEINTRESOURCEA(IDD_OPT_SIPSIMPLE_ABOUT
);
1301 odp
.pfnDlgProc
= DlgProcSipSimpleOptsAbout
;
1302 CallService( MS_OPT_ADDPAGE
, wParam
, ( LPARAM
)&odp
);
1306 odp
.ptszTab
= LPGENT("Features");
1307 odp
.pszTemplate
= MAKEINTRESOURCEA(IDD_OPT_ICQFEATURES
);
1308 odp
.pfnDlgProc
= DlgProcIcqFeaturesOpts
;
1309 CallService( MS_OPT_ADDPAGE
, wParam
, ( LPARAM
)&odp
);
1311 odp
.ptszTab
= LPGENT("Privacy");
1312 odp
.pszTemplate
= MAKEINTRESOURCEA(IDD_OPT_ICQPRIVACY
);
1313 odp
.pfnDlgProc
= DlgProcIcqPrivacyOpts
;
1314 CallService( MS_OPT_ADDPAGE
, wParam
, ( LPARAM
)&odp
);
1318 odp
.position
= 100000000;
1319 odp
.pszTemplate
= MAKEINTRESOURCEA(IDD_OPT_POPUPS
);
1320 odp
.groupPosition
= 900000000;
1321 odp
.pfnDlgProc
= DlgProcIcqPopupOpts
;
1322 odp
.ptszGroup
= LPGENT("Popups");
1324 CallService( MS_OPT_ADDPAGE
, wParam
, ( LPARAM
)&odp
);
1330 static int OnEvent( SIPPROTO
*pr
, PROTOEVENTTYPE eventType
, WPARAM wParam
, LPARAM lParam
)
1332 SIPE_DEBUG_INFO("OnEvent: type <%x>", eventType
);
1336 case EV_PROTO_ONLOAD
:
1337 OnModulesLoaded(pr
);
1340 case EV_PROTO_ONREADYTOEXIT
:
1343 case EV_PROTO_ONEXIT
:
1346 case EV_PROTO_ONRENAME
:
1349 case EV_PROTO_ONOPTIONS
:
1350 return OnOptionsInit( pr
, wParam
, lParam
);
1353 case EV_PROTO_ONERASE
:
1363 INT_PTR CALLBACK
DlgProcAccMgrUI(HWND hwndDlg
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1369 const SIPPROTO
*pr
= (const SIPPROTO
*)lParam
;
1372 TranslateDialogDefault(hwndDlg
);
1374 SetWindowLongPtr(hwndDlg
, GWLP_USERDATA
, lParam
);
1377 str
= sipe_miranda_getString(pr
, "username");
1378 SetDlgItemTextA(hwndDlg
, IDC_HANDLE
, str
);
1381 str
= sipe_miranda_getString(pr
, "login");
1382 SetDlgItemTextA(hwndDlg
, IDC_LOGIN
, str
);
1385 str
= sipe_miranda_getString(pr
, "password");
1386 if (str
) CallService(MS_DB_CRYPT_DECODESTRING
, strlen(str
),(LPARAM
)str
);
1387 SetDlgItemTextA(hwndDlg
, IDC_PASSWORD
, str
);
1390 SendDlgItemMessage(hwndDlg
, IDC_HANDLE
, EM_SETLIMITTEXT
, 50, 0);
1391 SendDlgItemMessage(hwndDlg
, IDC_LOGIN
, EM_SETLIMITTEXT
, 50, 0);
1392 SendDlgItemMessage(hwndDlg
, IDC_PASSWORD
, EM_SETLIMITTEXT
, 16, 0);
1398 if (HIWORD(wParam
) == EN_CHANGE
&& (HWND
)lParam
== GetFocus())
1400 switch(LOWORD(wParam
))
1405 SendMessage(GetParent(hwndDlg
), PSM_CHANGED
, 0, 0);
1411 if (((LPNMHDR
)lParam
)->code
== (UINT
)PSN_APPLY
)
1415 const SIPPROTO
*pr
= (const SIPPROTO
*)lParam
;
1417 GetDlgItemTextA(hwndDlg
, IDC_HANDLE
, buf
, sizeof(buf
));
1418 sipe_miranda_setString(pr
, "username", buf
);
1420 GetDlgItemTextA(hwndDlg
, IDC_LOGIN
, buf
, sizeof(buf
));
1421 sipe_miranda_setString(pr
, "login", buf
);
1423 GetDlgItemTextA(hwndDlg
, IDC_PASSWORD
, buf
, sizeof(buf
));
1424 CallService(MS_DB_CRYPT_ENCODESTRING
, sizeof(buf
),(LPARAM
)buf
);
1425 sipe_miranda_setString(pr
, "password", buf
);
1435 /* Event handlers */
1436 int OnPreBuildContactMenu(const SIPPROTO
*pr
, WPARAM wParam
, LPARAM lParam
)
1438 HANDLE hContact
= (HANDLE
)wParam
;
1443 int OnChatEvent(const SIPPROTO
*pr
, WPARAM w
, LPARAM l
)
1445 GCHOOK
*hook
= (GCHOOK
*)l
;
1446 GCDEST
*dst
= hook
->pDest
;
1448 if (dst
->iType
== GC_USER_MESSAGE
) {
1451 struct sipe_chat_session
*session
;
1453 gcd
.pszModule
= pr
->proto
.m_szModuleName
;
1454 gcd
.pszID
= dst
->pszID
;
1455 gcd
.iType
= GC_EVENT_GETITEMDATA
;
1457 gce
.cbSize
= sizeof(gce
);
1461 if ((session
= CallService( MS_GC_EVENT
, 0, (LPARAM
)&gce
)) == NULL
)
1463 SIPE_DEBUG_WARNING_NOFORMAT("Failed to get chat session");
1467 sipe_core_chat_send(pr
->sip
, session
, hook
->pszText
);
1469 } else if (dst
->iType
== GC_USER_PRIVMESS
) {
1475 int OnGroupChange( const SIPPROTO
*pr
, WPARAM w
, LPARAM l
)
1477 CLISTGROUPCHANGE
*gi
= (CLISTGROUPCHANGE
*)l
;
1478 HANDLE hContact
= (HANDLE
)w
;
1482 /* No contact => it's a group add/rename/remove */
1485 /* No old name => add */
1486 if (!gi
->pszOldName
)
1490 /* No new name => delete */
1491 else if (!gi
->pszNewName
)
1493 SIPE_DEBUG_INFO("Removing group <l%s>", gi
->pszOldName
);
1494 sipe_remove_group(pr
->sip
, TCHAR2CHAR(gi
->pszOldName
));
1498 SIPE_DEBUG_INFO("Renaming group <%ls> to <%ls>", gi
->pszOldName
, gi
->pszNewName
);
1499 sipe_rename_group(pr
->sip
, TCHAR2CHAR(gi
->pszOldName
), TCHAR2CHAR(gi
->pszNewName
));
1503 if ( !DBGetContactSettingString( hContact
, pr
->proto
.m_szModuleName
, SIP_UNIQUEID
, &dbv
)) {
1504 who
= g_strdup(dbv
.pszVal
);
1505 DBFreeVariant( &dbv
);
1507 if ( !DBGetContactSettingString( hContact
, "Clist", "Group", &dbv
)) {
1508 SIPE_DEBUG_INFO("Moving buddy <%s> from group <%ls> to group <%ls>", who
, dbv
.pszVal
, gi
->pszNewName
);
1509 sipe_group_buddy(pr
->sip
, who
, dbv
.pszVal
, TCHAR2CHAR(gi
->pszNewName
));
1510 DBFreeVariant( &dbv
);
1512 SIPE_DEBUG_INFO("Really adding buddy <%s> to list in group <%ls>", who
, gi
->pszNewName
);
1513 sipe_add_buddy(pr
->sip
, who
, TCHAR2CHAR(gi
->pszNewName
));
1522 INT_PTR
SvcCreateAccMgrUI(const SIPPROTO
*pr
, WPARAM wParam
, LPARAM lParam
)
1524 return (INT_PTR
)CreateDialogParam(hInst
, MAKEINTRESOURCE(IDD_ACCMGRUI
), (HWND
)lParam
, DlgProcAccMgrUI
, (LPARAM
)pr
);
1527 /* Main Miranda interface */
1528 __declspec(dllexport
) PLUGININFOEX
*MirandaPluginInfoEx(DWORD mirandaVersion
)
1530 // Only load for 0.8.0.29 or greater
1531 // We need the core stubs for PS_GETNAME and PS_GETSTATUS
1532 if (mirandaVersion
< PLUGIN_MAKE_VERSION(0, 9, 0, 0))
1536 "SIP/Simple plugin cannot be loaded. It requires Miranda IM 0.9.0.0 or later.",
1537 "SIP/Simple Plugin",
1538 MB_OK
| MB_ICONWARNING
| MB_SETFOREGROUND
| MB_TOPMOST
1546 static const MUUID interfaces
[] = {MIID_PROTOCOL
, MIID_LAST
};
1547 __declspec(dllexport
) const MUUID
* MirandaPluginInterfaces(void)
1552 static PROTO_INTERFACE
* sipsimpleProtoInit( const char* pszProtoName
, const TCHAR
* tszUserName
)
1554 SIPPROTO
*pr
= (SIPPROTO
*)mir_calloc(sizeof(SIPPROTO
));
1555 pr
->proto
.vtbl
= (PROTO_INTERFACE_VTBL
*)mir_calloc(sizeof(PROTO_INTERFACE_VTBL
));
1557 SIPE_DEBUG_INFO("protoname <%s> username <%ls>", pszProtoName
, tszUserName
);
1559 pr
->proto
.m_iVersion
= 2;
1560 pr
->proto
.m_szModuleName
= mir_strdup(pszProtoName
);
1561 pr
->proto
.m_tszUserName
= mir_tstrdup(tszUserName
);
1562 pr
->proto
.m_szProtoName
= mir_strdup(pszProtoName
);
1564 set_buddies_offline(pr
);
1566 /* Fill the function table */
1567 pr
->proto
.vtbl
->GetCaps
= GetCaps
;
1568 pr
->proto
.vtbl
->GetIcon
= GetIcon
;
1569 pr
->proto
.vtbl
->OnEvent
= OnEvent
;
1570 pr
->proto
.vtbl
->SetStatus
= SetStatus
;
1571 pr
->proto
.vtbl
->UserIsTyping
= UserIsTyping
;
1572 pr
->proto
.vtbl
->SendMsg
= SendMsg
;
1573 pr
->proto
.vtbl
->RecvMsg
= RecvMsg
;
1574 pr
->proto
.vtbl
->AddToListByEvent
= AddToListByEvent
;
1575 pr
->proto
.vtbl
->Authorize
= Authorize
;
1576 pr
->proto
.vtbl
->AuthDeny
= AuthDeny
;
1577 pr
->proto
.vtbl
->AuthRecv
= AuthRecv
;
1578 pr
->proto
.vtbl
->AuthRequest
= AuthRequest
;
1579 pr
->proto
.vtbl
->ChangeInfo
= ChangeInfo
;
1580 pr
->proto
.vtbl
->FileAllow
= FileAllow
;
1581 pr
->proto
.vtbl
->FileCancel
= FileCancel
;
1582 pr
->proto
.vtbl
->FileDeny
= FileDeny
;
1583 pr
->proto
.vtbl
->FileResume
= FileResume
;
1584 pr
->proto
.vtbl
->GetInfo
= GetInfo
;
1585 pr
->proto
.vtbl
->SearchBasic
= SearchBasic
;
1586 pr
->proto
.vtbl
->SearchAdvanced
= SearchAdvanced
;
1587 pr
->proto
.vtbl
->CreateExtendedSearchUI
= CreateExtendedSearchUI
;
1588 pr
->proto
.vtbl
->SearchByEmail
= SearchByEmail
;
1589 pr
->proto
.vtbl
->SearchByName
= SearchByName
;
1590 pr
->proto
.vtbl
->AddToList
= AddToList
;
1592 /* Setup services */
1593 CreateProtoService(pr
, PS_CREATEACCMGRUI
, &SvcCreateAccMgrUI
);
1595 HookProtoEvent(pr
, ME_OPT_INITIALISE
, &OnOptionsInit
);
1596 HookProtoEvent(pr
, ME_CLIST_GROUPCHANGE
, &OnGroupChange
);
1597 HookProtoEvent(pr
, ME_GC_EVENT
, &OnChatEvent
);
1598 HookProtoEvent(pr
, ME_CLIST_PREBUILDCONTACTMENU
, &OnPreBuildContactMenu
);
1600 return (PROTO_INTERFACE
*)pr
;
1603 static int sipsimpleProtoUninit( PROTO_INTERFACE
* _pr
)
1605 SIPPROTO
*pr
= (SIPPROTO
*)_pr
;
1607 mir_free(pr
->proto
.m_szModuleName
);
1608 mir_free(pr
->proto
.m_tszUserName
);
1609 mir_free(pr
->proto
.vtbl
);
1615 __declspec(dllexport
) int Load(PLUGINLINK
*link
)
1617 PROTOCOLDESCRIPTOR pd
= {0};
1625 // Register the module
1626 pd
.cbSize
= sizeof(pd
);
1627 pd
.szName
= SIPSIMPLE_PROTOCOL_NAME
;
1628 pd
.type
= PROTOTYPE_PROTOCOL
;
1629 pd
.fnInit
= sipsimpleProtoInit
;
1630 pd
.fnUninit
= sipsimpleProtoUninit
;
1631 CallService(MS_PROTO_REGISTERMODULE
, 0, (LPARAM
)&pd
);
1636 __declspec(dllexport
) int Unload(void)
1638 sipe_core_destroy();
1642 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
,DWORD fdwReason
,LPVOID lpvReserved
)