Mercurial > pidgin
diff src/protocols/icq/udphandle.c @ 2086:424a40f12a6c
[gaim-migrate @ 2096]
moving protocols from plugins/ to src/protocols. making it so that you can select which protocols are compiled statically.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Tue, 31 Jul 2001 01:00:39 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/icq/udphandle.c Tue Jul 31 01:00:39 2001 +0000 @@ -0,0 +1,814 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* + * $Id: udphandle.c 2096 2001-07-31 01:00:39Z warmenhoven $ + * + * Copyright (C) 1998-2001, Denis V. Dmitrienko <denis@null.net> and + * Bill Soudan <soudan@kde.org> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <stdlib.h> + +#include "icqlib.h" +#include "udp.h" +#include "queue.h" +#include "icqbyteorder.h" +#include "contacts.h" + +void icq_DoMsg(icq_Link *icqlink, DWORD type, WORD len, char *data, DWORD uin, BYTE hour, + BYTE minute, BYTE day, BYTE month, WORD year) +{ + icq_List *strList; + int fieldCount; + int i, k, nr; + const char **contact_uin; + const char **contact_nick; + (void)len; + + strList = icq_ListNew(); + switch(type) + { + case TYPE_ADDED: + /* Format: Nick, 0xFE, FName, 0xFE, LName, 0xFE, EMail */ + fieldCount = icq_SplitFields(strList, data); + if(fieldCount != 4 && fieldCount != 5) + { + icq_FmtLog(icqlink, ICQ_LOG_ERROR, "Bad TYPE_ADDED packet (expected 4/5 args, received %i)!\n", + fieldCount); + return; + } + icq_RusConv("wk", icq_ListAt(strList, 0)); /* Nick */ + icq_RusConv("wk", icq_ListAt(strList, 1)); /* FName */ + icq_RusConv("wk", icq_ListAt(strList, 2)); /* LName */ + icq_RusConv("wk", icq_ListAt(strList, 3)); /* EMail */ + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "%lu has added you to their contact list, " + "Nick: %s, First Name: %s, Last Name: %s, EMail: %s\n", + uin, icq_ListAt(strList, 0), icq_ListAt(strList, 1), + icq_ListAt(strList, 2), icq_ListAt(strList, 3)); + invoke_callback(icqlink,icq_RecvAdded)(icqlink, uin, hour, minute, day, month, year, + icq_ListAt(strList, 0), icq_ListAt(strList, 1), + icq_ListAt(strList, 2), icq_ListAt(strList, 3)); + break; + case TYPE_AUTH_REQ: + /* Format: Nick, 0xFE, FName, 0xFE, LName, 0xFE, EMail, 0xFE, 0, 0xFE, Reason */ + fieldCount = icq_SplitFields(strList, data); + if(fieldCount != 6) + { + icq_FmtLog(icqlink, ICQ_LOG_ERROR, "Bad TYPE_AUTH_REQ packet (expected 6 args, received %i)!\n", + fieldCount); + return; + } + icq_RusConv("wk", icq_ListAt(strList, 0)); /* Nick */ + icq_RusConv("wk", icq_ListAt(strList, 1)); /* FName */ + icq_RusConv("wk", icq_ListAt(strList, 2)); /* LName */ + icq_RusConv("wk", icq_ListAt(strList, 3)); /* EMail */ + icq_RusConv("wk", icq_ListAt(strList, 5)); /* Reason */ + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "%lu has requested your authorization to be added to " + "their contact list, Nick: %s, First Name: %s, Last Name: %s, " + "EMail: %s, Reason: %s\n", uin, icq_ListAt(strList, 0), icq_ListAt(strList, 1), + icq_ListAt(strList, 2), icq_ListAt(strList, 3), icq_ListAt(strList, 4)); + invoke_callback(icqlink,icq_RecvAuthReq)(icqlink, uin, hour, minute, day, month, year, + icq_ListAt(strList, 0), icq_ListAt(strList, 1), + icq_ListAt(strList, 2), icq_ListAt(strList, 3), + icq_ListAt(strList, 5)); + break; + case TYPE_URL: + /* Format: Description, 0xFE, URL */ + fieldCount = icq_SplitFields(strList, data); + if(fieldCount != 2) + { + icq_FmtLog(icqlink, ICQ_LOG_ERROR, "Bad TYPE_URL packet (expected 2 args, recived %i)!\n", + fieldCount); + return; + } + icq_RusConv("wk", icq_ListAt(strList, 0)); /* Description */ + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "URL received from %lu, URL: %s, Description: %s\n", + uin, icq_ListAt(strList, 1), icq_ListAt(strList, 0)); + invoke_callback(icqlink,icq_RecvURL)(icqlink, uin, hour, minute, day, month, year, + icq_ListAt(strList, 1), icq_ListAt(strList, 0)); + break; + case TYPE_WEBPAGER: + /* Format: Nick, 0xFE, Empty-FName, 0xFE, Empty-LName, 0xFE, EMail, 0xFE, + * Reason(3), 0xFE, Message with IP & Subject */ + fieldCount = icq_SplitFields(strList, data); + if(fieldCount != 6) + { + icq_FmtLog(icqlink, ICQ_LOG_ERROR, "Bad TYPE_WEBPAGER packet (expected 6 args, received %i)!\n", + fieldCount); + return; + } + icq_RusConv("wk", icq_ListAt(strList, 0)); /* Nick */ + icq_RusConv("wk", icq_ListAt(strList, 5)); /* Message */ + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "WebPager message received, Nick: %s, EMail: %s, " + "Message:\n%s\n", icq_ListAt(strList, 0), icq_ListAt(strList, 3), + icq_ListAt(strList, 5)); + invoke_callback(icqlink,icq_RecvWebPager)(icqlink, hour, minute, day, month, year, + icq_ListAt(strList, 0), icq_ListAt(strList, 3), + icq_ListAt(strList, 5)); + break; + case TYPE_EXPRESS: + /* Format: Nick, 0xFE, Empty-FName, 0xFE, Empty-LName, 0xFE, EMail, 0xFE, + * Reason(3), 0xFE, Message Subject */ + fieldCount = icq_SplitFields(strList, data); + if(fieldCount != 6) + { + icq_FmtLog(icqlink, ICQ_LOG_ERROR, "Bad TYPE_EXPRESS packet (expected 6 args, received %i)!\n", + fieldCount); + return; + } + icq_RusConv("wk", icq_ListAt(strList, 0)); /* Nick */ + icq_RusConv("wk", icq_ListAt(strList, 5)); /* Message */ + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "MailExpress message received, Nick: %s, EMail: %s, " + "Message:\n%s\n", icq_ListAt(strList, 0), icq_ListAt(strList, 3), + icq_ListAt(strList, 5)); + invoke_callback(icqlink, icq_RecvMailExpress)(icqlink, hour, minute, day, month, year, + icq_ListAt(strList, 0), icq_ListAt(strList, 3), + icq_ListAt(strList, 5)); + break; + case TYPE_CONTACT: + /* Format: Number of contacts, 0xFE, UIN, 0xFE, Nick, 0xFE, ... */ + nr = icq_SplitFields(strList, data); + contact_uin = (const char**)malloc((nr - 1) / 2); + contact_nick = (const char**)malloc((nr - 1) / 2); + + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "Contact List received from %lu (%i):\n", uin, + atoi(icq_ListAt(strList, 0))); + + for(i = 1, k = 0; i < (nr - 1); k++) + { + contact_uin[k] = icq_ListAt(strList, i); + contact_nick[k] = icq_ListAt(strList, i + 1); + i += 2; + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "\t%s - %s\n", contact_uin[k], contact_nick[k]); + } + invoke_callback(icqlink, icq_RecvContactList)(icqlink, uin, hour, minute, day, month, year, + k, contact_uin, contact_nick); + free(contact_uin); + free(contact_nick); + break; + default: + icq_RusConv("wk", data); /* Entire message */ + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "Instant message type %i from %lu:\n%s\n", type, uin, data); + invoke_callback(icqlink, icq_RecvMessage)(icqlink, uin, hour, minute, day, month, year, data); + } + icq_ListDelete(strList, free); +} + +void icq_HandleInfoReply(icq_Link *icqlink, icq_Packet *p) +{ + char *ptr1, *ptr2, *ptr3, *ptr4; + DWORD uin; + icq_PacketGotoUDPInData(p, 0); + uin = icq_PacketRead32(p); + ptr1 = icq_PacketReadStringNew(p); + ptr2 = icq_PacketReadStringNew(p); + ptr3 = icq_PacketReadStringNew(p); + ptr4 = icq_PacketReadStringNew(p); + icq_RusConv("wk", ptr1); + icq_RusConv("wk", ptr2); + icq_RusConv("wk", ptr3); + icq_RusConv("wk", ptr4); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "Info reply for %lu\n", uin); + icq_UDPAck(icqlink, icq_PacketReadUDPInSeq1(p)); + invoke_callback(icqlink,icq_InfoReply)(icqlink, uin, ptr1, ptr2, ptr3, ptr4, icq_PacketRead8(p)); + free(ptr1); + free(ptr2); + free(ptr3); + free(ptr4); +} + +void icq_HandleExtInfoReply(icq_Link *icqlink, icq_Packet *p) +{ + char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5; + DWORD uin; + WORD cnt_code, age; + char cnt_stat, gender; + + icq_PacketGotoUDPInData(p, 0); + uin = icq_PacketRead32(p); + ptr1 = icq_PacketReadStringNew(p); + cnt_code = icq_PacketRead16(p); + cnt_stat = icq_PacketRead8(p); + ptr2 = icq_PacketReadStringNew(p); + age = icq_PacketRead16(p); + gender = icq_PacketRead8(p); + ptr3 = icq_PacketReadStringNew(p); + ptr4 = icq_PacketReadStringNew(p); + ptr5 = icq_PacketReadStringNew(p); + icq_RusConv("wk", ptr1); + icq_RusConv("wk", ptr2); + icq_RusConv("wk", ptr3); + icq_RusConv("wk", ptr4); + icq_RusConv("wk", ptr5); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "Extended info reply for %lu\n", uin); + icq_UDPAck(icqlink, icq_PacketReadUDPInSeq1(p)); + invoke_callback(icqlink,icq_ExtInfoReply)(icqlink, uin, (char*)ptr1, cnt_code, cnt_stat, (char*)ptr2, + age, gender, (char*)ptr3, (char*)ptr4, (char*)ptr5); + free(ptr1); + free(ptr2); + free(ptr3); + free(ptr4); + free(ptr5); +} + +void icq_HandleSearchReply(icq_Link *icqlink, icq_Packet *p) +{ + char *ptr1, *ptr2, *ptr3, *ptr4, auth; + DWORD uin; + icq_PacketGotoUDPInData(p, 0); + uin = icq_PacketRead32(p); + ptr1 = icq_PacketReadStringNew(p); + ptr2 = icq_PacketReadStringNew(p); + ptr3 = icq_PacketReadStringNew(p); + ptr4 = icq_PacketReadStringNew(p); + icq_RusConv("wk", ptr1); + icq_RusConv("wk", ptr2); + icq_RusConv("wk", ptr3); + icq_RusConv("wk", ptr4); + auth = icq_PacketRead8(p); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "User found %lu, Nick: %s, First Name: %s, Last Name: %s, " + "EMail: %s, Auth: %s\n", uin, ptr1, ptr2, ptr3, ptr4, auth==1?"no":"yes"); + icq_UDPAck(icqlink, icq_PacketReadUDPInSeq1(p)); + invoke_callback(icqlink,icq_UserFound)(icqlink, uin, (char*)ptr1, (char*)ptr2, + (char*)ptr3, (char*)ptr4, auth); + free(ptr1); + free(ptr2); + free(ptr3); + free(ptr4); +} + +/************************************************ +This is called when a user goes offline +*************************************************/ +void icq_HandleUserOffline(icq_Link *icqlink, icq_Packet *p) +{ + DWORD remote_uin; + icq_ContactItem *ptr; + + icq_PacketGotoUDPInData(p, 0); + remote_uin = icq_PacketRead32(p); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "User %lu logged off\n", remote_uin); + + ptr=icq_ContactFind(icqlink, remote_uin); + if(ptr) + { + ptr->remote_ip = 0; + ptr->remote_port = 0; + } + icq_UDPAck(icqlink, icq_PacketReadUDPInSeq1(p)); + invoke_callback(icqlink,icq_UserOffline)(icqlink, remote_uin); +} + +void icq_HandleUserOnline(icq_Link *icqlink, icq_Packet *p) +{ + DWORD remote_uin, new_status, remote_ip, remote_real_ip; + DWORD remote_port; /* Why Mirabilis used 4 bytes for port? */ + BYTE tcp_flag; + icq_ContactItem *ptr; + + icq_PacketGotoUDPInData(p, 0); + remote_uin = icq_PacketRead32(p); + remote_ip = ntohl(icq_PacketRead32n(p)); /* icqtohl() */ + remote_port = icqtohl(icq_PacketRead32n(p)); + remote_real_ip = ntohl(icq_PacketRead32n(p)); /* icqtohl() */ + tcp_flag = icq_PacketRead8(p); + new_status = icq_PacketRead32(p); + + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, + "User %lu (%s = 0x%X) logged on. tcp_flag=0x%X IP=%08X, real IP=%08X, port=%d\n", + remote_uin, icq_ConvertStatus2Str(new_status), new_status, tcp_flag, remote_ip, + remote_real_ip, remote_port); + + ptr=icq_ContactFind(icqlink, remote_uin); + if(ptr) + { + ptr->remote_ip=remote_ip; + ptr->remote_real_ip=remote_real_ip; + ptr->remote_port = remote_port; + ptr->tcp_flag = tcp_flag; + } + icq_UDPAck(icqlink, icq_PacketReadUDPInSeq1(p)); + invoke_callback(icqlink,icq_UserOnline)(icqlink, remote_uin, new_status, remote_ip, + remote_port, remote_real_ip, tcp_flag); +} + +void icq_HandleStatusChange(icq_Link *icqlink, icq_Packet *p) +{ + unsigned long remote_uin, new_status; + + icq_PacketGotoUDPInData(p, 0); + remote_uin = icq_PacketRead32(p); + new_status = icq_PacketRead32(p); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "%lu changed status to %s (0x%X)\n", remote_uin, + icq_ConvertStatus2Str(new_status), new_status); + icq_UDPAck(icqlink, icq_PacketReadUDPInSeq1(p)); + invoke_callback(icqlink,icq_UserStatusUpdate)(icqlink, remote_uin, new_status); +} + +void icq_HandleMetaUserInfo(icq_Link *icqlink, icq_Packet *p) +{ + unsigned short subcmd, country, seq2, age, occupation, wcountry; + char res, auth, timezone, webaware, hideip, gender; + char *nick, *first, *last, *email, *about, *city; + char *pri_eml, *sec_eml, *old_eml; + char *phone, *fax, *street, *cellular, *state; + char *wcity, *wstate, *wphone, *wfax, *waddress; + char *company, *department, *job, *whomepage; + char *homepage; + char byear, bmonth, bday, lang1, lang2, lang3, inum; + int i; + char anum, bnum, hnum; + unsigned long uin, zip, wzip; + char *empty = NULL; + char *interests[4] = {0, 0, 0, 0}; + unsigned short icategory[4] = {0, 0, 0, 0}; + char *affiliations[4] = {0, 0, 0, 0}; + unsigned short acategory[4] = {0, 0, 0, 0}; + char *backgrounds[4] = {0, 0, 0, 0}; + unsigned short bcategory[4] = {0, 0, 0, 0}; + char *hpcat[4] = {0, 0, 0, 0}; + unsigned short hcategory[4] = {0, 0, 0, 0}; + + seq2 = icq_PacketReadUDPInSeq2(p); + icq_PacketGotoUDPInData(p, 0); + subcmd = icq_PacketRead16(p); + res = icq_PacketRead8(p); + icq_UDPAck(icqlink, icq_PacketReadUDPInSeq1(p)); + if(res == META_SRV_FAILURE) + { + icq_FmtLog(icqlink, ICQ_LOG_WARNING, "META failure\n"); + invoke_callback(icqlink,icq_RequestNotify)(icqlink, seq2, ICQ_NOTIFY_FAILED, + sizeof(subcmd), &subcmd); + } + else + switch(subcmd) + { + case META_SRV_USER_FOUND: + uin = icq_PacketRead32(p); + nick = icq_PacketReadStringNew(p); + first = icq_PacketReadStringNew(p); + last = icq_PacketReadStringNew(p); + email = icq_PacketReadStringNew(p); + auth = icq_PacketRead8(p); + icq_PacketRead16(p); /* ??? */ + icq_PacketRead32(p); /* ??? */ + icq_RusConv("wk", nick); + icq_RusConv("wk", first); + icq_RusConv("wk", last); + icq_RusConv("wk", email); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "META User Found %lu, Nick: %s, First Name: %s, "\ + "Last Name: %s, EMail: %s, Auth: %s\n", seq2, uin, nick, first, last, + email, auth==1?"no":"yes"); + invoke_callback(icqlink,icq_MetaUserFound)(icqlink, seq2, uin, nick, first, last, email, auth); + free(nick); + free(first); + free(last); + free(email); + break; + case META_SRV_USER_INFO: /* finished! */ + nick = icq_PacketReadStringNew(p); + first = icq_PacketReadStringNew(p); + last = icq_PacketReadStringNew(p); + pri_eml = icq_PacketReadStringNew(p); + sec_eml = icq_PacketReadStringNew(p); + old_eml = icq_PacketReadStringNew(p); + city = icq_PacketReadStringNew(p); + state = icq_PacketReadStringNew(p); + phone = icq_PacketReadStringNew(p); + fax = icq_PacketReadStringNew(p); + street = icq_PacketReadStringNew(p); + cellular = icq_PacketReadStringNew(p); + zip = icq_PacketRead32(p); + country = icq_PacketRead16(p); + timezone = icq_PacketRead8(p); /* +1 = -30min, -1 = +30min (-4 = GMT+0200) */ + auth = icq_PacketRead8(p); /* 1 - no auth required, 0 - required */ + webaware = icq_PacketRead8(p); /* 1 - yes, 0 - no */ + hideip = icq_PacketRead8(p); /* 1 - yes, 0 - no */ + icq_RusConv("wk", nick); + icq_RusConv("wk", first); + icq_RusConv("wk", last); + icq_RusConv("wk", pri_eml); + icq_RusConv("wk", sec_eml); + icq_RusConv("wk", old_eml); + icq_RusConv("wk", city); + icq_RusConv("wk", state); + icq_RusConv("wk", phone); + icq_RusConv("wk", fax); + icq_RusConv("wk", street); + icq_RusConv("wk", cellular); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "META User Info: %s, %s, %s, "\ + "%s, %s, %s, %s, %s, %s, %s, %s, %s, %lu, %s, %i, %s, %s, %s\n", + nick, first, last, pri_eml, sec_eml, old_eml, city, state, phone, + fax, street, cellular, zip, icq_GetCountryName(country), timezone, + auth?"false":"true", webaware?"true":"false", hideip?"true":"false"); + invoke_callback(icqlink,icq_MetaUserInfo)(icqlink, seq2, nick, first, last, pri_eml, + sec_eml, old_eml, city, state, phone, fax, + street, cellular, zip, country, timezone, + auth, webaware, hideip); + free(nick); + free(first); + free(last); + free(pri_eml); + free(sec_eml); + free(old_eml); + free(city); + free(state); + free(phone); + free(fax); + free(street); + free(cellular); + break; + case META_SRV_USER_WORK: /* finished! */ + wcity = icq_PacketReadStringNew(p); + wstate = icq_PacketReadStringNew(p); + wphone = icq_PacketReadStringNew(p); + wfax = icq_PacketReadStringNew(p); + waddress = icq_PacketReadStringNew(p); + wzip = icq_PacketRead32(p); + wcountry = icq_PacketRead16(p); /* icq_GetCountryName() */ + company = icq_PacketReadStringNew(p); + department = icq_PacketReadStringNew(p); + job = icq_PacketReadStringNew(p); + occupation = icq_PacketRead16(p); /* icq_GetMetaOccupationName() */ + whomepage = icq_PacketReadStringNew(p); + icq_RusConv("wk", wcity); + icq_RusConv("wk", wstate); + icq_RusConv("wk", wphone); + icq_RusConv("wk", wfax); + icq_RusConv("wk", waddress); + icq_RusConv("wk", company); + icq_RusConv("wk", department); + icq_RusConv("wk", job); + icq_RusConv("wk", whomepage); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "META User Work: %s, %s, %s, "\ + "%s, %s, %lu, %s, %s, %s, %s, %s, %s\n", wcity, wstate, + wphone, wfax, waddress, wzip, icq_GetCountryName(wcountry), + company, department, job, icq_GetMetaOccupationName(occupation), + whomepage); + invoke_callback(icqlink, icq_MetaUserWork)(icqlink, seq2, wcity, wstate, wphone, + wfax, waddress, wzip, wcountry, company, + department, job, occupation, whomepage); + free(wcity); + free(wstate); + free(wphone); + free(wfax); + free(waddress); + free(company); + free(department); + free(job); + free(whomepage); + break; + case META_SRV_USER_MORE: /* finished! */ + age = icq_PacketRead16(p); /* 0xFFFF - not entered */ + gender = icq_PacketRead8(p); /* 1 - female, 2 - male */ + homepage = icq_PacketReadStringNew(p); + byear = icq_PacketRead8(p); /* starting from 1900 */ + bmonth = icq_PacketRead8(p); + bday = icq_PacketRead8(p); + lang1 = icq_PacketRead8(p); /* icq_GetMetaLanguageName() */ + lang2 = icq_PacketRead8(p); /* icq_GetMetaLanguageName() */ + lang3 = icq_PacketRead8(p); /* icq_GetMetaLanguageName() */ + icq_RusConv("wk", homepage); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "META User More: %i, %s, %s, "\ + "%02i/%02i/%04i, %s, %s, %s\n", age, + gender==1?"female":gender==2?"male":"not entered", + homepage, bday, bmonth, byear+1900, icq_GetMetaLanguageName(lang1), + icq_GetMetaLanguageName(lang2), icq_GetMetaLanguageName(lang3)); + if(icqlink->icq_MetaUserMore) + (*icqlink->icq_MetaUserMore)(icqlink, seq2, age, gender, homepage, byear, + bmonth, bday, lang1, lang2, lang3); + free(homepage); + break; + case META_SRV_USER_ABOUT: /* finished! */ + about = icq_PacketReadStringNew(p); + icq_RusConv("wk", about); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "META User About: %s\n", about); + invoke_callback(icqlink,icq_MetaUserAbout)(icqlink, seq2, about); + free(about); + break; + case META_SRV_USER_INTERESTS: /* finished! */ + inum = icq_PacketRead8(p); + for(i=0; i<inum && i<4; i++) + { + icategory[i] = icq_PacketRead16(p); + interests[i] = icq_PacketReadStringNew(p); + icq_RusConv("wk", interests[i]); + } + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "META User Interests: %i, %i - %s, "\ + "%i - %s, %i - %s, %i - %s\n", inum, icategory[0], + interests[0]?interests[0]:empty, icategory[1], interests[1]?interests[1]:empty, + icategory[2], interests[2]?interests[2]:empty, icategory[3], + interests[3]?interests[3]:empty); + invoke_callback(icqlink, icq_MetaUserInterests)(icqlink, seq2, inum, + icategory[0], interests[0], icategory[1], + interests[1], icategory[2], interests[2], + icategory[3], interests[3]); + for(i=0; i<inum && i<4; i++) + free(interests[i]); + break; + case META_SRV_USER_AFFILIATIONS: /* finished! */ + bnum = icq_PacketRead8(p); + for(i=0; i<bnum && i<4; i++) + { + bcategory[i] = icq_PacketRead16(p); /* icq_GetMetaBackgroundName() */ + backgrounds[i] = icq_PacketReadStringNew(p); + icq_RusConv("wk", backgrounds[i]); + } + anum = icq_PacketRead8(p); + for(i=0; i<anum && i<4; i++) + { + acategory[i] = icq_PacketRead16(p); /* icq_GetMetaAffiliationName() */ + affiliations[i] = icq_PacketReadStringNew(p); + icq_RusConv("wk", affiliations[i]); + } + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "META User Affiliations: %i, %s - %s, "\ + "%s - %s, %s - %s, %s - %s; Backgrounds: %i, %s - %s, %s - %s, "\ + "%s - %s, %s - %s\n", anum, + icq_GetMetaAffiliationName(acategory[0]), affiliations[0]?affiliations[0]:empty, + icq_GetMetaAffiliationName(acategory[1]), affiliations[1]?affiliations[1]:empty, + icq_GetMetaAffiliationName(acategory[2]), affiliations[2]?affiliations[2]:empty, + icq_GetMetaAffiliationName(acategory[3]), affiliations[3]?affiliations[3]:empty, + bnum, icq_GetMetaBackgroundName(bcategory[0]), backgrounds[0]?backgrounds[0]:empty, + icq_GetMetaBackgroundName(bcategory[1]), backgrounds[1]?backgrounds[1]:empty, + icq_GetMetaBackgroundName(bcategory[2]), backgrounds[2]?backgrounds[2]:empty, + icq_GetMetaBackgroundName(bcategory[3]), backgrounds[3]?backgrounds[3]:empty); + invoke_callback(icqlink, icq_MetaUserAffiliations)(icqlink, seq2, anum, acategory[0], + affiliations[0], acategory[1], affiliations[1], + acategory[2], affiliations[2], acategory[3], + affiliations[3], bnum, bcategory[0], + backgrounds[0], bcategory[1], backgrounds[1], + bcategory[2], backgrounds[2], bcategory[3], + backgrounds[3]); + for(i=0; i<bnum && i<4; i++) + free(backgrounds[i]); + for(i=0; i<anum && i<4; i++) + free(affiliations[i]); + break; + case META_SRV_USER_HPCATEGORY: /* finished! */ + hnum = icq_PacketRead8(p); + for(i=0; i<hnum && i<1; i++) + { + hcategory[i] = icq_PacketRead16(p); + hpcat[i] = icq_PacketReadStringNew(p); + icq_RusConv("wk", hpcat[i]); + } + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "META User Homepage Category: %i, %i - %s\n", + hnum, hcategory[0], hpcat[0]); + invoke_callback(icqlink,icq_MetaUserHomePageCategory)(icqlink, seq2, + hnum, hcategory[0], hpcat[0]?hpcat[0]:empty); + for(i=0; i<hnum && i<1; i++) + free(hpcat[i]); + break; + case META_SRV_RES_INFO: + case META_SRV_RES_HOMEPAGE: + case META_SRV_RES_ABOUT: + case META_SRV_RES_SECURE: + case META_SRV_RES_PASS: + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "META success\n"); + invoke_callback(icqlink,icq_RequestNotify)(icqlink, seq2, ICQ_NOTIFY_SUCCESS, + sizeof(subcmd), &subcmd); + break; + default: + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "META User - 0x%04X\n", subcmd); + icq_PacketUDPDump(p); + break; + } +} + +void icq_HandleMultiPacket(icq_Link *icqlink, icq_Packet *p) +{ + icq_Packet *tmp; + int num, i; + icq_PacketGotoUDPInData(p, 0); + num = icq_PacketRead8(p); + + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "MultiPacket: %i packets\n", num); + + for(i = 0; i < num; i++) + { + tmp = icq_PacketNew(); + tmp->length = icq_PacketRead16(p); + memcpy(tmp->data, &(p->data[p->cursor]), tmp->length); + icq_PacketAdvance(p, tmp->length); + icq_ServerResponse(icqlink, tmp); + icq_PacketDelete(tmp); + } +} + +void icq_ServerResponse(icq_Link *icqlink, icq_Packet *p) +{ + time_t cur_time; + struct tm *tm_str; + int len; + struct in_addr in_a; + DWORD uin; + WORD year, type, seq, cmd, ver; + BYTE month, day, hour, minute; + + seq = icq_PacketReadUDPInSeq1(p); + cmd = icq_PacketReadUDPInCmd(p); + ver = icq_PacketReadUDPInVer(p); + + if(ver == 5) /* We understand only V5 packets! */ + { + switch(cmd) + { + case UDP_SRV_ACK: + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "The server acknowledged the command\n"); + invoke_callback(icqlink,icq_RequestNotify)(icqlink, seq, ICQ_NOTIFY_ACK, 0, 0); + invoke_callback(icqlink,icq_RequestNotify)(icqlink, seq, ICQ_NOTIFY_SUCCESS, 0, 0); + icq_UDPQueueDelSeq(icqlink, seq); + break; + case UDP_SRV_MULTI_PACKET: + icq_HandleMultiPacket(icqlink, p); + break; + case UDP_SRV_NEW_UIN: + uin = icq_PacketReadUDPInUIN(p); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "The new uin is %lu\n", uin); + icq_UDPAck(icqlink, seq); + invoke_callback(icqlink,icq_NewUIN)(icqlink, uin); + break; + case UDP_SRV_LOGIN_REPLY: + icq_PacketGotoUDPInData(p, 0); + icqlink->icq_OurIP = ntohl(icq_PacketRead32n(p)); +/* icq_OurIp = icq_PacketRead32(p); */ + in_a.s_addr = htonl(icqlink->icq_OurIP); + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "Login successful, UIN: %lu, IP: %s\n", + icqlink->icq_Uin, inet_ntoa(in_a)); + icq_UDPAck(icqlink, seq); + icq_SendLogin1(icqlink); + icq_SendContactList(icqlink); + icq_SendVisibleList(icqlink); + icq_SendInvisibleList(icqlink); + invoke_callback(icqlink,icq_Logged)(icqlink); + break; + case UDP_SRV_OFFLINE_MESSAGE: /* Offline message through the server */ + icq_PacketGotoUDPInData(p, 0); + uin = icq_PacketRead32(p); + year = icq_PacketRead16(p); + month = icq_PacketRead8(p); + day = icq_PacketRead8(p); + hour = icq_PacketRead8(p); + minute = icq_PacketRead8(p); + type = icq_PacketRead16(p); + len = icq_PacketRead16(p); + icq_UDPAck(icqlink, seq); + icq_DoMsg(icqlink, type, len, (char*)&p->data[p->cursor], uin, hour, minute, day, month, year); + break; + case UDP_SRV_X1: /* unknown message sent after login*/ + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "Acknowleged UDP_SRV_X1 (Begin messages)\n"); + icq_UDPAck(icqlink, seq); + break; + case UDP_SRV_X2: /* unknown message sent after login*/ + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "Acknowleged UDP_SRV_X2 (Done old messages)\n"); + icq_UDPAck(icqlink, seq); + icq_SendGotMessages(icqlink); + break; + case UDP_SRV_INFO_REPLY: + icq_HandleInfoReply(icqlink, p); + break; + case UDP_SRV_EXT_INFO_REPLY: + icq_HandleExtInfoReply(icqlink, p); + break; + case UDP_SRV_USER_ONLINE: + icq_HandleUserOnline(icqlink, p); + break; + case UDP_SRV_USER_OFFLINE: + icq_HandleUserOffline(icqlink, p); + break; + case UDP_SRV_TRY_AGAIN: + icq_FmtLog(icqlink, ICQ_LOG_WARNING, "Server is busy, please try again\n"); + icq_Login(icqlink, icqlink->icq_Status); + break; + case UDP_SRV_STATUS_UPDATE: + icq_HandleStatusChange(icqlink, p); + break; + case UDP_SRV_GO_AWAY: + icq_FmtLog(icqlink, ICQ_LOG_ERROR, "Server has forced us to disconnect\n"); + icq_UDPAck(icqlink, seq); + invoke_callback(icqlink, icq_Disconnected)(icqlink); + break; + case UDP_SRV_END_OF_SEARCH: + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "Search done\n"); + icq_UDPAck(icqlink, seq); + invoke_callback(icqlink, icq_SearchDone)(icqlink); + break; + case UDP_SRV_UPDATE_OK: + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "User info successfully updated\n"); + icq_UDPAck(icqlink, seq); + invoke_callback(icqlink, icq_UpdateSuccess)(icqlink); + break; + case UDP_SRV_UPDATE_FAIL: + icq_FmtLog(icqlink, ICQ_LOG_MESSAGE, "User info update failed\n"); + icq_UDPAck(icqlink, seq); + invoke_callback(icqlink, icq_UpdateFailure)(icqlink); + break; + case UDP_SRV_USER_FOUND: + icq_HandleSearchReply(icqlink, p); + break; + case UDP_SRV_ONLINE_MESSAGE: /* Online message through the server */ + cur_time = time(0L); + tm_str = localtime(&cur_time); + icq_PacketGotoUDPInData(p, 0); + uin = icq_PacketRead32(p); + type = icq_PacketRead16(p); + len = icq_PacketRead16(p); + icq_UDPAck(icqlink, seq); + icq_DoMsg(icqlink, type, len, (char*)&p->data[p->cursor], uin, tm_str->tm_hour, + tm_str->tm_min, tm_str->tm_mday, tm_str->tm_mon+1, tm_str->tm_year+1900); + break; + case UDP_SRV_WRONG_PASSWORD: + icq_FmtLog(icqlink, ICQ_LOG_ERROR, "Wrong password\n"); + icq_UDPAck(icqlink, seq); + invoke_callback(icqlink,icq_WrongPassword)(icqlink); + break; + case UDP_SRV_INVALID_UIN: + icq_FmtLog(icqlink, ICQ_LOG_WARNING, "Invalid UIN\n"); + icq_UDPAck(icqlink, seq); + invoke_callback(icqlink,icq_InvalidUIN)(icqlink); + break; + case UDP_SRV_META_USER: + icq_HandleMetaUserInfo(icqlink, p); + break; + default: /* commands we dont handle yet */ + icq_FmtLog(icqlink, ICQ_LOG_WARNING, "Unhandled message %04x, Version: %x, " + "Sequence: %04x, Size: %d\n", cmd, ver, seq, p->length); + icq_UDPAck(icqlink, seq); /* fake like we know what we're doing */ + break; + } + } + else if(ver == 3) /* And some of V3... */ + { + cmd = icq_PacketReadUDPInCmdV3(p); + switch(cmd) + { + case UDP_SRV_WRONG_PASSWORD: + icq_FmtLog(icqlink, ICQ_LOG_ERROR, "Wrong password\n"); + icq_UDPAck(icqlink, seq); + invoke_callback(icqlink,icq_WrongPassword)(icqlink); + break; + default: /* commands we dont handle yet */ + icq_FmtLog(icqlink, ICQ_LOG_WARNING, "Unhandled message %04x, Version: %x, " + "Sequence: %04x, Size: %d\n", cmd, ver, seq, p->length); + icq_UDPAck(icqlink, seq); /* fake like we know what we're doing */ + break; + } + } + else + { + icq_FmtLog(icqlink, ICQ_LOG_WARNING, "Unhandled protocol version! Message %04x, Version: %x, " + "Sequence: %04x, Size: %d\n", cmd, ver, seq, p->length); +/* icq_UDPAck(icqlink, seq); DO NOT ACK unhandled protocol version! */ + } +} + +/****************************************** +Handles packets that the server sends to us. +*******************************************/ +void icq_HandleServerResponse(icq_Link *icqlink) +{ + WORD seq, cmd; + int s; + icq_Packet *p; + + p = icq_PacketNew(); + s = icq_UDPSockRead(icqlink, p); + p->length = s; + if(s<=0) + { + icq_FmtLog(icqlink, ICQ_LOG_FATAL, "Connection terminated\n"); + icq_Disconnect(icqlink); + invoke_callback(icqlink,icq_Disconnected)(icqlink); + return; + } + seq = icq_PacketReadUDPInSeq1(p); + cmd = icq_PacketReadUDPInCmd(p); + if(icq_GetServMess(icqlink, seq) && cmd != UDP_SRV_NEW_UIN && cmd != UDP_SRV_GO_AWAY && cmd != UDP_SRV_ACK) + { + icq_FmtLog(icqlink, ICQ_LOG_WARNING, "Ignored a message cmd %04x, seq %04x\n", cmd, seq); + icq_UDPAck(icqlink, seq); /* LAGGGGG!! */ + icq_PacketDelete(p); + return; + } + if(cmd != UDP_SRV_ACK) + icq_SetServMess(icqlink, seq); + + icq_ServerResponse(icqlink, p); + + icq_PacketDelete(p); +}