1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
4 * $Id: udp.c 2487 2001-10-10 19:58:11Z warmenhoven $
6 * Copyright (C) 1998-2001, Denis V. Dmitrienko <denis@null.net> and
7 * Bill Soudan <soudan@kde.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 #include "stdpackets.h"
36 #include "icqbyteorder.h"
40 static const BYTE icq_UDPTable
[] = {
41 0x59, 0x60, 0x37, 0x6B, 0x65, 0x62, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x60, 0x57, 0x5B, 0x3D,
42 0x5E, 0x34, 0x6D, 0x36, 0x50, 0x3F, 0x6F, 0x67, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x47, 0x63, 0x39,
43 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x43, 0x69, 0x48, 0x33, 0x31, 0x64, 0x35, 0x5A, 0x4A, 0x42,
44 0x56, 0x40, 0x67, 0x53, 0x41, 0x07, 0x6C, 0x49, 0x58, 0x3B, 0x4D, 0x46, 0x68, 0x43, 0x69, 0x48,
45 0x33, 0x31, 0x44, 0x65, 0x62, 0x46, 0x48, 0x53, 0x41, 0x07, 0x6C, 0x69, 0x48, 0x33, 0x51, 0x54,
46 0x5D, 0x4E, 0x6C, 0x49, 0x38, 0x4B, 0x55, 0x4A, 0x62, 0x46, 0x48, 0x33, 0x51, 0x34, 0x6D, 0x36,
47 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x63, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, 0x35, 0x5A,
48 0x6A, 0x52, 0x6E, 0x3C, 0x51, 0x34, 0x6D, 0x36, 0x50, 0x5F, 0x5F, 0x3F, 0x4F, 0x37, 0x4B, 0x35,
49 0x5A, 0x4A, 0x62, 0x66, 0x58, 0x3B, 0x4D, 0x66, 0x58, 0x5B, 0x5D, 0x4E, 0x6C, 0x49, 0x58, 0x3B,
50 0x4D, 0x66, 0x58, 0x3B, 0x4D, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64,
51 0x55, 0x6A, 0x32, 0x3E, 0x44, 0x45, 0x52, 0x6E, 0x3C, 0x31, 0x64, 0x55, 0x6A, 0x52, 0x4E, 0x6C,
52 0x69, 0x48, 0x53, 0x61, 0x4C, 0x39, 0x30, 0x6F, 0x47, 0x63, 0x59, 0x60, 0x57, 0x5B, 0x3D, 0x3E,
53 0x64, 0x35, 0x3A, 0x3A, 0x5A, 0x6A, 0x52, 0x4E, 0x6C, 0x69, 0x48, 0x53, 0x61, 0x6C, 0x49, 0x58,
54 0x3B, 0x4D, 0x46, 0x68, 0x63, 0x39, 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x67, 0x53, 0x41, 0x25, 0x41,
55 0x3C, 0x51, 0x54, 0x3D, 0x5E, 0x54, 0x5D, 0x4E, 0x4C, 0x39, 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F,
56 0x47, 0x43, 0x69, 0x48, 0x33, 0x51, 0x54, 0x5D, 0x6E, 0x3C, 0x31, 0x64, 0x35, 0x5A, 0x00, 0x00,
59 DWORD
icq_UDPCalculateCheckCode(icq_Packet
*p
)
72 r1
= 0x18 + (rand() % (p
->length
- 0x18));
81 num2
+= icq_UDPTable
[r2
];
87 DWORD
icq_UDPScramble(DWORD cc
)
91 a
[0] = cc
& 0x0000001F;
92 a
[1] = cc
& 0x03E003E0;
93 a
[2] = cc
& 0xF8000400;
94 a
[3] = cc
& 0x0000F800;
95 a
[4] = cc
& 0x041F0000;
103 return a
[0] + a
[1] + a
[2] + a
[3] + a
[4];
106 void icq_UDPEncode(icq_Packet
*p
, char *buffer
)
108 DWORD checkcode
= icq_UDPCalculateCheckCode(p
);
109 DWORD code1
, code2
, code3
;
113 memcpy(buffer
, p
->data
, p
->length
);
115 tmp
= htoicql(checkcode
);
116 memcpy((buffer
+0x14),&tmp
,sizeof(DWORD
));
117 code1
= p
->length
* 0x68656c6cL
;
118 code2
= code1
+ checkcode
;
121 for(; pos
< p
->length
; pos
+=4)
124 memcpy(&data
, (p
->data
)+pos
, sizeof(DWORD
));
125 data
= icqtohl(data
);
126 code3
= code2
+ icq_UDPTable
[pos
& 0xFF];
128 data
= htoicql(data
);
129 memcpy((buffer
+pos
),&data
,sizeof(DWORD
));
131 checkcode
= icq_UDPScramble(checkcode
);
132 tmp
= htoicql(checkcode
);
133 memcpy((buffer
+0x14),&tmp
,sizeof(DWORD
));
136 /*********************************************************
137 icq_UDPSockWrite and icq_UDPSockRead are for _UDP_ packets
138 proxy support for TCP sockets is different!
139 *********************************************************/
140 int icq_UDPSockWriteDirect(icq_Link
*icqlink
, icq_Packet
*p
)
142 char tmpbuf
[ICQ_PACKET_DATA_SIZE
+10];
144 if(icqlink
->icq_UDPSok
<= 3)
146 icq_FmtLog(icqlink
, ICQ_LOG_ERROR
, "Bad socket!\n");
150 icq_UDPEncode(p
, tmpbuf
+10);
152 if(!icqlink
->icq_UseProxy
)
155 return send(icqlink
->icq_UDPSok
, tmpbuf
+10, p
->length
, 0);
157 return write(icqlink
->icq_UDPSok
, tmpbuf
+10, p
->length
);
162 tmpbuf
[0] = 0; /* reserved */
163 tmpbuf
[1] = 0; /* reserved */
164 tmpbuf
[2] = 0; /* standalone packet */
165 tmpbuf
[3] = 1; /* address type IP v4 */
166 *(unsigned long*)&tmpbuf
[4] = htonl(icqlink
->icq_ProxyDestIP
);
167 *(unsigned short*)&tmpbuf
[8] = htons(icqlink
->icq_ProxyDestPort
);
169 return send(icqlink
->icq_UDPSok
, tmpbuf
, p
->length
+10, 0)-10;
171 return write(icqlink
->icq_UDPSok
, tmpbuf
, p
->length
+10)-10;
176 int icq_UDPSockWrite(icq_Link
*icqlink
, icq_Packet
*p
)
178 icq_UDPQueuePut(icqlink
, p
);
180 return icq_UDPSockWriteDirect(icqlink
, p
);
183 int icq_UDPSockRead(icq_Link
*icqlink
, icq_Packet
*p
)
186 char tmpbuf
[ICQ_PACKET_DATA_SIZE
];
188 if(!icqlink
->icq_UseProxy
)
191 res
= recv(icqlink
->icq_UDPSok
, p
->data
, ICQ_PACKET_DATA_SIZE
, 0);
193 res
= read(icqlink
->icq_UDPSok
, p
->data
, ICQ_PACKET_DATA_SIZE
);
201 res
= recv(icqlink
->icq_UDPSok
, tmpbuf
, ICQ_PACKET_DATA_SIZE
, 0);
203 res
= read(icqlink
->icq_UDPSok
, tmpbuf
, ICQ_PACKET_DATA_SIZE
);
207 memcpy(p
->data
, &tmpbuf
[10], res
-10);
213 /****************************************
214 This must be called every 2 min.
215 so the server knows we're still alive.
216 JAVA client sends two different commands
218 *****************************************/
219 WORD
icq_KeepAlive(icq_Link
*icqlink
) /* V5 */
221 icq_Packet
*p
= icq_UDPCreateStdSeqPacket(icqlink
, UDP_CMD_KEEP_ALIVE
, icqlink
->d
->icq_UDPSeqNum1
++);
222 icq_PacketAppend32(p
, rand());
223 icq_UDPSockWriteDirect(icqlink
, p
); /* don't queue keep alive packets! */
226 icq_FmtLog(icqlink
, ICQ_LOG_MESSAGE
, "Send Keep Alive packet to the server\n");
228 return icqlink
->d
->icq_UDPSeqNum1
-1;
231 /**********************************
232 This must be called to remove
233 messages from the server
234 ***********************************/
235 void icq_SendGotMessages(icq_Link
*icqlink
) /* V5 */
237 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_ACK_MESSAGES
);
238 icq_PacketAppend32(p
, rand());
239 icq_UDPSockWrite(icqlink
, p
);
242 /*************************************
243 this sends over the contact list
244 *************************************/
245 void icq_SendContactList(icq_Link
*icqlink
) /* V5 */
248 icq_ContactItem
*ptr
= icq_ContactGetFirst(icqlink
);
252 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_CONT_LIST
);
255 icq_PacketAdvance(p
,1);
256 while(ptr
&& num_used
<64)
258 icq_PacketAppend32(p
, ptr
->uin
);
260 ptr
= icq_ContactGetNext(ptr
);
262 icq_PacketGotoUDPOutData(p
, 0);
263 icq_PacketAppend8(p
, num_used
);
264 icq_UDPSockWrite(icqlink
, p
);
268 void icq_SendNewUser(icq_Link
*icqlink
, unsigned long uin
) /* V5 */
270 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_ADD_TO_LIST
);
271 icq_PacketAppend32(p
, uin
);
272 icq_UDPSockWrite(icqlink
, p
);
275 /*************************************
276 this sends over the visible list
277 that allows certain users to see you
279 *************************************/
280 void icq_SendVisibleList(icq_Link
*icqlink
) /* V5 */
283 icq_ContactItem
*ptr
= icq_ContactGetFirst(icqlink
);
284 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_VIS_LIST
);
287 icq_PacketAdvance(p
,1);
292 icq_PacketAppend32(p
, ptr
->uin
);
295 ptr
= icq_ContactGetNext(ptr
);
299 icq_PacketGotoUDPOutData(p
, 0);
300 icq_PacketAppend8(p
, num_used
);
301 icq_UDPSockWrite(icqlink
, p
);
307 void icq_SendInvisibleList(icq_Link
*icqlink
) /* V5 */
310 icq_ContactItem
*ptr
= icq_ContactGetFirst(icqlink
);
311 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_INVIS_LIST
);
314 icq_PacketAdvance(p
,1);
319 icq_PacketAppend32(p
, ptr
->uin
);
322 ptr
= icq_ContactGetNext(ptr
);
326 icq_PacketGotoUDPOutData(p
, 0);
327 icq_PacketAppend8(p
, num_used
);
328 icq_UDPSockWrite(icqlink
, p
);
334 /**************************************
335 This sends the second login command
336 this is necessary to finish logging in.
337 ***************************************/
338 void icq_SendLogin1(icq_Link
*icqlink
) /* V5 */
340 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_LOGIN_1
);
341 icq_PacketAppend32(p
, rand());
342 icq_UDPSockWrite(icqlink
, p
);
345 /************************************
346 This procedure logins into the server with icq_Uin and pass
347 on the socket icq_Sok and gives our ip and port.
348 It does NOT wait for any kind of a response.
349 *************************************/
350 void icq_Login(icq_Link
*icqlink
, DWORD status
) /* V5 */
354 memset(icqlink
->d
->icq_UDPServMess
, FALSE
, sizeof(icqlink
->d
->icq_UDPServMess
));
355 icqlink
->d
->icq_UDPSession
= rand() & 0x3FFFFFFF;
356 icqlink
->d
->icq_UDPSeqNum1
= rand() & 0x7FFF;
357 icqlink
->d
->icq_UDPSeqNum2
= 1;
359 p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_LOGIN
);
360 icq_PacketAppend32(p
, time(0L));
361 icq_PacketAppend32n(p
, icqlink
->icq_TCPSrvPort
);
362 /*icq_PacketAppend16(p, 0);
363 icq_PacketAppend16n(p, htons(icqlink->icq_OurPort));*/
364 icq_PacketAppendString(p
, icqlink
->icq_Password
);
365 icq_PacketAppend32(p
, LOGIN_X1_DEF
);
366 if(icqlink
->icq_UseTCP
)
368 if(icqlink
->icq_UseProxy
)
370 icq_PacketAppend32n(p
, htonl(icqlink
->icq_ProxyIP
));
371 icq_PacketAppend8(p
, LOGIN_SNDONLY_TCP
);
375 icq_PacketAppend32n(p
, htonl(icqlink
->icq_OurIP
));
376 icq_PacketAppend8(p
, LOGIN_SNDRCV_TCP
);
381 icq_PacketAppend32n(p
, htonl(icqlink
->icq_ProxyIP
));
382 icq_PacketAppend8(p
, LOGIN_NO_TCP
);
384 icq_PacketAppend32(p
, status
);
385 icq_PacketAppend32(p
, LOGIN_X3_DEF
);
386 icq_PacketAppend32(p
, LOGIN_X4_DEF
);
387 icq_PacketAppend32(p
, LOGIN_X5_DEF
);
389 icq_UDPSockWrite(icqlink
, p
);
392 /**********************
394 ***********************/
395 void icq_Logout(icq_Link
*icqlink
) /* V5 */
397 icq_Packet
*p
= icq_UDPCreateStdSeqPacket(icqlink
, UDP_CMD_SEND_TEXT_CODE
, icqlink
->d
->icq_UDPSeqNum1
++);
398 icq_PacketAppendString(p
, "B_USER_DISCONNECTED");
399 icq_PacketAppend8(p
, 5);
400 icq_PacketAppend8(p
, 0);
401 icq_UDPSockWriteDirect(icqlink
, p
); /* don't queue */
405 /*******************************
406 This routine sends the aknowlegement cmd to the
407 server it appears that this must be done after
408 everything the server sends us
409 *******************************/
410 void icq_UDPAck(icq_Link
*icqlink
, int seq
) /* V5 */
412 icq_Packet
*p
= icq_UDPCreateStdSeqPacket(icqlink
, UDP_CMD_ACK
, seq
);
413 icq_PacketAppend32(p
, rand());
415 icq_FmtLog(icqlink
, ICQ_LOG_MESSAGE
, "Acking\n");
416 icq_UDPSockWriteDirect(icqlink
, p
);
420 /***************************************************
421 Sends a message thru the server to uin. Text is the
423 ***************************************************/
424 WORD
icq_UDPSendMessage(icq_Link
*icqlink
, DWORD uin
, const char *text
) /* V5 */
426 char buf
[ICQ_MAX_UDP_MESSAGE_SIZE
];
429 strncpy(buf
, text
, sizeof(buf
));
430 buf
[sizeof(buf
)-1] = 0;
431 icq_RusConv("kw", buf
);
433 p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_SEND_THRU_SRV
);
434 icq_PacketAppend32(p
, uin
);
435 icq_PacketAppend16(p
, TYPE_MSG
);
436 icq_PacketAppendString(p
, buf
);
438 icq_UDPSockWrite(icqlink
, p
);
439 return icqlink
->d
->icq_UDPSeqNum1
-1;
442 WORD
icq_UDPSendURL(icq_Link
*icqlink
, DWORD uin
, const char *url
, const char *descr
) /* V5 */
444 char buf1
[ICQ_MAX_UDP_MESSAGE_SIZE
], buf2
[ICQ_MAX_UDP_MESSAGE_SIZE
];
447 strncpy(buf1
, descr
, sizeof(buf1
));
448 buf1
[sizeof(buf1
)-1] = 0;
449 icq_RusConv("kw", buf1
);
450 strncpy(buf2
, url
, sizeof(buf2
));
451 buf2
[sizeof(buf2
)-1] = 0;
453 p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_SEND_THRU_SRV
);
454 icq_PacketAppend32(p
, uin
);
455 icq_PacketAppend16(p
, TYPE_URL
);
456 icq_PacketAppend16(p
, strlen(buf1
)+strlen(buf2
)+2); /* length + the NULL + 0xFE delimiter */
457 icq_PacketAppendStringFE(p
, buf1
);
458 icq_PacketAppendString0(p
, buf2
);
460 icq_UDPSockWrite(icqlink
, p
);
461 return icqlink
->d
->icq_UDPSeqNum1
-1;
464 /**************************************************
465 Sends a authorization to the server so the Mirabilis
466 client can add the user.
467 ***************************************************/
468 WORD
icq_SendAuthMsg(icq_Link
*icqlink
, DWORD uin
) /* V5 */
470 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_SEND_THRU_SRV
);
471 icq_PacketAppend32(p
, uin
);
472 icq_PacketAppend32(p
, TYPE_AUTH
);
473 icq_PacketAppend16(p
, 0);
474 icq_UDPSockWrite(icqlink
, p
);
476 return icqlink
->d
->icq_UDPSeqNum1
-1;
479 /**************************************************
480 Changes the users status on the server
481 ***************************************************/
482 void icq_ChangeStatus(icq_Link
*icqlink
, DWORD status
) /* V5 */
484 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_STATUS_CHANGE
);
485 icq_PacketAppend32(p
, status
);
486 icqlink
->icq_Status
= status
;
487 icq_UDPSockWrite(icqlink
, p
);
490 /********************************************************
491 Sends a request to the server for info on a specific user
492 *********************************************************/
493 WORD
icq_SendInfoReq(icq_Link
*icqlink
, DWORD uin
) /* V5 */
495 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_INFO_REQ
);
496 icq_PacketAppend32(p
, uin
);
497 icq_UDPSockWrite(icqlink
, p
);
498 return icqlink
->d
->icq_UDPSeqNum1
-1;
501 /********************************************************
502 Sends a request to the server for info on a specific user
503 *********************************************************/
504 WORD
icq_SendExtInfoReq(icq_Link
*icqlink
, DWORD uin
) /* V5 */
506 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_EXT_INFO_REQ
);
507 icq_PacketAppend32(p
, uin
);
508 icq_UDPSockWrite(icqlink
, p
);
509 return icqlink
->d
->icq_UDPSeqNum1
-1;
512 /**************************************************************
513 Initializes a server search for the information specified
514 ***************************************************************/
515 void icq_SendSearchReq(icq_Link
*icqlink
, const char *email
, const char *nick
, const char *first
,
516 const char *last
) /* V5 */
518 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_SEARCH_USER
);
519 icq_PacketAppendString(p
, nick
);
520 icq_PacketAppendString(p
, first
);
521 icq_PacketAppendString(p
, last
);
522 icq_PacketAppendString(p
, email
);
523 icq_UDPSockWrite(icqlink
, p
);
526 /**************************************************************
527 Initializes a server search for the information specified
528 ***************************************************************/
529 void icq_SendSearchUINReq(icq_Link
*icqlink
, DWORD uin
) /* V5 */
531 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_SEARCH_UIN
);
532 icq_PacketAppend32(p
, uin
);
533 icq_UDPSockWrite(icqlink
, p
);
536 /**************************************************
537 Registers a new uin in the ICQ network
538 ***************************************************/
539 void icq_RegNewUser(icq_Link
*icqlink
, const char *pass
) /* V5 */
542 icq_Packet
*p
= icq_UDPCreateStdSeqPacket(icqlink
, UDP_CMD_REG_NEW_USER
, icqlink
->d
->icq_UDPSeqNum1
++);
543 strncpy(pass8
, pass
, 8);
544 icq_PacketAppendString(p
, pass8
);
545 icq_PacketAppend32(p
, 0xA0);
546 icq_PacketAppend32(p
, 0x2461);
547 icq_PacketAppend32(p
, 0xA00000);
548 icq_PacketAppend32(p
, 0x00);
549 icq_PacketGoto(p
, 6);
550 icq_PacketAppend32(p
, 0);
551 icq_PacketAppend32(p
, rand());
552 icq_UDPSockWrite(icqlink
, p
);
553 icq_FmtLog(icqlink
, ICQ_LOG_MESSAGE
, "Send RegNewUser packet to the server\n");
556 WORD
icq_UpdateUserInfo(icq_Link
*icqlink
, const char *nick
, const char *first
, const char *last
,
557 const char *email
) /* V5 */
559 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_UPDATE_INFO
);
560 icq_PacketAppendString(p
, nick
);
561 icq_PacketAppendString(p
, first
);
562 icq_PacketAppendString(p
, last
);
563 icq_PacketAppendString(p
, email
);
565 icq_UDPSockWrite(icqlink
, p
);
566 return icqlink
->d
->icq_UDPSeqNum1
-1;
569 WORD
icq_UpdateAuthInfo(icq_Link
*icqlink
, DWORD auth
) /* V5 */
571 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_UPDATE_AUTH
);
572 icq_PacketAppend32(p
, auth
); /* NOT auth? */
573 icq_UDPSockWrite(icqlink
, p
);
574 return icqlink
->d
->icq_UDPSeqNum1
-1;
577 WORD
icq_UpdateMetaInfoSet(icq_Link
*icqlink
, const char *nick
, const char *first
, const char *last
,
578 const char *email
, const char *email2
, const char *email3
,
579 const char *city
, const char *state
, const char *phone
, const char *fax
,
580 const char *street
, const char *cellular
, unsigned long zip
,
581 unsigned short cnt_code
, unsigned char cnt_stat
, unsigned char emailhide
)
583 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_META_USER
);
584 icq_PacketAppend16(p
, META_CMD_SET_INFO
);
585 icq_PacketAppendString(p
, nick
);
586 icq_PacketAppendString(p
, first
);
587 icq_PacketAppendString(p
, last
);
588 icq_PacketAppendString(p
, email
);
589 icq_PacketAppendString(p
, email2
);
590 icq_PacketAppendString(p
, email3
);
591 icq_PacketAppendString(p
, city
);
592 icq_PacketAppendString(p
, state
);
593 icq_PacketAppendString(p
, phone
);
594 icq_PacketAppendString(p
, fax
);
595 icq_PacketAppendString(p
, street
);
596 icq_PacketAppendString(p
, cellular
);
597 icq_PacketAppend32(p
, zip
);
598 icq_PacketAppend16(p
, cnt_code
);
599 icq_PacketAppend8(p
, cnt_stat
);
600 icq_PacketAppend8(p
, emailhide
);
601 icq_UDPSockWrite(icqlink
, p
);
602 return icqlink
->d
->icq_UDPSeqNum2
-1;
605 WORD
icq_UpdateMetaInfoHomepage(icq_Link
*icqlink
, unsigned char age
, const char *homepage
,
606 unsigned char year
, unsigned char month
, unsigned char day
,
607 unsigned char lang1
, unsigned char lang2
, unsigned char lang3
)
609 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_META_USER
);
613 icq_PacketAppend16(p
, META_CMD_SET_HOMEPAGE
);
614 icq_PacketAppend8(p
, age
);
615 icq_PacketAppend16(p
, 0x0200);
616 icq_PacketAppendString(p
, homepage
);
617 icq_PacketAppend8(p
, year
);
618 icq_PacketAppend8(p
, month
);
619 icq_PacketAppend8(p
, day
);
620 icq_PacketAppend8(p
, 0xFF /* lang1 */);
621 icq_PacketAppend8(p
, 0xFF /* lang2 */);
622 icq_PacketAppend8(p
, 0xFF /* lang3 */);
623 icq_UDPSockWrite(icqlink
, p
);
624 return icqlink
->d
->icq_UDPSeqNum2
-1;
627 WORD
icq_UpdateMetaInfoAbout(icq_Link
*icqlink
, const char *about
)
629 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_META_USER
);
630 icq_PacketAppend16(p
, META_CMD_SET_ABOUT
);
631 icq_PacketAppendString(p
, about
);
632 icq_UDPSockWrite(icqlink
, p
);
633 return icqlink
->d
->icq_UDPSeqNum2
-1;
636 WORD
icq_UpdateMetaInfoSecurity(icq_Link
*icqlink
, unsigned char reqauth
, unsigned char webpresence
,
639 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_META_USER
);
640 icq_PacketAppend16(p
, META_CMD_SET_SECURE
);
641 icq_PacketAppend8(p
, !reqauth
);
642 icq_PacketAppend8(p
, webpresence
);
643 icq_PacketAppend8(p
, pubip
);
644 icq_UDPSockWrite(icqlink
, p
);
645 return icqlink
->d
->icq_UDPSeqNum2
-1;
648 WORD
icq_UpdateNewUserInfo(icq_Link
*icqlink
, const char *nick
, const char *first
, const char *last
,
649 const char *email
) /* V5 */
651 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_NEW_USER_INFO
);
652 icq_PacketAppendString(p
, nick
);
653 icq_PacketAppendString(p
, first
);
654 icq_PacketAppendString(p
, last
);
655 icq_PacketAppendString(p
, email
);
656 icq_PacketAppend8(p
, 1);
657 icq_PacketAppend8(p
, 1);
658 icq_PacketAppend8(p
, 1);
659 icq_UDPSockWrite(icqlink
, p
);
660 return icqlink
->d
->icq_UDPSeqNum1
-1;
663 WORD
icq_SendMetaInfoReq(icq_Link
*icqlink
, unsigned long uin
)
665 icq_Packet
*p
= icq_UDPCreateStdPacket(icqlink
, UDP_CMD_META_USER
);
666 icq_PacketAppend16(p
, META_CMD_REQ_INFO
);
667 icq_PacketAppend32(p
, uin
);
668 icq_UDPSockWrite(icqlink
, p
);
669 return icqlink
->d
->icq_UDPSeqNum2
-1;