source: trunk/zoo-project/zoo-kernel/request_parser.c @ 870

Last change on this file since 870 was 870, checked in by djay, 4 years ago

Add default string dataType to LiteralData? if none is defined.

  • Property svn:keywords set to Id
File size: 54.6 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          }
536
537          xmlNodePtr cur2 = cur->children;
538          while (cur2 != NULL)
539            {
540              while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE)
541                cur2 = cur2->next;
542              if (cur2 == NULL)
543                break;
544              // Indentifier
545              if (xmlStrncasecmp
546                  (cur2->name, BAD_CAST "Identifier",
547                   xmlStrlen (cur2->name)) == 0)
548                {
549                  xmlChar *val =
550                    xmlNodeListGetString (doc, cur2->xmlChildrenNode, 1);
551                  if (tmpmaps == NULL && val!=NULL)
552                    {
553                      tmpmaps = createMaps((char*)val);
554                      if (tmpmaps == NULL)
555                        {
556                          return errorException (*main_conf,
557                                                 _
558                                                 ("Unable to allocate memory"),
559                                                 "InternalError", NULL);
560                        }
561                      xmlFree (val);
562                    }
563                }
564              // Title, Asbtract
565              if (xmlStrncasecmp
566                  (cur2->name, BAD_CAST "Title",
567                   xmlStrlen (cur2->name)) == 0
568                  || xmlStrncasecmp (cur2->name, BAD_CAST "Abstract",
569                                     xmlStrlen (cur2->name)) == 0)
570                {
571                  xmlChar *val =
572                    xmlNodeListGetString (doc, cur2->xmlChildrenNode, 1);
573                  defineMissingIdentifier(main_conf,&tmpmaps);
574                  if(val!=NULL){
575                    if (tmpmaps->content != NULL)
576                      addToMap (tmpmaps->content,
577                                (char *) cur2->name, (char *) val);
578                    else
579                      tmpmaps->content =
580                        createMap ((char *) cur2->name, (char *) val);
581                    xmlFree (val);
582                  }
583                }
584              // InputDataFormChoice (Reference or Data ?) / 2.0.0 DataInputType / Input
585              if (xmlStrcasecmp (cur2->name, BAD_CAST "Input") == 0)
586                {
587                  char *xpathExpr=(char*)malloc(61+strlen(tmpmaps->name));
588                  sprintf(xpathExpr,"/*/*[local-name()='Input' and @id='%s']/*[local-name()='Input']",tmpmaps->name);
589                  xmlXPathObjectPtr tmpsptr = extractFromDoc (doc, xpathExpr);
590                  xmlNodeSet *tmps = tmpsptr->nodesetval;
591                  if(tmps!=NULL){
592                    maps* request_output1=NULL;
593                    if(xmlParseInputs(main_conf,s,&request_output1,doc,tmps,hInternet)<0)
594                      return -1;
595                    if(tmpmaps->child==NULL)
596                      tmpmaps->child=dupMaps(&request_output1);
597                    else
598                      addMapsToMaps(&tmpmaps->child,request_output1);
599                    freeMaps(&request_output1);
600                    free(request_output1);
601                  }
602                  while(cur2->next!=NULL)
603                    cur2=cur2->next;
604                }
605              else if (xmlStrcasecmp (cur2->name, BAD_CAST "Reference") == 0)
606                {
607                  defineMissingIdentifier(main_conf,&tmpmaps);
608                  // Get every attribute from a Reference node
609                  // mimeType, encoding, schema, href, method
610                  // Header and Body gesture should be added here
611                  const char *refs[5] =
612                    { "mimeType", "encoding", "schema", "method",
613                      "href"
614                    };
615                  for (l = 0; l < 5; l++)
616                    {
617                      xmlChar *val = xmlGetProp (cur2, BAD_CAST refs[l]);
618                      if (val != NULL && xmlStrlen (val) > 0)
619                        {
620                          if (tmpmaps->content != NULL)
621                            addToMap (tmpmaps->content, refs[l],
622                                      (char *) val);
623                          else
624                            tmpmaps->content =
625                              createMap (refs[l], (char *) val);
626
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                                      if (btmp != NULL)
753                                        {
754                                          addRequestToQueue(main_conf,hInternet,(char *) btmp->value,false);
755                                          InternetOpenUrl (hInternet,
756                                                           btmp->value,
757                                                           tmp,
758                                                           xmlStrlen(btmps),
759                                                           INTERNET_FLAG_NO_CACHE_WRITE,
760                                                           0);
761                                          addIntToMap (tmpmaps->content, "Order", hInternet->nb);
762                                        }
763                                      xmlFree (btmps);
764                                      free (tmp);
765                                      break;
766                                    }
767                                  }
768                                  cur4 = cur4->next;
769                                }
770                            }
771                          else
772                            if (xmlStrcasecmp
773                                (cur3->name,
774                                 BAD_CAST "BodyReference") == 0)
775                              {
776                                xmlChar *val =
777                                  xmlGetProp (cur3, BAD_CAST "href");
778                                HINTERNET bInternet, res1, res;
779                                bInternet = InternetOpen (
780#ifndef WIN32
781                                                          (LPCTSTR)
782#endif
783                                                          "ZooWPSClient\0",
784                                                          INTERNET_OPEN_TYPE_PRECONFIG,
785                                                          NULL, NULL, 0);
786                                if (!CHECK_INET_HANDLE (bInternet))
787                                  fprintf (stderr,
788                                           "WARNING : bInternet handle failed to initialize");
789                                bInternet.waitingRequests[0] =
790                                  strdup ((char *) val);
791                                res1 =
792                                  InternetOpenUrl (&bInternet,
793                                                   bInternet.waitingRequests
794                                                   [0], NULL, 0,
795                                                   INTERNET_FLAG_NO_CACHE_WRITE,
796                                                   0);
797                                processDownloads (&bInternet);
798                                char *tmp =
799                                  (char *)
800                                  malloc ((bInternet.ihandle[0].nDataLen +
801                                           1) * sizeof (char));
802                                if (tmp == NULL)
803                                  {
804                                    return errorException (*main_conf,
805                                                           _
806                                                           ("Unable to allocate memory"),
807                                                           "InternalError",
808                                                           NULL);
809                                  }
810                                size_t bRead;
811                                InternetReadFile (bInternet.ihandle[0],
812                                                  (LPVOID) tmp,
813                                                  bInternet.
814                                                  ihandle[0].nDataLen,
815                                                  &bRead);
816                                tmp[bInternet.ihandle[0].nDataLen] = 0;
817                                InternetCloseHandle (&bInternet);
818                                map *btmp =
819                                  getMap (tmpmaps->content, "href");
820                                if (btmp != NULL)
821                                  {
822                                    addRequestToQueue(main_conf,hInternet,(char *) btmp->value,false);
823
824                                    res =
825                                      InternetOpenUrl (hInternet,
826                                                       btmp->value,
827                                                       tmp,
828                                                       strlen(tmp),
829                                                       INTERNET_FLAG_NO_CACHE_WRITE,
830                                                       0);
831                                    addIntToMap (tmpmaps->content, "Order", hInternet->nb);
832                                  }
833                                free (tmp);
834                              }
835                        }
836                      cur3 = cur3->next;
837                    }
838                }
839              else if (xmlStrcasecmp (cur2->name, BAD_CAST "Data") == 0)
840                {
841                  defineMissingIdentifier(main_conf,&tmpmaps);
842                  xmlNodePtr cur4 = cur2->children;
843                  if(vid==1){
844                    // Get every dataEncodingAttributes from a Data node:
845                    // mimeType, encoding, schema
846                    const char *coms[3] =
847                      { "mimeType", "encoding", "schema" };
848                    for (l = 0; l < 3; l++){
849                      xmlChar *val =
850                          xmlGetProp (cur4, BAD_CAST coms[l]);
851                        if (val != NULL && strlen ((char *) val) > 0){
852                          if (tmpmaps->content != NULL)
853                            addToMap (tmpmaps->content,coms[l],(char *) val);
854                          else
855                            tmpmaps->content =
856                              createMap (coms[l],(char *) val);
857                        }
858                        xmlFree (val);
859                    }
860                    while (cur4 != NULL){
861                      while(cur4 != NULL && 
862                            cur4->type != XML_CDATA_SECTION_NODE &&
863                            cur4->type != XML_TEXT_NODE &&
864                            cur4->type != XML_ELEMENT_NODE)
865                        cur4=cur4->next;
866                      if(cur4!=NULL){
867                        if (cur4->type == XML_ELEMENT_NODE)
868                          {
869                            xmlChar *mv;
870                            int buffersize;
871                            xmlDocPtr doc1 = xmlNewDoc (BAD_CAST "1.0");
872                            xmlDocSetRootElement (doc1, cur4);
873                            xmlDocDumpFormatMemoryEnc (doc1, &mv,
874                                                       &buffersize,
875                                                       "utf-8", 0);
876                            if (tmpmaps->content != NULL)
877                              addToMap (tmpmaps->content, "value",
878                                        (char *) mv);
879                            else
880                              tmpmaps->content =
881                                createMap ("value", (char *) mv);
882                            free(mv);
883                          }
884                        else{
885                          if (tmpmaps->content != NULL)
886                            addToMap (tmpmaps->content, "value",
887                                      (char *) cur4->content);
888                          else
889                            tmpmaps->content =
890                              createMap ("value", (char *) cur4->content);
891                        }
892                        cur4=cur4->next;
893                      }
894                    }
895                  }
896
897
898                  while (cur4 != NULL)
899                    {
900                      while (cur4 != NULL
901                             && cur4->type != XML_ELEMENT_NODE)
902                        cur4 = cur4->next;
903                      if (cur4 == NULL)
904                        break;
905                      if (xmlStrcasecmp
906                          (cur4->name, BAD_CAST "LiteralData") == 0)
907                        {
908                          // Get every attribute from a LiteralData node
909                          // dataType , uom
910                          char *list[2];
911                          list[0] = zStrdup ("dataType");
912                          list[1] = zStrdup ("uom");
913                          for (l = 0; l < 2; l++)
914                            {
915                              xmlChar *val =
916                                xmlGetProp (cur4, BAD_CAST list[l]);
917                              if (val != NULL
918                                  && strlen ((char *) val) > 0)
919                                {
920                                  if (tmpmaps->content != NULL)
921                                    addToMap (tmpmaps->content, list[l],
922                                              (char *) val);
923                                  else
924                                    tmpmaps->content =
925                                      createMap (list[l], (char *) val);
926                                  xmlFree (val);
927                                }
928                              else{
929                                if(l==0){
930                                  if (tmpmaps->content != NULL)
931                                    addToMap (tmpmaps->content, list[l],
932                                              "string");
933                                  else
934                                    tmpmaps->content =
935                                      createMap (list[l],"string");
936                                }
937                              }
938                              free (list[l]);
939                            }
940                        }
941                      else
942                        if (xmlStrcasecmp
943                            (cur4->name, BAD_CAST "ComplexData") == 0)
944                          {
945                            // Get every attribute from a Reference node
946                            // mimeType, encoding, schema
947                            const char *coms[3] =
948                              { "mimeType", "encoding", "schema" };
949                            for (l = 0; l < 3; l++)
950                              {
951                                xmlChar *val =
952                                  xmlGetProp (cur4, BAD_CAST coms[l]);
953                                if (val != NULL
954                                    && strlen ((char *) val) > 0)
955                                  {
956                                    if (tmpmaps->content != NULL)
957                                      addToMap (tmpmaps->content, coms[l],
958                                                (char *) val);
959                                    else
960                                      tmpmaps->content =
961                                        createMap (coms[l], (char *) val);
962                                    xmlFree (val);
963                                  }
964                              }
965                          }
966
967                      map *test = getMap (tmpmaps->content, "encoding");
968
969                      if (test == NULL)
970                        { 
971                          if (tmpmaps->content != NULL)
972                            addToMap (tmpmaps->content, "encoding",
973                                      "utf-8");
974                          else
975                            tmpmaps->content =
976                              createMap ("encoding", "utf-8");
977                          test = getMap (tmpmaps->content, "encoding");
978                        }
979
980                      if (getMap(tmpmaps->content,"dataType")==NULL && strcasecmp (test->value, "base64") != 0)
981                        { 
982                          xmlChar *mv = xmlNodeListGetString (doc,
983                                                              cur4->xmlChildrenNode,
984                                                              1);
985                          map *ltmp =
986                            getMap (tmpmaps->content, "mimeType");
987                          if (mv == NULL
988                              ||
989                              (xmlStrcasecmp
990                               (cur4->name, BAD_CAST "ComplexData") == 0
991                               && (ltmp == NULL
992                                   || strncasecmp (ltmp->value,
993                                                   "text/xml", 8) == 0)))
994                            {
995                              xmlDocPtr doc1 = xmlNewDoc (BAD_CAST "1.0");
996                              int buffersize;
997                              xmlNodePtr cur5 = cur4->children;
998                              while (cur5 != NULL
999                                     && cur5->type != XML_ELEMENT_NODE
1000                                     && cur5->type != XML_CDATA_SECTION_NODE)
1001                                cur5 = cur5->next;
1002                              if (cur5 != NULL
1003                                  && cur5->type != XML_CDATA_SECTION_NODE)
1004                                {
1005                                  xmlDocSetRootElement (doc1, cur5);
1006                                  xmlDocDumpFormatMemoryEnc (doc1, &mv,
1007                                                             &buffersize,
1008                                                             "utf-8", 0);
1009                                  xmlFreeDoc (doc1);
1010                                }
1011                              else
1012                                {
1013                                  if (cur5 != NULL
1014                                      && cur5->type == XML_CDATA_SECTION_NODE){
1015                                    xmlDocPtr doc2 = xmlReadMemory((const char*)cur5->content,xmlStrlen(cur5->content),
1016                                                                   "input_content.xml", NULL, XML_PARSE_RECOVER);
1017                                    xmlDocDumpFormatMemoryEnc (doc2, &mv,
1018                                                               &buffersize,
1019                                                               "utf-8", 0);
1020                                    xmlFreeDoc (doc2);
1021                                  }
1022                                }
1023                              addIntToMap (tmpmaps->content, "size",
1024                                           buffersize);
1025                            }else{
1026                            if(xmlStrcasecmp
1027                               (cur4->name, BAD_CAST "BoundingBoxData") == 0){
1028                              xmlDocPtr doc1 = xmlNewDoc(BAD_CAST "1.0");
1029                              int buffersize;
1030                              xmlDocSetRootElement(doc1,cur4);
1031                              xmlDocDumpFormatMemoryEnc(doc1,&mv,
1032                                                        &buffersize,
1033                                                        "utf-8",0);
1034                              addIntToMap (tmpmaps->content, "size",
1035                                           buffersize);
1036                              xmlParseBoundingBox(main_conf,&tmpmaps->content,doc1);
1037                            }else{
1038                              xmlNodePtr cur5 = cur4->children;
1039                              while (cur5 != NULL
1040                                     && cur5->type != XML_CDATA_SECTION_NODE)
1041                                cur5 = cur5->next;
1042                              if (cur5 != NULL
1043                                  && cur5->type == XML_CDATA_SECTION_NODE){
1044                                if(mv!=NULL)
1045                                  xmlFree(mv);
1046                                mv=xmlStrdup(cur5->content);
1047                              }
1048                            }
1049                          }
1050                          if (mv != NULL)
1051                            {
1052                              addToMap (tmpmaps->content, "value",
1053                                        (char*) mv);
1054                              xmlFree (mv);
1055                            }
1056                        }
1057                      else
1058                        {
1059                          xmlNodePtr cur5 = cur4->children;
1060                          while (cur5 != NULL
1061                                 && cur5->type != XML_CDATA_SECTION_NODE)
1062                            cur5 = cur5->next;
1063                          if (cur5 != NULL
1064                              && cur5->type == XML_CDATA_SECTION_NODE)
1065                            {
1066                              addToMap (tmpmaps->content,
1067                                        "value",
1068                                        (char *) cur5->content);
1069                            }
1070                          else{
1071                            if(cur4->xmlChildrenNode!=NULL){
1072                              xmlChar *tmp = xmlNodeListGetRawString (doc,
1073                                                                      cur4->xmlChildrenNode,
1074                                                                      0);
1075                              addToMap (tmpmaps->content, "value",
1076                                        (char *) tmp);
1077                              xmlFree (tmp);
1078                            }
1079                          }
1080                        }
1081
1082                      cur4 = cur4->next;
1083                    }
1084                }
1085              cur2 = cur2->next;
1086              while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE){
1087                cur2 = cur2->next;
1088              }
1089            }
1090          {
1091            map* test=getMap(tmpmaps->content,"value");
1092            if(test==NULL && tmpmaps->child==NULL)
1093              addToMap(tmpmaps->content,"value","");
1094            maps *testPresence = getMaps (*request_output, tmpmaps->name);
1095            maps *cursor=*request_output;
1096            while(testPresence == NULL && cursor!=NULL){
1097              if(cursor->child!=NULL){
1098                testPresence = getMaps (cursor->child, tmpmaps->name);
1099              }
1100              cursor=cursor->next;
1101            }
1102            if (testPresence != NULL)
1103              {
1104                elements *elem = getElements (s->inputs, tmpmaps->name);
1105                elements *cursor=s->inputs;
1106                while(elem == NULL && cursor!=NULL){
1107                  if(cursor->child!=NULL){
1108                    elem = getElements (cursor->child, tmpmaps->name);
1109                  }
1110                  cursor=cursor->next;
1111                }
1112                if (elem != NULL)
1113                  {
1114                    if (appendMapsToMaps
1115                        (*main_conf, testPresence, tmpmaps, elem) < 0)
1116                      {
1117                        return errorException (*main_conf,
1118                                               _("Unable to append maps to maps."),
1119                                               "InternalError",
1120                                               NULL);
1121                      }
1122                  }
1123              }
1124            else
1125              addMapsToMaps (request_output, tmpmaps);
1126          }
1127          freeMaps (&tmpmaps);
1128          free (tmpmaps);
1129          tmpmaps = NULL;
1130        }
1131    }
1132  return 1;
1133}
1134
1135/**
1136 * Parse a BoundingBoxData node
1137 *
1138 * http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd: BoundingBoxType
1139 *
1140 * A map to store boundingbox information will contain:
1141 *  - LowerCorner : double double (minimum within this bounding box)
1142 *  - UpperCorner : double double (maximum within this bounding box)
1143 *  - crs : URI (Reference to definition of the CRS)
1144 *  - dimensions : int
1145 *
1146 * @param main_conf the conf maps containing the main.cfg settings
1147 * @param request_inputs the map storing KVP raw value
1148 * @param doc the xmlDocPtr containing the BoudingoxData node
1149 * @return a map containing all the bounding box keys
1150 */
1151int xmlParseBoundingBox(maps** main_conf,map** current_input,xmlDocPtr doc){
1152  xmlNode *root_element = xmlDocGetRootElement(doc);
1153  for(xmlAttrPtr attr = root_element->properties; NULL != attr; attr = attr->next){
1154    xmlChar *val = xmlGetProp (root_element, BAD_CAST attr->name);
1155    addToMap(*current_input,(char*)attr->name,(char*)val);
1156    xmlFree(val);
1157    xmlNodePtr cur = root_element->children;
1158    while(cur!=NULL && cur->type != XML_ELEMENT_NODE)
1159      cur=cur->next;
1160    while(cur!=NULL && cur->type==XML_ELEMENT_NODE){
1161      xmlChar *val =
1162        xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
1163      addToMap(*current_input,(char*)cur->name,(char*)val);
1164      cur=cur->next;
1165      xmlFree(val);
1166      while(cur!=NULL && cur->type != XML_ELEMENT_NODE)
1167        cur=cur->next;
1168    }
1169  }
1170}
1171
1172/**
1173 * Parse outputs from XML nodes and store them in a maps (WPS version 2.0.0).
1174 *
1175 * @param main_conf the conf maps containing the main.cfg settings
1176 * @param request_inputs the map storing KVP raw value
1177 * @param request_output the maps to store the KVP pairs
1178 * @param doc the xmlDocPtr containing the original request
1179 * @param cur the xmlNodePtr corresponding to the ResponseDocument or RawDataOutput XML node
1180 * @param raw true if the node is RawDataOutput, false in case of ResponseDocument
1181 * @return 0 on success, -1 on failure
1182 */
1183int xmlParseOutputs2(maps** main_conf,map** request_inputs,maps** request_output,xmlDocPtr doc,xmlNodeSet* nodes){
1184  int k = 0;
1185  int l = 0;
1186  for (k=0; k < nodes->nodeNr; k++){
1187    maps *tmpmaps = NULL;
1188    xmlNodePtr cur = nodes->nodeTab[k];
1189    if (cur->type == XML_ELEMENT_NODE){
1190      maps *tmpmaps = NULL;
1191      xmlChar *val = xmlGetProp (cur, BAD_CAST "id");
1192      if(val!=NULL)
1193        tmpmaps = createMaps((char *)val);
1194      else
1195        tmpmaps = createMaps("unknownIdentifier");
1196      const char ress[4][13] =
1197        { "mimeType", "encoding", "schema", "transmission" };
1198      for (l = 0; l < 4; l++){
1199        val = xmlGetProp (cur, BAD_CAST ress[l]);
1200        if (val != NULL && strlen ((char *) val) > 0)
1201          {
1202            if (tmpmaps->content != NULL)
1203              addToMap (tmpmaps->content, ress[l],
1204                        (char *) val);
1205            else
1206              tmpmaps->content =
1207                createMap (ress[l], (char *) val);
1208            if(l==3 && strncasecmp((char*)val,"reference",xmlStrlen(val))==0)
1209              addToMap (tmpmaps->content,"asReference","true");
1210          }
1211        xmlFree (val);
1212      }
1213      if(cur->children!=NULL){
1214        xmlNodePtr ccur = cur->children;
1215        while (ccur != NULL){
1216          if(ccur->type == XML_ELEMENT_NODE){
1217            char *xpathExpr=(char*)malloc(65+strlen(tmpmaps->name));
1218            sprintf(xpathExpr,"/*/*[local-name()='Output' and @id='%s']/*[local-name()='Output']",tmpmaps->name);
1219            xmlXPathObjectPtr tmpsptr = extractFromDoc (doc, xpathExpr);
1220            xmlNodeSet* cnodes = tmpsptr->nodesetval;
1221            xmlParseOutputs2(main_conf,request_inputs,&tmpmaps->child,doc,cnodes);
1222            break;
1223          }
1224          ccur = ccur->next;
1225        }
1226      }
1227      if (*request_output == NULL){
1228        *request_output = dupMaps(&tmpmaps);
1229      }
1230      else{
1231        addMapsToMaps(request_output,tmpmaps);
1232      }
1233      freeMaps(&tmpmaps);
1234      free(tmpmaps);
1235    }
1236  }
1237  return 0;
1238}
1239
1240/**
1241 * Parse outputs from XML nodes and store them in a maps.
1242 *
1243 * @param main_conf the conf maps containing the main.cfg settings
1244 * @param request_inputs the map storing KVP raw value
1245 * @param request_output the maps to store the KVP pairs
1246 * @param doc the xmlDocPtr containing the original request
1247 * @param cur the xmlNodePtr corresponding to the ResponseDocument or RawDataOutput XML node
1248 * @param raw true if the node is RawDataOutput, false in case of ResponseDocument
1249 * @return 0 on success, -1 on failure
1250 */
1251int xmlParseOutputs(maps** main_conf,map** request_inputs,maps** request_output,xmlDocPtr doc,xmlNodePtr cur,bool raw){
1252  int l=0;
1253  if( raw == true)
1254    {
1255      addToMap (*request_inputs, "RawDataOutput", "");
1256      if (cur->type == XML_ELEMENT_NODE)
1257        {
1258
1259          maps *tmpmaps = createMaps("unknownIdentifier");
1260          if (tmpmaps == NULL)
1261            {
1262              return errorException (*main_conf, _("Unable to allocate memory"),
1263                                     "InternalError", NULL);
1264            }
1265
1266          // Get every attribute from a RawDataOutput node
1267          // mimeType, encoding, schema, uom
1268          const char *outs[4] =
1269            { "mimeType", "encoding", "schema", "uom" };
1270          for (l = 0; l < 4; l++)
1271            {
1272              xmlChar *val = xmlGetProp (cur, BAD_CAST outs[l]);
1273              if (val != NULL)
1274                {
1275                  if (strlen ((char *) val) > 0)
1276                    {
1277                      if (tmpmaps->content != NULL)
1278                        addToMap (tmpmaps->content, outs[l],
1279                                  (char *) val);
1280                      else
1281                        tmpmaps->content =
1282                          createMap (outs[l], (char *) val);
1283                    }
1284                  xmlFree (val);
1285                }
1286            }
1287          xmlNodePtr cur2 = cur->children;
1288          while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE)
1289            cur2 = cur2->next;
1290          while (cur2 != NULL)
1291            {
1292              if (xmlStrncasecmp
1293                  (cur2->name, BAD_CAST "Identifier",
1294                   xmlStrlen (cur2->name)) == 0)
1295                {
1296                  xmlChar *val =
1297                    xmlNodeListGetString (NULL, cur2->xmlChildrenNode, 1);
1298                  free (tmpmaps->name);
1299                  tmpmaps->name = zStrdup ((char *) val);
1300                  xmlFree (val);
1301                }
1302              cur2 = cur2->next;
1303              while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE)
1304                cur2 = cur2->next;
1305            }
1306          if (*request_output == NULL)
1307            *request_output = dupMaps (&tmpmaps);
1308          else
1309            addMapsToMaps (request_output, tmpmaps);
1310          if (tmpmaps != NULL)
1311            {
1312              freeMaps (&tmpmaps);
1313              free (tmpmaps);
1314              tmpmaps = NULL;
1315            }
1316        }
1317    }
1318  else
1319    {
1320      addToMap (*request_inputs, "ResponseDocument", "");
1321
1322      if (cur->type == XML_ELEMENT_NODE) {
1323        // Get every attribute: storeExecuteResponse, lineage, status
1324        const char *ress[3] =
1325          { "storeExecuteResponse", "lineage", "status" };
1326        xmlChar *val;
1327        for (l = 0; l < 3; l++)
1328          {
1329            val = xmlGetProp (cur, BAD_CAST ress[l]);
1330            if (val != NULL && strlen ((char *) val) > 0)
1331              {
1332                addToMap (*request_inputs, ress[l], (char *) val);
1333              }
1334            xmlFree (val);
1335          }
1336                       
1337        xmlNodePtr cur1 = cur->children;               
1338        while (cur1 != NULL) // iterate over Output nodes
1339          {
1340            if (cur1->type != XML_ELEMENT_NODE || 
1341                xmlStrncasecmp(cur1->name, BAD_CAST "Output", 
1342                               xmlStrlen (cur1->name)) != 0) {
1343              cur1 = cur1->next;
1344              continue;
1345            }
1346                               
1347            maps *tmpmaps = createMaps("unknownIdentifier"); // one per Output node
1348            if (tmpmaps == NULL) {
1349              return errorException (*main_conf,
1350                                     _
1351                                     ("Unable to allocate memory"),
1352                                     "InternalError", NULL);
1353            }
1354                               
1355            xmlNodePtr elems = cur1->children;
1356                               
1357            while (elems != NULL) {
1358
1359              // Identifier
1360              if (xmlStrncasecmp
1361                  (elems->name, BAD_CAST "Identifier",
1362                   xmlStrlen (elems->name)) == 0)
1363                {
1364                  xmlChar *val =
1365                    xmlNodeListGetString (doc, elems->xmlChildrenNode, 1);
1366               
1367                  free(tmpmaps->name);
1368                  tmpmaps->name = zStrdup ((char *) val);
1369                  if (tmpmaps->content == NULL) {
1370                    tmpmaps->content = createMap("Identifier", zStrdup ((char *) val));
1371                  }
1372                  else {
1373                    addToMap(tmpmaps->content, "Identifier", zStrdup ((char *) val));
1374                  }
1375
1376                  map* tt = getMap (*request_inputs, "ResponseDocument");
1377                  if (strlen(tt->value) == 0) {
1378                    addToMap (*request_inputs, "ResponseDocument",
1379                              (char *) val);
1380                  }
1381                  else {
1382                    char* tmp = (char*) malloc((strlen(tt->value) + 1 
1383                                                + strlen((char*) val) + 1) * sizeof(char));
1384                    sprintf (tmp, "%s;%s", tt->value, (char *) val);
1385                    free(tt->value);
1386                    tt->value = tmp;
1387                  }
1388                  xmlFree (val);
1389                }
1390             
1391              // Title, Abstract
1392              else if (xmlStrncasecmp(elems->name, BAD_CAST "Title",
1393                                      xmlStrlen (elems->name)) == 0
1394                       || xmlStrncasecmp(elems->name, BAD_CAST "Abstract",
1395                                         xmlStrlen (elems->name)) == 0)
1396                {
1397                  xmlChar *val =
1398                    xmlNodeListGetString (doc, elems->xmlChildrenNode, 1);
1399                                                       
1400                  if (tmpmaps->content == NULL) {
1401                    tmpmaps->content = createMap((char*) elems->name, zStrdup ((char *) val));
1402                  }
1403                  else {
1404                    addToMap(tmpmaps->content, (char*) elems->name, zStrdup ((char *) val));
1405                  }
1406                  xmlFree (val);
1407                }
1408              elems = elems->next;
1409            }
1410                               
1411            // Get every attribute from an Output node:
1412            // mimeType, encoding, schema, uom, asReference
1413            const char *outs[5] =
1414              { "mimeType", "encoding", "schema", "uom", "asReference" };
1415                                         
1416            for (l = 0; l < 5; l++) {
1417              xmlChar *val = xmlGetProp (cur1, BAD_CAST outs[l]);                               
1418              if (val != NULL && xmlStrlen(val) > 0) {
1419                if (tmpmaps->content != NULL) {
1420                  addToMap (tmpmaps->content, outs[l], (char *) val);
1421                }                         
1422                else {
1423                  tmpmaps->content = createMap (outs[l], (char *) val);
1424                }       
1425              }
1426              xmlFree (val);
1427            }
1428                               
1429            if (*request_output == NULL) {
1430              *request_output = tmpmaps;
1431            }   
1432            else if (getMaps(*request_output, tmpmaps->name) != NULL) {
1433              return errorException (*main_conf,
1434                                     _
1435                                     ("Duplicate <Output> elements in WPS Execute request"),
1436                                     "InternalError", NULL);
1437            }
1438            else {
1439              maps* mptr = *request_output;
1440              while (mptr->next != NULL) {
1441                mptr = mptr->next;
1442              }
1443              mptr->next = tmpmaps;     
1444            }                                   
1445            cur1 = cur1->next;
1446          }                     
1447      }
1448    }
1449  return 1;
1450}
1451
1452/**
1453 * Parse XML request and store information in maps.
1454 *
1455 * @param main_conf the conf maps containing the main.cfg settings
1456 * @param post the string containing the XML request
1457 * @param request_inputs the map storing KVP raw value
1458 * @param s the service
1459 * @param inputs the maps to store the KVP pairs
1460 * @param outputs the maps to store the KVP pairs
1461 * @param hInternet the HINTERNET queue to add potential requests
1462 * @return 0 on success, -1 on failure
1463 */
1464int xmlParseRequest(maps** main_conf,const char* post,map** request_inputs,service* s,maps** inputs,maps** outputs,HINTERNET* hInternet){
1465
1466  map* version=getMapFromMaps(*main_conf,"main","rversion");
1467  int vid=getVersionId(version->value);
1468
1469  xmlInitParser ();
1470  xmlDocPtr doc = xmlReadMemory (post, cgiContentLength, "input_request.xml", NULL, XML_PARSE_RECOVER);
1471
1472  /**
1473   * Extract Input nodes from the XML Request.
1474   */
1475  xmlXPathObjectPtr tmpsptr =
1476    extractFromDoc (doc, (vid==0?"/*/*/*[local-name()='Input']":"/*/*[local-name()='Input']"));
1477  xmlNodeSet *tmps = tmpsptr->nodesetval;
1478  if(tmps==NULL || xmlParseInputs(main_conf,s,inputs,doc,tmps,hInternet)<0){
1479    xmlXPathFreeObject (tmpsptr);
1480    xmlFreeDoc (doc);
1481    xmlCleanupParser ();
1482    return -1;
1483  }
1484  xmlXPathFreeObject (tmpsptr);
1485
1486  if(vid==1){
1487    tmpsptr =
1488      extractFromDoc (doc, "/*[local-name()='Execute']");
1489    bool asRaw = false;
1490    tmps = tmpsptr->nodesetval;
1491    if(tmps->nodeNr > 0){
1492      int k = 0;
1493      for (k=0; k < tmps->nodeNr; k++){
1494        maps *tmpmaps = NULL;
1495        xmlNodePtr cur = tmps->nodeTab[k];
1496        if (cur->type == XML_ELEMENT_NODE){
1497          xmlChar *val = xmlGetProp (cur, BAD_CAST "mode");
1498          if(val!=NULL)
1499            addToMap(*request_inputs,"mode",(char*)val);
1500          else
1501            addToMap(*request_inputs,"mode","auto");
1502          val = xmlGetProp (cur, BAD_CAST "response");
1503          if(val!=NULL){
1504            addToMap(*request_inputs,"response",(char*)val);
1505            if(strncasecmp((char*)val,"raw",xmlStrlen(val))==0)
1506              addToMap(*request_inputs,"RawDataOutput","");
1507            else
1508              addToMap(*request_inputs,"ResponseDocument","");
1509          }
1510          else{
1511            addToMap(*request_inputs,"response","document");
1512            addToMap(*request_inputs,"ResponseDocument","");
1513          }
1514        }
1515      }
1516    }
1517    xmlXPathFreeObject (tmpsptr);
1518    tmpsptr =
1519      extractFromDoc (doc, "/*/*[local-name()='Output']");
1520    tmps = tmpsptr->nodesetval;
1521    if(tmps->nodeNr > 0){
1522      if(xmlParseOutputs2(main_conf,request_inputs,outputs,doc,tmps)<0){
1523        xmlXPathFreeObject (tmpsptr);
1524        xmlFreeDoc (doc);
1525        xmlCleanupParser ();
1526        return -1;
1527      }
1528    }
1529  }
1530  else{
1531    // Extract ResponseDocument / RawDataOutput from the XML Request
1532    tmpsptr =
1533      extractFromDoc (doc, "/*/*/*[local-name()='ResponseDocument']");
1534    bool asRaw = false;
1535    tmps = tmpsptr->nodesetval;
1536    if (tmps->nodeNr == 0)
1537      {
1538        xmlXPathFreeObject (tmpsptr);
1539        tmpsptr =
1540          extractFromDoc (doc, "/*/*/*[local-name()='RawDataOutput']");
1541        tmps = tmpsptr->nodesetval;
1542        asRaw = true;
1543      }
1544    if(tmps->nodeNr != 0){
1545      if(xmlParseOutputs(main_conf,request_inputs,outputs,doc,tmps->nodeTab[0],asRaw)<0){
1546        xmlXPathFreeObject (tmpsptr);
1547        xmlFreeDoc (doc);
1548        xmlCleanupParser ();
1549        return -1;
1550      }
1551    }
1552  }
1553  xmlXPathFreeObject (tmpsptr);
1554  xmlFreeDoc (doc);
1555  xmlCleanupParser ();
1556  return 1;
1557}
1558
1559/**
1560 * Parse request and store information in maps.
1561 *
1562 * @param main_conf the conf maps containing the main.cfg settings
1563 * @param post the string containing the XML request
1564 * @param request_inputs the map storing KVP raw value
1565 * @param s the service
1566 * @param inputs the maps to store the KVP pairs
1567 * @param outputs the maps to store the KVP pairs
1568 * @param hInternet the HINTERNET queue to add potential requests
1569 * @return 0 on success, -1 on failure
1570 * @see kvpParseOutputs,kvpParseInputs,xmlParseRequest
1571 */
1572int parseRequest(maps** main_conf,map** request_inputs,service* s,maps** inputs,maps** outputs,HINTERNET* hInternet){
1573  map *postRequest = NULL;
1574  postRequest = getMap (*request_inputs, "xrequest");
1575  if (postRequest == NULLMAP)
1576    {
1577      if(kvpParseOutputs(main_conf,*request_inputs,outputs)<0){
1578        return -1;
1579      }
1580      if(kvpParseInputs(main_conf,s,*request_inputs,inputs,hInternet)<0){
1581        return -1;
1582      }
1583    }
1584  else
1585    {
1586      //Parse XML request
1587      if(xmlParseRequest(main_conf,postRequest->value,request_inputs,s,inputs,outputs,hInternet)<0){
1588        return -1;
1589      }
1590    }
1591  return 1;
1592}
1593
1594/**
1595 * Ensure that each requested arguments are present in the request
1596 * DataInputs and ResponseDocument / RawDataOutput. Potentially run
1597 * http requests from the queue in parallel.
1598 * For optional inputs add default values defined in the ZCFG file.
1599 *
1600 * @param main_conf
1601 * @param s
1602 * @param original_request
1603 * @param request_inputs
1604 * @param request_outputs
1605 * @param hInternet
1606 *
1607 * @see runHttpRequests
1608 */
1609int validateRequest(maps** main_conf,service* s,map* original_request, maps** request_inputs,maps** request_outputs,HINTERNET* hInternet){
1610
1611  map* errI0=NULL;
1612  runHttpRequests (main_conf, request_inputs, hInternet,&errI0);
1613  if(errI0!=NULL){
1614    printExceptionReportResponse (*main_conf, errI0);
1615    InternetCloseHandle (hInternet);
1616    return -1;
1617  }
1618  InternetCloseHandle (hInternet);
1619
1620
1621  map* errI=NULL;
1622  char *dfv = addDefaultValues (request_inputs, s->inputs, *main_conf, 0,&errI);
1623
1624  maps *ptr = *request_inputs;
1625  while (ptr != NULL)
1626    {
1627      map *tmp0 = getMap (ptr->content, "size");
1628      map *tmp1 = getMap (ptr->content, "maximumMegabytes");
1629      if (tmp1 != NULL && tmp0 != NULL)
1630        {
1631          float i = atof (tmp0->value) / 1048576.0;
1632          if (i >= atoi (tmp1->value))
1633            {
1634              char tmps[1024];
1635              map *tmpe = createMap ("code", "FileSizeExceeded");
1636              snprintf (tmps, 1024,
1637                        _
1638                        ("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)."),
1639                        ptr->name, tmp1->value, i);
1640              addToMap (tmpe, "locator", ptr->name);
1641              addToMap (tmpe, "text", tmps);
1642              printExceptionReportResponse (*main_conf, tmpe);
1643              freeMap (&tmpe);
1644              free (tmpe);
1645              return -1;
1646            }
1647        }
1648      ptr = ptr->next;
1649    }
1650
1651  map* errO=NULL;
1652  char *dfv1 =
1653    addDefaultValues (request_outputs, s->outputs, *main_conf, 1,&errO);
1654
1655  if (strcmp (dfv1, "") != 0 || strcmp (dfv, "") != 0)
1656    {
1657      char tmps[1024];
1658      map *tmpe = NULL;
1659      if (strcmp (dfv, "") != 0)
1660        {
1661          tmpe = createMap ("code", "MissingParameterValue");
1662          int nb=0;
1663          int length=1;
1664          map* len=getMap(errI,"length");
1665          if(len!=NULL)
1666            length=atoi(len->value);
1667          for(nb=0;nb<length;nb++){
1668            map* errp=getMapArray(errI,"value",nb);
1669            snprintf (tmps, 1024,
1670                      _
1671                      ("The <%s> argument was not specified in DataInputs but is required according to the ZOO ServicesProvider configuration file."),
1672                      errp->value);
1673            setMapArray (tmpe, "locator", nb , errp->value);
1674            setMapArray (tmpe, "text", nb , tmps);
1675            setMapArray (tmpe, "code", nb , "MissingParameterValue");
1676          }
1677        }
1678      if (strcmp (dfv1, "") != 0)
1679        {
1680          int ilength=0;
1681          if(tmpe==NULL)
1682            tmpe = createMap ("code", "InvalidParameterValue");
1683          else{
1684            map* len=getMap(tmpe,"length");
1685            if(len!=NULL)
1686              ilength=atoi(len->value);
1687          }
1688          int nb=0;
1689          int length=1;
1690          map* len=getMap(errO,"length");
1691          if(len!=NULL)
1692            length=atoi(len->value);
1693          for(nb=0;nb<length;nb++){
1694            map* errp=getMapArray(errO,"value",nb);
1695            snprintf (tmps, 1024,
1696                      _
1697                      ("The <%s> argument specified as %s identifier was not recognized (not defined in the ZOO Configuration File)."),
1698                      errp->value,
1699                      ((getMap(original_request,"RawDataOutput")!=NULL)?"RawDataOutput":"ResponseDocument"));
1700            setMapArray (tmpe, "locator", nb+ilength , errp->value);
1701            setMapArray (tmpe, "text", nb+ilength , tmps);
1702            setMapArray (tmpe, "code", nb+ilength , "InvalidParameterValue");
1703          }
1704        }
1705      printExceptionReportResponse (*main_conf, tmpe);
1706      if(errI!=NULL){
1707        freeMap(&errI);
1708        free(errI);
1709      }
1710      if(errO!=NULL){
1711        freeMap(&errO);
1712        free(errO);
1713      }
1714      freeMap (&tmpe);
1715      free (tmpe);
1716      return -1;
1717    }
1718  maps *tmpReqI = *request_inputs;
1719  while (tmpReqI != NULL)
1720    {
1721      char name[1024];
1722      if (getMap (tmpReqI->content, "isFile") != NULL)
1723        {
1724          if (cgiFormFileName (tmpReqI->name, name, sizeof (name)) ==
1725              cgiFormSuccess)
1726            {
1727              int BufferLen = 1024;
1728              cgiFilePtr file;
1729              int targetFile;
1730              char *storageNameOnServer;
1731              char *fileNameOnServer;
1732              char contentType[1024];
1733              char buffer[1024];
1734              char *tmpStr = NULL;
1735              int size;
1736              int got, t;
1737              map *path = getMapFromMaps (*main_conf, "main", "tmpPath");
1738              cgiFormFileSize (tmpReqI->name, &size);
1739              cgiFormFileContentType (tmpReqI->name, contentType,
1740                                      sizeof (contentType));
1741              if (cgiFormFileOpen (tmpReqI->name, &file) == cgiFormSuccess)
1742                {
1743                  t = -1;
1744                  while (1)
1745                    {
1746                      tmpStr = strstr (name + t + 1, "\\");
1747                      if (NULL == tmpStr)
1748                        tmpStr = strstr (name + t + 1, "/");
1749                      if (NULL != tmpStr)
1750                        t = (int) (tmpStr - name);
1751                      else
1752                        break;
1753                    }
1754                  fileNameOnServer=(char*)malloc((strlen(name) - t - 1 )*sizeof(char));
1755                  strcpy (fileNameOnServer, name + t + 1);
1756
1757                  storageNameOnServer=(char*)malloc((strlen(path->value) + strlen(fileNameOnServer) + 2)*sizeof(char));
1758                  sprintf (storageNameOnServer, "%s/%s", path->value,
1759                           fileNameOnServer);
1760#ifdef DEBUG
1761                  fprintf (stderr, "Name on server %s\n",
1762                           storageNameOnServer);
1763                  fprintf (stderr, "fileNameOnServer: %s\n",
1764                           fileNameOnServer);
1765#endif
1766                  targetFile =
1767                    open (storageNameOnServer, O_RDWR | O_CREAT | O_TRUNC,
1768                          S_IRWXU | S_IRGRP | S_IROTH);
1769                  if (targetFile < 0)
1770                    {
1771#ifdef DEBUG
1772                      fprintf (stderr, "could not create the new file,%s\n",
1773                               fileNameOnServer);
1774#endif
1775                    }
1776                  else
1777                    {
1778                      while (cgiFormFileRead (file, buffer, BufferLen, &got)
1779                             == cgiFormSuccess)
1780                        {
1781                          if (got > 0)
1782                            write (targetFile, buffer, got);
1783                        }
1784                    }
1785                  addToMap (tmpReqI->content, "lref", storageNameOnServer);
1786                  cgiFormFileClose (file);
1787                  close (targetFile);
1788                  free(fileNameOnServer);
1789                  free(storageNameOnServer);
1790#ifdef DEBUG
1791                  fprintf (stderr, "File \"%s\" has been uploaded",
1792                           fileNameOnServer);
1793#endif
1794                }
1795            }
1796        }
1797      tmpReqI = tmpReqI->next;
1798    }
1799
1800  ensureDecodedBase64 (request_inputs);
1801  return 1;
1802}
1803
1804
1805/**
1806 * Verify if a parameter value is valid.
1807 *
1808 * @param request the request map
1809 * @param res the error map potentially generated
1810 * @param toCheck the parameter to use
1811 * @param avalues the acceptable values (or null if testing only for presence)
1812 * @param mandatory verify the presence of the parameter if mandatory > 0
1813 */
1814void checkValidValue(map* request,map** res,const char* toCheck,const char** avalues,int mandatory){
1815  map* lres=*res;
1816  map* r_inputs = getMap (request,toCheck);
1817  if (r_inputs == NULL){
1818    if(mandatory>0){
1819      const char *replace=_("Mandatory parameter <%s> was not specified");
1820      char *message=(char*)malloc((strlen(replace)+strlen(toCheck)+1)*sizeof(char));
1821      sprintf(message,replace,toCheck);
1822      if(lres==NULL){
1823        lres=createMap("code","MissingParameterValue");
1824        addToMap(lres,"text",message);
1825        addToMap(lres,"locator",toCheck);       
1826      }else{
1827        int length=1;
1828        map* len=getMap(lres,"length");
1829        if(len!=NULL){
1830          length=atoi(len->value);
1831        }
1832        setMapArray(lres,"text",length,message);
1833        setMapArray(lres,"locator",length,toCheck);
1834        setMapArray(lres,"code",length,"MissingParameterValue");
1835      }
1836      free(message);
1837    }
1838  }else{
1839    if(avalues==NULL)
1840      return;
1841    int nb=0;
1842    int hasValidValue=-1;
1843    if(strncasecmp(toCheck,"Accept",6)==0){
1844      char *tmp=zStrdup(r_inputs->value);
1845      char *pToken,*saveptr;
1846      pToken=strtok_r(tmp,",",&saveptr);
1847      while(pToken!=NULL){
1848        while(avalues[nb]!=NULL){
1849          if(strcasecmp(avalues[nb],pToken)==0){
1850            hasValidValue=1;
1851            break;
1852          }
1853          nb++;
1854        }
1855        pToken=strtok_r(NULL,",",&saveptr);
1856      }
1857      free(tmp);
1858    }else{
1859      while(avalues[nb]!=NULL){
1860        if(strcasecmp(avalues[nb],r_inputs->value)==0){
1861          hasValidValue=1;
1862          break;
1863        }
1864        nb++;
1865      }
1866    }
1867    if(hasValidValue<0){
1868      const char *replace=_("The value <%s> was not recognized, %s %s the only acceptable value.");
1869      nb=0;
1870      char *vvalues=NULL;
1871      const char* num=_("is");
1872      while(avalues[nb]!=NULL){
1873        char *tvalues;
1874        if(vvalues==NULL){
1875          vvalues=(char*)malloc((strlen(avalues[nb])+3)*sizeof(char));
1876          sprintf(vvalues,"%s",avalues[nb]);
1877        }
1878        else{
1879          tvalues=zStrdup(vvalues);
1880          vvalues=(char*)realloc(vvalues,(strlen(tvalues)+strlen(avalues[nb])+3)*sizeof(char));
1881          sprintf(vvalues,"%s, %s",tvalues,avalues[nb]);
1882          free(tvalues);
1883          num=_("are");
1884        }
1885        nb++;
1886      }
1887      char *message=(char*)malloc((strlen(replace)+strlen(num)+strlen(vvalues)+strlen(toCheck)+1)*sizeof(char));
1888      sprintf(message,replace,toCheck,vvalues,num);
1889      const char *code="VersionNegotiationFailed";
1890      code="InvalidParameterValue";
1891      const char *locator=toCheck;
1892      if( strncasecmp(toCheck,"version",7)==0 ||
1893          strncasecmp(toCheck,"AcceptVersions",14)==0 )
1894        code="VersionNegotiationFailed";
1895      if( strncasecmp(toCheck,"request",7)==0){
1896        code="OperationNotSupported";
1897        locator=r_inputs->value;
1898      }
1899      if(lres==NULL){
1900        lres=createMap("code",code);
1901        addToMap(lres,"text",message);
1902        addToMap(lres,"locator",locator);       
1903      }else{
1904        int length=1;
1905        map* len=getMap(lres,"length");
1906        if(len!=NULL){
1907          length=atoi(len->value);
1908        }
1909        setMapArray(lres,"text",length,message);
1910        setMapArray(lres,"locator",length,locator);
1911        setMapArray(lres,"code",length,code);
1912      }
1913    }
1914  }
1915  if(lres!=NULL){
1916    *res=lres;
1917  }
1918}
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