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

Last change on this file since 814 was 805, checked in by djay, 10 years ago

Return default iotype if no value has been provided. Fix potential segfault in case tmpIoType is null.

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