Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Problem using TIdFTP in C++ Builder 2007. List() doesn't work

844 views
Skip to first unread message

Star

unread,
Jul 20, 2007, 3:11:22 PM7/20/07
to
Hi,

I wrote a project in C++ Builder 5 a long time ago that
was using TIdFTP from Indy. Now I have updated to C++ Builder 2007
which already comes with Indy but for some reason it's not working
correctly.

The problem is very simple. If I have this piece of code:

IdFTP1->Username = "anonymous";
IdFTP1->Password = "te...@test.com";
IdFTP1->Host = "ftp.borland.com";
IdFTP1->Port = 21;

IdFTP1->Connect();

IdFTP1->List( NULL, "", true);
for(int i = 0; i < IdFTP1->DirectoryListing->Count; ++i)
{

}

For some reason, IdFTP1->DirectoryListing->Count is always 0.
However, this code works ok in my old version of Indy.

What am I missing?

Thanks

Remy Lebeau (TeamB)

unread,
Jul 20, 2007, 3:46:18 PM7/20/07
to

"Star" <noe...@noemail.com> wrote in message
news:46a108f5$1...@newsgroups.borland.com...

> For some reason, IdFTP1->DirectoryListing->Count is always 0.

Please read the Indy 10 documentation. This issue is covered in the
DirectoryListing topic.

The formatting of FTP listings in the LIST and NLST commands are not
standardized at all. Servers are free to use whatever they want. There are
new drafts that introduce additional commands that have standardized
formats, but not all servers support them yet. As such, there are dozens of
formats used online today.

In Indy 9, the DirectoryListing supported only a few hard-coded formats that
were commonly used.

In Indy 10, the DirectoryListing was completely redesigned to use a plugin
system now. Indy 10 has several dozen parser plugins available, but none of
them are enabled by default. That is why the Count is always 0 -
DirectoryListing doesn't know how the parse the data. You have to include
the appropriate IdFTPListParse...hpp header files for the specific parser(s)
that you want to use. Or alternatively include the IdAllFTPListParsers.hpp
header file to enable them all.


Gambit


Star

unread,
Jul 20, 2007, 4:07:25 PM7/20/07
to

wow... thanks a lot, Remy. I'm surprised how it works now. I think they
should have made that differently. I think it would be easier if you
could specify the parser by code instead of adding header files...

Anyway, I have tried it but still doesn't work.

This is my whole test project:

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "IdAllFTPListParsers.hpp"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "IdExplicitTLSClientServerBase"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
IdFTP1->Username = "anonymous";
IdFTP1->Password = "fsjk...@fsjfsdj.com";


IdFTP1->Host = "ftp.borland.com";
IdFTP1->Port = 21;

IdFTP1->AutoLogin = true;

IdFTP1->Connect();

IdFTP1->List( NULL, "", true);

for(int i = 0; i < IdFTP1->DirectoryListing->Count; ++i)
{

}

}


Do you think I am missing something?

I'm using C++ Builder 2007, which comes with Indy 10.1.5

Thanks

Remy Lebeau (TeamB)

unread,
Jul 20, 2007, 8:40:54 PM7/20/07
to

"Star" <noe...@noemail.com> wrote in message
news:46a11619$1...@newsgroups.borland.com...

> I think it would be easier if you could specify the
> parser by code instead of adding header files...

Well, that is what happens when you use a header file - you are specifying
in code what you want to use.

You can do dynamic registrations if you want. There are
RegisterFTPListParser() and UnRegisterFTPListParser() functions implemented
in the IdFTPListParseBase unit.

> Anyway, I have tried it but still doesn't work.

You haven't said what is not actually working. So I am assuming that the
Count is still returning 0? If so, then either the parsers are not being
registered correctly at program startup, or else you are simply retreiving a
listing that there is no parser available for.

> void __fastcall TForm1::FormCreate(TObject *Sender)

DO NOT use the OnCreate event in C++! It is a Delphi idiom that can produce
illegal behavior in C++, as it ican be triggered before the constructor in
run. Use the actual constructor instead, or else wait until after the form
is fully constructed.


Gambit


Star

unread,
Jul 23, 2007, 10:43:04 AM7/23/07
to
>> I think it would be easier if you could specify the
>> parser by code instead of adding header files...
>
> Well, that is what happens when you use a header file - you are specifying
> in code what you want to use.

I just think it's not very intuitive. It would be easier to have a
property where you can specify the list of parsers that you are
insterested instead of having big list of header files included in your
project.


> You haven't said what is not actually working. So I am assuming that the
> Count is still returning 0? If so, then either the parsers are not being
> registered correctly at program startup, or else you are simply retreiving a
> listing that there is no parser available for.

Yes, the count is 0. I don't know what else to try. It seems pretty
straightforward. You saw my code. There is nothing else. In that example
I'm retrieving data from the borland site. I would be surprised that
there is not a parser for that.

>> void __fastcall TForm1::FormCreate(TObject *Sender)
>
> DO NOT use the OnCreate event in C++! It is a Delphi idiom that can produce
> illegal behavior in C++, as it ican be triggered before the constructor in
> run. Use the actual constructor instead, or else wait until after the form
> is fully constructed.

Ok, I put my code in a different place but still doesn't work.


Thanks for your help.

Remy Lebeau (TeamB)

unread,
Jul 23, 2007, 1:14:29 PM7/23/07
to

"Star" <noe...@noemail.com> wrote in message
news:46a4bea5$1...@newsgroups.borland.com...

> I just think it's not very intuitive. It would be easier to have
> a property where you can specify the list of parsers that
> you are insterested instead of having big list of header files
> included in your project.

