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

Last change on this file since 789 was 789, checked in by knut, 7 years ago

Added support for include mechanism in the main.cfg file. An [include] block can be added in main.cfg, like this:

[include]
servicename1 = /my/service/repository/service1.zcfg
servicename2 = /my/service/repository/service2.zcfg
...

The word "include" thus has a special (reserved) meaning, just as "main" does. If necessary, a user may change "include" to something else by redefining the IMPORTSERVICE macro.

The service name (left hand side) should match the [service name] in the config (zcfg) file, but the path/file name (right hand side) may be arbitrary.

When handling requests, Zoo will first check if there is an [include] block, then recursively search the working directory (CWD) and subdirectories as before. If an [include]d service happens to be located in a CWD (sub)directory, it will be published by its [include]d name.

As currently implemented, Zoo will search CWD for the library files of [include]d services if the libPath parameter is not set (note that presently only C and PHP services support the libPath parameter).

Added new function (zoo_path_compare) to check if two path strings refer to the same physical file. It should handle symbolic links (typically, Linux/Unix?) and different path separators (typically, Windows).

  • Property svn:keywords set to Id
File size: 34.4 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  maps* out1=*out;
586  char *result=NULL;
587  int nb=0;
588  if(type==1){
589    while(out1!=NULL){
590      if(getElements(in,out1->name)==NULL){
591        if(res==NULL){
592          res=createMap("value",out1->name);
593        }else{
594          setMapArray(res,"value",nb,out1->name);
595        }
596        nb++;
597        result=out1->name;
598      }
599      out1=out1->next;
600    }
601    if(res!=NULL){
602      *err=res;
603      return result;
604    }
605    out1=*out;
606  }
607  while(tmpInputs!=NULL){
608    maps *tmpMaps=getMaps(out1,tmpInputs->name);
609    if(tmpMaps==NULL){
610      maps* tmpMaps2=(maps*)malloc(MAPS_SIZE);
611      tmpMaps2->name=strdup(tmpInputs->name);
612      tmpMaps2->content=NULL;
613      tmpMaps2->next=NULL;
614     
615      if(type==0){
616        map* tmpMapMinO=getMap(tmpInputs->content,"minOccurs");
617        if(tmpMapMinO!=NULL){
618          if(atoi(tmpMapMinO->value)>=1){
619            freeMaps(&tmpMaps2);
620            free(tmpMaps2);
621            if(res==NULL){
622              res=createMap("value",tmpInputs->name);
623            }else{
624              setMapArray(res,"value",nb,tmpInputs->name);
625            }
626            nb++;
627            result=tmpInputs->name;
628          }
629          else{
630            if(tmpMaps2->content==NULL)
631              tmpMaps2->content=createMap("minOccurs",tmpMapMinO->value);
632            else
633              addToMap(tmpMaps2->content,"minOccurs",tmpMapMinO->value);
634          }
635        }
636        if(res==NULL){
637          map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
638          if(tmpMaxO!=NULL){
639            if(tmpMaps2->content==NULL)
640              tmpMaps2->content=createMap("maxOccurs",tmpMaxO->value);
641            else
642              addToMap(tmpMaps2->content,"maxOccurs",tmpMaxO->value);
643          }
644          map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");
645          if(tmpMaxMB!=NULL){
646            if(tmpMaps2->content==NULL)
647              tmpMaps2->content=createMap("maximumMegabytes",tmpMaxMB->value);
648            else
649              addToMap(tmpMaps2->content,"maximumMegabytes",tmpMaxMB->value);
650          }
651        }
652      }
653
654      if(res==NULL){
655        iotype* tmpIoType=tmpInputs->defaults;
656        if(tmpIoType!=NULL){
657          map* tmpm=tmpIoType->content;
658          while(tmpm!=NULL){
659            if(tmpMaps2->content==NULL)
660              tmpMaps2->content=createMap(tmpm->name,tmpm->value);
661            else
662              addToMap(tmpMaps2->content,tmpm->name,tmpm->value);
663            tmpm=tmpm->next;
664          }
665        }
666        addToMap(tmpMaps2->content,"inRequest","false");
667        if(type==0){
668          map *tmpMap=getMap(tmpMaps2->content,"value");
669          if(tmpMap==NULL)
670            addToMap(tmpMaps2->content,"value","NULL");
671        }
672        if(out1==NULL){
673          *out=dupMaps(&tmpMaps2);
674          out1=*out;
675        }
676        else
677          addMapsToMaps(&out1,tmpMaps2);
678        freeMap(&tmpMaps2->content);
679        free(tmpMaps2->content);
680        tmpMaps2->content=NULL;
681        freeMaps(&tmpMaps2);
682        free(tmpMaps2);
683        tmpMaps2=NULL;
684      }
685    }
686    else{
687      iotype* tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,
688                                             tmpMaps->content);
689      if(type==0) {
690        /**
691         * In case of an Input maps, then add the minOccurs and maxOccurs to the
692         * content map.
693         */
694        map* tmpMap1=getMap(tmpInputs->content,"minOccurs");
695        if(tmpMap1!=NULL){
696          if(tmpMaps->content==NULL)
697            tmpMaps->content=createMap("minOccurs",tmpMap1->value);
698          else
699            addToMap(tmpMaps->content,"minOccurs",tmpMap1->value);
700        }
701        map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
702        if(tmpMaxO!=NULL){
703          if(tmpMaps->content==NULL)
704            tmpMaps->content=createMap("maxOccurs",tmpMaxO->value);
705          else
706            addToMap(tmpMaps->content,"maxOccurs",tmpMaxO->value);
707        }
708        map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");
709        if(tmpMaxMB!=NULL){
710          if(tmpMaps->content==NULL)
711            tmpMaps->content=createMap("maximumMegabytes",tmpMaxMB->value);
712          else
713            addToMap(tmpMaps->content,"maximumMegabytes",tmpMaxMB->value);
714        }
715        /**
716         * Parsing BoundingBoxData, fill the following map and then add it to
717         * the content map of the Input maps:
718         * lowerCorner, upperCorner, srs and dimensions
719         * cf. parseBoundingBox
720         */
721        if(tmpInputs->format!=NULL && strcasecmp(tmpInputs->format,"BoundingBoxData")==0){
722          maps* tmpI=getMaps(*out,tmpInputs->name);
723          if(tmpI!=NULL){
724            map* tmpV=getMap(tmpI->content,"value");
725            if(tmpV!=NULL){
726              char *tmpVS=strdup(tmpV->value);
727              map* tmp=parseBoundingBox(tmpVS);
728              free(tmpVS);
729              map* tmpC=tmp;
730              while(tmpC!=NULL){
731                addToMap(tmpMaps->content,tmpC->name,tmpC->value);
732                tmpC=tmpC->next;
733              }
734              freeMap(&tmp);
735              free(tmp);
736            }
737          }
738        }
739      }
740
741      if(tmpIoType!=NULL){
742        map* tmpContent=tmpIoType->content;
743        map* cval=NULL;
744        int hasPassed=-1;
745        while(tmpContent!=NULL){
746          if((cval=getMap(tmpMaps->content,tmpContent->name))==NULL){
747#ifdef DEBUG
748            fprintf(stderr,"addDefaultValues %s => %s\n",tmpContent->name,tmpContent->value);
749#endif
750            if(tmpMaps->content==NULL)
751              tmpMaps->content=createMap(tmpContent->name,tmpContent->value);
752            else
753              addToMap(tmpMaps->content,tmpContent->name,tmpContent->value);
754           
755            if(hasPassed<0 && type==0 && getMap(tmpMaps->content,"isArray")!=NULL){
756              map* length=getMap(tmpMaps->content,"length");
757              int i;
758              char *tcn=strdup(tmpContent->name);
759              for(i=1;i<atoi(length->value);i++){
760#ifdef DEBUG
761                dumpMap(tmpMaps->content);
762                fprintf(stderr,"addDefaultValues %s_%d => %s\n",tcn,i,tmpContent->value);
763#endif
764                int len=strlen((char*) tcn);
765                char *tmp1=(char *)malloc((len+10)*sizeof(char));
766                sprintf(tmp1,"%s_%d",tcn,i);
767#ifdef DEBUG
768                fprintf(stderr,"addDefaultValues %s => %s\n",tmp1,tmpContent->value);
769#endif
770                addToMap(tmpMaps->content,tmp1,tmpContent->value);
771                free(tmp1);
772                hasPassed=1;
773              }
774              free(tcn);
775            }
776          }
777          tmpContent=tmpContent->next;
778        }
779#ifdef USE_MS
780        /**
781         * check for useMapServer presence
782         */
783        map* tmpCheck=getMap(tmpIoType->content,"useMapServer");
784        if(tmpCheck!=NULL){
785          // Get the default value
786          tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,NULL);
787          tmpCheck=getMap(tmpMaps->content,"mimeType");
788          addToMap(tmpMaps->content,"requestedMimeType",tmpCheck->value);
789          map* cursor=tmpIoType->content;
790          while(cursor!=NULL){
791            addToMap(tmpMaps->content,cursor->name,cursor->value);
792            cursor=cursor->next;
793          }
794         
795          cursor=tmpInputs->content;
796          while(cursor!=NULL){
797            if(strcasecmp(cursor->name,"Title")==0 ||
798               strcasecmp(cursor->name,"Abstract")==0)
799              addToMap(tmpMaps->content,cursor->name,cursor->value);
800           cursor=cursor->next;
801          }
802        }
803#endif
804      }
805      if(tmpMaps->content==NULL)
806        tmpMaps->content=createMap("inRequest","true");
807      else
808        addToMap(tmpMaps->content,"inRequest","true");
809
810    }
811    tmpInputs=tmpInputs->next;
812  }
813  if(res!=NULL){
814    *err=res;
815    return result;
816  }
817  return "";
818}
819
820/**
821 * Access the last error message returned by the OS when trying to dynamically
822 * load a shared library.
823 *
824 * @return the last error message
825 * @warning The character string returned from getLastErrorMessage resides
826 * in a static buffer. The application should not write to this
827 * buffer or attempt to free() it.
828 */ 
829char* getLastErrorMessage() {                                             
830#ifdef WIN32
831  LPVOID lpMsgBuf;
832  DWORD errCode = GetLastError();
833  static char msg[ERROR_MSG_MAX_LENGTH];
834  size_t i;
835 
836  DWORD length = FormatMessage(
837                               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
838                               FORMAT_MESSAGE_FROM_SYSTEM |
839                               FORMAT_MESSAGE_IGNORE_INSERTS,
840                               NULL,
841                               errCode,
842                               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
843                               (LPTSTR) &lpMsgBuf,
844                               0, NULL );       
845 
846#ifdef UNICODE         
847  wcstombs_s( &i, msg, ERROR_MSG_MAX_LENGTH,
848              (wchar_t*) lpMsgBuf, _TRUNCATE );
849#else
850  strcpy_s( msg, ERROR_MSG_MAX_LENGTH,
851            (char *) lpMsgBuf );               
852#endif 
853  LocalFree(lpMsgBuf);
854
855  return msg;
856#else
857  return dlerror();
858#endif
859}
860
861#include <dirent.h>
862#ifndef RELY_ON_DB
863/**
864 * Read the Result file (.res).
865 *
866 * @param conf the maps containing the setting of the main.cfg file
867 * @param pid the service identifier (usid key from the [lenv] section)
868 */
869void readFinalRes(maps* conf,char* pid,map* statusInfo){
870  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
871  char* fbkpid =
872    (char *)
873    malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
874  sprintf (fbkpid, "%s/%s.res", r_inputs->value, pid);
875  struct stat file_status;
876  int istat = stat (fbkpid, &file_status);
877  if (istat == 0 && file_status.st_size > 0)
878    {
879      maps *res = (maps *) malloc (MAPS_SIZE);
880      conf_read (fbkpid, res);
881      map* status=getMapFromMaps(res,"status","status");
882      addToMap(statusInfo,"Status",status->value);
883      freeMaps(&res);
884      free(res);
885    }
886  else
887    addToMap(statusInfo,"Status","Failed"); 
888  free(fbkpid);
889}
890
891/**
892 * Check if a service is running.
893 *
894 * @param conf the maps containing the setting of the main.cfg file
895 * @param pid the unique service identifier (usid from the lenv section)
896 * @return 1 in case the service is still running, 0 otherwise
897 */
898int isRunning(maps* conf,char* pid){
899  int res=0;
900  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
901  char* fbkpid =
902    (char *)
903    malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
904  sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid);
905  FILE* f0 = fopen (fbkpid, "r");
906  if(f0!=NULL){
907    fclose(f0);
908    res=1;
909  }
910  free(fbkpid);
911  return res;
912}
913#else
914#include "sqlapi.h"
915#endif
916
917/**
918 * Run GetStatus requests.
919 *
920 * @param conf the maps containing the setting of the main.cfg file
921 * @param pid the service identifier (usid key from the [lenv] section)
922 * @param req the request (GetStatus / GetResult)
923 */
924void runGetStatus(maps* conf,char* pid,char* req){
925  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
926  char *sid=getStatusId(conf,pid);
927  if(sid==NULL){
928    errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
929                    "NoSuchJob", pid);
930  }else{
931    map* statusInfo=createMap("JobID",pid);
932    if(isRunning(conf,pid)>0){
933      if(strncasecmp(req,"GetResult",strlen(req))==0){
934        errorException (conf, _("The result for the requested JobID has not yet been generated. "),
935                        "ResultNotReady", pid);
936        return;
937      }
938      else
939        if(strncasecmp(req,"GetStatus",strlen(req))==0){
940          addToMap(statusInfo,"Status","Running");
941          char* tmpStr=_getStatus(conf,pid);
942          if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
943            char *tmpStr1=strdup(tmpStr);
944            char *tmpStr0=strdup(strstr(tmpStr,"|")+1);
945            free(tmpStr);
946            tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
947            addToMap(statusInfo,"PercentCompleted",tmpStr1);
948            addToMap(statusInfo,"Message",tmpStr0);
949            free(tmpStr0);
950            free(tmpStr1);
951          }
952        }
953    }
954    else{
955      if(strncasecmp(req,"GetResult",strlen(req))==0){
956        char* result=_getStatusFile(conf,pid);
957        if(result!=NULL){
958          char *encoding=getEncoding(conf);
959          printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
960          printf("%s",result);
961          fflush(stdout);
962          freeMap(&statusInfo);
963          free(statusInfo);
964          return;
965        }else{
966          errorException (conf, _("The result for the requested JobID has not yet been generated. "),
967                          "ResultNotReady", pid);
968          freeMap(&statusInfo);
969          free(statusInfo);
970          return;
971        }
972      }else
973        if(strncasecmp(req,"GetStatus",strlen(req))==0){
974          readFinalRes(conf,pid,statusInfo);
975          char* tmpStr=_getStatus(conf,pid);
976          if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
977            char *tmpStr1=strdup(tmpStr);
978            char *tmpStr0=strdup(strstr(tmpStr,"|")+1);
979            free(tmpStr);
980            tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
981            addToMap(statusInfo,"PercentCompleted",tmpStr1);
982            addToMap(statusInfo,"Message",tmpStr0);
983            free(tmpStr0);
984            free(tmpStr1);
985          }
986        }
987    }
988    printStatusInfo(conf,statusInfo,req);
989    freeMap(&statusInfo);
990    free(statusInfo);
991  }
992  return;
993}
994
995/**
996 * Run Dismiss requests.
997 *
998 * @param conf the maps containing the setting of the main.cfg file
999 * @param pid the service identifier (usid key from the [lenv] section)
1000 */
1001void runDismiss(maps* conf,char* pid){
1002  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
1003  char *sid=getStatusId(conf,pid);
1004  if(sid==NULL){
1005    errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
1006                    "NoSuchJob", pid);
1007  }else{
1008    // We should send the Dismiss request to the target host if it differs
1009    char* fbkpid =
1010      (char *)
1011      malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
1012    sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid);
1013    FILE* f0 = fopen (fbkpid, "r");
1014    if(f0!=NULL){
1015      long flen;
1016      char *fcontent;
1017      fseek (f0, 0, SEEK_END);
1018      flen = ftell (f0);
1019      fseek (f0, 0, SEEK_SET);
1020      fcontent = (char *) malloc ((flen + 1) * sizeof (char));
1021      fread(fcontent,flen,1,f0);
1022      fcontent[flen]=0;
1023      fclose(f0);
1024#ifndef WIN32
1025      kill(atoi(fcontent),SIGKILL);
1026#else
1027      HANDLE myZooProcess=OpenProcess(PROCESS_ALL_ACCESS,false,atoi(fcontent));
1028      TerminateProcess(myZooProcess,1);
1029      CloseHandle(myZooProcess);
1030#endif
1031      free(fcontent);
1032    }
1033    free(fbkpid);
1034    struct dirent *dp;
1035    DIR *dirp = opendir(r_inputs->value);
1036    char fileName[1024];
1037    int hasFile=-1;
1038    if(dirp!=NULL){
1039      while ((dp = readdir(dirp)) != NULL){
1040#ifdef DEBUG
1041        fprintf(stderr,"File : %s searched : %s\n",dp->d_name,tmp);
1042#endif
1043        if(strstr(dp->d_name,pid)!=0){
1044          sprintf(fileName,"%s/%s",r_inputs->value,dp->d_name);
1045          if(unlink(fileName)!=0){
1046            errorException (conf, 
1047                            _("The job cannot be removed, a file cannot be removed"),
1048                            "NoApplicableCode", NULL);
1049            return;
1050          }
1051        }
1052      }
1053    }
1054#ifdef RELY_ON_DB
1055    removeService(conf,pid);
1056#endif
1057    map* statusInfo=createMap("JobID",pid);
1058    addToMap(statusInfo,"Status","Dismissed");
1059    printStatusInfo(conf,statusInfo,"Dismiss");
1060    free(statusInfo);
1061  }
1062  return;
1063}
1064
1065extern int getServiceFromFile (maps *, const char *, service **);
1066
1067/**
1068 * Parse the service file using getServiceFromFile or use getServiceFromYAML
1069 * if YAML support was activated.
1070 *
1071 * @param conf the conf maps containing the main.cfg settings
1072 * @param file the file name to parse
1073 * @param service the service to update witht the file content
1074 * @param name the service name
1075 * @return true if the file can be parsed or false
1076 * @see getServiceFromFile, getServiceFromYAML
1077 */
1078int readServiceFile (maps * conf, char *file, service ** service, char *name){
1079  int t = getServiceFromFile (conf, file, service);
1080#ifdef YAML
1081  if (t < 0){
1082    t = getServiceFromYAML (conf, file, service, name);
1083  }
1084#endif
1085  return t;
1086}
1087
1088/**
1089 * Create the profile registry.
1090 *
1091 * The profile registry is optional (created only if the registry key is
1092 * available in the [main] section of the main.cfg file) and can be used to
1093 * store the profiles hierarchy. The registry is a directory which should
1094 * contain the following sub-directories:
1095 *  * concept: direcotry containing .html files describing concept
1096 *  * generic: directory containing .zcfg files for wps:GenericProcess
1097 *  * implementation: directory containing .zcfg files for wps:Process
1098 *
1099 * @param m the conf maps containing the main.cfg settings
1100 * @param r the registry to update
1101 * @param reg_dir the resgitry
1102 * @return 0 if the resgitry is null or was correctly updated, -1 on failure
1103 */
1104int createRegistry (maps* m,registry ** r, char *reg_dir)
1105{
1106  char registryKeys[3][15]={
1107    "concept",
1108    "generic",
1109    "implementation"
1110  };
1111  int scount = 0,i=0;
1112  if (reg_dir == NULL)
1113    return 0;
1114  for(i=0;i<3;i++){
1115    char * tmpName =
1116      (char *) malloc ((strlen (reg_dir) + strlen (registryKeys[i]) + 2) *
1117                       sizeof (char));
1118    sprintf (tmpName, "%s/%s", reg_dir, registryKeys[i]);
1119   
1120    DIR *dirp1 = opendir (tmpName);
1121    if(dirp1==NULL){
1122      setMapInMaps(m,"lenv","message",_("Unable to open the registry directory."));
1123      setMapInMaps(m,"lenv","type","InternalError");
1124      return -1;
1125    }
1126    struct dirent *dp1;
1127    while ((dp1 = readdir (dirp1)) != NULL){
1128      char* extn = strstr(dp1->d_name, ".zcfg");
1129      if(dp1->d_name[0] != '.' && extn != NULL && strlen(extn) == 5)
1130        {
1131          int t;
1132          char *tmps1=
1133            (char *) malloc ((strlen (tmpName) + strlen (dp1->d_name) + 2) *
1134                             sizeof (char));
1135          sprintf (tmps1, "%s/%s", tmpName, dp1->d_name);
1136          char *tmpsn = zStrdup (dp1->d_name);
1137          tmpsn[strlen (tmpsn) - 5] = 0;
1138          service* s1 = (service *) malloc (SERVICE_SIZE);
1139          if (s1 == NULL)
1140            {
1141              setMapInMaps(m,"lenv","message",_("Unable to allocate memory."));
1142              setMapInMaps(m,"lenv","type","InternalError");
1143              return -2;
1144            }
1145          t = readServiceFile (m, tmps1, &s1, tmpsn);
1146          free (tmpsn);
1147          if (t < 0)
1148            {
1149              map *tmp00 = getMapFromMaps (m, "lenv", "message");
1150              char tmp01[1024];
1151              if (tmp00 != NULL)
1152                sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"),
1153                         dp1->d_name, tmp00->value);
1154              else
1155                sprintf (tmp01, _("Unable to parse the ZCFG file: %s."),
1156                         dp1->d_name);
1157              setMapInMaps(m,"lenv","message",tmp01);
1158              setMapInMaps(m,"lenv","type","InternalError");
1159              return -1;
1160            }
1161          if(strncasecmp(registryKeys[i],"implementation",14)==0){
1162            inheritance(*r,&s1);
1163          }
1164          addServiceToRegistry(r,registryKeys[i],s1);
1165          freeService (&s1);
1166          free (s1);
1167          scount++;
1168        }
1169    }
1170    (void) closedir (dirp1);
1171  }
1172  return 0;
1173}
1174
1175#ifdef WIN32
1176/**
1177 * Create a KVP request for executing background task.
1178 * TODO: use the XML request in case of input POST request.
1179 *
1180 * @param m the maps containing the parameters from the main.cfg file
1181 * @param length the total length of the KVP parameters
1182 * @param type
1183 */
1184char* getMapsAsKVP(maps* m,int length,int type){
1185  char *dataInputsKVP=(char*) malloc(length*sizeof(char));
1186  char *dataInputsKVPi=NULL;
1187  maps* curs=m;
1188  int i=0;
1189  while(curs!=NULL){
1190    map *inRequest=getMap(curs->content,"inRequest");
1191    map *hasLength=getMap(curs->content,"length");
1192    if((inRequest!=NULL && strncasecmp(inRequest->value,"true",4)==0) ||
1193       inRequest==NULL){
1194      if(i==0)
1195        if(type==0){
1196          sprintf(dataInputsKVP,"%s=",curs->name);
1197          if(hasLength!=NULL){
1198            dataInputsKVPi=(char*)malloc((strlen(curs->name)+2)*sizeof(char));
1199            sprintf(dataInputsKVPi,"%s=",curs->name);
1200          }
1201        }
1202        else
1203          sprintf(dataInputsKVP,"%s",curs->name);
1204      else{
1205        char *temp=zStrdup(dataInputsKVP);
1206        if(type==0)
1207          sprintf(dataInputsKVP,"%s;%s=",temp,curs->name);
1208        else
1209          sprintf(dataInputsKVP,"%s;%s",temp,curs->name);
1210      }
1211      map* icurs=curs->content;
1212      if(type==0){
1213        char *temp=zStrdup(dataInputsKVP);
1214        if(getMap(curs->content,"xlink:href")!=NULL)
1215          sprintf(dataInputsKVP,"%sReference",temp);
1216        else{
1217          if(hasLength!=NULL){
1218            int j;
1219            for(j=0;j<atoi(hasLength->value);j++){
1220              map* tmp0=getMapArray(curs->content,"value",j);
1221              if(j==0)
1222                free(temp);
1223              temp=zStrdup(dataInputsKVP);
1224              if(j==0)
1225                sprintf(dataInputsKVP,"%s%s",temp,tmp0->value);
1226              else
1227                sprintf(dataInputsKVP,"%s;%s%s",temp,dataInputsKVPi,tmp0->value);
1228            }
1229          }
1230          else
1231            sprintf(dataInputsKVP,"%s%s",temp,icurs->value);
1232        }
1233        free(temp);
1234      }
1235      while(icurs!=NULL){
1236        if(strncasecmp(icurs->name,"value",5)!=0 &&
1237           strncasecmp(icurs->name,"mimeType_",9)!=0 &&
1238           strncasecmp(icurs->name,"dataType_",9)!=0 &&
1239           strncasecmp(icurs->name,"size",4)!=0 &&
1240           strncasecmp(icurs->name,"length",4)!=0 &&
1241           strncasecmp(icurs->name,"isArray",7)!=0 &&
1242           strcasecmp(icurs->name,"Reference")!=0 &&
1243           strcasecmp(icurs->name,"minOccurs")!=0 &&
1244           strcasecmp(icurs->name,"maxOccurs")!=0 &&
1245           strncasecmp(icurs->name,"fmimeType",9)!=0 &&
1246           strcasecmp(icurs->name,"inRequest")!=0){
1247          char *itemp=zStrdup(dataInputsKVP);
1248          if(strcasecmp(icurs->name,"xlink:href")!=0)
1249            sprintf(dataInputsKVP,"%s@%s=%s",itemp,icurs->name,icurs->value);
1250          else
1251            sprintf(dataInputsKVP,"%s@%s=%s",itemp,icurs->name,url_encode(icurs->value));
1252          free(itemp);
1253        }
1254        icurs=icurs->next;
1255      }
1256    }
1257    curs=curs->next;
1258    i++;
1259  }
1260  return dataInputsKVP;
1261}
1262#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