source: branches/prototype-v0/zoo-project/zoo-kernel/server_internal.c @ 902

Last change on this file since 902 was 902, checked in by djay, 5 years ago

Make Callback and HPC support independent.

  • Property svn:keywords set to Id
File size: 36.6 KB
Line 
1/*
2 * Author : Gérald Fenoy
3 *
4 *  Copyright 2008-2015 GeoLabs SARL. All rights reserved.
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 "server_internal.h"
26#include "service_internal.h"
27#include "response_print.h"
28//#include "service_callback.h"
29#include "mimetypes.h"
30#ifndef WIN32
31#include <dlfcn.h>
32#include <uuid/uuid.h>
33#else
34#include <rpc.h>
35#define ERROR_MSG_MAX_LENGTH 1024
36#endif
37#include <signal.h>
38
39// #include <stdlib.h>
40/*
41 * Compare two file path strings to see if they refer to the same file.
42 *
43 * @param path1 the first file path
44 * @param path2 the second file path
45 *
46 * @return 0 if the files are identical
47 */
48#define PATHBUFSIZE 4096
49int zoo_path_compare(char* path1, char* path2) {
50
51  if (path1 == NULL || path2 == NULL) {
52    return -1;
53  }
54
55  char realpath1[PATHBUFSIZE];
56  char realpath2[PATHBUFSIZE];
57
58#ifdef WIN32
59  int res1 = GetFullPathName(path1, PATHBUFSIZE, realpath1, NULL);
60  int res2 = GetFullPathName(path2, PATHBUFSIZE, realpath2, NULL);
61
62  if (res1 == 0 || res2 == 0) {
63    return -1;
64  }
65  else {
66    return strncasecmp(realpath1, realpath2, PATHBUFSIZE);
67  }
68#else
69  char* ptr1 = realpath(path1, realpath1);
70  char* ptr2 = realpath(path2, realpath2);
71
72  if (ptr1 == NULL || ptr2 == NULL) {
73    return -1;
74  }
75  else {
76    return strncmp(realpath1, realpath2, PATHBUFSIZE);
77  }
78#endif
79}
80
81/**
82 * Detect WPS version used (1.0.0 or 2.0.0).
83 *
84 * @param version number as char* (1.0.0 or 2.0.0)
85 * @return 0 in case of version 1.0.0, 1 for 2.0.0, -1 in other case
86 */
87int getVersionId(const char* version){
88  int schemaId=0;
89  for(;schemaId<2;schemaId++){
90    if(strncasecmp(version,schemas[schemaId][0],5)==0)
91      return schemaId;
92  }
93  return -1;
94}
95
96/**
97 * Generate a UUID.
98 * ref: https://www.ietf.org/rfc/rfc4122.txt / 4.2
99 *
100 * @return a new char* containing the UUID, make sure to free the returned
101 *  resource once used.
102 */
103char *get_uuid(){
104  char *res=(char*)malloc(37*sizeof(char));
105#ifdef WIN32
106  UUID uuid;
107  UuidCreate(&uuid);
108  RPC_CSTR rest = NULL;
109  UuidToString(&uuid,&rest);
110#else
111  uuid_t uuid;
112  uuid_generate_time(uuid);
113  char rest[128];
114  uuid_unparse(uuid,rest);
115#endif
116  sprintf(res,"%s",rest);
117#ifdef WIN32
118  RpcStringFree(&rest);
119#endif
120  return res;
121}
122
123/**
124 * Extract the service identifier from the full service identifier
125 * ie:
126 *  - Full service name: OTB.BandMath
127 *  - Service name: BandMath
128 *
129 * @param conf the maps containing the settings of the main.cfg file
130 * @param conf_dir the full path to the ZOO-Kernel directory
131 * @param identifier the full service name (potentialy including a prefix, ie:
132 *  Prefix.MyService)
133 * @param buffer the resulting service identifier (without any prefix)
134 */
135void parseIdentifier(maps* conf,char* conf_dir,char *identifier,char* buffer){
136  setMapInMaps(conf,"lenv","oIdentifier",identifier);
137  char *lid=zStrdup(identifier);
138  char *saveptr1;
139  char *tmps1=strtok_r(lid,".",&saveptr1);
140  int level=0;
141  char key[25];
142  char levels[18];
143  while(tmps1!=NULL){
144    char *test=zStrdup(tmps1);
145    char* tmps2=(char*)malloc((strlen(test)+2)*sizeof(char));
146    sprintf(key,"sprefix_%d",level);
147    sprintf(tmps2,"%s.",test);
148    sprintf(levels,"%d",level);
149    setMapInMaps(conf,"lenv","level",levels);
150    setMapInMaps(conf,"lenv",key,tmps2);
151    free(tmps2);
152    free(test);
153    level++;
154    tmps1=strtok_r(NULL,".",&saveptr1);
155  }
156  int i=0;
157  sprintf(buffer,"%s",conf_dir);
158  for(i=0;i<level;i++){
159    char *tmp0=zStrdup(buffer);
160    sprintf(key,"sprefix_%d",i);
161    map* tmp00=getMapFromMaps(conf,"lenv",key);
162    if(tmp00!=NULL)
163      sprintf(buffer,"%s/%s",tmp0,tmp00->value);
164    free(tmp0);
165    buffer[strlen(buffer)-1]=0;
166    if(i+1<level){ 
167      #ifdef IGNORE_METAPATH
168        map* tmpMap = createMap("metapath", "");
169      #else 
170        map* tmpMap=getMapFromMaps(conf,"lenv","metapath");
171      #endif     
172      if(tmpMap==NULL || strlen(tmpMap->value)==0){
173        char *tmp01=zStrdup(tmp00->value);
174        tmp01[strlen(tmp01)-1]=0;
175        setMapInMaps(conf,"lenv","metapath",tmp01);
176        free(tmp01);
177        tmp01=NULL;
178      }
179      else{
180        if(tmp00!=NULL && tmpMap!=NULL){
181          char *tmp00s=zStrdup(tmp00->value);
182          tmp00s[strlen(tmp00s)-1]=0;
183          char *value=(char*)malloc((strlen(tmp00s)+strlen(tmpMap->value)+2)*sizeof(char));
184          sprintf(value,"%s/%s",tmpMap->value,tmp00s);
185          setMapInMaps(conf,"lenv","metapath",value);
186          free(value);
187          free(tmp00s);
188          value=NULL;
189        }
190      }
191    }else{
192      char *tmp01=zStrdup(tmp00->value);
193      tmp01[strlen(tmp01)-1]=0;
194      setMapInMaps(conf,"lenv","Identifier",tmp01);
195      free(tmp01);
196    }
197  }
198  char *tmp0=zStrdup(buffer);
199  sprintf(buffer,"%s.zcfg",tmp0);
200  free(tmp0);
201  free(lid);
202}
203
204/**
205 * Converts a hex character to its integer value
206 *
207 * @param ch the char to convert
208 * @return the converted char
209 */
210char from_hex(char ch) {
211  return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
212}
213
214/**
215 * Converts an integer value to its hec character
216 *
217 * @param code the char to convert
218 * @return the converted char
219 */
220char to_hex(char code) {
221  static char hex[] = "0123456789abcdef";
222  return hex[code & 15];
223}
224
225/**
226 * URLEncode an url
227 *
228 * @param str the url to encode
229 * @return a url-encoded version of str
230 * @warning be sure to free() the returned string after use
231 */
232char *url_encode(char *str) {
233  char *pstr = str, *buf = (char*) malloc(strlen(str) * 3 + 1), *pbuf = buf;
234  while (*pstr) {
235    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 
236      *pbuf++ = *pstr;
237    else if (*pstr == ' ') 
238      *pbuf++ = '+';
239    else 
240      *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
241    pstr++;
242  }
243  *pbuf = '\0';
244  return buf;
245}
246
247/**
248 * Decode an URLEncoded url
249 *
250 * @param str the URLEncoded url to decode
251 * @return a url-decoded version of str
252 * @warning be sure to free() the returned string after use
253 */
254char *url_decode(char *str) {
255  char *pstr = str, *buf = (char*) malloc(strlen(str) + 1), *pbuf = buf;
256  while (*pstr) {
257    if (*pstr == '%') {
258      if (pstr[1] && pstr[2]) {
259        *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
260        pstr += 2;
261      }
262    } else if (*pstr == '+') { 
263      *pbuf++ = ' ';
264    } else {
265      *pbuf++ = *pstr;
266    }
267    pstr++;
268  }
269  *pbuf = '\0';
270  return buf;
271}
272
273/**
274 * Verify if a given language is listed in the lang list defined in the [main]
275 * section of the main.cfg file.
276 *
277 * @param conf the map containing the settings from the main.cfg file
278 * @param str the specific language
279 * @return 1 if the specific language is listed, -1 in other case.
280 */
281int isValidLang(maps* conf,const char *str){
282  map *tmpMap=getMapFromMaps(conf,"main","language");
283  char *tmp0=NULL,*tmp=NULL,*tmp1=NULL;
284  if(tmpMap!=NULL)
285    tmp0=zStrdup(tmpMap->value);
286  tmpMap=getMapFromMaps(conf,"main","lang");
287  if(tmpMap!=NULL)
288    tmp=zStrdup(tmpMap->value);
289  if(tmp0!=NULL && tmp!=NULL){
290    tmp1=(char*)malloc((strlen(tmp0)+strlen(tmp)+2)*sizeof(char));
291    sprintf(tmp1,"%s,%s",tmp0,tmp);
292    free(tmp0);
293    free(tmp);
294  }else{
295    if(tmp!=NULL){
296      tmp1=zStrdup(tmp);
297      free(tmp);
298    }else{
299      if(tmp0!=NULL){
300        tmp1=zStrdup(tmp0);
301        free(tmp0);
302      }
303    }
304  }
305  char *pToken,*saveptr;
306  pToken=strtok_r(tmp1,",",&saveptr);
307  int res=-1;
308  while(pToken!=NULL){
309    if(strcasecmp(str,pToken)==0){
310      res=1;
311      break;
312    }
313    pToken=strtok_r(NULL,",",&saveptr);
314  }
315  if(tmp1!=NULL)
316    free(tmp1);
317  return res;
318}
319
320
321/**
322 * Access the value of the encoding key in a maps
323 *
324 * @param m the maps to search for the encoding key
325 * @return the value of the encoding key in a maps if encoding key exists,
326 *  "UTF-8" in other case.
327 */
328char* getEncoding(maps* m){
329  if(m!=NULL){
330    map* tmp=getMap(m->content,"encoding");
331    if(tmp!=NULL){
332      return tmp->value;
333    }
334    else
335      return (char*)"UTF-8";
336  }
337  else
338    return (char*)"UTF-8"; 
339}
340
341/**
342 * Access the value of the version key in a maps
343 *
344 * @param m the maps to search for the version key
345 * @return the value of the version key in a maps if encoding key exists,
346 *  "1.0.0" in other case.
347 */
348char* getVersion(maps* m){
349  if(m!=NULL){
350    map* tmp=getMap(m->content,"version");
351    if(tmp!=NULL){
352      return tmp->value;
353    }
354    else
355      return (char*)"1.0.0";
356  }
357  else
358    return (char*)"1.0.0";
359}
360
361/**
362 * Read a file generated by a service.
363 *
364 * @param m the conf maps
365 * @param content the output item
366 * @param filename the file to read
367 */
368void readGeneratedFile(maps* m,map* content,char* filename){
369  char rsize[1024];
370  FILE * file=fopen(filename,"rb");
371  if(file==NULL){
372    setMapInMaps(m,"lenv","message","Unable to read produced file. Please try again later");
373    return ;
374  }
375  fseek(file, 0, SEEK_END);
376  long count = ftell(file);
377  sprintf(rsize,"%lld",ftell(file));
378  rewind(file);
379  if(getMap(content,"storage")==NULL){
380    map* tmpMap1=getMap(content,"value");
381    if(tmpMap1==NULL){
382      addToMap(content,"value","");
383      tmpMap1=getMap(content,"value");
384    }
385    free(tmpMap1->value);
386    tmpMap1->value=(char*) malloc((count+1)*sizeof(char));
387    if(tmpMap1->value==NULL){
388      setMapInMaps(m,"lenv","message","Unable to allocate the memory required to read the produced file.");
389    }
390    fread(tmpMap1->value,1,count,file);
391    tmpMap1->value[count]=0;
392  }
393  fclose(file); 
394  addToMap(content,"size",rsize);
395}
396
397
398/**
399 * Write a file from value and length
400 *
401 * @param fname the file name
402 * @param val the value
403 * @param length the value length
404 */
405int writeFile(char* fname,char* val,int length){
406  FILE* of=fopen(fname,"wb");
407  if(of==NULL){
408    return -1;
409  }
410  size_t ret=fwrite(val,sizeof(char),length,of);
411  if(ret<length){
412    fprintf(stderr,"Write error occurred!\n");
413    fclose(of);
414    return -1;
415  }
416  fclose(of);
417  return 1;
418}
419
420/**
421 * Dump all values in a maps as files
422 *
423 * @param main_conf the maps containing the settings of the main.cfg file
424 * @param in the maps containing values to dump as files
425 */
426void dumpMapsValuesToFiles(maps** main_conf,maps** in){
427  map* tmpPath=getMapFromMaps(*main_conf,"main","tmpPath");
428  map* tmpUrl=getMapFromMaps(*main_conf,"main","tmpUrl");
429  map* tmpSid=getMapFromMaps(*main_conf,"lenv","usid");
430  maps* inputs=*in;
431  int length=0;
432  while(inputs!=NULL){
433    if(getMap(inputs->content,"mimeType")!=NULL &&
434       getMap(inputs->content,"cache_file")==NULL){
435      map* cMap=inputs->content;
436      if(getMap(cMap,"length")!=NULL){
437        map* tmpLength=getMap(cMap,"length");
438        int len=atoi(tmpLength->value);
439        int k=0;
440        for(k=0;k<len;k++){
441          map* cMimeType=getMapArray(cMap,"mimeType",k);
442          map* cValue=getMapArray(cMap,"value",k);
443          map* cSize=getMapArray(cMap,"size",k);
444          char file_ext[32];
445          getFileExtension(cMimeType != NULL ? cMimeType->value : NULL, file_ext, 32);
446          char* val=(char*)malloc((strlen(tmpPath->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char));
447          sprintf(val,"%s/Input_%s_%s_%d.%s",tmpPath->value,inputs->name,tmpSid->value,k,file_ext);
448          length=0;
449          if(cSize!=NULL){
450            length=atoi(cSize->value);
451          }else
452            length=strlen(cValue->value);
453          writeFile(val,cValue->value,length);
454          setMapArray(cMap,"cache_file",k,val);
455          free(val);
456          val=(char*)malloc((strlen(tmpUrl->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char));
457          sprintf(val,"%s/Input_%s_%s_%d.%s",tmpUrl->value,inputs->name,tmpSid->value,k,file_ext);
458          setMapArray(cMap,"cache_url",k,val);
459          setMapArray(cMap,"byValue",k,"true");
460          free(val);
461        }
462      }else{
463        int length=0;
464        map* cMimeType=getMap(cMap,"mimeType");
465        map* cValue=getMap(cMap,"value");
466        map* cSize=getMap(cMap,"size");
467        char file_ext[32];
468        getFileExtension(cMimeType != NULL ? cMimeType->value : NULL, file_ext, 32);
469        char *val=(char*)malloc((strlen(tmpPath->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char));
470        sprintf(val,"%s/Input_%s_%s_%d.%s",tmpPath->value,inputs->name,tmpSid->value,0,file_ext);
471        if(cSize!=NULL){
472          length=atoi(cSize->value);
473        }else
474          length=strlen(cValue->value);
475        writeFile(val,cValue->value,length);
476        addToMap(cMap,"cache_file",val);
477        free(val);
478        val=(char*)malloc((strlen(tmpUrl->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char));
479        sprintf(val,"%s/Input_%s_%s_%d.%s",tmpUrl->value,inputs->name,tmpSid->value,0,file_ext);
480        addToMap(cMap,"cache_url",val);
481        addToMap(cMap,"byValue",val);
482        free(val);
483      }
484    }
485    inputs=inputs->next;
486  }
487}
488
489
490/**
491 * Base64 encoding of a char*
492 *
493 * @param input the value to encode
494 * @param length the value length
495 * @return the buffer containing the base64 value
496 * @warning make sure to free the returned value
497 */
498char *base64(const char *input, int length)
499{
500  BIO *bmem, *b64;
501  BUF_MEM *bptr;
502
503  b64 = BIO_new(BIO_f_base64());
504  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
505  bmem = BIO_new(BIO_s_mem());
506  b64 = BIO_push(b64, bmem);
507  BIO_write(b64, input, length);
508  BIO_flush(b64);
509  BIO_get_mem_ptr(b64, &bptr);
510
511  char *buff = (char *)malloc((bptr->length+1)*sizeof(char));
512  memcpy(buff, bptr->data, bptr->length);
513  buff[bptr->length] = 0;
514
515  BIO_free_all(b64);
516
517  return buff;
518}
519
520/**
521 * Base64 decoding of a char*
522 *
523 * @param input the value to decode
524 * @param length the value length
525 * @param red the value length
526 * @return the buffer containing the base64 value
527 * @warning make sure to free the returned value
528 */
529char *base64d(const char *input, int length,int* red)
530{
531  BIO *b64, *bmem;
532
533  char *buffer = (char *)malloc(length);
534  if(buffer){
535    memset(buffer, 0, length);
536    b64 = BIO_new(BIO_f_base64());
537    if(b64){
538      bmem = BIO_new_mem_buf((unsigned char*)input,length);
539      bmem = BIO_push(b64, bmem);
540      *red=BIO_read(bmem, buffer, length);
541      buffer[length-1]=0;
542      BIO_free_all(bmem);
543    }
544  }
545  return buffer;
546}
547
548/**
549 * Read Base64 value and split it value by lines of 64 char.
550 *
551 * @param in the map containing the value to split
552 */
553void readBase64(map **in){
554  char *res = NULL;
555  char *curs = (*in)->value;
556  int i = 0;
557  for (i = 0; i <= strlen ((*in)->value) / 64;
558       i++)
559    {
560      if (res == NULL)
561        res =
562          (char *) malloc (65 * sizeof (char));
563      else
564        res =
565          (char *) realloc (res,
566                            (((i + 1) * 65) +
567                             i) * sizeof (char));
568      int csize = i * 65;
569      strncpy (res + csize, curs, 64);
570      if (i == strlen ((*in)->value) / 64)
571        strcat (res, "\n\0");
572      else
573        {
574          strncpy (res + (((i + 1) * 64) + i),
575                   "\n\0", 2);
576          curs += 64;
577        }
578    }
579  free ((*in)->value);
580  (*in)->value = zStrdup (res);
581  free (res);
582}
583
584
585/**
586 * Add the default values defined in the zcfg to a maps.
587 *
588 * @param out the maps containing the inputs or outputs given in the initial
589 *  HTTP request
590 * @param in the description of all inputs or outputs available for a service
591 * @param m the maps containing the settings of the main.cfg file
592 * @param type 0 for inputs and 1 for outputs
593 * @param err the map to store potential missing mandatory input parameters or
594 *  wrong output names depending on the type.
595 * @return "" if no error was detected, the name of last input or output causing
596 *  an error.
597 */
598char* addDefaultValues(maps** out,elements* in,maps* m,int type,map** err){
599  map *res=*err;
600  elements* tmpInputs=in;
601  elements* tmpInputss=NULL;
602  maps* out1=*out;
603  maps* out1s=NULL;
604  char *result=NULL;
605  int nb=0;
606  int inb=0;
607 loopOnInputs:
608  if(type==1){
609    while(out1!=NULL){
610      if(getElements(in,out1->name)==NULL){
611        if(res==NULL){
612          res=createMap("value",out1->name);
613        }else{
614          setMapArray(res,"value",nb,out1->name);
615        }
616        nb++;
617        result=out1->name;
618      }
619      inb++;
620      out1=out1->next;
621    }
622    if(res!=NULL){
623      fflush(stderr);
624      *err=res;
625      return result;
626    }
627    if(out1==NULL && inb>=1)
628      out1=*out;
629  }
630  while(tmpInputs!=NULL){
631    maps *tmpMaps=getMaps(out1,tmpInputs->name);
632    if(tmpMaps==NULL){
633      maps* tmpMaps2=createMaps(tmpInputs->name);
634      if(type==0){
635        map* tmpMapMinO=getMap(tmpInputs->content,"minOccurs");
636        if(tmpMapMinO!=NULL){
637          if(atoi(tmpMapMinO->value)>=1){
638            freeMaps(&tmpMaps2);
639            free(tmpMaps2);
640            if(res==NULL){
641              res=createMap("value",tmpInputs->name);
642            }else{
643              setMapArray(res,"value",nb,tmpInputs->name);
644            }
645            nb++;
646            result=tmpInputs->name;
647          }
648          else{
649            if(tmpMaps2->content==NULL)
650              tmpMaps2->content=createMap("minOccurs",tmpMapMinO->value);
651            else
652              addToMap(tmpMaps2->content,"minOccurs",tmpMapMinO->value);
653          }
654        }
655        if(res==NULL){
656          map* tmpMaxO0=getMap(tmpInputs->content,"useMapserver");
657          if(tmpMaxO0!=NULL){
658            if(tmpMaps2->content==NULL)
659              tmpMaps2->content=createMap("useMapserver",tmpMaxO0->value);
660            else
661              addToMap(tmpMaps2->content,"useMapserver",tmpMaxO0->value);
662          }
663          map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
664          if(tmpMaxO!=NULL){
665            if(tmpMaps2->content==NULL)
666              tmpMaps2->content=createMap("maxOccurs",tmpMaxO->value);
667            else
668              addToMap(tmpMaps2->content,"maxOccurs",tmpMaxO->value);
669          }
670          map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");
671          if(tmpMaxMB!=NULL){
672            if(tmpMaps2->content==NULL)
673              tmpMaps2->content=createMap("maximumMegabytes",tmpMaxMB->value);
674            else
675              addToMap(tmpMaps2->content,"maximumMegabytes",tmpMaxMB->value);
676          }
677        }
678      }
679     
680      if(res==NULL){
681        iotype* tmpIoType=tmpInputs->defaults;
682        if(tmpIoType!=NULL){
683          map* tmpm=tmpIoType->content;
684          while(tmpm!=NULL){
685            if(tmpMaps2->content==NULL)
686              tmpMaps2->content=createMap(tmpm->name,tmpm->value);
687            else{
688              addToMap(tmpMaps2->content,tmpm->name,tmpm->value);
689            }
690            tmpm=tmpm->next;
691          }
692        }
693        if(tmpMaps2->content==NULL){
694          tmpMaps2->content=createMap("inRequest","false");
695          dumpMaps(tmpMaps2);
696        }
697        else
698          addToMap(tmpMaps2->content,"inRequest","false");
699        if(type==0){
700          map *tmpMap=getMap(tmpMaps2->content,"value");
701          if(tmpMap==NULL)
702            addToMap(tmpMaps2->content,"value","NULL");
703        }
704        elements* tmpElements=getElements(in,tmpMaps2->name);
705        if(tmpElements!=NULL && tmpElements->child!=NULL){
706          char *res=addDefaultValues(&tmpMaps2->child,tmpElements->child,m,type,err);
707          if(strlen(res)>0){
708            return res;
709          }
710        }
711
712        if(out1==NULL){
713          *out=dupMaps(&tmpMaps2);
714          out1=*out;
715        }
716        else
717          addMapsToMaps(&out1,tmpMaps2);
718        freeMap(&tmpMaps2->content);
719        free(tmpMaps2->content);
720        tmpMaps2->content=NULL;
721        freeMaps(&tmpMaps2);
722        free(tmpMaps2);
723        tmpMaps2=NULL;
724      }
725    }
726    else /*toto*/{ 
727      iotype* tmpIoType=NULL;
728      if(tmpMaps->content!=NULL){
729        tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,
730                                       tmpMaps->content);
731        if(type==0) {
732          /**
733           * In case of an Input maps, then add the minOccurs and maxOccurs to the
734           * content map.
735           */
736          char* keys[4]={
737            "minOccurs",
738            "maxOccurs",
739            "maximumMegabytes",
740            "useMapserver"
741          };
742          int i=0;
743          for(i=0;i<4;i++){
744            map* tmpMap1=getMap(tmpInputs->content,keys[i]);
745            if(tmpMap1!=NULL){
746              addToMap(tmpMaps->content,keys[i],tmpMap1->value);
747            }
748          }
749          /**
750           * Parsing BoundingBoxData, fill the following map and then add it to
751           * the content map of the Input maps:
752           * lowerCorner, upperCorner, srs and dimensions
753           * cf. parseBoundingBox
754           */
755          if(tmpInputs->format!=NULL && strcasecmp(tmpInputs->format,"BoundingBoxData")==0){
756            maps* tmpI=getMaps(*out,tmpInputs->name);
757            if(tmpI!=NULL){
758              map* tmpV=getMap(tmpI->content,"value");
759              if(tmpV!=NULL){
760                char *tmpVS=zStrdup(tmpV->value);
761                map* tmp=parseBoundingBox(tmpVS);
762                free(tmpVS);
763                map* tmpC=tmp;
764                while(tmpC!=NULL){
765                  addToMap(tmpMaps->content,tmpC->name,tmpC->value);
766                  tmpC=tmpC->next;
767                }
768                freeMap(&tmp);
769                free(tmp);
770              }
771            }
772          }
773        }
774      }else{
775        if(tmpInputs!=NULL){
776          tmpIoType=tmpInputs->defaults;
777        }
778      }
779
780      if(tmpIoType!=NULL){
781        map* tmpContent=tmpIoType->content;
782        map* cval=NULL;
783        int hasPassed=-1;
784        while(tmpContent!=NULL){
785          if((cval=getMap(tmpMaps->content,tmpContent->name))==NULL){
786#ifdef DEBUG
787            fprintf(stderr,"addDefaultValues %s => %s\n",tmpContent->name,tmpContent->value);
788#endif
789            if(tmpMaps->content==NULL)
790              tmpMaps->content=createMap(tmpContent->name,tmpContent->value);
791            else
792              addToMap(tmpMaps->content,tmpContent->name,tmpContent->value);
793           
794            if(hasPassed<0 && type==0 && getMap(tmpMaps->content,"isArray")!=NULL){
795              map* length=getMap(tmpMaps->content,"length");
796              int i;
797              char *tcn=zStrdup(tmpContent->name);
798              for(i=1;i<atoi(length->value);i++){
799#ifdef DEBUG
800                dumpMap(tmpMaps->content);
801                fprintf(stderr,"addDefaultValues %s_%d => %s\n",tcn,i,tmpContent->value);
802#endif
803                int len=strlen((char*) tcn);
804                char *tmp1=(char *)malloc((len+10)*sizeof(char));
805                sprintf(tmp1,"%s_%d",tcn,i);
806#ifdef DEBUG
807                fprintf(stderr,"addDefaultValues %s => %s\n",tmp1,tmpContent->value);
808#endif
809                addToMap(tmpMaps->content,tmp1,tmpContent->value);
810                free(tmp1);
811                hasPassed=1;
812              }
813              free(tcn);
814            }
815          }
816          tmpContent=tmpContent->next;
817        }
818#ifdef USE_MS
819        /**
820         * check for useMapServer presence
821         */
822        if(tmpIoType!=NULL){
823          map* tmpCheck=getMap(tmpIoType->content,"useMapserver");
824          if(tmpCheck!=NULL && strncasecmp(tmpCheck->value,"true",4)==0){
825            // Get the default value
826            addToMap(tmpMaps->content,"useMapserver","true");
827            tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,NULL);
828            tmpCheck=getMap(tmpMaps->content,"mimeType");
829            addToMap(tmpMaps->content,"requestedMimeType",tmpCheck->value);
830            map* cursor=tmpIoType->content;
831            while(cursor!=NULL){
832              addToMap(tmpMaps->content,cursor->name,cursor->value);
833              cursor=cursor->next;
834            }
835         
836            cursor=tmpInputs->content;
837            while(cursor!=NULL){
838              if(strcasecmp(cursor->name,"Title")==0 ||
839                 strcasecmp(cursor->name,"Abstract")==0)
840                addToMap(tmpMaps->content,cursor->name,cursor->value);
841              cursor=cursor->next;
842            }
843          }
844        }
845#endif
846      }
847      if(tmpMaps->content==NULL)
848        tmpMaps->content=createMap("inRequest","true");
849      else
850        addToMap(tmpMaps->content,"inRequest","true");
851      elements* tmpElements=getElements(in,tmpMaps->name);
852      if(/*tmpMaps->child!=NULL && */tmpElements!=NULL && tmpElements->child!=NULL){
853        char *res=addDefaultValues(&tmpMaps->child,tmpElements->child,m,type,err);
854        if(strlen(res)>0){
855          return res;
856        }
857      }
858    }
859    if(tmpInputs->child!=NULL){
860      tmpInputss=tmpInputs->next;
861      tmpInputs=tmpInputs->child;
862      if(tmpMaps!=NULL){
863        out1=tmpMaps->child;
864        out1s=tmpMaps;
865      }
866    }
867    tmpInputs=tmpInputs->next;
868  }
869  if(tmpInputss!=NULL){
870    out1=out1s;
871    tmpInputs=tmpInputss;
872    tmpInputss=NULL;
873    out1s=NULL;
874    goto loopOnInputs;
875  }
876  if(res!=NULL){
877    *err=res;
878    return result;
879  }
880  return "";
881}
882
883/**
884 * Access the last error message returned by the OS when trying to dynamically
885 * load a shared library.
886 *
887 * @return the last error message
888 * @warning The character string returned from getLastErrorMessage resides
889 * in a static buffer. The application should not write to this
890 * buffer or attempt to free() it.
891 */ 
892char* getLastErrorMessage() {                                             
893#ifdef WIN32
894  LPVOID lpMsgBuf;
895  DWORD errCode = GetLastError();
896  static char msg[ERROR_MSG_MAX_LENGTH];
897  size_t i;
898 
899  DWORD length = FormatMessage(
900                               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
901                               FORMAT_MESSAGE_FROM_SYSTEM |
902                               FORMAT_MESSAGE_IGNORE_INSERTS,
903                               NULL,
904                               errCode,
905                               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
906                               (LPTSTR) &lpMsgBuf,
907                               0, NULL );       
908 
909#ifdef UNICODE         
910  wcstombs_s( &i, msg, ERROR_MSG_MAX_LENGTH,
911              (wchar_t*) lpMsgBuf, _TRUNCATE );
912#else
913  strcpy_s( msg, ERROR_MSG_MAX_LENGTH,
914            (char *) lpMsgBuf );               
915#endif 
916  LocalFree(lpMsgBuf);
917
918  return msg;
919#else
920  return dlerror();
921#endif
922}
923
924#include <dirent.h>
925#ifndef RELY_ON_DB
926/**
927 * Read the Result file (.res).
928 *
929 * @param conf the maps containing the setting of the main.cfg file
930 * @param pid the service identifier (usid key from the [lenv] section)
931 */
932void readFinalRes(maps* conf,char* pid,map* statusInfo){
933  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
934  char* fbkpid =
935    (char *)
936    malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
937  sprintf (fbkpid, "%s/%s.res", r_inputs->value, pid);
938  struct stat file_status;
939  int istat = stat (fbkpid, &file_status);
940  if (istat == 0 && file_status.st_size > 0)
941    {
942      maps *res = (maps *) malloc (MAPS_SIZE);
943      conf_read (fbkpid, res);
944      res->child=NULL;
945      map* status=getMapFromMaps(res,"status","status");
946      addToMap(statusInfo,"Status",status->value);
947      freeMaps(&res);
948      free(res);
949    }
950  else
951    addToMap(statusInfo,"Status","Failed"); 
952  free(fbkpid);
953}
954
955/**
956 * Check if a service is running.
957 *
958 * @param conf the maps containing the setting of the main.cfg file
959 * @param pid the unique service identifier (usid from the lenv section)
960 * @return 1 in case the service is still running, 0 otherwise
961 */
962int isRunning(maps* conf,char* pid){
963  int res=0;
964  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
965  char* fbkpid =
966    (char *)
967    malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
968  sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid);
969  FILE* f0 = fopen (fbkpid, "r");
970  if(f0!=NULL){
971    fclose(f0);
972    res=1;
973  }
974  free(fbkpid);
975  return res;
976}
977#else
978#include "sqlapi.h"
979#endif
980
981/**
982 * Run GetStatus requests.
983 *
984 * @param conf the maps containing the setting of the main.cfg file
985 * @param pid the service identifier (usid key from the [lenv] section)
986 * @param req the request (GetStatus / GetResult)
987 */
988void runGetStatus(maps* conf,char* pid,char* req){
989  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
990  char *sid=getStatusId(conf,pid);
991  if(sid==NULL){
992    errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
993                    "NoSuchJob", pid);
994  }else{
995    map* statusInfo=createMap("JobID",pid);
996    if(isRunning(conf,pid)>0){
997      if(strncasecmp(req,"GetResult",strlen(req))==0){
998        errorException (conf, _("The result for the requested JobID has not yet been generated. The service is currently running."),
999                        "ResultNotReady", pid);
1000        return;
1001      }
1002      else
1003        if(strncasecmp(req,"GetStatus",strlen(req))==0){
1004          addToMap(statusInfo,"Status","Running");
1005          char* tmpStr=_getStatus(conf,pid);
1006          if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
1007            char *tmpStr1=zStrdup(tmpStr);
1008            char *tmpStr0=zStrdup(strstr(tmpStr,"|")+1);
1009            free(tmpStr);
1010            tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
1011            addToMap(statusInfo,"PercentCompleted",tmpStr1);
1012            addToMap(statusInfo,"Message",tmpStr0);
1013            free(tmpStr0);
1014            free(tmpStr1);
1015          }
1016        }
1017    }
1018    else{
1019      if(strncasecmp(req,"GetResult",strlen(req))==0){
1020        char* result=_getStatusFile(conf,pid);
1021        if(result!=NULL){
1022          char *encoding=getEncoding(conf);
1023          printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
1024          printf("%s",result);
1025          fflush(stdout);
1026          free(sid);
1027          freeMap(&statusInfo);
1028          free(statusInfo);
1029          free(result);
1030          return;
1031        }else{
1032          errorException (conf, _("The result for the requested JobID has not yet been generated. The service ends but it still needs to produce the outputs."),
1033                          "ResultNotReady", pid);
1034          freeMap(&statusInfo);
1035          free(statusInfo);
1036          return;
1037        }
1038      }else
1039        if(strncasecmp(req,"GetStatus",strlen(req))==0){
1040          readFinalRes(conf,pid,statusInfo);
1041          char* tmpStr=_getStatus(conf,pid);
1042          if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
1043            char *tmpStr1=zStrdup(tmpStr);
1044            char *tmpStr0=zStrdup(strstr(tmpStr,"|")+1);
1045            free(tmpStr);
1046            tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
1047            addToMap(statusInfo,"PercentCompleted",tmpStr1);
1048            addToMap(statusInfo,"Message",tmpStr0);
1049            free(tmpStr0);
1050            free(tmpStr1);
1051          }
1052        }
1053    }
1054    free(sid);
1055    printStatusInfo(conf,statusInfo,req);
1056    freeMap(&statusInfo);
1057    free(statusInfo);
1058  }
1059  return;
1060}
1061
1062/**
1063 * Run Dismiss requests.
1064 *
1065 * @param conf the maps containing the setting of the main.cfg file
1066 * @param pid the service identifier (usid key from the [lenv] section)
1067 */
1068void runDismiss(maps* conf,char* pid){
1069  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
1070  char *sid=getStatusId(conf,pid);
1071  if(sid==NULL){
1072    errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
1073                    "NoSuchJob", pid);
1074  }else{
1075    // We should send the Dismiss request to the target host if it differs
1076    char* fbkpid =
1077      (char *)
1078      malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
1079    sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid);
1080    FILE* f0 = fopen (fbkpid, "r");
1081    if(f0!=NULL){
1082      long flen;
1083      char *fcontent;
1084      fseek (f0, 0, SEEK_END);
1085      flen = ftell (f0);
1086      fseek (f0, 0, SEEK_SET);
1087      fcontent = (char *) malloc ((flen + 1) * sizeof (char));
1088      fread(fcontent,flen,1,f0);
1089      fcontent[flen]=0;
1090      fclose(f0);
1091#ifndef WIN32
1092      kill(atoi(fcontent),SIGKILL);
1093#else
1094      HANDLE myZooProcess=OpenProcess(PROCESS_ALL_ACCESS,false,atoi(fcontent));
1095      TerminateProcess(myZooProcess,1);
1096      CloseHandle(myZooProcess);
1097#endif
1098      free(fcontent);
1099    }
1100    free(fbkpid);
1101    struct dirent *dp;
1102    DIR *dirp = opendir(r_inputs->value);
1103    char fileName[1024];
1104    int hasFile=-1;
1105    if(dirp!=NULL){
1106      while ((dp = readdir(dirp)) != NULL){
1107#ifdef DEBUG
1108        fprintf(stderr,"File : %s searched : %s\n",dp->d_name,tmp);
1109#endif
1110        if(strstr(dp->d_name,pid)!=0){
1111          sprintf(fileName,"%s/%s",r_inputs->value,dp->d_name);
1112          if(unlink(fileName)!=0){
1113            errorException (conf, 
1114                            _("The job cannot be removed, a file cannot be removed"),
1115                            "NoApplicableCode", NULL);
1116            return;
1117          }
1118        }
1119      }
1120    }
1121#ifdef RELY_ON_DB
1122    removeService(conf,pid);
1123#endif
1124    /* No need to call 7_1 when an execution is dismissed.
1125      fprintf(stderr,"************************* %s %d \n\n",__FILE__,__LINE__);
1126      invokeCallback(conf,NULL,NULL,7,1);
1127      fprintf(stderr,"************************* %s %d \n\n",__FILE__,__LINE__);
1128    */
1129    map* statusInfo=createMap("JobID",pid);
1130    addToMap(statusInfo,"Status","Dismissed");
1131    printStatusInfo(conf,statusInfo,"Dismiss");
1132    free(statusInfo);
1133  }
1134  return;
1135}
1136
1137extern int getServiceFromFile (maps *, const char *, service **);
1138
1139/**
1140 * Parse the service file using getServiceFromFile or use getServiceFromYAML
1141 * if YAML support was activated.
1142 *
1143 * @param conf the conf maps containing the main.cfg settings
1144 * @param file the file name to parse
1145 * @param service the service to update witht the file content
1146 * @param name the service name
1147 * @return true if the file can be parsed or false
1148 * @see getServiceFromFile, getServiceFromYAML
1149 */
1150int readServiceFile (maps * conf, char *file, service ** service, char *name){
1151  int t = getServiceFromFile (conf, file, service);
1152#ifdef YAML
1153  if (t < 0){
1154    t = getServiceFromYAML (conf, file, service, name);
1155  }
1156#endif
1157  return t;
1158}
1159
1160/**
1161 * Create the profile registry.
1162 *
1163 * The profile registry is optional (created only if the registry key is
1164 * available in the [main] section of the main.cfg file) and can be used to
1165 * store the profiles hierarchy. The registry is a directory which should
1166 * contain the following sub-directories:
1167 *  * concept: direcotry containing .html files describing concept
1168 *  * generic: directory containing .zcfg files for wps:GenericProcess
1169 *  * implementation: directory containing .zcfg files for wps:Process
1170 *
1171 * @param m the conf maps containing the main.cfg settings
1172 * @param r the registry to update
1173 * @param reg_dir the resgitry
1174 * @return 0 if the resgitry is null or was correctly updated, -1 on failure
1175 */
1176int createRegistry (maps* m,registry ** r, char *reg_dir)
1177{
1178  char registryKeys[3][15]={
1179    "concept",
1180    "generic",
1181    "implementation"
1182  };
1183  int scount = 0,i=0;
1184  if (reg_dir == NULL)
1185    return 0;
1186  for(i=0;i<3;i++){
1187    char * tmpName =
1188      (char *) malloc ((strlen (reg_dir) + strlen (registryKeys[i]) + 2) *
1189                       sizeof (char));
1190    sprintf (tmpName, "%s/%s", reg_dir, registryKeys[i]);
1191   
1192    DIR *dirp1 = opendir (tmpName);
1193    if(dirp1==NULL){
1194      setMapInMaps(m,"lenv","message",_("Unable to open the registry directory."));
1195      setMapInMaps(m,"lenv","type","InternalError");
1196      return -1;
1197    }
1198    struct dirent *dp1;
1199    while ((dp1 = readdir (dirp1)) != NULL){
1200      char* extn = strstr(dp1->d_name, ".zcfg");
1201      if(dp1->d_name[0] != '.' && extn != NULL && strlen(extn) == 5)
1202        {
1203          int t;
1204          char *tmps1=
1205            (char *) malloc ((strlen (tmpName) + strlen (dp1->d_name) + 2) *
1206                             sizeof (char));
1207          sprintf (tmps1, "%s/%s", tmpName, dp1->d_name);
1208          char *tmpsn = zStrdup (dp1->d_name);
1209          tmpsn[strlen (tmpsn) - 5] = 0;
1210          service* s1 = (service *) malloc (SERVICE_SIZE);
1211          if (s1 == NULL)
1212            {
1213              setMapInMaps(m,"lenv","message",_("Unable to allocate memory."));
1214              setMapInMaps(m,"lenv","type","InternalError");
1215              return -2;
1216            }
1217          t = readServiceFile (m, tmps1, &s1, tmpsn);
1218          free (tmpsn);
1219          if (t < 0)
1220            {
1221              map *tmp00 = getMapFromMaps (m, "lenv", "message");
1222              char tmp01[1024];
1223              if (tmp00 != NULL)
1224                sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"),
1225                         dp1->d_name, tmp00->value);
1226              else
1227                sprintf (tmp01, _("Unable to parse the ZCFG file: %s."),
1228                         dp1->d_name);
1229              setMapInMaps(m,"lenv","message",tmp01);
1230              setMapInMaps(m,"lenv","type","InternalError");
1231              return -1;
1232            }
1233          if(strncasecmp(registryKeys[i],"implementation",14)==0){
1234            inheritance(*r,&s1);
1235          }
1236          addServiceToRegistry(r,registryKeys[i],s1);
1237          freeService (&s1);
1238          free (s1);
1239          scount++;
1240        }
1241    }
1242    (void) closedir (dirp1);
1243  }
1244  return 0;
1245}
1246
1247#ifdef WIN32
1248/**
1249 * Create a KVP request for executing background task.
1250 * TODO: use the XML request in case of input POST request.
1251 *
1252 * @param m the maps containing the parameters from the main.cfg file
1253 * @param length the total length of the KVP parameters
1254 * @param type
1255 */
1256char* getMapsAsKVP(maps* m,int length,int type){
1257  char *dataInputsKVP=(char*) malloc(length*sizeof(char));
1258  char *dataInputsKVPi=NULL;
1259  maps* curs=m;
1260  int i=0;
1261  while(curs!=NULL){
1262    map *inRequest=getMap(curs->content,"inRequest");
1263    map *hasLength=getMap(curs->content,"length");
1264    if((inRequest!=NULL && strncasecmp(inRequest->value,"true",4)==0) ||
1265       inRequest==NULL){
1266      if(i==0)
1267        if(type==0){
1268          sprintf(dataInputsKVP,"%s=",curs->name);
1269          if(hasLength!=NULL){
1270            dataInputsKVPi=(char*)malloc((strlen(curs->name)+2)*sizeof(char));
1271            sprintf(dataInputsKVPi,"%s=",curs->name);
1272          }
1273        }
1274        else
1275          sprintf(dataInputsKVP,"%s",curs->name);
1276      else{
1277        char *temp=zStrdup(dataInputsKVP);
1278        if(type==0)
1279          sprintf(dataInputsKVP,"%s;%s=",temp,curs->name);
1280        else
1281          sprintf(dataInputsKVP,"%s;%s",temp,curs->name);
1282      }
1283      map* icurs=curs->content;
1284      if(type==0){
1285        char *temp=zStrdup(dataInputsKVP);
1286        if(getMap(curs->content,"xlink:href")!=NULL)
1287          sprintf(dataInputsKVP,"%sReference",temp);
1288        else{
1289          if(hasLength!=NULL){
1290            int j;
1291            for(j=0;j<atoi(hasLength->value);j++){
1292              map* tmp0=getMapArray(curs->content,"value",j);
1293              if(j==0)
1294                free(temp);
1295              temp=zStrdup(dataInputsKVP);
1296              if(j==0)
1297                sprintf(dataInputsKVP,"%s%s",temp,tmp0->value);
1298              else
1299                sprintf(dataInputsKVP,"%s;%s%s",temp,dataInputsKVPi,tmp0->value);
1300            }
1301          }
1302          else
1303            sprintf(dataInputsKVP,"%s%s",temp,icurs->value);
1304        }
1305        free(temp);
1306      }
1307      while(icurs!=NULL){
1308        if(strncasecmp(icurs->name,"value",5)!=0 &&
1309           strncasecmp(icurs->name,"mimeType_",9)!=0 &&
1310           strncasecmp(icurs->name,"dataType_",9)!=0 &&
1311           strncasecmp(icurs->name,"size",4)!=0 &&
1312           strncasecmp(icurs->name,"length",4)!=0 &&
1313           strncasecmp(icurs->name,"isArray",7)!=0 &&
1314           strcasecmp(icurs->name,"Reference")!=0 &&
1315           strcasecmp(icurs->name,"minOccurs")!=0 &&
1316           strcasecmp(icurs->name,"maxOccurs")!=0 &&
1317           strncasecmp(icurs->name,"fmimeType",9)!=0 &&
1318           strcasecmp(icurs->name,"inRequest")!=0){
1319          char *itemp=zStrdup(dataInputsKVP);
1320          if(strcasecmp(icurs->name,"xlink:href")!=0)
1321            sprintf(dataInputsKVP,"%s@%s=%s",itemp,icurs->name,icurs->value);
1322          else
1323            sprintf(dataInputsKVP,"%s@%s=%s",itemp,icurs->name,url_encode(icurs->value));
1324          free(itemp);
1325        }
1326        icurs=icurs->next;
1327      }
1328    }
1329    curs=curs->next;
1330    i++;
1331  }
1332  return dataInputsKVP;
1333}
1334#endif
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