Line data Source code
1 : /*
2 : cJSON_deploy.c
3 : Created by Danny Goossen, Gioxa Ltd on 11/2/17.
4 :
5 : MIT License
6 :
7 : Copyright (c) 2017 deployctl, Gioxa Ltd.
8 :
9 : Permission is hereby granted, free of charge, to any person obtaining a copy
10 : of this software and associated documentation files (the "Software"), to deal
11 : in the Software without restriction, including without limitation the rights
12 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 : copies of the Software, and to permit persons to whom the Software is
14 : furnished to do so, subject to the following conditions:
15 :
16 : The above copyright notice and this permission notice shall be included in all
17 : copies or substantial portions of the Software.
18 :
19 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 : SOFTWARE.
26 :
27 : */
28 : /*! \cJSON_deploy.c
29 : * \brief cJSON extensions
30 : * \author Danny Goossen
31 : * \date 11/2/17
32 : * \copyright (c) 2017 Danny Goossen. All rights reserved.
33 : */
34 : #include "deployd.h"
35 :
36 0 : void cJSON_AddTimeStampToObject(cJSON * object,const char *key)
37 : {
38 0 : if(!object || !key) return;
39 : struct tm *tm_gmt;
40 : time_t t;
41 0 : t = time(NULL);
42 0 : tm_gmt = gmtime(&t);
43 : char date_buffer[36];
44 0 : strftime(date_buffer, 36, "%Y-%m-%dT%H:%M:%S.000000000Z", tm_gmt);
45 :
46 0 : if (cJSON_GetObjectItem(object,key))
47 0 : cJSON_ReplaceItemInObject(object, key, cJSON_CreateString(date_buffer));
48 : else
49 0 : cJSON_AddStringToObject(object,key,date_buffer);
50 : }
51 :
52 :
53 : // dupplicate a string from a non null terminated string
54 68 : char* cJSON_strdup_n(const unsigned char * str, size_t n)
55 : {
56 68 : size_t len = 0;
57 68 : char *copy = NULL;
58 :
59 68 : if (str == NULL)
60 : {
61 : return NULL;
62 : }
63 :
64 68 : len = n + 1;
65 68 : if (!(copy = (char *)calloc(len,1)))
66 : {
67 : return NULL;
68 : }
69 68 : memcpy(copy, str, len);
70 68 : copy[n]=0;
71 68 : return copy;
72 : }
73 :
74 : // add item to object with a key derived from a non 0 terminated string
75 0 : void cJSON_AddItemToObject_n(cJSON *object, const char *string,size_t n , cJSON *item)
76 : {
77 0 : if (!item)
78 : {
79 0 : return;
80 : }
81 :
82 : /* free old key and set new one */
83 0 : if (item->string)
84 : {
85 0 : free(item->string);
86 : }
87 0 : item->string = (char*)cJSON_strdup_n((const unsigned char*)string,n);
88 0 : cJSON_AddItemToArray(object,item);
89 : }
90 :
91 : // create a string object from a non null terminated string
92 0 : cJSON *cJSON_CreateString_n(const char *string, size_t n)
93 : {
94 0 : cJSON *item = cJSON_CreateObject();
95 0 : if(item)
96 : {
97 0 : item->type = cJSON_String;
98 0 : item->valuestring = (char*)cJSON_strdup_n((const unsigned char*)string, n);
99 0 : if(!item->valuestring)
100 : {
101 0 : cJSON_Delete(item);
102 0 : return NULL;
103 : }
104 : }
105 :
106 0 : return item;
107 : }
108 :
109 :
110 : /* insert item at the beginning of the array/object. */
111 9 : void cJSON_AddItemToBeginArray(cJSON *array, cJSON *item)
112 : {
113 9 : if (!array) return;
114 9 : cJSON *c = array->child;
115 9 : if (!item)
116 : {
117 : return;
118 : }
119 9 : if (!c)
120 : {
121 : /* list is empty, start new one */
122 3 : array->child = item;
123 : }
124 : else
125 : {
126 6 : array->child=item;
127 6 : item->next=c;
128 6 : c->prev=item;
129 : }
130 : }
131 :
132 : // create an JSON tree from **envp
133 : // but only for environment vars starting with : CI_, GITLAB_ or DEPLOY_
134 0 : cJSON * cJSON_Create_env_obj(char** envp)
135 : {
136 0 : cJSON *environment = cJSON_CreateObject();
137 : char** env;
138 0 : for (env = envp; *env != 0; env++)
139 : {
140 0 : char* thisEnv = *env;
141 : //printf("thisenv: %s\n", thisEnv);
142 0 : char * e=thisEnv;
143 0 : int len=(int)strlen(thisEnv);
144 0 : int pos = 0;
145 0 : while (*e++ != '=' && pos < len) pos++;
146 : //if (pos != len && pos >1)
147 : {
148 : //if (strncmp(thisEnv,"CI_",3)==0 || \
149 : // ( pos >8 && strncmp(thisEnv,"DEPLOY_",7)==0 )|| \
150 : // ( pos>7 && strncmp(thisEnv,"GITLAB",6)==0) ) \
151 :
152 : {
153 0 : cJSON_AddItemToObject_n(environment, thisEnv, pos, cJSON_CreateString(thisEnv+pos+1));
154 : }
155 : }
156 : }
157 0 : return environment;
158 : }
159 :
160 :
161 0 : void cJSON_append_env_obj_from_dkr_Env(cJSON**target,const cJSON * dkr_env)
162 : {
163 0 : if (!target || !dkr_env) return ;
164 0 : if (!*target) *target= cJSON_CreateObject();
165 0 : cJSON * item=NULL;
166 0 : cJSON_ArrayForEach(item, dkr_env)
167 : {
168 0 : const char* thisEnv = item->valuestring;
169 0 : if (thisEnv && strlen(thisEnv)>0)
170 : {
171 : //printf("thisenv: %s\n", thisEnv);
172 0 : const char * e=thisEnv;
173 0 : int len=(int)strlen(thisEnv);
174 0 : int pos = 0;
175 0 : while (*e++ != '=' && pos < len) pos++;
176 : {
177 0 : cJSON_AddItemToObject_n(*target, thisEnv, pos, cJSON_CreateString(thisEnv+pos+1));
178 : }
179 : }
180 : }
181 : return;
182 : }
183 :
184 :
185 : // compaire a string value of a key, check if present and compaire
186 : // returns 0 if match
187 0 : int validate_key(const cJSON * item, const char * key,const char * value )
188 : {
189 0 : if (!key || !item) return -2;
190 0 : if (item->type==cJSON_String && !value) return -1;
191 0 : const cJSON * tmp_json=cJSON_GetObjectItem(item, key );
192 0 : if (tmp_json)
193 : {
194 0 : if (tmp_json->valuestring && value)
195 0 : return(strcmp(value,tmp_json->valuestring)); // return 0 on equal string
196 0 : else if (!value && !tmp_json->valuestring)
197 : return 0; // NULL==NULL
198 : else
199 0 : return -1;
200 : }
201 : else
202 : {
203 :
204 : return(-1);
205 : //else return 0; // no item == no value
206 : }
207 : }
208 :
209 : // get a key valuestring but check if exist
210 : // return NULL on non exist
211 0 : int get_key(const cJSON * item, const char * key,char ** value )
212 : {
213 :
214 0 : if (!key) return -2;
215 0 : cJSON * tmp_json=cJSON_GetObjectItem(item, key );
216 0 : if (tmp_json)
217 : {
218 0 : if (value) *value=tmp_json->valuestring;
219 : return (0);
220 : }
221 : else
222 : {
223 : return(-1);
224 : }
225 : }
226 :
227 : // parse the JSON env-tree to an **envp
228 0 : int parse_env(cJSON * env_json, char *** newevpp)
229 : {
230 : int i;
231 : size_t len;
232 0 : int array_size = cJSON_GetArraySize(env_json);
233 0 : *newevpp=calloc(sizeof(char *), array_size+1);
234 0 : char**walk=*newevpp;
235 0 : for (i = 0; i < array_size; i++)
236 : {
237 0 : cJSON *subitem = cJSON_GetArrayItem(env_json, i);
238 0 : if (cJSON_IsString(subitem))
239 : {
240 0 : len=strlen(subitem->string)+1+strlen(subitem->valuestring) +1;
241 0 : *walk=calloc(1, len);
242 0 : sprintf(*walk, "%s=%s",subitem->string,subitem->valuestring);
243 : // printf("%s\n",*walk);
244 : }
245 0 : walk++;
246 : }
247 0 : return (0);
248 : }
249 :
250 : // cleanup of env created with : int parse_env(cJSON * env_json, char *** newevpp)
251 0 : void free_envp(char *** envp)
252 : {
253 0 : char ** walk = *envp;
254 0 : while (*walk)
255 : {
256 0 : if (*walk) free(*walk);
257 0 : *walk=NULL;
258 0 : walk ++;
259 : }
260 0 : free(*envp);
261 0 : *envp=NULL;
262 0 : }
263 :
264 :
265 : // check if item is present in json string array
266 0 : int in_string_array(const cJSON * json_list, char * search)
267 : {
268 0 : if (!json_list || json_list->type==cJSON_NULL || json_list->type==cJSON_Invalid) return -3;
269 0 : if (!search) return 0;
270 :
271 0 : cJSON * pos=NULL;
272 0 : int found=0;
273 0 : cJSON_ArrayForEach(pos,json_list)
274 : {
275 0 : if (pos->valuestring && strcmp(search,pos->valuestring)==0)
276 : {
277 : found =1;
278 : break;
279 : }
280 : }
281 0 : return !found;
282 : }
283 :
284 : // check if list of keys is present in JSON structure
285 0 : int check_presence(cJSON * env_json, char ** list, char ** error_msg)
286 : {
287 0 : if (!env_json) return -1;
288 0 : if (!list) return 0;
289 : char** item;
290 : int result=0;
291 0 : for (item = list; *item != NULL; item++)
292 : {
293 0 : if(!cJSON_GetObjectItem(env_json, *item))
294 : {
295 0 : result++;
296 0 : if (error_msg&&*error_msg) asprintf(error_msg, "\nERROR: Missing \"%s\"\n",*item);
297 : }
298 : }
299 : return result;
300 : }
301 :
302 : // get's the object->valuestring of key
303 : // return NULL on non exiting
304 : // return a null terminated string,
305 : // caller should not freeit, points to string in object
306 17 : const char * cJSON_get_key(const cJSON * item, const char * key)
307 : {
308 17 : if (!item || !key ) return NULL;
309 17 : const char * result=NULL;
310 17 : cJSON * thisitem=cJSON_GetObjectItem(item, key);
311 17 : if (thisitem) result=thisitem->valuestring;
312 17 : return result;
313 : }
314 0 : char * cJSON_get_stringvalue_as_var(const cJSON * item, const char * key)
315 : {
316 0 : if (!item || !key ) return NULL;
317 0 : char * result=NULL;
318 0 : cJSON * thisitem=cJSON_GetObjectItem(item, key);
319 0 : if (thisitem) result=thisitem->valuestring;
320 0 : return result;
321 : }
322 :
323 0 : char * cJSON_get_stringvalue_dup(const cJSON * item, const char * key)
324 : {
325 0 : if (!item || !key ) return NULL;
326 0 : char * result=NULL;
327 0 : cJSON * thisitem=cJSON_GetObjectItem(item, key);
328 0 : if (thisitem && thisitem->valuestring) result=strdup(thisitem->valuestring);
329 0 : return result;
330 : }
331 :
332 0 : int cJSON_safe_IsTrue(const cJSON *object,char * key)
333 : {
334 0 : if (!object) return 0;
335 0 : cJSON * tp=cJSON_GetObjectItem(object,key );
336 0 : if (tp) return cJSON_IsTrue(tp);
337 : else return 0;
338 : }
339 :
340 0 : int cJSON_safe_IsFalse(const cJSON *object,char * key)
341 : {
342 0 : if (!object) return 0;
343 0 : cJSON * tp=cJSON_GetObjectItem(object,key );
344 0 : if (tp) return cJSON_IsFalse(tp);
345 : else return 0;
346 : }
347 :
348 :
349 0 : int32_t cJSON_safe_GetNumber(const cJSON *object,char * key)
350 : {
351 0 : if (!object)
352 : return INT32_MAX;
353 0 : cJSON * tp=cJSON_GetObjectItem(object,key );
354 0 : if (tp && cJSON_IsNumber(tp))
355 0 : return tp->valueint;
356 : else
357 : return INT32_MAX;
358 : }
359 :
360 :
361 :
362 :
363 5 : void cJSON_add_string(cJSON * target,const char * key,const char * value)
364 : {
365 5 : if (value)
366 : {
367 5 : if (cJSON_GetObjectItem(target,key))
368 0 : cJSON_ReplaceItemInObject(target,key,cJSON_CreateString( value));
369 : else
370 5 : cJSON_AddStringToObject(target,key,value);
371 : }
372 5 : return;
373 : }
374 :
375 0 : void cJSON_add_string_n(cJSON * target,const char * key,const char * value,size_t len)
376 : {
377 0 : if (value)
378 : {
379 0 : if (cJSON_GetObjectItem(target,key))
380 0 : cJSON_ReplaceItemInObject(target,key,cJSON_CreateString_n( value,len));
381 : else
382 0 : cJSON_AddStringToObject_n(target,key,value,len);
383 : }
384 0 : return;
385 : }
386 :
387 :
388 0 : void cJSON_add_string_v(cJSON * target,const char * key,const char * content,...)
389 : {
390 0 : char * value=CSPRINTF(content);
391 0 : if (value)
392 : {
393 0 : if (cJSON_GetObjectItem(target,key))
394 0 : cJSON_ReplaceItemInObject(target,key,cJSON_CreateString( value));
395 : else
396 0 : cJSON_AddStringToObject(target,key,value);
397 0 : free(value);
398 : }
399 0 : return;
400 : }
401 :
402 0 : void cJSON_add_string_from_object(cJSON * target,const char * newkey,const cJSON * env_vars,const char * key)
403 : {
404 0 : const char * value=cJSON_get_key(env_vars,key );
405 0 : if (value)
406 : {
407 0 : if (cJSON_GetObjectItem(target,newkey))
408 0 : cJSON_ReplaceItemInObject(target,newkey,cJSON_CreateString( value));
409 : else
410 0 : cJSON_AddStringToObject(target,newkey,value);
411 : }
412 0 : return;
413 : }
414 :
415 7 : void cJSON_add_Array_string(cJSON * target,const char * value)
416 : {
417 7 : if (value)
418 : {
419 7 : cJSON_AddItemToArray(target, cJSON_CreateString(value));
420 : }
421 7 : return;
422 : }
423 :
424 :
425 0 : void cJSON_add_Array_string_v(cJSON * target,const char * string,...)
426 : {
427 0 : char * value=CSPRINTF(string);
428 0 : if (value)
429 : {
430 0 : cJSON *item = cJSON_CreateObject();
431 0 : if(item)
432 : {
433 0 : item->type = cJSON_String;
434 0 : item->valuestring = value;
435 0 : cJSON_AddItemToArray(target, item);
436 : }
437 0 : else free(value);
438 : }
439 0 : return;
440 : }
441 :
442 0 : void cJSON_add_Array_string_n(cJSON * target,const char * string,size_t n)
443 : {
444 0 : cJSON *item = cJSON_CreateObject();
445 0 : if(item)
446 : {
447 0 : item->type = cJSON_String;
448 0 : item->valuestring = (char*)cJSON_strdup_n((const unsigned char*)string, n);
449 0 : if(!item->valuestring)
450 : {
451 0 : cJSON_Delete(item);
452 0 : return;
453 : }
454 : else
455 : {
456 0 : cJSON_AddItemToArray(target, item);
457 : }
458 : }
459 : return;
460 : }
461 :
462 :
463 6 : int cJSON_findinstringarry_n(cJSON * sa,const char * content,size_t n)
464 : {
465 6 : int res=-1;
466 6 : cJSON * item=NULL;
467 8 : cJSON_ArrayForEach(item, sa)
468 : {
469 5 : if (cJSON_IsString(item))
470 : {
471 5 : if (strncmp(item->valuestring, content, n)==0)
472 : {
473 : res=0;
474 : break;
475 : }
476 : }
477 : else
478 : break;
479 : }
480 6 : return res;
481 : }
482 :
483 0 : int cJSON_IsTrue_string(const char *valuestring)
484 : {
485 0 : int result=0;
486 0 : if (*valuestring)
487 : {
488 0 : char * tmp=strdup(valuestring);
489 0 : lower_string(tmp);
490 0 : if(strcmp(tmp,"true")==0 || strcmp(tmp,"yes")==0 || strcmp(tmp,"1")==0)
491 0 : result=1;
492 0 : free(tmp);
493 0 : tmp=NULL;
494 : }
495 0 : return result;
496 : }
497 :
498 :
499 0 : int cJSON_validate_contains_match(const cJSON * json,const char *key,const char * match)
500 : {
501 0 : int result = 0;
502 0 : if (!json) return 0;
503 0 : if (!key) return 0;
504 0 : if (!match) return 0;
505 0 : char * valuestring=cJSON_get_stringvalue_dup(json, key);
506 0 : if (!valuestring) return 0;
507 0 : lower_string(valuestring);
508 0 : char * match_ls=strdup(match);
509 0 : if (match)
510 : {
511 0 : lower_string(match_ls);
512 0 : result=strstr(valuestring,match_ls)!=NULL;
513 0 : free(match_ls);
514 : }
515 0 : free(valuestring);
516 0 : return result;
517 : }
518 :
519 : /*------------------------------------------------------------------------
520 : * Read a JSON file with dirpath/filename
521 : * returns NULL on errors
522 : * returns a cJSON object, caller is responsible for freeing it!
523 : *------------------------------------------------------------------------*/
524 0 : cJSON * read_file_json_v( char ** errormsg,const char * vpath,...)
525 : {
526 0 : if (!vpath || strlen(vpath)==0)
527 : {
528 0 : if (errormsg) asprintf(errormsg, "vpath is empty");
529 : return NULL;
530 : }
531 0 : char *dirpath=CSPRINTF(vpath);
532 0 : if (!dirpath || strlen(dirpath)==0)
533 : {
534 0 : if (errormsg) asprintf(errormsg, "Filename results empty");
535 : return NULL;
536 : }
537 0 : FILE *f = fopen(dirpath, "r");
538 0 : if (f == NULL)
539 : {
540 0 : if (errormsg) asprintf(errormsg, "Reading %s: %s",dirpath, strerror(errno));
541 0 : if (dirpath) free(dirpath);
542 : return NULL;
543 : }
544 :
545 0 : dynbuffer *mem= dynbuffer_init();
546 : char buf[1024];
547 0 : bzero(buf, 1024);
548 0 : while( fgets( buf, 1024-1, f ) != NULL )
549 : {
550 0 : dynbuffer_write(buf, &mem );
551 0 : bzero(buf, 1024);
552 : }
553 0 : fclose(f);
554 0 : cJSON * result=NULL;
555 0 : if (dynbuffer_get(mem) && dynbuffer_len(mem)>0)
556 : {
557 0 : result=cJSON_Parse(dynbuffer_get(mem));
558 0 : if (!result && errormsg) asprintf(errormsg, "file %s parsing returns NULL object", dirpath);
559 : }
560 : else
561 0 : if (errormsg) asprintf(errormsg, "file %s is empty", dirpath);
562 0 : dynbuffer_clear(mem);
563 0 : if (dirpath) free(dirpath);
564 0 : dirpath=0;
565 0 : return result;
566 : }
|