11

I am trying to port my code from Delphi 2007 to Delphi XE (no Update 1 yet). The problem which I have stumbled on is that under Delphi XE I am getting different response from server after sending second GET message.

The message in formated HTML says that my session has expired. However, the same code works without any problems under Delphi 2007 up to this day. I have searched information over the internet and found out that I should use a CookieManager?

The thing is that I am not using any in Delphi 2007 and when I assigned one in Delphi XE the result of my code has not changed. Still I am getting message about expired session.

What else can I try?

Update: I have found some info that Indy 10 has problems with cookies but they were fixed.

I have downloaded snapshot Indy10_4722, unfortunately the error still occurs.

Update 2 - Code provided

So, I've prepared an example code. This is compatibile with both Delphi (2007 and XE). However to compile it under 2007 you need to have GraphicEx library.

The code is connecting to the real server, loads a security image and displays it one the form. Rewrite letters from image to the edit box and close the form. That is all what you need to do to test it.

program IndyTest;

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Contnrs, Menus, ExtCtrls, IdBaseComponent,
  IdComponent, IdTCPConnection, IdTCPClient, IdHTTP,
  {$IFDEF VER220}PngImage{$ELSE}GraphicEx{$ENDIF}, StrUtils;

{$R *.res}

procedure LoadSecurityImage(AImage: TImage; AIdHTTP: TIdHTTP; AImgLink: String);
var
  PNGGraphic: {$IFDEF VER220}TPngImage{$ELSE} TPNGGraphic{$ENDIF};
  ResponseStream: TMemoryStream;
begin
  ResponseStream := TMemoryStream.Create;
  PNGGraphic   := {$IFDEF VER220}TPngImage.Create{$ELSE}TPNGGraphic.Create{$ENDIF};
  try
    AIdHTTP.Get(AImgLink, ResponseStream);
    ResponseStream.Position := 0;
    PNGGraphic.LoadFromStream(ResponseStream);
    AImage.Picture.Assign(PNGGraphic);
  finally
    ResponseStream.Free;
    PNGGraphic.Free;
  end;
end;

function GetImageLink(AIdHTTP: TIdHTTP): String;
var
  WebContentStream: TStringStream;
  Index, Index2: Integer;
begin
  Result := '';
  WebContentStream := TStringStream.Create('');
  try
    AIdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
    AIdHTTP.Get('http://czat.wp.pl/i,1,chat.html', WebContentStream);
    Index := Pos('id="secImg">', WebContentStream.DataString);
    if Index > 0 then
    begin
      Index := PosEx('src="', WebContentStream.DataString, Index) + 5;
      Index2 := PosEx('">', WebContentStream.DataString, Index);
      if Index > 10 then
      begin
        Result := Copy(WebContentStream.DataString, Index, Index2 - Index);
      end;
    end;
  finally
    WebContentStream.Free;
  end;
end;

procedure CheckForContent(const ANick, AImageSeed: String; AIdHTTP: TIdHTTP);
var
  WebContent: TStringStream;
  S: String;
begin
  WebContent := TStringStream.Create('');
  try
    AIdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
    S := 'http://czat.wp.pl/chat.html?i=31179&auth=nie&nick=' + ANick
      + '&regulamin=tak&simg=' + AImageSeed + '&x=39&y=13';
    AIdHTTP.Get(S, WebContent);
    if Pos('<div class="applet">', WebContent.DataString) > 0 then
      ShowMessage('It works properly.')
    else if Pos('<div id="alert">Sesja wygas', WebContent.DataString) > 0 then
      ShowMessage('Session expired')
    else
      ShowMessage('Unknown result.');
  finally
    WebContent.Free;
  end;
end;

var
  LogForm: TForm;
  SecurityImage: TImage;
  Edit: TEdit;
  IdHTTPWp: TIdHTTP;
begin
  Application.Initialize;
  IdHTTPWp := TIdHTTP.Create(Application);
  IdHTTPWp.AllowCookies := True;
  IdHTTPWp.HandleRedirects := True;
  IdHTTPWp.HTTPOptions := [hoForceEncodeParams];

  LogForm := TForm.Create(Application);
  LogForm.Position := poScreenCenter;
  SecurityImage := TImage.Create(LogForm);
  SecurityImage.Parent := LogForm;
  SecurityImage.AutoSize := True;
  Edit := TEdit.Create(LogForm);
  Edit.Parent := LogForm;
  Edit.Top := 64;
  LoadSecurityImage(SecurityImage, IdHTTPWp, GetImageLink(IdHTTPWp));
  LogForm.ShowModal;
  CheckForContent('TestUser', Edit.Text, IdHTTPWp);
  Application.Run;
end.

Update 3

Data packets for Delphi 2007 example are here.

Data packets for Delphi XE example are here.

Free program to analyze packets SmartSniff.

Thanks.

Marko
  • 20,385
  • 13
  • 48
  • 64
Wodzu
  • 6,932
  • 10
  • 65
  • 105
  • Ok I will, but you'd better answer my question mister! ;-) – Wodzu Jan 03 '12 at 17:26
  • 3
    `TIdHTTP` uses an implicit `TIdCookieManager` object internally if you do not provide one yourself. Older snapshots of Indy 10 did have some cookie-related problems, but modern snapshots have a completely re-designed cookie handling system that is based on new cookie RFCs released in 2011, and as far as I know are working correctly for most known systems. If you think you are still having cookie problems, then we need to see the actual cookies, and the associated HTTP request/response traffic surrounding them so we can see when the cookies are, or are not, being sent back to the server. – Remy Lebeau Jan 03 '12 at 22:41
  • Thank you, today I will provide a full working example and full not working example to compare. – Wodzu Jan 04 '12 at 07:49
  • @Wodzu: Relevant RFCs to HTTP State Management Mechanism in chronological order are: [RFC 2109](http://www.rfc-editor.org/rfc/rfc2109.txt) (obsolete), [RFC 2965](http://www.rfc-editor.org/rfc/rfc2965.txt) (obsolete) and finally [RFC 6265](http://www.rfc-editor.org/rfc/rfc6265.txt) released on Aprill 2011. – menjaraz Jan 05 '12 at 03:57
  • Indy 10 used to implement RFCs 2109 and 2965, as well as Netscape's original cookie spec which had no RFC. Now it only implements RFC 6265, which covers everything that most modern systems actually use in the real world. – Remy Lebeau Mar 03 '12 at 19:14
  • Will it be a lot of work for me to include older RFCs implementations to new Indy? – Wodzu Mar 29 '12 at 06:21
  • My session would expire with each request when I connected to a certain server because it expected me to maintain the connection. Once I added `keep-alive` to `TIdHTTP.Request.Connection`, my expired sessions disappeared. Have you tried that yet? – James L. Jun 30 '12 at 06:44
  • @JamesL. thanks for the suggestion. I've checked it out and it did not help. – Wodzu Jul 01 '12 at 08:57

1 Answers1

1

I think you should consider inspecting the request using some tools like httpanalyzer or fiddler.

First use Internet Explorer and see how it does the request.

Then use your app and compare both requests. If it is a cookie problem you will see what is wrong.

Keep-alive is not you answer. It only makes you connection to not be dropped on each request to the same server. See Wikipedia

Rafael Colucci
  • 6,018
  • 4
  • 52
  • 121