sendmsg.c
上传用户:ai20ln
上传日期:2007-01-05
资源大小:79k
文件大小:26k
源码类别:

ICQ/即时通讯

开发平台:

Unix_Linux

  1. /*
  2. Send Message Function for ICQ... 
  3. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. Author : zed@mentasm.com
  5. */
  6. #include "datatype.h"
  7. #include "micq.h"
  8. #include "msg_queue.h"
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <time.h>
  12. #ifdef _WIN32
  13.   #include <winsock2.h>
  14. #else
  15.   #include <unistd.h>
  16.   #include <sys/types.h>
  17.   #include <sys/socket.h>
  18. #endif
  19. #include <string.h>
  20. #include <assert.h>
  21. #include <limits.h>
  22. /*unsigned int next_resend;*/
  23. static size_t SOCKWRITE_LOW( SOK_T sok, void * ptr, size_t len );
  24. /* Historical */
  25. void Initialize_Msg_Queue()
  26. {
  27.     msg_queue_init();
  28. }
  29. /****************************************************************
  30. Checks if packets are waiting to be resent and sends them.
  31. *****************************************************************/
  32. void Do_Resend( SOK_T sok )
  33. {
  34.     struct msg *queued_msg;
  35.     SIMPLE_MESSAGE_PTR s_mesg;
  36.     DWORD type; 
  37.     char *data;
  38.     char *tmp;
  39.     char *temp;
  40.     char url_desc[1024], url_data[1024];
  41.     net_icq_pak pak;
  42.     if ((queued_msg = msg_queue_pop()) != NULL)
  43.     {
  44.         queued_msg->attempts++;
  45.         if (queued_msg->attempts <= 6)
  46.         {
  47.             if ( Verbose )
  48.             {
  49.                 M_print( "nResending message with SEQ num %04x.tCMD ", queued_msg->seq );
  50. Print_CMD( Chars_2_Word( &queued_msg->body[6] ) );
  51. M_print( "(Attempt #%d.)n", queued_msg->attempts);
  52.                 Prompt();
  53.             }
  54.             if ( 0x1000 < Chars_2_Word( &queued_msg->body[6] ) ) {
  55. Dump_Queue();
  56.             }
  57.     temp = malloc( queued_msg->len );
  58.     memcpy( temp, queued_msg->body, queued_msg->len);
  59.             SOCKWRITE_LOW(sok, temp, queued_msg->len);
  60.     free(temp);
  61.             queued_msg->exp_time = time(NULL) + 10; 
  62.             msg_queue_push( queued_msg );
  63.         }
  64.         else
  65.         {
  66.             memcpy(&pak.head.ver, queued_msg->body, queued_msg->len); 
  67.     if ( CMD_SENDM  == Chars_2_Word( pak.head.cmd ) ) {
  68.                s_mesg = ( SIMPLE_MESSAGE_PTR ) pak.data;
  69.                M_print("nDiscarding message to ");
  70.                Print_UIN_Name( Chars_2_DW( s_mesg->uin ) );
  71.                M_print(" after %d send attempts.  Message content:n",
  72.                        queued_msg->attempts - 1);
  73.                type = Chars_2_Word(s_mesg->type);
  74.                data = s_mesg->len + 2; 
  75.                if (type == URL_MESS || type == MRURL_MESS)
  76.                {
  77.                    tmp = strchr( data, 'xFE' );
  78.                    if ( tmp != NULL )
  79.                    {
  80.                        *tmp = 0;
  81.                        rus_conv("wk", data);
  82.                        strcpy(url_desc, data);
  83.                        tmp++;
  84.                        data = tmp;
  85.                        rus_conv("wk", data);
  86.                        strcpy(url_data, data);
  87.                        M_print( " Description: " MESSCOL "%s" 
  88.                                NOCOL "n", url_desc );
  89.                        M_print( " URL        : " MESSCOL "%s" NOCOL "n", 
  90.                                url_data );
  91.                    }
  92.                }
  93.                else if (type == NORM_MESS || type == MRNORM_MESS)
  94.                {
  95.                    rus_conv("wk", data); 
  96.                    M_print( MESSCOL "%s", data );
  97.                    M_print( NOCOL "n" );
  98.                }
  99.             } else {
  100.        M_print( "nDiscarded a " );
  101.        Print_CMD( Chars_2_Word( pak.head.cmd ) );
  102.        M_print( " packet.n" );
  103.        if ( ( CMD_LOGIN == Chars_2_Word( pak.head.cmd ) ) ||
  104.             ( CMD_KEEP_ALIVE == Chars_2_Word( pak.head.cmd ) ) ) {
  105.                   M_print( "aConnection unstable exiting....n" );
  106.   Quit = TRUE;
  107.        }
  108.     }
  109.             Prompt();
  110.             free(queued_msg->body);
  111.             free(queued_msg);
  112.         }
  113.         if ( (queued_msg = msg_queue_peek() ) != NULL )
  114.         {
  115.             next_resend = queued_msg->exp_time; 
  116.         }
  117.         else
  118.         {
  119.             next_resend = INT_MAX;
  120.         }
  121.     }
  122.     else
  123.     {
  124.         next_resend = INT_MAX;
  125.     }
  126. }
  127. /*********************************
  128. This must be called to remove messages
  129. from the server
  130. **********************************/
  131. void snd_got_messages( int sok )
  132. {
  133.    net_icq_pak pak;
  134.    
  135.    Word_2_Chars( pak.head.ver, ICQ_VER );
  136.    Word_2_Chars( pak.head.cmd, CMD_ACK_MESSAGES );
  137.    Word_2_Chars( pak.head.seq, seq_num++ );
  138.    DW_2_Chars( pak.head.UIN, UIN );
  139.    
  140.    last_cmd[ (seq_num - 1) & 0x3ff ] = Chars_2_Word( pak.head.cmd );
  141.    SOCKWRITE( sok, &(pak.head.ver), sizeof( pak.head ) - 2 );
  142. }
  143. /*************************************
  144. this sends over the contact list
  145. **************************************/
  146. void snd_contact_list( int sok )
  147. {
  148.    net_icq_pak pak;
  149.    int num_used;
  150.    int i, size;
  151.    char *tmp;
  152.    
  153.    Word_2_Chars( pak.head.ver, ICQ_VER );
  154.    Word_2_Chars( pak.head.cmd, CMD_CONT_LIST );
  155.    Word_2_Chars( pak.head.seq, seq_num++ );
  156.    DW_2_Chars( pak.head.UIN, UIN );
  157.    
  158.    tmp = pak.data;
  159.    tmp++;
  160.    for ( i=0, num_used=0; i < Num_Contacts ; i++ )
  161.    {
  162.       if ( (S_DWORD) Contacts[ i ].uin >  0 )
  163.       {
  164.          DW_2_Chars( tmp, Contacts[i].uin );
  165.          tmp+=4;
  166.          num_used++;
  167.       }
  168.    }
  169.    pak.data[0] = num_used;
  170. /*   Word_2_Chars( pak.data, num_used ); */
  171.    size = sizeof( DWORD ) * num_used + 1;
  172.    size += sizeof( pak.head ) - 2;
  173.    last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  174.    SOCKWRITE( sok, &(pak.head.ver), size );
  175. }
  176. /*************************************
  177. this sends over the Invisible list
  178. that allows certain users to see you
  179. if you're invisible.
  180. **************************************/
  181. void snd_invis_list( int sok )
  182. {
  183.    net_icq_pak pak;
  184.    int num_used;
  185.    int i, size;
  186.    char *tmp;
  187.    
  188.    Word_2_Chars( pak.head.ver, ICQ_VER );
  189.    Word_2_Chars( pak.head.cmd, CMD_INVIS_LIST );
  190.    Word_2_Chars( pak.head.seq, seq_num );
  191.    DW_2_Chars( pak.head.UIN, UIN );
  192.    
  193.    tmp = pak.data;
  194.    tmp++;
  195.    for ( i=0, num_used=0; i < Num_Contacts ; i++ )
  196.    {
  197.       if ( (S_DWORD) Contacts[ i ].uin >  0 )
  198.       {
  199.          if ( Contacts[i].invis_list )
  200.          {
  201.             DW_2_Chars( tmp, Contacts[i].uin );
  202.             tmp+=4;
  203.             num_used++;
  204.          }
  205.       }
  206.    }
  207.    if ( num_used != 0 )
  208.    {
  209.       pak.data[0] = num_used;
  210.       size = ( ( int ) tmp - ( int ) pak.data );
  211.       size += sizeof( pak.head ) - 2;
  212.       last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  213.       SOCKWRITE( sok, &(pak.head.ver), size );
  214.       seq_num++;
  215.    }
  216. }
  217. /*************************************
  218. this sends over the Visible list
  219. that allows certain users to see you
  220. if you're invisible.
  221. **************************************/
  222. void snd_vis_list( int sok )
  223. {
  224.    net_icq_pak pak;
  225.    int num_used;
  226.    int i, size;
  227.    char *tmp;
  228.    
  229.    Word_2_Chars( pak.head.ver, ICQ_VER );
  230.    Word_2_Chars( pak.head.cmd, CMD_VIS_LIST );
  231.    Word_2_Chars( pak.head.seq, seq_num );
  232.    DW_2_Chars( pak.head.UIN, UIN );
  233.    
  234.    tmp = pak.data;
  235.    tmp++;
  236.    for ( i=0, num_used=0; i < Num_Contacts ; i++ )
  237.    {
  238.       if ( (S_DWORD) Contacts[ i ].uin >  0 )
  239.       {
  240.          if ( Contacts[i].vis_list )
  241.          {
  242.             DW_2_Chars( tmp, Contacts[i].uin );
  243.             tmp+=4;
  244.             num_used++;
  245.          }
  246.       }
  247.    }
  248.    if ( num_used != 0 )
  249.    {
  250.       pak.data[0] = num_used;
  251.       size = ( ( int ) tmp - ( int ) pak.data );
  252.       size += sizeof( pak.head ) - 2;
  253.       last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  254.       SOCKWRITE( sok, &(pak.head.ver), size );
  255.       seq_num++;
  256.    }
  257. }
  258. /**************************************
  259. This sends the second login command
  260. this is necessary to finish logging in.
  261. ***************************************/
  262. void snd_login_1( int sok )
  263. {
  264.    net_icq_pak pak;
  265.    
  266.    Word_2_Chars( pak.head.ver, ICQ_VER );
  267.    Word_2_Chars( pak.head.cmd, CMD_LOGIN_1 );
  268.    Word_2_Chars( pak.head.seq, seq_num++ );
  269.    DW_2_Chars( pak.head.UIN, UIN );
  270.    
  271.    last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  272.    SOCKWRITE( sok, &(pak.head.ver), sizeof( pak.head ) - 2 );
  273. }
  274. /*********************************
  275. This must be called every 2 min.
  276. so the server knows we're still alive.
  277. JAVA client sends two different commands
  278. so we do also :)
  279. **********************************/
  280. void Keep_Alive( int sok )
  281. {
  282.    net_icq_pak pak;
  283.    
  284.    Word_2_Chars( pak.head.ver, ICQ_VER );
  285.    Word_2_Chars( pak.head.cmd, CMD_KEEP_ALIVE );
  286.    Word_2_Chars( pak.head.seq, seq_num++ );
  287.    DW_2_Chars( pak.head.UIN, UIN );
  288.    
  289.    last_cmd[(seq_num - 1) & 0x3ff ] = Chars_2_Word( pak.head.cmd );
  290.    SOCKWRITE( sok, &(pak.head.ver), sizeof( pak.head ) - 2 );
  291.    Word_2_Chars( pak.head.ver, ICQ_VER );
  292.    Word_2_Chars( pak.head.cmd, CMD_KEEP_ALIVE2 );
  293.    Word_2_Chars( pak.head.seq, seq_num++ );
  294.    DW_2_Chars( pak.head.UIN, UIN );
  295.    
  296.    last_cmd[(seq_num - 1) & 0x3ff ] = Chars_2_Word( pak.head.cmd );
  297.    SOCKWRITE( sok, &(pak.head.ver), sizeof( pak.head ) - 2 );
  298.    if ( Verbose )
  299.    {
  300. #ifdef FUNNY_MSGS
  301.    M_print( "nIf you go to" MESSCOL " Z'Ha'Dum " NOCOL "you will die!!!!n" ); 
  302.    /* or if you don't send this packet */
  303. #else
  304.    M_print( "nSend Keep_Alive packet to the servern" );
  305. #endif
  306.    }
  307. }
  308. /********************************************************
  309. The following data constitutes fair use for compatibility.
  310. *********************************************************/
  311. unsigned char icq_check_data[257] = {
  312. 0x0a, 0x5b, 0x31, 0x5d, 0x20, 0x59, 0x6f, 0x75, 
  313. 0x20, 0x63, 0x61, 0x6e, 0x20, 0x6d, 0x6f, 0x64, 
  314. 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 
  315. 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x20, 0x49,
  316. 0x43, 0x51, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73, 
  317. 0x2e, 0x20, 0x4a, 0x75, 0x73, 0x74, 0x20, 0x73, 
  318. 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x22, 0x53, 
  319. 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x20, 0x66, 
  320. 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
  321. 0x22, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65,
  322. 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x6d, 0x69, 0x73,
  323. 0x63, 0x22, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x43,
  324. 0x51, 0x20, 0x6f, 0x72, 0x20, 0x66, 0x72, 0x6f,
  325. 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x53,
  326. 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x20, 0x69,
  327. 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
  328. 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x70, 0x61,
  329. 0x6e, 0x65, 0x6c, 0x2e, 0x20, 0x43, 0x72, 0x65,
  330. 0x64, 0x69, 0x74, 0x3a, 0x20, 0x45, 0x72, 0x61,
  331. 0x6e, 0x0a, 0x5b, 0x32, 0x5d, 0x20, 0x43, 0x61,
  332. 0x6e, 0x27, 0x74, 0x20, 0x72, 0x65, 0x6d, 0x65,
  333. 0x6d, 0x62, 0x65, 0x72, 0x20, 0x77, 0x68, 0x61,
  334. 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x61,
  335. 0x69, 0x64, 0x3f, 0x20, 0x20, 0x44, 0x6f, 0x75,
  336. 0x62, 0x6c, 0x65, 0x2d, 0x63, 0x6c, 0x69, 0x63,
  337. 0x6b, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x20, 0x75,
  338. 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x67,
  339. 0x65, 0x74, 0x20, 0x61, 0x20, 0x64, 0x69, 0x61,
  340. 0x6c, 0x6f, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x61,
  341. 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61,
  342. 0x67, 0x65, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74,
  343. 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0
  344. };
  345. /***************************************************
  346. Sends a message thru the server to uin.  Text is the
  347. message to send.
  348. ****************************************************/
  349. void icq_sendmsg( SOK_T sok, DWORD uin, char *text, DWORD msg_type)
  350. {
  351. SIMPLE_MESSAGE msg;
  352. net_icq_pak pak;
  353. int size, len; 
  354. log_event("You sent instant message",text,uin);
  355. rus_conv ("kw",text);
  356. len = strlen(text);
  357. Word_2_Chars( pak.head.ver, ICQ_VER );
  358. Word_2_Chars( pak.head.cmd, CMD_SENDM );
  359. Word_2_Chars( pak.head.seq, seq_num++ );
  360. DW_2_Chars( pak.head.UIN, UIN );
  361. DW_2_Chars( msg.uin, uin );
  362. Word_2_Chars(msg.type, msg_type);
  363. Word_2_Chars( msg.len, len + 1 ); /* length + the NULL */
  364. memcpy(&pak.data, &msg, sizeof( msg ) );
  365. memcpy(&pak.data[8], text, len + 1);
  366. size = sizeof( msg ) + len + 1;
  367. last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  368. SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  369. }
  370. /**************************************************
  371. Sends a authorixation to the server so the Mirabilis
  372. client can add the user.
  373. ***************************************************/
  374. void icq_sendauthmsg( SOK_T sok, DWORD uin)
  375. {
  376. SIMPLE_MESSAGE msg;
  377. net_icq_pak pak;
  378. int size; 
  379. Word_2_Chars( pak.head.ver, ICQ_VER );
  380. Word_2_Chars( pak.head.cmd, CMD_SENDM );
  381. Word_2_Chars( pak.head.seq, seq_num++ );
  382. DW_2_Chars( pak.head.UIN, UIN );
  383. DW_2_Chars( msg.uin, uin );
  384. DW_2_Chars( msg.type, AUTH_MESSAGE ); /* A type authorization msg*/
  385. Word_2_Chars( msg.len, 2 );
  386. memcpy(&pak.data, &msg, sizeof( msg ) );
  387.    pak.data[ sizeof(msg) ]=0x03;
  388.    pak.data[ sizeof(msg) + 1]=0x00;
  389. size = sizeof( msg ) + 2;
  390. last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  391. SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  392. }
  393. /***************************************************
  394. Requests a random user from the specified group.
  395. ****************************************************/
  396. void icq_rand_user_req( SOK_T sok, DWORD group )
  397. {
  398.    net_icq_pak pak;
  399.    int size ;
  400.    Word_2_Chars( pak.head.ver, ICQ_VER );
  401.    Word_2_Chars( pak.head.cmd, CMD_RAND_SEARCH );
  402.    Word_2_Chars( pak.head.seq, seq_num++ );
  403.    DW_2_Chars( pak.head.UIN, UIN );
  404.    DW_2_Chars( pak.data, group);
  405.    size = 4;
  406.    last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  407.    SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  408. }
  409. /***************************************************
  410. Sets our Random chat group
  411. ****************************************************/
  412. void icq_rand_set( SOK_T sok, DWORD group )
  413. {
  414.    net_icq_pak pak;
  415.    int size ;
  416.    Word_2_Chars( pak.head.ver, ICQ_VER );
  417.    Word_2_Chars( pak.head.cmd, CMD_RAND_SET );
  418.    Word_2_Chars( pak.head.seq, seq_num++ );
  419.    DW_2_Chars( pak.head.UIN, UIN );
  420.    DW_2_Chars( pak.data, group);
  421.    size = 4;
  422.    last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  423.    SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  424. }
  425. /***************************************************
  426. Changes the users status on the server
  427. ****************************************************/
  428. void icq_change_status( SOK_T sok, DWORD status )
  429. {
  430. net_icq_pak pak;
  431. int size ;
  432. Word_2_Chars( pak.head.ver, ICQ_VER );
  433. Word_2_Chars( pak.head.cmd, CMD_STATUS_CHANGE );
  434. Word_2_Chars( pak.head.seq, seq_num++ );
  435. DW_2_Chars( pak.head.UIN, UIN );
  436.    DW_2_Chars( pak.data, status);
  437.    Current_Status = status;
  438. size = 4;
  439. last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  440. SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  441. }
  442. /******************************************************************
  443. Logs off ICQ should handle other cleanup as well
  444. ********************************************************************/
  445. void Quit_ICQ( int sok )
  446. {
  447. net_icq_pak pak;
  448. int size, len;
  449.    
  450. Word_2_Chars( pak.head.ver, ICQ_VER );
  451. Word_2_Chars( pak.head.cmd, CMD_SEND_TEXT_CODE );
  452. Word_2_Chars( pak.head.seq, seq_num++ );
  453. DW_2_Chars( pak.head.UIN, UIN );
  454.    
  455.    len = strlen( "B_USER_DISCONNECTED" ) + 1;
  456.    *(short * ) pak.data = len;
  457.    size = len + 4;
  458.    
  459.    memcpy( &pak.data[2], "B_USER_DISCONNECTED", len );
  460.    pak.data[ 2 + len ] = 05;
  461.    pak.data[ 3 + len ] = 00;
  462.    last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  463.    SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  464.    SOCKCLOSE(sok);
  465.    SOCKCLOSE( sok );
  466. }
  467. void info_req_99( SOK_T sok, DWORD uin )
  468. {
  469. net_icq_pak pak;
  470. int size ;
  471. Word_2_Chars( pak.head.ver, ICQ_VER );
  472. Word_2_Chars( pak.head.cmd, CMD_META_USER );
  473. Word_2_Chars( pak.head.seq, seq_num++ );
  474. DW_2_Chars( pak.head.UIN, UIN );
  475. #if ICQ_VER == 0x0002
  476.    Word_2_Chars( pak.data , seq_num );
  477.    DW_2_Chars( pak.data + 2, uin );
  478. size = 6;
  479. #else
  480.    Word_2_Chars( pak.data , META_INFO_REQ );
  481.    DW_2_Chars( pak.data + 2, uin );
  482. size = 6;
  483. #endif
  484. last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  485. SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  486. }
  487. /*********************************************************
  488. Sends a request to the server for info on a specific user
  489. **********************************************************/
  490. void send_info_req( SOK_T sok, DWORD uin )
  491. {
  492. net_icq_pak pak;
  493. int size ;
  494. #if 1
  495. Word_2_Chars( pak.head.ver, ICQ_VER );
  496. Word_2_Chars( pak.head.cmd, CMD_INFO_REQ );
  497. Word_2_Chars( pak.head.seq, seq_num++ );
  498. DW_2_Chars( pak.head.UIN, UIN );
  499. #if ICQ_VER == 0x0002
  500.    Word_2_Chars( pak.data , seq_num );
  501.    DW_2_Chars( pak.data + 2, uin );
  502. size = 6;
  503. #else
  504.    DW_2_Chars( pak.data, uin );
  505. size = 4;
  506. #endif
  507. last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  508. SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  509. #endif
  510. }
  511. /*********************************************************
  512. Sends a request to the server for info on a specific user
  513. **********************************************************/
  514. void send_ext_info_req( SOK_T sok, DWORD uin )
  515. {
  516. net_icq_pak pak;
  517. int size ;
  518. Word_2_Chars( pak.head.ver, ICQ_VER );
  519. Word_2_Chars( pak.head.cmd, CMD_EXT_INFO_REQ );
  520. Word_2_Chars( pak.head.seq, seq_num++ );
  521. DW_2_Chars( pak.head.UIN, UIN );
  522. #if ICQ_VER == 0x0002
  523.    Word_2_Chars( pak.data , seq_num );
  524.    DW_2_Chars( pak.data + 2, uin );
  525. size = 6;
  526. #else
  527.    DW_2_Chars( pak.data , uin );
  528. size = 4;
  529. #endif
  530. last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  531. SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  532. }
  533. /***************************************************************
  534. Initializes a server search for the information specified
  535. ****************************************************************/
  536. void start_search( SOK_T sok, char *email, char *nick, char* first, char* last )
  537. {
  538. net_icq_pak pak;
  539. int size ;
  540. Word_2_Chars( pak.head.ver, ICQ_VER );
  541. Word_2_Chars( pak.head.cmd, CMD_SEARCH_USER );
  542. Word_2_Chars( pak.head.seq, seq_num++ );
  543. DW_2_Chars( pak.head.UIN, UIN );
  544. /*
  545.    Word_2_Chars( pak.data , seq_num++ );
  546.    size = 2;
  547. */
  548.    size = 0;
  549.    Word_2_Chars( pak.data + size, strlen( nick ) + 1 );
  550.    size += 2;
  551.    strcpy( pak.data + size , nick );
  552.    size += strlen( nick ) + 1;
  553.    Word_2_Chars( pak.data + size, strlen( first ) + 1 );
  554.    size += 2;
  555.    strcpy( pak.data + size , first );
  556.    size += strlen( first ) + 1;
  557.    Word_2_Chars( pak.data + size, strlen( last ) + 1);
  558.    size += 2;
  559.    strcpy( pak.data + size , last );
  560.    size += strlen( last ) +1 ;
  561.    Word_2_Chars( pak.data + size, strlen( email ) + 1  );
  562.    size += 2;
  563.    strcpy( pak.data + size , email );
  564.    size += strlen( email ) + 1;
  565. last_cmd[seq_num - 2 ] = Chars_2_Word( pak.head.cmd );
  566. SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  567. }
  568. /***************************************************
  569. Registers a new UIN in the ICQ network
  570. ****************************************************/
  571. void reg_new_user( SOK_T sok, char *pass)
  572. {
  573. #if ICQ_VER == 0x0002
  574. srv_net_icq_pak pak;
  575. #else
  576. net_icq_pak pak;
  577. #endif
  578.    char len_buf[2];
  579. int size, len; 
  580. len = strlen(pass);
  581. Word_2_Chars( pak.head.ver, ICQ_VER );
  582. Word_2_Chars( pak.head.cmd, CMD_REG_NEW_USER );
  583. Word_2_Chars( pak.head.seq, seq_num++ );
  584. #if ICQ_VER != 0x0002
  585. Word_2_Chars( pak.head.seq2, seq_num-1 );
  586. #endif
  587.    Word_2_Chars( len_buf, len );
  588. #if ICQ_VER == 0x0002
  589. memcpy(&pak.data, "x02x00", 2 );
  590.    memcpy(&pak.data[2], len_buf, 2 );
  591. memcpy(&pak.data[4], pass, len + 1);
  592.    DW_2_Chars( &pak.data[4+len], 0x0072 );
  593.    DW_2_Chars( &pak.data[8+len], 0x0000 );
  594.   size = len + 12;
  595. #else
  596. /* memcpy(&pak.data, "x02x00", 2 );*/
  597.    memcpy(&pak.data[0], len_buf, 2 );
  598. memcpy(&pak.data[2], pass, len + 1);
  599.    DW_2_Chars( &pak.data[2+len], 0xA0 );
  600.    DW_2_Chars( &pak.data[6+len], 0x2461 );
  601.    DW_2_Chars( &pak.data[10+len], 0xa00000 );
  602.    DW_2_Chars( &pak.data[14+len], 0x00 );
  603. size = len + 18;
  604. #endif
  605. last_cmd[seq_num - 1 ] = Chars_2_Word( pak.head.cmd );
  606. SOCKWRITE_LOW( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  607. }
  608. void Update_User_Info( SOK_T sok, USER_INFO_PTR user)
  609. {
  610. net_icq_pak pak;
  611. int size ;
  612. Word_2_Chars( pak.head.ver, ICQ_VER );
  613. Word_2_Chars( pak.head.cmd, CMD_UPDATE_INFO );
  614. Word_2_Chars( pak.head.seq, seq_num++ );
  615. DW_2_Chars( pak.head.UIN, UIN );
  616.    
  617. #if ICQ_VER == 0x0002
  618.    Word_2_Chars( pak.data , seq_num++ );
  619.    size = 2;
  620. #else
  621.    size = 0;
  622. #endif
  623.    Word_2_Chars( pak.data + size, strlen( user->nick ) + 1 );
  624.    size += 2;
  625.    strcpy( pak.data + size , user->nick );
  626.    size += strlen( user->nick ) + 1;
  627.    Word_2_Chars( pak.data + size, strlen( user->first ) + 1 );
  628.    size += 2;
  629.    strcpy( pak.data + size , user->first );
  630.    size += strlen( user->first ) + 1;
  631.    Word_2_Chars( pak.data + size, strlen( user->last ) + 1);
  632.    size += 2;
  633.    strcpy( pak.data + size , user->last );
  634.    size += strlen( user->last ) +1 ;
  635.    Word_2_Chars( pak.data + size, strlen( user->email ) + 1  );
  636.    size += 2;
  637.    strcpy( pak.data + size , user->email );
  638.    size += strlen( user->email ) + 1;
  639.    pak.data[ size ] = user->auth;
  640.    size++;
  641. last_cmd[ ( seq_num - 1 ) & 0x3ff ] = Chars_2_Word( pak.head.cmd );
  642. SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  643. Word_2_Chars( pak.head.ver, ICQ_VER );
  644. Word_2_Chars( pak.head.cmd, CMD_AUTH_UPDATE );
  645. Word_2_Chars( pak.head.seq, seq_num++ );
  646. DW_2_Chars( pak.head.UIN, UIN );
  647.    DW_2_Chars( pak.data, ! user->auth );
  648. last_cmd[ ( seq_num - 1 ) & 0x3ff ] = Chars_2_Word( pak.head.cmd );
  649. SOCKWRITE( sok, &(pak.head.ver), 4 + sizeof( pak.head ) - 2);
  650. }
  651. void Update_More_User_Info( SOK_T sok, MORE_INFO_PTR user)
  652. {
  653. net_icq_pak pak;
  654. int size ;
  655. Word_2_Chars( pak.head.ver, ICQ_VER );
  656. Word_2_Chars( pak.head.cmd, CMD_META_USER );
  657. Word_2_Chars( pak.head.seq, seq_num++ );
  658. DW_2_Chars( pak.head.UIN, UIN );
  659.    
  660.    Word_2_Chars( pak.data , META_INFO_SET );
  661.    size = 2;
  662.    Word_2_Chars( pak.data + size, strlen( user->nick ) + 1 );
  663.    size += 2;
  664.    strcpy( pak.data + size , user->nick );
  665.    size += strlen( user->nick ) + 1;
  666.    Word_2_Chars( pak.data + size, strlen( user->first ) + 1 );
  667.    size += 2;
  668.    strcpy( pak.data + size , user->first );
  669.    size += strlen( user->first ) + 1;
  670.    Word_2_Chars( pak.data + size, strlen( user->last ) + 1);
  671.    size += 2;
  672.    strcpy( pak.data + size , user->last );
  673.    size += strlen( user->last ) +1 ;
  674.    Word_2_Chars( pak.data + size, strlen( user->email ) + 1  );
  675.    size += 2;
  676.    strcpy( pak.data + size , user->email );
  677.    size += strlen( user->email ) + 1;
  678.    Word_2_Chars( pak.data + size, strlen( user->email2 ) + 1  );
  679.    size += 2;
  680.    strcpy( pak.data + size , user->email2 );
  681.    size += strlen( user->email2 ) + 1;
  682.    Word_2_Chars( pak.data + size, strlen( user->email3 ) + 1  );
  683.    size += 2;
  684.    strcpy( pak.data + size , user->email3 );
  685.    size += strlen( user->email3 ) + 1;
  686.    Word_2_Chars( pak.data + size, strlen( user->city ) + 1  );
  687.    size += 2;
  688.    strcpy( pak.data + size , user->city );
  689.    size += strlen( user->city ) + 1;
  690.    Word_2_Chars( pak.data + size, strlen( user->state ) + 1  );
  691.    size += 2;
  692.    strcpy( pak.data + size , user->state );
  693.    size += strlen( user->state ) + 1;
  694.    Word_2_Chars( pak.data + size, strlen( user->phone ) + 1  );
  695.    size += 2;
  696.    strcpy( pak.data + size , user->phone );
  697.    size += strlen( user->phone ) + 1;
  698.    Word_2_Chars( pak.data + size, strlen( user->fax ) + 1  );
  699.    size += 2;
  700.    strcpy( pak.data + size , user->fax );
  701.    size += strlen( user->fax ) + 1;
  702.    Word_2_Chars( pak.data + size, strlen( user->street ) + 1  );
  703.    size += 2;
  704.    strcpy( pak.data + size , user->street );
  705.    size += strlen( user->street ) + 1;
  706.    Word_2_Chars( pak.data + size, strlen( user->cellular ) + 1  );
  707.    size += 2;
  708.    strcpy( pak.data + size , user->cellular );
  709.    size += strlen( user->cellular ) + 1;
  710.    DW_2_Chars( &pak.data[ size ] , user->zip );
  711.    size += 4;
  712.    Word_2_Chars( &pak.data[ size ] , user->country );
  713.    size += 2;
  714.    pak.data[ size ++ ] = user->c_status;
  715.    pak.data[ size ] = user->hide_email;
  716.    size++;
  717. last_cmd[ ( seq_num - 1 ) & 0x3ff ] = Chars_2_Word( pak.head.cmd );
  718. SOCKWRITE( sok, &(pak.head.ver), size + sizeof( pak.head ) - 2);
  719. }
  720. void icq_sendurl( SOK_T sok, DWORD uin, char *description, char *url )
  721. {
  722.    char buf[450];
  723.    
  724.    sprintf( buf, "%sxFE%s", url, description );
  725.    icq_sendmsg( sok, uin, buf, URL_MESS );
  726. }
  727. void Wrinkle( void * ptr, size_t len )
  728. {
  729.    static BOOL before = FALSE;
  730.    BYTE *buf;
  731.    DWORD chksum;
  732.    DWORD key;
  733.    DWORD tkey, temp;
  734.    BYTE r1,r2;
  735.    int n, pos;
  736.    DWORD chk1,chk2;
  737.    buf = ptr;
  738.    if ( ! before ) {
  739.       srand( time( NULL ) );
  740.    }
  741.    buf[2] = rand() & 0xff ;
  742.    buf[3] = rand() & 0xff ;
  743.    buf[4] = 0;
  744.    buf[5] = 0;
  745.    r1 = rand() % ( len - 4 );
  746.    r2 = rand() & 0xff;
  747.    chk1 = (BYTE) buf[8];
  748.    chk1 <<= 8;
  749.    chk1 += (BYTE) buf[4];
  750.    chk1 <<= 8;
  751.    chk1 += (BYTE) buf[2];
  752.    chk1 <<= 8;
  753.    chk1 += (BYTE) buf[6];
  754.    chk2 = r1;
  755.    chk2 <<= 8;
  756.    chk2 +=(BYTE) ( buf[ r1 ] );
  757.    chk2 <<= 8;
  758.    chk2 += r2;
  759.    chk2 <<= 8;
  760.    chk2 +=(BYTE) ( icq_check_data[ r2 ] );
  761.    chk2 ^= 0x00ff00ff;
  762.    
  763.    chksum = chk2 ^ chk1;
  764.    
  765.    DW_2_Chars( &buf[ 0x10 ], chksum );
  766.    key = len;
  767.    key *= 0x66756B65;
  768.    key += chksum;
  769.    n = ( len + 3 ) / 4;   
  770.    pos = 0;
  771.    while ( pos < n )
  772.    {
  773.       if ( pos != 0x10 )
  774.       {
  775.          tkey = key + icq_check_data[ pos & 0xff ];
  776.          temp = Chars_2_DW( &buf[ pos ] );
  777.          temp ^= tkey;
  778.          DW_2_Chars( &buf[ pos ], temp );
  779.       }
  780.       pos += 4;
  781.    }
  782.    Word_2_Chars( &buf[0], ICQ_VER );
  783. }
  784. /***************************************************************
  785. This handles actually sending a packet after it's been assembled.
  786. When V5 is implemented this will wrinkle the packet and calculate 
  787. the checkcode.
  788. Adds packet to the queued messages.
  789. ****************************************************************/
  790. size_t SOCKWRITE( SOK_T sok, void * ptr, size_t len )
  791. {
  792.    struct msg *msg_to_queue;
  793.    WORD cmd;
  794.    Word_2_Chars( &((BYTE *)ptr)[4], 0 );
  795.    ((BYTE *)ptr)[0x0A] = ((BYTE *) ptr)[8];
  796.    ((BYTE *)ptr)[0x0B] = ((BYTE *) ptr)[9];
  797.    cmd = Chars_2_Word( (((ICQ_PAK_PTR)((BYTE*)ptr-2))->cmd ) );
  798.    if ( cmd != CMD_ACK ) {
  799.       msg_to_queue = (struct msg *) malloc(sizeof(struct msg));
  800.       msg_to_queue->seq = Chars_2_Word( &((BYTE *)ptr)[0x0A] );
  801.       msg_to_queue->attempts = 1;
  802.       msg_to_queue->exp_time = time(NULL) + 10;
  803.       msg_to_queue->body = (char *) malloc( len );
  804.       msg_to_queue->len = len;
  805.       memcpy(msg_to_queue->body, ptr, msg_to_queue->len);
  806.       msg_queue_push( msg_to_queue );
  807.       if (msg_queue_peek() == msg_to_queue)
  808.       {
  809.   next_resend = msg_to_queue->exp_time;
  810.       }
  811.    }
  812.    return SOCKWRITE_LOW( sok, ptr, len );
  813. }
  814. /***************************************************************
  815. This handles actually sending a packet after it's been assembled.
  816. When V5 is implemented this will wrinkle the packet and calculate 
  817. the checkcode.
  818. Doesn't add packet to the queue.
  819. ****************************************************************/
  820. static size_t SOCKWRITE_LOW( SOK_T sok, void * ptr, size_t len )
  821. {
  822. #if 1
  823.       if ( Verbose > 1 )
  824.          Hex_Dump( ptr, len );
  825. #endif 
  826.    Wrinkle( ptr, len );
  827. #if 0
  828.       if ( Verbose > 1 )
  829.          Hex_Dump( ptr, len );
  830. #endif 
  831.    return sockwrite( sok, ptr, len );
  832. }
  833. size_t SOCKREAD( SOK_T sok, void * ptr, size_t len )
  834. {
  835.    size_t sz;
  836.    
  837.    sz = sockread( sok, ptr, len );
  838.    if ( ( Verbose > 2 ) && ( sz > 0 ) )
  839.       Hex_Dump( ptr, sz );
  840.    return sz;
  841. }