BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

idftpserver stream size not working

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Internet Winsock
View previous topic :: View next topic  
Author Message
dvorak.m
Guest





PostPosted: Mon Dec 20, 2004 8:31 pm    Post subject: idftpserver stream size not working Reply with quote



Hi

I use the following code onStoreFile event for IdFtpServer, basically i
want to know before I write the Vstream to disk what is its size (could not
get it to work using tmemorystream), So i thout i could try and check its
size after writing to disk (with tfilestream). this shows a message of 0
whereas 617 bytes were uploaded to the ftp server


procedure TForm1.IdFTPServer1StoreFile(ASender: TIdFTPServerThread;
const AFileName: String; AAppend: Boolean; var VStream: TStream);
begin
VStream := TFileStream.create( translatepath( AFilename,
ASender.HomeDir ) , fmCreate or fmShareExclusive ) ;
showmessage(inttostr(vstream.size));
end;

Anybody with any suggestions ??

thank you


Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Mon Dec 20, 2004 8:48 pm    Post subject: Re: idftpserver stream size not working Reply with quote




"dvorak.m" <mickey (AT) disney (DOT) com> wrote


Quote:
I use the following code onStoreFile event for IdFtpServer,
basically i want to know before I write the Vstream to disk what
is its size

That information is not available in that event because the transfer has not
actually started yet.

Quote:
could not get it to work using tmemorystream), So i thout i could try
and check its size after writing to disk (with tfilestream). this shows a
message of 0 whereas 617 bytes were uploaded to the ftp server

The transfer has not started yet at the time that event is triggered. That
event sets up the TStream that the data will be transfered to, but the
actual transfer does not proceed until after the event handler exits.


Gambit



Back to top
dvorak.m
Guest





PostPosted: Tue Dec 21, 2004 2:23 am    Post subject: Re: idftpserver stream size not working Reply with quote




"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote

Quote:

"dvorak.m" <mickey (AT) disney (DOT) com> wrote in message
news:41c7368f (AT) newsgroups (DOT) borland.com...

That information is not available in that event because the transfer has
not
actually started yet.

The transfer has not started yet at the time that event is triggered.
That
event sets up the TStream that the data will be transfered to, but the
actual transfer does not proceed until after the event handler exits.

Thank you for educating me on this, but where does the actual tranfer take
place, I am trying to limit the directory size for each user with the
ftpserver, so if directory size + current size of stream > some value then
raise an exception. Any help will be greately appreciated

thank you again

Dvorak



Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue Dec 21, 2004 4:08 am    Post subject: Re: idftpserver stream size not working Reply with quote


"dvorak.m" <mickey (AT) disney (DOT) com> wrote


Quote:
Thank you for educating me on this, but where does the
actual tranfer take place

It is handled by TIdFTPServer internally.

Quote:
I am trying to limit the directory size for each user with the ftpserver,
so if directory size + current size of stream > some value then raise
an exception.

The only way to do that during the actual transfer is to write your own
custom TStream class, and perform the checking inside of its overwritten
Write() method. Indy has no provisions for accessing the actual transfer.

The only other possibility is if the client issues an ALLO command prior to
requesting the transfer. In which case, you can check the AThread's
ALLOSize property in the OnStoreFile event, and send back a 452 or 552
respose if needed before the actual transfer takes place.


Gambit



Back to top
dvorak.m
Guest





PostPosted: Tue Dec 21, 2004 6:24 am    Post subject: Re: idftpserver stream size not working Reply with quote


"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote

Quote:

"dvorak.m" <mickey (AT) disney (DOT) com> wrote in message
news:41c7893f (AT) newsgroups (DOT) borland.com...

It is handled by TIdFTPServer internally.

I looked at the source and found it

Quote:
The only way to do that during the actual transfer is to write your own
custom TStream class, and perform the checking inside of its overwritten
Write() method. Indy has no provisions for accessing the actual transfer.

I can write my own TSream class but I think i would have to add it to the

Indy code, otherwise how would it check for the necessary condition ? No way
to do it without actually messign with the Indy code ?

Thank you



Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue Dec 21, 2004 9:49 am    Post subject: Re: idftpserver stream size not working Reply with quote


"dvorak.m" <mickey (AT) disney (DOT) com> wrote


