summaryrefslogtreecommitdiff
path: root/miranda-wine/protocols/JabberG/jabber_misc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'miranda-wine/protocols/JabberG/jabber_misc.cpp')
-rw-r--r--miranda-wine/protocols/JabberG/jabber_misc.cpp382
1 files changed, 382 insertions, 0 deletions
diff --git a/miranda-wine/protocols/JabberG/jabber_misc.cpp b/miranda-wine/protocols/JabberG/jabber_misc.cpp
new file mode 100644
index 0000000..35e356e
--- /dev/null
+++ b/miranda-wine/protocols/JabberG/jabber_misc.cpp
@@ -0,0 +1,382 @@
+/*
+
+Jabber Protocol Plugin for Miranda IM
+Copyright ( C ) 2002-04 Santithorn Bunchua
+Copyright ( C ) 2005-06 George Hazan
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or ( at your option ) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+File name : $Source: /cvsroot/miranda/miranda/protocols/JabberG/jabber_misc.cpp,v $
+Revision : $Revision: 3322 $
+Last change on : $Date: 2006-07-13 16:11:29 +0400 (Чтв, 13 Июл 2006) $
+Last change by : $Author: rainwater $
+
+*/
+
+#include "jabber.h"
+#include "jabber_list.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// JabberAddContactToRoster() - adds a contact to the roster
+
+void JabberAddContactToRoster( const TCHAR* jid, const TCHAR* nick, const TCHAR* grpName, JABBER_SUBSCRIPTION subscription )
+{
+ XmlNodeIq iq( "set" );
+ XmlNode* query = iq.addQuery( "jabber:iq:roster" );
+ XmlNode* item = query->addChild( "item" ); item->addAttr( "name", nick ); item->addAttr( "jid", jid );
+ switch( subscription ) {
+ case SUB_BOTH: item->addAttr( "subscription", "both" ); break;
+ case SUB_TO: item->addAttr( "subscription", "to" ); break;
+ case SUB_FROM: item->addAttr( "subscription", "from" ); break;
+ default: item->addAttr( "subscription", "none" ); break;
+ }
+
+ if ( grpName != NULL )
+ item->addChild( "group", grpName );
+ JabberSend( jabberThreadInfo->s, iq );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// JabberChatDllError() - missing CHAT.DLL
+
+void JabberChatDllError()
+{
+ MessageBox( NULL,
+ TranslateT( "CHAT plugin is required for conferences. Install it before chatting" ),
+ TranslateT( "Jabber Error Message" ), MB_OK|MB_SETFOREGROUND );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// JabberCompareJids
+
+int JabberCompareJids( const TCHAR* jid1, const TCHAR* jid2 )
+{
+ if ( !lstrcmpi( jid1, jid2 ))
+ return 0;
+
+ // match only node@domain part
+ TCHAR szTempJid1[ JABBER_MAX_JID_LEN ], szTempJid2[ JABBER_MAX_JID_LEN ];
+ return lstrcmpi(
+ JabberStripJid( jid1, szTempJid1, sizeof szTempJid1 ),
+ JabberStripJid( jid2, szTempJid2, sizeof szTempJid2 ));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// JabberContactListCreateGroup()
+
+static void JabberContactListCreateClistGroup( TCHAR* groupName )
+{
+ char str[33];
+ int i;
+ DBVARIANT dbv;
+
+ for ( i=0;;i++ ) {
+ itoa( i, str, 10 );
+ if ( DBGetContactSettingTString( NULL, "CListGroups", str, &dbv ))
+ break;
+ TCHAR* name = dbv.ptszVal;
+ if ( name[0]!='\0' && !_tcscmp( name+1, groupName )) {
+ // Already exists, no need to create
+ JFreeVariant( &dbv );
+ return;
+ }
+ JFreeVariant( &dbv );
+ }
+
+ // Create new group with id = i ( str is the text representation of i )
+ TCHAR newName[128];
+ newName[0] = 1 | GROUPF_EXPANDED;
+ _tcsncpy( newName+1, groupName, SIZEOF( newName )-1 );
+ newName[ SIZEOF( newName )-1] = '\0';
+ DBWriteContactSettingTString( NULL, "CListGroups", str, newName );
+ JCallService( MS_CLUI_GROUPADDED, i+1, 0 );
+}
+
+void JabberContactListCreateGroup( TCHAR* groupName )
+{
+ TCHAR name[128], *p;
+
+ if ( groupName==NULL || groupName[0]=='\0' || groupName[0]=='\\' ) return;
+
+ _tcsncpy( name, groupName, SIZEOF( name ));
+ name[ SIZEOF( name )-1] = '\0';
+ for ( p=name; *p!='\0'; p++ ) {
+ if ( *p == '\\' ) {
+ *p = '\0';
+ JabberContactListCreateClistGroup( name );
+ *p = '\\';
+ }
+ }
+ JabberContactListCreateClistGroup( name );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// JabberDBAddAuthRequest()
+
+void JabberDBAddAuthRequest( TCHAR* jid, TCHAR* nick )
+{
+ HANDLE hContact = JabberDBCreateContact( jid, NULL, FALSE, TRUE );
+ JDeleteSetting( hContact, "Hidden" );
+ JSetStringT( hContact, "Nick", nick );
+
+ #if defined( _UNICODE )
+ char* szJid = u2a( jid );
+ char* szNick = u2a( nick );
+ #else
+ char* szJid = jid;
+ char* szNick = nick;
+ #endif
+
+ //blob is: uin( DWORD ), hContact( HANDLE ), nick( ASCIIZ ), first( ASCIIZ ), last( ASCIIZ ), email( ASCIIZ ), reason( ASCIIZ )
+ //blob is: 0( DWORD ), hContact( HANDLE ), nick( ASCIIZ ), ""( ASCIIZ ), ""( ASCIIZ ), email( ASCIIZ ), ""( ASCIIZ )
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof( DBEVENTINFO );
+ dbei.szModule = jabberProtoName;
+ dbei.timestamp = ( DWORD )time( NULL );
+ dbei.flags = 0;
+ dbei.eventType = EVENTTYPE_AUTHREQUEST;
+ dbei.cbBlob = sizeof( DWORD )+ sizeof( HANDLE ) + strlen( szNick ) + strlen( szJid ) + 5;
+ PBYTE pCurBlob = dbei.pBlob = ( PBYTE ) mir_alloc( dbei.cbBlob );
+ *(( PDWORD ) pCurBlob ) = 0; pCurBlob += sizeof( DWORD );
+ *(( PHANDLE ) pCurBlob ) = hContact; pCurBlob += sizeof( HANDLE );
+ strcpy(( char* )pCurBlob, szNick ); pCurBlob += strlen( szNick )+1;
+ *pCurBlob = '\0'; pCurBlob++; //firstName
+ *pCurBlob = '\0'; pCurBlob++; //lastName
+ strcpy(( char* )pCurBlob, szJid ); pCurBlob += strlen( szJid )+1;
+ *pCurBlob = '\0'; //reason
+
+ JCallService( MS_DB_EVENT_ADD, ( WPARAM ) ( HANDLE ) NULL, ( LPARAM )&dbei );
+ JabberLog( "Setup DBAUTHREQUEST with nick='" TCHAR_STR_PARAM "' jid='" TCHAR_STR_PARAM "'", szNick, szJid );
+
+ #if defined( _UNICODE )
+ mir_free( szJid );
+ mir_free( szNick );
+ #endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// JabberDBCreateContact()
+// jid & nick are passed in TXT
+
+HANDLE JabberDBCreateContact( TCHAR* jid, TCHAR* nick, BOOL temporary, BOOL stripResource )
+{
+ TCHAR* s, *p, *q;
+ int len;
+ char* szProto;
+
+ if ( jid==NULL || jid[0]=='\0' )
+ return NULL;
+
+ s = mir_tstrdup( jid );
+ q = NULL;
+ // strip resource if present
+ if (( p = _tcschr( s, '@' )) != NULL )
+ if (( q = _tcschr( p, '/' )) != NULL )
+ *q = '\0';
+
+ if ( !stripResource && q!=NULL ) // so that resource is not stripped
+ *q = '/';
+ len = _tcslen( s );
+
+ // We can't use JabberHContactFromJID() here because of the stripResource option
+ HANDLE hContact = ( HANDLE ) JCallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while ( hContact != NULL ) {
+ szProto = ( char* )JCallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM ) hContact, 0 );
+ if ( szProto!=NULL && !strcmp( jabberProtoName, szProto )) {
+ DBVARIANT dbv;
+ if ( !JGetStringT( hContact, "jid", &dbv )) {
+ p = dbv.ptszVal;
+ if ( p && ( int )_tcslen( p )>=len && ( p[len]=='\0'||p[len]=='/' ) && !_tcsnicmp( p, s, len )) {
+ JFreeVariant( &dbv );
+ break;
+ }
+ JFreeVariant( &dbv );
+ } }
+ hContact = ( HANDLE ) JCallService( MS_DB_CONTACT_FINDNEXT, ( WPARAM ) hContact, 0 );
+ }
+
+ if ( hContact == NULL ) {
+ hContact = ( HANDLE ) JCallService( MS_DB_CONTACT_ADD, 0, 0 );
+ JCallService( MS_PROTO_ADDTOCONTACT, ( WPARAM ) hContact, ( LPARAM )jabberProtoName );
+ JSetStringT( hContact, "jid", s );
+ if ( nick != NULL && *nick != '\0' )
+ JSetStringT( hContact, "Nick", nick );
+ if ( temporary )
+ DBWriteContactSettingByte( hContact, "CList", "NotOnList", 1 );
+ JabberLog( "Create Jabber contact jid=" TCHAR_STR_PARAM ", nick=" TCHAR_STR_PARAM, s, nick );
+ }
+
+ mir_free( s );
+ return hContact;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// JabberGetAvatarFileName() - gets a file name for the avatar image
+
+void JabberGetAvatarFileName( HANDLE hContact, char* pszDest, int cbLen )
+{
+ JCallService( MS_DB_GETPROFILEPATH, cbLen, LPARAM( pszDest ));
+
+ int tPathLen = strlen( pszDest );
+ tPathLen += mir_snprintf( pszDest + tPathLen, MAX_PATH - tPathLen, "\\Jabber\\" );
+ CreateDirectoryA( pszDest, NULL );
+
+ char* szFileType;
+ switch( JGetByte( hContact, "AvatarType", PA_FORMAT_PNG )) {
+ case PA_FORMAT_JPEG: szFileType = "jpg"; break;
+ case PA_FORMAT_PNG: szFileType = "png"; break;
+ case PA_FORMAT_GIF: szFileType = "gif"; break;
+ case PA_FORMAT_BMP: szFileType = "bmp"; break;
+ }
+
+ if ( hContact != NULL ) {
+ char str[ 256 ];
+ DBVARIANT dbv;
+ if ( !JGetStringUtf( hContact, "jid", &dbv )) {
+ strncpy( str, dbv.pszVal, sizeof str );
+ str[ sizeof(str)-1 ] = 0;
+ JFreeVariant( &dbv );
+ }
+ else ltoa(( long )hContact, str, 10 );
+
+ char* hash = JabberSha1( str );
+ mir_snprintf( pszDest + tPathLen, MAX_PATH - tPathLen, "%s.%s", hash, szFileType );
+ mir_free( hash );
+ }
+ else if ( jabberThreadInfo != NULL ) {
+ mir_snprintf( pszDest + tPathLen, MAX_PATH - tPathLen, TCHAR_STR_PARAM"@%s avatar.%s", jabberThreadInfo->username, jabberThreadInfo->server, szFileType );
+ }
+ else {
+ DBVARIANT dbv1, dbv2;
+ BOOL res1 = DBGetContactSetting( NULL, jabberProtoName, "LoginName", &dbv1 );
+ BOOL res2 = DBGetContactSetting( NULL, jabberProtoName, "LoginServer", &dbv2 );
+ mir_snprintf( pszDest + tPathLen, MAX_PATH - tPathLen, "%s@%s avatar.%s",
+ res1 ? "noname" : dbv1.pszVal,
+ res2 ? jabberProtoName : dbv2.pszVal,
+ szFileType );
+ if (!res1) JFreeVariant( &dbv1 );
+ if (!res2) JFreeVariant( &dbv2 );
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// JabberForkThread()
+
+struct FORK_ARG {
+ HANDLE hEvent;
+ void ( __cdecl *threadcode )( void* );
+ void *arg;
+};
+
+static void __cdecl forkthread_r( struct FORK_ARG *fa )
+{
+ void ( *callercode )( void* ) = fa->threadcode;
+ void *arg = fa->arg;
+ JabberLog( "Thread started: %08X %d", callercode, GetCurrentThreadId());
+ JCallService( MS_SYSTEM_THREAD_PUSH, 0, 0 );
+ SetEvent( fa->hEvent );
+ __try {
+ callercode( arg );
+ } __finally {
+ JCallService( MS_SYSTEM_THREAD_POP, 0, 0 );
+ }
+ return;
+}
+
+ULONG JabberForkThread( void ( __cdecl *threadcode )( void* ), unsigned long stacksize, void *arg )
+{
+ struct FORK_ARG fa;
+ fa.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ fa.threadcode = threadcode;
+ fa.arg = arg;
+
+ ULONG rc = _beginthread(( JABBER_THREAD_FUNC )forkthread_r, stacksize, &fa );
+ if (( unsigned long ) -1L != rc )
+ WaitForSingleObject( fa.hEvent, INFINITE );
+
+ CloseHandle( fa.hEvent );
+ return rc;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// JabberSetServerStatus()
+
+void JabberSetServerStatus( int iNewStatus )
+{
+ if ( !jabberConnected )
+ return;
+
+ // change status
+ int oldStatus = jabberStatus;
+ switch ( iNewStatus ) {
+ case ID_STATUS_ONLINE:
+ case ID_STATUS_NA:
+ case ID_STATUS_FREECHAT:
+ case ID_STATUS_INVISIBLE:
+ jabberStatus = iNewStatus;
+ break;
+ case ID_STATUS_AWAY:
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OUTTOLUNCH:
+ jabberStatus = ID_STATUS_AWAY;
+ break;
+ case ID_STATUS_DND:
+ case ID_STATUS_OCCUPIED:
+ jabberStatus = ID_STATUS_DND;
+ break;
+ default:
+ return;
+ }
+
+ // send presence update
+ JabberSendPresence( jabberStatus );
+ JSendBroadcast( NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, ( HANDLE ) oldStatus, jabberStatus );
+}
+
+// Process a string, and double all % characters, according to chat.dll's restrictions
+// Returns a pointer to the new string (old one is not freed)
+char* EscapeChatTags(char* pszText)
+{
+ int nChars = 0;
+ for ( char* p = pszText; ( p = strchr( p, '%' )) != NULL; p++ )
+ nChars++;
+
+ if ( nChars == 0 )
+ return mir_strdup( pszText );
+
+ char* pszNewText = (char*)mir_alloc( strlen( pszText ) + 1 + nChars ), *s, *d;
+ if ( pszNewText == NULL )
+ return mir_strdup( pszText );
+
+ for ( s = pszText, d = pszNewText; *s; s++ ) {
+ if ( *s == '%' )
+ *d++ = '%';
+ *d++ = *s;
+ }
+ *d = 0;
+ return pszNewText;
+}
+
+char* UnEscapeChatTags(char* str_in)
+{
+ char* s = str_in, *d = str_in;
+ while ( *s ) {
+ if (( *s == '%' && s[1] == '%' ) || ( *s == '\n' && s[1] == '\n' ))
+ s++;
+ *d++ = *s++;
+ }
+ *d = 0;
+ return str_in;
+}