コード例 #1
0
ファイル: proto.cpp プロジェクト: MrtsComputers/miranda-ng
HANDLE CYahooProto::AddToList( int flags, PROTOSEARCHRESULT* psr )
{
	debugLogA("[YahooAddToList] Flags: %d", flags);

	if (!m_bLoggedIn) {
		debugLogA("[YahooAddToList] WARNING: WE ARE OFFLINE!");
		return 0;
	}

	if (psr == NULL || psr->cbSize != sizeof( PROTOSEARCHRESULT )) {
		debugLogA("[YahooAddToList] Empty data passed?");
		return 0;
	}

	char *id = psr->flags & PSR_UNICODE ? mir_utf8encodeW((wchar_t*)psr->id) : mir_utf8encode((char*)psr->id);
	HANDLE hContact = getbuddyH(id);
	if (hContact != NULL) {
		if (db_get_b(hContact, "CList", "NotOnList", 0)) {
			debugLogA("[YahooAddToList] Temporary Buddy:%s already on our buddy list", id);
			//return 0;
		} else {
			debugLogA("[YahooAddToList] Buddy:%s already on our buddy list", id);
			mir_free(id);
			return 0;
		}
	} else if (flags & PALF_TEMPORARY) { /* not on our list */
		debugLogA("[YahooAddToList] Adding Temporary Buddy:%s ", id);
	}

	int protocol = psr->reserved[0];
	debugLogA("Adding buddy:%s", id);
	hContact = add_buddy(id, id, protocol, flags);
	mir_free(id);
	return hContact;
}
コード例 #2
0
void CYahooProto::request_avatar(const char* who)
{
	if (!getByte("ShowAvatars", 1)) {
		LOG(("Avatars disabled, but available for: %s", who));
		return;
	}

	MCONTACT hContact = getbuddyH(who);

	if (!hContact)
		return;

	time_t cur_time;
	time(&cur_time);
	time_t last_chk = getDword(hContact, "PictLastCheck", 0);

	/*
	* time() - in seconds ( 60*60 = 1 hour)
	*/
	if (getDword(hContact, "PictCK", 0) == 0 || last_chk == 0 || (cur_time - last_chk) > 60) {
		setDword(hContact, "PictLastCheck", (DWORD)cur_time);
		LOG(("Requesting Avatar for: %s", who));
		yahoo_request_buddy_avatar(m_id, who);
	}
	else LOG(("Avatar Not Available for: %s Last Check: %ld Current: %ld (Flood Check in Effect)", who, last_chk, cur_time));
}
コード例 #3
0
void CYahooProto::ext_got_picture_checksum(const char *me, const char *who, int cksum)
{
	LOG(("ext_yahoo_got_picture_checksum for %s checksum: %d", who, cksum));

	MCONTACT hContact = getbuddyH(who);
	if (hContact == NULL) {
		LOG(("Buddy Not Found. Skipping avatar update"));
		return;
	}

	/* Last thing check the checksum and request new one if we need to */
	if (!cksum || cksum == -1) {
		setDword(hContact, "PictCK", 0);
		reset_avatar(hContact);
	}
	else {
		if (getDword(hContact, "PictCK", 0) != cksum) {
			// Now save the new checksum. No rush requesting new avatar yet.
			setDword(hContact, "PictCK", cksum);

			// Need to delete the Avatar File!!
			TCHAR szFile[MAX_PATH];
			GetAvatarFileName(hContact, szFile, _countof(szFile) - 1, 0);
			DeleteFile(szFile);

			// Reset the avatar and cleanup.
			reset_avatar(hContact);

			// Request new avatar here... (might also want to check the sharing status?)

			if (getByte("ShareAvatar", 0) == 2)
				request_avatar(who);
		}
	}
}
コード例 #4
0
void CYahooProto::ext_got_picture_update(const char *me, const char *who, int buddy_icon)
{
	LOG(("ext_got_picture_update for %s buddy_icon: %d", who, buddy_icon));

	MCONTACT hContact = getbuddyH(who);
	if (hContact == NULL) {
		LOG(("Buddy Not Found. Skipping avatar update"));
		return;
	}

	setByte(hContact, "AvatarType", buddy_icon);

	/* Last thing check the checksum and request new one if we need to */
	reset_avatar(hContact);
}
コード例 #5
0
ファイル: chat.cpp プロジェクト: ybznek/miranda-ng
void CYahooProto::ChatEvent(const char* room, const char* who, int evt, const TCHAR* msg)
{
	TCHAR* idt = mir_a2t(room);
	TCHAR* snt = mir_a2t(who);

	MCONTACT hContact = getbuddyH(who);
	TCHAR* nick = hContact ? (TCHAR*)pcli->pfnGetContactDisplayName(WPARAM(hContact), 0) : snt;

	GCDEST gcd = { m_szModuleName, idt, evt };
	GCEVENT gce = { sizeof(gce), &gcd };
	gce.dwFlags = GCEF_ADDTOLOG;
	gce.ptszNick = nick;
	gce.ptszUID = snt;
	gce.bIsMe = _stricmp(who, m_yahoo_id) == 0;
	gce.ptszStatus = gce.bIsMe ? TranslateT("Me") : TranslateT("Others");
	gce.ptszText = msg;
	gce.time = time(NULL);
	CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);

	mir_free(snt);
	mir_free(idt);
}
コード例 #6
0
ファイル: chat.cpp プロジェクト: ybznek/miranda-ng
int __cdecl CYahooProto::OnGCEventHook(WPARAM, LPARAM lParam)
{
	GCHOOK *gch = (GCHOOK*)lParam;
	if (!gch) return 1;

	if (mir_strcmp(gch->pDest->pszModule, m_szModuleName)) return 0;

	char *room = mir_t2a(gch->pDest->ptszID);
	char *who = mir_t2a(gch->ptszUID);

	switch (gch->pDest->iType) {
	case GC_SESSION_TERMINATE:
		{
			ChatRoom *cm = m_chatrooms.find((ChatRoom*)&room);
			if (cm) {
				yahoo_conference_logoff(m_id, NULL, cm->members, room);
				m_chatrooms.remove((ChatRoom*)&room);
			}
		}
		break;

	case GC_USER_MESSAGE:
		if (gch->ptszText && gch->ptszText[0]) {
			ChatRoom *cm = m_chatrooms.find((ChatRoom*)&room);
			if (cm)
				yahoo_conference_message(m_id, NULL, cm->members, room, T2Utf(gch->ptszText), 1);
		}
		break;

	case GC_USER_CHANMGR:
		DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CHATROOM_INVITE), NULL, InviteToChatDialog,
			LPARAM(new InviteChatParam(room, this)));
		break;

	case GC_USER_PRIVMESS:
		CallService(MS_MSG_SENDMESSAGE, (WPARAM)getbuddyH(who));
		break;

	case GC_USER_LOGMENU:
		switch (gch->dwData) {
		case 10:
			DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_CHATROOM_INVITE), NULL, InviteToChatDialog,
				LPARAM(new InviteChatParam(room, this)));
			break;

		case 20:
			ChatLeave(room);
			break;
		}
		break;

	case GC_USER_NICKLISTMENU:
		switch (gch->dwData) {
		case 10:
			CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)getbuddyH(who));
			break;

		case 20:
			CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)getbuddyH(who));
			break;

		case 110:
			ChatLeave(room);
			break;
		}
		break;

	case GC_USER_TYPNOTIFY:
		break;
	}
	mir_free(who);
	mir_free(room);

	return 0;
}
コード例 #7
0
ファイル: im.cpp プロジェクト: MrtsComputers/miranda-ng
void CYahooProto::ext_got_im(const char *me, const char *who, int protocol, const char *msg, 
								long tm, int stat, int utf8, int buddy_icon, 
								const char *seqn, int sendn)
{
	char 		*umsg;
	const char	*c = msg;
	int 		oidx = 0;

	LOG(("YAHOO_GOT_IM id:%s %s: %s (len: %d) tm:%lu stat:%i utf8:%i buddy_icon: %i", me, who, msg, lstrlenA(msg), tm, stat, utf8, buddy_icon));

	if (stat == 2) {
		char z[1024];

		mir_snprintf(z, SIZEOF(z), "Error sending message to %s", who);
		LOG((z));
		ShowError( TranslateT("Yahoo Error"), _A2T(z));
		return;
	}

	if (!msg) {
		LOG(("Empty Incoming Message, exiting."));
		return;
	}

	if (getByte("IgnoreUnknown", 0)) {

		/*
		* Check our buddy list to see if we have it there. And if it's not on the list then we don't accept any IMs.
		*/
		if (getbuddyH(who) == NULL) {
			LOG(("Ignoring unknown user messages. User '%s'. Dropping Message.", who));
			return;
		}
	}

	if ( BuddyIgnored( who )) {
		LOG(("User '%s' on our Ignore List. Dropping Message.", who));
		return;
	}

	// make a bigger buffer for \n -> \r\n conversion (x2)
	umsg = (char *) alloca(lstrlenA(msg) * 2 + 1); 

	while ( *c != '\0') {
		// Strip the font tag
		if (!_strnicmp(c,"<font ",6) || !_strnicmp(c,"</font>",6) ||
			// strip the fade tag
			!_strnicmp(c, "<FADE ",6) || !_strnicmp(c,"</FADE>",7) ||
			// strip the alternate colors tag
			!_strnicmp(c, "<ALT ",5) || !_strnicmp(c, "</ALT>",6)) { 
				while ((*c++ != '>') && (*c != '\0')); 
		} else
			// strip ANSI color combination
			if ((*c == 0x1b) && (*(c+1) == '[')) { 
				while ((*c++ != 'm') && (*c != '\0')); 
			} else

				if (*c != '\0') {
					umsg[oidx++] = *c;

					/* Adding \r to \r\n conversion */
					if (*c == '\r' && *(c + 1) != '\n') 
						umsg[oidx++] = '\n';

					c++;
				}
	}

	umsg[oidx++]= '\0';

	/* Need to strip off formatting stuff first. Then do all decoding/converting */
	LOG(("%s: %s", who, umsg));

	HANDLE hContact = add_buddy(who, who, protocol, PALF_TEMPORARY);
	//setWord(hContact, "yprotoid", protocol);
	Set_Protocol(hContact, protocol);

	PROTORECVEVENT pre = { 0 };
	pre.flags = (utf8) ? PREF_UTF : 0;

	if (tm) {
		HANDLE hEvent = db_event_last(hContact);

		if (hEvent) { // contact has events
			DWORD dummy;
			DBEVENTINFO dbei = { sizeof (dbei) };
			dbei.pBlob = (BYTE*)&dummy;
			dbei.cbBlob = 2;
			if (!db_event_get(hEvent, &dbei)) 
				// got that event, if newer than ts then reset to current time
				if ((DWORD)tm < dbei.timestamp) tm = (long)time(NULL);
		}

		pre.timestamp = (DWORD)time(NULL);
		
		if ((DWORD)tm < pre.timestamp)
			pre.timestamp = tm;
		
	}
	else pre.timestamp = (DWORD)time(NULL);

	pre.szMessage = umsg;
	pre.lParam = 0;

	// Turn off typing
	CallService(MS_PROTO_CONTACTISTYPING, (WPARAM) hContact, PROTOTYPE_CONTACTTYPING_OFF);
	ProtoChainRecvMsg(hContact, &pre);

	// ack the message we just got
	if (seqn)
		yahoo_send_im_ack(m_id, me, who, seqn, sendn);

	if (buddy_icon < 0) return;

	//?? Don't generate floods!!
	setByte(hContact, "AvatarType", (BYTE)buddy_icon);
	if (buddy_icon != 2)
		reset_avatar(hContact);
	else if (getDword(hContact, "PictCK", 0) == 0) /* request the buddy image */
		request_avatar(who); 
}
コード例 #8
0
void CYahooProto::ext_got_picture(const char *me, const char *who, const char *pic_url, int cksum, int type)
{
	MCONTACT hContact = 0;

	LOG(("[ext_yahoo_got_picture] for %s with url %s (checksum: %d) type: %d", who, pic_url, cksum, type));

	/*
	  Type:

	  1 - Send Avatar Info
	  2 - Got Avatar Info
	  3 - YIM6 didn't like my avatar? Expired? We need to invalidate and re-load
	  */
	switch (type) {
	case 1:
		{
			int cksum = 0;
			DBVARIANT dbv;

			/* need to send avatar info */
			if (!getByte("ShowAvatars", 1)) {
				LOG(("[ext_yahoo_got_picture] We are not using/showing avatars!"));
				yahoo_send_picture_update(m_id, who, 0); // no avatar (disabled)
				return;
			}

			LOG(("[ext_yahoo_got_picture] Getting ready to send info!"));
			/* need to read CheckSum */
			cksum = getDword("AvatarHash", 0);
			if (cksum) {
				if (!getString("AvatarURL", &dbv)) {
					LOG(("[ext_yahoo_got_picture] Sending url: %s checksum: %d to '%s'!", dbv.pszVal, cksum, who));
					//void yahoo_send_picture_info(int id, const char *me, const char *who, const char *pic_url, int cksum)
					yahoo_send_picture_info(m_id, who, 2, dbv.pszVal, cksum);
					db_free(&dbv);
					break;
				}
				else
					LOG(("No AvatarURL???"));

				/*
				 * Try to re-upload the avatar
				 */
				if (getByte("AvatarUL", 0) != 1) {
					// NO avatar URL??
					if (!getTString("AvatarFile", &dbv)) {
						struct _stat statbuf;

						if (_tstat(dbv.ptszVal, &statbuf) != 0) {
							LOG(("[ext_yahoo_got_picture] Avatar File Missing? Can't find file: %s", dbv.ptszVal));
						}
						else {
							setString("AvatarInv", who);
							SendAvatar(dbv.ptszVal);
						}

						db_free(&dbv);
					}
					else {
						LOG(("[ext_yahoo_got_picture] No Local Avatar File??? "));
					}
				}
				else
					LOG(("[ext_yahoo_got_picture] Another avatar upload in progress?"));
			}
		}
		break;
	case 2: /*
			  * We got Avatar Info for our buddy.
			  */
		if (!getByte("ShowAvatars", 1)) {
			LOG(("[ext_yahoo_got_picture] We are not using/showing avatars!"));
			return;
		}

		/* got avatar info, so set miranda up */
		hContact = getbuddyH(who);
		if (!hContact) {
			LOG(("[ext_yahoo_got_picture] Buddy not on my buddy list?."));
			return;
		}

		if (!cksum && pic_url) {
			const char *chk = strstr(pic_url, "chksum=");
			if (chk)
				cksum = strtol(chk + 7, NULL, 10);
		}

		if (!cksum || cksum == -1) {
			LOG(("[ext_yahoo_got_picture] Resetting avatar."));
			setDword(hContact, "PictCK", 0);
			reset_avatar(hContact);
		}
		else {
			if (pic_url == NULL) {
				LOG(("[ext_yahoo_got_picture] WARNING: Empty URL for avatar?"));
				return;
			}

			TCHAR z[1024];
			GetAvatarFileName(hContact, z, 1024, getByte(hContact, "AvatarType", 0));

			if (getDword(hContact, "PictCK", 0) != cksum || _taccess(z, 0) != 0) {

				debugLogA("[ext_yahoo_got_picture] Checksums don't match or avatar file is missing. Current: %d, New: %d",
					getDword(hContact, "PictCK", 0), cksum);

				struct avatar_info *avt = (avatar_info*)malloc(sizeof(struct avatar_info));
				avt->who = strdup(who);
				avt->pic_url = strdup(pic_url);
				avt->cksum = cksum;

				ForkThread(&CYahooProto::recv_avatarthread, avt);
			}
		}

		break;
	case 3:
		// Our Avatar is not good anymore? Need to re-upload??
		/* who, pic_url, cksum */
		{
			int mcksum = 0;
			DBVARIANT dbv;

			/* need to send avatar info */
			if (!getByte("ShowAvatars", 1)) {
				LOG(("[ext_yahoo_got_picture] We are not using/showing avatars!"));
				yahoo_send_picture_update(m_id, who, 0); // no avatar (disabled)
				return;
			}

			LOG(("[ext_yahoo_got_picture] Getting ready to send info!"));
			/* need to read CheckSum */
			mcksum = getDword("AvatarHash", 0);
			if (mcksum == 0) {
				/* this should NEVER Happen??? */
				LOG(("[ext_yahoo_got_picture] No personal checksum? and Invalidate?!"));
				yahoo_send_picture_update(m_id, who, 0); // no avatar (disabled)
				return;
			}

			LOG(("[ext_yahoo_got_picture] My Checksum: %d", mcksum));

			if (!getString("AvatarURL", &dbv)) {
				if (mir_strcmpi(pic_url, dbv.pszVal) == 0) {
					DBVARIANT dbv2;
					/*time_t  ts;
					DWORD	ae;*/

					if (mcksum != cksum)
						LOG(("[ext_yahoo_got_picture] WARNING: Checksums don't match!"));

					/*time(&ts);
					ae = getDword("AvatarExpires", 0);

					if (ae != 0 && ae > (ts - 300)) {
					LOG(("[ext_yahoo_got_picture] Current Time: %lu Expires: %lu ", ts, ae));
					LOG(("[ext_yahoo_got_picture] We just reuploaded! Stop screwing with Yahoo FT. "));

					// don't leak stuff
					db_free(&dbv);

					break;
					}*/

					LOG(("[ext_yahoo_got_picture] Buddy: %s told us this is bad??Expired??. Re-uploading", who));
					delSetting("AvatarURL");

					if (!getTString("AvatarFile", &dbv2)) {
						setString("AvatarInv", who);
						SendAvatar(dbv2.ptszVal);
						db_free(&dbv2);
					}
					else {
						LOG(("[ext_yahoo_got_picture] No Local Avatar File??? "));
					}
				}
				else {
					LOG(("[ext_yahoo_got_picture] URL doesn't match? Tell them the right thing!!!"));
					yahoo_send_picture_info(m_id, who, 2, dbv.pszVal, mcksum);
				}
				// don't leak stuff
				db_free(&dbv);
			}
			else {
				LOG(("[ext_yahoo_got_picture] no AvatarURL?"));
			}
		}
		break;
	default:
		LOG(("[ext_yahoo_got_picture] Unknown request/packet type exiting!"));
	}

	LOG(("ext_yahoo_got_picture exiting"));
}
コード例 #9
0
void __cdecl CYahooProto::recv_avatarthread(void *pavt)
{
	struct avatar_info *avt = (avatar_info*)pavt;
	int 	error = 0;
	TCHAR  buf[4096];

	if (avt == NULL) {
		debugLogA("AVT IS NULL!!!");
		return;
	}

	if (!m_bLoggedIn) {
		debugLogA("We are not logged in!!!");
		return;
	}

	//    ProtoBroadcastAck(hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, 0);

	LOG(("yahoo_recv_avatarthread who:%s url:%s checksum: %d", avt->who, avt->pic_url, avt->cksum));

	MCONTACT hContact = getbuddyH(avt->who);

	if (!hContact) {
		LOG(("ERROR: Can't find buddy: %s", avt->who));
		error = 1;
	}
	else if (!error) {
		setDword(hContact, "PictCK", avt->cksum);
		setDword(hContact, "PictLoading", 1);
	}

	if (!error) {

		NETLIBHTTPREQUEST nlhr = { 0 }, *nlhrReply;

		nlhr.cbSize = sizeof(nlhr);
		nlhr.requestType = REQUEST_GET;
		nlhr.flags = NLHRF_NODUMP | NLHRF_GENERATEHOST | NLHRF_SMARTAUTHHEADER;
		nlhr.szUrl = avt->pic_url;

		nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)&nlhr);

		if (nlhrReply) {

			if (nlhrReply->resultCode != 200) {
				LOG(("Update server returned '%d' instead of 200. It also sent the following: %s", nlhrReply->resultCode, nlhrReply->szResultDescr));
				// make sure it's a real problem and not a problem w/ our connection
				yahoo_send_picture_info(m_id, avt->who, 3, avt->pic_url, avt->cksum);
				error = 1;
			}
			else if (nlhrReply->dataLength < 1 || nlhrReply->pData == NULL) {
				LOG(("No data??? Got %d bytes.", nlhrReply->dataLength));
				error = 1;
			}
			else {
				GetAvatarFileName(hContact, buf, 1024, getByte(hContact, "AvatarType", 0));
				DeleteFile(buf);

				LOG(("Saving file: %s size: %u", buf, nlhrReply->dataLength));
				HANDLE myhFile = CreateFile(buf,
					GENERIC_WRITE,
					FILE_SHARE_WRITE,
					NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

				if (myhFile != INVALID_HANDLE_VALUE) {
					DWORD c;

					WriteFile(myhFile, nlhrReply->pData, nlhrReply->dataLength, &c, NULL);
					CloseHandle(myhFile);

					setDword(hContact, "PictLastCheck", 0);
				}
				else {
					LOG(("Can not open file for writing: %s", buf));
					error = 1;
				}
			}
			CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply);
		}
	}

	if (getDword(hContact, "PictCK", 0) != avt->cksum) {
		LOG(("WARNING: Checksum updated during download?!"));
		error = 1; /* don't use this one? */
	}

	setDword(hContact, "PictLoading", 0);
	LOG(("File download complete!?"));

	if (error)
		buf[0] = '\0';

	free(avt->who);
	free(avt->pic_url);
	free(avt);

	PROTO_AVATAR_INFORMATION ai;
	ai.format = PA_FORMAT_PNG;
	ai.hContact = hContact;
	_tcsncpy_s(ai.filename, buf, _TRUNCATE);

	if (error)
		setDword(hContact, "PictCK", 0);

	ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, !error ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, (HANDLE)&ai, 0);
}
コード例 #10
0
ファイル: test.cpp プロジェクト: Seldom/miranda-ng
static int ServiceParseYmsgrLink(WPARAM wParam, LPARAM lParam)
{
	char *arg = (char*)lParam;
	UNREFERENCED_PARAMETER(wParam);
	if (arg == NULL) return 1; /* sanity check */
  /*
	  add user:       ymsgr:addfriend?ID
	  send message:   ymsgr:sendim?ID&m=MESSAGE
	  add chatroom:   ymsgr:chat?ROOM
  */
  /* skip leading prefix */
	arg = strchr(arg, ':');
	if (arg == NULL) return 1; /* parse failed */
	for (++arg; *arg == '/'; ++arg);
	/* add a contact to the list */
	if (!_strnicmp(arg, "addfriend?", 10)) {
		char *tok, *id = NULL;
		ADDCONTACTSTRUCT acs;
		PROTOSEARCHRESULT psr;
		if (*(arg += 10) == 0) return 1; /* parse failed */
		tok = strtok(arg, "&"); /* first token */
		if (tok != NULL) id = Netlib_UrlDecode(tok);
		if (id == NULL || *id == 0) return 1; /* parse failed */
		if (getbuddyH(id) == NULL) { /* does not yet check if id is current user */
			acs.handleType = HANDLE_SEARCHRESULT;
			acs.szProto = yahooProtocolName;
			acs.psr = &psr;
			memset(&psr, 0, sizeof(PROTOSEARCHRESULT));
			psr.cbSize = sizeof(PROTOSEARCHRESULT);
			psr.nick.t = id;
			CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs);
		}
		return 0;
	}
	/* send a message to a contact */
	else if (!_strnicmp(arg, "sendim?", 7)) {
		char *tok, *id = NULL, *msg = NULL;
		MCONTACT hContact;
		if (*(arg += 7) == 0) return 1; /* parse failed */
		tok = strtok(arg, "&"); /* first token */
		if (tok != NULL) id = tok;
		while (tok != NULL) {
			if (!_strnicmp(tok, "m=", 2) && *(tok + 2) != 0)
				msg = Netlib_UrlDecode(tok + 2);
			tok = strtok(NULL, "&"); /* next token */
		}
		if (id == NULL || *id == 0) return 1; /* parse failed */
		if (ServiceExists(MS_MSG_SENDMESSAGE)) { /* does not yet check if sn is current user */
			hContact = add_buddy(id, id, PALF_TEMPORARY); /* ensure contact is on list */
			if (hContact != NULL)
				CallService(MS_MSG_SENDMESSAGE, hContact, (LPARAM)msg);
		}
		return 0;
	}
	/* open a chatroom */
	else if (!_strnicmp(arg, "chat?", 5)) {
		char *tok, *rm = NULL;
		if (*(arg += 5) == 0) return 1; /* parse failed */
		tok = strtok(arg, "&"); /* first token */
		if (tok != NULL) rm = Netlib_UrlDecode(tok);
		if (rm == NULL) return 1; /* parse failed */
		/* not yet implemented (rm contains name of chatroom)*/
		return 0;
	}
	return 1; /* parse failed */
}