1 /*
2  * Portions of this file Copyright 1999-2005 University of Chicago
3  * Portions of this file Copyright 1999-2005 The University of Southern California.
4  *
5  * This file or a portion of this file is licensed under the
6  * terms of the Globus Toolkit Public License, found at
7  * http://www.globus.org/toolkit/download/license.html.
8  * If you redistribute this file, with or without
9  * modifications, you must include this notice in the file.
10  */
11
12
13 #include "globus_common.h"
14 #include "version.h"
15 #include "globus_i_wsdl_config.h"
16
17 #define MAX_LINE_SIZE 1000
18
19 #ifdef WIN32
20 #define FILE_SEPARATOR "\\"
21 #else
22 #define FILE_SEPARATOR "/"
23 #endif
24
25 static int globus_l_wsdl_config_activate();
26 static int globus_l_wsdl_config_deactivate();
27
28 globus_module_descriptor_t              globus_i_wsdl_config_module =
29 {
30     "globus_wsdl_config",
31     globus_l_wsdl_config_activate,
32     globus_l_wsdl_config_deactivate,
33     GLOBUS_NULL,
34     GLOBUS_NULL,
35     &local_version
36 };
37
38 0 GlobusDebugDefine(GLOBUS_WSDL_CONFIG);
39
40 static int
41 globus_l_wsdl_config_activate()
42 {
43 0     int                                 res = (int) GLOBUS_SUCCESS;
44     
45 0     res = (int) globus_module_activate(GLOBUS_COMMON_MODULE);
46 0     GlobusDebugInit(GLOBUS_WSDL_CONFIG, ERROR TRACE INFO);
47 0     return res;
48 }
49
50 static int
51 globus_l_wsdl_config_deactivate()
52 0 {
53 0     globus_result_t                     result = GLOBUS_SUCCESS;
54 0     globus_module_deactivate(GLOBUS_COMMON_MODULE);
55 0     GlobusDebugDestroy(GLOBUS_WSDL_CONFIG);
56 0     return (int) result;
57 }
58
59 void
60 globus_i_wsdl_config_delete_entry(
61     void *                              hash_entry)
62 495 {
63 495     char **                             entry;
64
65 495     entry = (char **) hash_entry;
66
67 495     if(entry[0])
68     {
69 495         free(entry[0]);
70     }
71
72 495     if(entry[1])
73     {
74 495         free(entry[1]);
75     }
76
77 495     free(entry);
78 }
79
80 static
81 const char *
82 my_strpbrk(
83     const char *                        str,
84     size_t                              str_length,
85     int *                               locator_index,
86     const char *                        delims,
87     int *                               delim_index);
88
89 char *
90 globus_wsdl_config_get_property(
91     globus_hashtable_t                  props,
92     const char *                        key)
93 15226 {
94 15226     char **                             entry;
95
96 15226     entry = globus_hashtable_lookup(&props, (void *)key);
97 15226     if(!entry)
98     {
99 214         return NULL;
100     }
101
102 15012     return (char *) entry[1];
103 }
104
105 globus_result_t
106 globus_wsdl_config_set_property(
107     globus_hashtable_t *                props,
108     const char *                        prop_string)
109 138 {
110 138     globus_result_t                     result = GLOBUS_SUCCESS;
111 138     int                                 res = 0;
112 138     char *                              key;
113 138     char *                              value;
114 138     char *                              prop = NULL;
115 138     char *                              pos;
116 138     char *                              qpos;
117 138     char *                              qpos_end;
118 138     char *                              delim;
119 138     int                                 line_length;
120 138     int                                 index;
121 138     int                                 delim_index;
122 138     char **                             hash_entry;
123 138     GlobusFuncName(globus_wsdl_config_set_property);
124     GlobusWSDLConfigDebugEnter();
125
126 138     prop = globus_libc_strdup(prop_string);
127 138     pos = prop;
128 138     line_length = strlen(prop);
129 138     pos = (char *)my_strpbrk(pos, line_length, &index, "=", NULL);
130 138     if(!pos)
131     {
132 0         result = GlobusWSDLConfigErrorNoEqualsProp(prop);
133 0         goto exit;
134     }
135     
136 138     *pos = '\0';
137
138 138     key = prop;
139 138     pos++;
140 138     line_length -= (pos - prop);
141 138     qpos = (char *) my_strpbrk(pos, line_length, &index, "\"'", &delim_index);
142 138     if(!qpos)
143     {
144 138         value = pos;
145     }
146     else
147     {
148 0         line_length -= (qpos - pos);
149 0         qpos++;
150 0         if(delim_index == 0)
151         {
152 0             delim = "\"";
153         }
154         else
155         {
156 0             delim = "'";
157         }
158         
159 0         qpos_end = (char *) my_strpbrk(qpos, line_length, &index, delim, NULL);
160 0         if(!qpos_end)
161         {
162 0             result = GlobusWSDLConfigErrorNoEndQuoteProp(
163                 prop, delim);
164 0             goto exit;
165         }
166         else
167         {
168 0             *qpos_end = '\0';
169 0             value = qpos;
170         }
171     }
172
173 138     hash_entry = globus_malloc(2 * sizeof(char *));
174 138     if(!hash_entry)
175     {
176 0         result = GlobusWSDLConfigErrorOutOfMemory;
177 0         goto exit;
178     }
179     
180 138     hash_entry[0] = globus_libc_strdup(key);
181 138     hash_entry[1] = globus_libc_strdup(value);
182
183 138     res = globus_hashtable_insert(
184         props, (void *) hash_entry[0], (void *) hash_entry);
185 138     if(res != GLOBUS_SUCCESS)
186     {
187 0         result = GlobusWSDLConfigErrorHashInsertFailed();
188         goto exit;
189     }
190
191  exit:
192
193 138     if(prop)
194     {
195 138         free(prop);
196     }
197
198     GlobusWSDLConfigDebugExit();
199 138     return result;
200 }
201
202 void
203 globus_wsdl_config_properties_destroy(
204     globus_hashtable_t                  props)
205 34 {
206 34     globus_hashtable_destroy_all(&props, globus_i_wsdl_config_delete_entry);
207 }
208
209 globus_result_t
210 globus_wsdl_config_properties_init(
211     globus_hashtable_t *                props)
212 34 {
213 34     GlobusFuncName(globus_wsdl_config_properties_init);
214     GlobusWSDLConfigDebugEnter();
215     
216 34     globus_hashtable_init(props, 10, 
217                           globus_hashtable_string_hash,
218                           globus_hashtable_string_keyeq);
219 34     globus_assert(props);
220  
221     GlobusWSDLConfigDebugExit();
222 34     return GLOBUS_SUCCESS;
223 }
224
225
226 globus_result_t
227 globus_wsdl_config_load_properties(
228     const char *                        filename,
229     globus_hashtable_t *                properties)
230
231 17 {
232 17     globus_result_t                     result = GLOBUS_SUCCESS;
233 17     char                                line[MAX_LINE_SIZE];
234 17     FILE *                              propstream = NULL;
235 17     int                                 linenum = 0;
236 17     char *                              key = NULL;
237 17     char *                              value = NULL;
238 17     char *                              new_value = NULL;
239 17     size_t                              new_value_length = 0;
240 17     char **                             hash_entry = NULL;
241 17     GlobusFuncName(globus_wsdl_config_load_properties);
242     GlobusWSDLConfigDebugEnter();
243
244 17     globus_assert_string(properties, 
245                          "NULL properties parameter passed to function");
246 17     globus_assert_string(filename,
247                          "NULL filename passed to function");
248
249 17     propstream = fopen(filename, "r");
250 17     if(!propstream)
251     {
252 0         result = GlobusWSDLConfigErrorFileOpen(filename);
253 0         goto exit;
254     }
255
256 17     memset(line, 0, MAX_LINE_SIZE);
257 374     while(fgets(line, MAX_LINE_SIZE, propstream) != NULL)
258     {
259 357         size_t                          line_length;
260 357         char *                          pos = NULL;
261 357         char *                          kpos = NULL;
262 357         char *                          qpos = NULL;
263 357         char *                          qpos_end = NULL;
264 357         int                             index = 0;
265 357         int                             delim_index = 0;
266 357         char *                          delim = NULL;
267 357         int                             res = 0;
268
269 357         linenum++;
270 357         line_length = strlen(line);
271
272 357         pos = line;
273
274 357         while(pos && (*pos == ' '))
275         {
276 0             ++pos;
277         }
278
279 357         if(pos && ((*pos == '#') || (*pos == '\n')))
280         {
281 357             continue;
282         }
283
284 357         if(line[line_length-1] == '\n')
285         {
286 357             line[line_length-1] = '\0';
287         }
288
289 357         kpos = pos;
290 357         pos = (char *)my_strpbrk(pos, line_length, &index, "=", NULL);
291 357         if(!pos)
292         {
293 0             result = GlobusWSDLConfigErrorNoEquals(filename, linenum);
294 0             goto exit;
295         }
296
297 357         *pos = '\0';
298
299 357         key = globus_libc_strdup(kpos);
300 357         pos++;
301 357         line_length -= (pos - line);
302 357         qpos = (char *) my_strpbrk(pos, line_length, &index, "\"'", &delim_index);
303 357         if(!qpos)
304         {
305 357             value = globus_libc_strdup(pos);
306         }
307         else
308         {
309 0             line_length -= (qpos - pos);
310 0             qpos++;
311 0             if(delim_index == 0)
312             {
313 0                 delim = "\"";
314             }
315             else
316             {
317 0                 delim = "'";
318             }
319
320 0             qpos_end = (char *) my_strpbrk(qpos, line_length, &index, delim, NULL);
321 0             if(!qpos_end)
322             {
323 0                 result = GlobusWSDLConfigErrorNoEndQuote(
324                     filename, linenum, delim);
325 0                 goto exit;
326             }
327             else
328             {
329 0                 *qpos_end = '\0';
330 0                 value = globus_libc_strdup(qpos);
331             }
332         }
333
334 357         hash_entry = globus_malloc(2 * sizeof(char *));
335 357         if(!hash_entry)
336         {
337 0             result = GlobusWSDLConfigErrorOutOfMemory;
338 0             goto exit;
339         }
340
341 357         hash_entry[0] = globus_libc_strdup(key);
342 357         hash_entry[1] = globus_libc_strdup(value);
343 357         res = globus_hashtable_insert(
344             properties, (void *) key, (void *) hash_entry);
345 357         if(res != GLOBUS_SUCCESS)
346         {
347 0             result = GlobusWSDLConfigErrorHashInsertFailed();
348 0             goto exit;
349         }
350
351 357         hash_entry = NULL;
352 357         key = NULL;
353 357         value = NULL;
354
355 357         memset(line, 0, MAX_LINE_SIZE);
356     }
357
358 17     hash_entry = (char **)globus_hashtable_first(properties);
359 374     while(hash_entry)
360     {
361 357         result = globus_wsdl_config_expand_refs(
362             *properties, hash_entry[1], strlen(hash_entry[1]) + 1, 
363             &new_value, &new_value_length);
364 357         if(result != GLOBUS_SUCCESS)
365         {
366 0             result = GlobusWSDLConfigErrorExpandingRefs(result, filename, linenum);
367 0             goto exit;
368         }
369
370 357         if(hash_entry[1] != new_value)
371         {
372 0             free(hash_entry[1]);
373 0             hash_entry[1] = globus_libc_strdup(new_value);
374         }
375
376 357         new_value = NULL;
377         
378 357         hash_entry = (char **)globus_hashtable_next(properties);
379     }
380
381  exit:
382     
383 17     if(propstream)
384     {
385 17         fclose(propstream);
386     }
387
388 17     if(key)
389     {
390 0         free(key);
391     }
392
393 17     if(value)
394     {
395 0         free(value);
396     }
397
398 17     if(new_value)
399     {
400 0         free(new_value);
401     }
402
403 17     if(hash_entry)
404     {
405 0         globus_free(hash_entry);
406     }
407
408     GlobusWSDLConfigDebugExit();
409 17     return result;
410 }        
411         
412 globus_result_t
413 globus_wsdl_config_expand_refs(
414     globus_hashtable_t                  hash,
415     char *                              value,
416     size_t                              value_length,
417     char **                             new_value,
418     size_t *                            new_length)
419 357 {
420 357     char *                              nvalue = NULL;
421 357     size_t                              nvalue_length = 0;
422 357     char *                              rp = NULL;
423 357     char *                              prev_rp = NULL;
424 357     size_t                              rp_length = 0;
425 357     int                                 rp_index = 0;
426 357     int                                 newrp_index = 0;
427 357     char *                              rp_env = NULL;
428 357     char *                              tmp_rp = NULL;
429 357     int                                 tmp_rp_index = 0;
430 357     char *                              envstring = NULL;
431 357     globus_result_t                     result = GLOBUS_SUCCESS;
432 357     char **                             hash_entry = NULL;
433
434 357     GlobusFuncName(globus_wsdl_config_expand_refs);
435     GlobusWSDLConfigDebugEnter();
436
437 357     rp = (char *)value;
438 357     prev_rp = rp;
439 357     rp_length = value_length;
440 357     rp = (char *)my_strpbrk(rp, rp_length, &rp_index, "$", NULL);
441
442 357     if(!rp)
443     {
444 357         nvalue = value;
445 357         nvalue_length = value_length;
446     }
447
448 357     while(rp)
449     {
450 0         rp_length -= rp_index;
451
452 0         if(rp_index != 0)
453         {
454 0             if(rp[-1] == '\\')
455             {
456 0                 rp++;
457 0                 rp_length--;
458 0                 rp = (char *)my_strpbrk(rp, rp_length, &newrp_index,
459                                         "$", NULL);
460 0                 rp_length -= newrp_index;
461 0                 rp_index += newrp_index + 1;
462             }
463         }
464
465         
466 0         nvalue = realloc(nvalue, nvalue_length + rp_index);
467 0         memcpy(nvalue + (nvalue_length - 1), prev_rp, rp_index);
468 0         nvalue_length += rp_index;
469
470 0         if(rp_length && (*(rp + 1) == '{'))
471         {
472 0             rp_env = rp + 2;
473 0             rp_length -= 2;
474         
475 0             tmp_rp = (char *)my_strpbrk(rp_env, rp_length, &tmp_rp_index, "}", NULL);
476 0             if(!tmp_rp)
477             {
478 0                 result = GlobusWSDLConfigErrorNoCurly();
479 0                 goto error_exit;
480             }
481             
482 0             envstring = malloc(tmp_rp_index + 1);
483 0             memcpy(envstring, rp_env, tmp_rp_index);
484 0             envstring[tmp_rp_index] = '\0';
485 0             rp = tmp_rp + 1;
486 0             rp_length -= tmp_rp_index - 1;
487         }
488         else
489         {
490 0             rp_env = rp + 1;
491 0             tmp_rp = (char *)my_strpbrk(rp_env, rp_length, &tmp_rp_index, 
492                                         FILE_SEPARATOR" ", NULL);
493 0             if(tmp_rp)
494             {
495 0                 rp = tmp_rp;
496 0                 rp_length -= tmp_rp_index;
497 0                 envstring = malloc(tmp_rp_index + 1);
498 0                 memcpy(envstring, rp_env, tmp_rp_index);
499 0                 envstring[tmp_rp_index] = '\0';
500             }
501             else
502             {
503 0                 rp = tmp_rp;
504 0                 envstring = malloc(rp_length + 1);
505 0                 memcpy(envstring, rp_env, rp_length);
506 0                 envstring[rp_length] = '\0';
507 0                 rp_length = 0;
508             }
509         }
510
511 0         hash_entry = globus_hashtable_lookup(&hash, (void *) envstring);
512 0         if(hash_entry)
513         {
514 0             size_t                      tmp_length = strlen(hash_entry[1]);
515 0             nvalue = realloc(nvalue, nvalue_length + tmp_length);
516 0             memcpy(nvalue + (nvalue_length - 1), hash_entry[1], tmp_length);
517 0             nvalue_length += tmp_length;
518         }
519         else
520         {
521 0             char *                      env_value;
522 0             size_t                      tmp_length;
523 0             env_value = getenv(envstring);
524 0             if(!env_value)
525             {
526 0                 result = GlobusWSDLConfigErrorNoEnv(envstring);
527 0                 goto error_exit;
528             }
529
530 0             tmp_length += strlen(env_value);
531 0             nvalue = realloc(nvalue, nvalue_length + tmp_length);
532 0             memcpy(nvalue + (nvalue_length - 1), env_value, tmp_length);
533 0             nvalue_length += tmp_length;
534         }
535
536 0         if(envstring)
537         {
538 0             free(envstring);
539 0             envstring = NULL;
540         }
541
542 0         if(rp)
543         {
544 0             prev_rp = rp;
545 0             rp = (char *)my_strpbrk(rp, rp_length, &rp_index, "$", NULL);
546         }
547     }
548
549 357     if(rp && rp_length)
550     {
551 0         nvalue = realloc(nvalue, nvalue_length + rp_length);
552 0         memcpy(nvalue + (nvalue_length - 1), rp, rp_length);
553 0         nvalue_length += rp_length;
554     }
555     
556 357     nvalue[nvalue_length - 1] = '\0';
557
558 357     *new_value = nvalue;
559 357     *new_length = nvalue_length;
560     
561 357     goto exit;
562
563  error_exit:
564     
565 0     if(nvalue)
566     {
567 0         free(nvalue);
568     }
569     
570  exit:
571
572 357     if(envstring)
573     {
574 0         free(envstring);
575     }
576     
577     GlobusWSDLConfigDebugExit();
578 357     return result;
579 }
580
581 static
582 const char *
583 my_strpbrk(
584     const char *                        str,
585     size_t                              str_length,
586     int *                               locator_index,
587     const char *                        delims,
588     int *                               delim_index)
589 1347 {
590 1347     const char *                        locator;
591 1347     int                                 delim_count, ind, i;
592     
593 1347     ind = 0;
594 1347     i = 0;
595 1347     delim_count = strlen(delims);
596 1347     locator = str;
597 29760     while(*locator && ind < str_length)
598     {
599 60251         for(i = 0; i < delim_count; ++i)
600         {
601 31838             if(*locator == delims[i])
602             {
603 495                 if(locator_index)
604                 {
605 495                     *locator_index = ind;
606                 }
607                 
608 495                 if(delim_index)
609                 {
610 0                     *delim_index = i;
611                 }
612 495                 return locator;
613             }
614         }
615         
616 28413         locator++;
617 28413         ind++;
618     }
619
620 852     if(locator_index)
621     {
622 852         *locator_index = -1;
623     }
624 852     return NULL;