Solved

Plain Simple Records (no db stuff)

Posted on 2000-05-07
20
146 Views
Last Modified: 2010-04-04
All i want to know is why is the buffer not being correctly done?...

   type
            yahoo = record
                  ycht:     string; //= YCHT
                  ver:      word; //= 0010
                  login:    word; //= 0001
                  size:     word; //= len(name)  + len(cookie) + len(del1)
                  name:     string; // username
                  cookie:   string;// = cookie
                  del1:     byte; //byr0x01
              end;

var
  craig: yahoo;

username:='craig_capel';
password:='password';
craig.ycht:='YCHT';
craig.ver:=0010;
craig.login:=0001;
craig.size:=length(username)+length(edit1.text)+01;
craig.name:=username;
craig.cookie:=edit1.text;
craig.del1:=01;
// FillChar(buffer, sizeOf(craig),craig);

Move(craig, buffer, sizeof(craig));

problem is, if you look at the buffer at it finishes, it does not put all the
correct data in, does anyone know why?...

Thanks

Craig C.
0
Comment
Question by:craig_capel
  • 9
  • 5
  • 2
  • +4
20 Comments
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
oh and guess what, for all those yahoo users, my password <> password :-)
0
 
LVL 4

Expert Comment

by:mhervais
Comment Utility
I see nothing wrong in this, except maybe problems that could arise with the option parameters you set
(aligned fields and optimization);

but as I am not a specialist of low level functions, maybe somebody else will wee what's wrong
0
 
LVL 2

Expert Comment

by:mullet_attack
Comment Utility
You dont say what 'buffer' is, but I assume it's a Pchar. In this case either will do it.

Move(craig, buffer^, sizeof(craig));
(takes variables as parameters)

MoveMemory(buffer, @craig,sizeof(craig));
(takes pointers as parameters)

Also you should use fixed length strings. In your record, Sizeof(craig) is 19 bytes, regardless of the data content. This because for example ycht:string is stored as a 4 byte pointer. if you specify ycht:string[10] then 10 bytes will be allocated.
0
 
LVL 12

Expert Comment

by:rwilson032697
Comment Utility
How is buffer declared?

You should also be careful of field alignment. Try declaring the record like this:

yahoo = packed record
         ...
        end;

Also, if the string fields are huge strings ($H+ in the compiler options), you mihght get unexpected behaviour doing moves like this.

Cheers,

Raymond.
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
hi craig,

?...

   type
            yahoo = record
                  ycht:     string; //= YCHT
                  ver:      word; //= 0010
                  login:    word; //= 0001
                  size:     word; //= len(name)  + len(cookie) + len(del1)
                  name:     string; // username
                  cookie:   string;// = cookie
                  del1:     byte; //byr0x01
              end;

in your recordstructure the strings has no specific length. does it helps to use pchar instead?

another thing could be that you maust use the packed-keyword in your record-definition like

   type
            yahoo = packed record
             ...

meikl
0
 
LVL 12

Expert Comment

by:rwilson032697
Comment Utility
Snap!
0
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
well i have not done that packed thing yet :)...

nope i am using tclientsocket... so i need to transfer the record into this.... ok, i will try that packed thing now thanks all, don't go away!...

clientsocket1.socket.Send1Buf(buffer,1024);


Craig C.
0
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
Adjusted points from 20 to 30
0
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
y'Ø''a'#13#1#10#0#0#24'§' Is what i got...

and so on, if i do pchar, its all nil in the buffer....

    59 43 : 48 54 00 00 01 00 00 00          YCHT......
 00 01 00 00 00 4A 41 73 : 6B 46 6F 72 42 6F 6F 7A    .....craig_capel
 65 01 76 3D 31 26 6E 3D : 38 6C 35 67 33 33 39 70    e.v=1&n=8l5g339p
 37 6A 30 66 66 26 6C 3D : 37 30 64 36 63 30 64 5F    7j0ff&l=70d6c0d_
 31 65 6A 2F 6F 26 70 3D : 6D 32 63 32 62 38 36 35    1ej/o&p=m2c2b865
 31 30 30 30 32 26 72 : 3D 34 67 26 6C 67 3D 75 73    10002&r=4g&lg=us

Thats what i am aiming for....


see what i am trying to get at now?...

Thanks Again..
0
 
LVL 2

Expert Comment

by:kotik
Comment Utility
Hi!

Do you allocate memory for your buffer?
Try this:

GetMem(buffer, sizeOf(yahoo));

Regards,
Kot.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 2

Author Comment

by:craig_capel
Comment Utility
incompatible types.....

unit yah1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Psock, NMHttp, ScktComp, ExtCtrls;

