Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
ICQ2000 сделай сам 10


Автор: Alexander Vaga
WEB-сайт: http://icq2000cc.hobi.ru

Одиночество - это когда контакт лист 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

Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay