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 465 {
63 465     char **                             entry;
64
65 465     entry = (char **) hash_entry;
66
67 465     if(entry[0])
68     {
69 465         free(entry[0]);
70     }
71
72 465     if(entry[1])
73     {
74 465         free(entry[1]);
75     }
76
77 465     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 14860 {
94 14860     char **                             entry;
95
96 14860     entry = globus_hashtable_lookup(&props, (void *)key);
97 14860     if(!entry)
98     {
99 175         return NULL;
100     }
101
102 14685     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 129 {
110 129     globus_result_t                     result = GLOBUS_SUCCESS;
111 129     int                                 res = 0;
112 129     char *                              key;
113 129     char *                              value;
114 129     char *                              prop = NULL;
115 129     char *                              pos;
116 129     char *                              qpos;
117 129     char *                              qpos_end;
118 129     char *                              delim;
119 129     int                                 line_length;
120 129     int                                 index;
121 129     int                                 delim_index;
122 129     char **                             hash_entry;
123 129     GlobusFuncName(globus_wsdl_config_set_property);
124     GlobusWSDLConfigDebugEnter();
125
126 129     prop = globus_libc_strdup(prop_string);
127 129     pos = prop;
128 129     line_length = strlen(prop);
129 129     pos = (char *)my_strpbrk(pos, line_length, &index, "=", NULL);
130 129     if(!pos)
131     {
132 0         result = GlobusWSDLConfigErrorNoEqualsProp(prop);
133 0         goto exit;
134     }
135     
136 129     *pos = '\0';
137
138 129     key = prop;
139 129     pos++;
140 129     line_length -= (pos - prop);
141 129     qpos = (char *) my_strpbrk(pos, line_length, &index, "\"'", &delim_index);
142 129     if(!qpos)
143     {
144 129         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 129     hash_entry = globus_malloc(2 * sizeof(char *));
174 129     if(!hash_entry)
175     {
176 0         result = GlobusWSDLConfigErrorOutOfMemory;
177 0         goto exit;
178     }
179     
180 129     hash_entry[0] = globus_libc_strdup(key);
181 129     hash_entry[1] = globus_libc_strdup(value);
182
183 129     res = globus_hashtable_insert(
184         props, (void *) hash_entry[0], (void *) hash_entry);
185 129     if(res != GLOBUS_SUCCESS)
186     {
187 0         result = GlobusWSDLConfigErrorHashInsertFailed();
188         goto exit;
189     }
190
191  exit:
192
193 129     if(prop)
194     {
195 129         free(prop);
196     }
197
198     GlobusWSDLConfigDebugExit();
199 129     return result;
200 }
201
202 void
203 globus_wsdl_config_properties_destroy(
204     globus_hashtable_t                  props)
205 32 {
206 32     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 32 {
213 32     GlobusFuncName(globus_wsdl_config_properties_init);
214     GlobusWSDLConfigDebugEnter();
215     
216 32     globus_hashtable_init(props, 10, 
217                           globus_hashtable_string_hash,
218                           globus_hashtable_string_keyeq);
219 32     globus_assert(props);
220  
221     GlobusWSDLConfigDebugExit();
222 32     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 16 {
232 16     globus_result_t                     result = GLOBUS_SUCCESS;
233 16     char                                line[MAX_LINE_SIZE];
234 16     FILE *                              propstream = NULL;
235 16     int                                 linenum = 0;
236 16     char *                              key = NULL;
237 16     char *                              value = NULL;
238 16     char *                              new_value = NULL;
239 16     size_t                              new_value_length = 0;
240 16     char **                             hash_entry = NULL;
241 16     GlobusFuncName(globus_wsdl_config_load_properties);
242     GlobusWSDLConfigDebugEnter();
243
244 16     globus_assert_string(properties, 
245                          "NULL properties parameter passed to function");
246 16     globus_assert_string(filename,
247                          "NULL filename passed to function");
248
249 16     propstream = fopen(filename, "r");
250 16     if(!propstream)
251     {
252 0         result = GlobusWSDLConfigErrorFileOpen(filename);
253 0         goto exit;
254     }
255
256 16     memset(line, 0, MAX_LINE_SIZE);
257 352     while(fgets(line, MAX_LINE_SIZE, propstream) != NULL)
258     {
259 336         size_t                          line_length;
260 336         char *                          pos = NULL;
261 336         char *                          kpos = NULL;
262 336         char *                          qpos = NULL;
263 336         char *                          qpos_end = NULL;
264 336         int                             index = 0;
265 336         int                             delim_index = 0;
266 336         char *                          delim = NULL;
267 336         int                             res = 0;
268
269 336         linenum++;
270 336         line_length = strlen(line);
271
272 336         pos = line;
273
274 336         while(pos && (*pos == ' '))
275         {
276 0             ++pos;
277         }
278
279 336         if(pos && ((*pos == '#') || (*pos == '\n')))
280         {
281 336             continue;
282         }
283
284 336         if(line[line_length-1] == '\n')
285         {
286 336             line[line_length-1] = '\0';
287         }
288
289 336         kpos = pos;
290 336         pos = (char *)my_strpbrk(pos, line_length, &index, "=", NULL);
291 336         if(!pos)
292         {
293 0             result = GlobusWSDLConfigErrorNoEquals(filename, linenum);
294 0             goto exit;
295         }
296
297 336         *pos = '\0';
298
299 336         key = globus_libc_strdup(kpos);
300 336         pos++;
301 336         line_length -= (pos - line);
302 336         qpos = (char *) my_strpbrk(pos, line_length, &index, "\"'", &delim_index);
303 336         if(!qpos)
304         {
305 336             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 336         hash_entry = globus_malloc(2 * sizeof(char *));
335 336         if(!hash_entry)
336         {
337 0             result = GlobusWSDLConfigErrorOutOfMemory;
338 0             goto exit;
339         }
340
341 336         hash_entry[0] = globus_libc_strdup(key);
342 336         hash_entry[1] = globus_libc_strdup(value);
343 336         res = globus_hashtable_insert(
344             properties, (void *) key, (void *) hash_entry);
345 336         if(res != GLOBUS_SUCCESS)
346         {
347 0             result = GlobusWSDLConfigErrorHashInsertFailed();
348 0             goto exit;
349         }
350
351 336         hash_entry = NULL;
352 336         key = NULL;
353 336         value = NULL;
354
355 336         memset(line, 0, MAX_LINE_SIZE);
356     }
357
358 16     hash_entry = (char **)globus_hashtable_first(properties);
359 352     while(hash_entry)
360     {
361 336         result = globus_wsdl_config_expand_refs(
362             *properties, hash_entry[1], strlen(hash_entry[1]) + 1, 
363             &new_value, &new_value_length);
364 336         if(result != GLOBUS_SUCCESS)
365         {
366 0             result = GlobusWSDLConfigErrorExpandingRefs(result, filename, linenum);
367 0             goto exit;
368         }
369
370 336         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 336         new_value = NULL;
377         
378 336         hash_entry = (char **)globus_hashtable_next(properties);
379     }
380
381  exit:
382     
383 16     if(propstream)
384     {
385 16         fclose(propstream);
386     }
387
388 16     if(key)
389     {
390 0         free(key);
391     }
392
393 16     if(value)
394     {
395 0         free(value);
396     }
397
398 16     if(new_value)
399     {
400 0         free(new_value);
401     }
402
403 16     if(hash_entry)
404     {
405 0         globus_free(hash_entry);
406     }
407
408     GlobusWSDLConfigDebugExit();
409 16     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 336 {
420 336     char *                              nvalue = NULL;
421 336     size_t                              nvalue_length = 0;
422 336     char *                              rp = NULL;
423 336     char *                              prev_rp = NULL;
424 336     size_t                              rp_length = 0;
425 336     int                                 rp_index = 0;
426 336     int                                 newrp_index = 0;
427 336     char *                              rp_env = NULL;
428 336     char *                              tmp_rp = NULL;
429 336     int                                 tmp_rp_index = 0;
430 336     char *                              envstring = NULL;
431 336     globus_result_t                     result = GLOBUS_SUCCESS;
432 336     char **                             hash_entry = NULL;
433
434 336     GlobusFuncName(globus_wsdl_config_expand_refs);
435     GlobusWSDLConfigDebugEnter();
436
437 336     rp = (char *)value;
438 336     prev_rp = rp;
439 336     rp_length = value_length;
440 336     rp = (char *)my_strpbrk(rp, rp_length, &rp_index, "$", NULL);
441
442 336     if(!rp)
443     {
444 336         nvalue = value;
445 336         nvalue_length = value_length;
446     }
447
448 336     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 336     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 336     nvalue[nvalue_length - 1] = '\0';
557
558 336     *new_value = nvalue;
559 336     *new_length = nvalue_length;
560     
561 336     goto exit;
562
563  error_exit:
564     
565 0     if(nvalue)
566     {
567 0         free(nvalue);
568     }
569     
570  exit:
571
572 336     if(envstring)
573     {
574 0         free(envstring);
575     }
576     
577     GlobusWSDLConfigDebugExit();
578 336     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 1266 {
590 1266     const char *                        locator;
591 1266     int                                 delim_count, ind, i;
592     
593 1266     ind = 0;
594 1266     i = 0;
595 1266     delim_count = strlen(delims);
596 1266     locator = str;
597 27963     while(*locator && ind < str_length)
598     {
599 56605         for(i = 0; i < delim_count; ++i)
600         {
601 29908             if(*locator == delims[i])
602             {
603 465                 if(locator_index)
604                 {
605 465                     *locator_index = ind;
606                 }
607                 
608 465                 if(delim_index)
609                 {
610 0                     *delim_index = i;
611                 }
612 465                 return locator;
613             }
614         }
615         
616 26697         locator++;
617 26697         ind++;
618     }
619
620 801     if(locator_index)
621     {
622 801         *locator_index = -1;
623     }
624 801     return NULL;