Quote:
I can write my own TSream class but I think i would have to add it
to the Indy code, otherwise how would it check for the necessary
condition ?

As I said earlier, have your TStream class override its inherited Write()
method, and do your checking from there. In the OnStoreFile event, you
instantiate your TStream class and give it to Indy for use. Since you will
be calling the TStream's constructor yourself, you can pass in whatever
conditional data that the TStream will need, such as directory name, size
limit, etc. Then the TStream can handle everything it needs to internally.
For example:

type
TMyFileStream = class(TFileStream)
protected
FDirectory: String;
FErrorReply: TIdRFCReply;
FMaxSize: Longint;
procedure CheckMaxSize(IncomingBytes: Longint);
procedure SetSize(NewSize: Longint); override;
public
constructor Create(const FileName: string; Mode: Word; MaxSize:
Longint; ErrorReply: TIdRFCReply); reintroduce;
function Write(const Buffer; Count: Longint): Longint; override;
end;

constructor TMyFileStream.Create(const FileName: string; Mode: Word;
AMaxSize: Longint; ErrorReply: TIdRFCReply);
begin
FDirectory := ExtractFileDir(FileName);
FErrorReply := ErrorReply;
FMaxSize := MaxSize;
inherited Create(FileName, Mode);
end;

procedure TMyFileStream.CheckMaxSize(IncomingBytes: Longint);
var
LCurrentSize: Longint;
begin
LCurrentSize := get directory size from FDirectory as needed;
if (LCurrentSize + IncomingBytes) > FMaxBytes then begin
FErrorReply.SetReply(552, 'Requested file action aborted.
Exceeded storage allocation.');
raise Exception('');
end;
end;

procedure TMyFileStream.SetSize(NewSize: Longint);
begin
CheckMaxSize(NewSize);
inherited SetSize(NewSize);
end;

function TMyFileStream.Write(const Buffer; Count: Longint): Longint;
begin
CheckMaxSize(Count);
Result := inherited Write(Buffer, Count);
end;


procedure TForm1.IdFTPServer1StoreFile(ASender: TIdFTPServerThread;
const AFileName: String; AAppend: Boolean; var VStream: TStream);
begin
VStream := TMyFileStream.Create(TranslatePath(AFilename,
ASender.HomeDir), fmCreate, MaxSizeAllowedHere, ASender.ErrorReply);
end;

Quote:
No way to do it without actually messign with the Indy code ?

If you do not write your own TStream, then no.

It has already been suggested to Indy's developers for TIdFTPServer to be
extended with additional events so that applications can keep track of the
status of the actual transfer. This will be implemented in a future
release.


Gambit




Back to top
dvorak.m
Guest





PostPosted: Tue Dec 21, 2004 4:43 pm    Post subject: Re: idftpserver stream size not working Reply with quote


"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote

Quote:

As I said earlier, have your TStream class override its inherited Write()
method, and do your checking from there. In the OnStoreFile event, you
instantiate your TStream class and give it to Indy for use. Since you
will
be calling the TStream's constructor yourself, you can pass in whatever
conditional data that the TStream will need, such as directory name, size
limit, etc. Then the TStream can handle everything it needs to
internally.
For example:

Thank you for the example, it works - altho I have a question, if you look
at the code below

procedure TMyFileStream.CheckMaxSize(IncomingBytes: Longint);
var
LCurrentSize: Longint;
begin
LCurrentSize := GetDirSize(FDirectory, true);
if (LCurrentSize + IncomingBytes) > FMaxSize then begin
FErrorReply.SetReply(552,'Requestedfileactionaborted. Exceeded
storage allocation.');
raise Exception.Create('');
end;
end;

what is the purpose of FErrorReply.SetReply() I dont see it in anyway moving
through to the client. The raising of the exception has nothing to do with
what the values of NumericCode and Text are.

Thank you for any insight




Back to top
dvorak.m
Guest





PostPosted: Tue Dec 21, 2004 4:54 pm    Post subject: Re: idftpserver stream size not working Reply with quote


"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote

Quote:

As I said earlier, have your TStream class override its inherited Write()
method, and do your checking from there. In the OnStoreFile event, you
instantiate your TStream class and give it to Indy for use. Since you
will
be calling the TStream's constructor yourself, you can pass in whatever
conditional data that the TStream will need, such as directory name, size
limit, etc. Then the TStream can handle everything it needs to
internally.
For example:

Where would i look to delete the partial file that has been created ?

something like this would be ideal, but something tells me that we are
inside one of the methods of TMyFileStream so it would not be prudent to
attempt to delete the file here

procedure TMyFileStream.CheckMaxSize(IncomingBytes: Longint);
var
LCurrentSize: Longint;
begin
LCurrentSize := GetDirSize(FDirectory, true);
if (LCurrentSize + IncomingBytes) > FMaxSize then begin
try
FErrorReply.SetReply(552,'Requestedfileactionaborted. Exceeded
storage allocation.');
raise Exception.Create('');
except
DeleteFile (....);
end;
end;
end;

thank you again



Back to top
dvorak.m
Guest





PostPosted: Tue Dec 21, 2004 6:05 pm    Post subject: Re: idftpserver stream size not working Reply with quote

"dvorak.m" <mickey (AT) disney (DOT) com> wrote

Quote:
something like this would be ideal, but something tells me that we are
inside one of the methods of TMyFileStream so it would not be prudent to
attempt to delete the file here

I think i figured this one out simply set a local boolean to false in case
of larger than FmaxSize and then in the destructor to delete the file

if (LCurrentSize + IncomingBytes) > FMaxSize then begin
FErrorReply.SetReply(552,'Requestedfileactionaborted. Exceeded
storage allocation.');
FDel := True;
raise Exception.Create('testing');
end;

destructor TMyFileStream.Destroy;
begin
inherited destroy;
if FDel then DeleteFile(FFileName);
end;



Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue Dec 21, 2004 6:20 pm    Post subject: Re: idftpserver stream size not working Reply with quote


"dvorak.m" <mickey (AT) disney (DOT) com> wrote


Quote:
what is the purpose of FErrorReply.SetReply()

It sets the error info that is sent to the client.

Quote:
I dont see it in anyway moving through to the client.

Look in TIdDataChannelThread.Run(). When an exception is thrown during the
transfer, the ErrorReply is sent to the client.

Quote:
The raising of the exception has nothing to do with
what the values of NumericCode and Text are.

The raising of the exception is what triggers TIdDataChannelThread to send
whatever is currently assigned to the ErrorReply.


Gambit



Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue Dec 21, 2004 6:26 pm    Post subject: Re: idftpserver stream size not working Reply with quote


"dvorak.m" <mickey (AT) disney (DOT) com> wrote


Quote:
Where would i look to delete the partial file that has been created ?

Set a flag inside your TStream class before you throw your exception and
then delete the file inside the TStream's destructor. There is no other way
to detect a failed transfer.

Quote:
something like this would be ideal

No, it would not, because you are trapping the exception from ever leaving
the method - defeating the whole purpose of the code.

Quote:
but something tells me that we are inside one of the methods
of TMyFileStream so it would not be prudent to attempt to
delete the file here

You need to close the stream first before you can safely delete the file.
If you need to do that inside of CheckMaxSize(), then you cannot derive from
TFileStream directly, as it provides no way to safely close the file handle
manually from descendant class. You would have to derive from TStream
directly instead and use a separate TFileStream instance internally. Then
you can free the TFileStream whenever you want.


Gambit



Back to top
dvorak.m
Guest





PostPosted: Tue Dec 21, 2004 7:14 pm    Post subject: Re: idftpserver stream size not working Reply with quote


Thank you for the assitance, I follow now how the code works (just an
additional hint, we would need to flush the filestream as it buffers before
writing to disk and that could cause us to exceed the preset limit)

Dvorak


Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue Dec 21, 2004 7:45 pm    Post subject: Re: idftpserver stream size not working Reply with quote


"dvorak.m" <mickey (AT) disney (DOT) com> wrote


Quote:
just an additional hint, we would need to flush the filestream as it
buffers before writing to disk and that could cause us to exceed
the preset limit

If you do not derive from TFileStream, then you can open the file manually
using the Win32 API CreateFile() function directly. Then you can specify
that the file is not to be buffered.


Gambit



Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Internet Winsock All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.