source: trunk/zoo-project/zoo-kernel/server_internal.c @ 778

Last change on this file since 778 was 756, checked in by djay, 9 years ago

Remove prefix for storeSupported and statusSupported for 1.0.0. Fix isValidLang function. Fix error code to MissingParameterValue? or any other relevant code.

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