1 module orelang.operator.CurlOperators;
2 import orelang.operator.IOperator,
3        orelang.Engine,
4        orelang.Value;
5 import std.net.curl;
6 
7 class CurlDownloadOperator : IOperator {
8   /**
9    * call
10    */
11   public Value call(Engine engine, Value[] args) {
12     string url        = engine.eval(args[0]).getString,
13            saveToPath = engine.eval(args[1]).getString;
14 
15     try {
16       download(url, saveToPath);
17 
18       return new Value(true); 
19     } catch(Exception e) {
20       return new Value(false);
21     }
22   }
23 }
24 
25 class CurlUploadOperator : IOperator {
26   /**
27    * call
28    */
29   public Value call(Engine engine, Value[] args) {
30     string loadFromPath = engine.eval(args[0]).getString,
31            url          = engine.eval(args[1]).getString;
32 
33     try {
34       upload(loadFromPath, url);
35 
36       return new Value(true); 
37     } catch(Exception e) {
38       return new Value(false);
39     }
40   }
41 }
42 
43 class CurlGetOperator : IOperator {
44   /**
45    * call
46    */
47   public Value call(Engine engine, Value[] args) {
48     string url = engine.eval(args[0]).getString;
49 
50     try {
51       auto contents = {
52         if (args.length == 2) {
53           auto http = HTTP();
54           Value[string] headers = engine.eval(args[1]).getHashMap;
55 
56           foreach (key, value; headers) {
57             http.addRequestHeader(key, value.getString);
58           }
59 
60           return get(url, http);
61         } else {
62           return get(url);
63         }
64       }();
65       Value[] ret;
66 
67       foreach (elem; contents) {
68         ret ~= new Value(elem);
69       }
70 
71       return new Value(ret);
72     } catch(CurlException e) {
73       return new Value;
74     }
75   }
76 }
77 
78 class CurlGetStringOperator : IOperator {
79   /**
80    * call
81    */
82   public Value call(Engine engine, Value[] args) {
83     CurlGetOperator cgo = new CurlGetOperator;
84     Value[] ret = cgo.call(engine, args).getArray;
85     ubyte[] data;
86     
87     foreach (e; ret) {
88       if (e.type == ValueType.Ubyte) {
89         data ~= e.getUbyte;
90       } else {
91         throw new Exception("Fatal internal error - Invalid typed data was given to curl-get-string");
92       }
93     }
94 
95     return new Value(cast(string)data);
96   }
97 }
98 
99 class CurlPostOperator : IOperator {
100   /**
101    * call
102    */
103   import std.algorithm,
104          std..string,
105          std.array,
106          std.range,
107          std.conv;
108   public Value call(Engine engine, Value[] args) {
109     string url  = engine.eval(args[0]).getString;
110     Value pargs = engine.eval(args[1]);
111 
112     if (pargs.type == ValueType.HashMap) {
113       string[string] params;
114       Value[string] dict = pargs.getHashMap;
115 
116       foreach (key, value; dict) {
117         params[key] = value.getString;
118       }
119 
120       auto contents = {
121         if (args.length == 3) {
122           auto http = HTTP();
123           Value[string] headers = engine.eval(args[2]).getHashMap;
124 
125           foreach (key, value; headers) {
126             http.addRequestHeader(key, value.getString);
127           }
128 
129           return post(url, params.keys.map!(k => k ~ "=" ~ params[k]).join("&"), http);
130         } else {
131           return post(url, params.keys.map!(k => k ~ "=" ~ params[k]).join("&"));
132         }
133       }();
134       Value[] ret;
135 
136       foreach (elem; contents) {
137         ret ~= new Value(elem);
138       }
139 
140       return new Value(ret);
141     } else if (pargs.type == ValueType.Array || (pargs.type == ValueType.ImmediateValue && (pargs.getImmediateValue.value.type == ValueType.Array))) {
142       Value[] array;
143       if (pargs.type == ValueType.Array) {
144         array = pargs.getArray;
145       } else {
146         array = pargs.getImmediateValue.value.getArray;
147       }
148 
149       ubyte[] postData;
150 
151       foreach (value; array) {
152         switch (value.type) with (ValueType) {
153           case Ubyte:
154             postData ~= value.getUbyte;
155             break;
156           case Numeric:
157             postData ~= value.getNumeric.to!ubyte;
158             break;
159           default:
160             throw new Exception("Invalid argument was given to curl-post");
161         }
162       }
163 
164       auto contents = {
165         if (args.length == 3) {
166           auto http = HTTP();
167           Value[string] headers = engine.eval(args[2]).getHashMap;
168 
169           foreach (key, value; headers) {
170             http.addRequestHeader(key, value.getString);
171           }
172 
173           return post(url, postData, http);
174         } else {
175           return post(url, postData);
176         }
177       }();
178       Value[] ret;
179 
180       foreach (elem; contents) {
181         ret ~= new Value(elem);
182       }
183 
184       return new Value(ret);
185     } else if (pargs.type == ValueType.String) {
186       auto contents = {
187         if (args.length == 3) {
188           auto http = HTTP();
189           Value[string] headers = engine.eval(args[2]).getHashMap;
190 
191           foreach (key, value; headers) {
192             http.addRequestHeader(key, value.getString);
193           }
194 
195           return post(url, pargs.getString, http);
196         } else {
197           return post(url, pargs.getString);
198         }
199       }();
200       Value[] ret;
201 
202       foreach (elem; contents) {
203         ret ~= new Value(elem);
204       }
205 
206       return new Value(ret);
207     } else {
208       throw new Exception("Invalid argument was given to curl-post");
209     }
210   }
211 }
212 
213 class CurlPostStringOperator : IOperator {
214   /**
215    * call
216    */
217   public Value call(Engine engine, Value[] args) {
218     CurlPostOperator cpo = new CurlPostOperator;
219     Value[] ret = cpo.call(engine, args).getArray;
220     ubyte[] data;
221     
222     foreach (e; ret) {
223       if (e.type == ValueType.Ubyte) {
224         data ~= e.getUbyte;
225       } else {
226         throw new Exception("Fatal internal error - Invalid typed data was given to curl-post-string");
227       }
228     }
229 
230     return new Value(cast(string)data);
231   }
232 }