Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

FTPConnection

Moderators: kris

Posted: 12/28/07 13:36:14

I believe this could be useful addition to FTPConnection (especially FtpAddress?)

FtpAddress?("ftp://me:password@myftp.com:21") breaks down the address to components...

and few convenience functions for FTPConnection. Plus it could accept FtpAddress? (or just string) in the constructor and in connect.

struct FtpAddress
{
	static FtpAddress* opCall(char[] str)
	{
		if(str.length==0) return null;
		try
		{
			auto ret=new FtpAddress;
			//remove ftp://
			auto i=locatePattern(str,"ftp://");
			if(i==0) str=str[6..$];

			//check for username and/or password user[:pass]@
			i=locatePrior(str,'@');
			if(i!=str.length)
			{
				char[] up=str[0..i];
				str=str[i+1..$];
				i=locate(up,':');
				if(i!=up.length)
				{
					ret.user=up[0..i];
					ret.pass=up[i+1..$];
				}
				else ret.user=up;
			}

			//check for port
			i=locatePrior(str,':');
			if(i!=str.length)
			{
				ret.port=cast(uint)Int.toLong(str[i+1..$]);
				str=str[0..i];
			}

			//check any directories after the adress
			i=locate(str,'/');
			if(i!=str.length) ret.directory=str[i+1..$];

			//the rest should be the address
			ret.address=str[0..i];
			if(ret.address.length==0) return null;

			return ret;

		}catch(Object o) {return null;}
	}

	char[] address;
	char[] directory;
	char[] user;
	char[] pass;
	uint port=21;
}

class FTPConnection2 : FTPConnection
{
	this(){super();}

	int exist(char[] file)
	{
		try
		{
			auto fi=getFileInfo(file);
			if(fi.type==FtpFileType.file) return 1;
			else if(fi.type==FtpFileType.dir || fi.type==FtpFileType.cdir || fi.type==FtpFileType.pdir) return 2;
		}
		catch(FTPException o) {if(o.response_code!="501") throw o;}
		return 0;
	}

	Time* modified(char[] file)
	{
		try return &getFileInfo(file).modify;
		catch(FTPException o) {if(o.response_code!="501") throw o;}
		return null;
	}

	long size(char[] file)
	{
		try return getFileInfo(file).size;
		catch(FTPException o) {if(o.response_code!="501") throw o;}
		return -1;
	}
}
Author Message

Posted: 12/28/07 22:18:12

Does your code work right out of the box and a couple of copy and pastes will fix this into FtpClient?. If so let me know and I will add them to the standard FtpConnection? class. Thanks for the suggestions and I would like for you to try my new FtpClient?. I shortened the timeout time to 2.5 seconds so hopefully(if a ftp server can reply in that much timeout time) this will half your close time. If you have any Idea about how much time a ftp server needs to reply(if shorter than 2.5 seconds) let me know and I will set that to the standard timeout time.

Thanks for your suggestions and your continued feedback,

Lester L. Martin II

Posted: 12/28/07 22:20:57

oh and your user and pass fields will be automatically signed user = "anonymous"; pass = "anonymous@anonymous;

that way you aren't required to fill in the user and pass unless you really have one.

Should of been in my last post,

Lester L. Martin II

Posted: 12/29/07 09:34:38

Yes, it works. At least I am using it in this form... Note that FtpAddress?.opCall is not throwing anything. It returns null on error (as well as the other functions), because it is not very practical to type try/catch around each function to check for errors. I don't know about the reply time. I have very fast connection to my server, it just never responds to the close so I always have to wait for the timeout. I can provide you with username/password for testing if you need. I will write more on this topic later, as I am currently trying to fix a bug with the modified time (I suspect it has something to do with the gregorian calendar, but it is affecting the FtpClient? too).

Posted: 12/29/07 10:05:57

Ok, it was not the calendar. The "modified" function above was misbehaving. Here is a fixed one. Hope it works now. If you want to test the ftp client on my server to see why the "close" is acting like that mail me at bobef at abv dot bg and will provide you with username/password.

Time* modified(char[] file)
	{
		auto ret=new Time;
		try
		{
			*ret=filemtime(file);
			return ret;
		}
		catch(FTPException o)
		{
			if(o.response_code!="501") try
			{
				*ret=getFileInfo(file).modify;
				return ret;
			}
			catch(FTPException o) {if(o.response_code!="501") throw o;}
		}
		return null;
	}

Posted: 12/29/07 10:27:36 -- Modified: 12/29/07 10:29:58 by
lmartin92

Have to make note of stuff here before I forget. I added comments to the file where it is your code. //descrition; contributed by Bobef

Thankyou and soon an email will come,

Lester L. Martin II

Posted: 02/17/08 06:56:12

BTW, the Uri class should be able to correctly parse (and construct) those FTP urls

Posted: 02/23/08 14:36:27

The naming of this tango.net.Uri class is inconsistent. The setter/getters have set/get prefix which is unusual for Tango, I think.

Posted: 02/23/08 19:08:07

Yes, quite right. We've been dragging our feet in fixing that, since it would break a bunch of stuff :(