source: branches/prototype-v0/zoo-project/zoo-kernel/request_parser.c @ 839

Last change on this file since 839 was 839, checked in by djay, 7 years ago

Update the source code for HPC support. Automatically adding nested outputs for the HPC support (should this be available for every support?). Add capability to store the metadata in the Collection DataBase?. Addition of the zcfg2sql to import any existing ZCFG file into the Collection DB. Add the support to invoke a callback (for history purpose) in case a [callback] section contains at least one parameter defined (url). Add support to convert maps and map to JSON (for callback use only by now). Fix some memory leaks (some are still there).

  • Property svn:keywords set to Id
File size: 52.3 KB
Line 
1/*
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2015 GeoLabs SARL
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#include "request_parser.h"
26#include "service_internal.h"
27#include "server_internal.h"
28#include "response_print.h"
29#include "caching.h"
30
31/**
32 * Apply XPath Expression on XML document.
33 *
34 * @param doc the XML Document
35 * @param search the XPath expression
36 * @return xmlXPathObjectPtr containing the resulting nodes set
37 */
38xmlXPathObjectPtr
39extractFromDoc (xmlDocPtr doc, const char *search)
40{
41  xmlXPathContextPtr xpathCtx;
42  xmlXPathObjectPtr xpathObj;
43  xpathCtx = xmlXPathNewContext (doc);
44  xpathObj = xmlXPathEvalExpression (BAD_CAST search, xpathCtx);
45  xmlXPathFreeContext (xpathCtx);
46  return xpathObj;
47}
48
49/**
50 * Create (or append to) an array valued maps value = "["",""]"
51 *
52 * @param m the conf maps containing the main.cfg settings
53 * @param mo the map to update
54 * @param mi the map to append
55 * @param elem the elements containing default definitions
56 * @return 0 on success, -1 on failure
57 */
58int appendMapsToMaps (maps * m, maps * mo, maps * mi, elements * elem){
59  maps *tmpMaps = getMaps (mo, mi->name);
60  map *tmap = getMapType (tmpMaps->content);
61  elements *el = getElements (elem, mi->name);
62  elements *cursor = elem;
63  while(cursor!=NULL && el==NULL){
64    if(cursor->child!=NULL)
65      el = getElements (cursor->child, mi->name);
66    cursor=cursor->next;
67  }
68  int hasEl = 1;
69  if (el == NULL)
70    hasEl = -1;
71
72  if (tmap == NULL)
73    {
74      if (hasEl > 0)
75        tmap = getMapType (el->defaults->content);
76    }
77 
78  map *testMap = NULL;
79  if (hasEl > 0)
80    {
81      testMap = getMap (el->content, "maxOccurs");
82    }
83  else
84    {
85      testMap = createMap ("maxOccurs", "unbounded");
86    }
87   
88  if (testMap != NULL)
89    {
90      if (strncasecmp (testMap->value, "unbounded", 9) != 0
91          && atoi (testMap->value) > 1)
92        {
93          addMapsArrayToMaps (&mo, mi, tmap->name);
94          map* nb=getMapFromMaps(mo,mi->name,"length");
95          if (nb!=NULL && atoi(nb->value)>atoi(testMap->value))
96            {
97              char emsg[1024];
98              sprintf (emsg,
99                       _("The maximum allowed occurrences for <%s> (%i) was exceeded."),
100                       mi->name, atoi (testMap->value));
101              errorException (m, emsg, "InternalError", NULL);
102              return -1;
103            }
104        }
105      else
106        {
107          if (strncasecmp (testMap->value, "unbounded", 9) == 0)
108            {
109              if (hasEl < 0)
110                {
111                  freeMap (&testMap);
112                  free (testMap);
113                }
114              if (addMapsArrayToMaps (&mo, mi, tmap->name) < 0)
115                {
116                  char emsg[1024];
117                  map *tmpMap = getMap (mi->content, "length");
118                  sprintf (emsg,
119                           _
120                           ("ZOO-Kernel was unable to load your data for %s position %s."),
121                           mi->name, tmpMap->value);
122                  errorException (m, emsg, "InternalError", NULL);
123                  return -1;
124                }
125            }
126          else
127            {
128              char emsg[1024];
129              sprintf (emsg,
130                       _
131                       ("The maximum allowed occurrences for <%s> is one."),
132                       mi->name);
133              errorException (m, emsg, "InternalError", NULL);
134              return -1;
135            }
136        }
137    }
138  return 0;
139}
140
141/**
142 * Make sure that each value encoded in base64 in a maps is decoded.
143 *
144 * @param in the maps containing the values
145 * @see readBase64
146 */
147void ensureDecodedBase64(maps **in){
148  maps* cursor=*in;
149  while(cursor!=NULL){
150    map *tmp=getMap(cursor->content,"encoding");
151    if(tmp!=NULL && strncasecmp(tmp->value,"base64",6)==0){
152      tmp=getMap(cursor->content,"value");
153      readBase64(&tmp);
154      addToMap(cursor->content,"base64_value",tmp->value);
155      int size=0;
156      char *s=strdup(tmp->value);
157      free(tmp->value);
158      tmp->value=base64d(s,strlen(s),&size);
159      free(s);
160      char sizes[1024];
161      sprintf(sizes,"%d",size);
162      addToMap(cursor->content,"size",sizes);
163    }
164    map* length=getMap(cursor->content,"length");
165    if(length!=NULL){
166      int len=atoi(length->value);
167      for(int i=1;i<len;i++){
168        tmp=getMapArray(cursor->content,"encoding",i);
169        if(tmp!=NULL && strncasecmp(tmp->value,"base64",6)==0){
170          char key[17];
171          sprintf(key,"base64_value_%d",i);
172          tmp=getMapArray(cursor->content,"value",i);
173          readBase64(&tmp);
174          addToMap(cursor->content,key,tmp->value);
175          int size=0;
176          char *s=strdup(tmp->value);
177          free(tmp->value);
178          tmp->value=base64d(s,strlen(s),&size);
179          free(s);
180          char sizes[1024];
181          sprintf(sizes,"%d",size);
182          sprintf(key,"size_%d",i);
183          addToMap(cursor->content,key,sizes);
184        }
185      }
186    }
187    if(cursor->child!=NULL)
188      ensureDecodedBase64(&cursor->child);
189    cursor=cursor->next;
190  }
191}
192
193/**
194 * Parse inputs provided as KVP and store them in a maps.
195 *
196 * @param main_conf the conf maps containing the main.cfg settings
197 * @param s the service
198 * @param request_inputs the map storing KVP raw value
199 * @param request_output the maps to store the KVP pairs
200 * @param hInternet the HINTERNET queue to add potential requests
201 * @return 0 on success, -1 on failure
202 */
203int kvpParseInputs(maps** main_conf,service* s,map *request_inputs,maps** request_output,HINTERNET* hInternet){
204  // Parsing inputs provided as KVP
205  maps *tmpmaps = *request_output;
206  map* r_inputs = getMap (request_inputs, "DataInputs");
207  char* cursor_input;
208  if (r_inputs != NULL){
209    //snprintf (cursor_input, 40960, "%s", r_inputs->value);
210    if(strstr(r_inputs->value,"=")==NULL)
211      cursor_input = url_decode (r_inputs->value);
212    else
213      cursor_input = zStrdup (r_inputs->value);
214    int j = 0;
215
216    // Put each DataInputs into the inputs_as_text array
217    char *pToken;
218    pToken = strtok (cursor_input, ";");
219    char **inputs_as_text = (char **) malloc (100 * sizeof (char *));
220    if (inputs_as_text == NULL)
221      {
222        free(cursor_input);
223        return errorException (*main_conf, _("Unable to allocate memory"),
224                               "InternalError", NULL);
225      }
226    int i = 0;
227    while (pToken != NULL)
228      {
229        inputs_as_text[i] =
230          (char *) malloc ((strlen (pToken) + 1) * sizeof (char));
231        if (inputs_as_text[i] == NULL)
232          {
233            free(cursor_input);
234            return errorException (*main_conf, _("Unable to allocate memory"),
235                                   "InternalError", NULL);
236          }
237        snprintf (inputs_as_text[i], strlen (pToken) + 1, "%s", pToken);
238        pToken = strtok (NULL, ";");
239        i++;
240      }
241       
242    for (j = 0; j < i; j++)
243      {
244        char *tmp = zStrdup (inputs_as_text[j]);
245        free (inputs_as_text[j]);
246        char *tmpc;
247        tmpc = strtok (tmp, "@");
248        while (tmpc != NULL)
249          {
250            char *tmpv = strstr (tmpc, "=");
251            char tmpn[256];
252            memset (tmpn, 0, 256);
253            if (tmpv != NULL)
254              {
255                strncpy (tmpn, tmpc,
256                         (strlen (tmpc) - strlen (tmpv)) * sizeof (char));
257                tmpn[strlen (tmpc) - strlen (tmpv)] = 0;
258              }
259            else
260              {
261                strncpy (tmpn, tmpc, strlen (tmpc) * sizeof (char));
262                tmpn[strlen (tmpc)] = 0;
263              }
264            if (tmpmaps == NULL)
265              {
266                tmpmaps = createMaps(tmpn);
267                if (tmpmaps == NULL)
268                  {
269                    free(cursor_input);
270                    return errorException (*main_conf,
271                                           _("Unable to allocate memory"),
272                                           "InternalError", NULL);
273                  }
274                if (tmpv != NULL)
275                  {
276                    char *tmpvf = url_decode (tmpv + 1);
277                    tmpmaps->content = createMap ("value", tmpvf);
278                    free (tmpvf);
279                  }
280                else
281                  tmpmaps->content = createMap ("value", "Reference");
282                tmpmaps->next = NULL;
283              }
284            tmpc = strtok (NULL, "@");
285            while (tmpc != NULL)
286              {
287                char *tmpv1 = strstr (tmpc, "=");
288                char tmpn1[1024];
289                memset (tmpn1, 0, 1024);
290                if (tmpv1 != NULL)
291                  {
292                    strncpy (tmpn1, tmpc, strlen (tmpc) - strlen (tmpv1));
293                    tmpn1[strlen (tmpc) - strlen (tmpv1)] = 0;
294                    addToMap (tmpmaps->content, tmpn1, tmpv1 + 1);
295                  }
296                else
297                  {
298                    strncpy (tmpn1, tmpc, strlen (tmpc));
299                    tmpn1[strlen (tmpc)] = 0;
300                    map *lmap = getLastMap (tmpmaps->content);
301                    char *tmpValue =
302                      (char *) malloc ((strlen (tmpv) + strlen (tmpc) + 1) *
303                                       sizeof (char));
304                    sprintf (tmpValue, "%s@%s", tmpv + 1, tmpc);
305                    free (lmap->value);
306                    lmap->value = zStrdup (tmpValue);
307                    free (tmpValue);
308                    tmpc = strtok (NULL, "@");
309                    continue;
310                  }
311                if (strcmp (tmpn1, "xlink:href") != 0)
312                  addToMap (tmpmaps->content, tmpn1, tmpv1 + 1);
313                else if (tmpv1 != NULL)
314                  {
315                    char *tmpx2 = url_decode (tmpv1 + 1);
316                    if (strncasecmp (tmpx2, "http://", 7) != 0 &&
317                        strncasecmp (tmpx2, "ftp://", 6) != 0 &&
318                        strncasecmp (tmpx2, "https://", 8) != 0)
319                      {
320                        char emsg[1024];
321                        sprintf (emsg,
322                                 _
323                                 ("Unable to find a valid protocol to download the remote file %s"),
324                                 tmpv1 + 1);
325                        free(cursor_input);
326                        return errorException (*main_conf, emsg, "InternalError", NULL);
327                      }
328                    addToMap (tmpmaps->content, tmpn1, tmpx2);
329                    {
330                      if (loadRemoteFile
331                          (&*main_conf, &tmpmaps->content, hInternet, tmpx2) < 0)
332                        {
333                          free(cursor_input);
334                          return errorException (*main_conf, "Unable to fetch any resource", "InternalError", NULL);
335                        }
336                      }
337                    free (tmpx2);
338                    addIntToMap (tmpmaps->content, "Order", hInternet->nb);
339                    addToMap (tmpmaps->content, "Reference", tmpv1 + 1);
340                  }
341                tmpc = strtok (NULL, "@");
342              }
343            if (*request_output == NULL)
344              *request_output = dupMaps (&tmpmaps);
345            else
346              {
347                maps *testPresence =
348                  getMaps (*request_output, tmpmaps->name);
349                if (testPresence != NULL)
350                  {
351                    elements *elem =
352                      getElements (s->inputs, tmpmaps->name);
353                    if (elem != NULL)
354                      {
355                        if (appendMapsToMaps
356                            (*main_conf, *request_output, tmpmaps,
357                             elem) < 0)
358                          {
359                            free(cursor_input);
360                            return errorException (*main_conf, "Unable to append maps", "InternalError", NULL);
361                          }
362                      }
363                  }
364                else
365                  addMapsToMaps (request_output, tmpmaps);
366              }
367            freeMaps (&tmpmaps);
368            free (tmpmaps);
369            tmpmaps = NULL;
370            free (tmp);
371          }
372      }
373    free (inputs_as_text);
374    free(cursor_input);
375  }
376  return 1;
377}
378
379/**
380 * Parse outputs provided as KVP and store them in a maps.
381 *
382 * @param main_conf the conf maps containing the main.cfg settings
383 * @param request_inputs the map storing KVP raw value
384 * @param request_output the maps to store the KVP pairs
385 * @return 0 on success, -1 on failure
386 */
387int kvpParseOutputs(maps** main_conf,map *request_inputs,maps** request_output){
388  /**
389   * Parsing outputs provided as KVP
390   */
391  map *r_inputs = NULL;
392  r_inputs = getMap (request_inputs, "ResponseDocument");
393  if (r_inputs == NULL)
394    r_inputs = getMap (request_inputs, "RawDataOutput");
395
396  if (r_inputs != NULL)
397    {
398      char *cursor_output = zStrdup (r_inputs->value);
399      int j = 0;
400
401      /**
402       * Put each Output into the outputs_as_text array
403       */
404      char *pToken;
405      maps *tmp_output = NULL;
406      pToken = strtok (cursor_output, ";");
407      char **outputs_as_text = (char **) malloc (128 * sizeof (char *));
408      if (outputs_as_text == NULL)
409        {
410          free(cursor_output);
411          return errorException (*main_conf, _("Unable to allocate memory"),
412                                 "InternalError", NULL);
413        }
414      int i = 0;
415      while (pToken != NULL)
416        {
417          outputs_as_text[i] =
418            (char *) malloc ((strlen (pToken) + 1) * sizeof (char));
419          if (outputs_as_text[i] == NULL)
420            {
421              free(cursor_output);
422              return errorException (*main_conf, _("Unable to allocate memory"),
423                                     "InternalError", NULL);
424            }
425          snprintf (outputs_as_text[i], strlen (pToken) + 1, "%s",
426                    pToken);
427          pToken = strtok (NULL, ";");
428          i++;
429        }
430      for (j = 0; j < i; j++)
431        {
432          char *tmp = zStrdup (outputs_as_text[j]);
433          free (outputs_as_text[j]);
434          char *tmpc;
435          tmpc = strtok (tmp, "@");
436          int k = 0;
437          while (tmpc != NULL)
438            {
439              if (k == 0)
440                {
441                  if (tmp_output == NULL)
442                    {
443                      tmp_output = createMaps(tmpc);
444                      if (tmp_output == NULL)
445                        {
446                          free(cursor_output);
447                          return errorException (*main_conf,
448                                                 _
449                                                 ("Unable to allocate memory"),
450                                                 "InternalError", NULL);
451                        }
452                    }
453                }
454              else
455                {
456                  char *tmpv = strstr (tmpc, "=");
457                  char tmpn[256];
458                  memset (tmpn, 0, 256);
459                  strncpy (tmpn, tmpc,
460                           (strlen (tmpc) -
461                            strlen (tmpv)) * sizeof (char));
462                  tmpn[strlen (tmpc) - strlen (tmpv)] = 0;
463                  if (tmp_output->content == NULL)
464                    {
465                      tmp_output->content = createMap (tmpn, tmpv + 1);
466                      tmp_output->content->next = NULL;
467                    }
468                  else
469                    addToMap (tmp_output->content, tmpn, tmpv + 1);
470                }
471              k++;
472              tmpc = strtok (NULL, "@");
473            }
474          if (*request_output == NULL)
475            *request_output = dupMaps (&tmp_output);
476          else
477            addMapsToMaps (request_output, tmp_output);
478          freeMaps (&tmp_output);
479          free (tmp_output);
480          tmp_output = NULL;
481          free (tmp);
482        }
483      free (outputs_as_text);
484      free(cursor_output);
485    }
486  return 1;
487}
488
489/**
490 * Create a "missingIdentifier" maps in case it is NULL.
491 *
492 * @param main_conf the conf maps containing the main.cfg settings
493 * @param mymaps the maps to update
494 * @return 0 on success, 4 on failure
495 */
496int defineMissingIdentifier(maps** main_conf,maps** mymaps){
497  if (*mymaps == NULL){
498    *mymaps = createMaps("missingIndetifier");
499    if (*mymaps == NULL){
500      return errorException (*main_conf,
501                             _("Unable to allocate memory"),
502                             "InternalError", NULL);
503    }
504  }
505  return 0;
506}
507
508/**
509 * Parse inputs from XML nodes and store them in a maps.
510 *
511 * @param main_conf the conf maps containing the main.cfg settings
512 * @param s the service
513 * @param request_output the maps to store the KVP pairs
514 * @param doc the xmlDocPtr containing the original request
515 * @param nodes the input nodes array
516 * @param hInternet the HINTERNET queue to add potential requests
517 * @return 0 on success, -1 on failure
518 */
519int xmlParseInputs(maps** main_conf,service* s,maps** request_output,xmlDocPtr doc,xmlNodeSet* nodes,HINTERNET* hInternet){
520  int k = 0;
521  int l = 0;
522  map* version=getMapFromMaps(*main_conf,"main","rversion");
523  int vid=getVersionId(version->value);
524  for (k=0; k < nodes->nodeNr; k++)
525    {
526      maps *tmpmaps = NULL;
527      xmlNodePtr cur = nodes->nodeTab[k];
528
529      if (nodes->nodeTab[k]->type == XML_ELEMENT_NODE)
530        {
531          // A specific Input node.
532          if(vid==1){
533            xmlChar *val = xmlGetProp (cur, BAD_CAST "id");
534            tmpmaps = createMaps((char *) val);
535            xmlFree(val);
536          }
537
538          xmlNodePtr cur2 = cur->children;
539          while (cur2 != NULL)
540            {
541              while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE)
542                cur2 = cur2->next;
543              if (cur2 == NULL)
544                break;
545              // Indentifier
546              if (xmlStrncasecmp
547                  (cur2->name, BAD_CAST "Identifier",
548                   xmlStrlen (cur2->name)) == 0)
549                {
550                  xmlChar *val =
551                    xmlNodeListGetString (doc, cur2->xmlChildrenNode, 1);
552                  if (tmpmaps == NULL && val!=NULL)
553                    {
554                      tmpmaps = createMaps((char*)val);
555                      if (tmpmaps == NULL)
556                        {
557                          return errorException (*main_conf,
558                                                 _
559                                                 ("Unable to allocate memory"),
560                                                 "InternalError", NULL);
561                        }
562                      xmlFree (val);
563                    }
564                }
565              // Title, Asbtract
566              if (xmlStrncasecmp
567                  (cur2->name, BAD_CAST "Title",
568                   xmlStrlen (cur2->name)) == 0
569                  || xmlStrncasecmp (cur2->name, BAD_CAST "Abstract",
570                                     xmlStrlen (cur2->name)) == 0)
571                {
572                  xmlChar *val =
573                    xmlNodeListGetString (doc, cur2->xmlChildrenNode, 1);
574                  defineMissingIdentifier(main_conf,&tmpmaps);
575                  if(val!=NULL){
576                    if (tmpmaps->content != NULL)
577                      addToMap (tmpmaps->content,
578                                (char *) cur2->name, (char *) val);
579                    else
580                      tmpmaps->content =
581                        createMap ((char *) cur2->name, (char *) val);
582                    xmlFree (val);
583                  }
584                }
585              // InputDataFormChoice (Reference or Data ?) / 2.0.0 DataInputType / Input
586              if (xmlStrcasecmp (cur2->name, BAD_CAST "Input") == 0)
587                {
588                  char *xpathExpr=(char*)malloc(61+strlen(tmpmaps->name));
589                  sprintf(xpathExpr,"/*/*[local-name()='Input' and @id='%s']/*[local-name()='Input']",tmpmaps->name);
590                  xmlXPathObjectPtr tmpsptr = extractFromDoc (doc, xpathExpr);
591                  xmlNodeSet *tmps = tmpsptr->nodesetval;
592                  if(tmps!=NULL){
593                    maps* request_output1=NULL;
594                    if(xmlParseInputs(main_conf,s,&request_output1,doc,tmps,hInternet)<0)
595                      return -1;
596                    if(tmpmaps->child==NULL)
597                      tmpmaps->child=dupMaps(&request_output1);
598                    else
599                      addMapsToMaps(&tmpmaps->child,request_output1);
600                    freeMaps(&request_output1);
601                    free(request_output1);
602                  }
603                  while(cur2->next!=NULL)
604                    cur2=cur2->next;
605                }
606              else if (xmlStrcasecmp (cur2->name, BAD_CAST "Reference") == 0)
607                {
608                  defineMissingIdentifier(main_conf,&tmpmaps);
609                  // Get every attribute from a Reference node
610                  // mimeType, encoding, schema, href, method
611                  // Header and Body gesture should be added here
612                  const char *refs[5] =
613                    { "mimeType", "encoding", "schema", "method",
614                      "href"
615                    };
616                  for (l = 0; l < 5; l++)
617                    {
618                      xmlChar *val = xmlGetProp (cur2, BAD_CAST refs[l]);
619                      if (val != NULL && xmlStrlen (val) > 0)
620                        {
621                          if (tmpmaps->content != NULL)
622                            addToMap (tmpmaps->content, refs[l],
623                                      (char *) val);
624                          else
625                            tmpmaps->content =
626                              createMap (refs[l], (char *) val);
627                          map *ltmp = getMap (tmpmaps->content, "method");
628                          if (l == 4 )
629                            {
630                              if ((ltmp==NULL || strncmp (ltmp->value, "POST",4) != 0))
631                                {
632                                  if (loadRemoteFile
633                                      (main_conf, &tmpmaps->content, hInternet,
634                                       (char *) val) != 0)
635                                    {
636                                      return errorException (*main_conf,
637                                                             _("Unable to add a request in the queue."),
638                                                             "InternalError",
639                                                             NULL);
640                                    }
641                                  addIntToMap (tmpmaps->content, "Order", hInternet->nb);
642                                }
643                              addToMap (tmpmaps->content, "Reference", (char*) val);
644                            }
645                        }
646                      xmlFree (val);
647                    }
648                  // Parse Header and Body from Reference
649                  xmlNodePtr cur3 = cur2->children;
650                  while (cur3 != NULL)
651                    {
652                      while (cur3 != NULL
653                             && cur3->type != XML_ELEMENT_NODE)
654                        cur3 = cur3->next;
655                      if (cur3 == NULL)
656                        break;
657                      if (xmlStrcasecmp (cur3->name, BAD_CAST "Header") ==
658                          0)
659                        {
660                          const char *ha[2];
661                          ha[0] = "key";
662                          ha[1] = "value";
663                          int hai;
664                          char *has=NULL;
665                          char *key;
666                          for (hai = 0; hai < 2; hai++)
667                            {
668                              xmlChar *val =
669                                xmlGetProp (cur3, BAD_CAST ha[hai]);
670#ifdef POST_DEBUG
671                              fprintf (stderr, "%s = %s\n", ha[hai],
672                                       (char *) val);
673#endif
674                              if (hai == 0)
675                                {
676                                  key = zStrdup ((char *) val);
677                                }
678                              else
679                                {
680                                  has =
681                                    (char *)
682                                    malloc ((4 + xmlStrlen (val) +
683                                             strlen (key)) *
684                                            sizeof (char));
685                                  if (has == NULL)
686                                    {
687                                      return errorException (*main_conf,
688                                                             _
689                                                             ("Unable to allocate memory"),
690                                                             "InternalError",
691                                                             NULL);
692                                    }
693                                  snprintf (has,
694                                            (3 + xmlStrlen (val) +
695                                             strlen (key)), "%s: %s", key,
696                                            (char *) val);
697                                  free (key);
698                                }
699                              xmlFree (val);
700                            }
701                          if (has != NULL){
702                            hInternet->ihandle[hInternet->nb].header = NULL;
703                            hInternet->ihandle[hInternet->nb].header =
704                              curl_slist_append (hInternet->ihandle
705                                                 [hInternet->nb].header,
706                                                 has);
707                            free (has);
708                          }
709                        }
710                      else
711                        {
712#ifdef POST_DEBUG
713                          fprintf (stderr,
714                                   "Try to fetch the body part of the request ...\n");
715#endif
716                          if (xmlStrcasecmp (cur3->name, BAD_CAST "Body")
717                              == 0)
718                            {
719#ifdef POST_DEBUG
720                              fprintf (stderr, "Body part found (%s) !!!\n",
721                                       (char *) cur3->content);
722#endif
723                              char *tmp = NULL;
724                              xmlNodePtr cur4 = cur3->children;
725                              while (cur4 != NULL)
726                                {
727                                  while (cur4 && cur4 != NULL && cur4->type && cur4->type != XML_ELEMENT_NODE){
728                                    if(cur4->next)
729                                      cur4 = cur4->next;
730                                    else
731                                      cur4 = NULL;
732                                  }
733                                  if(cur4 != NULL) {
734                                    xmlDocPtr bdoc =
735                                      xmlNewDoc (BAD_CAST "1.0");
736                                    bdoc->encoding =
737                                      xmlCharStrdup ("UTF-8");
738                                    xmlDocSetRootElement (bdoc, cur4);
739                                    xmlChar *btmps;
740                                    int bsize;
741                                    // TODO : check for encoding defined in the input
742                                    xmlDocDumpFormatMemoryEnc(bdoc, &btmps, &bsize, "UTF-8", 0);
743                                    if (btmps != NULL){
744                                      tmp = (char *) malloc ((bsize + 1) * sizeof (char));
745
746                                      sprintf (tmp, "%s", (char*) btmps);
747
748                                      //xmlFreeDoc (bdoc);
749                                         
750                                      map *btmp =
751                                        getMap (tmpmaps->content, "Reference");
752                                      addToMap (tmpmaps->content, "Body", tmp);
753                                      if (btmp != NULL)
754                                        {
755                                          addRequestToQueue(main_conf,hInternet,(char *) btmp->value,false);
756                                          InternetOpenUrl (hInternet,
757                                                           btmp->value,
758                                                           tmp,
759                                                           xmlStrlen(btmps),
760                                                           INTERNET_FLAG_NO_CACHE_WRITE,
761                                                           0);
762                                          addIntToMap (tmpmaps->content, "Order", hInternet->nb);
763                                        }
764                                      xmlFree (btmps);
765                                      free (tmp);
766                                      break;
767                                    }
768                                  }
769                                  cur4 = cur4->next;
770                                }
771                            }
772                          else
773                            if (xmlStrcasecmp
774                                (cur3->name,
775                                 BAD_CAST "BodyReference") == 0)
776                              {
777                                xmlChar *val =
778                                  xmlGetProp (cur3, BAD_CAST "href");
779                                HINTERNET bInternet, res1, res;
780                                bInternet = InternetOpen (
781#ifndef WIN32
782                                                          (LPCTSTR)
783#endif
784                                                          "ZooWPSClient\0",
785                                                          INTERNET_OPEN_TYPE_PRECONFIG,
786                                                          NULL, NULL, 0);
787                                if (!CHECK_INET_HANDLE (bInternet))
788                                  fprintf (stderr,
789                                           "WARNING : bInternet handle failed to initialize");
790                                bInternet.waitingRequests[0] =
791                                  strdup ((char *) val);
792                                res1 =
793                                  InternetOpenUrl (&bInternet,
794                                                   bInternet.waitingRequests
795                                                   [0], NULL, 0,
796                                                   INTERNET_FLAG_NO_CACHE_WRITE,
797                                                   0);
798                                processDownloads (&bInternet);
799                                char *tmp =
800                                  (char *)
801                                  malloc ((bInternet.ihandle[0].nDataLen +
802                                           1) * sizeof (char));
803                                if (tmp == NULL)
804                                  {
805                                    return errorException (*main_conf,
806                                                           _
807                                                           ("Unable to allocate memory"),
808                                                           "InternalError",
809                                                           NULL);
810                                  }
811                                size_t bRead;
812                                InternetReadFile (bInternet.ihandle[0],
813                                                  (LPVOID) tmp,
814                                                  bInternet.
815                                                  ihandle[0].nDataLen,
816                                                  &bRead);
817                                tmp[bInternet.ihandle[0].nDataLen] = 0;
818                                InternetCloseHandle(&bInternet);
819                                addToMap (tmpmaps->content, "Body", tmp);
820                                map *btmp =
821                                  getMap (tmpmaps->content, "href");
822                                if (btmp != NULL)
823                                  {
824                                    addRequestToQueue(main_conf,hInternet,(char *) btmp->value,false);
825
826                                    res =
827                                      InternetOpenUrl (hInternet,
828                                                       btmp->value,
829                                                       tmp,
830                                                       strlen(tmp),
831                                                       INTERNET_FLAG_NO_CACHE_WRITE,
832                                                       0);
833                                    addIntToMap (tmpmaps->content, "Order", hInternet->nb);
834                                  }
835                                free (tmp);
836                                xmlFree (val);
837                              }
838                        }
839                      cur3 = cur3->next;
840                    }
841                }
842              else if (xmlStrcasecmp (cur2->name, BAD_CAST "Data") == 0)
843                {
844                  defineMissingIdentifier(main_conf,&tmpmaps);
845                  xmlNodePtr cur4 = cur2->children;
846                  if(vid==1){
847                    // Get every dataEncodingAttributes from a Data node:
848                    // mimeType, encoding, schema
849                    const char *coms[3] =
850                      { "mimeType", "encoding", "schema" };
851                    for (l = 0; l < 3; l++){
852                      xmlChar *val =
853                          xmlGetProp (cur4, BAD_CAST coms[l]);
854                        if (val != NULL && strlen ((char *) val) > 0){
855                          if (tmpmaps->content != NULL)
856                            addToMap (tmpmaps->content,coms[l],(char *) val);
857                          else
858                            tmpmaps->content =
859                              createMap (coms[l],(char *) val);
860                        }
861                        xmlFree (val);
862                    }
863                    while (cur4 != NULL){
864                      while(cur4 != NULL && 
865                            cur4->type != XML_CDATA_SECTION_NODE &&
866                            cur4->type != XML_TEXT_NODE &&
867                            cur4->type != XML_ELEMENT_NODE)
868                        cur4=cur4->next;
869                      if(cur4!=NULL){
870                        if (cur4->type == XML_ELEMENT_NODE)
871                          {
872                            xmlChar *mv;
873                            int buffersize;
874                            xmlDocPtr doc1 = xmlNewDoc (BAD_CAST "1.0");
875                            xmlDocSetRootElement (doc1, cur4);
876                            xmlDocDumpFormatMemoryEnc (doc1, &mv,
877                                                       &buffersize,
878                                                       "utf-8", 0);
879                            if (tmpmaps->content != NULL)
880                              addToMap (tmpmaps->content, "value",
881                                        (char *) mv);
882                            else
883                              tmpmaps->content =
884                                createMap ("value", (char *) mv);
885                            free(mv);
886                          }
887                        else{
888                          if (tmpmaps->content != NULL)
889                            addToMap (tmpmaps->content, "value",
890                                      (char *) cur4->content);
891                          else
892                            tmpmaps->content =
893                              createMap ("value", (char *) cur4->content);
894                        }
895                        cur4=cur4->next;
896                      }
897                    }
898                  }
899
900
901                  while (cur4 != NULL)
902                    {
903                      while (cur4 != NULL
904                             && cur4->type != XML_ELEMENT_NODE)
905                        cur4 = cur4->next;
906                      if (cur4 == NULL)
907                        break;
908                      if (xmlStrcasecmp
909                          (cur4->name, BAD_CAST "LiteralData") == 0)
910                        {
911                          // Get every attribute from a LiteralData node
912                          // dataType , uom
913                          char *list[2];
914                          list[0] = zStrdup ("dataType");
915                          list[1] = zStrdup ("uom");
916                          for (l = 0; l < 2; l++)
917                            {
918                              xmlChar *val =
919                                xmlGetProp (cur4, BAD_CAST list[l]);
920                              if (val != NULL
921                                  && strlen ((char *) val) > 0)
922                                {
923                                  if (tmpmaps->content != NULL)
924                                    addToMap (tmpmaps->content, list[l],
925                                              (char *) val);
926                                  else
927                                    tmpmaps->content =
928                                      createMap (list[l], (char *) val);
929                                }
930                              xmlFree (val);
931                              free (list[l]);
932                            }
933                        }
934                      else
935                        if (xmlStrcasecmp
936                            (cur4->name, BAD_CAST "ComplexData") == 0)
937                          {
938                            // Get every attribute from a Reference node
939                            // mimeType, encoding, schema
940                            const char *coms[3] =
941                              { "mimeType", "encoding", "schema" };
942                            for (l = 0; l < 3; l++)
943                              {
944                                xmlChar *val =
945                                  xmlGetProp (cur4, BAD_CAST coms[l]);
946                                if (val != NULL
947                                    && strlen ((char *) val) > 0)
948                                  {
949                                    if (tmpmaps->content != NULL)
950                                      addToMap (tmpmaps->content, coms[l],
951                                                (char *) val);
952                                    else
953                                      tmpmaps->content =
954                                        createMap (coms[l], (char *) val);
955                                  }
956                                xmlFree (val);
957                              }
958                          }
959
960                      map *test = getMap (tmpmaps->content, "encoding");
961
962                      if (test == NULL)
963                        { 
964                          if (tmpmaps->content != NULL)
965                            addToMap (tmpmaps->content, "encoding",
966                                      "utf-8");
967                          else
968                            tmpmaps->content =
969                              createMap ("encoding", "utf-8");
970                          test = getMap (tmpmaps->content, "encoding");
971                        }
972
973                      if (strcasecmp (test->value, "base64") != 0)
974                        { 
975                          xmlChar *mv = xmlNodeListGetString (doc,
976                                                              cur4->xmlChildrenNode,
977                                                              1);
978                          map *ltmp =
979                            getMap (tmpmaps->content, "mimeType");
980                          if (mv == NULL
981                              ||
982                              (xmlStrcasecmp
983                               (cur4->name, BAD_CAST "ComplexData") == 0
984                               && (ltmp == NULL
985                                   || strncasecmp (ltmp->value,
986                                                   "text/xml", 8) == 0)))
987                            {
988                              xmlDocPtr doc1 = xmlNewDoc (BAD_CAST "1.0");
989                              int buffersize;
990                              xmlNodePtr cur5 = cur4->children;
991                              while (cur5 != NULL
992                                     && cur5->type != XML_ELEMENT_NODE
993                                     && cur5->type != XML_CDATA_SECTION_NODE)
994                                cur5 = cur5->next;
995                              if (cur5 != NULL
996                                  && cur5->type != XML_CDATA_SECTION_NODE)
997                                {
998                                  xmlDocSetRootElement (doc1, cur5);
999                                  xmlDocDumpFormatMemoryEnc (doc1, &mv,
1000                                                             &buffersize,
1001                                                             "utf-8", 0);
1002                                }
1003                              else
1004                                {
1005                                  if (cur5 != NULL
1006                                      && cur5->type == XML_CDATA_SECTION_NODE){
1007                                    xmlDocPtr doc2 = xmlReadMemory((const char*)cur5->content,xmlStrlen(cur5->content),
1008                                                                   "input_content.xml", NULL, XML_PARSE_RECOVER);
1009                                    xmlDocDumpFormatMemoryEnc (doc2, &mv,
1010                                                               &buffersize,
1011                                                               "utf-8", 0);
1012                                    xmlFreeDoc (doc2);
1013                                  }
1014                                }
1015                              addIntToMap (tmpmaps->content, "size",
1016                                           buffersize);
1017                              xmlFreeDoc (doc1);
1018                            }else{
1019                            xmlNodePtr cur5 = cur4->children;
1020                            while (cur5 != NULL
1021                                   && cur5->type != XML_CDATA_SECTION_NODE)
1022                              cur5 = cur5->next;
1023                            if (cur5 != NULL
1024                                && cur5->type == XML_CDATA_SECTION_NODE){
1025                              xmlFree(mv);
1026                              mv=xmlStrdup(cur5->content);
1027                            }
1028                          }
1029                          if (mv != NULL)
1030                            {
1031                              addToMap (tmpmaps->content, "value",
1032                                        (char*) mv);
1033                              xmlFree (mv);
1034                            }
1035                        }
1036                      else
1037                        {
1038                          xmlChar *tmp = xmlNodeListGetRawString (doc,
1039                                                                  cur4->xmlChildrenNode,
1040                                                                  0);
1041                          addToMap (tmpmaps->content, "value",
1042                                    (char *) tmp);
1043                          xmlFree (tmp);
1044                        }
1045
1046                      cur4 = cur4->next;
1047                    }
1048                }
1049              cur2 = cur2->next;
1050              while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE){
1051                cur2 = cur2->next;
1052              }
1053            }
1054          {
1055            map* test=getMap(tmpmaps->content,"value");
1056            if(test==NULL && tmpmaps->child==NULL)
1057              addToMap(tmpmaps->content,"value","");
1058            maps *testPresence = getMaps (*request_output, tmpmaps->name);
1059            maps *cursor=*request_output;
1060            while(testPresence == NULL && cursor!=NULL){
1061              if(cursor->child!=NULL){
1062                testPresence = getMaps (cursor->child, tmpmaps->name);
1063              }
1064              cursor=cursor->next;
1065            }
1066            if (testPresence != NULL)
1067              {
1068                elements *elem = getElements (s->inputs, tmpmaps->name);
1069                elements *cursor=s->inputs;
1070                while(elem == NULL && cursor!=NULL){
1071                  if(cursor->child!=NULL){
1072                    elem = getElements (cursor->child, tmpmaps->name);
1073                  }
1074                  cursor=cursor->next;
1075                }
1076                if (elem != NULL)
1077                  {
1078                    if (appendMapsToMaps
1079                        (*main_conf, testPresence, tmpmaps, elem) < 0)
1080                      {
1081                        return errorException (*main_conf,
1082                                               _("Unable to append maps to maps."),
1083                                               "InternalError",
1084                                               NULL);
1085                      }
1086                  }
1087              }
1088            else
1089              addMapsToMaps (request_output, tmpmaps);
1090          }
1091          freeMaps (&tmpmaps);
1092          free (tmpmaps);
1093          tmpmaps = NULL;
1094        }
1095    }
1096  return 1;
1097}
1098
1099/**
1100 * Parse outputs from XML nodes and store them in a maps (WPS version 2.0.0).
1101 *
1102 * @param main_conf the conf maps containing the main.cfg settings
1103 * @param request_inputs the map storing KVP raw value
1104 * @param request_output the maps to store the KVP pairs
1105 * @param doc the xmlDocPtr containing the original request
1106 * @param cur the xmlNodePtr corresponding to the ResponseDocument or RawDataOutput XML node
1107 * @param raw true if the node is RawDataOutput, false in case of ResponseDocument
1108 * @return 0 on success, -1 on failure
1109 */
1110int xmlParseOutputs2(maps** main_conf,map** request_inputs,maps** request_output,xmlDocPtr doc,xmlNodeSet* nodes){
1111  int k = 0;
1112  int l = 0;
1113  for (k=0; k < nodes->nodeNr; k++){
1114    maps *tmpmaps = NULL;
1115    xmlNodePtr cur = nodes->nodeTab[k];
1116    if (cur->type == XML_ELEMENT_NODE){
1117      maps *tmpmaps = NULL;
1118      xmlChar *val = xmlGetProp (cur, BAD_CAST "id");
1119      if(val!=NULL)
1120        tmpmaps = createMaps((char *)val);
1121      else
1122        tmpmaps = createMaps("unknownIdentifier");
1123      const char ress[4][13] =
1124        { "mimeType", "encoding", "schema", "transmission" };
1125      xmlFree (val);
1126      for (l = 0; l < 4; l++){
1127        val = xmlGetProp (cur, BAD_CAST ress[l]);
1128        if (val != NULL && strlen ((char *) val) > 0)
1129          {
1130            if (tmpmaps->content != NULL)
1131              addToMap (tmpmaps->content, ress[l],
1132                        (char *) val);
1133            else
1134              tmpmaps->content =
1135                createMap (ress[l], (char *) val);
1136            if(l==3 && strncasecmp((char*)val,"reference",xmlStrlen(val))==0)
1137              addToMap (tmpmaps->content,"asReference","true");
1138          }
1139        xmlFree (val);
1140      }
1141      if(cur->children!=NULL){
1142        xmlNodePtr ccur = cur->children;
1143        while (ccur != NULL){
1144          if(ccur->type == XML_ELEMENT_NODE){
1145            char *xpathExpr=(char*)malloc(66+strlen(tmpmaps->name));
1146            sprintf(xpathExpr,"/*/*[local-name()='Output' and @id='%s']/*[local-name()='Output']",tmpmaps->name);           
1147            xmlXPathObjectPtr tmpsptr = extractFromDoc (doc, xpathExpr);
1148            xmlNodeSet* cnodes = tmpsptr->nodesetval;
1149            xmlParseOutputs2(main_conf,request_inputs,&tmpmaps->child,doc,cnodes);
1150            xmlXPathFreeObject (tmpsptr);
1151            free(xpathExpr);
1152            break;
1153          }
1154          ccur = ccur->next;
1155        }
1156      }
1157      if (*request_output == NULL){
1158        *request_output = dupMaps(&tmpmaps);
1159      }
1160      else{
1161        addMapsToMaps(request_output,tmpmaps);
1162      }
1163      freeMaps(&tmpmaps);
1164      free(tmpmaps);
1165    }
1166  }
1167  return 0;
1168}
1169
1170/**
1171 * Parse outputs from XML nodes and store them in a maps.
1172 *
1173 * @param main_conf the conf maps containing the main.cfg settings
1174 * @param request_inputs the map storing KVP raw value
1175 * @param request_output the maps to store the KVP pairs
1176 * @param doc the xmlDocPtr containing the original request
1177 * @param cur the xmlNodePtr corresponding to the ResponseDocument or RawDataOutput XML node
1178 * @param raw true if the node is RawDataOutput, false in case of ResponseDocument
1179 * @return 0 on success, -1 on failure
1180 */
1181int xmlParseOutputs(maps** main_conf,map** request_inputs,maps** request_output,xmlDocPtr doc,xmlNodePtr cur,bool raw){
1182  int l=0;
1183  if( raw == true)
1184    {
1185      addToMap (*request_inputs, "RawDataOutput", "");
1186      if (cur->type == XML_ELEMENT_NODE)
1187        {
1188
1189          maps *tmpmaps = createMaps("unknownIdentifier");
1190          if (tmpmaps == NULL)
1191            {
1192              return errorException (*main_conf, _("Unable to allocate memory"),
1193                                     "InternalError", NULL);
1194            }
1195
1196          // Get every attribute from a RawDataOutput node
1197          // mimeType, encoding, schema, uom
1198          const char *outs[4] =
1199            { "mimeType", "encoding", "schema", "uom" };
1200          for (l = 0; l < 4; l++)
1201            {
1202              xmlChar *val = xmlGetProp (cur, BAD_CAST outs[l]);
1203              if (val != NULL)
1204                {
1205                  if (strlen ((char *) val) > 0)
1206                    {
1207                      if (tmpmaps->content != NULL)
1208                        addToMap (tmpmaps->content, outs[l],
1209                                  (char *) val);
1210                      else
1211                        tmpmaps->content =
1212                          createMap (outs[l], (char *) val);
1213                    }
1214                  xmlFree (val);
1215                }
1216            }
1217          xmlNodePtr cur2 = cur->children;
1218          while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE)
1219            cur2 = cur2->next;
1220          while (cur2 != NULL)
1221            {
1222              if (xmlStrncasecmp
1223                  (cur2->name, BAD_CAST "Identifier",
1224                   xmlStrlen (cur2->name)) == 0)
1225                {
1226                  xmlChar *val =
1227                    xmlNodeListGetString (NULL, cur2->xmlChildrenNode, 1);
1228                  free (tmpmaps->name);
1229                  tmpmaps->name = zStrdup ((char *) val);
1230                  xmlFree (val);
1231                }
1232              cur2 = cur2->next;
1233              while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE)
1234                cur2 = cur2->next;
1235            }
1236          if (*request_output == NULL)
1237            *request_output = dupMaps (&tmpmaps);
1238          else
1239            addMapsToMaps (request_output, tmpmaps);
1240          if (tmpmaps != NULL)
1241            {
1242              freeMaps (&tmpmaps);
1243              free (tmpmaps);
1244              tmpmaps = NULL;
1245            }
1246        }
1247    }
1248  else
1249    {
1250      addToMap (*request_inputs, "ResponseDocument", "");
1251
1252      if (cur->type == XML_ELEMENT_NODE) {
1253        // Get every attribute: storeExecuteResponse, lineage, status
1254        const char *ress[3] =
1255          { "storeExecuteResponse", "lineage", "status" };
1256        xmlChar *val;
1257        for (l = 0; l < 3; l++)
1258          {
1259            val = xmlGetProp (cur, BAD_CAST ress[l]);
1260            if (val != NULL && strlen ((char *) val) > 0)
1261              {
1262                addToMap (*request_inputs, ress[l], (char *) val);
1263              }
1264            xmlFree (val);
1265          }
1266                       
1267        xmlNodePtr cur1 = cur->children;               
1268        while (cur1 != NULL) // iterate over Output nodes
1269          {
1270            if (cur1->type != XML_ELEMENT_NODE || 
1271                xmlStrncasecmp(cur1->name, BAD_CAST "Output", 
1272                               xmlStrlen (cur1->name)) != 0) {
1273              cur1 = cur1->next;
1274              continue;
1275            }
1276                               
1277            maps *tmpmaps = createMaps("unknownIdentifier"); // one per Output node
1278            if (tmpmaps == NULL) {
1279              return errorException (*main_conf,
1280                                     _
1281                                     ("Unable to allocate memory"),
1282                                     "InternalError", NULL);
1283            }
1284                               
1285            xmlNodePtr elems = cur1->children;
1286                               
1287            while (elems != NULL) {
1288
1289              // Identifier
1290              if (xmlStrncasecmp
1291                  (elems->name, BAD_CAST "Identifier",
1292                   xmlStrlen (elems->name)) == 0)
1293                {
1294                  xmlChar *val =
1295                    xmlNodeListGetString (doc, elems->xmlChildrenNode, 1);
1296               
1297                  free(tmpmaps->name);
1298                  tmpmaps->name = zStrdup ((char *) val);
1299                  if (tmpmaps->content == NULL) {
1300                    tmpmaps->content = createMap("Identifier", zStrdup ((char *) val));
1301                  }
1302                  else {
1303                    addToMap(tmpmaps->content, "Identifier", zStrdup ((char *) val));
1304                  }
1305
1306                  map* tt = getMap (*request_inputs, "ResponseDocument");
1307                  if (strlen(tt->value) == 0) {
1308                    addToMap (*request_inputs, "ResponseDocument",
1309                              (char *) val);
1310                  }
1311                  else {
1312                    char* tmp = (char*) malloc((strlen(tt->value) + 1 
1313                                                + strlen((char*) val) + 1) * sizeof(char));
1314                    sprintf (tmp, "%s;%s", tt->value, (char *) val);
1315                    free(tt->value);
1316                    tt->value = tmp;
1317                  }
1318                  xmlFree (val);
1319                }
1320             
1321              // Title, Abstract
1322              else if (xmlStrncasecmp(elems->name, BAD_CAST "Title",
1323                                      xmlStrlen (elems->name)) == 0
1324                       || xmlStrncasecmp(elems->name, BAD_CAST "Abstract",
1325                                         xmlStrlen (elems->name)) == 0)
1326                {
1327                  xmlChar *val =
1328                    xmlNodeListGetString (doc, elems->xmlChildrenNode, 1);
1329                                                       
1330                  if (tmpmaps->content == NULL) {
1331                    tmpmaps->content = createMap((char*) elems->name, zStrdup ((char *) val));
1332                  }
1333                  else {
1334                    addToMap(tmpmaps->content, (char*) elems->name, zStrdup ((char *) val));
1335                  }
1336                  xmlFree (val);
1337                }
1338              elems = elems->next;
1339            }
1340                               
1341            // Get every attribute from an Output node:
1342            // mimeType, encoding, schema, uom, asReference
1343            const char *outs[5] =
1344              { "mimeType", "encoding", "schema", "uom", "asReference" };
1345                                         
1346            for (l = 0; l < 5; l++) {
1347              xmlChar *val = xmlGetProp (cur1, BAD_CAST outs[l]);                               
1348              if (val != NULL && xmlStrlen(val) > 0) {
1349                if (tmpmaps->content != NULL) {
1350                  addToMap (tmpmaps->content, outs[l], (char *) val);
1351                }                         
1352                else {
1353                  tmpmaps->content = createMap (outs[l], (char *) val);
1354                }       
1355              }
1356              xmlFree (val);
1357            }
1358                               
1359            if (*request_output == NULL) {
1360              *request_output = tmpmaps;
1361            }   
1362            else if (getMaps(*request_output, tmpmaps->name) != NULL) {
1363              return errorException (*main_conf,
1364                                     _
1365                                     ("Duplicate <Output> elements in WPS Execute request"),
1366                                     "InternalError", NULL);
1367            }
1368            else {
1369              maps* mptr = *request_output;
1370              while (mptr->next != NULL) {
1371                mptr = mptr->next;
1372              }
1373              mptr->next = tmpmaps;     
1374            }                                   
1375            cur1 = cur1->next;
1376          }                     
1377      }
1378    }
1379  return 1;
1380}
1381
1382/**
1383 * Parse XML request and store information in maps.
1384 *
1385 * @param main_conf the conf maps containing the main.cfg settings
1386 * @param post the string containing the XML request
1387 * @param request_inputs the map storing KVP raw value
1388 * @param s the service
1389 * @param inputs the maps to store the KVP pairs
1390 * @param outputs the maps to store the KVP pairs
1391 * @param hInternet the HINTERNET queue to add potential requests
1392 * @return 0 on success, -1 on failure
1393 */
1394int xmlParseRequest(maps** main_conf,const char* post,map** request_inputs,service* s,maps** inputs,maps** outputs,HINTERNET* hInternet){
1395
1396  map* version=getMapFromMaps(*main_conf,"main","rversion");
1397  int vid=getVersionId(version->value);
1398
1399  xmlInitParser ();
1400  xmlDocPtr doc = xmlReadMemory (post, cgiContentLength, "input_request.xml", NULL, XML_PARSE_RECOVER);
1401
1402  /**
1403   * Extract Input nodes from the XML Request.
1404   */
1405  xmlXPathObjectPtr tmpsptr =
1406    extractFromDoc (doc, (vid==0?"/*/*/*[local-name()='Input']":"/*/*[local-name()='Input']"));
1407  xmlNodeSet *tmps = tmpsptr->nodesetval;
1408  if(tmps==NULL || xmlParseInputs(main_conf,s,inputs,doc,tmps,hInternet)<0){
1409    xmlXPathFreeObject (tmpsptr);
1410    xmlFreeDoc (doc);
1411    xmlCleanupParser ();
1412    return -1;
1413  }
1414  xmlXPathFreeObject (tmpsptr);
1415
1416  if(vid==1){
1417    tmpsptr =
1418      extractFromDoc (doc, "/*[local-name()='Execute']");
1419    bool asRaw = false;
1420    tmps = tmpsptr->nodesetval;
1421    if(tmps->nodeNr > 0){
1422      int k = 0;
1423      for (k=0; k < tmps->nodeNr; k++){
1424        maps *tmpmaps = NULL;
1425        xmlNodePtr cur = tmps->nodeTab[k];
1426        if (cur->type == XML_ELEMENT_NODE){
1427          xmlChar *val = xmlGetProp (cur, BAD_CAST "mode");
1428          if(val!=NULL)
1429            addToMap(*request_inputs,"mode",(char*)val);
1430          else
1431            addToMap(*request_inputs,"mode","auto");
1432          xmlFree(val);
1433          val = xmlGetProp (cur, BAD_CAST "response");
1434          if(val!=NULL){
1435            addToMap(*request_inputs,"response",(char*)val);
1436            if(strncasecmp((char*)val,"raw",xmlStrlen(val))==0)
1437              addToMap(*request_inputs,"RawDataOutput","");
1438            else
1439              addToMap(*request_inputs,"ResponseDocument","");
1440          }
1441          else{
1442            addToMap(*request_inputs,"response","document");
1443            addToMap(*request_inputs,"ResponseDocument","");
1444          }
1445          xmlFree(val);
1446        }
1447      }
1448    }
1449    xmlXPathFreeObject (tmpsptr);
1450    tmpsptr =
1451      extractFromDoc (doc, "/*/*[local-name()='Output']");
1452    tmps = tmpsptr->nodesetval;
1453    if(tmps->nodeNr > 0){
1454      if(xmlParseOutputs2(main_conf,request_inputs,outputs,doc,tmps)<0){
1455        xmlXPathFreeObject (tmpsptr);
1456        xmlFreeDoc (doc);
1457        xmlCleanupParser ();
1458        return -1;
1459      }
1460    }
1461  }
1462  else{
1463    // Extract ResponseDocument / RawDataOutput from the XML Request
1464    tmpsptr =
1465      extractFromDoc (doc, "/*/*/*[local-name()='ResponseDocument']");
1466    bool asRaw = false;
1467    tmps = tmpsptr->nodesetval;
1468    if (tmps->nodeNr == 0)
1469      {
1470        xmlXPathFreeObject (tmpsptr);
1471        tmpsptr =
1472          extractFromDoc (doc, "/*/*/*[local-name()='RawDataOutput']");
1473        tmps = tmpsptr->nodesetval;
1474        asRaw = true;
1475      }
1476    if(tmps->nodeNr != 0){
1477      if(xmlParseOutputs(main_conf,request_inputs,outputs,doc,tmps->nodeTab[0],asRaw)<0){
1478        xmlXPathFreeObject (tmpsptr);
1479        xmlFreeDoc (doc);
1480        xmlCleanupParser ();
1481        return -1;
1482      }
1483    }
1484  }
1485  xmlXPathFreeObject (tmpsptr);
1486  xmlFreeDoc (doc);
1487  xmlCleanupParser ();
1488  return 1;
1489}
1490
1491/**
1492 * Parse request and store information in maps.
1493 *
1494 * @param main_conf the conf maps containing the main.cfg settings
1495 * @param post the string containing the XML request
1496 * @param request_inputs the map storing KVP raw value
1497 * @param s the service
1498 * @param inputs the maps to store the KVP pairs
1499 * @param outputs the maps to store the KVP pairs
1500 * @param hInternet the HINTERNET queue to add potential requests
1501 * @return 0 on success, -1 on failure
1502 * @see kvpParseOutputs,kvpParseInputs,xmlParseRequest
1503 */
1504int parseRequest(maps** main_conf,map** request_inputs,service* s,maps** inputs,maps** outputs,HINTERNET* hInternet){
1505  map *postRequest = NULL;
1506  postRequest = getMap (*request_inputs, "xrequest");
1507  if (postRequest == NULLMAP)
1508    {
1509      if(kvpParseOutputs(main_conf,*request_inputs,outputs)<0){
1510        return -1;
1511      }
1512      if(kvpParseInputs(main_conf,s,*request_inputs,inputs,hInternet)<0){
1513        return -1;
1514      }
1515    }
1516  else
1517    {
1518      //Parse XML request
1519      if(xmlParseRequest(main_conf,postRequest->value,request_inputs,s,inputs,outputs,hInternet)<0){
1520        return -1;
1521      }
1522    }
1523  return 1;
1524}
1525
1526/**
1527 * Ensure that each requested arguments are present in the request
1528 * DataInputs and ResponseDocument / RawDataOutput. Potentially run
1529 * http requests from the queue in parallel.
1530 * For optional inputs add default values defined in the ZCFG file.
1531 *
1532 * @param main_conf
1533 * @param s
1534 * @param original_request
1535 * @param request_inputs
1536 * @param request_outputs
1537 * @param hInternet
1538 *
1539 * @see runHttpRequests
1540 */
1541int validateRequest(maps** main_conf,service* s,map* original_request, maps** request_inputs,maps** request_outputs,HINTERNET* hInternet){
1542
1543  map* errI0=NULL;
1544  runHttpRequests (main_conf, request_inputs, hInternet,&errI0);
1545  if(errI0!=NULL){
1546    printExceptionReportResponse (*main_conf, errI0);
1547    InternetCloseHandle (hInternet);
1548    return -1;
1549  }
1550  InternetCloseHandle (hInternet);
1551
1552
1553  map* errI=NULL;
1554  char *dfv = addDefaultValues (request_inputs, s->inputs, *main_conf, 0,&errI);
1555
1556  maps *ptr = *request_inputs;
1557  while (ptr != NULL)
1558    {
1559      map *tmp0 = getMap (ptr->content, "size");
1560      map *tmp1 = getMap (ptr->content, "maximumMegabytes");
1561      if (tmp1 != NULL && tmp0 != NULL)
1562        {
1563          float i = atof (tmp0->value) / 1048576.0;
1564          if (i >= atoi (tmp1->value))
1565            {
1566              char tmps[1024];
1567              map *tmpe = createMap ("code", "FileSizeExceeded");
1568              snprintf (tmps, 1024,
1569                        _
1570                        ("The <%s> parameter has a size limit (%s MB) defined in the ZOO ServicesProvider configuration file, but the reference you provided exceeds this limit (%f MB)."),
1571                        ptr->name, tmp1->value, i);
1572              addToMap (tmpe, "locator", ptr->name);
1573              addToMap (tmpe, "text", tmps);
1574              printExceptionReportResponse (*main_conf, tmpe);
1575              freeMap (&tmpe);
1576              free (tmpe);
1577              return -1;
1578            }
1579        }
1580      ptr = ptr->next;
1581    }
1582
1583  map* errO=NULL;
1584  char *dfv1 =
1585    addDefaultValues (request_outputs, s->outputs, *main_conf, 1,&errO);
1586
1587  if (strcmp (dfv1, "") != 0 || strcmp (dfv, "") != 0)
1588    {
1589      char tmps[1024];
1590      map *tmpe = NULL;
1591      if (strcmp (dfv, "") != 0)
1592        {
1593          tmpe = createMap ("code", "MissingParameterValue");
1594          int nb=0;
1595          int length=1;
1596          map* len=getMap(errI,"length");
1597          if(len!=NULL)
1598            length=atoi(len->value);
1599          for(nb=0;nb<length;nb++){
1600            map* errp=getMapArray(errI,"value",nb);
1601            snprintf (tmps, 1024,
1602                      _
1603                      ("The <%s> argument was not specified in DataInputs but is required according to the ZOO ServicesProvider configuration file."),
1604                      errp->value);
1605            setMapArray (tmpe, "locator", nb , errp->value);
1606            setMapArray (tmpe, "text", nb , tmps);
1607            setMapArray (tmpe, "code", nb , "MissingParameterValue");
1608          }
1609        }
1610      if (strcmp (dfv1, "") != 0)
1611        {
1612          int ilength=0;
1613          if(tmpe==NULL)
1614            tmpe = createMap ("code", "InvalidParameterValue");
1615          else{
1616            map* len=getMap(tmpe,"length");
1617            if(len!=NULL)
1618              ilength=atoi(len->value);
1619          }
1620          int nb=0;
1621          int length=1;
1622          map* len=getMap(errO,"length");
1623          if(len!=NULL)
1624            length=atoi(len->value);
1625          for(nb=0;nb<length;nb++){
1626            map* errp=getMapArray(errO,"value",nb);
1627            snprintf (tmps, 1024,
1628                      _
1629                      ("The <%s> argument specified as %s identifier was not recognized (not defined in the ZOO Configuration File)."),
1630                      errp->value,
1631                      ((getMap(original_request,"RawDataOutput")!=NULL)?"RawDataOutput":"ResponseDocument"));
1632            setMapArray (tmpe, "locator", nb+ilength , errp->value);
1633            setMapArray (tmpe, "text", nb+ilength , tmps);
1634            setMapArray (tmpe, "code", nb+ilength , "InvalidParameterValue");
1635          }
1636        }
1637      printExceptionReportResponse (*main_conf, tmpe);
1638      if(errI!=NULL){
1639        freeMap(&errI);
1640        free(errI);
1641      }
1642      if(errO!=NULL){
1643        freeMap(&errO);
1644        free(errO);
1645      }
1646      freeMap (&tmpe);
1647      free (tmpe);
1648      return -1;
1649    }
1650  maps *tmpReqI = *request_inputs;
1651  while (tmpReqI != NULL)
1652    {
1653      char name[1024];
1654      if (getMap (tmpReqI->content, "isFile") != NULL)
1655        {
1656          if (cgiFormFileName (tmpReqI->name, name, sizeof (name)) ==
1657              cgiFormSuccess)
1658            {
1659              int BufferLen = 1024;
1660              cgiFilePtr file;
1661              int targetFile;
1662              char *storageNameOnServer;
1663              char *fileNameOnServer;
1664              char contentType[1024];
1665              char buffer[1024];
1666              char *tmpStr = NULL;
1667              int size;
1668              int got, t;
1669              map *path = getMapFromMaps (*main_conf, "main", "tmpPath");
1670              cgiFormFileSize (tmpReqI->name, &size);
1671              cgiFormFileContentType (tmpReqI->name, contentType,
1672                                      sizeof (contentType));
1673              if (cgiFormFileOpen (tmpReqI->name, &file) == cgiFormSuccess)
1674                {
1675                  t = -1;
1676                  while (1)
1677                    {
1678                      tmpStr = strstr (name + t + 1, "\\");
1679                      if (NULL == tmpStr)
1680                        tmpStr = strstr (name + t + 1, "/");
1681                      if (NULL != tmpStr)
1682                        t = (int) (tmpStr - name);
1683                      else
1684                        break;
1685                    }
1686                  fileNameOnServer=(char*)malloc((strlen(name) - t - 1 )*sizeof(char));
1687                  strcpy (fileNameOnServer, name + t + 1);
1688
1689                  storageNameOnServer=(char*)malloc((strlen(path->value) + strlen(fileNameOnServer) + 2)*sizeof(char));
1690                  sprintf (storageNameOnServer, "%s/%s", path->value,
1691                           fileNameOnServer);
1692#ifdef DEBUG
1693                  fprintf (stderr, "Name on server %s\n",
1694                           storageNameOnServer);
1695                  fprintf (stderr, "fileNameOnServer: %s\n",
1696                           fileNameOnServer);
1697#endif
1698                  targetFile =
1699                    open (storageNameOnServer, O_RDWR | O_CREAT | O_TRUNC,
1700                          S_IRWXU | S_IRGRP | S_IROTH);
1701                  if (targetFile < 0)
1702                    {
1703#ifdef DEBUG
1704                      fprintf (stderr, "could not create the new file,%s\n",
1705                               fileNameOnServer);
1706#endif
1707                    }
1708                  else
1709                    {
1710                      while (cgiFormFileRead (file, buffer, BufferLen, &got)
1711                             == cgiFormSuccess)
1712                        {
1713                          if (got > 0)
1714                            write (targetFile, buffer, got);
1715                        }
1716                    }
1717                  addToMap (tmpReqI->content, "lref", storageNameOnServer);
1718                  cgiFormFileClose (file);
1719                  close (targetFile);
1720                  free(fileNameOnServer);
1721                  free(storageNameOnServer);
1722#ifdef DEBUG
1723                  fprintf (stderr, "File \"%s\" has been uploaded",
1724                           fileNameOnServer);
1725#endif
1726                }
1727            }
1728        }
1729      tmpReqI = tmpReqI->next;
1730    }
1731
1732  ensureDecodedBase64 (request_inputs);
1733  return 1;
1734}
1735
1736
1737/**
1738 * Verify if a parameter value is valid.
1739 *
1740 * @param request the request map
1741 * @param res the error map potentially generated
1742 * @param toCheck the parameter to use
1743 * @param avalues the acceptable values (or null if testing only for presence)
1744 * @param mandatory verify the presence of the parameter if mandatory > 0
1745 */
1746void checkValidValue(map* request,map** res,const char* toCheck,const char** avalues,int mandatory){
1747  map* lres=*res;
1748  map* r_inputs = getMap (request,toCheck);
1749  if (r_inputs == NULL){
1750    if(mandatory>0){
1751      char *replace=_("Mandatory parameter <%s> was not specified");
1752      char *message=(char*)malloc((strlen(replace)+strlen(toCheck)+1)*sizeof(char));
1753      sprintf(message,replace,toCheck);
1754      if(lres==NULL){
1755        lres=createMap("code","MissingParameterValue");
1756        addToMap(lres,"text",message);
1757        addToMap(lres,"locator",toCheck);       
1758      }else{
1759        int length=1;
1760        map* len=getMap(lres,"length");
1761        if(len!=NULL){
1762          length=atoi(len->value);
1763        }
1764        setMapArray(lres,"text",length,message);
1765        setMapArray(lres,"locator",length,toCheck);
1766        setMapArray(lres,"code",length,"MissingParameterValue");
1767      }
1768      free(message);
1769    }
1770  }else{
1771    if(avalues==NULL)
1772      return;
1773    int nb=0;
1774    int hasValidValue=-1;
1775    if(strncasecmp(toCheck,"Accept",6)==0){
1776      char *tmp=zStrdup(r_inputs->value);
1777      char *pToken,*saveptr;
1778      pToken=strtok_r(tmp,",",&saveptr);
1779      while(pToken!=NULL){
1780        while(avalues[nb]!=NULL){
1781          if(strcasecmp(avalues[nb],pToken)==0){
1782            hasValidValue=1;
1783            break;
1784          }
1785          nb++;
1786        }
1787        pToken=strtok_r(NULL,",",&saveptr);
1788      }
1789      free(tmp);
1790    }else{
1791      while(avalues[nb]!=NULL){
1792        if(strcasecmp(avalues[nb],r_inputs->value)==0){
1793          hasValidValue=1;
1794          break;
1795        }
1796        nb++;
1797      }
1798    }
1799    if(hasValidValue<0){
1800      char *replace=_("The value <%s> was not recognized, %s %s the only acceptable value.");
1801      nb=0;
1802      char *vvalues=NULL;
1803      char* num=_("is");
1804      while(avalues[nb]!=NULL){
1805        char *tvalues;
1806        if(vvalues==NULL){
1807          vvalues=(char*)malloc((strlen(avalues[nb])+3)*sizeof(char));
1808          sprintf(vvalues,"%s",avalues[nb]);
1809        }
1810        else{
1811          tvalues=zStrdup(vvalues);
1812          vvalues=(char*)realloc(vvalues,(strlen(tvalues)+strlen(avalues[nb])+3)*sizeof(char));
1813          sprintf(vvalues,"%s, %s",tvalues,avalues[nb]);
1814          free(tvalues);
1815          num=_("are");
1816        }
1817        nb++;
1818      }
1819      char *message=(char*)malloc((strlen(replace)+strlen(num)+strlen(vvalues)+strlen(toCheck)+1)*sizeof(char));
1820      sprintf(message,replace,toCheck,vvalues,num);
1821      const char *code="VersionNegotiationFailed";
1822      code="InvalidParameterValue";
1823      const char *locator=toCheck;
1824      if( strncasecmp(toCheck,"version",7)==0 ||
1825          strncasecmp(toCheck,"AcceptVersions",14)==0 )
1826        code="VersionNegotiationFailed";
1827      if( strncasecmp(toCheck,"request",7)==0){
1828        code="OperationNotSupported";
1829        locator=r_inputs->value;
1830      }
1831      if(lres==NULL){
1832        lres=createMap("code",code);
1833        addToMap(lres,"text",message);
1834        addToMap(lres,"locator",locator);       
1835      }else{
1836        int length=1;
1837        map* len=getMap(lres,"length");
1838        if(len!=NULL){
1839          length=atoi(len->value);
1840        }
1841        setMapArray(lres,"text",length,message);
1842        setMapArray(lres,"locator",length,locator);
1843        setMapArray(lres,"code",length,code);
1844      }
1845    }
1846  }
1847  if(lres!=NULL){
1848    *res=lres;
1849  }
1850}
Note: See TracBrowser for help on using the repository browser.

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png