Search code examples
delphiindy

Delphi Indy login and download a file


Problem is that i cant download a file (cause im not logged). I can login, but nothing more. Delphi version: XE2, Indy version: 10.5.8.0 (also tested on Delphi XE4 with newest Indy). There is one cookie with 1970r date. Thanks for help.

Code: (login and password are real)

var
  IdHTTP: TIdHTTP;
  Request: TStringList;
  Response: TMemoryStream;
  File: TMemoryStream;
begin
  try
    Response := TMemoryStream.Create;
    try
      Request := TStringList.Create;
      try
        Request.Add('user[login]=1212test1212');
        Request.Add('user[password]=test1212');
        IdHTTP := TIdHTTP.Create;
        File := TMemoryStream.Create;
        try
          IdHTTP.AllowCookies := True;
          IdHTTP.CookieManager:=Form1.IdCookieManager1;
          IdHTTP.HandleRedirects := True;
          IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
          IdHTTP.Post('http://www.twitch.tv/login', Request, Response);
          IdHTTP.Get('http://www.twitch.tv/broadcast/fmle3_config',File);
          File.SaveToFile('C:\aaa.xml');
        finally
          IdHTTP.Free;
          MS.Free;
        end;
      finally
        Request.Free;
      end;
    finally
      Response.Free;
    end;
  except
    on E: Exception do
      ShowMessage(E.Message);
  end;
end;

HTTP Analyzer Logs:

(Status-Line):HTTP/1.1 302 Moved Temporarily
Cache-Control:no-cache, no-store, must-revalidate
Pragma:no-cache
Set-Cookie:feature_bucket=83; domain=.twitch.tv; path=/
Set-Cookie:name=1212test1212; domain=.twitch.tv; path=/; expires=Tue, 06-Aug-2013 19:20:52 GMT
Set-Cookie:_twitch_session_id=16d9fc8368fe22701324c7ce39c9f668; domain=.twitch.tv; path=/; expires=Wed, 24-Jul-2013 07:20:52 GMT; HttpOnly
Set-Cookie:unique_id=a5b16cf36861154f9dd118e673fd4aa0; domain=.twitch.tv; path=/
Set-Cookie:persistent=46516706_1212test1212_35ptd94szs8ysrpfcckrcx21t; domain=.twitch.tv; path=/; expires=Tue, 06-Aug-2013 19:20:52 GMT; HttpOnly
Set-Cookie:login=1212test1212; domain=.twitch.tv; path=/; expires=Tue, 06-Aug-2013 19:20:52 GMT
Set-Cookie:last_login=Tue+Jul+23+19%3A20%3A52+UTC+2013; domain=.twitch.tv; path=/; expires=Tue, 06-Aug-2013 19:20:52 GMT
Set-Cookie:language=en; domain=.twitch.tv; path=/; expires=Sat, 23-Jul-2033 19:20:52 GMT
Set-Cookie:api_token=daa32f51e6d015daf9c7a1949d1ef9e0; domain=.twitch.tv; path=/; expires=Tue, 06-Aug-2013 19:20:52 GMT
Content-Length:144
Content-Type:text/html
Location:http://www.twitch.tv/
Server:nginx
Front-End-Https:off
P3P:CP="CAO PSA OUR"
status:302 Found
x-geo:PL
x-rack-cache:invalidate, pass
x-request-id:a829998aa94c51788ec9b504656639f3
x-runtime:0.272887
x-ua-compatible:IE=Edge,chrome=1
Date:Tue, 23 Jul 2013 19:20:52 GMT
Connection:close

(Status-Line):HTTP/1.1 200 OK
Cache-Control:no-cache, no-store, must-revalidate
Pragma:no-cache
Set-Cookie:_twitch_session_id=860dc07ccd1dd937f1cb6adfc84a7f14; domain=.twitch.tv; path=/; expires=Wed, 24-Jul-2013 07:20:53 GMT; HttpOnly
Set-Cookie:persistent=; domain=.twitch.tv; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT
Content-Length:59850
Content-Type:text/html; charset=utf-8
Server:nginx
Front-End-Https:off
status:200 OK
x-geo:PL
x-rack-cache:invalidate, pass
x-request-id:2557352c302a3eddfe9080882aaa3028
x-runtime:0.301446
x-ua-compatible:IE=Edge,chrome=1
Date:Tue, 23 Jul 2013 19:20:53 GMT
Connection:close

