1 /*
2  * Copyright (C) 2020-2021 Bareos GmbH & Co. KG
3  * Copyright (C) 2010 SCALITY SA. All rights reserved.
4  * http://www.scality.com
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  * Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY SCALITY SA ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL SCALITY SA OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * The views and conclusions contained in the software and documentation
30  * are those of the authors and should not be interpreted as representing
31  * official policies, either expressed or implied, of SCALITY SA.
32  *
33  * https://github.com/scality/Droplet
34  */
35 #include "dropletp.h"
36 
37 //#define DPRINTF(fmt,...) fprintf(stderr, fmt, ##__VA_ARGS__)
38 #define DPRINTF(fmt, ...)
39 
dpl_req_free(dpl_req_t * req)40 void dpl_req_free(dpl_req_t* req)
41 {
42   if (NULL != req->host) free(req->host);
43 
44   if (NULL != req->port) free(req->port);
45 
46   if (NULL != req->bucket) free(req->bucket);
47 
48   if (NULL != req->resource) free(req->resource);
49 
50   if (NULL != req->subresource) free(req->subresource);
51 
52   if (NULL != req->cache_control) free(req->cache_control);
53 
54   if (NULL != req->content_disposition) free(req->content_disposition);
55 
56   if (NULL != req->content_encoding) free(req->content_encoding);
57 
58   if (NULL != req->content_type) free(req->content_type);
59 
60   if (NULL != req->metadata) dpl_dict_free(req->metadata);
61 
62   if (NULL != req->src_bucket) free(req->src_bucket);
63 
64   if (NULL != req->src_resource) free(req->src_resource);
65 
66   if (NULL != req->src_subresource) free(req->src_subresource);
67 
68   free(req);
69 }
70 
dpl_req_new(dpl_ctx_t * ctx)71 dpl_req_t* dpl_req_new(dpl_ctx_t* ctx)
72 {
73   dpl_req_t* req = NULL;
74 
75   req = malloc(sizeof(*req));
76   if (NULL == req) goto bad;
77 
78   memset(req, 0, sizeof(*req));
79 
80   req->ctx = ctx;
81 
82   req->metadata = dpl_dict_new(13);
83   if (NULL == req->metadata) goto bad;
84 
85   // virtual hosting is prefered since it "disperses" connections
86   req->behavior_flags = DPL_BEHAVIOR_KEEP_ALIVE | DPL_BEHAVIOR_VIRTUAL_HOSTING;
87 
88   return req;
89 
90 bad:
91 
92   if (NULL != req) dpl_req_free(req);
93 
94   return NULL;
95 }
96 
dpl_req_set_host(dpl_req_t * req,const char * host)97 dpl_status_t dpl_req_set_host(dpl_req_t* req, const char* host)
98 {
99   char* nstr;
100 
101   nstr = strdup(host);
102   if (NULL == nstr) return DPL_ENOMEM;
103 
104   if (NULL != req->host) free(req->host);
105 
106   req->host = nstr;
107 
108   return DPL_SUCCESS;
109 }
110 
dpl_req_set_port(dpl_req_t * req,const char * port)111 dpl_status_t dpl_req_set_port(dpl_req_t* req, const char* port)
112 {
113   char* nstr;
114 
115   nstr = strdup(port);
116   if (NULL == nstr) return DPL_ENOMEM;
117 
118   if (NULL != req->port) free(req->port);
119 
120   req->port = nstr;
121 
122   return DPL_SUCCESS;
123 }
124 
dpl_req_set_method(dpl_req_t * req,dpl_method_t method)125 void dpl_req_set_method(dpl_req_t* req, dpl_method_t method)
126 {
127   req->method = method;
128 }
129 
dpl_req_set_bucket(dpl_req_t * req,const char * bucket)130 dpl_status_t dpl_req_set_bucket(dpl_req_t* req, const char* bucket)
131 {
132   char* nstr;
133 
134   nstr = strdup(bucket);
135   if (NULL == nstr) return DPL_ENOMEM;
136 
137   if (NULL != req->bucket) free(req->bucket);
138 
139   req->bucket = nstr;
140 
141   return DPL_SUCCESS;
142 }
143 
dpl_req_set_resource(dpl_req_t * req,const char * resource)144 dpl_status_t dpl_req_set_resource(dpl_req_t* req, const char* resource)
145 {
146   char* nstr;
147   char npath[DPL_MAXPATHLEN];
148 
149   if (resource == NULL || *resource == '\0' || !strcmp(resource, "/")) {
150     if (!strcmp(req->ctx->base_path, "/")) {
151       if (!req->ctx->preserve_root_path)
152         npath[0] = '\0';
153       else
154         strncpy(npath, resource, sizeof(npath));
155     } else {
156       if (!req->ctx->preserve_root_path)
157         strncpy(npath, req->ctx->base_path, sizeof(npath));
158       else {
159         snprintf(npath, sizeof(npath), "%s%s", req->ctx->base_path, resource);
160       }
161     }
162   } else {
163     if (!strcmp(req->ctx->base_path, "/"))
164       snprintf(npath, sizeof(npath), "%s", resource);
165     else
166       snprintf(npath, sizeof(npath), "%s/%s", req->ctx->base_path, resource);
167   }
168 
169   nstr = strdup(npath);
170   if (NULL == nstr) return DPL_ENOMEM;
171 
172   if (NULL != req->resource) free(req->resource);
173 
174   req->resource = nstr;
175   return DPL_SUCCESS;
176 }
177 
dpl_req_set_subresource(dpl_req_t * req,const char * subresource)178 dpl_status_t dpl_req_set_subresource(dpl_req_t* req, const char* subresource)
179 {
180   char* nstr;
181 
182   nstr = strdup(subresource);
183   if (NULL == nstr) return DPL_ENOMEM;
184 
185   if (NULL != req->subresource) free(req->subresource);
186 
187   req->subresource = nstr;
188 
189   return DPL_SUCCESS;
190 }
191 
dpl_req_add_subresource(dpl_req_t * req,const char * subresource)192 dpl_status_t dpl_req_add_subresource(dpl_req_t* req, const char* subresource)
193 {
194   char* tmp = NULL;
195 
196   if (!req->subresource) return dpl_req_set_subresource(req, subresource);
197 
198   tmp = realloc(req->subresource,
199                 strlen(req->subresource) + strlen(subresource) + 2);
200   if (!tmp) return DPL_ENOMEM;
201 
202   tmp = strcat(tmp, ";");
203   tmp = strcat(tmp, subresource);
204   req->subresource = tmp;
205 
206   return DPL_SUCCESS;
207 }
208 
dpl_req_add_behavior(dpl_req_t * req,unsigned int flags)209 void dpl_req_add_behavior(dpl_req_t* req, unsigned int flags)
210 {
211   req->behavior_flags |= flags;
212 }
213 
dpl_req_rm_behavior(dpl_req_t * req,unsigned int flags)214 void dpl_req_rm_behavior(dpl_req_t* req, unsigned int flags)
215 {
216   req->behavior_flags &= ~flags;
217 }
218 
dpl_req_set_location_constraint(dpl_req_t * req,dpl_location_constraint_t location_constraint)219 void dpl_req_set_location_constraint(
220     dpl_req_t* req,
221     dpl_location_constraint_t location_constraint)
222 {
223   req->location_constraint = location_constraint;
224 }
225 
dpl_req_set_canned_acl(dpl_req_t * req,dpl_canned_acl_t canned_acl)226 void dpl_req_set_canned_acl(dpl_req_t* req, dpl_canned_acl_t canned_acl)
227 {
228   req->canned_acl = canned_acl;
229 }
230 
dpl_req_set_storage_class(dpl_req_t * req,dpl_storage_class_t storage_class)231 void dpl_req_set_storage_class(dpl_req_t* req,
232                                dpl_storage_class_t storage_class)
233 {
234   req->storage_class = storage_class;
235 }
236 
dpl_req_set_condition(dpl_req_t * req,const dpl_condition_t * condition)237 void dpl_req_set_condition(dpl_req_t* req, const dpl_condition_t* condition)
238 {
239   req->condition = *condition;
240 }
241 
dpl_req_set_cache_control(dpl_req_t * req,const char * cache_control)242 dpl_status_t dpl_req_set_cache_control(dpl_req_t* req,
243                                        const char* cache_control)
244 {
245   char* nstr;
246 
247   nstr = strdup(cache_control);
248   if (NULL == nstr) return DPL_ENOMEM;
249 
250   if (NULL != req->cache_control) free(req->cache_control);
251 
252   req->cache_control = nstr;
253 
254   return DPL_SUCCESS;
255 }
256 
dpl_req_set_content_disposition(dpl_req_t * req,const char * content_disposition)257 dpl_status_t dpl_req_set_content_disposition(dpl_req_t* req,
258                                              const char* content_disposition)
259 {
260   char* nstr;
261 
262   nstr = strdup(content_disposition);
263   if (NULL == nstr) return DPL_ENOMEM;
264 
265   if (NULL != req->content_disposition) free(req->content_disposition);
266 
267   req->content_disposition = nstr;
268 
269   return DPL_SUCCESS;
270 }
271 
dpl_req_set_content_encoding(dpl_req_t * req,const char * content_encoding)272 dpl_status_t dpl_req_set_content_encoding(dpl_req_t* req,
273                                           const char* content_encoding)
274 {
275   char* nstr;
276 
277   nstr = strdup(content_encoding);
278   if (NULL == nstr) return DPL_ENOMEM;
279 
280   if (NULL != req->content_encoding) free(req->content_encoding);
281 
282   req->content_encoding = nstr;
283 
284   return DPL_SUCCESS;
285 }
286 
dpl_req_set_data(dpl_req_t * req,const char * data_buf,u_int data_len)287 void dpl_req_set_data(dpl_req_t* req, const char* data_buf, u_int data_len)
288 {
289   req->data_buf = data_buf;
290   req->data_len = data_len;
291   req->data_enabled = 1;
292 }
293 
dpl_req_add_metadatum(dpl_req_t * req,const char * key,const char * value)294 dpl_status_t dpl_req_add_metadatum(dpl_req_t* req,
295                                    const char* key,
296                                    const char* value)
297 {
298   return dpl_dict_add(req->metadata, key, value, 0);
299 }
300 
dpl_req_add_metadata(dpl_req_t * req,const dpl_dict_t * metadata)301 dpl_status_t dpl_req_add_metadata(dpl_req_t* req, const dpl_dict_t* metadata)
302 {
303   int ret;
304 
305   ret = dpl_dict_copy(req->metadata, metadata);
306   if (DPL_SUCCESS != ret) { return DPL_FAILURE; }
307 
308   return DPL_SUCCESS;
309 }
310 
dpl_req_set_content_type(dpl_req_t * req,const char * content_type)311 dpl_status_t dpl_req_set_content_type(dpl_req_t* req, const char* content_type)
312 {
313   char* nstr;
314 
315   nstr = strdup(content_type);
316   if (NULL == nstr) return DPL_ENOMEM;
317 
318   if (NULL != req->content_type) free(req->content_type);
319 
320   req->content_type = nstr;
321 
322   return DPL_SUCCESS;
323 }
324 
dpl_req_set_object_type(dpl_req_t * req,dpl_ftype_t object_type)325 dpl_status_t dpl_req_set_object_type(dpl_req_t* req, dpl_ftype_t object_type)
326 {
327   req->object_type = object_type;
328 
329   return DPL_SUCCESS;
330 }
331 
dpl_req_add_range(dpl_req_t * req,uint64_t start,uint64_t end)332 dpl_status_t dpl_req_add_range(dpl_req_t* req, uint64_t start, uint64_t end)
333 {
334   req->range.start = start;
335   req->range.end = end;
336   req->range_enabled = 1;
337 
338   return DPL_SUCCESS;
339 }
340 
dpl_req_set_expires(dpl_req_t * req,time_t expires)341 void dpl_req_set_expires(dpl_req_t* req, time_t expires)
342 {
343   req->expires = expires;
344 }
345 
dpl_req_set_src_bucket(dpl_req_t * req,const char * src_bucket)346 dpl_status_t dpl_req_set_src_bucket(dpl_req_t* req, const char* src_bucket)
347 {
348   char* nstr;
349 
350   nstr = strdup(src_bucket);
351   if (NULL == nstr) return DPL_ENOMEM;
352 
353   if (NULL != req->src_bucket) free(req->src_bucket);
354 
355   req->src_bucket = nstr;
356 
357   return DPL_SUCCESS;
358 }
359 
dpl_req_set_src_resource_ext(dpl_req_t * req,const char * src_resource,int add_base_path)360 dpl_status_t dpl_req_set_src_resource_ext(dpl_req_t* req,
361                                           const char* src_resource,
362                                           int add_base_path)
363 {
364   char* nstr;
365   char npath[DPL_MAXPATHLEN];
366 
367   if (add_base_path) {
368     if (!strcmp(req->ctx->base_path, "/"))
369       snprintf(npath, sizeof(npath), "%s", src_resource);
370     else
371       snprintf(npath, sizeof(npath), "%s/%s", req->ctx->base_path,
372                src_resource);
373   } else
374     snprintf(npath, sizeof(npath), "%s", src_resource);
375 
376   nstr = strdup(npath);
377   if (NULL == nstr) return DPL_ENOMEM;
378 
379   if (NULL != req->src_resource) free(req->src_resource);
380 
381   req->src_resource = nstr;
382 
383   return DPL_SUCCESS;
384 }
385 
dpl_req_set_src_resource(dpl_req_t * req,const char * src_resource)386 dpl_status_t dpl_req_set_src_resource(dpl_req_t* req, const char* src_resource)
387 {
388   return dpl_req_set_src_resource_ext(req, src_resource, 1);
389 }
390 
dpl_req_set_src_subresource(dpl_req_t * req,const char * src_subresource)391 dpl_status_t dpl_req_set_src_subresource(dpl_req_t* req,
392                                          const char* src_subresource)
393 {
394   char* nstr;
395   nstr = strdup(src_subresource);
396   if (NULL == nstr) return DPL_ENOMEM;
397 
398   if (NULL != req->src_subresource) free(req->src_subresource);
399 
400   req->src_subresource = nstr;
401 
402   return DPL_SUCCESS;
403 }
404 
dpl_req_set_copy_directive(dpl_req_t * req,dpl_copy_directive_t copy_directive)405 void dpl_req_set_copy_directive(dpl_req_t* req,
406                                 dpl_copy_directive_t copy_directive)
407 {
408   req->copy_directive = copy_directive;
409 }
410 
dpl_req_set_copy_source_condition(dpl_req_t * req,const dpl_condition_t * condition)411 void dpl_req_set_copy_source_condition(dpl_req_t* req,
412                                        const dpl_condition_t* condition)
413 {
414   req->copy_source_condition = *condition;
415 }
416