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