| 
   
ICQ2000 сделай сам 10
  
  
 
 | 
Одиночество - это когда контакт лист icq грохнулся.
 |  
  
Урок №3
 
Запрос информации о клиенте, 
 
Поиск клиентов по различным критериям и др.
 
Итак... Передавать и принимать сообщения уже умеем. На очереди - получение информации о клиентах, которые находятся в списке контактов; а также поиск новых клиентов по различным критериям. Такие запросы к серверу посылаются с помощью все тех же SNAC(15,2). Вспомните, как производится запрос оффлайновых сообщений.
 
Точно также SNAC(15,2) с типом запроса равным D007 применяется: 
 
  - при всех операциях с Инфо клиентов ( и получение, и обновление своего); 
 
  - при поиске клиентов по имени, по UINу, по E-mailу; 
 
  - при изменении пароля; 
 
  - при удалении UINа из реестра ICQ; 
 
  - при многих других операциях. 
 
 
Каждая из перечисленных операций определяется подтипом запроса. Приведу обобщенную таблицу SNAC(15,2) для некоторых запросов:
 
                  
                    
                    
                      | FLAP |  
                    
                      | Command Start | 
                      2A |  
                    
                      | Channel ID | 
                      02 |  
                    
                      | Sequence Number | 
                      XX XX |  
                    
                      | Data Field Length | 
                      XX XX |  
                    
                      
                        
                          
                          
                            
                              
                                
                                
                                | SNAC (15, 
                                02) |  
                                
                                | Family ID | 
                                00 15 |  
                                
                                | SubType ID | 
                                00 02 |  
                                
                                | Flags[0] | 
                                00 |  
                                
                                | Flags[1] | 
                                00 |  
                                
                                | Request ID | 
                                00 XX 00 02 (по 
                                ним можно опознать ответ)  |  
                                
                                
                                
                                
                                
                                
                                
                                
                                
                                | TLV 
                                (1) |  
                                
                                | Type | 
                                00 01 |  
                                
                                | Length | 
                                XX XX  |  
                                
                                | Value | 
                                Length-2
  | 
                                (и что 
                                оно тут делает ?) |  
                                
                                | XX XX XX XX | 
                                наш UIN 
                                 |  
                                
                                | D0 07 | 
                                тип 
                                запроса |  
                                
                                | XX 00 | 
                                cookie  (по 
                                нему можно/нужно опознавать ответ) |  
                                
                                | B2 04 | 
                                подтип 
                                запроса (B204 - запрос инфо 
                                клиента)  |  
                                
                                | 
                                 Это переменная часть 
                                зпроса. Она определяется 
                                подтипом 
                                запроса.
  Например:
  При запросе инфо клиента 
                                (B2 04) 
                                или при поиске клиента по 
                                UINу (1F05) здесь следует 
                                разместить запрашиваемый UIN.
  При поиске клиента по E-mail 
                                (2905) здесь будет помещена строка с 
                                искомым адресом.
  При поиске по NickName, FirstName, 
                                LastName (1505) сюда помещаются 
                                соответственно три стоки. 
                                При смене пароля 
                                (2E04) здесь будет лишь строка с паролем, 
                                а наш UIN сервер и так 
                                знает.
   |   
  |    |   
  |    |   
Теперь к Delphi-проекту добавлены еще два модуля: UInfo и SUser (User Info & Search User).
 
Очередные исходники 3-его урока здесь. Т.к. все рассмотренные више запросы практически однотипные, то приведу комментарии только к одному из них. Это будет поиск по NickName, FirstName, LastName:
 
unit  SUser;
 
 
procedure TSearchUser.META_Search_User(NN,FN,LN : string);
var p : PPack;
    // промежуточный массив.
    // в нем накапливаются данные TLV(1)
    b : TByteArray;
    i : integer;
