1 /**
2  * VFS driver for curl.
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <ae@cy.md>
12  */
13 
14 module ae.sys.vfs.curl;
15 
16 private:
17 
18 import ae.sys.vfs;
19 
20 import etc.c.curl : CurlOption;
21 import std.net.curl;
22 import std.string;
23 
24 class CurlVFS : VFS
25 {
26 	override void[] read(string path) { return get!(AutoProtocol, ubyte)(path); }
27 	override void write(string path, const(void)[] data) { put!(AutoProtocol, ubyte)(path, cast(ubyte[])data); }
28 	override bool exists(string path)
29 	{
30 		auto proto = path.split("://")[0];
31 		if (proto == "http" || proto == "https")
32 		{
33 			auto http = HTTP(path);
34 			http.method = HTTP.Method.head;
35 			bool ok = false;
36 			http.onReceiveStatusLine = (statusLine) { ok = statusLine.code < 400; };
37 			http.perform();
38 			return ok;
39 		}
40 		else
41 		{
42 			try
43 			{
44 				read(path);
45 				return true;
46 			}
47 			catch (Exception e)
48 				return false;
49 		}
50 	}
51 	override void remove(string path) { del(path); }
52 	override void mkdirRecurse(string path) { assert(false, "Operation not supported"); }
53 
54 	static this()
55 	{
56 		registry["http"] =
57 		registry["https"] =
58 		registry["ftp"] =
59 		registry["ftps"] =
60 		// std.net.curl (artificially) restricts supported protocols to the above
61 		//registry["scp"] =
62 		//registry["sftp"] =
63 		//registry["telnet"] =
64 		//registry["ldap"] =
65 		//registry["ldaps"] =
66 		//registry["dict"] =
67 		//registry["file"] =
68 		//registry["tftp"] =
69 			new CurlVFS();
70 	}
71 }
72 
73 unittest
74 {
75 	if (false)
76 	{
77 		assert( "http://thecybershadow.net/robots.txt".exists);
78 		assert(!"http://thecybershadow.net/nonexistent".exists);
79 	}
80 }