That would require a lot of runtime overhead to initialize things that the
app may or may not actually use. With the header file approach, you are
specifying what you are actually interested in.

> Yes, the count is 0. I don't know what else to try. It seems
> pretty straightforward. You saw my code. There is nothing else.
> In that example I'm retrieving data from the borland site. I
> would be surprised that there is not a parser for that.

Like I said, there are only two possibilities for that. Have you tried
stepping through the parsing code yet to find out where the failure point
is? Did you try looking at the raw listing data that the server is actually
sending back?


Gambit


Star

unread,
Jul 24, 2007, 3:30:10 PM7/24/07
to

> That would require a lot of runtime overhead to initialize things that the
> app may or may not actually use. With the header file approach, you are
> specifying what you are actually interested in.

I don't know about you, but If I write an FTP client, I want this client
to work with any type of ftp servers. I don't really know where this ftp
client is going to connect to. The ftp server that the client is
connecting should be transparent to the final user.
If we use your approach, every time I find out my client stops working,
I have to recompile my project after adding the right header and send
the new version to our customers... Who wants to do that?


With Indy 9 everything worked great. No wonder when I check the
newsgroups there is so many people trying to use 9 instead of 10.

By the way, it seems that I'm not the only one who thinks that adding
header files is not very intuitive. Even the developers say that in the
documentation!


> Like I said, there are only two possibilities for that. Have you tried
> stepping through the parsing code yet to find out where the failure point
> is? Did you try looking at the raw listing data that the server is actually
> sending back?

If I use IdFTP1->ListResult->Count I get the data correctly. The count
is 2 and I get these 2 lines:

drwxr-xr-x 2 0 0 4096 Jun 27 20:45 downloads
drwxr-xr-x 22 0 0 4096 Jun 27 20:25 pub

However, IdFTP1->DirectoryListing->Count is always 0.


Don't you have Indy 10 on your computer? Could you just test the code
that I posted here?

Just in case, here is my full source code again:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "IdAllFTPListParsers.hpp"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "IdExplicitTLSClientServerBase"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{

IdFTP1->Username = "anonymous";
IdFTP1->Password = "te...@test.com";


IdFTP1->Host = "ftp.borland.com";
IdFTP1->Port = 21;

IdFTP1->Connect();

IdFTP1->List( NULL, "", true);

for(int i = 0; i < IdFTP1->ListResult->Count; ++i)
{
AnsiString pp = IdFTP1->ListResult->Strings[i];
}

for(int i = 0; i < IdFTP1->DirectoryListing->Count; ++i)
{

}
}

Thanks

Star

unread,
Jul 24, 2007, 4:40:14 PM7/24/07
to

> I have never seen the Indy documentation say anything like that.

http://www.indyproject.org/KB/Downloads%5CIndyKB.pdf

Section 16.2

Remy Lebeau (TeamB)

unread,
Jul 24, 2007, 4:01:21 PM7/24/07
to

"Star" <noe...@noemail.com> wrote in message
news:46a65374$1...@newsgroups.borland.com...

> If we use your approach, every time I find out my client stops
> working, I have to recompile my project after adding the right
> header and send the new version to our customers... Who wants
> to do that?

You would have to do that anyway. If you enable all of the available
parsers (which you are doing now) and it still isn't able to handle a
particular server, then you'd have to recompile when you implement a new
parser that can handle that server.

> With Indy 9 everything worked great.

Not as great as you think. Indy 9 couldn't handle most of the formats that
are actually used in the world. That is why the new plugin system was
introduced into TIdFTP in Indy 10 to begin with.

> By the way, it seems that I'm not the only one who thinks that
> adding header files is not very intuitive. Even the developers say
> that in the documentation!

I have never seen the Indy documentation say anything like that.

> If I use IdFTP1->ListResult->Count I get the data correctly.


> The count is 2 and I get these 2 lines:
>
> drwxr-xr-x 2 0 0 4096 Jun 27 20:45 downloads
> drwxr-xr-x 22 0 0 4096 Jun 27 20:25 pub
>
> However, IdFTP1->DirectoryListing->Count is always 0.

Then you don't have a suitable parser registered correctly. In this case,
that would be the TIdFTPLPUnix class in the IdFTPListParseUnix unit. Which
would suggest that your project is not linking in that unit, since
TIdFTPLPUnix is registered when the unit is initialized.

> Don't you have Indy 10 on your computer?

Yes, but it is not in a usable state right now because I am doing a lot of
changes in it for the next release in the near future.

> Could you just test the code that I posted here?

No, I cannot.


Gambit


Star

unread,
Aug 24, 2007, 5:57:28 AM8/24/07
to
Just in case somebody has this problem, I finally found the solution.

Unfortunately it wasn't as simple as Remy said (just adding the right
.hpp header in your file), and I had to do the following:

1. Go to the Indy website and download the Indy 10 package.
2. Find the file IdAllFTPListParsers.pas and add it to your project
(this file doesn't come with C++ Builder 2007 by default)
3. Go to the properties of your file and add this to the Include Path
and Library Path:

C:\Program Files\CodeGear\RAD Studio\5.0\lib\Indy10


And that's it. Now IdFTP1->DirectoryListing->Count will not return 0.

Hope it helps.

Remy Lebeau (TeamB)

unread,
Aug 24, 2007, 1:37:16 PM8/24/07
to

"Star" <noe...@noemail.com> wrote in message
news:46ceab8d$1...@newsgroups.borland.com...

> Unfortunately it wasn't as simple as Remy said (just adding
> the right .hpp header in your file)

That is a known issue that hasn't been addressed yet.


Gambit


0 new messages