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

Last change on this file since 777 was 756, checked in by djay, 11 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