(Status-Line):HTTP/1.1 302 Moved Temporarily
Cache-Control:must-revalidate, no-cache, no-store, private
Pragma:no-cache
Set-Cookie:_twitch_session_id=860dc07ccd1dd937f1cb6adfc84a7f14; domain=.twitch.tv; path=/; expires=Wed, 24-Jul-2013 07:20:54 GMT; HttpOnly
Content-Length:150
Content-Type:text/html
Location:http://www.twitch.tv/signup
Server:nginx
Front-End-Https:off
status:302 Found
x-geo:PL
x-rack-cache:miss
x-request-id:b35e5b998a633b80cfb1f53373e5627a
x-runtime:0.029409
X-UA-Compatible:IE=Edge,chrome=1
Date:Tue, 23 Jul 2013 19:20:54 GMT
Connection:keep-alive

http://img197.imageshack.us/img197/7007/xgyf.jpg


Solution

  • You are not logging in to the correct URL. http://www.twitch.tv/login is just the HTML login form that users fill out in their web browser and then submit to the real login URL, which is https://secure.twitch.tv/user/login instead. If you look at the HTML for that login form, you would see that, as well as several hidden form fields that you need to submit but are not currently submitting.

    Also, because the actual login URL is using HTTPS, you need to attach an SSL IOHandler to TIdHTTP, such as TIdSSLIOHandlerSocketOpenSSL.

    And to complicate things, the required authenticity_token value is dynamically generated when http://www.twitch.tv/login is requested, so you need to first download the HTML for the login form, manually parse out the token value, and then finish the login submission.

    Try this:

    var
      IdHTTP: TIdHTTP;
      IdSSL: TIdSSLIOHandlerSocketOpenSSL;
      HTML, AuthToken: string;
      Request: TStringList;
      File: TMemoryStream;
    begin
      try
        IdHTTP := TIdHTTP.Create;
        try
          IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
          IdHTTP.IOHandler := IdSSL;
    
          IdHTTP.AllowCookies := True;
          IdHTTP.CookieManager := Form1.IdCookieManager1;
          IdHTTP.HandleRedirects := True;
    
          HTML := IdHTTP.Get('http://www.twitch.tv/login');
          AuthToken := ...; // parse the HTML to extract the authenticity_token value...
    
          Request := TStringList.Create;
          try
            Request.Add('utf8=✓');
            Request.Add('authenticity_token=' + AuthToken);
            Request.Add('redirect_on_login=http://www.twitch.tv/');
            Request.Add('embed_form=false');
            Request.Add('user[login]=1212test1212');
            Request.Add('user[password]=test1212');
    
            IdHTTP.Post('https://secure.twitch.tv/user/login', Request, nil, IndyTextEncoding_UTF8);
          finally
            Request.Free;
          end;
    
          File := TMemoryStream.Create;
          try
            IdHTTP.Get('http://www.twitch.tv/broadcast/fmle3_config', File);
            File.SaveToFile('C:\aaa.xml');
          finally
            File.Free;
          end;
        finally
          IdHTTP.Free;
        end;
      except
        on E: Exception do
          ShowMessage(E.Message);
      end;
    end;
    

    With that said, because the login form performs a redirect to a specified URL when the login is successful, you might try this slightly shorter approach to avoid one roundtrip:

    var
      IdHTTP: TIdHTTP;
      IdSSL: TIdSSLIOHandlerSocketOpenSSL;
      HTML, AuthToken: string;
      Request: TStringList;
      File: TMemoryStream;
    begin
      try
        IdHTTP := TIdHTTP.Create;
        try
          IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
          IdHTTP.IOHandler := IdSSL;
    
          IdHTTP.AllowCookies := True;
          IdHTTP.CookieManager := Form1.IdCookieManager1;
          IdHTTP.HandleRedirects := True;
    
          HTML := IdHTTP.Get('http://www.twitch.tv/login');
          AuthToken := ...; // parse the HTML to extract the authenticity_token value...
    
          Request := TStringList.Create;
          try
            Request.Add('utf8=✓');
            Request.Add('authenticity_token=' + AuthToken);
            Request.Add('redirect_on_login=http://www.twitch.tv/broadcast/fmle3_config');
            Request.Add('embed_form=false');
            Request.Add('user[login]=1212test1212');
            Request.Add('user[password]=test1212');
    
            File := TMemoryStream.Create;
            try
              IdHTTP.Post('https://secure.twitch.tv/user/login', Request, File, IndyTextEncoding_UTF8);
              File.SaveToFile('C:\aaa.xml');
            finally
              File.Free;
            end;
          finally
            Request.Free;
          end;
        finally
          IdHTTP.Free;
        end;
      except
        on E: Exception do
          ShowMessage(E.Message);
      end;
    end;