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

Last change on this file since 695 was 682, checked in by djay, 9 years ago

Fix GetResult? and POST asynchronous requests on Windows. Prevent CONTENT_TYPE=text/xml before creating the process using CreateProcess?. Revert modifications made r587 for using url_decode directly inside zoo_loader.c, the url_decode call should be in kvpParseInputs (from request_parser.c), indeed, there should not be any decoding required in other cases than Execute requests. Fix issue in mapsFromPyDict, small changes in mapFromPyDict to fix parsing result value (only) for Python 3.

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