type
  TForm1 = class(TForm)
    NMHTTP1: TNMHTTP;
    Edit1: TEdit;
    Button1: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    Edit2: TEdit;
    Button2: TButton;
    Memo3: TMemo;
    ClientSocket1: TClientSocket;
    Button3: TButton;
    Label1: TLabel;
    Memo4: TMemo;
    Bevel1: TBevel;
    Label2: TLabel;
    Button4: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure ClientSocket1Connect(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure Button4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

     type
            yahoo = record
                  ycht:     string; //= YCHT
                  ver:      word; //= 0010
                  login:    word; //= 0001
                  size:     word; //= len(name)  + len(cookie) + len(del1)
                  name:     string; // username
                  cookie:   string;// = cookie
                  del1:     byte; //byr0x01
              end;

var
  Form1: TForm1;
  buffer: array [1..1024] of char;
  loginname: string;
  cookie,packetheader: string;
  lencookie: integer;
  password, username: string;
  craig: yahoo;
  num: integer;
  grabrest: boolean;
  tmp,tmp2: string;


implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);

begin
//username:=edit4.text;
//password:=edit5.text;
password:='award4';
username:='craig_capel';

//nmhttp1.get('http://edit.yahoo.com/config/ncclogin?.src=bl&login='+username+'&passwd='+password+'&n=1  Accept: */*'+#10+#10);
nmhttp1.get('http://edit.yahoo.com/config/ncclogin?.src=bl&login='+username+'&passwd='+password+'&n=1 HTTP/1.1'+#10+#10);
  //booker, on some os the top two lines have to be swapped
  //if this does not work on yours swap them arround...
 Memo1.Text := NMHTTP1.Body;
  Memo2.Text := NMHTTP1.header;
//  repeat application.processmessages; until memo2.lines[10]<>'';
//edit3.text:=memo2.lines[10];//
tmp2:='';
grabrest:=false;
 for num:=1 to memo2.Lines.count-1 do
  begin
   tmp:=memo2.lines[num];
    if pos('v=1&n=',tmp)>0 then grabrest:=true;
     if grabrest=true then
      begin
       tmp2:=tmp2+memo2.lines[num];
      end;

    end;
    tmp2:=copy(tmp2,1,pos('=us',tmp2)+2);
  edit1.text:=tmp2;
  lencookie:=length(tmp2);
  cookie:=tmp2;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin

clientsocket1.active:=true;
//clientsocket1.socket.SendBuf(ty,1024);
//clientsocket1.
end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
label1.caption:='connected';
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
username:='craig_capel';
password:='password';
craig.ycht:='YCHT';
craig.ver:=0010;
craig.login:=0001;
craig.size:=length(username)+length(edit1.text)+01;
craig.name:=username;
craig.cookie:=edit1.text;
craig.del1:=01;
     // GetMem(buffer,sizeOf(craig));
// FillChar(buffer, sizeOf(craig),craig);

Move(craig, buffer, sizeof(craig));
end;

end.


ok this is what i have done in total, its not much cos i'm stuck, its using the standard controls with Delphi 4 Prof...

You may have seen yahoo chat clients. IE cheeta chat, Kchat, and a good few others, BUT nobody (i don't think) has wrote a delphi chat client.... Someone whoever, i don't care who, i just want to see Delphi do it.....

http://tenerife1.com/cjc/y1.txt  <<read up on the specifications, on how the protocol works, thats of course if your intrested :-) but think its about time there is one....

Thanks....

Craig C.
0
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
right... i just made a big mistake, i gave out my password, don't worry i have changed all my passwords now hehe :)....
0
 
LVL 3

Expert Comment

by:sburck
Comment Utility
This should work if you are using the ShortString type, but it's iffy if you're using the String type.  First, a quote from the help file:

A ShortString is 0 to 255 characters long. While the length of a ShortString can change dynamically, its memory is a statically allocated 256 bytes; the first byte stores the length of the string, and the remaining 255 bytes are available for characters.

....and another one...

AnsiString, also called a long string, represents a dynamically allocated string whose maximum length is limited only by available memory. It uses 8-bit ANSI characters.
A long-string variable is a pointer occupying four bytes of memory. When the variable is empty—that is, when it contains a zero-length string—the pointer is nil and the string uses no additional storage. When the variable is nonempty, it points to a dynamically allocated block of memory that contains the string value, a 32-bit length indicator, and a 32-bit reference count. This memory is allocated on the heap, but its management is entirely automatic and requires no user code.

Thus, when you do a Move, you copy the contents of the pointer, and not the reference, to your buffer.  If you use ShortString, you'll be OK, otherwise you'll have to copy the record programatically, moving the strings by themselves.
0
 
LVL 2

Expert Comment

by:mullet_attack
Comment Utility
Craig, I already gave you the answer before. You _must_ use short strings in a record, and the 'move' syntax I used works.The code is below.

-------------------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
 yahoo = packed record
        ycht:     string[10]; //= YCHT
        ver:      word; //= 0010
        login:    word; //= 0001
        size:     word; //= len(name)  + len(cookie) + len(del1)
        name:     string[20]; // username
        cookie:   string[20];// = cookie
        del1:     byte; //byr0x01
    end;

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  craig: yahoo;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  Buffer : PChar;
  username,password : string;
  ToF: file;
begin
GetMem(Buffer,sizeof(Yahoo));
username:='craig_capel';
password:='password';
craig.ycht:='YCHT';
craig.ver:=0010;
craig.login:=0001;
craig.size:=length(username)+length(edit1.text)+ 01;
craig.name := username;
craig.cookie:=edit1.text;
craig.del1:=01;
FillChar(buffer^, sizeOf(craig),#0);

Move(craig, buffer^, sizeof(craig));

AssignFile(ToF, 'craig_capel.dat');
Rewrite(ToF, 1);
BlockWrite(ToF, Buffer^, sizeof(craig));
CloseFile(ToF);

end;

end.

-------------------------------------

However, a bigger problem exists. I read the protocol spec, and this bit :

size     = len(name)  + len(cookie) + len(del1)
name     = username


in the login packet requires a variable length field for username. You cannot put all the packet data into record if a field is variable length, because the memory for the record is pre-allocated. Don't try to use a dynamic array of chars instead of string[xx], as this will only store a pointer to the array, not the array data. Your only option here is the build the buffer from each variable . example :

-----------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
 yahoo = packed record
        ycht:     array[0..3] of char; //= YCHT
        ver:      word; //= 0010
        login:    word; //= 0001
        size:     word; //= len(name)  + len(cookie) + len(del1)
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  craig: yahoo;
  Buffer : array of byte;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  username,password : string;
  ToF: file;
  TextData : PChar;
  t : integer;
  BufferPointer : integer;
begin
GetMem(Buffer,sizeof(Yahoo));
username:='craig_capel';
password:='password';
StrPCopy(craig.ycht,'YCHT');
craig.ver:=0010;
craig.login:=0001;
craig.size:=length(username)+length(edit1.text)+ 01;
Setlength(Buffer,sizeof(Craig) + craig.size);
MoveMemory(Buffer, @craig, sizeof(craig));

BufferPointer := sizeof(craig);

for t := 1 to length(username) do
  begin
    Buffer[BufferPointer] := byte(username[t]);
    inc(BufferPointer);
  end;

Buffer[BufferPointer] := 1;
Inc(BufferPointer);

for t := 1 to length(edit1.text) do
  begin
    Buffer[BufferPointer] := byte(edit1.text[t]);
    inc(BufferPointer);
  end;



AssignFile(ToF, 'craig_capel.dat');
Rewrite(ToF, 1);
BlockWrite(ToF, Buffer[0], length(Buffer));
CloseFile(ToF);

end;

end.

-----------------------------

note that I think the x01 delimeter should be between the username and cookie, not after cookie as stated.

Hope this helps.
0
 
LVL 2

Expert Comment

by:mullet_attack
Comment Utility
BTW, have look at craig_capel.dat file after running 2nd example.

0
 
LVL 2

Expert Comment

by:mullet_attack
Comment Utility
oops, reading the spec again, yahoo should be declared as :

yahoo = packed record
        ycht:     array[0..3] of char; //= YCHT
        ver:      longint; //= 0010
        login:    longint; //= 0001
        zeroes:   word;
        size:     word; //= len(name)  + len(cookie) + len(del1)
 
and set zeros := 0;

they are 4 byte values, not 2 as a word is... :-)
0
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
your all way to kind.....

I am supposed to be at work now.... just about to leave house... be back with you in abou 15 mins :-)....

Craig C.
0
 
LVL 2

Accepted Solution

by:
mullet_attack earned 30 total points
Comment Utility
gee, another typo !

this line :

GetMem(Buffer,sizeof(Yahoo));


shouldn't be there. It's a leftover from experiments ...
as is

TextData : PChar;
0
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
sorry guys, i've been ill the past couple of days.... ok, then, i remember now, i went work, someone had broke my computer, developed a bad head, went home ill, two days later here i am :)...


just....


Testing code... hope it works :)
0
 
LVL 2

Author Comment

by:craig_capel
Comment Utility
thanks mullet
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now