begin
     if (NN='')and(FN='')and(LN='') then exit;
     EndOfSearch := false;
     // word(b[0]) - тут будет ненужная длина
     // (но ее надо потом корректно заполнить)
     // а пока переходим к 3-у елементу
     i:=2;
     // вписываем UIN (только СВОЙ - укажем явно,что из модуля Main.pas)
     PLONG(@(b[i]))^ := main.UIN;    inc(i,4);
     // ТИП запроса
     PWORD(@(b[i]))^ := swap($D007);   inc(i,2);
     // придумаем себе COOKIE
     // (можно и по-проще, но в настоящей аське
     // COOKIE имеет такой вид XX00)
     Cookie := random($FF) shl 8;
     PWORD(@(b[i]))^ := swap(Cookie); inc(i,2);
     // ПОДТИП запроса
     PWORD(@(b[i]))^ := swap($1505);   inc(i,2);
     // добавляем три текстовые строки (First, Last, Nick)
     // у AOL новый тип строк наверное :)
     // впереди - длина строки, а в конце #0
     // (что-то одно из них убрали бы)
     // длина строки
     PWORD(@(b[i]))^ := length(FN)+1;  inc(i,2);
     // сама строка FirstName
     MOVE(FN[1],b[i],length(FN));     inc(i,Length(FN));
     // завершающий #0
     PBYTE(@(b[i]))^ := 0;             inc(i,1);
     // LastName
     PWORD(@(b[i]))^ := length(LN)+1;  inc(i,2);
     MOVE(LN[1],b[i],length(LN));     inc(i,Length(LN));
     PBYTE(@(b[i]))^ := 0;             inc(i,1);
     // NickName
     PWORD(@(b[i]))^ := length(NN)+1;  inc(i,2);
     MOVE(NN[1],b[i],length(NN));     inc(i,Length(NN));
     PBYTE(@(b[i]))^ := 0;             inc(i,1);
     // дозаполним "ненужную" длину в начале массива
     PWORD(@(b[0]))^ := i-2;
     // создаем FLAP-пакет
     P:=CreatePacket(2,SEQ);
     // добавляем SNAC(15,2)
     SNACAppend(p,$15,$2);
     // добавляем TLV(1) с данными из промежуточного массива
     TLVAppend(p,1,i,@b);
     // шлем запрос
     Form1.PacketSend(p);
     // пишем в Memo
     M(Form1.Memo,'> Search Detail: Nick:'+NN+
                               '   First:'+FN+
                                '   Last:'+LN+'   '+
                                 'Cookie:$'+inttohex(Cookie,4));
end;
 |  
  
Запросы других подтипов передаются аналогично. С небольшими вариациями. Оновременно можем передавать на сервер много запросов. Сервер разберется. Ведь в каждом нашем запросе есть уникальное(ый) Cookie (а также и RequestID в SNAC-заголовке). Сервер пометит свои пакеты-ответы этими же опознавательными знаками. 
 
Я лично делаю проверку(сверку) только по Cookie. Выдавая запрос, запоминаю Cookie. А когда приходит ответ от сервера, то процедура-обработчик SNAC_15_3 просто использует WinAPI функцию PostMessage для передачи ответа окну, которое выдало запрос. В параметрах PostMessage указан Cookie из ответа сервера. Какое окно его опознает - значит тому окну и предназначен ответ.
 
Работа процедуры-обработчика SNAC_15_3 уже ранее рассматривалась. Сейчас она просто дополнена новыми блоками, обрабатывающими новые ответы сервера. Следует упомянуть, что на один (единственный) наш запрос сервер присылает сразу целый массив из SNAC-ответов. Это типичная ситуация. 
 
Например: запрашиваем Инфо о клиенте SNAC(15,2) [подтип запроса B204].
 
В ответ получим сразу восемь SNAC-ответов.
 
Вот их краткие названия-описания: 
 
  - main-home-info 
 
  - homepage-more-info 
 
  - more-email-info 
 
  - additional-info 
 
  - work-info 
 
  - about 
 
  - personal-interests 
 
  - past-background 
 
 
Все полученные данные теперь сохраняются в файле .dat 
 
           |