views:

290

answers:

2

The following code will log in my application to a server. That server will return an authentication token if the login is successful. I need to use that token to query the server for information.

  egressMsg := pchar('email='+LabeledEdit1.text+'&&password='+MaskEdit1.Text+#0);
  egressMsg64 := pchar(Encode64(egressMsg));

  Reserved := 0;

  // open connection
    hInternetConn := InternetOpen('MyApp', INTERNET_OPEN_TYPE_PRECONFIG, NIL, NIL, 0);

  if hInternetConn = NIL then
  begin
    ShowMessage('Error opening internet connection');
    exit;
  end;

  // connect
  hHttpSession := InternetConnect(hInternetConn, 'myserver.com',
    INTERNET_DEFAULT_HTTP_PORT, '', '', INTERNET_SERVICE_HTTP, 0, 0);

  if hHttpSession = NIL then
  begin
    ShowMessage('Error connecting');
    exit;
  end;

  // send request
  hHttpRequest := HttpOpenRequest(hHttpSession, 'POST',
      '/myapp/login', NIL, NIL, NIL, 0, 0);

  if hHttpRequest = NIL then
  begin
    ShowMessage('Error opening request');
    exit;
  end;

  label2.caption := egressMsg64 + '    '+inttostr(length(egressMsg64));
  res := HttpSendRequest(hHttpRequest, Nil,
        DWORD(-1), egressMsg64, length(egressMsg64));

  if not res then
  begin
    ShowMessage('Error sending request ' + inttostr(GetLastError));
    exit;
  end;

  BufferSize := Length(infoBuffer);

  res := HttpQueryInfo(hHttpRequest, HTTP_QUERY_STATUS_CODE, @infoBuffer, BufferSize, Reserved);

  if not res then
  begin
    ShowMessage('Error querrying request ' + inttostr(GetLastError));
    exit;
  end;

  reply := infoBuffer;
  Memo1.Lines.Add(reply);

  if reply <> '200' then
  begin
    //error here
  end;

  // how to I get the token here!!!!

  InternetCloseHandle(hHttpRequest);
  InternetCloseHandle(hHttpSession);        
  InternetCloseHandle(hInternetConn);

How do I get that token? I tried querying the cookie, I tried InternetGetCookie() and a lot more. Code is appreciated

Thanks

jess

EDIT

I found that if you use InternetReadFile you can get that token. However that token comes out as an array of bytes. It's hard to use it later to send it to the server... anyone knows how to convert an array of bytes to pchar or string?

A: 

here it is:

  if not InternetReadFile(hHttpRequest, @token2, sizeof(token2), Reserved2) then
    Memo1.Lines.Add('error = ' + inttostr(GetLastError))
  else
  begin
    for i:=1 to Reserved2 do
      strtoken := strtoken + Chr(token2[i]);

    Memo1.Lines.Add('token = '+strtoken);
    Memo1.Lines.Add('recevied = '+inttostr(Reserved2));
  end;

token2 is an array of bytes.

Jessica
+1  A: 

Shouldn't that be 'Chr(token2[i-1])' for normal zero based arrays?

Alternatively, assuming a non-unicode Delphi, you could use:

SetLength(strtoken, Reserved2);
CopyMemory(@strtoken[1], @token2[0], Reserved2);

NB: This will break in Unicode Delphi unless you declare strtoken as AnsiString
For a Unicode aware Delphi use TEncoding.ASCII.GetString

shunty
from what I found out token2[0] has the size of the array in it, so I am calling for i:=1 to Reserved2 do
Jessica
Fair enough. But I can't help feeling there's an 'off by 1' error lurking in there somewhere. If you're reading Reserved2 bytes then the array can only hold valid values from index [0] to [Reserved2 - 1]. token2[Reserved2] should not contain a useful value and unless the size of token2 is greater than Reserved2 there ought to be a range check error.
shunty
I get an error: "Constant expression violates subrange bounds" and the cursor is placed after @token2[0]
Jessica
Ok, can't explain that I'm afraid. The only InternetReadfile example I've found on my machine is from my TMS library source code which uses your method for copying the token/buffer to string but has 'for i := 0 to Reserved2 - 1 do'...But if it works ok for you then stick with it :-)
shunty