Антикапча [Delphi]

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by GlooK, 30 Oct 2009.

  1. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    Возникла проблемка при реализации антикапчи...
    Не знаю в каком типе переменной хранить мусор пикчи :).

    Использую такую фанкшин:
    Code:
    function fWSRecv(wHost, wRequest: string):string;
    var
    wsData: TWSAData;
    hHost: PHostEnt;
    hAddr: TSockAddrIn;
    hTimeout: TTimeVal;
    iRead: integer;
    hData: string;
    hBuffer: array[0..buffsize] of char;
    begin
     WSAStartup($202, wsData);
     hSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     hHost := gethostbyname(PChar(wHost));
     hAddr.sin_family := AF_INET;
     hAddr.sin_port := htons(80);
     hAddr.sin_addr := pinaddr(hHost^.h_addr^)^;
     hTimeout.tv_usec := 0;
     hTimeout.tv_sec := mstimeout;
     setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, @hTimeout, sizeof(ttimeval));
     connect(hSocket, hAddr, SizeOf(hAddr));
     hData := '';
     Send(hSocket, wRequest[1], length(wRequest), 0);
     while (TRUE) do
     begin
      FillChar(hBuffer, SizeOf(hBuffer), 0);
      iRead := Recv(hSocket, hBuffer, length(hBuffer), 0);
      hData := hData + copy(hBuffer, 0, iRead);
      if (iRead <= 0) then break;
     end;
     CloseSocket(hSocket);
     WSACleanup;
     result := hData;
    end;
    
    Она естественно не подходит под пикчи, т.к. возвращает string, а в ней теряется мусор, т.к. он содержит нуль символы.
    Какой тип данных использовать в result?

    P.S. Со стрингами я работал через strpos, delete, copy.
    Нужно чтобы их тоже можно было юзать или укажите аналогичные замены.

    На antigate.com пример смотрел.
    IdMultipartFormData - в своей лайт версии delphi не обнаружил.
    Да и не люблю я инди...

    Вообще то странно, что нет единой темы про антикапчу. Или я криво смотрел...
     
  2. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    как вариант, выделяй память, туда закидывай данные и возвращай указатель на эту память. А там уже как угодно можешь юзать эту память, главное потом не забыть прибить её
     
  3. 0rs

    0rs Member

    Joined:
    30 Dec 2008
    Messages:
    70
    Likes Received:
    23
    Reputations:
    3
    Вроде в string нуль символы не должны теряться потому что строка не завершается нуль символом, а перед ней указывается длина. Кроме того в hData будет не только картинка, но и заголовок ответа сервера. А length(hBuffer) случайно не 0?
    А вообще я выкладывал пример на дельфи для антикапчи /thread151622.html, правда там используется сторонняя dll.
     
    #3 0rs, 30 Oct 2009
    Last edited: 30 Oct 2009
  4. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    Составил в блокноте... куча ошибок наверное. Боюсь проверять даже на валидность :)
    Code:
    [B]type
    BArray := array[0..buffsize] of char;
    var
    hBuffer: ^BArray;
    numcap: integer = 1;[/B]
    
    function fWSRecv(wHost, wRequest: string):[B]pointer;[/B]
    var
    wsData: TWSAData;
    hHost: PHostEnt;
    hAddr: TSockAddrIn;
    hTimeout: TTimeVal;
    iRead: integer;
    hData: string;
    begin
     WSAStartup($202, wsData);
     hSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     hHost := gethostbyname(PChar(wHost));
     hAddr.sin_family := AF_INET;
     hAddr.sin_port := htons(80);
     hAddr.sin_addr := pinaddr(hHost^.h_addr^)^;
     hTimeout.tv_usec := 0;
     hTimeout.tv_sec := mstimeout;
     setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, @hTimeout, sizeof(ttimeval));
     connect(hSocket, hAddr, SizeOf(hAddr));
     hData := '';
     Send(hSocket, wRequest[1], length(wRequest), 0);
     [B]GetMem(hBuffer, numcap * SizeOf(hBuffer));
     FillChar(hBuffer, SizeOf(hBuffer), 0);[/B]
     while (TRUE) do
     begin
      iRead := Recv(hSocket, [B]hBuffer[numcap]^[/B], length(hBuffer), 0);
      [B]ReallocMem(hBuffer, numcap * SizeOf(hBuffer));
      inc(numcap);[/B]
      if (iRead <= 0) then break;
     end;
     CloseSocket(hSocket);
     WSACleanup;
     result := hBuffer;
    [B] FreeMem(hBuffer);[/B]
    end;
    
    Похоже на правду?

    Лучше SizeOf использовать?
    Пример, кста, полезный... спс.
     
  5. sidapas23

    sidapas23 New Member

    Joined:
    13 Nov 2010
    Messages:
    88
    Likes Received:
    2
    Reputations:
    -3
    дайте полноценныйй код и инструкции как сделать антикапчу пожалуйста
     
  6. 1n0y

    1n0y Active Member

    Joined:
    9 May 2009
    Messages:
    272
    Likes Received:
    276
    Reputations:
    2
    http://antigate.com/delphi.zip

    http://antigate.com/panel.php?action=api
     
  7. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    GlooK, зачем тебе делать на сокетах, если ты задаешь подобные вотпросы, то может воспользоваться Indy? TIdMultiPartFormDataStream - есть обычный TStream, его можно заменить на TMemoryStream и туда запихнуть нужные данные, эффект будет тот же. Ниже приведу код, идея которого как у slesh'a

    А по теме :
    1.
    Code:
    WSAStartup($202, wsData);
    Вызывается только один раз.
    2.
    Code:
     result := hBuffer;
     FreeMem(hBuffer);
    Как думаешь, что будет когда после вызова своей функции обратишься по возвращаемому адресу?
    3. Сделать можно вот так :
    t
    Code:
    ype
       TMemAndSize = reocrd
         Mem : Pointer;
         Size : Cardinal;
        end;
    function fWSRecv(wHost, wRequest: string):TMemAndSize;
    var
      hHost: PHostEnt; 
      hAddr: TSockAddrIn;
      hTimeout: TTimeVal;
      iRead : integer;
      buffer : array[0..2047] of Byte;
    begin
       Result.Mem := nil;
       Result.Size := 0;
       hSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
       hHost := gethostbyname(PChar(wHost));
       hAddr.sin_family := AF_INET;
       hAddr.sin_port := htons(80);
       hAddr.sin_addr := pinaddr(hHost^.h_addr^)^;
       hTimeout.tv_usec := 0;
       hTimeout.tv_sec := mstimeout;
       setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, @hTimeout, sizeof(ttimeval));
       connect(hSocket, hAddr, SizeOf(hAddr)); {тут нужно проверить результат}
       Send(hSocket, wRequest[1], length(wRequest), 0); {Проверить результат}
       repeat  
          iRead := Recv(hSocket, buffer[0], 2048);
          if iRead <= 0 then Break;
          Inc(Result.Count, iRead);
          if not Assigned(Result.Mem) then
            GetMem(Result.Mem, Result.Count) else
          Begin
                ReallocMem(Result.Mem, Result.Count);
                Move(buffer[0], PByte(Pointer(Result.Count))^, iRead);
          end;
       until false;
       CloseSocket(hSocket);
    end;
    
    {Вспомогательная функция}
    function fWSRecvStr(wHost, wRequest: string):String;
    Var tmp : TMemAndSize;
    Begin
       Result := '';
       try
         tmp := fWSRecv(wHost, wRequest);
       finally
         if Assigned(tmp.Mem) then
         Begin
           SetLength(Result, tmp.Size);
           if tmp.Size > 0 then
              Move(PByte(Result.Mem)^, Result[1], tmp.Size);
           FreeMem(tmp.Mem); {Заметим, что теперь мы освобождаем то что создала fWSRecv}
         end;
       end;
    end;
    {код инициализации/финализации модуля}
    var
      wsData: TWSAData;
    initialization
      WSAStartup($202, wsData);
    finalization
      WSACleanup;
    end. 
    Могут быть ошибки, т.к. писал в браузере. Хочу так же отметить что освобождение памяти должны делать мы, а не автоматом та функция, которая выделила, причем если указатель не равен Null.
     
    #7 Jingo Bo, 11 Dec 2010
    Last edited: 11 Dec 2010