Example #1
0
static char *getDisplayName(const char *id)
{
	CONTACTINFO ci;
	char jid[256];
	HANDLE hContact;
	DBVARIANT dbv;
	if (!DBGetContactSetting(NULL, jabberProtoName, "LoginServer", &dbv)) {
		_snprintf(jid, sizeof(jid), "%s@%s", id, dbv.pszVal);
		JabberLog("JID: %s", jid);
		DBFreeVariant(&dbv);
		if (((hContact=JabberHContactFromJID(jid)) != NULL) || !strcmp(id, jabberThreadInfo->username)) {
			ZeroMemory(&ci, sizeof(ci));
			ci.cbSize = sizeof(ci);
			ci.hContact = hContact;
			ci.szProto = (char *)jabberProtoName;
			ci.dwFlag = CNF_DISPLAY;
			if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) {
				if (ci.type == CNFT_ASCIIZ) {
					if (ci.pszVal) {
						char * str = mir_strdup(ci.pszVal);
						JabberLog("NICK %s", str);
						miranda_sys_free(ci.pszVal);
						return str;
					}
				}
			}
		}
	}
	return mir_strdup(id);
}
Example #2
0
void JabberDBAddAuthRequest(TlenProtocol *proto, char *jid, char *nick)
{
	char *s;
	PBYTE pCurBlob;
    PBYTE pBlob;
	DWORD cbBlob;
	HANDLE hContact;

	if ((hContact=JabberHContactFromJID(proto, jid)) == NULL) {
		hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
		CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) proto->iface.m_szModuleName);
        // strip resource if present
        s = JabberLoginFromJID(jid);
        _strlwr(s);
		DBWriteContactSettingString(hContact, proto->iface.m_szModuleName, "jid", s);
        mir_free(s);
	}
	else {
		DBDeleteContactSetting(hContact, proto->iface.m_szModuleName, "Hidden");
	}
	DBWriteContactSettingString(hContact, proto->iface.m_szModuleName, "Nick", nick);
	JabberLog(proto, "auth request: %s, %s", jid, nick);
	//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)
	cbBlob = sizeof(DWORD) + sizeof(HANDLE) + (int)strlen(nick) + (int)strlen(jid) + 5;
	pBlob = pCurBlob = (PBYTE) mir_alloc(cbBlob);
	*((PDWORD) pCurBlob) = 0; pCurBlob += sizeof(DWORD);
	*((PHANDLE) pCurBlob) = hContact; pCurBlob += sizeof(HANDLE);
	strcpy((char *) pCurBlob, nick); pCurBlob += strlen(nick)+1;
	*pCurBlob = '\0'; pCurBlob++;		//firstName
	*pCurBlob = '\0'; pCurBlob++;		//lastName
	strcpy((char *) pCurBlob, jid); pCurBlob += strlen(jid)+1;
	*pCurBlob = '\0';					//reason
    JabberDBAddEvent(proto, NULL, EVENTTYPE_AUTHREQUEST, 0, pBlob, cbBlob);
}
Example #3
0
static char *getDisplayName(const char *id) 
{
	char jid[256];
	HANDLE hContact;
	DBVARIANT dbv;
	if (!DBGetContactSetting(NULL, jabberProtoName, "LoginServer", &dbv)) {
		_snprintf(jid, sizeof(jid), "%s@%s", id, dbv.pszVal);
		DBFreeVariant(&dbv);
		if ((hContact=JabberHContactFromJID(jid)) != NULL) {
			return _strdup((char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, 0));
		}
	}
	return _strdup(id);
}
void JabberMenuUpdateSrmmIcon(JABBER_LIST_ITEM *item)
{
	if ( item->list != LIST_ROSTER || !ServiceExists( MS_MSG_MODIFYICON ))
		return;

	HANDLE hContact = JabberHContactFromJID(item->jid);
	if (!hContact)
		return;

	StatusIconData sid = {0};
	sid.cbSize = sizeof(sid);
	sid.szModule = jabberProtoName;
	sid.flags = item->resourceCount ? 0 : MBF_HIDDEN;
	CallService(MS_MSG_MODIFYICON, (WPARAM)hContact, (LPARAM)&sid);
}
int JabberGcInit( WPARAM wParam, LPARAM lParam )
{
	JABBER_LIST_ITEM* item = ( JABBER_LIST_ITEM* )wParam;
	GCSESSION gcw = {0};
	GCEVENT gce = {0};

	TCHAR* szNick = JabberNickFromJID( item->jid );
	gcw.cbSize = sizeof(GCSESSION);
	gcw.iType = GCW_CHATROOM;
	gcw.pszModule = jabberProtoName;
	gcw.ptszName = szNick;
	gcw.ptszID = item->jid;
	gcw.dwFlags = GC_TCHAR;
	JCallService( MS_GC_NEWSESSION, NULL, (LPARAM)&gcw );

	HANDLE hContact = JabberHContactFromJID( item->jid );
	if ( hContact != NULL ) {
		DBVARIANT dbv;
		if ( !DBGetContactSettingTString( hContact, jabberProtoName, "MyNick", &dbv )) {
			if ( !lstrcmp( dbv.ptszVal, szNick ))
				JDeleteSetting( hContact, "MyNick" );
			else
				JSetStringT( hContact, "MyNick", item->nick );
			JFreeVariant( &dbv );
		}
		else JSetStringT( hContact, "MyNick", item->nick );
	}
	mir_free( szNick );

	item->bChatActive = TRUE;

	GCDEST gcd = { jabberProtoName, NULL, GC_EVENT_ADDGROUP };
	gcd.ptszID = item->jid;
	gce.cbSize = sizeof(GCEVENT);
	gce.pDest = &gcd;
	gce.dwFlags = GC_TCHAR;
	for ( int i = SIZEOF(sttRoles)-1; i >= 0; i-- ) {
		gce.ptszStatus = TranslateTS( sttRoles[i] );
		JCallService(MS_GC_EVENT, NULL, ( LPARAM )&gce );
	}

	gce.cbSize = sizeof(GCEVENT);
	gce.pDest = &gcd;
	gcd.iType = GC_EVENT_CONTROL;
	JCallService(MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce);
	JCallService(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce);
	return 0;
}
Example #6
0
HANDLE JabberDBCreateContact(TlenProtocol *proto, char *jid, char *nick, BOOL temporary)
{
	HANDLE hContact;
	if (jid==NULL || jid[0]=='\0')
		return NULL;

	if ((hContact=JabberHContactFromJID(proto, jid)) == NULL) {
		hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
		CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) proto->iface.m_szModuleName);
		DBWriteContactSettingString(hContact, proto->iface.m_szModuleName, "jid", jid);
		if (nick!=NULL && nick[0]!='\0')
			DBWriteContactSettingString(hContact, proto->iface.m_szModuleName, "Nick", nick);
		if (temporary)
			DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
	}
	return hContact;
}
Example #7
0
void JabberDBAddAuthRequest(char *jid, char *nick)
{
	char *s, *p, *q;
	DBEVENTINFO dbei = {0};
	PBYTE pCurBlob;
	HANDLE hContact;

	// strip resource if present
	s = mir_strdup(jid);
	if ((p=strchr(s, '@')) != NULL) {
		if ((q=strchr(p, '/')) != NULL)
			*q = '\0';
	}
	_strlwr(s);

	if ((hContact=JabberHContactFromJID(jid)) == NULL) {
		hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
		CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) jabberProtoName);
		DBWriteContactSettingString(hContact, jabberProtoName, "jid", s);
	}
	else {
		DBDeleteContactSetting(hContact, jabberProtoName, "Hidden");
	}
	DBWriteContactSettingString(hContact, jabberProtoName, "Nick", nick);

	//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)
	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(nick) + strlen(jid) + 5;
	pCurBlob = dbei.pBlob = (PBYTE) mir_alloc(dbei.cbBlob);
	*((PDWORD) pCurBlob) = 0; pCurBlob += sizeof(DWORD);
	*((PHANDLE) pCurBlob) = hContact; pCurBlob += sizeof(HANDLE);
	strcpy((char *) pCurBlob, nick); pCurBlob += strlen(nick)+1;
	*pCurBlob = '\0'; pCurBlob++;		//firstName
	*pCurBlob = '\0'; pCurBlob++;		//lastName
	strcpy((char *) pCurBlob, jid); pCurBlob += strlen(jid)+1;
	*pCurBlob = '\0';					//reason

	CallService(MS_DB_EVENT_ADD, (WPARAM) (HANDLE) NULL, (LPARAM) &dbei);
	JabberLog("Setup DBAUTHREQUEST with nick='%s' jid='%s'", nick, jid);
}
Example #8
0
HANDLE JabberDBCreateContact(char *jid, char *nick, BOOL temporary)
{
	HANDLE hContact;
	if (jid==NULL || jid[0]=='\0')
		return NULL;

	if ((hContact=JabberHContactFromJID(jid)) == NULL) {
		hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
		CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) jabberProtoName);
		DBWriteContactSettingString(hContact, jabberProtoName, "jid", jid);
		if (nick!=NULL && nick[0]!='\0')
			DBWriteContactSettingString(hContact, jabberProtoName, "Nick", nick);
		if (temporary)
			DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1);
		JabberLog("Create Jabber contact jid=%s, nick=%s", jid, nick);
	}
	return hContact;
}
Example #9
0
int TlenProcessAvatarNode(XmlNode *avatarNode, JABBER_LIST_ITEM *item) {
	XmlNode *aNode;
	char *oldHash = NULL;
	char *md5 = NULL, *type = NULL;
	HANDLE hContact;
	hContact = NULL;
	if (item != NULL) {
		if ((hContact=JabberHContactFromJID(item->jid)) == NULL) return 0;
	} 
	if (item == NULL) {
		oldHash = jabberThreadInfo->avatarHash;
	} else {
		oldHash = item->avatarHash;
	}
	if (avatarNode != NULL) {
		aNode = JabberXmlGetChild(avatarNode, "a");
		if (aNode != NULL) {
			type = JabberXmlGetAttrValue(aNode, "type");
			md5 = JabberXmlGetAttrValue(aNode, "md5");
		}
	}
	if (md5 != NULL) {
		/* check contact's avatar hash - md5 */
		if (oldHash == NULL || strcmp(oldHash, md5)) {
			if (item != NULL) {
				item->newAvatarDownloading = TRUE;
			}
			TlenGetAvatar(hContact);
			return 1;
		}
	} else {
		/* remove avatar */
		if (oldHash != NULL) {
			if (item != NULL) {
				item->avatarHash = NULL;
				mir_free(oldHash);
				item->newAvatarDownloading = FALSE;
			}
			RemoveAvatar(hContact);
			return 1;
		}
	}
	return 0;
}
void   JabberUpdateMirVer(JABBER_LIST_ITEM *item)
{
	HANDLE hContact = JabberHContactFromJID(item->jid);
	if (!hContact)
		return;

	int resource = -1;
	if (item->resourceMode == RSMODE_LASTSEEN)
		resource = item->lastSeenResource;
	else if (item->resourceMode == RSMODE_MANUAL)
		resource = item->manualResource;
	if ((resource < 0) || (resource >= item->resourceCount))
		return;

	if (!item->resource[resource].software)
		return;

	JSetStringT(hContact, "MirVer", item->resource[resource].software);
}
void sttRenameParticipantNick( JABBER_LIST_ITEM* item, TCHAR* oldNick, XmlNode *itemNode )
{
	TCHAR* newNick = JabberXmlGetAttrValue( itemNode, "nick" );
	TCHAR* jid = JabberXmlGetAttrValue( itemNode, "jid" );
	if ( newNick == NULL )
		return;

	for ( int i=0; i < item->resourceCount; i++ ) {
		JABBER_RESOURCE_STATUS& RS = item->resource[i];
		if ( !lstrcmp( RS.resourceName, oldNick )) {
			replaceStr( RS.resourceName, newNick );

			if ( !lstrcmp( item->nick, oldNick )) {
				replaceStr( item->nick, newNick );

				HANDLE hContact = JabberHContactFromJID( item->jid );
				if ( hContact != NULL )
					JSetStringT( hContact, "MyNick", newNick );
			}

			GCDEST gcd = { jabberProtoName, NULL, GC_EVENT_CHUID };
			gcd.ptszID = item->jid;

			GCEVENT gce = {0};
			gce.cbSize = sizeof(GCEVENT);
			gce.pDest = &gcd;
			gce.ptszNick = oldNick;
			gce.ptszText = newNick;
			if (jid != NULL)
				gce.ptszUserInfo = jid;
			gce.time = time(0);
			gce.dwFlags = GC_TCHAR;
			JCallService( MS_GC_EVENT, NULL, ( LPARAM )&gce );

			gcd.iType = GC_EVENT_NICK;
			gce.ptszNick = oldNick;
			gce.ptszUID = newNick;
			gce.ptszText = newNick;
			JCallService( MS_GC_EVENT, NULL, ( LPARAM )&gce );
			break;
}	}	}
void JabberGcQuit( JABBER_LIST_ITEM* item, int code, XmlNode* reason )
{
	TCHAR* szReason = NULL;
	if ( reason != NULL && reason->text != NULL )
		szReason = reason->text;

	GCDEST gcd = { jabberProtoName, NULL, GC_EVENT_CONTROL };
	gcd.ptszID = item->jid;
	GCEVENT gce = {0};
	gce.cbSize = sizeof(GCEVENT);
	gce.ptszUID = item->jid;
	gce.ptszText = szReason;
	gce.dwFlags = GC_TCHAR;
	gce.pDest = &gcd;

	if ( code != 307 ) {
		JCallService( MS_GC_EVENT, SESSION_TERMINATE, ( LPARAM )&gce );
		JCallService( MS_GC_EVENT, WINDOW_CLEARLOG, ( LPARAM )&gce );
	}
	else {
		TCHAR* myNick = JabberNickFromJID( jabberJID );
		JabberGcLogUpdateMemberStatus( item, myNick, NULL, GC_EVENT_KICK, reason );
		mir_free( myNick );
		JCallService( MS_GC_EVENT, SESSION_OFFLINE, ( LPARAM )&gce );
	}

	DBDeleteContactSetting( JabberHContactFromJID( item->jid ), "CList", "Hidden" );
	item->bChatActive = FALSE;

	if ( jabberOnline ) {
		TCHAR text[ 1024 ];
		mir_sntprintf( text, SIZEOF( text ), _T("%s/%s"), item->jid, item->nick );
		XmlNode p( "presence" ); p.addAttr( "to", text ); p.addAttr( "type", "unavailable" );
		JabberSend( jabberThreadInfo->s, p );
		JabberListRemove( LIST_CHATROOM, item->jid );
}	}
Example #13
0
static int ServiceParseXmppURI(WPARAM wParam, LPARAM lParam)
{
	char *arg = (char*)lParam;
	char *jid;
	UNREFERENCED_PARAMETER(wParam);
	if (arg == NULL) return 1; /* sanity check */
  /* skip leading prefix */
	arg = strchr(arg, ':');
	if (arg == NULL) return 1; /* parse failed */
	for (++arg; *arg == '/'; ++arg);
	/*
		complete specification: http://www.xmpp.org/extensions/xep-0147.html
		send message:           xmpp:JID?message;subject=TEXT&body=TEXT
		add user:               xmpp:JID?roster
		remove user:            xmpp:JID?remove
	*/
	/* user id */
	arg = strchr(jid = arg, '?');
	if (arg == NULL) arg += mir_strlen(arg); /* points to terminating nul */
	else *(arg++) = 0;
	if (*jid == 0) return 1; /* parse failed */
	 /* send a message to a contact */
	else if (*arg == 0 || (!_strnicmp(arg, "message", 7) && (*(arg + 7) == ';' || *(arg + 7) == 0))) {
		char *tok, *subj = NULL, *body = NULL;
		MCONTACT hContact;
		char msg[1024];
		arg += 7;
		while (*arg == ';') ++arg;
		tok = strtok(arg, "&"); /* first token */
		while (tok != NULL) {
			if (!_strnicmp(tok, "subject=", 8) && *(tok + 8) != 0)
				subj = Netlib_UrlDecode(tok + 8);
			if (!_strnicmp(tok, "body=", 5) && *(tok + 5) != 0)
				body = Netlib_UrlDecode(tok + 5);
			tok = strtok(NULL, "&"); /* next token */
		}
		if (ServiceExists(MS_MSG_SENDMESSAGE)) {
			hContact = JabberDBCreateContact(jid, jid, TRUE, FALSE);
			if (subj != NULL && body != NULL) {
				mir_snprintf(msg, _countof(msg), "%.128s %s", subj, body);
				body = msg;
			}
			else if (body == NULL) body = subj;
			if (hContact != NULL)
				CallService(MS_MSG_SENDMESSAGE, hContact, (LPARAM)body);
		}
		return 0;
	}
	/* add user to contact list */
	else if (!_strnicmp(arg, "roster", 6) && (*(arg + 6) == ';' || *(arg + 6) == 0)) {
		ADDCONTACTSTRUCT acs;
		PROTOSEARCHRESULT psr;
		if (JabberHContactFromJID(jid) == NULL) { /* does not yet check if jid belongs to current user */
			acs.handleType = HANDLE_SEARCHRESULT;
			acs.szProto = jabberProtoName;
			acs.psr = &psr;
			memset(&psr, 0, sizeof(PROTOSEARCHRESULT));
			psr.cbSize = sizeof(PROTOSEARCHRESULT);
			psr.nick.t = jid;
			CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs);
		}
		return 0;
	}
	/* remove user from contact list */
	else if (!_strnicmp(arg, "remove", 6) && (*(arg + 6) == ';' || *(arg + 6) == 0)) {
		MCONTACT hContact;
		hContact = JabberHContactFromJID(jid);
		if (hContact == NULL) /* not yet implemented: show standard miranda dialog here */
			CallService(MS_DB_CONTACT_DELETE, hContact, 0);
		return 0;
	}
	/* add user subscription */
	else if (!_strnicmp(arg, "subscribe", 9) && (*(arg + 9) == ';' || *(arg + 9) == 0)) {
		/* not yet implemented */
		return 0;
	}
	/* remove user subscription */
	else if (!_strnicmp(arg, "unsubscribe", 11) && (*(arg + 11) == ';' || *(arg + 11) == 0)) {
		/* not yet implemented */
		return 0;
	}
	return 1; /* parse failed */
}
static void sttLogListHook( JABBER_LIST_ITEM* item, GCHOOK* gch )
{
	TCHAR szBuffer[ 1024 ];

	switch( gch->dwData ) {
	case IDM_VOICE:
		JabberAdminGet( gch->pDest->ptszID, xmlnsAdmin, "role", _T("participant"), JabberIqResultMucGetVoiceList );
		break;

	case IDM_MEMBER:
		JabberAdminGet( gch->pDest->ptszID, xmlnsAdmin, "affiliation", _T("member"), JabberIqResultMucGetMemberList );
		break;

	case IDM_MODERATOR:
		JabberAdminGet( gch->pDest->ptszID, xmlnsAdmin, "role", _T("moderator"), JabberIqResultMucGetModeratorList );
		break;

	case IDM_BAN:
		JabberAdminGet( gch->pDest->ptszID, xmlnsAdmin, "affiliation", _T("outcast"), JabberIqResultMucGetBanList );
		break;

	case IDM_ADMIN:
		JabberAdminGet( gch->pDest->ptszID, xmlnsOwner, "affiliation", _T("admin"), JabberIqResultMucGetAdminList );
		break;

	case IDM_OWNER:
		JabberAdminGet( gch->pDest->ptszID, xmlnsOwner, "affiliation", _T("owner"), JabberIqResultMucGetOwnerList );
		break;

	case IDM_TOPIC:
		mir_sntprintf( szBuffer, SIZEOF(szBuffer), _T("%s %s"), TranslateT( "Set topic for" ), gch->pDest->ptszID );
		if ( JabberEnterString( szBuffer, SIZEOF(szBuffer))) {
			XmlNode msg( "message" ); msg.addAttr( "to", gch->pDest->ptszID ); msg.addAttr( "type", "groupchat" );
			msg.addChild( "subject", szBuffer );
			JabberSend( jabberThreadInfo->s, msg );
		}
		break;

	case IDM_NICK:
		mir_sntprintf( szBuffer, SIZEOF(szBuffer), _T("%s %s"), TranslateT( "Change nickname in" ), gch->pDest->ptszID );
		if ( JabberEnterString( szBuffer, SIZEOF(szBuffer))) {
			JABBER_LIST_ITEM* item = JabberListGetItemPtr( LIST_CHATROOM, gch->pDest->ptszID );
			if ( item != NULL ) {
				TCHAR text[ 1024 ];
				mir_sntprintf( text, SIZEOF( text ), _T("%s/%s"), gch->pDest->ptszID, szBuffer );
				JabberSendPresenceTo( jabberStatus, text, NULL );
		}	}
		break;

	case IDM_INVITE:
		CreateDialogParam( hInst, MAKEINTRESOURCE( IDD_GROUPCHAT_INVITE ), NULL, JabberGcLogInviteDlgProc, ( LPARAM )gch->pDest->pszID );
		break;

	case IDM_CONFIG:
	{
		int iqId = JabberSerialNext();
		JabberIqAdd( iqId, IQ_PROC_NONE, JabberIqResultGetMuc );

		XmlNodeIq iq( "get", iqId, gch->pDest->ptszID );
		XmlNode* query = iq.addQuery( xmlnsOwner );
		JabberSend( jabberThreadInfo->s, iq );
		break;
	}
	case IDM_BOOKMARKS:
	{
		JABBER_LIST_ITEM* item = JabberListGetItemPtr( LIST_BOOKMARK, gch->pDest->ptszID );
		if ( item == NULL ) {
			item = JabberListGetItemPtr( LIST_CHATROOM, gch->pDest->ptszID );
			if (item != NULL) {
				item->type = _T("conference");
				HANDLE hContact = JabberHContactFromJID( item->jid );
				item->name = ( TCHAR* )JCallService( MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR );
				JabberAddEditBookmark(NULL, (LPARAM) item);
			}
		}
		break;
	}
	case IDM_DESTROY:
		mir_sntprintf( szBuffer, SIZEOF(szBuffer), _T("%s %s"), TranslateT( "Reason to destroy" ), gch->pDest->ptszID );
		if ( !JabberEnterString( szBuffer, SIZEOF(szBuffer)))
			break;

		{	XmlNodeIq iq( "set", NOID, gch->pDest->ptszID );
			XmlNode* query = iq.addQuery( xmlnsOwner );
			query->addChild( "destroy" )->addChild( "reason", szBuffer );
			JabberSend( jabberThreadInfo->s, iq );
		}

	case IDM_LEAVE:
		JabberGcQuit( item, 0, 0 );
		break;
}	}
static BOOL CALLBACK JabberGcLogInviteDlgProc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch ( msg ) {
	case WM_INITDIALOG:
		{
			RECT dlgRect, scrRect;
			GetWindowRect( hwndDlg, &dlgRect );
			SystemParametersInfo( SPI_GETWORKAREA, 0, &scrRect, 0 );
			SetWindowPos( hwndDlg, HWND_TOPMOST, (scrRect.right/2)-(dlgRect.right/2), (scrRect.bottom/2)-(dlgRect.bottom/2), 0, 0, SWP_NOSIZE );
			TranslateDialogDefault( hwndDlg );
			SendMessage( hwndDlg, WM_SETICON, ICON_BIG, ( LPARAM )iconBigList[0]);
			SetDlgItemText( hwndDlg, IDC_ROOM, ( TCHAR* )lParam );

			SetWindowLong(GetDlgItem(hwndDlg, IDC_CLIST), GWL_STYLE,
				GetWindowLong(GetDlgItem(hwndDlg, IDC_CLIST), GWL_STYLE)|CLS_HIDEOFFLINE|CLS_CHECKBOXES|CLS_HIDEEMPTYGROUPS|CLS_USEGROUPS|CLS_GREYALTERNATE|CLS_GROUPCHECKBOXES);
			SendMessage(GetDlgItem(hwndDlg, IDC_CLIST), CLM_SETEXSTYLE, CLS_EX_DISABLEDRAGDROP|CLS_EX_TRACKSELECT, 0);
			ResetListOptions(GetDlgItem(hwndDlg, IDC_CLIST));
			FilterList(GetDlgItem(hwndDlg, IDC_CLIST));

			SendDlgItemMessage(hwndDlg, IDC_ADDJID, BUTTONSETASFLATBTN, 0, 0);
			SendDlgItemMessage(hwndDlg, IDC_ADDJID, BM_SETIMAGE, IMAGE_ICON, (LPARAM)iconList[17]);//LoadIconEx("addroster"));

			// use new operator to properly construct LIST object
			JabberGcLogInviteDlgData *data = new JabberGcLogInviteDlgData((TCHAR *)lParam);
			data->room = mir_tstrdup((TCHAR *)lParam);
			SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)data);
		}
		return TRUE;

	case WM_COMMAND:
		switch ( LOWORD( wParam )) {
		case IDC_ADDJID:
			{
				TCHAR buf[JABBER_MAX_JID_LEN];
				GetWindowText(GetDlgItem(hwndDlg, IDC_NEWJID), buf, SIZEOF(buf));
				SetWindowText(GetDlgItem(hwndDlg, IDC_NEWJID), _T(""));

				if (JabberHContactFromJID(buf))
					break;

				JabberGcLogInviteDlgData *data = (JabberGcLogInviteDlgData *)GetWindowLong(hwndDlg, GWL_USERDATA);

				int i;
				for (i = 0; i < data->newJids.getCount(); ++i)
					if (!lstrcmp(data->newJids[i]->jid, buf))
						break;
				if (i != data->newJids.getCount())
					break;

				JabberGcLogInviteDlgJidData *jidData = (JabberGcLogInviteDlgJidData *)mir_alloc(sizeof(JabberGcLogInviteDlgJidData));
				lstrcpy(jidData->jid, buf);
				CLCINFOITEM cii = {0};
				cii.cbSize = sizeof(cii);
				cii.flags = CLCIIF_CHECKBOX;
				mir_sntprintf(buf, SIZEOF(buf), _T("%s (%s)"), jidData->jid, TranslateT("not on roster"));
				cii.pszText = buf;
				jidData->hItem = SendDlgItemMessage(hwndDlg,IDC_CLIST,CLM_ADDINFOITEM,0,(LPARAM)&cii);
				SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, jidData->hItem, 1);
				data->newJids.insert(jidData);
			}
			break;

		case IDC_INVITE:
			{
				JabberGcLogInviteDlgData *data = (JabberGcLogInviteDlgData *)GetWindowLong(hwndDlg, GWL_USERDATA);
				TCHAR* room = data->room;
				if ( room != NULL ) {
					TCHAR text[256];
					GetDlgItemText( hwndDlg, IDC_REASON, text, SIZEOF( text ));
					HWND hwndList = GetDlgItem(hwndDlg, IDC_CLIST);

					// invite users from roster
					for	(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
							hContact;
							hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) {
						char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
						if ( !lstrcmpA(proto, jabberProtoName) && !DBGetContactSettingByte(hContact, proto, "ChatRoom", 0)) {
							if (int hItem = SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0)) {
								if ( SendMessage(hwndList, CLM_GETCHECKMARK, (WPARAM)hItem, 0 )) {
									DBVARIANT dbv={0};
									JGetStringT(hContact, "jid", &dbv);
									if (dbv.ptszVal && ( dbv.type == DBVT_ASCIIZ || dbv.type == DBVT_WCHAR ))
										InviteUser(room, dbv.ptszVal, text);
									JFreeVariant(&dbv);
					}	}	}	}

					// invite others
					for (int i = 0; i < data->newJids.getCount(); ++i)
						if (SendMessage(hwndList, CLM_GETCHECKMARK, (WPARAM)data->newJids[i]->hItem, 0))
							InviteUser(room, data->newJids[i]->jid, text);
			}	}
			// Fall through
		case IDCANCEL:
		case IDCLOSE:
			DestroyWindow( hwndDlg );
			return TRUE;
		}
		break;

	case WM_NOTIFY:
		if (((LPNMHDR)lParam)->idFrom == IDC_CLIST) {
			switch (((LPNMHDR)lParam)->code) {
			case CLN_NEWCONTACT:
				FilterList(GetDlgItem(hwndDlg,IDC_CLIST));
				break;
			case CLN_LISTREBUILT:
				FilterList(GetDlgItem(hwndDlg,IDC_CLIST));
				break;
			case CLN_OPTIONSCHANGED:
				ResetListOptions(GetDlgItem(hwndDlg,IDC_CLIST));
				break;
		}	}
		break;

	case WM_CLOSE:
		DestroyWindow( hwndDlg );
		break;

	case WM_DESTROY:
		JabberGcLogInviteDlgData *data = (JabberGcLogInviteDlgData *)GetWindowLong(hwndDlg, GWL_USERDATA);
		delete data;
		break;
	}

	return FALSE;
}
Example #16
0
void JabberIqResultGetRoster(XmlNode *iqNode, void *userdata)
{
	//struct ThreadData *info = (struct ThreadData *) userdata;
	XmlNode *queryNode;
	char *type;
	char *str;

	// RECVED: roster information
	// ACTION: populate LIST_ROSTER and create contact for any new rosters
	JabberLog("<iq/> iqIdGetRoster");
	if ((type=JabberXmlGetAttrValue(iqNode, "type")) == NULL) return;
	if ((queryNode=JabberXmlGetChild(iqNode, "query")) == NULL) return;

	if (!strcmp(type, "result")) {
		str = JabberXmlGetAttrValue(queryNode, "xmlns");
		if (str!=NULL && !strcmp(str, "jabber:iq:roster")) {
			DBVARIANT dbv;
			XmlNode *itemNode, *groupNode;
			JABBER_SUBSCRIPTION sub;
			JABBER_LIST_ITEM *item;
			HANDLE hContact;
			char *jid, *name, *nick;
			int i, oldStatus;

			for (i=0; i<queryNode->numChild; i++) {
				itemNode = queryNode->child[i];
				if (!strcmp(itemNode->name, "item")) {
					str = JabberXmlGetAttrValue(itemNode, "subscription");
					if (str==NULL) sub = SUB_NONE;
					else if (!strcmp(str, "both")) sub = SUB_BOTH;
					else if (!strcmp(str, "to")) sub = SUB_TO;
					else if (!strcmp(str, "from")) sub = SUB_FROM;
					else sub = SUB_NONE;
					//if (str!=NULL && (!strcmp(str, "to") || !strcmp(str, "both"))) {
					if ((jid=JabberXmlGetAttrValue(itemNode, "jid")) != NULL) {
						if ((name=JabberXmlGetAttrValue(itemNode, "name")) != NULL) {
							nick = JabberTextDecode(name);
						} else {
							nick = JabberLocalNickFromJID(jid);
						}
						if (nick != NULL) {
							item = JabberListAdd(LIST_ROSTER, jid);
							if (item->nick) free(item->nick);
							item->nick = nick;
							item->subscription = sub;
							if ((hContact=JabberHContactFromJID(jid)) == NULL) {
								// Received roster has a new JID.
								// Add the jid (with empty resource) to Miranda contact list.
								hContact = JabberDBCreateContact(jid, nick, FALSE, TRUE);
							}
							DBWriteContactSettingString(hContact, "CList", "MyHandle", nick);
							if (item->group) free(item->group);
							if ((groupNode=JabberXmlGetChild(itemNode, "group"))!=NULL && groupNode->text!=NULL) {
								item->group = JabberTextDecode(groupNode->text);
								JabberContactListCreateGroup(item->group);
								// Don't set group again if already correct, or Miranda may show wrong group count in some case
								if (!DBGetContactSetting(hContact, "CList", "Group", &dbv)) {
									if (strcmp(dbv.pszVal, item->group))
										DBWriteContactSettingString(hContact, "CList", "Group", item->group);
									DBFreeVariant(&dbv);
								}
								else
									DBWriteContactSettingString(hContact, "CList", "Group", item->group);
							}
							else {
								item->group = NULL;
								DBDeleteContactSetting(hContact, "CList", "Group");
							}
						}
					}
				}
			}
			// Delete orphaned contacts (if roster sync is enabled)
			if (DBGetContactSettingByte(NULL, jabberProtoName, "RosterSync", FALSE) == TRUE) {
				HANDLE *list;
				int listSize, listAllocSize;

				listSize = listAllocSize = 0;
				list = NULL;
				hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
				while (hContact != NULL) {
					str = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
					if(str!=NULL && !strcmp(str, jabberProtoName)) {
						if (!DBGetContactSetting(hContact, jabberProtoName, "jid", &dbv)) {
							if (!JabberListExist(LIST_ROSTER, dbv.pszVal)) {
								JabberLog("Syncing roster: preparing to delete %s (hContact=0x%x)", dbv.pszVal, hContact);
								if (listSize >= listAllocSize) {
									listAllocSize = listSize + 100;
									if ((list=(HANDLE *) realloc(list, listAllocSize)) == NULL) {
										listSize = 0;
										break;
									}
								}
								list[listSize++] = hContact;
							}
							DBFreeVariant(&dbv);
						}
					}
					hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
				}
				for (i=0; i<listSize; i++) {
					JabberLog("Syncing roster: deleting 0x%x", list[i]);
					CallService(MS_DB_CONTACT_DELETE, (WPARAM) list[i], 0);
				}
				if (list != NULL)
					free(list);
			}
			///////////////////////////////////////
			{
				CLISTMENUITEM clmi;
				memset(&clmi, 0, sizeof(CLISTMENUITEM));
				clmi.cbSize = sizeof(CLISTMENUITEM);
				clmi.flags = CMIM_FLAGS;
				CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hMenuMUC, (LPARAM) &clmi);
				CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hMenuChats, (LPARAM) &clmi);
			}

			jabberOnline = TRUE;
			JabberLog("Status changed via THREADSTART");
			oldStatus = jabberStatus;
			switch (jabberDesiredStatus) {
			case ID_STATUS_ONLINE:
			case ID_STATUS_NA:
			case ID_STATUS_FREECHAT:
			case ID_STATUS_INVISIBLE:
				jabberStatus = jabberDesiredStatus;
				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;
			}
			JabberSendPresence(jabberStatus);
			ProtoBroadcastAck(jabberProtoName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, jabberStatus);
			//////////////////////////////////
		}
	}
}
Example #17
0
// Tlen actually use jabber:iq:search for other users vCard or jabber:iq:register for own vCard
void TlenIqResultGetVcard(XmlNode *iqNode, void *userdata)
{
	XmlNode *queryNode, *itemNode, *n;
	char *type, *jid;
	char text[128];
	HANDLE hContact;
	char *nText;

	JabberLog("<iq/> iqIdGetVcard (tlen)");
	if ((type=JabberXmlGetAttrValue(iqNode, "type")) == NULL) return;

	if (!strcmp(type, "result")) {
		BOOL hasFirst, hasLast, hasNick, hasEmail, hasCity, hasAge, hasGender, hasSchool, hasLookFor, hasOccupation;
		DBVARIANT dbv;
		int i;

		if ((queryNode=JabberXmlGetChild(iqNode, "query")) == NULL) return;
		if ((itemNode=JabberXmlGetChild(queryNode, "item")) == NULL) return;
		if ((jid=JabberXmlGetAttrValue(itemNode, "jid")) != NULL) {
			if (DBGetContactSetting(NULL, jabberProtoName, "LoginServer", &dbv)) return;
			sprintf(text, "%s@%s", jid, dbv.pszVal);	// Add @tlen.pl
			DBFreeVariant(&dbv);
			if ((hContact=JabberHContactFromJID(text)) == NULL) {
				if (DBGetContactSetting(NULL, jabberProtoName, "LoginName", &dbv)) return;
				if (strcmp(dbv.pszVal, jid)) {
					DBFreeVariant(&dbv);
					return;
				}
				DBFreeVariant(&dbv);
			}
		} else {
			hContact = NULL;
		}
		hasFirst = hasLast = hasNick = hasEmail = hasCity = hasAge = hasGender = hasOccupation = hasLookFor = hasSchool = FALSE;
		for (i=0; i<itemNode->numChild; i++) {
			n = itemNode->child[i];
			if (n==NULL || n->name==NULL) continue;
			if (!strcmp(n->name, "first")) {
				if (n->text != NULL) {
					hasFirst = TRUE;
					nText = JabberTextDecode(n->text);
					DBWriteContactSettingString(hContact, jabberProtoName, "FirstName", nText);
					free(nText);
				}
			}
			else if (!strcmp(n->name, "last")) {
				if (n->text != NULL) {
					hasLast = TRUE;
					nText = JabberTextDecode(n->text);
					DBWriteContactSettingString(hContact, jabberProtoName, "LastName", nText);
					free(nText);
				}
			}
			else if (!strcmp(n->name, "nick")) {
				if (n->text != NULL) {
					hasNick = TRUE;
					nText = JabberTextDecode(n->text);
					DBWriteContactSettingString(hContact, jabberProtoName, "Nick", nText);
					free(nText);
				}
			}
			else if (!strcmp(n->name, "email")) {
				if (n->text != NULL) {
					hasEmail = TRUE;
					nText = JabberTextDecode(n->text);
					DBWriteContactSettingString(hContact, jabberProtoName, "e-mail", nText);
					free(nText);
				}
			}
			else if (!strcmp(n->name, "c")) {
				if (n->text != NULL) {
					hasCity = TRUE;
					nText = JabberTextDecode(n->text);
					DBWriteContactSettingString(hContact, jabberProtoName, "City", nText);
					free(nText);
				}
			}
			else if (!strcmp(n->name, "b")) {
				if (n->text != NULL) {
					WORD nAge;
					hasAge = TRUE;
					nAge = atoi(n->text);
					DBWriteContactSettingWord(hContact, jabberProtoName, "Age", nAge);
				}
			}
			else if (!strcmp(n->name, "s")) {
				if (n->text!=NULL && n->text[1]=='\0' && (n->text[0]=='1' || n->text[0]=='2')) {
					hasGender = TRUE;
					DBWriteContactSettingByte(hContact, jabberProtoName, "Gender", (BYTE) (n->text[0]=='1'?'M':'F'));
				}
			}
			else if (!strcmp(n->name, "e")) {
				if (n->text != NULL) {
					hasSchool = TRUE;
					nText = JabberTextDecode(n->text);
					DBWriteContactSettingString(hContact, jabberProtoName, "School", nText);
					free(nText);
				}
			}
			else if (!strcmp(n->name, "j")) {
				if (n->text != NULL) {
					WORD nOccupation;
					hasOccupation = TRUE;
					nOccupation = atoi(n->text);
					DBWriteContactSettingWord(hContact, jabberProtoName, "Occupation", nOccupation);
				}
			}
			else if (!strcmp(n->name, "r")) {
				if (n->text != NULL) {
					WORD nLookFor;
					hasLookFor = TRUE;
					nLookFor = atoi(n->text);
					DBWriteContactSettingWord(hContact, jabberProtoName, "LookingFor", nLookFor);
				}
			}
			else if (!strcmp(n->name, "g")) {
				if (n->text != NULL) {
					BYTE bVoice;
					bVoice = atoi(n->text);
					DBWriteContactSettingWord(hContact, jabberProtoName, "VoiceChat", bVoice);
				}
			}
		}
		if (!hasFirst)
			DBDeleteContactSetting(hContact, jabberProtoName, "FirstName");
		if (!hasLast)
			DBDeleteContactSetting(hContact, jabberProtoName, "LastName");
		// We are not removing "Nick"
//		if (!hasNick)
//			DBDeleteContactSetting(hContact, jabberProtoName, "Nick");
		if (!hasEmail)
			DBDeleteContactSetting(hContact, jabberProtoName, "e-mail");
		if (!hasCity)
			DBDeleteContactSetting(hContact, jabberProtoName, "City");
		if (!hasAge)
			DBDeleteContactSetting(hContact, jabberProtoName, "Age");
		if (!hasGender)
			DBDeleteContactSetting(hContact, jabberProtoName, "Gender");
		if (!hasSchool)
			DBDeleteContactSetting(hContact, jabberProtoName, "School");
		if (!hasOccupation)
			DBDeleteContactSetting(hContact, jabberProtoName, "Occupation");
		if (!hasLookFor)
			DBDeleteContactSetting(hContact, jabberProtoName, "LookingFor");
		ProtoBroadcastAck(jabberProtoName, hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, 0);
	}
}
Example #18
0
void TlenProcessPresenceAvatar(XmlNode *node, JABBER_LIST_ITEM *item) {
	HANDLE hContact;
	if ((hContact=JabberHContactFromJID(item->jid)) == NULL) return;
	TlenProcessAvatarNode(JabberXmlGetChild(node, "avatar"), item);
}
void JabberFtHandleSiRequest( XmlNode *iqNode )
{
	TCHAR* from, *sid, *str, *szId, *filename;
	XmlNode *siNode, *fileNode, *featureNode, *xNode, *fieldNode, *optionNode, *n;
	int filesize, i;
	JABBER_FT_TYPE ftType;

	if ( iqNode==NULL ||
		  ( from=JabberXmlGetAttrValue( iqNode, "from" ))==NULL ||
		  ( str=JabberXmlGetAttrValue( iqNode, "type" ))==NULL || _tcscmp( str, _T("set")) ||
		  ( siNode=JabberXmlGetChildWithGivenAttrValue( iqNode, "si", "xmlns", _T("http://jabber.org/protocol/si"))) == NULL )
		return;

	szId = JabberXmlGetAttrValue( iqNode, "id" );
	if (( sid=JabberXmlGetAttrValue( siNode, "id" ))!=NULL &&
		( fileNode=JabberXmlGetChildWithGivenAttrValue( siNode, "file", "xmlns", _T("http://jabber.org/protocol/si/profile/file-transfer")))!=NULL &&
		( filename=JabberXmlGetAttrValue( fileNode, "name" ))!=NULL &&
		( str=JabberXmlGetAttrValue( fileNode, "size" ))!=NULL ) {

		filesize = _ttoi( str );
		if (( featureNode=JabberXmlGetChildWithGivenAttrValue( siNode, "feature", "xmlns", _T("http://jabber.org/protocol/feature-neg"))) != NULL &&
			( xNode=JabberXmlGetChildWithGivenAttrValue( featureNode, "x", "xmlns", _T("jabber:x:data")))!=NULL &&
			( fieldNode=JabberXmlGetChildWithGivenAttrValue( xNode, "field", "var", _T("stream-method")))!=NULL ) {

			for ( i=0; i<fieldNode->numChild; i++ ) {
				optionNode = fieldNode->child[i];
				if ( optionNode->name && !strcmp( optionNode->name, "option" )) {
					if (( n=JabberXmlGetChild( optionNode, "value" ))!=NULL && n->text ) {
						if ( !_tcscmp( n->text, _T("http://jabber.org/protocol/bytestreams"))) {
							ftType = FT_BYTESTREAM;
							break;
			}	}	}	}

			if ( i < fieldNode->numChild ) {
				// Found known stream mechanism
				CCSDATA ccs;
				PROTORECVEVENT pre;

				char *localFilename = t2a( filename );
				char *desc = (( n=JabberXmlGetChild( fileNode, "desc" ))!=NULL && n->text!=NULL ) ? t2a( n->text ) : mir_strdup( "" );

				filetransfer* ft = new filetransfer;
				ft->jid = mir_tstrdup( from );
				ft->std.hContact = JabberHContactFromJID( from );
				ft->sid = mir_tstrdup( sid );
				ft->iqId = mir_tstrdup( szId );
				ft->type = ftType;
				ft->std.totalFiles = 1;
				ft->std.currentFile = localFilename;
				ft->std.totalBytes = ft->std.currentFileSize = filesize;
				char* szBlob = ( char* )alloca( sizeof( DWORD )+ strlen( localFilename ) + strlen( desc ) + 2 );
				*(( PDWORD ) szBlob ) = ( DWORD )ft;
				strcpy( szBlob + sizeof( DWORD ), localFilename );
				strcpy( szBlob + sizeof( DWORD )+ strlen( localFilename ) + 1, desc );
				pre.flags = 0;
				pre.timestamp = time( NULL );
				pre.szMessage = szBlob;
				pre.lParam = 0;
				ccs.szProtoService = PSR_FILE;
				ccs.hContact = ft->std.hContact;
				ccs.wParam = 0;
				ccs.lParam = ( LPARAM )&pre;
				JCallService( MS_PROTO_CHAINRECV, 0, ( LPARAM )&ccs );
				mir_free( desc );
				return;
			}
			else {
				// Unknown stream mechanism
				XmlNodeIq iq( "error", szId, from );
				XmlNode* e = iq.addChild( "error" ); e->addAttr( "code", 400 ); e->addAttr( "type", "cancel" );
				XmlNode* br = e->addChild( "bad-request" ); br->addAttr( "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas" );
				XmlNode* nvs = e->addChild( "no-valid-streams" ); nvs->addAttr( "xmlns", "http://jabber.org/protocol/si" );
				JabberSend( jabberThreadInfo->s, iq );
				return;
	}	}	}

	// Bad stream initiation, reply with bad-profile
	XmlNodeIq iq( "error", szId, from );
	XmlNode* e = iq.addChild( "error" ); e->addAttr( "code", 400 ); e->addAttr( "type", "cancel" );
	XmlNode* br = e->addChild( "bad-request" ); br->addAttr( "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas" );
	XmlNode* nvs = e->addChild( "bad-profile" ); nvs->addAttr( "xmlns", "http://jabber.org/protocol/si" );
	JabberSend( jabberThreadInfo->s, iq );
}
void TlenProcessPresence(XmlNode *node, TlenProtocol *proto)
{
	HANDLE hContact;
	XmlNode *showNode, *statusNode;
	JABBER_LIST_ITEM *item;
	char *from, *type, *nick, *show;
	int status, laststatus = ID_STATUS_OFFLINE;
	char *p;

	if ((from=JabberXmlGetAttrValue(node, "from")) != NULL) {
		if (JabberListExist(proto, LIST_CHATROOM, from)); //JabberGroupchatProcessPresence(node, userdata);

		else {
			type = JabberXmlGetAttrValue(node, "type");
			item = JabberListGetItemPtr(proto, LIST_ROSTER, from);
			if (item != NULL) {
				if (proto->tlenOptions.enableAvatars) {
					TlenProcessPresenceAvatar(proto, node, item);
				}
			}
			if (type==NULL || (!strcmp(type, "available"))) {
				if ((nick=JabberLocalNickFromJID(from)) != NULL) {
					if ((hContact=JabberHContactFromJID(proto, from)) == NULL)
						hContact = JabberDBCreateContact(proto, from, nick, FALSE);
					if (!JabberListExist(proto, LIST_ROSTER, from)) {
						JabberLog(proto, "Receive presence online from %s (who is not in my roster)", from);
						JabberListAdd(proto, LIST_ROSTER, from);
					}
					status = ID_STATUS_ONLINE;
					if ((showNode=JabberXmlGetChild(node, "show")) != NULL) {
						if ((show=showNode->text) != NULL) {
							if (!strcmp(show, "away")) status = ID_STATUS_AWAY;
							else if (!strcmp(show, "xa")) status = ID_STATUS_NA;
							else if (!strcmp(show, "dnd")) status = ID_STATUS_DND;
							else if (!strcmp(show, "chat")) status = ID_STATUS_FREECHAT;
							else if (!strcmp(show, "unavailable")) {
								// Always show invisible (on old Tlen client) as invisible (not offline)
								status = ID_STATUS_OFFLINE;
							}
						}
					}

					statusNode = JabberXmlGetChild(node, "status");
					if (statusNode)
						p = JabberTextDecode(statusNode->text);
					else
						p = NULL;
					JabberListAddResource(proto, LIST_ROSTER, from, status, statusNode?p:NULL);
					if (p) {
						DBWriteContactSettingString(hContact, "CList", "StatusMsg", p);
						mir_free(p);
					} else {
						DBDeleteContactSetting(hContact, "CList", "StatusMsg");
					}
					// Determine status to show for the contact and request version information
					if (item != NULL) {
						laststatus = item->status;
						item->status = status;
					}
					if (strchr(from, '@')!=NULL || DBGetContactSettingByte(NULL, proto->iface.m_szModuleName, "ShowTransport", TRUE)==TRUE) {
						if (DBGetContactSettingWord(hContact, proto->iface.m_szModuleName, "Status", ID_STATUS_OFFLINE) != status)
							DBWriteContactSettingWord(hContact, proto->iface.m_szModuleName, "Status", (WORD) status);
					}
					if (item != NULL) {
						if (!item->infoRequested) {
							int iqId = JabberSerialNext(proto);
							item->infoRequested = TRUE;
							JabberSend( proto, "<iq type='get' id='"JABBER_IQID"%d'><query xmlns='jabber:iq:info' to='%s'></query></iq>", iqId, from);
						}
						if (proto->tlenOptions.enableVersion && !item->versionRequested) {
							item->versionRequested = TRUE;
							if (proto->iface.m_iStatus != ID_STATUS_INVISIBLE) {
								JabberSend( proto, "<message to='%s' type='iq'><iq type='get'><query xmlns='jabber:iq:version'/></iq></message>", from );
							}
						}
					}
					JabberLog(proto, "%s (%s) online, set contact status to %d", nick, from, status);
					mir_free(nick);
				}
			}
			else if (!strcmp(type, "unavailable")) {
				if (!JabberListExist(proto, LIST_ROSTER, from)) {
					JabberLog(proto, "Receive presence offline from %s (who is not in my roster)", from);
					JabberListAdd(proto, LIST_ROSTER, from);
				}
				else {
					JabberListRemoveResource(proto, LIST_ROSTER, from);
				}
				status = ID_STATUS_OFFLINE;
				statusNode = JabberXmlGetChild(node, "status");
				if (statusNode) {
					if (proto->tlenOptions.offlineAsInvisible) {
						status = ID_STATUS_INVISIBLE;
					}
					p = JabberTextDecode(statusNode->text);
					JabberListAddResource(proto, LIST_ROSTER, from, status, p);
					if ((hContact=JabberHContactFromJID(proto, from)) != NULL) {
						if (p) {
							DBWriteContactSettingString(hContact, "CList", "StatusMsg", p);
						} else {
							DBDeleteContactSetting(hContact, "CList", "StatusMsg");
						}
					}
					if (p) mir_free(p);
				}
				if ((item=JabberListGetItemPtr(proto, LIST_ROSTER, from)) != NULL) {
					// Determine status to show for the contact based on the remaining resources
					item->status = status;
					item->versionRequested = FALSE;
					item->infoRequested = FALSE;
				}
				if ((hContact=JabberHContactFromJID(proto, from)) != NULL) {
					if (strchr(from, '@')!=NULL || DBGetContactSettingByte(NULL, proto->iface.m_szModuleName, "ShowTransport", TRUE)==TRUE) {
						if (DBGetContactSettingWord(hContact, proto->iface.m_szModuleName, "Status", ID_STATUS_OFFLINE) != status)
							DBWriteContactSettingWord(hContact, proto->iface.m_szModuleName, "Status", (WORD) status);
					}
					if (item != NULL && item->isTyping) {
						item->isTyping = FALSE;
						CallService(MS_PROTO_CONTACTISTYPING, (WPARAM) hContact, PROTOTYPE_CONTACTTYPING_OFF);
					}
					JabberLog(proto, "%s offline, set contact status to %d", from, status);
				}
			}
			else if (!strcmp(type, "subscribe")) {
				if (strchr(from, '@') == NULL) {
					// automatically send authorization allowed to agent/transport
					JabberSend(proto, "<presence to='%s' type='subscribed'/>", from);
				}
				else if ((nick=JabberNickFromJID(from)) != NULL) {
					JabberLog(proto, "%s (%s) requests authorization", nick, from);
					JabberDBAddAuthRequest(proto, from, nick);
					mir_free(nick);
				}
			}
			else if (!strcmp(type, "subscribed")) {
				if ((item=JabberListGetItemPtr(proto, LIST_ROSTER, from)) != NULL) {
					if (item->subscription == SUB_FROM) item->subscription = SUB_BOTH;
					else if (item->subscription == SUB_NONE) {
						item->subscription = SUB_TO;
					}
				}
			}
		}
	}
}
void JabberGroupchatProcessPresence( XmlNode *node, void *userdata )
{
	ThreadData* info;
	XmlNode *showNode, *statusNode, *errorNode, *itemNode, *n;
	TCHAR* from;
	int status, newRes;
	int i;
	BOOL roomCreated;

	if ( !node || !node->name || strcmp( node->name, "presence" )) return;
	if (( info=( ThreadData* ) userdata ) == NULL ) return;
	if (( from=JabberXmlGetAttrValue( node, "from" )) == NULL ) return;

	TCHAR* nick = _tcschr( from, '/' );
	if ( nick == NULL || nick[1] == '\0' )
		return;
	nick++;

	JABBER_LIST_ITEM* item = JabberListGetItemPtr( LIST_CHATROOM, from );
	if ( item == NULL )
		return;

	XmlNode* xNode = JabberXmlGetChildWithGivenAttrValue( node, "x", "xmlns", _T("http://jabber.org/protocol/muc#user"));

	TCHAR* type = JabberXmlGetAttrValue( node, "type" );
	if ( type == NULL || !_tcscmp( type, _T("available"))) {
		TCHAR* room = JabberNickFromJID( from );
		if ( room == NULL )
			return;

		JabberGcLogCreate( item );

		// Update status of room participant
		status = ID_STATUS_ONLINE;
		if (( showNode=JabberXmlGetChild( node, "show" )) != NULL ) {
			if ( showNode->text != NULL ) {
				if ( !_tcscmp( showNode->text , _T("away"))) status = ID_STATUS_AWAY;
				else if ( !_tcscmp( showNode->text , _T("xa"))) status = ID_STATUS_NA;
				else if ( !_tcscmp( showNode->text , _T("dnd"))) status = ID_STATUS_DND;
				else if ( !_tcscmp( showNode->text , _T("chat"))) status = ID_STATUS_FREECHAT;
		}	}

		TCHAR* str;
		if (( statusNode=JabberXmlGetChild( node, "status" ))!=NULL && statusNode->text!=NULL )
			str = statusNode->text;
		else
			str = NULL;
		newRes = ( JabberListAddResource( LIST_CHATROOM, from, status, str ) == 0 ) ? 0 : GC_EVENT_JOIN;

		roomCreated = FALSE;

		// Check additional MUC info for this user
		if ( xNode != NULL ) {
			if (( itemNode=JabberXmlGetChild( xNode, "item" )) != NULL ) {
				JABBER_RESOURCE_STATUS* r = item->resource;
				for ( i=0; i<item->resourceCount && _tcscmp( r->resourceName, nick ); i++, r++ );
				if ( i < item->resourceCount ) {
					if (( str=JabberXmlGetAttrValue( itemNode, "affiliation" )) != NULL ) {
						if ( !_tcscmp( str, _T("owner")))        r->affiliation = AFFILIATION_OWNER;
						else if ( !_tcscmp( str, _T("admin")))   r->affiliation = AFFILIATION_ADMIN;
						else if ( !_tcscmp( str, _T("member")))  r->affiliation = AFFILIATION_MEMBER;
						else if ( !_tcscmp( str, _T("outcast"))) r->affiliation = AFFILIATION_OUTCAST;
					}
					if (( str=JabberXmlGetAttrValue( itemNode, "role" )) != NULL ) {
						JABBER_GC_ROLE newRole = r->role;

						if ( !_tcscmp( str, _T("moderator")))        newRole = ROLE_MODERATOR;
						else if ( !_tcscmp( str, _T("participant"))) newRole = ROLE_PARTICIPANT;
						else if ( !_tcscmp( str, _T("visitor")))     newRole = ROLE_VISITOR;
						else                                         newRole = ROLE_NONE;

						if ( newRole != r->role && r->role != ROLE_NONE ) {
							JabberGcLogUpdateMemberStatus( item, nick, NULL, GC_EVENT_REMOVESTATUS, NULL );
							newRes = GC_EVENT_ADDSTATUS;
						}
						r->role = newRole;
					}
					str = JabberXmlGetAttrValue( itemNode, "jid" );
			}	}

			if ( sttGetStatusCode( xNode ) == 201 )
				roomCreated = TRUE;
		}

		// Update groupchat log window
		JabberGcLogUpdateMemberStatus( item, nick, str, newRes, NULL );

		HANDLE hContact = JabberHContactFromJID( from );
		if ( hContact != NULL )
			JSetWord( hContact, "Status", status );

		// Update room status
		//if ( item->status != ID_STATUS_ONLINE ) {
		//	item->status = ID_STATUS_ONLINE;
		//	JSetWord( hContact, "Status", ( WORD )ID_STATUS_ONLINE );
		//	JabberLog( "Room %s online", from );
		//}

		// Check <created/>
		if ( roomCreated ||
			(( n=JabberXmlGetChild( node, "created" ))!=NULL &&
				( str=JabberXmlGetAttrValue( n, "xmlns" ))!=NULL &&
				!_tcscmp( str, _T("http://jabber.org/protocol/muc#owner"))) ) {
			// A new room just created by me
			// Request room config
			int iqId = JabberSerialNext();
			JabberIqAdd( iqId, IQ_PROC_NONE, JabberIqResultGetMuc );

			XmlNodeIq iq( "get", iqId, item->jid );
			XmlNode* query = iq.addQuery( xmlnsOwner );
			JabberSend( jabberThreadInfo->s, iq );
		}

		mir_free( room );
	}
	else if ( !lstrcmp( type, _T("unavailable"))) {
		TCHAR* str = 0;
		if ( xNode != NULL && item->nick != NULL ) {
			itemNode = JabberXmlGetChild( xNode, "item" );
			XmlNode* reasonNode = JabberXmlGetChild( itemNode, "reason" );
			str = JabberXmlGetAttrValue( itemNode, "jid" );
			if ( !lstrcmp( nick, item->nick )) {
				int iStatus = sttGetStatusCode( xNode );
				switch( iStatus ) {
				case 301:	case 307:
					JabberGcQuit( item, iStatus, reasonNode );
					break;

				case 303:
					sttRenameParticipantNick( item, nick, itemNode );
					return;
			}	}
			else {
				switch( sttGetStatusCode( xNode )) {
				case 303:
					sttRenameParticipantNick( item, nick, itemNode );
					return;

				case 301:
				case 307:
					JabberListRemoveResource( LIST_CHATROOM, from );
					JabberGcLogUpdateMemberStatus( item, nick, str, GC_EVENT_KICK, reasonNode );
					return;
		}	}	}

		JabberListRemoveResource( LIST_CHATROOM, from );
		JabberGcLogUpdateMemberStatus( item, nick, str, GC_EVENT_PART, NULL );

		HANDLE hContact = JabberHContactFromJID( from );
		if ( hContact != NULL )
			JSetWord( hContact, "Status", ID_STATUS_OFFLINE );
	}
	else if ( !lstrcmp( type, _T("error"))) {
		errorNode = JabberXmlGetChild( node, "error" );
		TCHAR* str = JabberErrorMsg( errorNode );
		MessagePopup( NULL, str, TranslateT( "Jabber Error Message" ), MB_OK|MB_SETFOREGROUND );
		//JabberListRemoveResource( LIST_CHATROOM, from );
		JabberListRemove( LIST_CHATROOM, from );
		mir_free( str );
}	}