Home Handling BabyFTP MKD 250 response with Indy
Reply: 2

Handling BabyFTP MKD 250 response with Indy

Frazz
1#
Frazz Published in 2017-09-13 15:12:40Z

I'm using BabyFTP as an embedded FTP server for a Delphi 10.1 Berlin application. Even though I'm still not sure it's the best lightweight FTP server I can use with my requirements, it seems to be working well enough... except for one detail:

On a successful MKD command, BabyFTP responds with a 250, instead of the expected (by RFC and Indy) 257. Because of this the TIdFTP raises an EIdReplyRFCError exception which breaks the flow of what I'm trying to do (save a blob field to a file):

s := TBytesStream.Create;
Try
  Field.SaveToStream(s);
  MakeDir(TPath.GetDirectoryName(url));
  Put(s, url);
Finally
  s.Free;
End;

Of course, I know I could wrap the MakeDir line in a Try Except block and ignore the specific exception type. But this seems a bit risky as from the raised exception I can't be sure I got a 250 or some other real error.

I've tried looking if Indy's response codes are somehow configurable, but it seems they are hard coded in the specific methods. Subclassing TIdFTP is not feasible as the methods are not virtual. I could customize the IdFTP.pas unit, but I don't want to do that as I'm working in a team and I prefer not having to distribute patches to standard Delphi units.

I could use another FTP server... but I suppose most of them have some not perfectly standard feature like this one.

Does anyone know of other workarounds? Remy?

Remy Lebeau
2#
Remy Lebeau Reply to 2017-09-13 16:15:22Z

Ondrej's answer explains how to address the issue of handling a 250 reply in TIdFTP.MakeDir().

Note that TIdFTP.MakeDir() is just a wrapper for TIdTCPConnection.SendCmd():

procedure TIdFTP.MakeDir(const ADirName: string);
begin
  SendCmd('MKD ' + ADirName, 257); {do not localize}
end;

SendCmd() is public, so an alternative solution would be to call SendCmd() directly and tell it that 250 is an acceptable reply code:

s := TBytesStream.Create;
Try
  Field.SaveToStream(s);
  //MakeDir(TPath.GetDirectoryName(url));
  SendCmd('MKD ' + TPath.GetDirectoryName(url), [250, 257]);
  Put(s, url);
Finally
  s.Free;
End;

Or, to accept any 2xx reply code, you can do this:

s := TBytesStream.Create;
Try
  Field.SaveToStream(s);
  //MakeDir(TPath.GetDirectoryName(url));
  if (SendCmd('MKD ' + TPath.GetDirectoryName(url)) div 100) <> 2 then
    RaiseExceptionForLastCmdResult;
  Put(s, url);
Finally
  s.Free;
End;
Remy Lebeau
3#
Remy Lebeau Reply to 2017-09-13 16:06:54Z

You could handle just the specific case of EIdReplyRFCError when its ErrorCode property equals 250, re-raising in any other case.

s := TBytesStream.Create;
Try
  Field.SaveToStream(s);
  Try
    MakeDir(TPath.GetDirectoryName(url));
  Except
    on E: EIdReplyRFCError do
      if E.ErrorCode <> 250 then raise;
  end
  Put(s, url);
Finally
  s.Free;
End;
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.245451 second(s) , Gzip On .

© 2016 Powered by cudou.com design MATCHINFO