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

Last change on this file since 748 was 745, checked in by djay, 8 years ago

Fix issue when XML request contains empty nodes for inputs

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