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

Last change on this file since 795 was 790, checked in by djay, 8 years ago

Add support for nested inputs and outputs.

  • 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        map* tmpCheck=getMap(tmpIoType->content,"useMapServer");
794        if(tmpCheck!=NULL){
795          // Get the default value
796          tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,NULL);
797          tmpCheck=getMap(tmpMaps->content,"mimeType");
798          addToMap(tmpMaps->content,"requestedMimeType",tmpCheck->value);
799          map* cursor=tmpIoType->content;
800          while(cursor!=NULL){
801            addToMap(tmpMaps->content,cursor->name,cursor->value);
802            cursor=cursor->next;
803          }
804         
805          cursor=tmpInputs->content;
806          while(cursor!=NULL){
807            if(strcasecmp(cursor->name,"Title")==0 ||
808               strcasecmp(cursor->name,"Abstract")==0)
809              addToMap(tmpMaps->content,cursor->name,cursor->value);
810           cursor=cursor->next;
811          }
812        }
813#endif
814      }
815      if(tmpMaps->content==NULL)
816        tmpMaps->content=createMap("inRequest","true");
817      else
818        addToMap(tmpMaps->content,"inRequest","true");
819      elements* tmpElements=getElements(in,tmpMaps->name);
820      if(tmpMaps->child!=NULL and tmpElements!=NULL and tmpElements->child!=NULL){
821        char *res=addDefaultValues(&tmpMaps->child,tmpElements->child,m,type,err);
822        if(strlen(res)>0){
823          fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
824          return res;
825        }
826      }
827    }
828    if(tmpInputs->child!=NULL){
829      tmpInputss=tmpInputs->next;
830      tmpInputs=tmpInputs->child;
831      if(tmpMaps!=NULL){
832        out1=tmpMaps->child;
833        out1s=tmpMaps;
834      }
835    }else
836      tmpInputs=tmpInputs->next;
837  }
838  if(tmpInputss!=NULL){
839    out1=out1s;
840    tmpInputs=tmpInputss;
841    tmpInputss=NULL;
842    out1s=NULL;
843    goto loopOnInputs;
844  }
845  if(res!=NULL){
846    *err=res;
847    return result;
848  }
849  return "";
850}
851
852/**
853 * Access the last error message returned by the OS when trying to dynamically
854 * load a shared library.
855 *
856 * @return the last error message
857 * @warning The character string returned from getLastErrorMessage resides
858 * in a static buffer. The application should not write to this
859 * buffer or attempt to free() it.
860 */ 
861char* getLastErrorMessage() {                                             
862#ifdef WIN32
863  LPVOID lpMsgBuf;
864  DWORD errCode = GetLastError();
865  static char msg[ERROR_MSG_MAX_LENGTH];
866  size_t i;
867 
868  DWORD length = FormatMessage(
869                               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
870                               FORMAT_MESSAGE_FROM_SYSTEM |
871                               FORMAT_MESSAGE_IGNORE_INSERTS,
872                               NULL,
873                               errCode,
874                               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
875                               (LPTSTR) &lpMsgBuf,
876                               0, NULL );       
877 
878#ifdef UNICODE         
879  wcstombs_s( &i, msg, ERROR_MSG_MAX_LENGTH,
880              (wchar_t*) lpMsgBuf, _TRUNCATE );
881#else
882  strcpy_s( msg, ERROR_MSG_MAX_LENGTH,
883            (char *) lpMsgBuf );               
884#endif 
885  LocalFree(lpMsgBuf);
886
887  return msg;
888#else
889  return dlerror();
890#endif
891}
892
893#include <dirent.h>
894#ifndef RELY_ON_DB
895/**
896 * Read the Result file (.res).
897 *
898 * @param conf the maps containing the setting of the main.cfg file
899 * @param pid the service identifier (usid key from the [lenv] section)
900 */
901void readFinalRes(maps* conf,char* pid,map* statusInfo){
902  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
903  char* fbkpid =
904    (char *)
905    malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
906  sprintf (fbkpid, "%s/%s.res", r_inputs->value, pid);
907  struct stat file_status;
908  int istat = stat (fbkpid, &file_status);
909  if (istat == 0 && file_status.st_size > 0)
910    {
911      maps *res = (maps *) malloc (MAPS_SIZE);
912      conf_read (fbkpid, res);
913      res->child=NULL;
914      map* status=getMapFromMaps(res,"status","status");
915      addToMap(statusInfo,"Status",status->value);
916      freeMaps(&res);
917      free(res);
918    }
919  else
920    addToMap(statusInfo,"Status","Failed"); 
921  free(fbkpid);
922}
923
924/**
925 * Check if a service is running.
926 *
927 * @param conf the maps containing the setting of the main.cfg file
928 * @param pid the unique service identifier (usid from the lenv section)
929 * @return 1 in case the service is still running, 0 otherwise
930 */
931int isRunning(maps* conf,char* pid){
932  int res=0;
933  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
934  char* fbkpid =
935    (char *)
936    malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
937  sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid);
938  FILE* f0 = fopen (fbkpid, "r");
939  if(f0!=NULL){
940    fclose(f0);
941    res=1;
942  }
943  free(fbkpid);
944  return res;
945}
946#else
947#include "sqlapi.h"
948#endif
949
950/**
951 * Run GetStatus requests.
952 *
953 * @param conf the maps containing the setting of the main.cfg file
954 * @param pid the service identifier (usid key from the [lenv] section)
955 * @param req the request (GetStatus / GetResult)
956 */
957void runGetStatus(maps* conf,char* pid,char* req){
958  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
959  char *sid=getStatusId(conf,pid);
960  if(sid==NULL){
961    errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
962                    "NoSuchJob", pid);
963  }else{
964    map* statusInfo=createMap("JobID",pid);
965    if(isRunning(conf,pid)>0){
966      if(strncasecmp(req,"GetResult",strlen(req))==0){
967        errorException (conf, _("The result for the requested JobID has not yet been generated. "),
968                        "ResultNotReady", pid);
969        return;
970      }
971      else
972        if(strncasecmp(req,"GetStatus",strlen(req))==0){
973          addToMap(statusInfo,"Status","Running");
974          char* tmpStr=_getStatus(conf,pid);
975          if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
976            char *tmpStr1=strdup(tmpStr);
977            char *tmpStr0=strdup(strstr(tmpStr,"|")+1);
978            free(tmpStr);
979            tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
980            addToMap(statusInfo,"PercentCompleted",tmpStr1);
981            addToMap(statusInfo,"Message",tmpStr0);
982            free(tmpStr0);
983            free(tmpStr1);
984          }
985        }
986    }
987    else{
988      if(strncasecmp(req,"GetResult",strlen(req))==0){
989        char* result=_getStatusFile(conf,pid);
990        if(result!=NULL){
991          char *encoding=getEncoding(conf);
992          printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
993          printf("%s",result);
994          fflush(stdout);
995          freeMap(&statusInfo);
996          free(statusInfo);
997          return;
998        }else{
999          errorException (conf, _("The result for the requested JobID has not yet been generated. "),
1000                          "ResultNotReady", pid);
1001          freeMap(&statusInfo);
1002          free(statusInfo);
1003          return;
1004        }
1005      }else
1006        if(strncasecmp(req,"GetStatus",strlen(req))==0){
1007          readFinalRes(conf,pid,statusInfo);
1008          char* tmpStr=_getStatus(conf,pid);
1009          if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
1010            char *tmpStr1=strdup(tmpStr);
1011            char *tmpStr0=strdup(strstr(tmpStr,"|")+1);
1012            free(tmpStr);
1013            tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
1014            addToMap(statusInfo,"PercentCompleted",tmpStr1);
1015            addToMap(statusInfo,"Message",tmpStr0);
1016            free(tmpStr0);
1017            free(tmpStr1);
1018          }
1019        }
1020    }
1021    printStatusInfo(conf,statusInfo,req);
1022    freeMap(&statusInfo);
1023    free(statusInfo);
1024  }
1025  return;
1026}
1027
1028/**
1029 * Run Dismiss requests.
1030 *
1031 * @param conf the maps containing the setting of the main.cfg file
1032 * @param pid the service identifier (usid key from the [lenv] section)
1033 */
1034void runDismiss(maps* conf,char* pid){
1035  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
1036  char *sid=getStatusId(conf,pid);
1037  if(sid==NULL){
1038    errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
1039                    "NoSuchJob", pid);
1040  }else{
1041    // We should send the Dismiss request to the target host if it differs
1042    char* fbkpid =
1043      (char *)
1044      malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
1045    sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid);
1046    FILE* f0 = fopen (fbkpid, "r");
1047    if(f0!=NULL){
1048      long flen;
1049      char *fcontent;
1050      fseek (f0, 0, SEEK_END);
1051      flen = ftell (f0);
1052      fseek (f0, 0, SEEK_SET);
1053      fcontent = (char *) malloc ((flen + 1) * sizeof (char));
1054      fread(fcontent,flen,1,f0);
1055      fcontent[flen]=0;
1056      fclose(f0);
1057#ifndef WIN32
1058      kill(atoi(fcontent),SIGKILL);
1059#else
1060      HANDLE myZooProcess=OpenProcess(PROCESS_ALL_ACCESS,false,atoi(fcontent));
1061      TerminateProcess(myZooProcess,1);
1062      CloseHandle(myZooProcess);
1063#endif
1064      free(fcontent);
1065    }
1066    free(fbkpid);
1067    struct dirent *dp;
1068    DIR *dirp = opendir(r_inputs->value);
1069    char fileName[1024];
1070    int hasFile=-1;
1071    if(dirp!=NULL){
1072      while ((dp = readdir(dirp)) != NULL){
1073#ifdef DEBUG
1074        fprintf(stderr,"File : %s searched : %s\n",dp->d_name,tmp);
1075#endif
1076        if(strstr(dp->d_name,pid)!=0){
1077          sprintf(fileName,"%s/%s",r_inputs->value,dp->d_name);
1078          if(unlink(fileName)!=0){
1079            errorException (conf, 
1080                            _("The job cannot be removed, a file cannot be removed"),
1081                            "NoApplicableCode", NULL);
1082            return;
1083          }
1084        }
1085      }
1086    }
1087#ifdef RELY_ON_DB
1088    removeService(conf,pid);
1089#endif
1090    map* statusInfo=createMap("JobID",pid);
1091    addToMap(statusInfo,"Status","Dismissed");
1092    printStatusInfo(conf,statusInfo,"Dismiss");
1093    free(statusInfo);
1094  }
1095  return;
1096}
1097
1098extern int getServiceFromFile (maps *, const char *, service **);
1099
1100/**
1101 * Parse the service file using getServiceFromFile or use getServiceFromYAML
1102 * if YAML support was activated.
1103 *
1104 * @param conf the conf maps containing the main.cfg settings
1105 * @param file the file name to parse
1106 * @param service the service to update witht the file content
1107 * @param name the service name
1108 * @return true if the file can be parsed or false
1109 * @see getServiceFromFile, getServiceFromYAML
1110 */
1111int readServiceFile (maps * conf, char *file, service ** service, char *name){
1112  int t = getServiceFromFile (conf, file, service);
1113#ifdef YAML
1114  if (t < 0){
1115    t = getServiceFromYAML (conf, file, service, name);
1116  }
1117#endif
1118  return t;
1119}
1120
1121/**
1122 * Create the profile registry.
1123 *
1124 * The profile registry is optional (created only if the registry key is
1125 * available in the [main] section of the main.cfg file) and can be used to
1126 * store the profiles hierarchy. The registry is a directory which should
1127 * contain the following sub-directories:
1128 *  * concept: direcotry containing .html files describing concept
1129 *  * generic: directory containing .zcfg files for wps:GenericProcess
1130 *  * implementation: directory containing .zcfg files for wps:Process
1131 *
1132 * @param m the conf maps containing the main.cfg settings
1133 * @param r the registry to update
1134 * @param reg_dir the resgitry
1135 * @return 0 if the resgitry is null or was correctly updated, -1 on failure
1136 */
1137int createRegistry (maps* m,registry ** r, char *reg_dir)
1138{
1139  char registryKeys[3][15]={
1140    "concept",
1141    "generic",
1142    "implementation"
1143  };
1144  int scount = 0,i=0;
1145  if (reg_dir == NULL)
1146    return 0;
1147  for(i=0;i<3;i++){
1148    char * tmpName =
1149      (char *) malloc ((strlen (reg_dir) + strlen (registryKeys[i]) + 2) *
1150                       sizeof (char));
1151    sprintf (tmpName, "%s/%s", reg_dir, registryKeys[i]);
1152   
1153    DIR *dirp1 = opendir (tmpName);
1154    if(dirp1==NULL){
1155      setMapInMaps(m,"lenv","message",_("Unable to open the registry directory."));
1156      setMapInMaps(m,"lenv","type","InternalError");
1157      return -1;
1158    }
1159    struct dirent *dp1;
1160    while ((dp1 = readdir (dirp1)) != NULL){
1161      char* extn = strstr(dp1->d_name, ".zcfg");
1162      if(dp1->d_name[0] != '.' && extn != NULL && strlen(extn) == 5)
1163        {
1164          int t;
1165          char *tmps1=
1166            (char *) malloc ((strlen (tmpName) + strlen (dp1->d_name) + 2) *
1167                             sizeof (char));
1168          sprintf (tmps1, "%s/%s", tmpName, dp1->d_name);
1169          char *tmpsn = zStrdup (dp1->d_name);
1170          tmpsn[strlen (tmpsn) - 5] = 0;
1171          service* s1 = (service *) malloc (SERVICE_SIZE);
1172          if (s1 == NULL)
1173            {
1174              setMapInMaps(m,"lenv","message",_("Unable to allocate memory."));
1175              setMapInMaps(m,"lenv","type","InternalError");
1176              return -2;
1177            }
1178          t = readServiceFile (m, tmps1, &s1, tmpsn);
1179          free (tmpsn);
1180          if (t < 0)
1181            {
1182              map *tmp00 = getMapFromMaps (m, "lenv", "message");
1183              char tmp01[1024];
1184              if (tmp00 != NULL)
1185                sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"),
1186                         dp1->d_name, tmp00->value);
1187              else
1188                sprintf (tmp01, _("Unable to parse the ZCFG file: %s."),
1189                         dp1->d_name);
1190              setMapInMaps(m,"lenv","message",tmp01);
1191              setMapInMaps(m,"lenv","type","InternalError");
1192              return -1;
1193            }
1194          if(strncasecmp(registryKeys[i],"implementation",14)==0){
1195            inheritance(*r,&s1);
1196          }
1197          addServiceToRegistry(r,registryKeys[i],s1);
1198          freeService (&s1);
1199          free (s1);
1200          scount++;
1201        }
1202    }
1203    (void) closedir (dirp1);
1204  }
1205  return 0;
1206}
1207
1208#ifdef WIN32
1209/**
1210 * Create a KVP request for executing background task.
1211 * TODO: use the XML request in case of input POST request.
1212 *
1213 * @param m the maps containing the parameters from the main.cfg file
1214 * @param length the total length of the KVP parameters
1215 * @param type
1216 */
1217char* getMapsAsKVP(maps* m,int length,int type){
1218  char *dataInputsKVP=(char*) malloc(length*sizeof(char));
1219  char *dataInputsKVPi=NULL;
1220  maps* curs=m;
1221  int i=0;
1222  while(curs!=NULL){
1223    map *inRequest=getMap(curs->content,"inRequest");
1224    map *hasLength=getMap(curs->content,"length");
1225    if((inRequest!=NULL && strncasecmp(inRequest->value,"true",4)==0) ||
1226       inRequest==NULL){
1227      if(i==0)
1228        if(type==0){
1229          sprintf(dataInputsKVP,"%s=",curs->name);
1230          if(hasLength!=NULL){
1231            dataInputsKVPi=(char*)malloc((strlen(curs->name)+2)*sizeof(char));
1232            sprintf(dataInputsKVPi,"%s=",curs->name);
1233          }
1234        }
1235        else
1236          sprintf(dataInputsKVP,"%s",curs->name);
1237      else{
1238        char *temp=zStrdup(dataInputsKVP);
1239        if(type==0)
1240          sprintf(dataInputsKVP,"%s;%s=",temp,curs->name);
1241        else
1242          sprintf(dataInputsKVP,"%s;%s",temp,curs->name);
1243      }
1244      map* icurs=curs->content;
1245      if(type==0){
1246        char *temp=zStrdup(dataInputsKVP);
1247        if(getMap(curs->content,"xlink:href")!=NULL)
1248          sprintf(dataInputsKVP,"%sReference",temp);
1249        else{
1250          if(hasLength!=NULL){
1251            int j;
1252            for(j=0;j<atoi(hasLength->value);j++){
1253              map* tmp0=getMapArray(curs->content,"value",j);
1254              if(j==0)
1255                free(temp);
1256              temp=zStrdup(dataInputsKVP);
1257              if(j==0)
1258                sprintf(dataInputsKVP,"%s%s",temp,tmp0->value);
1259              else
1260                sprintf(dataInputsKVP,"%s;%s%s",temp,dataInputsKVPi,tmp0->value);
1261            }
1262          }
1263          else
1264            sprintf(dataInputsKVP,"%s%s",temp,icurs->value);
1265        }
1266        free(temp);
1267      }
1268      while(icurs!=NULL){
1269        if(strncasecmp(icurs->name,"value",5)!=0 &&
1270           strncasecmp(icurs->name,"mimeType_",9)!=0 &&
1271           strncasecmp(icurs->name,"dataType_",9)!=0 &&
1272           strncasecmp(icurs->name,"size",4)!=0 &&
1273           strncasecmp(icurs->name,"length",4)!=0 &&
1274           strncasecmp(icurs->name,"isArray",7)!=0 &&
1275           strcasecmp(icurs->name,"Reference")!=0 &&
1276           strcasecmp(icurs->name,"minOccurs")!=0 &&
1277           strcasecmp(icurs->name,"maxOccurs")!=0 &&
1278           strncasecmp(icurs->name,"fmimeType",9)!=0 &&
1279           strcasecmp(icurs->name,"inRequest")!=0){
1280          char *itemp=zStrdup(dataInputsKVP);
1281          if(strcasecmp(icurs->name,"xlink:href")!=0)
1282            sprintf(dataInputsKVP,"%s@%s=%s",itemp,icurs->name,icurs->value);
1283          else
1284            sprintf(dataInputsKVP,"%s@%s=%s",itemp,icurs->name,url_encode(icurs->value));
1285          free(itemp);
1286        }
1287        icurs=icurs->next;
1288      }
1289    }
1290    curs=curs->next;
1291    i++;
1292  }
1293  return dataInputsKVP;
1294}
1295#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