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 #include "globus_common.h"
13 #include "libxml/xmlreader.h"
14 #include <string.h>
15 #include <fcntl.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18 #include <errno.h>
19
20 #define TEMPLATE_NODE                   "tmpl"
21 #define EVAL_NODE                       "eval"
22 #define SCRIPT_NODE                     "script"
23
24 #define BEGIN_PRINT                     "\nprint(\""
25 #define BEGIN_PRINT_LENGTH              8
26 #define END_PRINT                       "\");\n"
27 #define END_PRINT_LENGTH                4
28 #define PRINT_LENGTH                    12
29
30 #define BEGIN_EPRINT                    "\nprint("
31 #define BEGIN_EPRINT_LENGTH             7
32 #define END_EPRINT                      ");\n"
33 #define END_EPRINT_LENGTH               3
34 #define EPRINT_LENGTH                   10
35
36 #define DELIMITER_COUNT                 2
37 static const char *                     DELIMITERS = "\n\"";
38 static const char *                     REPLACEMENTS[DELIMITER_COUNT] = 
39                                         {"\\n", "\\\""};
40
41 /**
42  * Functions for parsing the template file
43  */
44
45 static
46 const char *
47 my_strpbrk(
48     const char *                        str,
49     size_t                              str_length,
50     int *                               locator_index,
51     const char *                        delims,
52     int *                               delim_index,
53     int                                 escape);
54
55 static
56 int
57 globus_i_template_convert_chars(
58     const char *                        old_buffer,
59     size_t                              old_length,
60     char **                             buffer,
61     size_t *                            length,
62     int                                 delim_count,
63     const char *                        delim_set,
64     const char **                       replace_set);
65
66 int
67 globus_wsdl_template_get_jsbuf(
68     const char *                        filename,
69     char **                             buffer,
70     size_t *                            length,
71     char **                             error_string,
72     char                                script_token,
73     char                                eval_token)
74 221 {
75 221     size_t                              read_length = 0;
76 221     char                                read_buffer[1000];
77 221     size_t                              new_length = 0;
78 221     char *                              new_buffer = NULL;
79 221     size_t                              tmp_length = 0;
80 221     char *                              tmp_buffer = NULL;
81 221     size_t                              script_length = 0;
82 221     size_t                              eval_length = 0;
83 221     size_t                              tmpl_length = 0;
84 221     const char *                        loc;
85 221     const char *                        prev;
86 221     char                                charset[3];
87 221     size_t                              template_length = 0;
88 221     char *                              template_buffer = NULL;
89 221     int                                 infd, res;
90 221     int                                 in_script = 0;
91 221     int                                 in_eval = 0;
92 221     char                                token;
93 221     int                                 loc_index, loc_length;
94 221     int                                 delim_index;
95 221     int                                 add_loc_index = 0;
96
97 221     *error_string = NULL;
98 221     charset[0] = script_token;
99 221     charset[1] = eval_token;
100 221     charset[2] = 0;
101
102 221     infd = open(filename, O_RDONLY, 0);
103 221     if(infd < 0)
104     {
105 /** XXX - this should be changed to use globus errno error calls */
106 0         char *                          error_message;
107 0         error_message = strerror(errno);
108 0         *error_string = globus_libc_strdup(error_message); 
109 0         goto exit;
110     }
111
112 221     memset(read_buffer, 0, 1000);
113
114 4274     while((read_length = read(infd, read_buffer, 1000)) > 0)
115     {
116 4053         tmp_buffer = realloc(tmp_buffer, tmp_length + read_length);
117 4053         if(!tmp_buffer)
118         {
119 /** XXX - this should be fixed to use globus_error_errno calls */
120 0             char *                      error_message;
121 0             error_message = strerror(errno);
122 0             *error_string = globus_libc_strdup(error_message);
123 0             goto exit;
124         }
125         
126 4053         memcpy(tmp_buffer + tmp_length, read_buffer, read_length);
127 4053         tmp_length += read_length;
128     }
129
130 221     tmp_buffer = realloc(tmp_buffer, tmp_length + 1);
131 221     tmp_buffer[tmp_length] = 0;
132
133 221     loc = tmp_buffer;
134 221     loc_length = tmp_length;
135 221     prev = tmp_buffer;
136
137 54381     while(1)
138     {
139 54381         loc = my_strpbrk(loc, loc_length, &loc_index, charset, &delim_index, 1);
140 54381         if(!loc)
141         {
142 221             if(in_script)
143             {
144 0                 *error_string = globus_libc_strdup(
145                     "End of file reached inside a script chunk");
146 0                 goto exit;
147             }
148
149 221             if(in_eval)
150             {
151 0                 *error_string = globus_libc_strdup(
152                     "End of file reached inside an evalu chunk");
153 0                 goto exit;
154             }
155
156 221             tmpl_length = loc_length;
157 221             globus_i_template_convert_chars(
158                 prev, tmpl_length,
159                 &template_buffer, &template_length,
160                 DELIMITER_COUNT,
161                 DELIMITERS, 
162                 REPLACEMENTS);
163 221             new_buffer = realloc(
164                 new_buffer,
165                 new_length + template_length + PRINT_LENGTH);
166 221             memcpy(new_buffer + new_length, 
167                    BEGIN_PRINT, BEGIN_PRINT_LENGTH);
168 221             memcpy(new_buffer + new_length + BEGIN_PRINT_LENGTH,
169                    template_buffer, template_length);
170 221             memcpy(new_buffer + new_length + 
171                    BEGIN_PRINT_LENGTH + template_length, 
172                    END_PRINT, END_PRINT_LENGTH);
173 221             new_length += PRINT_LENGTH + template_length;
174
175 221             free(template_buffer);
176 221             template_buffer = NULL;
177
178 221             break;
179         }
180
181 54160         if(add_loc_index > 0)
182         {
183 0             loc_index += add_loc_index + 1;
184 0             add_loc_index = 0;
185         }
186
187 54160         if(loc_index != 0 && (*(loc - 1) == '\\'))
188         {
189 0             add_loc_index = loc_index;
190 0             ++loc;
191 0             continue;
192         }
193
194 54160         loc_length -= (loc_index + 1);
195
196 54160         token = *loc;
197         
198 54160         if(token == script_token)
199         {
200 9184             if(in_eval)
201             {
202 0                 *error_string = malloc(500);
203 0                 sprintf(*error_string,
204                         "While parsing %s: Found a script token (%c), "
205                         "expected an eval token (%c)",
206                         filename, script_token, eval_token);
207 0                 goto exit;
208             }
209
210 9184             if(in_script)
211             {
212 4592                 in_script = 0;
213
214 4592                 script_length = loc_index;
215 4592                 new_buffer = realloc(new_buffer, new_length + script_length);
216 4592                 memcpy(new_buffer + new_length, prev, script_length);
217 4592                 new_length += script_length;
218             }
219             else
220             {
221 4592                 in_script = 1;
222                 
223 4592                 tmpl_length = loc_index;
224 4592                 globus_i_template_convert_chars(
225                     prev, tmpl_length,
226                     &template_buffer, &template_length, 
227                     DELIMITER_COUNT,
228                     DELIMITERS,
229                     REPLACEMENTS);
230 4592                 new_buffer = realloc(
231                     new_buffer,
232                     new_length + template_length + PRINT_LENGTH);
233 4592                 memcpy(new_buffer + new_length, 
234                        BEGIN_PRINT, BEGIN_PRINT_LENGTH);
235 4592                 memcpy(new_buffer + new_length + BEGIN_PRINT_LENGTH,
236                        template_buffer, template_length);
237 4592                 memcpy(new_buffer + new_length + 
238                        BEGIN_PRINT_LENGTH + template_length, 
239                        END_PRINT, END_PRINT_LENGTH);
240 4592                 new_length += PRINT_LENGTH + template_length;
241
242 4592                 free(template_buffer);
243 4592                 template_buffer = NULL;
244             }
245         }
246 44976         else if(token == eval_token)
247         {
248 44976             if(in_script)
249             {
250 0                 *error_string = malloc(500);
251 0                 sprintf(
252                     *error_string,
253                     "While parsing %s: Found an eval token (%c), "
254                     "expected a script token (%c)",
255                     filename, eval_token, script_token);
256 0                 goto exit;
257             }
258
259 44976             if(in_eval)
260             {
261 22488                 in_eval = 0;
262
263 22488                 eval_length = loc_index;
264 22488                 new_buffer = realloc(new_buffer, 
265                                      new_length + eval_length + EPRINT_LENGTH);
266 22488                 memcpy(new_buffer + new_length, BEGIN_EPRINT, 
267                        BEGIN_EPRINT_LENGTH);
268 22488                 memcpy(new_buffer + new_length + BEGIN_EPRINT_LENGTH,
269                        prev, eval_length);
270 22488                 memcpy(new_buffer + new_length + 
271                        BEGIN_EPRINT_LENGTH + eval_length, 
272                        END_EPRINT, END_EPRINT_LENGTH);
273 22488                 new_length += EPRINT_LENGTH + eval_length;
274             }
275             else
276             {
277 22488                 in_eval = 1;
278
279 22488                 tmpl_length = loc_index;
280 22488                 globus_i_template_convert_chars(
281                     prev, tmpl_length,
282                     &template_buffer, &template_length, 
283                     DELIMITER_COUNT,
284                     DELIMITERS,
285                     REPLACEMENTS);
286 22488                 new_buffer = realloc(
287                     new_buffer,
288                     new_length + template_length + PRINT_LENGTH);
289 22488                 memcpy(new_buffer + new_length, 
290                        BEGIN_PRINT, BEGIN_PRINT_LENGTH);
291 22488                 memcpy(new_buffer + new_length + BEGIN_PRINT_LENGTH,
292                        template_buffer, template_length);
293 22488                 memcpy(new_buffer + new_length + 
294                        BEGIN_PRINT_LENGTH + template_length, 
295                        END_PRINT, END_PRINT_LENGTH);
296 22488                 new_length += PRINT_LENGTH + template_length;
297
298 22488                 free(template_buffer);
299 22488                 template_buffer = NULL;
300             }
301         }
302
303 54160         if(loc_length >= 0)
304         {
305 54160             ++loc;
306 54160             prev = loc;
307         }
308         else
309         {
310 221             break;
311         }
312     }
313
314 221     new_buffer = realloc(new_buffer, new_length + 2);
315 221     memcpy(new_buffer + new_length, "\r\n", 2);
316 221     new_length += 2;
317     
318 221     *buffer = new_buffer;
319 221     *length = new_length;
320
321   exit:
322
323 221     if(infd > 0)
324     {
325 221         close(infd);
326     }
327
328 221     if(*error_string)
329     {
330 0         return -1;
331     }
332
333 221     return 0;
334 }
335
336
337 /* int */
338 /* globus_wsdl_xml_template_get_jsbuf( */
339 /*     const char *                        filename, */
340 /*     char **                             buffer, */
341 /*     size_t *                            length, */
342 /*     char **                             error_string) */
343 /* { */
344 /*     size_t                              new_length = 0; */
345 /*     xmlTextReaderPtr                    reader = NULL; */
346 /*     char *                              new_buffer = NULL; */
347
348 /*     reader = xmlNewTextReaderFilename(filename); */
349 /*     if(!reader) */
350 /*     { */
351 /*         xmlErrorPtr                     error; */
352 /*         char *                          error_message; */
353
354 /*         error = xmlGetLastError(); */
355 /*         if(!error) */
356 /*         { */
357 /*             return -1; */
358 /*         } */
359
360 /*         error_message = malloc(strlen(error->message) + 500); */
361 /*         if(!error_message) */
362 /*         { */
363 /*             return -1; */
364 /*         } */
365         
366 /*         sprintf(error_message, "Could not parse template: %s: %s",  */
367 /*                 filename, error->message); */
368 /*         *error_string = error_message; */
369 /*         return -1; */
370 /*     } */
371
372 /*     while(xmlTextReaderRead(reader) > 0) */
373 /*     { */
374 /*         const xmlChar *                 local_name; */
375
376 /*         local_name = xmlTextReaderConstLocalName(reader); */
377 /*         if(xmlStrEqual(local_name, TEMPLATE_NODE)) */
378 /*         { */
379 /*             int                         bufflen; */
380 /*             char *                      template_buffer; */
381 /*             xmlNodePtr                  node; */
382
383 /*             node = xmlTextReaderExpand(reader); */
384 /*             if(node) */
385 /*             { */
386 /*                 node = node->children; */
387 /*             } */
388
389 /*             while(node) */
390 /*             { */
391 /*                 if(node->type == XML_TEXT_NODE) */
392 /*                 { */
393 /*                     if(node->content) */
394 /*                     { */
395 /*                         size_t          template_length; */
396
397 /*                         globus_i_template_convert_chars( */
398 /*                             node->content, strlen(node->content), */
399 /*                             &template_buffer, &template_length,  */
400 /*                             '\n', "\\n"); */
401 /*                         bufflen = template_length + 12; */
402 /*                         new_buffer = realloc(new_buffer, new_length + bufflen); */
403 /*                         memcpy(new_buffer + new_length, "\nprint(\"", 8); */
404 /*                         memcpy(new_buffer + new_length + 8,  */
405 /*                                template_buffer, template_length); */
406 /*                         memcpy(new_buffer + new_length + 8 + template_length, */
407 /*                                "\");\n", 4); */
408 /*                         new_length += bufflen; */
409 /*                     } */
410 /*                 } */
411                 
412 /*                 node = node->next; */
413 /*             } */
414 /*         } */
415 /*         else if(xmlStrEqual(local_name, EVAL_NODE)) */
416 /*         { */
417 /*             int                         bufflen; */
418 /*             size_t                      eval_length; */
419 /*             const xmlChar *             eval_buffer; */
420 /*             xmlNodePtr                  node; */
421
422 /*             node = xmlTextReaderExpand(reader); */
423 /*             if(node) */
424 /*             { */
425 /*                 node = node->children; */
426 /*             } */
427
428 /*             while(node) */
429 /*             { */
430 /*                 if(node->type == XML_TEXT_NODE) */
431 /*                 { */
432 /*                     eval_buffer = node->content; */
433 /*                     if(eval_buffer) */
434 /*                     { */
435 /*                         eval_length = strlen(eval_buffer); */
436 /*                         bufflen = eval_length + 10; */
437 /*                         new_buffer = realloc(new_buffer, new_length + bufflen); */
438 /*                         memcpy(new_buffer + new_length, "\nprint(", 7); */
439 /*                         memcpy(new_buffer + new_length + 7,  */
440 /*                                eval_buffer, eval_length); */
441 /*                         memcpy(new_buffer + new_length + 7 + eval_length, */
442 /*                                ");\n", 3); */
443 /*                         new_length += bufflen; */
444 /*                     } */
445 /*                 } */
446
447 /*                 node = node->next; */
448 /*             } */
449 /*         } */
450 /*         else if(xmlStrEqual(local_name, SCRIPT_NODE)) */
451 /*         { */
452 /*             size_t                      script_length; */
453 /*             const xmlChar *             script_buffer; */
454 /*             xmlNodePtr                  node; */
455
456 /*             node = xmlTextReaderExpand(reader); */
457 /*             if(node) */
458 /*             { */
459 /*                 node = node->children; */
460 /*             } */
461
462 /*             while(node) */
463 /*             { */
464 /*                 if(node->type == XML_TEXT_NODE) */
465 /*                 { */
466 /*                     script_buffer = node->content; */
467 /*                     if(script_buffer) */
468 /*                     { */
469 /*                         script_length = strlen(script_buffer); */
470 /*                         new_buffer = realloc(new_buffer,  */
471 /*                                              new_length + script_length); */
472 /*                         memcpy(new_buffer + new_length,  */
473 /*                                script_buffer, script_length); */
474 /*                         new_length += script_length; */
475 /*                     } */
476 /*                 } */
477
478 /*                 node = node->next; */
479 /*             } */
480 /*         } */
481 /*     } */
482
483 /*     new_buffer = realloc(new_buffer, new_length + 1); */
484 /*     memcpy(new_buffer + new_length, "\0", 1); */
485 /*     new_length += 1; */
486
487 /*     *buffer = new_buffer; */
488 /*     *length = new_length; */
489 /*     return 0; */
490 /* }         */
491
492 static
493 const char *
494 my_strpbrk(
495     const char *                        str,
496     size_t                              str_length,
497     int *                               locator_index,
498     const char *                        delims,
499     int *                               delim_index,
500     int                                 escape)
501 163428 {
502 163428     const char *                        locator;
503 163428     int                                 delim_count, ind, i;
504
505 163428     ind = 0;
506 163428     i = 0;
507 163428     delim_count = strlen(delims);
508 163428     locator = str;
509 6081422     while(*locator && ind < str_length)
510     {
511 17947357         for(i = 0; i < delim_count; ++i)
512         {
513 12029363             if(*locator == delims[i])
514             {
515 147811                 if(escape &&
516                    (ind != 0 && (*(locator - 1) == '\\')))
517                 {
518 3124                     continue;
519                 }
520
521 144687                 if(locator_index)
522                 {
523 144687                     *locator_index = ind;
524                 }
525
526 144687                 if(delim_index)
527                 {
528 144687                     *delim_index = i;
529                 }
530 144687                 return locator;
531             }
532         }
533         
534 5917994         locator++;
535 5917994         ind++;
536     }
537
538 18741     if(locator_index)
539     {
540 18741         *locator_index = -1;
541     }
542 18741     return NULL;
543 }
544
545 static
546 int
547 globus_i_template_convert_chars(
548     const char *                        tmp_buffer,
549     size_t                              tmp_length,
550     char **                             buffer,
551     size_t *                            length,
552     int                                 delim_count,
553     const char *                        delim_set,
554     const char **                       replace_set)
555 27301 {
556 27301     const char *                        locator;
557 27301     const char *                        prev;
558 27301     char *                              new_buffer = NULL;
559 27301     size_t                              new_length = 0;
560 27301     int                                 upto_length, locator_length; 
561 27301     int                                 replace_length;
562 27301     int                                 found_index, delim_index;
563
564 27301     locator = tmp_buffer;
565 27301     locator_length = tmp_length;
566 27301     prev = tmp_buffer;
567 117828     while(1)
568     {
569 117828         if(locator_length <= 0)
570         {
571 8781             break;
572         }
573
574 109047         locator = my_strpbrk(locator, locator_length, &found_index, delim_set, &delim_index, 0);
575 109047         if(!locator)
576         {
577 18520             upto_length = locator_length;
578 18520             new_buffer = realloc(new_buffer, new_length + upto_length);
579 18520             memcpy(new_buffer + new_length, prev, upto_length);
580 18520             new_length += upto_length;
581 18520             break;
582         }
583
584 90527         upto_length = found_index;
585 90527         locator_length -= (found_index + 1);
586
587 90527         replace_length = strlen(replace_set[delim_index]);
588 90527         new_buffer = realloc(new_buffer, 
589                              new_length + replace_length + upto_length);
590 90527         memcpy(new_buffer + new_length, prev, upto_length);
591 90527         memcpy(new_buffer + new_length + upto_length, replace_set[delim_index],
592                replace_length);
593 90527         new_length += upto_length + replace_length;
594
595 90527         locator++;
596 90527         prev = locator;
597         
598     }
599
600 27301     *buffer = new_buffer;
601 27301     *length = new_length;
602
603 27301     return 0;