?
Solved

Plain Simple Records (no db stuff)

Posted on 2000-05-07
20
Medium Priority
?
154 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 5
  • 2
  • +4
20 Comments
 
LVL 2

Author Comment

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

Expert Comment

by:mhervais
ID: 2786676
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
ID: 2786779
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 12

Expert Comment

by:rwilson032697
ID: 2787007
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
ID: 2787280
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
ID: 2787524
Snap!
0
 
LVL 2

Author Comment

by:craig_capel
ID: 2787926
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
ID: 2787948
Adjusted points from 20 to 30
0
 
LVL 2

Author Comment

by:craig_capel
ID: 2787949
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
ID: 2787966
Hi!

Do you allocate memory for your buffer?
Try this:

GetMem(buffer, sizeOf(yahoo));

Regards,
Kot.
0
 
LVL 2

Author Comment

by:craig_capel
ID: 2788049
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
ID: 2788076
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
ID: 2788855
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
ID: 2790816
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
ID: 2790822
BTW, have look at craig_capel.dat file after running 2nd example.

0
 
LVL 2

Expert Comment

by:mullet_attack
ID: 2790837
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
ID: 2791742
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 90 total points
ID: 2792984
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
ID: 2798220
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
ID: 2800094
thanks mullet
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
Suggested Courses
Course of the Month10 days, 14 hours left to enroll

770 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