[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 156
  • Last Modified:

Plain Simple Records (no db stuff)

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
craig_capel
Asked:
craig_capel
  • 9
  • 5
  • 2
  • +4
1 Solution
 
craig_capelAuthor Commented:
oh and guess what, for all those yahoo users, my password <> password :-)
0
 
mhervaisCommented:
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
 
mullet_attackCommented:
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
Take Control of Web Hosting For Your Clients

As a web developer or IT admin, successfully managing multiple client accounts can be challenging. In this webinar we will look at the tools provided by Media Temple and Plesk to make managing your clients’ hosting easier.

 
rwilson032697Commented:
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
 
kretzschmarCommented:
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
 
rwilson032697Commented:
Snap!
0
 
craig_capelAuthor Commented:
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
 
craig_capelAuthor Commented:
Adjusted points from 20 to 30
0
 
craig_capelAuthor Commented:
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
 
kotikCommented:
Hi!

Do you allocate memory for your buffer?
Try this:

GetMem(buffer, sizeOf(yahoo));

Regards,
Kot.
0
 
craig_capelAuthor Commented:
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
 
craig_capelAuthor Commented:
right... i just made a big mistake, i gave out my password, don't worry i have changed all my passwords now hehe :)....
0
 
sburckCommented:
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
 
mullet_attackCommented:
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
 
mullet_attackCommented:
BTW, have look at craig_capel.dat file after running 2nd example.

0
 
mullet_attackCommented:
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
 
craig_capelAuthor Commented:
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
 
mullet_attackCommented:
gee, another typo !

this line :

GetMem(Buffer,sizeof(Yahoo));


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

TextData : PChar;
0
 
craig_capelAuthor Commented:
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
 
craig_capelAuthor Commented:
thanks mullet
0

Featured Post

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

  • 9
  • 5
  • 2
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now