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

Last change on this file since 681 was 680, checked in by djay, 9 years ago

Various fixes for Windows support: generate uuid using UuidCreate?, pass usid to the created process, call TerminateProcess? on dismiss request.

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