source: trunk/zoo-project/zoo-kernel/service_internal.c @ 579

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

Add initial doxygen comments in some C files, for future documentation generation.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 115.1 KB
RevLine 
[579]1/*
[1]2 * Author : Gérald FENOY
3 *
[576]4 * Copyright (c) 2009-2015 GeoLabs SARL
[1]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 "service_internal.h"
[364]26#ifdef USE_MS
27#include "service_internal_ms.h"
[478]28#else
29#include "cpl_vsi.h"
[216]30#endif
31
[365]32#ifndef TRUE
33#define TRUE 1
34#endif
35#ifndef FALSE
36#define FALSE -1
37#endif
38
[578]39#ifndef WIN32
40#include <dlfcn.h>
41#endif
42
43#define ERROR_MSG_MAX_LENGTH 1024
44
[579]45/**
46 * Verify if a given language is listed in the lang list defined in the [main]
47 * section of the main.cfg file.
48 *
49 * @param conf the map containing the settings from the main.cfg file
50 * @param str the specific language
51 * @return 1 if the specific language is listed, -1 in other case.
52 */
[501]53int isValidLang(maps* conf,const char *str){
54  map *tmpMap=getMapFromMaps(conf,"main","lang");
55  char *tmp=zStrdup(tmpMap->value);
56  char *pToken=strtok(tmp,",");
57  int res=-1;
58  while(pToken!=NULL){
59    if(strcasecmp(str,pToken)==0){
60      res=1;
61      break;
62    }
63    pToken = strtok(NULL,",");
64  }
65  free(tmp);
66  return res;
67}
68
[579]69/**
70 * Print the HTTP headers based on a map.
71 *
72 * @param m the map containing the headers informations
73 */
[375]74void printHeaders(maps* m){
75  maps *_tmp=getMaps(m,"headers");
76  if(_tmp!=NULL){
77    map* _tmp1=_tmp->content;
78    while(_tmp1!=NULL){
79      printf("%s: %s\r\n",_tmp1->name,_tmp1->value);
80      _tmp1=_tmp1->next;
81    }
82  }
83}
84
[579]85/**
86 * Add a land attribute to a XML node
87 *
88 * @param n the XML node to add the attribute
89 * @param m the map containing the language key to add as xml:lang
90 */
[216]91void addLangAttr(xmlNodePtr n,maps *m){
[34]92  map *tmpLmap=getMapFromMaps(m,"main","language");
93  if(tmpLmap!=NULL)
94    xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST tmpLmap->value);
95  else
96    xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST "en-US");
97}
98
[579]99/**
100 * Converts a hex character to its integer value
101 *
102 * @param ch the char to convert
103 * @return the converted char
104 */
[1]105char from_hex(char ch) {
106  return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
107}
108
[579]109/**
110 * Converts an integer value to its hec character
111 *
112 * @param code the char to convert
113 * @return the converted char
114 */
[1]115char to_hex(char code) {
116  static char hex[] = "0123456789abcdef";
117  return hex[code & 15];
118}
119
[579]120/**
121 * Get the ongoing status of a running service
122 *
123 * @param conf the maps containing the setting of the main.cfg file
124 * @param pid the service identifier (usid key from the [lenv] section)
125 * @return the reported status char* (MESSAGE|POURCENTAGE)
126 */
[507]127char* _getStatus(maps* conf,int pid){
128  char lid[1024];
129  sprintf(lid,"%d",pid);
130  setMapInMaps(conf,"lenv","lid",lid);
131  semid lockid=getShmLockId(conf,1);
132  if(
[216]133#ifdef WIN32
[507]134     lockid==NULL
135#else
136     lockid<0
137#endif
138     ){
139    char tmp[3];
140    sprintf(tmp,"%d",ZOO_LOCK_CREATE_FAILED);
141    return tmp;
142  }
143  if(lockShm(lockid)<0){
144    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
145    fflush(stderr);
146    char tmp[3];
147    sprintf(tmp,"%d",ZOO_LOCK_ACQUIRE_FAILED);
148    return tmp;
149  }
150  char *tmp=getStatus(pid);
151  unlockShm(lockid);
152  if(tmp==NULL || strncmp(tmp,"-1",2)==0){
153    removeShmLock(conf,1);
154  }
155  return tmp;
156}
[216]157
[507]158#ifdef WIN32
159
[216]160#include <windows.h>
[476]161#include <fcgi_stdio.h>
[216]162#include <stdio.h>
163#include <conio.h>
164#include <tchar.h>
165
166#define SHMEMSIZE 4096
167
[554]168size_t getKeyValue(maps* conf, char* key, size_t length){
169  if(conf==NULL) {
[579]170    strncpy(key, "700666", length);
171    return strlen(key);
[554]172  }
173 
[507]174  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
175  if(tmpMap==NULL)
[554]176        tmpMap=getMapFromMaps(conf,"lenv","usid");
177
[507]178  if(tmpMap!=NULL){
[554]179        snprintf(key, length, "zoo_sem_%s", tmpMap->value);     
[507]180  }
[554]181  else {
182        strncpy(key, "-1", length); 
183  }
184  return strlen(key);
[579]185}
186
187
[507]188semid getShmLockId(maps* conf, int nsems){
189    semid sem_id;
[554]190        char key[MAX_PATH];
191        getKeyValue(conf, key, MAX_PATH);
[507]192   
193    sem_id = CreateSemaphore( NULL, nsems, nsems+1, key);
194    if(sem_id==NULL){
[554]195
[507]196#ifdef DEBUG
[578]197      fprintf(stderr,"Semaphore failed to create: %s\n", getLastErrorMessage());
[507]198#endif
199      return NULL;
200    }
201#ifdef DEBUG
202    fprintf(stderr,"%s Accessed !\n",key);
203#endif
[554]204
[507]205    return sem_id;
206}
207
208int removeShmLock(maps* conf, int nsems){
209  semid sem_id=getShmLockId(conf,1);
210  if (CloseHandle(sem_id) == 0) {
[578]211    fprintf(stderr,"Unable to remove semaphore: %s\n", getLastErrorMessage());
[507]212    return -1;
213  }
214#ifdef DEBUG
215  fprintf(stderr,"%d Removed !\n",sem_id);
216#endif
217  return 0;
218}
219
220int lockShm(semid id){
221  DWORD dwWaitResult=WaitForSingleObject(id,INFINITE);
222  switch (dwWaitResult){
223    case WAIT_OBJECT_0:
224      return 0;
225      break;
226    case WAIT_TIMEOUT:
227      return -1;
228      break;
229    default:
230      return -2;
231      break;
232  }
233  return 0;
234}
235
236int unlockShm(semid id){
237  if(!ReleaseSemaphore(id,1,NULL)){
238    return -1;
239  }
240  return 0;
241}
242
[216]243static LPVOID lpvMemG = NULL;      // pointer to shared memory
244static HANDLE hMapObjectG = NULL;  // handle to file mapping
245
[471]246int _updateStatus(maps *conf){
[384]247  LPWSTR lpszTmp;
248  BOOL fInit;
[452]249  char *final_string=NULL;
[384]250  char *s=NULL;
[452]251  map *tmpMap1;
[514]252  map *tmpMap=getMapFromMaps(conf,"lenv","usid");
[507]253  semid lockid=getShmLockId(conf,1);
254  if(lockid==NULL){
255#ifdef DEBUG
256    fprintf(stderr,"Unable to create semaphore on line %d!! \n",__LINE__);
257#endif
258    return ZOO_LOCK_CREATE_FAILED;
259  }
260  if(lockShm(lockid)<0){
261#ifdef DEBUG
262    fprintf(stderr,"Unable to create semaphore on line %d!! \n",__LINE__);
263#endif
264    return ZOO_LOCK_ACQUIRE_FAILED;
265  }
266 
[384]267  if(hMapObjectG==NULL)
268    hMapObjectG = CreateFileMapping( 
269                                    INVALID_HANDLE_VALUE,   // use paging file
270                                    NULL,                   // default security attributes
271                                    PAGE_READWRITE,         // read/write access
272                                    0,                      // size: high 32-bits
273                                    SHMEMSIZE,              // size: low 32-bits
274                                    TEXT(tmpMap->value));   // name of map object
275  if (hMapObjectG == NULL){
[507]276#ifdef DEBUG
[578]277    fprintf(stderr,"Unable to create shared memory segment: %s\n", getLastErrorMessage());
[507]278#endif
[471]279    return -2;
[384]280  }
281  fInit = (GetLastError() != ERROR_ALREADY_EXISTS); 
282  if(lpvMemG==NULL)
283    lpvMemG = MapViewOfFile( 
284                            hMapObjectG,     // object to map view of
285                            FILE_MAP_WRITE, // read/write access
286                            0,              // high offset:  map from
287                            0,              // low offset:   beginning
288                            0);             // default: map entire file
289  if (lpvMemG == NULL){
[507]290#ifdef DEBUG
[384]291    fprintf(stderr,"Unable to create or access the shared memory segment %s !! \n",tmpMap->value);
[507]292#endif
[471]293    return -1;
[384]294  } 
[452]295  memset(lpvMemG, '\0', SHMEMSIZE);
[384]296  tmpMap=getMapFromMaps(conf,"lenv","status");
[452]297  tmpMap1=NULL;
298  tmpMap1=getMapFromMaps(conf,"lenv","message");
[384]299  lpszTmp = (LPWSTR) lpvMemG;
[452]300  final_string=(char*)malloc((strlen(tmpMap1->value)+strlen(tmpMap->value)+2)*sizeof(char));
301  sprintf(final_string,"%s|%s",tmpMap->value,tmpMap1->value);
302  for(s=final_string;*s!='\0';*s++){
[384]303    *lpszTmp++ = *s;
[452]304  }
305  *lpszTmp++ = '\0';
306  free(final_string);
[507]307  unlockShm(lockid);
[471]308  return 0;
[216]309}
310
311char* getStatus(int pid){
[467]312  char *lpszBuf=(char*) malloc(SHMEMSIZE*sizeof(char));
[452]313  int i=0;
[216]314  LPWSTR lpszTmp=NULL;
315  LPVOID lpvMem = NULL;
316  HANDLE hMapObject = NULL;
317  BOOL fIgnore,fInit;
[507]318  char tmp[1024];
319  sprintf(tmp,"%d",pid);
[216]320  if(hMapObject==NULL)
321    hMapObject = CreateFileMapping( 
322                                   INVALID_HANDLE_VALUE,   // use paging file
323                                   NULL,                   // default security attributes
324                                   PAGE_READWRITE,         // read/write access
325                                   0,                      // size: high 32-bits
326                                   4096,                   // size: low 32-bits
327                                   TEXT(tmp));   // name of map object
[507]328  if (hMapObject == NULL){
329#ifdef DEBUG
330    fprintf(stderr,"ERROR on line %d\n",__LINE__);
331#endif
332    return "-1";
333  }
[216]334  if((GetLastError() != ERROR_ALREADY_EXISTS)){
[507]335#ifdef DEBUG
336    fprintf(stderr,"ERROR on line %d\n",__LINE__);
[578]337    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
[507]338#endif
[216]339    fIgnore = UnmapViewOfFile(lpvMem); 
340    fIgnore = CloseHandle(hMapObject);
341    return "-1";
342  }
343  fInit=TRUE;
344  if(lpvMem==NULL)
345    lpvMem = MapViewOfFile( 
346                           hMapObject,     // object to map view of
347                           FILE_MAP_READ,  // read/write access
348                           0,              // high offset:  map from
349                           0,              // low offset:   beginning
350                           0);             // default: map entire file
[507]351  if (lpvMem == NULL){
352#ifdef DEBUG
353    fprintf(stderr,"READING STRING S %d\n",__LINE__);
[578]354    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
[507]355#endif
[216]356    return "-1"; 
[507]357  }
[216]358  lpszTmp = (LPWSTR) lpvMem;
[452]359  while (*lpszTmp){
360    lpszBuf[i] = (char)*lpszTmp;
361    *lpszTmp++; 
362    lpszBuf[i+1] = '\0'; 
363    i++;
364  }
365  return (char*)lpszBuf;
[216]366}
367
368void unhandleStatus(maps *conf){
369  BOOL fIgnore;
370  fIgnore = UnmapViewOfFile(lpvMemG); 
371  fIgnore = CloseHandle(hMapObjectG);
372}
[507]373
[216]374#else
[579]375/**
376 * Number of time to try to access a semaphores set
377 * @see getShmLockId
378 */
[507]379#define MAX_RETRIES 10
380
[509]381#ifndef __APPLE__
382union semun {
383  int val;
384  struct semid_ds *buf;
385  ushort *array;
386};
387#endif
388
[579]389/**
390 * Set in the pre-allocated key the zoo_sem_[SID] string
391 * where [SID] is the lid (if any) or usid value from the [lenv] section.
392 *
393 * @param conf the map containing the setting of the main.cfg file
394 */
[507]395int getKeyValue(maps* conf){
[514]396  if(conf==NULL)
397     return 700666;
[507]398  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
399  if(tmpMap==NULL)
[514]400    tmpMap=getMapFromMaps(conf,"lenv","usid");
[507]401  int key=-1;
402  if(tmpMap!=NULL)
403    key=atoi(tmpMap->value);
404  return key;
405}
406
[579]407/**
408 * Try to create or access a semaphore set.
409 *
410 * @see getKeyValue
411 * @param conf the map containing the setting of the main.cfg file
412 * @param nsems number of semaphores
413 * @return a semaphores set indentifier on success, -1 in other case
414 */
[507]415int getShmLockId(maps* conf, int nsems){
416    int i;
417    union semun arg;
418    struct semid_ds buf;
419    struct sembuf sb;
420    semid sem_id;
421    int key=getKeyValue(conf);
422   
423    sem_id = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666);
424
425    if (sem_id >= 0) { /* we got it first */
426        sb.sem_op = 1; 
427        sb.sem_flg = 0;
428        arg.val=1;
429        for(sb.sem_num = 0; sb.sem_num < nsems; sb.sem_num++) { 
430            /* do a semop() to "free" the semaphores. */
431            /* this sets the sem_otime field, as needed below. */
432            if (semop(sem_id, &sb, 1) == -1) {
433                int e = errno;
434                semctl(sem_id, 0, IPC_RMID); /* clean up */
435                errno = e;
436                return -1; /* error, check errno */
437            }
438        }
439    } else if (errno == EEXIST) { /* someone else got it first */
440        int ready = 0;
441
442        sem_id = semget(key, nsems, 0); /* get the id */
443        if (sem_id < 0) return sem_id; /* error, check errno */
444
445        /* wait for other process to initialize the semaphore: */
446        arg.buf = &buf;
447        for(i = 0; i < MAX_RETRIES && !ready; i++) {
448            semctl(sem_id, nsems-1, IPC_STAT, arg);
449            if (arg.buf->sem_otime != 0) {
450#ifdef DEBUG
451              fprintf(stderr,"Semaphore acquired ...\n");
452#endif
453              ready = 1;
454            } else {
455#ifdef DEBUG
456              fprintf(stderr,"Retry to access the semaphore later ...\n");
457#endif
458              sleep(1);
459            }
460        }
[576]461        errno = ZOO_LOCK_ACQUIRE_FAILED;
[507]462        if (!ready) {
463#ifdef DEBUG
464          fprintf(stderr,"Unable to access the semaphore ...\n");
465#endif
466          errno = ETIME;
467          return -1;
468        }
469    } else {
470        return sem_id; /* error, check errno */
471    }
472#ifdef DEBUG
473    fprintf(stderr,"%d Created !\n",sem_id);
474#endif
475    return sem_id;
476}
477
[579]478/**
479 * Try to remove a semaphore set.
480 *
481 * @param conf the map containing the setting of the main.cfg file
482 * @param nsems number of semaphores
483 * @return 0 if the semaphore can be removed, -1 in other case.
484 */
[507]485int removeShmLock(maps* conf, int nsems){
486  union semun arg;
487  int sem_id=getShmLockId(conf,nsems);
488  if (semctl(sem_id, 0, IPC_RMID, arg) == -1) {
489    perror("semctl");
490    return -1;
491  }
492  return 0;
493}
494
[579]495/**
496 * Lock a semaphore set.
497 *
498 * @param id the semaphores set indetifier
499 * @return 0 if the semaphore can be locked, -1 in other case.
500 */
[507]501int lockShm(int id){
502  struct sembuf sb;
503  sb.sem_num = 0;
504  sb.sem_op = -1;  /* set to allocate resource */
505  sb.sem_flg = SEM_UNDO;
506  if (semop(id, &sb, 1) == -1){
507    perror("semop");
508    return -1;
509  }
510  return 0;
511}
512
[579]513/**
514 * unLock a semaphore set.
515 *
516 * @param id the semaphores set indetifier
517 * @return 0 if the semaphore can be locked, -1 in other case.
518 */
[507]519int unlockShm(int id){
520  struct sembuf sb;
521  sb.sem_num = 0;
522  sb.sem_op = 1;  /* free resource */
523  sb.sem_flg = SEM_UNDO;
524  if (semop(id, &sb, 1) == -1) {
525    perror("semop");
526    return -1;
527  }
528  return 0;
529}
530
[579]531/**
532 * Stop handling status repport.
533 *
534 * @param conf the map containing the setting of the main.cfg file
535 */
[216]536void unhandleStatus(maps *conf){
[490]537  int shmid;
[26]538  key_t key;
539  void *shm;
540  struct shmid_ds shmids;
[514]541  map *tmpMap=getMapFromMaps(conf,"lenv","usid");
[26]542  if(tmpMap!=NULL){
543    key=atoi(tmpMap->value);
544    if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
545#ifdef DEBUG
546      fprintf(stderr,"shmget failed to update value\n");
547#endif
548    }else{
549      if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
550#ifdef DEBUG
551        fprintf(stderr,"shmat failed to update value\n");
552#endif
553      }else{
554        shmdt(shm);
555        shmctl(shmid,IPC_RMID,&shmids);
556      }
557    }
558  }
559}
560
[579]561/**
562 * Update the current of the running service.
563 *
564 * @see getKeyValue, getShmLockId, lockShm
565 * @param conf the map containing the setting of the main.cfg file
566 * @return 0 on success, -2 if shmget failed, -1 if shmat failed
567 */
[471]568int _updateStatus(maps *conf){
[490]569  int shmid;
[26]570  char *shm,*s,*s1;
571  map *tmpMap=NULL;
[507]572  key_t key=getKeyValue(conf);
573  if(key!=-1){
574    semid lockid=getShmLockId(conf,1);
575    if(lockid<0)
576      return ZOO_LOCK_CREATE_FAILED;
577    if(lockShm(lockid)<0){
578      return ZOO_LOCK_ACQUIRE_FAILED;
579    }
[26]580    if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
581#ifdef DEBUG
[255]582      fprintf(stderr,"shmget failed to create new Shared memory segment\n");
[26]583#endif
[507]584      unlockShm(lockid);
[471]585      return -2;
[26]586    }else{
587      if ((shm = (char*) shmat(shmid, NULL, 0)) == (char *) -1) {
588#ifdef DEBUG
589        fprintf(stderr,"shmat failed to update value\n");
590#endif
[507]591        unlockShm(lockid);
[471]592        return -1;
[26]593      }
594      else{
595        tmpMap=getMapFromMaps(conf,"lenv","status");
596        s1=shm;
[255]597        for(s=tmpMap->value;*s!=NULL && *s!=0;s++){
[26]598          *s1++=*s;
[255]599        }
[440]600        *s1++='|';
601        tmpMap=getMapFromMaps(conf,"lenv","message");
602        if(tmpMap!=NULL)
603          for(s=tmpMap->value;*s!=NULL && *s!=0;s++){
604            *s1++=*s;
605        }
[255]606        *s1=NULL;
[26]607        shmdt((void *)shm);
[507]608        unlockShm(lockid);
[26]609      }
610    }
611  }
[471]612  return 0;
[26]613}
614
[579]615/**
616 * Update the current of the running service.
617 *
618 * @see getKeyValue, getShmLockId, lockShm
619 * @param pid the semaphores
620 * @return 0 on success, -2 if shmget failed, -1 if shmat failed
621 */
[26]622char* getStatus(int pid){
[490]623  int shmid;
[26]624  key_t key;
625  void *shm;
626  key=pid;
627  if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
628#ifdef DEBUG
629    fprintf(stderr,"shmget failed in getStatus\n");
630#endif
631  }else{
632    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
633#ifdef DEBUG
634      fprintf(stderr,"shmat failed in getStatus\n");
635#endif
636    }else{
[514]637      char *ret=strdup((char*)shm);
638      shmdt((void *)shm);
639      return ret;
[26]640    }
641  }
[490]642  return (char*)"-1";
[26]643}
644
[216]645#endif
[26]646
[216]647#ifdef USE_JS
648
649JSBool
[274]650JSUpdateStatus(JSContext *cx, uintN argc, jsval *argv1)
[216]651{
[274]652  jsval *argv = JS_ARGV(cx,argv1);
[216]653  JS_MaybeGC(cx);
654  int istatus=0;
655  char *status=NULL;
656  maps *conf;
657  if(argc>2){
658#ifdef JS_DEBUG
659    fprintf(stderr,"Number of arguments used to call the function : %i",argc);
660#endif
661    return JS_FALSE;
662  }
663  conf=mapsFromJSObject(cx,argv[0]);
664  if(JS_ValueToInt32(cx,argv[1],&istatus)==JS_TRUE){
665    char tmpStatus[4];
666    sprintf(tmpStatus,"%i",istatus);
667    tmpStatus[3]=0;
668    status=strdup(tmpStatus);
669  }
670  if(getMapFromMaps(conf,"lenv","status")!=NULL){
[274]671    if(status!=NULL){
[216]672      setMapInMaps(conf,"lenv","status",status);
[274]673      free(status);
674    }
[216]675    else
676      setMapInMaps(conf,"lenv","status","15");
[471]677    _updateStatus(conf);
[216]678  }
679  freeMaps(&conf);
680  free(conf);
681  JS_MaybeGC(cx);
682  return JS_TRUE;
683}
684
685#endif
686
687
[579]688/**
689 * URLEncode an url
690 *
691 * @param str the url to encode
692 * @return a url-encoded version of str
693 * @warning be sure to free() the returned string after use
694 */
[1]695char *url_encode(char *str) {
696  char *pstr = str, *buf = (char*) malloc(strlen(str) * 3 + 1), *pbuf = buf;
697  while (*pstr) {
698    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 
699      *pbuf++ = *pstr;
700    else if (*pstr == ' ') 
701      *pbuf++ = '+';
702    else 
703      *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
704    pstr++;
705  }
706  *pbuf = '\0';
707  return buf;
708}
709
[579]710/**
711 * Decode an URLEncoded url
712 *
713 * @param str the URLEncoded url to decode
714 * @return a url-decoded version of str
715 * @warning be sure to free() the returned string after use
716 */
[1]717char *url_decode(char *str) {
718  char *pstr = str, *buf = (char*) malloc(strlen(str) + 1), *pbuf = buf;
719  while (*pstr) {
720    if (*pstr == '%') {
721      if (pstr[1] && pstr[2]) {
722        *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
723        pstr += 2;
724      }
725    } else if (*pstr == '+') { 
726      *pbuf++ = ' ';
727    } else {
728      *pbuf++ = *pstr;
729    }
730    pstr++;
731  }
732  *pbuf = '\0';
733  return buf;
734}
735
[579]736/**
737 * Replace the first letter by its upper case version in a new char array
738 *
739 * @param tmp the char*
740 * @return a new char* with first letter in upper case
741 * @warning be sure to free() the returned string after use
742 */
[9]743char *zCapitalize1(char *tmp){
[576]744  char *res=zStrdup(tmp);
745  if(res[0]>=97 && res[0]<=122)
746    res[0]-=32;
747  return res;
[9]748}
[1]749
[579]750/**
751 * Replace all letters by their upper case version in a new char array
752 *
753 * @param tmp the char*
754 * @return a new char* with first letter in upper case
755 * @warning be sure to free() the returned string after use
756 */
[9]757char *zCapitalize(char *tmp){
758  int i=0;
[576]759  char *res=zStrdup(tmp);
[9]760  for(i=0;i<strlen(res);i++)
761    if(res[i]>=97 && res[i]<=122)
762      res[i]-=32;
763  return res;
764}
[1]765
[579]766/**
767 * Search for an existing XML namespace in usedNS.
768 *
769 * @param name the name of the XML namespace to search
770 * @return the index of the XML namespace found or -1 if not found.
771 */
[114]772int zooXmlSearchForNs(const char* name){
[9]773  int i;
774  int res=-1;
775  for(i=0;i<nbNs;i++)
776    if(strncasecmp(name,nsName[i],strlen(nsName[i]))==0){
777      res=i;
778      break;
[1]779    }
[9]780  return res;
781}
[1]782
[579]783/**
784 * Add an XML namespace to the usedNS if it was not already used.
785 *
786 * @param nr the xmlNodePtr to attach the XML namspace (can be NULL)
787 * @param url the url of the XML namespace to add
788 * @param name the name of the XML namespace to add
789 * @return the index of the XML namespace added.
790 */
[114]791int zooXmlAddNs(xmlNodePtr nr,const char* url,const char* name){
[1]792#ifdef DEBUG
[483]793  fprintf(stderr,"zooXmlAddNs %d %s \n",nbNs,name);
[1]794#endif
[9]795  int currId=-1;
796  if(nbNs==0){
797    nbNs++;
798    currId=0;
799    nsName[currId]=strdup(name);
800    usedNs[currId]=xmlNewNs(nr,BAD_CAST url,BAD_CAST name);
801  }else{
802    currId=zooXmlSearchForNs(name);
803    if(currId<0){
804      nbNs++;
805      currId=nbNs-1;
806      nsName[currId]=strdup(name);
807      usedNs[currId]=xmlNewNs(nr,BAD_CAST url,BAD_CAST name);
[1]808    }
[9]809  }
810  return currId;
811}
[1]812
[579]813/**
814 * Free allocated memory to store used XML namespace.
815 */
[9]816void zooXmlCleanupNs(){
817  int j;
[1]818#ifdef DEBUG
[9]819  fprintf(stderr,"zooXmlCleanup %d\n",nbNs);
[1]820#endif
[9]821  for(j=nbNs-1;j>=0;j--){
[1]822#ifdef DEBUG
[9]823    fprintf(stderr,"zooXmlCleanup %d\n",j);
[1]824#endif
[9]825    if(j==0)
826      xmlFreeNs(usedNs[j]);
827    free(nsName[j]);
828    nbNs--;
[1]829  }
[9]830  nbNs=0;
[1]831}
832
[579]833/**
834 * Add a XML document to the iDocs.
835 *
836 * @param value the string containing the XML document
837 * @return the index of the XML document added.
838 */
[490]839int zooXmlAddDoc(const char* value){
840  int currId=0;
841  nbDocs++;
842  currId=nbDocs-1;
843  iDocs[currId]=xmlParseMemory(value,strlen(value));
844  return currId;
845}
846
[579]847/**
848 * Free allocated memort to store XML documents
849 */
[490]850void zooXmlCleanupDocs(){
851  int j;
852  for(j=nbDocs-1;j>=0;j--){
853    xmlFreeDoc(iDocs[j]);
854  }
855  nbDocs=0;
856}
857
[576]858/**
859 * Generate a SOAP Envelope node when required (if the isSoap key of the [main]
860 * section is set to true).
861 *
862 * @param conf the conf maps containing the main.cfg settings
863 * @param n the node used as children of the generated soap:Envelope
864 * @return the generated soap:Envelope (if isSoap=true) or the input node n
865 *  (when isSoap=false)
866 */
[280]867xmlNodePtr soapEnvelope(maps* conf,xmlNodePtr n){
868  map* soap=getMapFromMaps(conf,"main","isSoap");
869  if(soap!=NULL && strcasecmp(soap->value,"true")==0){
870    int lNbNs=nbNs;
871    nsName[lNbNs]=strdup("soap");
872    usedNs[lNbNs]=xmlNewNs(NULL,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap");
873    nbNs++;
874    xmlNodePtr nr = xmlNewNode(usedNs[lNbNs], BAD_CAST "Envelope");
875    nsName[nbNs]=strdup("soap");
876    usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap");
877    nbNs++;
878    nsName[nbNs]=strdup("xsi");
879    usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
880    nbNs++;
881    xmlNsPtr ns_xsi=usedNs[nbNs-1];
882    xmlNewNsProp(nr,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.w3.org/2003/05/soap-envelope http://www.w3.org/2003/05/soap-envelope");
883    xmlNodePtr nr1 = xmlNewNode(usedNs[lNbNs], BAD_CAST "Body");
884    xmlAddChild(nr1,n);
885    xmlAddChild(nr,nr1);
886    return nr;
887  }else
888    return n;
889}
890
[576]891/**
892 * Generate a WPS header.
893 *
894 * @param doc the document to add the header
895 * @param m the conf maps containing the main.cfg settings
896 * @param req the request type (GetCapabilities,DescribeProcess,Execute)
897 * @param rname the root node name
898 * @return the generated wps:rname xmlNodePtr (can be wps: Capabilities,
899 *  wps:ProcessDescriptions,wps:ExecuteResponse)
900 */
901xmlNodePtr printWPSHeader(xmlDocPtr doc,maps* m,const char* req,const char* rname){
902
903  xmlNsPtr ns,ns_xsi;
904  xmlNodePtr n;
905
906  int wpsId=zooXmlAddNs(NULL,"http://schemas.opengis.net/wps/1.0.0","wps");
[9]907  ns=usedNs[wpsId];
[576]908  n = xmlNewNode(ns, BAD_CAST rname);
909  zooXmlAddNs(n,"http://www.opengis.net/ows/1.1","ows");
[1]910  xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
[576]911  zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
[9]912  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
913  ns_xsi=usedNs[xsiId];
[576]914 
915  char *tmp=(char*) malloc((86+strlen(req)+1)*sizeof(char));
916  sprintf(tmp,"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wps%s_response.xsd",req);
917  xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST tmp);
918  free(tmp);
[1]919  xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
[576]920  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
[34]921  addLangAttr(n,m);
[576]922  xmlNodePtr fn=soapEnvelope(m,n);
923  xmlDocSetRootElement(doc, fn);
924  return n;
925}
[1]926
[576]927/**
928 * Generate a Capabilities header.
929 *
930 * @param doc the document to add the header
931 * @param m the conf maps containing the main.cfg settings
932 * @return the generated wps:ProcessOfferings xmlNodePtr
933 */
934xmlNodePtr printGetCapabilitiesHeader(xmlDocPtr doc,maps* m){
935
936  xmlNsPtr ns,ns_ows,ns_xlink;
937  xmlNodePtr n,nc,nc1,nc2,nc3,nc4,nc5,nc6;
938  n = printWPSHeader(doc,m,"GetCapabilities","Capabilities");
939  maps* toto1=getMaps(m,"main");
[1]940  char tmp[256];
[576]941
942  int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");
943  ns=usedNs[wpsId];
944  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
945  ns_xlink=usedNs[xlinkId];
946  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
947  ns_ows=usedNs[owsId];
948
[1]949  nc = xmlNewNode(ns_ows, BAD_CAST "ServiceIdentification");
950  maps* tmp4=getMaps(m,"identification");
951  if(tmp4!=NULL){
952    map* tmp2=tmp4->content;
[490]953    const char *orderedFields[5];
[71]954    orderedFields[0]="Title";
955    orderedFields[1]="Abstract";
956    orderedFields[2]="Keywords";
957    orderedFields[3]="Fees";
958    orderedFields[4]="AccessConstraints";
959    int oI=0;
960    for(oI=0;oI<5;oI++)
961      if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){
962        if(strcasecmp(tmp2->name,"abstract")==0 ||
963           strcasecmp(tmp2->name,"title")==0 ||
964           strcasecmp(tmp2->name,"accessConstraints")==0 ||
965           strcasecmp(tmp2->name,"fees")==0){
966          tmp2->name[0]=toupper(tmp2->name[0]);
967          nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
968          xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
969          xmlAddChild(nc,nc1);
970        }
971        else
972          if(strcmp(tmp2->name,"keywords")==0){
973            nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords");
974            char *toto=tmp2->value;
975            char buff[256];
976            int i=0;
977            int j=0;
978            while(toto[i]){
979              if(toto[i]!=',' && toto[i]!=0){
980                buff[j]=toto[i];
981                buff[j+1]=0;
982                j++;
983              }
984              else{
985                nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
986                xmlAddChild(nc2,xmlNewText(BAD_CAST buff));           
987                xmlAddChild(nc1,nc2);
988                j=0;
989              }
990              i++;
[1]991            }
[71]992            if(strlen(buff)>0){
[1]993              nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
994              xmlAddChild(nc2,xmlNewText(BAD_CAST buff));             
995              xmlAddChild(nc1,nc2);
996            }
[71]997            xmlAddChild(nc,nc1);
998            nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceType");
999            xmlAddChild(nc2,xmlNewText(BAD_CAST "WPS"));
1000            xmlAddChild(nc,nc2);
1001            nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceTypeVersion");
1002            xmlAddChild(nc2,xmlNewText(BAD_CAST "1.0.0"));
[576]1003            xmlAddChild(nc,nc2);
[1]1004          }
[71]1005        tmp2=tmp2->next;
1006      }
[1]1007  }
1008  else{
1009    fprintf(stderr,"TMP4 NOT FOUND !!");
1010    return NULL;
1011  }
1012  xmlAddChild(n,nc);
1013
1014  nc = xmlNewNode(ns_ows, BAD_CAST "ServiceProvider");
1015  nc3 = xmlNewNode(ns_ows, BAD_CAST "ServiceContact");
1016  nc4 = xmlNewNode(ns_ows, BAD_CAST "ContactInfo");
1017  nc5 = xmlNewNode(ns_ows, BAD_CAST "Phone");
1018  nc6 = xmlNewNode(ns_ows, BAD_CAST "Address");
1019  tmp4=getMaps(m,"provider");
1020  if(tmp4!=NULL){
1021    map* tmp2=tmp4->content;
[490]1022    const char *tmpAddress[6];
[57]1023    tmpAddress[0]="addressDeliveryPoint";
1024    tmpAddress[1]="addressCity";
1025    tmpAddress[2]="addressAdministrativeArea";
1026    tmpAddress[3]="addressPostalCode";
1027    tmpAddress[4]="addressCountry";
1028    tmpAddress[5]="addressElectronicMailAddress";
[490]1029    const char *tmpPhone[2];
[57]1030    tmpPhone[0]="phoneVoice";
1031    tmpPhone[1]="phoneFacsimile";
[490]1032    const char *orderedFields[12];
[71]1033    orderedFields[0]="providerName";
1034    orderedFields[1]="providerSite";
1035    orderedFields[2]="individualName";
1036    orderedFields[3]="positionName";
1037    orderedFields[4]=tmpPhone[0];
1038    orderedFields[5]=tmpPhone[1];
1039    orderedFields[6]=tmpAddress[0];
1040    orderedFields[7]=tmpAddress[1];
1041    orderedFields[8]=tmpAddress[2];
1042    orderedFields[9]=tmpAddress[3];
1043    orderedFields[10]=tmpAddress[4];
1044    orderedFields[11]=tmpAddress[5];
1045    int oI=0;
1046    for(oI=0;oI<12;oI++)
1047      if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){
1048        if(strcmp(tmp2->name,"keywords")!=0 &&
1049           strcmp(tmp2->name,"serverAddress")!=0 &&
1050           strcmp(tmp2->name,"lang")!=0){
1051          tmp2->name[0]=toupper(tmp2->name[0]);
1052          if(strcmp(tmp2->name,"ProviderName")==0){
[1]1053            nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
[71]1054            xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
[1]1055            xmlAddChild(nc,nc1);
[71]1056          }
1057          else{
1058            if(strcmp(tmp2->name,"ProviderSite")==0){
[1]1059              nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
[71]1060              xmlNewNsProp(nc1,ns_xlink,BAD_CAST "href",BAD_CAST tmp2->value);
1061              xmlAddChild(nc,nc1);
[1]1062            } 
[71]1063            else 
1064              if(strcmp(tmp2->name,"IndividualName")==0 || 
1065                 strcmp(tmp2->name,"PositionName")==0){
1066                nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
1067                xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
1068                xmlAddChild(nc3,nc1);
1069              } 
[1]1070              else 
[71]1071                if(strncmp(tmp2->name,"Phone",5)==0){
[57]1072                  int j;
[71]1073                  for(j=0;j<2;j++)
1074                    if(strcasecmp(tmp2->name,tmpPhone[j])==0){
[490]1075                      char *tmp4=tmp2->name;
1076                      nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+5);
[57]1077                      xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
[71]1078                      xmlAddChild(nc5,nc1);
[57]1079                    }
[1]1080                }
[71]1081                else 
1082                  if(strncmp(tmp2->name,"Address",7)==0){
1083                    int j;
1084                    for(j=0;j<6;j++)
1085                      if(strcasecmp(tmp2->name,tmpAddress[j])==0){
[490]1086                        char *tmp4=tmp2->name;
1087                        nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+7);
[71]1088                        xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
1089                        xmlAddChild(nc6,nc1);
1090                      }
1091                  }
1092          }
[1]1093        }
[71]1094        else
1095          if(strcmp(tmp2->name,"keywords")==0){
1096            nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords");
1097            char *toto=tmp2->value;
1098            char buff[256];
1099            int i=0;
1100            int j=0;
1101            while(toto[i]){
1102              if(toto[i]!=',' && toto[i]!=0){
1103                buff[j]=toto[i];
1104                buff[j+1]=0;
1105                j++;
1106              }
1107              else{
1108                nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
1109                xmlAddChild(nc2,xmlNewText(BAD_CAST buff));           
1110                xmlAddChild(nc1,nc2);
1111                j=0;
1112              }
1113              i++;
[1]1114            }
[71]1115            if(strlen(buff)>0){
[1]1116              nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
1117              xmlAddChild(nc2,xmlNewText(BAD_CAST buff));             
1118              xmlAddChild(nc1,nc2);
1119            }
[71]1120            xmlAddChild(nc,nc1);
[1]1121          }
[71]1122        tmp2=tmp2->next;
1123      }
[1]1124  }
1125  else{
1126    fprintf(stderr,"TMP4 NOT FOUND !!");
1127  }
1128  xmlAddChild(nc4,nc5);
1129  xmlAddChild(nc4,nc6);
1130  xmlAddChild(nc3,nc4);
1131  xmlAddChild(nc,nc3);
1132  xmlAddChild(n,nc);
1133
1134
1135  nc = xmlNewNode(ns_ows, BAD_CAST "OperationsMetadata");
1136  char *tmp2[3];
[9]1137  tmp2[0]=strdup("GetCapabilities");
1138  tmp2[1]=strdup("DescribeProcess");
1139  tmp2[2]=strdup("Execute");
[1]1140  int j=0;
1141
1142  if(toto1!=NULL){
1143    map* tmp=getMap(toto1->content,"serverAddress");
1144    if(tmp!=NULL){
1145      SERVICE_URL = strdup(tmp->value);
1146    }
1147    else
[576]1148      SERVICE_URL = strdup("not_defined");
[1]1149  }
1150  else
[576]1151    SERVICE_URL = strdup("not_defined");
[1]1152
1153  for(j=0;j<3;j++){
1154    nc1 = xmlNewNode(ns_ows, BAD_CAST "Operation");
1155    xmlNewProp(nc1,BAD_CAST "name",BAD_CAST tmp2[j]);
1156    nc2 = xmlNewNode(ns_ows, BAD_CAST "DCP");
1157    nc3 = xmlNewNode(ns_ows, BAD_CAST "HTTP");
1158    nc4 = xmlNewNode(ns_ows, BAD_CAST "Get");
[576]1159    sprintf(tmp,"%s",SERVICE_URL);
[9]1160    xmlNewNsProp(nc4,ns_xlink,BAD_CAST "href",BAD_CAST tmp);
[1]1161    xmlAddChild(nc3,nc4);
[576]1162    nc4 = xmlNewNode(ns_ows, BAD_CAST "Post");
1163    xmlNewNsProp(nc4,ns_xlink,BAD_CAST "href",BAD_CAST tmp);
1164    xmlAddChild(nc3,nc4);
[1]1165    xmlAddChild(nc2,nc3);
1166    xmlAddChild(nc1,nc2);   
1167    xmlAddChild(nc,nc1);   
1168  }
[9]1169  for(j=2;j>=0;j--)
1170    free(tmp2[j]);
[1]1171  xmlAddChild(n,nc);
1172
1173  nc = xmlNewNode(ns, BAD_CAST "ProcessOfferings");
1174  xmlAddChild(n,nc);
1175
1176  nc1 = xmlNewNode(ns, BAD_CAST "Languages");
1177  nc2 = xmlNewNode(ns, BAD_CAST "Default");
1178  nc3 = xmlNewNode(ns, BAD_CAST "Supported");
1179 
1180  toto1=getMaps(m,"main");
1181  if(toto1!=NULL){
1182    map* tmp1=getMap(toto1->content,"lang");
1183    char *toto=tmp1->value;
1184    char buff[256];
1185    int i=0;
1186    int j=0;
1187    int dcount=0;
1188    while(toto[i]){
1189      if(toto[i]!=',' && toto[i]!=0){
1190        buff[j]=toto[i];
1191        buff[j+1]=0;
1192        j++;
1193      }
1194      else{
1195        nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
1196        xmlAddChild(nc4,xmlNewText(BAD_CAST buff));
1197        if(dcount==0){
1198          xmlAddChild(nc2,nc4);
1199          xmlAddChild(nc1,nc2);
1200          dcount++;
1201        }
1202        nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
1203        xmlAddChild(nc4,xmlNewText(BAD_CAST buff));
1204        xmlAddChild(nc3,nc4);
1205        j=0;
1206        buff[j]=0;
1207      }
1208      i++;
1209    }
1210    if(strlen(buff)>0){
1211      nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
1212      xmlAddChild(nc4,xmlNewText(BAD_CAST buff));             
1213      xmlAddChild(nc3,nc4);
1214    }
1215  }
1216  xmlAddChild(nc1,nc3);
1217  xmlAddChild(n,nc1);
1218 
[9]1219  free(SERVICE_URL);
[1]1220  return nc;
1221}
1222
[579]1223/**
1224 * Add prefix to the service name.
1225 *
1226 * @param conf the conf maps containing the main.cfg settings
1227 * @param level the map containing the level information
1228 * @param serv the service structure created from the zcfg file
1229 */
[469]1230void addPrefix(maps* conf,map* level,service* serv){
1231  if(level!=NULL){
1232    char key[25];
1233    char* prefix=NULL;
1234    int clevel=atoi(level->value);
1235    int cl=0;
1236    for(cl=0;cl<clevel;cl++){
1237      sprintf(key,"sprefix_%d",cl);
1238      map* tmp2=getMapFromMaps(conf,"lenv",key);
1239      if(tmp2!=NULL){
1240        if(prefix==NULL)
1241          prefix=zStrdup(tmp2->value);
1242        else{
1243          int plen=strlen(prefix);
1244          prefix=(char*)realloc(prefix,(plen+strlen(tmp2->value)+2)*sizeof(char));
1245          memcpy(prefix+plen,tmp2->value,strlen(tmp2->value)*sizeof(char));
1246          prefix[plen+strlen(tmp2->value)]=0;
1247        }
1248      }
1249    }
1250    if(prefix!=NULL){
1251      char* tmp0=strdup(serv->name);
1252      free(serv->name);
1253      serv->name=(char*)malloc((strlen(prefix)+strlen(tmp0)+1)*sizeof(char));
1254      sprintf(serv->name,"%s%s",prefix,tmp0);
1255      free(tmp0);
1256      free(prefix);
1257      prefix=NULL;
1258    }
1259  }
1260}
1261
[579]1262/**
1263 * Generate a wps:Process node for a servie and add it to a given node.
1264 *
1265 * @param m the conf maps containing the main.cfg settings
1266 * @param nc the XML node to add the Process node
1267 * @param serv the service structure created from the zcfg file
1268 * @return the generated wps:ProcessOfferings xmlNodePtr
1269 */
[1]1270void printGetCapabilitiesForProcess(maps* m,xmlNodePtr nc,service* serv){
[9]1271  xmlNsPtr ns,ns_ows,ns_xlink;
[490]1272  xmlNodePtr n=NULL,nc1,nc2;
[9]1273  /**
1274   * Initialize or get existing namspaces
1275   */
1276  int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");
1277  ns=usedNs[wpsId];
1278  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
1279  ns_ows=usedNs[owsId];
1280  int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
1281  ns_xlink=usedNs[xlinkId];
[1]1282
1283  map* tmp1;
1284  if(serv->content!=NULL){
1285    nc1 = xmlNewNode(ns, BAD_CAST "Process");
1286    tmp1=getMap(serv->content,"processVersion");
1287    if(tmp1!=NULL)
[9]1288      xmlNewNsProp(nc1,ns,BAD_CAST "processVersion",BAD_CAST tmp1->value);
[469]1289    map* tmp3=getMapFromMaps(m,"lenv","level");
1290    addPrefix(m,tmp3,serv);
[1]1291    printDescription(nc1,ns_ows,serv->name,serv->content);
1292    tmp1=serv->metadata;
1293    while(tmp1!=NULL){
1294      nc2 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
[9]1295      xmlNewNsProp(nc2,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
[1]1296      xmlAddChild(nc1,nc2);
1297      tmp1=tmp1->next;
1298    }
1299    xmlAddChild(nc,nc1);
1300  }
1301}
1302
[579]1303/**
1304 * Generate a ProcessDescription node for a servie and add it to a given node.
1305 *
1306 * @param m the conf maps containing the main.cfg settings
1307 * @param nc the XML node to add the Process node
1308 * @param serv the servive structure created from the zcfg file
1309 * @return the generated wps:ProcessOfferings xmlNodePtr
1310 */
[469]1311void printDescribeProcessForProcess(maps* m,xmlNodePtr nc,service* serv){
[490]1312  xmlNsPtr ns,ns_ows,ns_xlink;
1313  xmlNodePtr n,nc1;
[1]1314
1315  n=nc;
1316 
[9]1317  int wpsId=zooXmlAddNs(NULL,"http://schemas.opengis.net/wps/1.0.0","wps");
1318  ns=usedNs[wpsId];
1319  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
1320  ns_ows=usedNs[owsId];
1321  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
1322  ns_xlink=usedNs[xlinkId];
[1]1323
1324  nc = xmlNewNode(NULL, BAD_CAST "ProcessDescription");
[490]1325  const char *tmp4[3];
[1]1326  tmp4[0]="processVersion";
1327  tmp4[1]="storeSupported";
1328  tmp4[2]="statusSupported";
1329  int j=0;
1330  map* tmp1=NULL;
1331  for(j=0;j<3;j++){
[9]1332    tmp1=getMap(serv->content,tmp4[j]);
[1]1333    if(tmp1!=NULL){
1334      if(j==0)
[9]1335        xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp1->value);     
[1]1336      else
1337        xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST tmp1->value);     
1338    }
1339    else{
1340      if(j>0)
1341        xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST "false");     
1342    }
1343  }
1344 
[469]1345  tmp1=getMapFromMaps(m,"lenv","level");
1346  addPrefix(m,tmp1,serv);
[9]1347  printDescription(nc,ns_ows,serv->name,serv->content);
[1]1348
[9]1349  tmp1=serv->metadata;
[1]1350  while(tmp1!=NULL){
1351    nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
[9]1352    xmlNewNsProp(nc1,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
[1]1353    xmlAddChild(nc,nc1);
1354    tmp1=tmp1->next;
1355  }
1356
[9]1357  tmp1=getMap(serv->content,"Profile");
[1]1358  if(tmp1!=NULL){
1359    nc1 = xmlNewNode(ns, BAD_CAST "Profile");
1360    xmlAddChild(nc1,xmlNewText(BAD_CAST tmp1->value));
1361    xmlAddChild(nc,nc1);
1362  }
1363
[471]1364  if(serv->inputs!=NULL){
1365    nc1 = xmlNewNode(NULL, BAD_CAST "DataInputs");
1366    elements* e=serv->inputs;
[490]1367    printFullDescription(1,e,"Input",ns_ows,nc1);
[471]1368    xmlAddChild(nc,nc1);
1369  }
[1]1370
[76]1371  nc1 = xmlNewNode(NULL, BAD_CAST "ProcessOutputs");
[471]1372  elements* e=serv->outputs;
[490]1373  printFullDescription(0,e,"Output",ns_ows,nc1);
[76]1374  xmlAddChild(nc,nc1);
[1]1375
[76]1376  xmlAddChild(n,nc);
[1]1377
[76]1378}
[1]1379
[579]1380/**
1381 * Generate the required XML tree for the detailled metadata informations of
1382 * inputs or outputs
1383 *
1384 * @param in 1 in case of inputs, 0 for outputs
1385 * @param elem the elements structure containing the metadata informations
1386 * @param type the name ("Input" or "Output") of the XML node to create
1387 * @param ns_ows the ows XML namespace
1388 * @param nc1 the XML node to use to add the created tree
1389 */
[490]1390void printFullDescription(int in,elements *elem,const char* type,xmlNsPtr ns_ows,xmlNodePtr nc1){
1391  const char *orderedFields[13];
[76]1392  orderedFields[0]="mimeType";
1393  orderedFields[1]="encoding";
1394  orderedFields[2]="schema";
1395  orderedFields[3]="dataType";
1396  orderedFields[4]="uom";
1397  orderedFields[5]="CRS";
1398  orderedFields[6]="value";
[459]1399  orderedFields[7]="AllowedValues";
[465]1400  orderedFields[8]="range";
1401  orderedFields[9]="rangeMin";
1402  orderedFields[10]="rangeMax";
1403  orderedFields[11]="rangeClosure";
1404  orderedFields[12]="rangeSpace";
[76]1405
[471]1406  xmlNodePtr nc2,nc3,nc4,nc5,nc6,nc7,nc8,nc9;
[76]1407  elements* e=elem;
[471]1408
[76]1409  map* tmp1=NULL;
[1]1410  while(e!=NULL){
[76]1411    int default1=0;
1412    int isAnyValue=1;
1413    nc2 = xmlNewNode(NULL, BAD_CAST type);
[471]1414    if(strncmp(type,"Input",5)==0){
1415      tmp1=getMap(e->content,"minOccurs");
1416      if(tmp1!=NULL){
1417        xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
1418      }else
1419        xmlNewProp(nc2,BAD_CAST "minOccurs",BAD_CAST "0");
1420      tmp1=getMap(e->content,"maxOccurs");
1421      if(tmp1!=NULL){
1422        if(strcasecmp(tmp1->value,"unbounded")!=0)
1423          xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
1424        else
1425          xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1000");
1426      }else
1427        xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1");
[485]1428      if((tmp1=getMap(e->content,"maximumMegabytes"))!=NULL){
1429        xmlNewProp(nc2,BAD_CAST "maximumMegabytes",BAD_CAST tmp1->value);
1430      }
[1]1431    }
1432
1433    printDescription(nc2,ns_ows,e->name,e->content);
1434
[471]1435    /**
1436     * Build the (Literal/Complex/BoundingBox)Data node
1437     */
[76]1438    if(strncmp(type,"Output",6)==0){
1439      if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0)
1440        nc3 = xmlNewNode(NULL, BAD_CAST "LiteralOutput");
1441      else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
[1]1442        nc3 = xmlNewNode(NULL, BAD_CAST "ComplexOutput");
[76]1443      else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
1444        nc3 = xmlNewNode(NULL, BAD_CAST "BoundingBoxOutput");
[1]1445      else
1446        nc3 = xmlNewNode(NULL, BAD_CAST e->format);
[76]1447    }else{
[79]1448      if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0){
[76]1449        nc3 = xmlNewNode(NULL, BAD_CAST "LiteralData");
[79]1450      }
[76]1451      else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
1452        nc3 = xmlNewNode(NULL, BAD_CAST "ComplexData");
1453      else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
1454        nc3 = xmlNewNode(NULL, BAD_CAST "BoundingBoxData");
1455      else
1456        nc3 = xmlNewNode(NULL, BAD_CAST e->format);
1457    }
[471]1458
[465]1459    iotype* _tmp0=NULL;
[1]1460    iotype* _tmp=e->defaults;
1461    int datatype=0;
[79]1462    bool hasUOM=false;
[471]1463    bool hasUOM1=false;
[1]1464    if(_tmp!=NULL){
[79]1465      if(strcmp(e->format,"LiteralOutput")==0 ||
1466         strcmp(e->format,"LiteralData")==0){
[1]1467        datatype=1;
1468        nc4 = xmlNewNode(NULL, BAD_CAST "UOMs");
1469        nc5 = xmlNewNode(NULL, BAD_CAST "Default");
[79]1470      }
1471      else if(strcmp(e->format,"BoundingBoxOutput")==0 ||
1472              strcmp(e->format,"BoundingBoxData")==0){
1473        datatype=2;
1474        nc5 = xmlNewNode(NULL, BAD_CAST "Default");
1475      }
1476      else{
1477        nc4 = xmlNewNode(NULL, BAD_CAST "Default");
1478        nc5 = xmlNewNode(NULL, BAD_CAST "Format");
1479      }
1480     
1481      tmp1=_tmp->content;
[459]1482
[471]1483      if((tmp1=getMap(_tmp->content,"DataType"))!=NULL){
1484        nc8 = xmlNewNode(ns_ows, BAD_CAST "DataType");
1485        xmlAddChild(nc8,xmlNewText(BAD_CAST tmp1->value));
1486        char tmp[1024];
1487        sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
1488        xmlNewNsProp(nc8,ns_ows,BAD_CAST "reference",BAD_CAST tmp);
1489        xmlAddChild(nc3,nc8);
1490        datatype=1;
1491      }
1492     
1493      if(strncmp(type,"Input",5)==0){
[465]1494
[471]1495        if((tmp1=getMap(_tmp->content,"AllowedValues"))!=NULL){
1496          nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
1497          char *token,*saveptr1;
1498          token=strtok_r(tmp1->value,",",&saveptr1);
1499          while(token!=NULL){
1500            nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
1501            char *tmps=strdup(token);
1502            tmps[strlen(tmps)]=0;
1503            xmlAddChild(nc7,xmlNewText(BAD_CAST tmps));
1504            free(tmps);
1505            xmlAddChild(nc6,nc7);
1506            token=strtok_r(NULL,",",&saveptr1);
1507          }
1508          if(getMap(_tmp->content,"range")!=NULL ||
1509             getMap(_tmp->content,"rangeMin")!=NULL ||
1510             getMap(_tmp->content,"rangeMax")!=NULL ||
1511             getMap(_tmp->content,"rangeClosure")!=NULL )
1512            goto doRange;
1513          xmlAddChild(nc3,nc6);
1514          isAnyValue=-1;
1515        }
[465]1516
[471]1517        tmp1=getMap(_tmp->content,"range");
1518        if(tmp1==NULL)
1519          tmp1=getMap(_tmp->content,"rangeMin");
1520        if(tmp1==NULL)
1521          tmp1=getMap(_tmp->content,"rangeMax");
1522       
1523        if(tmp1!=NULL && isAnyValue==1){
1524          nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
1525        doRange:
1526         
1527          /**
1528           * Range: Table 46 OGC Web Services Common Standard
1529           */
1530          nc8 = xmlNewNode(ns_ows, BAD_CAST "Range");
1531         
1532          map* tmp0=getMap(tmp1,"range");
1533          if(tmp0!=NULL){
1534            char* pToken;
1535            char* orig=zStrdup(tmp0->value);
1536            /**
1537             * RangeClosure: Table 47 OGC Web Services Common Standard
1538             */
[490]1539            const char *tmp="closed";
[471]1540            if(orig[0]=='[' && orig[strlen(orig)-1]=='[')
1541              tmp="closed-open";
1542            else
1543              if(orig[0]==']' && orig[strlen(orig)-1]==']')
1544                tmp="open-closed";
1545              else
1546                if(orig[0]==']' && orig[strlen(orig)-1]=='[')
1547                  tmp="open";
1548            xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
1549            pToken=strtok(orig,",");
1550            int nci0=0;
1551            while(pToken!=NULL){
1552              char *tmpStr=(char*) malloc((strlen(pToken))*sizeof(char));
1553              if(nci0==0){
1554                nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
[507]1555                strncpy( tmpStr, pToken+1, strlen(pToken)-1 );
1556                tmpStr[strlen(pToken)-1] = '\0';
1557              }else{
[471]1558                nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
[507]1559                const char* bkt;
1560                if ( ( bkt = strchr(pToken, '[') ) != NULL || ( bkt = strchr(pToken, ']') ) != NULL ){
1561                    strncpy( tmpStr, pToken, bkt - pToken );
1562                    tmpStr[bkt - pToken] = '\0';
1563                  }
[459]1564              }
[471]1565              xmlAddChild(nc7,xmlNewText(BAD_CAST tmpStr));
1566              free(tmpStr);
1567              xmlAddChild(nc8,nc7);
1568              nci0++;
1569              pToken = strtok(NULL,",");
1570            }               
1571            if(getMap(tmp1,"rangeSpacing")==NULL){
1572              nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
1573              xmlAddChild(nc7,xmlNewText(BAD_CAST "1"));
1574              xmlAddChild(nc8,nc7);
[79]1575            }
[471]1576            free(orig);
1577          }else{
1578           
1579            tmp0=getMap(tmp1,"rangeMin");
1580            if(tmp0!=NULL){
1581              nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
1582              xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1583              xmlAddChild(nc8,nc7);
1584            }else{
1585              nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
1586              xmlAddChild(nc8,nc7);
[79]1587            }
[471]1588            tmp0=getMap(tmp1,"rangeMax");
1589            if(tmp0!=NULL){
1590              nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
1591              xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1592              xmlAddChild(nc8,nc7);
1593            }else{
1594              nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
1595              xmlAddChild(nc8,nc7);
1596            }
1597            tmp0=getMap(tmp1,"rangeSpacing");
1598            if(tmp0!=NULL){
1599              nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
1600              xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1601              xmlAddChild(nc8,nc7);
1602            }
1603            tmp0=getMap(tmp1,"rangeClosure");
1604            if(tmp0!=NULL){
[490]1605              const char *tmp="closed";
[471]1606              if(strcasecmp(tmp0->value,"co")==0)
1607                tmp="closed-open";
1608              else
1609                if(strcasecmp(tmp0->value,"oc")==0)
1610                  tmp="open-closed";
1611                else
1612                  if(strcasecmp(tmp0->value,"o")==0)
1613                    tmp="open";
1614              xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
1615            }else
1616              xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST "closed");
1617          }
1618          if(_tmp0==NULL){
1619            xmlAddChild(nc6,nc8);
1620            _tmp0=e->supported;
[507]1621            if(_tmp0!=NULL &&
1622               (getMap(_tmp0->content,"range")!=NULL ||
1623                getMap(_tmp0->content,"rangeMin")!=NULL ||
1624                getMap(_tmp0->content,"rangeMax")!=NULL ||
1625                getMap(_tmp0->content,"rangeClosure")!=NULL )){
[476]1626              tmp1=_tmp0->content;
1627              goto doRange;
1628            }
[79]1629          }else{
[471]1630            _tmp0=_tmp0->next;
1631            if(_tmp0!=NULL){
1632              xmlAddChild(nc6,nc8);
[476]1633              if(getMap(_tmp0->content,"range")!=NULL ||
1634                 getMap(_tmp0->content,"rangeMin")!=NULL ||
1635                 getMap(_tmp0->content,"rangeMax")!=NULL ||
1636                 getMap(_tmp0->content,"rangeClosure")!=NULL ){
1637                tmp1=_tmp0->content;
1638                goto doRange;
1639              }
[79]1640            }
1641          }
[471]1642          xmlAddChild(nc6,nc8);
1643          xmlAddChild(nc3,nc6);
1644          isAnyValue=-1;
[1]1645        }
[471]1646       
1647      }
1648   
1649     
1650    int oI=0;
1651    for(oI=0;oI<13;oI++)
1652      if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
1653#ifdef DEBUG
1654        printf("DATATYPE DEFAULT ? %s\n",tmp1->name);
1655#endif
1656        if(strcmp(tmp1->name,"asReference")!=0 &&
1657           strncasecmp(tmp1->name,"DataType",8)!=0 &&
1658           strcasecmp(tmp1->name,"extension")!=0 &&
1659           strcasecmp(tmp1->name,"value")!=0 &&
1660           strcasecmp(tmp1->name,"AllowedValues")!=0 &&
1661           strncasecmp(tmp1->name,"range",5)!=0){
1662          if(datatype!=1){
1663            char *tmp2=zCapitalize1(tmp1->name);
1664            nc9 = xmlNewNode(NULL, BAD_CAST tmp2);
1665            free(tmp2);
1666          }
1667          else{
1668            char *tmp2=zCapitalize(tmp1->name);
1669            nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);
1670            free(tmp2);
1671          }
1672          xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));
1673          xmlAddChild(nc5,nc9);
1674          if(strcasecmp(tmp1->name,"uom")==0)
1675            hasUOM1=true;
1676          hasUOM=true;
1677        }else 
1678         
1679          tmp1=tmp1->next;
1680      }
1681   
1682   
1683      if(datatype!=2){
1684        if(hasUOM==true){
1685          xmlAddChild(nc4,nc5);
1686          xmlAddChild(nc3,nc4);
1687        }else{
1688          if(hasUOM1==false){
1689            xmlFreeNode(nc5);
1690            if(datatype==1)
1691              xmlFreeNode(nc4);
1692          }
[459]1693        }
[471]1694      }else{
1695        xmlAddChild(nc3,nc5);
[459]1696      }
[465]1697     
[471]1698      if(datatype!=1 && default1<0){
1699        xmlFreeNode(nc5);
1700        if(datatype!=2)
1701          xmlFreeNode(nc4);
1702      }
1703
[465]1704      map* metadata=e->metadata;
[490]1705      xmlNodePtr n=NULL;
[465]1706      int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
1707      xmlNsPtr ns_xlink=usedNs[xlinkId];
1708
1709      while(metadata!=NULL){
[471]1710        nc6=xmlNewNode(ns_ows, BAD_CAST "Metadata");
[465]1711        xmlNewNsProp(nc6,ns_xlink,BAD_CAST metadata->name,BAD_CAST metadata->value);
1712        xmlAddChild(nc2,nc6);
1713        metadata=metadata->next;
1714      }
[471]1715
[1]1716    }
[280]1717
[1]1718    _tmp=e->supported;
[471]1719    if(_tmp==NULL && datatype!=1)
[280]1720      _tmp=e->defaults;
1721
[71]1722    int hasSupported=-1;
[471]1723
[1]1724    while(_tmp!=NULL){
[71]1725      if(hasSupported<0){
1726        if(datatype==0){
1727          nc4 = xmlNewNode(NULL, BAD_CAST "Supported");
1728          nc5 = xmlNewNode(NULL, BAD_CAST "Format");
1729        }
1730        else
1731          nc5 = xmlNewNode(NULL, BAD_CAST "Supported");
1732        hasSupported=0;
1733      }else
[76]1734        if(datatype==0)
1735          nc5 = xmlNewNode(NULL, BAD_CAST "Format");
[1]1736      tmp1=_tmp->content;
[71]1737      int oI=0;
[76]1738      for(oI=0;oI<6;oI++)
[71]1739        if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
[1]1740#ifdef DEBUG
[71]1741          printf("DATATYPE SUPPORTED ? %s\n",tmp1->name);
[1]1742#endif
[71]1743          if(strcmp(tmp1->name,"asReference")!=0 && 
[471]1744             strcmp(tmp1->name,"value")!=0 && 
[71]1745             strcmp(tmp1->name,"DataType")!=0 &&
1746             strcasecmp(tmp1->name,"extension")!=0){
[76]1747            if(datatype!=1){
[71]1748              char *tmp2=zCapitalize1(tmp1->name);
1749              nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
1750              free(tmp2);
1751            }
1752            else{
1753              char *tmp2=zCapitalize(tmp1->name);
1754              nc6 = xmlNewNode(ns_ows, BAD_CAST tmp2);
1755              free(tmp2);
1756            }
[76]1757            if(datatype==2){
1758              char *tmpv,*tmps;
1759              tmps=strtok_r(tmp1->value,",",&tmpv);
1760              while(tmps){
1761                xmlAddChild(nc6,xmlNewText(BAD_CAST tmps));
1762                tmps=strtok_r(NULL,",",&tmpv);
1763                if(tmps){
1764                  char *tmp2=zCapitalize1(tmp1->name);
1765                  nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
1766                  free(tmp2);
1767                }
1768              }
1769            }
1770            else{
1771              xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
1772            }
[471]1773            xmlAddChild(nc5,nc6);
[9]1774          }
[71]1775          tmp1=tmp1->next;
[1]1776        }
[71]1777      if(hasSupported<=0){
[471]1778        if(datatype==0){
[71]1779          xmlAddChild(nc4,nc5);
1780          xmlAddChild(nc3,nc4);
[471]1781        }else{
1782          if(datatype!=1)
1783            xmlAddChild(nc3,nc5);
1784        }
[71]1785        hasSupported=1;
[1]1786      }
[71]1787      else
[471]1788        if(datatype==0){
[76]1789          xmlAddChild(nc4,nc5);
[471]1790          xmlAddChild(nc3,nc4);
[76]1791        }
1792        else
[471]1793          if(datatype!=1)
1794            xmlAddChild(nc3,nc5);
1795
[76]1796      _tmp=_tmp->next;
[1]1797    }
[471]1798
1799    if(hasSupported==0){
1800      if(datatype==0)
1801        xmlFreeNode(nc4);
1802      xmlFreeNode(nc5);
1803    }
1804
1805    _tmp=e->defaults;
1806    if(datatype==1 && hasUOM1==true){
1807      xmlAddChild(nc4,nc5);
1808      xmlAddChild(nc3,nc4);
1809    }
1810
[490]1811    if(in>0 && datatype==1 &&
[471]1812       getMap(_tmp->content,"AllowedValues")==NULL &&
1813       getMap(_tmp->content,"range")==NULL &&
1814       getMap(_tmp->content,"rangeMin")==NULL &&
1815       getMap(_tmp->content,"rangeMax")==NULL &&
1816       getMap(_tmp->content,"rangeClosure")==NULL ){
1817      tmp1=getMap(_tmp->content,"dataType");
[542]1818      if(tmp1!=NULL && strcasecmp(tmp1->value,"boolean")==0){
1819        nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
1820        nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
1821        xmlAddChild(nc7,xmlNewText(BAD_CAST "true"));
1822        xmlAddChild(nc6,nc7);
1823        nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
1824        xmlAddChild(nc7,xmlNewText(BAD_CAST "false"));
1825        xmlAddChild(nc6,nc7);
1826        xmlAddChild(nc3,nc6);
1827      }
1828      else
1829        xmlAddChild(nc3,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
[471]1830    }
1831   
1832    if((tmp1=getMap(_tmp->content,"value"))!=NULL){
1833      nc7 = xmlNewNode(NULL, BAD_CAST "DefaultValue");
1834      xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value));
1835      xmlAddChild(nc3,nc7);
1836    }
1837   
[1]1838    xmlAddChild(nc2,nc3);
1839   
1840    xmlAddChild(nc1,nc2);
1841   
1842    e=e->next;
1843  }
1844}
1845
[579]1846/**
1847 * Generate a wps:Execute XML document.
1848 *
1849 * @param m the conf maps containing the main.cfg settings
1850 * @param request the map representing the HTTP request
1851 * @param pid the process identifier linked to a service
1852 * @param serv the serv structure created from the zcfg file
1853 * @param service the service name
1854 * @param status the status returned by the service
1855 * @param inputs the inputs provided
1856 * @param outputs the outputs generated by the service
1857 */
[114]1858void printProcessResponse(maps* m,map* request, int pid,service* serv,const char* service,int status,maps* inputs,maps* outputs){
[576]1859  xmlNsPtr ns,ns_ows,ns_xlink;
[490]1860  xmlNodePtr nr,n,nc,nc1=NULL,nc3;
[9]1861  xmlDocPtr doc;
1862  time_t time1; 
1863  time(&time1);
[280]1864  nr=NULL;
[9]1865  doc = xmlNewDoc(BAD_CAST "1.0");
[576]1866  n = printWPSHeader(doc,m,"Execute","ExecuteResponse");
[9]1867  int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");
1868  ns=usedNs[wpsId];
[576]1869  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
[9]1870  ns_ows=usedNs[owsId];
[576]1871  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
[9]1872  ns_xlink=usedNs[xlinkId];
[34]1873
[9]1874  char tmp[256];
[26]1875  char url[1024];
[72]1876  char stored_path[1024];
[9]1877  memset(tmp,0,256);
[72]1878  memset(url,0,1024);
1879  memset(stored_path,0,1024);
[9]1880  maps* tmp_maps=getMaps(m,"main");
1881  if(tmp_maps!=NULL){
[26]1882    map* tmpm1=getMap(tmp_maps->content,"serverAddress");
1883    /**
1884     * Check if the ZOO Service GetStatus is available in the local directory.
1885     * If yes, then it uses a reference to an URL which the client can access
1886     * to get information on the status of a running Service (using the
1887     * percentCompleted attribute).
1888     * Else fallback to the initial method using the xml file to write in ...
1889     */
1890    char ntmp[1024];
1891#ifndef WIN32
1892    getcwd(ntmp,1024);
1893#else
1894    _getcwd(ntmp,1024);
1895#endif
1896    struct stat myFileInfo;
1897    int statRes;
1898    char file_path[1024];
1899    sprintf(file_path,"%s/GetStatus.zcfg",ntmp);
1900    statRes=stat(file_path,&myFileInfo);
1901    if(statRes==0){
1902      char currentSid[128];
1903      map* tmpm=getMap(tmp_maps->content,"rewriteUrl");
1904      map *tmp_lenv=NULL;
[514]1905      tmp_lenv=getMapFromMaps(m,"lenv","usid");
[26]1906      if(tmp_lenv==NULL)
1907        sprintf(currentSid,"%i",pid);
1908      else
1909        sprintf(currentSid,"%s",tmp_lenv->value);
1910      if(tmpm==NULL || strcasecmp(tmpm->value,"false")==0){
[280]1911        sprintf(url,"%s?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
[26]1912      }else{
1913        if(strlen(tmpm->value)>0)
1914          if(strcasecmp(tmpm->value,"true")!=0)
1915            sprintf(url,"%s/%s/GetStatus/%s",tmpm1->value,tmpm->value,currentSid);
1916          else
1917            sprintf(url,"%s/GetStatus/%s",tmpm1->value,currentSid);
1918        else
[41]1919          sprintf(url,"%s/?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
[26]1920      }
1921    }else{
[514]1922      int lpid;
1923      map* tmpm2=getMapFromMaps(m,"lenv","usid");
1924      lpid=atoi(tmpm2->value);
1925      tmpm2=getMap(tmp_maps->content,"tmpUrl");
[26]1926      if(tmpm1!=NULL && tmpm2!=NULL){
[453]1927        if( strncasecmp( tmpm2->value, "http://", 7) == 0 ||
1928            strncasecmp( tmpm2->value, "https://", 8 ) == 0 ){
[514]1929          sprintf(url,"%s/%s_%i.xml",tmpm2->value,service,lpid);
[378]1930        }else
[514]1931          sprintf(url,"%s/%s/%s_%i.xml",tmpm1->value,tmpm2->value,service,lpid);
[26]1932      }
[9]1933    }
[26]1934    if(tmpm1!=NULL)
[280]1935      sprintf(tmp,"%s",tmpm1->value);
[514]1936    int lpid;
1937    tmpm1=getMapFromMaps(m,"lenv","usid");
1938    lpid=atoi(tmpm1->value);
[72]1939    tmpm1=getMapFromMaps(m,"main","TmpPath");
[514]1940    sprintf(stored_path,"%s/%s_%i.xml",tmpm1->value,service,lpid);
[9]1941  }
1942
[72]1943
[364]1944
[9]1945  xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp);
[72]1946  map* test=getMap(request,"storeExecuteResponse");
1947  bool hasStoredExecuteResponse=false;
1948  if(test!=NULL && strcasecmp(test->value,"true")==0){
[9]1949    xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url);
[72]1950    hasStoredExecuteResponse=true;
[9]1951  }
1952
1953  nc = xmlNewNode(ns, BAD_CAST "Process");
1954  map* tmp2=getMap(serv->content,"processVersion");
1955  if(tmp2!=NULL)
1956    xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp2->value);
1957 
[539]1958  map* tmpI=getMapFromMaps(m,"lenv","oIdentifier");
1959  printDescription(nc,ns_ows,tmpI->value,serv->content);
[9]1960
1961  xmlAddChild(n,nc);
1962
1963  nc = xmlNewNode(ns, BAD_CAST "Status");
1964  const struct tm *tm;
1965  size_t len;
1966  time_t now;
1967  char *tmp1;
[26]1968  map *tmpStatus;
[9]1969 
1970  now = time ( NULL );
1971  tm = localtime ( &now );
1972
1973  tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char));
1974
1975  len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
1976
[26]1977  xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
1978
1979  char sMsg[2048];
[9]1980  switch(status){
1981  case SERVICE_SUCCEEDED:
1982    nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded");
[34]1983    sprintf(sMsg,_("Service \"%s\" run successfully."),serv->name);
[26]1984    nc3=xmlNewText(BAD_CAST sMsg);
1985    xmlAddChild(nc1,nc3);
[9]1986    break;
1987  case SERVICE_STARTED:
1988    nc1 = xmlNewNode(ns, BAD_CAST "ProcessStarted");
[26]1989    tmpStatus=getMapFromMaps(m,"lenv","status");
1990    xmlNewProp(nc1,BAD_CAST "percentCompleted",BAD_CAST tmpStatus->value);
[34]1991    sprintf(sMsg,_("ZOO Service \"%s\" is currently running. Please, reload this document to get the up-to-date status of the Service."),serv->name);
[26]1992    nc3=xmlNewText(BAD_CAST sMsg);
1993    xmlAddChild(nc1,nc3);
[9]1994    break;
1995  case SERVICE_ACCEPTED:
1996    nc1 = xmlNewNode(ns, BAD_CAST "ProcessAccepted");
[34]1997    sprintf(sMsg,_("Service \"%s\" was accepted by the ZOO Kernel and it run as a background task. Please consult the statusLocation attribtue providen in this document to get the up-to-date document."),serv->name);
[26]1998    nc3=xmlNewText(BAD_CAST sMsg);
1999    xmlAddChild(nc1,nc3);
[9]2000    break;
2001  case SERVICE_FAILED:
2002    nc1 = xmlNewNode(ns, BAD_CAST "ProcessFailed");
[26]2003    map *errorMap;
2004    map *te;
2005    te=getMapFromMaps(m,"lenv","code");
2006    if(te!=NULL)
2007      errorMap=createMap("code",te->value);
2008    else
2009      errorMap=createMap("code","NoApplicableCode");
2010    te=getMapFromMaps(m,"lenv","message");
2011    if(te!=NULL)
[57]2012      addToMap(errorMap,"text",_ss(te->value));
[26]2013    else
[34]2014      addToMap(errorMap,"text",_("No more information available"));
[26]2015    nc3=createExceptionReportNode(m,errorMap,0);
[59]2016    freeMap(&errorMap);
2017    free(errorMap);
[26]2018    xmlAddChild(nc1,nc3);
[9]2019    break;
2020  default :
[34]2021    printf(_("error code not know : %i\n"),status);
[26]2022    //exit(1);
[9]2023    break;
2024  }
2025  xmlAddChild(nc,nc1);
2026  xmlAddChild(n,nc);
2027  free(tmp1);
2028
2029#ifdef DEBUG
2030  fprintf(stderr,"printProcessResponse 1 161\n");
2031#endif
2032
2033  map* lineage=getMap(request,"lineage");
[87]2034  if(lineage!=NULL && strcasecmp(lineage->value,"true")==0){
[9]2035    nc = xmlNewNode(ns, BAD_CAST "DataInputs");
2036    maps* mcursor=inputs;
[65]2037    elements* scursor=NULL;
[9]2038    while(mcursor!=NULL /*&& scursor!=NULL*/){
[65]2039      scursor=getElements(serv->inputs,mcursor->name);
[76]2040      printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Input");
[9]2041      mcursor=mcursor->next;
2042    }
2043    xmlAddChild(n,nc);
2044   
2045#ifdef DEBUG
2046    fprintf(stderr,"printProcessResponse 1 177\n");
2047#endif
2048
2049    nc = xmlNewNode(ns, BAD_CAST "OutputDefinitions");
2050    mcursor=outputs;
[65]2051    scursor=NULL;
2052    while(mcursor!=NULL){
2053      scursor=getElements(serv->outputs,mcursor->name);
[576]2054      printOutputDefinitions(doc,nc,ns,ns_ows,scursor,mcursor,"Output");
[9]2055      mcursor=mcursor->next;
2056    }
2057    xmlAddChild(n,nc);
2058  }
2059#ifdef DEBUG
2060  fprintf(stderr,"printProcessResponse 1 190\n");
2061#endif
2062
2063  /**
2064   * Display the process output only when requested !
2065   */
2066  if(status==SERVICE_SUCCEEDED){
2067    nc = xmlNewNode(ns, BAD_CAST "ProcessOutputs");
2068    maps* mcursor=outputs;
2069    elements* scursor=serv->outputs;
[379]2070    map* testResponse=getMap(request,"RawDataOutput");
2071    if(testResponse==NULL)
2072      testResponse=getMap(request,"ResponseDocument");
[63]2073    while(mcursor!=NULL){
[379]2074      map* tmp0=getMap(mcursor->content,"inRequest");
[65]2075      scursor=getElements(serv->outputs,mcursor->name);
[280]2076      if(scursor!=NULL){
[403]2077        if(testResponse==NULL || tmp0==NULL)
[379]2078          printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
2079        else
[403]2080          if(tmp0!=NULL && strncmp(tmp0->value,"true",4)==0)
[379]2081            printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
[449]2082      }else
2083        /**
2084         * In case there was no definition found in the ZCFG file but
2085         * present in the service code
2086         */
2087        printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
[9]2088      mcursor=mcursor->next;
2089    }
2090    xmlAddChild(n,nc);
2091  }
[364]2092
[507]2093  if(hasStoredExecuteResponse==true && status!=SERVICE_STARTED){
2094    semid lid=getShmLockId(m,1);
2095    if(lid<0)
[393]2096      return;
[507]2097    else{
2098#ifdef DEBUG
2099      fprintf(stderr,"LOCK %s %d !\n",__FILE__,__LINE__);
2100#endif
2101      lockShm(lid);
2102      /* We need to write the ExecuteResponse Document somewhere */
2103      FILE* output=fopen(stored_path,"w");
2104      if(output==NULL){
2105        /* If the file cannot be created return an ExceptionReport */
2106        char tmpMsg[1024];
2107        sprintf(tmpMsg,_("Unable to create the file : \"%s\" for storing the ExecuteResponse."),stored_path);
[576]2108
2109        errorException(m,tmpMsg,"InternalError",NULL);
[507]2110        xmlFreeDoc(doc);
2111        xmlCleanupParser();
2112        zooXmlCleanupNs();
2113        unlockShm(lid);
2114        return;
2115      }
2116      xmlChar *xmlbuff;
2117      int buffersize;
2118      xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1);
2119      fwrite(xmlbuff,1,xmlStrlen(xmlbuff)*sizeof(char),output);
2120      xmlFree(xmlbuff);
2121      fclose(output);
2122#ifdef DEBUG
2123      fprintf(stderr,"UNLOCK %s %d !\n",__FILE__,__LINE__);
2124#endif
2125      unlockShm(lid);
2126      map* test1=getMap(request,"status");
2127      if(test1==NULL || strcasecmp(test1->value,"true")!=0){
2128        removeShmLock(m,1);
2129      }
[393]2130    }
[72]2131  }
[9]2132  printDocument(m,doc,pid);
2133
2134  xmlCleanupParser();
2135  zooXmlCleanupNs();
2136}
2137
[579]2138/**
2139 * Print a XML document.
2140 *
2141 * @param m the conf maps containing the main.cfg settings
2142 * @param doc the XML document
2143 * @param pid the process identifier linked to a service
2144 */
[9]2145void printDocument(maps* m, xmlDocPtr doc,int pid){
2146  char *encoding=getEncoding(m);
2147  if(pid==getpid()){
[384]2148    printHeaders(m);
[9]2149    printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
2150  }
2151  fflush(stdout);
2152  xmlChar *xmlbuff;
2153  int buffersize;
[1]2154  /*
[9]2155   * Dump the document to a buffer and print it on stdout
[1]2156   * for demonstration purposes.
2157   */
[9]2158  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
[114]2159  printf("%s",xmlbuff);
[216]2160  fflush(stdout);
[1]2161  /*
2162   * Free associated memory.
2163   */
2164  xmlFree(xmlbuff);
[9]2165  xmlFreeDoc(doc);
2166  xmlCleanupParser();
2167  zooXmlCleanupNs();
[1]2168}
2169
[579]2170/**
2171 * Print a XML document.
2172 *
2173 * @param doc the XML document (unused)
2174 * @param nc the XML node to add the output definition
2175 * @param ns_wps the wps XML namespace
2176 * @param ns_ows the ows XML namespace
2177 * @param e the output elements
2178 * @param m the conf maps containing the main.cfg settings
2179 * @param type the type (unused)
2180 */
[576]2181void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,const char* type){
[1]2182  xmlNodePtr nc1;
2183  nc1=xmlNewNode(ns_wps, BAD_CAST type);
2184  map *tmp=NULL; 
2185  if(e!=NULL && e->defaults!=NULL)
2186    tmp=e->defaults->content;
2187  else{
2188    /*
2189    dumpElements(e);
2190    */
2191    return;
2192  }
2193  while(tmp!=NULL){
[9]2194    if(strncasecmp(tmp->name,"MIMETYPE",strlen(tmp->name))==0
2195       || strncasecmp(tmp->name,"ENCODING",strlen(tmp->name))==0
2196       || strncasecmp(tmp->name,"SCHEMA",strlen(tmp->name))==0
2197       || strncasecmp(tmp->name,"UOM",strlen(tmp->name))==0)
[1]2198    xmlNewProp(nc1,BAD_CAST tmp->name,BAD_CAST tmp->value);
2199    tmp=tmp->next;
2200  }
2201  tmp=getMap(e->defaults->content,"asReference");
2202  if(tmp==NULL)
2203    xmlNewProp(nc1,BAD_CAST "asReference",BAD_CAST "false");
2204
2205  tmp=e->content;
2206
2207  printDescription(nc1,ns_ows,m->name,e->content);
2208
2209  xmlAddChild(nc,nc1);
2210
2211}
2212
[579]2213/**
2214 * Generate XML nodes describing inputs or outputs metadata.
2215 *
2216 * @param doc the XML document
2217 * @param nc the XML node to add the definition
2218 * @param ns_wps the wps namespace
2219 * @param ns_ows the ows namespace
2220 * @param ns_xlink the xlink namespace
2221 * @param e the output elements
2222 * @param m the conf maps containing the main.cfg settings
2223 * @param type the type
2224 */
[114]2225void printIOType(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,elements* e,maps* m,const char* type){
[1]2226  xmlNodePtr nc1,nc2,nc3;
2227  nc1=xmlNewNode(ns_wps, BAD_CAST type);
[65]2228  map *tmp=NULL;
2229  if(e!=NULL)
2230    tmp=e->content;
2231  else
2232    tmp=m->content;
[26]2233#ifdef DEBUG
[1]2234  dumpMap(tmp);
2235  dumpElements(e);
[26]2236#endif
[1]2237  nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier");
[65]2238  if(e!=NULL)
2239    nc3=xmlNewText(BAD_CAST e->name);
2240  else
2241    nc3=xmlNewText(BAD_CAST m->name);
[9]2242  xmlAddChild(nc2,nc3);
[1]2243  xmlAddChild(nc1,nc2);
2244  xmlAddChild(nc,nc1);
[65]2245  if(e!=NULL)
2246    tmp=getMap(e->content,"Title");
2247  else
2248    tmp=getMap(m->content,"Title");
2249 
2250  if(tmp!=NULL){
[43]2251    nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
2252    nc3=xmlNewText(BAD_CAST _ss(tmp->value));
2253    xmlAddChild(nc2,nc3); 
2254    xmlAddChild(nc1,nc2);
[65]2255  }
2256
2257  if(e!=NULL)
2258    tmp=getMap(e->content,"Abstract");
2259  else
2260    tmp=getMap(m->content,"Abstract");
2261  if(tmp!=NULL){
2262    nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
2263    nc3=xmlNewText(BAD_CAST _ss(tmp->value));
2264    xmlAddChild(nc2,nc3); 
2265    xmlAddChild(nc1,nc2);
[43]2266    xmlAddChild(nc,nc1);
2267  }
[1]2268
2269  /**
2270   * IO type Reference or full Data ?
2271   */
[26]2272#ifdef DEBUG
[9]2273  fprintf(stderr,"FORMAT %s %s\n",e->format,e->format);
[26]2274#endif
[9]2275  map *tmpMap=getMap(m->content,"Reference");
2276  if(tmpMap==NULL){
2277    nc2=xmlNewNode(ns_wps, BAD_CAST "Data");
[65]2278    if(e!=NULL){
[76]2279      if(strncasecmp(e->format,"LiteralOutput",strlen(e->format))==0)
[65]2280        nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
[9]2281      else
[76]2282        if(strncasecmp(e->format,"ComplexOutput",strlen(e->format))==0)
[65]2283          nc3=xmlNewNode(ns_wps, BAD_CAST "ComplexData");
[76]2284        else if(strncasecmp(e->format,"BoundingBoxOutput",strlen(e->format))==0)
2285          nc3=xmlNewNode(ns_wps, BAD_CAST "BoundingBoxData");
[65]2286        else
2287          nc3=xmlNewNode(ns_wps, BAD_CAST e->format);
2288    }
2289    else{
2290      map* tmpV=getMapFromMaps(m,"format","value");
2291      if(tmpV!=NULL)
2292        nc3=xmlNewNode(ns_wps, BAD_CAST tmpV->value);
2293      else
2294        nc3=xmlNewNode(ns_wps, BAD_CAST "LitteralData");
[76]2295    } 
[9]2296    tmp=m->content;
[297]2297#ifdef USE_MS
2298    map* testMap=getMap(tmp,"requestedMimeType");
2299#endif
[9]2300    while(tmp!=NULL){
[70]2301      if(strcasecmp(tmp->name,"mimeType")==0 ||
2302         strcasecmp(tmp->name,"encoding")==0 ||
2303         strcasecmp(tmp->name,"schema")==0 ||
2304         strcasecmp(tmp->name,"datatype")==0 ||
[490]2305         strcasecmp(tmp->name,"uom")==0){
[297]2306#ifdef USE_MS
[299]2307        if(testMap==NULL || (testMap!=NULL && strncasecmp(testMap->value,"text/xml",8)==0)){
[297]2308#endif
[490]2309          xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
[297]2310#ifdef USE_MS
[299]2311        }
[490]2312        else
2313          if(strcasecmp(tmp->name,"mimeType")==0){
2314            if(testMap!=NULL)
2315              xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST testMap->value);
2316            else 
2317              xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
2318          }
[297]2319#endif
[490]2320      }
[9]2321      tmp=tmp->next;
2322      xmlAddChild(nc2,nc3);
[1]2323    }
[76]2324    if(e!=NULL && e->format!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
2325      map* bb=getMap(m->content,"value");
2326      if(bb!=NULL){
2327        map* tmpRes=parseBoundingBox(bb->value);
2328        printBoundingBox(ns_ows,nc3,tmpRes);
2329        freeMap(&tmpRes);
2330        free(tmpRes);
[9]2331      }
[76]2332    }else{
2333      if(e!=NULL)
2334        tmp=getMap(e->defaults->content,"mimeType");
2335      else
2336        tmp=NULL;
[297]2337#ifdef USE_MS
2338      /**
2339       * In case of OGC WebServices output use, as the data was requested
2340       * with asReference=false we have to download the resulting OWS request
2341       * stored in the Reference map value.
2342       */
2343      map* testMap=getMap(m->content,"requestedMimeType");
2344      if(testMap!=NULL){
2345        HINTERNET hInternet;
[492]2346        char* tmpValue;
2347        size_t dwRead;
[297]2348        hInternet=InternetOpen(
2349#ifndef WIN32
2350                               (LPCTSTR)
2351#endif
2352                               "ZooWPSClient\0",
2353                               INTERNET_OPEN_TYPE_PRECONFIG,
2354                               NULL,NULL, 0);
2355        testMap=getMap(m->content,"Reference");
[492]2356        loadRemoteFile(&m,&m->content,&hInternet,testMap->value);
2357        processDownloads(&hInternet);
2358        tmpValue=(char*)malloc((hInternet.ihandle[0].nDataLen+1)*sizeof(char));
2359        InternetReadFile(hInternet.ihandle[0],(LPVOID)tmpValue,hInternet.ihandle[0].nDataLen,&dwRead);
2360        InternetCloseHandle(&hInternet);
[297]2361      }
2362#endif
[76]2363      map* tmp1=getMap(m->content,"encoding");
2364      map* tmp2=getMap(m->content,"mimeType");
[379]2365      map* tmp3=getMap(m->content,"value");
2366      int hasValue=1;
2367      if(tmp3==NULL){
2368        tmp3=createMap("value","");
2369        hasValue=-1;
2370      }
[76]2371      if((tmp1!=NULL && strncmp(tmp1->value,"base64",6)==0)
2372         || (tmp2!=NULL && (strncmp(tmp2->value,"image/",6)==0 ||
[490]2373                            (strncmp(tmp2->value,"application/",12)==0 &&
2374                             strncmp(tmp2->value,"application/json",16)!=0&&
2375                             strncmp(tmp2->value,"application/x-javascript",24)!=0&&
2376                             strncmp(tmp2->value,"application/vnd.google-earth.kml",32)!=0))
[279]2377             )) {
[76]2378        map* rs=getMap(m->content,"size");
2379        bool isSized=true;
2380        if(rs==NULL){
2381          char tmp1[1024];
[576]2382          sprintf(tmp1,"%ld",strlen(tmp3->value));
[280]2383          rs=createMap("size",tmp1);
[76]2384          isSized=false;
2385        }
[94]2386
[379]2387        xmlAddChild(nc3,xmlNewText(BAD_CAST base64(tmp3->value, atoi(rs->value))));
[500]2388        if(tmp1==NULL || (tmp1!=NULL && strncmp(tmp1->value,"base64",6)!=0))
2389          xmlNewProp(nc3,BAD_CAST "encoding",BAD_CAST "base64");
[76]2390        if(!isSized){
2391          freeMap(&rs);
2392          free(rs);
2393        }
[59]2394      }
[280]2395      else if(tmp2!=NULL){
2396        if(strncmp(tmp2->value,"text/js",7)==0 ||
2397           strncmp(tmp2->value,"application/json",16)==0)
[379]2398          xmlAddChild(nc3,xmlNewCDataBlock(doc,BAD_CAST tmp3->value,strlen(tmp3->value)));
[280]2399        else{
2400          if(strncmp(tmp2->value,"text/xml",8)==0 ||
[307]2401             strncmp(tmp2->value,"application/vnd.google-earth.kml",32)==0){
[490]2402            int li=zooXmlAddDoc(tmp3->value);
2403            xmlDocPtr doc = iDocs[li];
[280]2404            xmlNodePtr ir = xmlDocGetRootElement(doc);
2405            xmlAddChild(nc3,ir);
2406          }
2407          else
[379]2408            xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value));
[280]2409        }
[76]2410        xmlAddChild(nc2,nc3);
2411      }
[364]2412      else{
[379]2413        xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value));
2414      }
2415      if(hasValue<0){
2416        freeMap(&tmp3);
2417        free(tmp3);
2418      }
[9]2419    }
[1]2420  }
[9]2421  else{
[297]2422    tmpMap=getMap(m->content,"Reference");
[9]2423    nc3=nc2=xmlNewNode(ns_wps, BAD_CAST "Reference");
[76]2424    if(strcasecmp(type,"Output")==0)
2425      xmlNewProp(nc3,BAD_CAST "href",BAD_CAST tmpMap->value);
2426    else
2427      xmlNewNsProp(nc3,ns_xlink,BAD_CAST "href",BAD_CAST tmpMap->value);
[9]2428    tmp=m->content;
[297]2429#ifdef USE_MS
2430    map* testMap=getMap(tmp,"requestedMimeType");
2431#endif
[9]2432    while(tmp!=NULL){
[70]2433      if(strcasecmp(tmp->name,"mimeType")==0 ||
2434         strcasecmp(tmp->name,"encoding")==0 ||
2435         strcasecmp(tmp->name,"schema")==0 ||
2436         strcasecmp(tmp->name,"datatype")==0 ||
[490]2437         strcasecmp(tmp->name,"uom")==0){
[297]2438#ifdef USE_MS
2439        if(testMap!=NULL  && strncasecmp(testMap->value,"text/xml",8)!=0){
2440          if(strcasecmp(tmp->name,"mimeType")==0)
2441            xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST testMap->value);
2442        }
2443        else
2444#endif
[492]2445          if(strcasecmp(tmp->name,"datatype")==0)
2446            xmlNewProp(nc3,BAD_CAST "mimeType",BAD_CAST "text/plain");
2447          else
2448            xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
[490]2449      }
[9]2450      tmp=tmp->next;
2451      xmlAddChild(nc2,nc3);
2452    }
[1]2453  }
2454  xmlAddChild(nc1,nc2);
2455  xmlAddChild(nc,nc1);
2456
2457}
2458
[579]2459/**
2460 * Create XML node with basic ows metadata informations (Identifier,Title,Abstract)
2461 *
2462 * @param root the root XML node to add the description
2463 * @param ns_ows the ows XML namespace
2464 * @param identifier the identifier to use
2465 * @param amap the map containing the ows metadata informations
2466 */
[114]2467void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map* amap){
[1]2468  xmlNodePtr nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
[469]2469 
[1]2470  xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
2471  xmlAddChild(root,nc2);
2472  map* tmp=amap;
[490]2473  const char *tmp2[2];
[1]2474  tmp2[0]="Title";
2475  tmp2[1]="Abstract";
2476  int j=0;
2477  for(j=0;j<2;j++){
2478    map* tmp1=getMap(tmp,tmp2[j]);
2479    if(tmp1!=NULL){
2480      nc2 = xmlNewNode(ns_ows, BAD_CAST tmp2[j]);
[34]2481      xmlAddChild(nc2,xmlNewText(BAD_CAST _ss(tmp1->value)));
[1]2482      xmlAddChild(root,nc2);
2483    }
2484  }
2485}
2486
[579]2487/**
2488 * Access the value of the encoding key in a maps
2489 *
2490 * @param m the maps to search for the encoding key
2491 * @return the value of the encoding key in a maps if encoding key exists,
2492 *  "UTF-8" in other case.
2493 */
[9]2494char* getEncoding(maps* m){
2495  if(m!=NULL){
2496    map* tmp=getMap(m->content,"encoding");
[1]2497    if(tmp!=NULL){
[9]2498      return tmp->value;
[1]2499    }
2500    else
[490]2501      return (char*)"UTF-8";
[1]2502  }
2503  else
[490]2504    return (char*)"UTF-8"; 
[9]2505}
[1]2506
[579]2507/**
2508 * Access the value of the version key in a maps
2509 *
2510 * @param m the maps to search for the version key
2511 * @return the value of the version key in a maps if encoding key exists,
2512 *  "1.0.0" in other case.
2513 */
[9]2514char* getVersion(maps* m){
2515  if(m!=NULL){
2516    map* tmp=getMap(m->content,"version");
[1]2517    if(tmp!=NULL){
[9]2518      return tmp->value;
[1]2519    }
2520    else
[490]2521      return (char*)"1.0.0";
[1]2522  }
2523  else
[490]2524    return (char*)"1.0.0";
[9]2525}
[1]2526
[576]2527/**
2528 * Print an OWS ExceptionReport Document and HTTP headers (when required)
2529 * depending on the code.
2530 * Set hasPrinted value to true in the [lenv] section.
2531 *
[579]2532 * @param m the maps containing the settings of the main.cfg file
[576]2533 * @param s the map containing the text,code,locator keys
2534 */
[9]2535void printExceptionReportResponse(maps* m,map* s){
[469]2536  if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL)
2537    return;
[9]2538  int buffersize;
2539  xmlDocPtr doc;
2540  xmlChar *xmlbuff;
[34]2541  xmlNodePtr n;
[1]2542
[483]2543  zooXmlCleanupNs();
[9]2544  doc = xmlNewDoc(BAD_CAST "1.0");
2545  maps* tmpMap=getMaps(m,"main");
2546  char *encoding=getEncoding(tmpMap);
[490]2547  const char *exceptionCode;
[459]2548 
2549  map* tmp=getMap(s,"code");
2550  if(tmp!=NULL){
[576]2551    if(strcmp(tmp->value,"OperationNotSupported")==0 ||
2552       strcmp(tmp->value,"NoApplicableCode")==0)
[459]2553      exceptionCode="501 Not Implemented";
2554    else
2555      if(strcmp(tmp->value,"MissingParameterValue")==0 ||
2556         strcmp(tmp->value,"InvalidUpdateSequence")==0 ||
2557         strcmp(tmp->value,"OptionNotSupported")==0 ||
2558         strcmp(tmp->value,"VersionNegotiationFailed")==0 ||
2559         strcmp(tmp->value,"InvalidParameterValue")==0)
2560        exceptionCode="400 Bad request";
2561      else
[576]2562        exceptionCode="501 Internal Server Error";
[459]2563  }
2564  else
2565    exceptionCode="501 Internal Server Error";
2566
[32]2567  if(m!=NULL){
2568    map *tmpSid=getMapFromMaps(m,"lenv","sid");
2569    if(tmpSid!=NULL){
[384]2570      if( getpid()==atoi(tmpSid->value) ){
2571        printHeaders(m);
[459]2572        printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
[384]2573      }
[32]2574    }
[384]2575    else{
2576      printHeaders(m);
[459]2577      printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
[384]2578    }
[385]2579  }else{
[459]2580    printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
[385]2581  }
[34]2582  n=createExceptionReportNode(m,s,1);
[1]2583  xmlDocSetRootElement(doc, n);
[9]2584  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2585  printf("%s",xmlbuff);
2586  fflush(stdout);
2587  xmlFreeDoc(doc);
[1]2588  xmlFree(xmlbuff);
[9]2589  xmlCleanupParser();
[57]2590  zooXmlCleanupNs();
[471]2591  if(m!=NULL)
2592    setMapInMaps(m,"lenv","hasPrinted","true");
[1]2593}
2594
[576]2595/**
2596 * Create an OWS ExceptionReport Node.
2597 *
2598 * @param m the conf maps
2599 * @param s the map containing the text,code,locator keys
2600 * @param use_ns (0/1) choose if you want to generate an ExceptionReport or
2601 *  ows:ExceptionReport node respectively
2602 * @return the ExceptionReport/ows:ExceptionReport node
2603 */
[26]2604xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){
2605 
[490]2606  xmlNsPtr ns,ns_xsi;
2607  xmlNodePtr n,nc,nc1;
[1]2608
[469]2609  int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows");
[57]2610  ns=usedNs[nsid];
[576]2611  if(use_ns==0){
[481]2612    ns=NULL;
2613  }
[26]2614  n = xmlNewNode(ns, BAD_CAST "ExceptionReport");
2615  if(use_ns==1){
[576]2616    xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST"ows");
[26]2617    int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
2618    ns_xsi=usedNs[xsiId];
[469]2619    xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd");
[26]2620  }
[481]2621
2622
[34]2623  addLangAttr(n,m);
[26]2624  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.1.0");
2625 
[576]2626  int length=1;
2627  int cnt=0;
2628  map* len=getMap(s,"length");
2629  if(len!=NULL)
2630    length=atoi(len->value);
2631  for(cnt=0;cnt<length;cnt++){
2632    nc = xmlNewNode(ns, BAD_CAST "Exception");
2633   
2634    map* tmp=getMapArray(s,"code",cnt);
2635    if(tmp==NULL)
2636      tmp=getMap(s,"code");
2637    if(tmp!=NULL)
2638      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST tmp->value);
2639    else
2640      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode");
2641   
2642    tmp=getMapArray(s,"locator",cnt);
2643    if(tmp==NULL)
2644      tmp=getMap(s,"locator");
2645    if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0)
2646      xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value);
[26]2647
[576]2648    tmp=getMapArray(s,"text",cnt);
2649    nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
2650    if(tmp!=NULL){
2651      xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value);
2652      xmlAddChild(nc1,txt);
2653    }
2654    else{
2655      xmlNodeSetContent(nc1, BAD_CAST _("No debug message available"));
2656    }
2657    xmlAddChild(nc,nc1);
2658    xmlAddChild(n,nc);
[26]2659  }
2660  return n;
2661}
2662
[576]2663/**
2664 * Print an OWS ExceptionReport.
2665 *
2666 * @param m the conf maps
2667 * @param message the error message
2668 * @param errorcode the error code
2669 * @param locator the potential locator
2670 */
2671int errorException(maps *m, const char *message, const char *errorcode, const char *locator) 
2672{
2673  map* errormap = createMap("text", message);
2674  addToMap(errormap,"code", errorcode);
2675  if(locator!=NULL)
2676    addToMap(errormap,"locator", locator);
2677  else
2678    addToMap(errormap,"locator", "NULL");
2679  printExceptionReportResponse(m,errormap);
2680  freeMap(&errormap);
2681  free(errormap);
2682  return -1;
2683}
2684
[550]2685/**
2686 * Read a file generated by a service.
2687 *
2688 * @param m the conf maps
2689 * @param content the output item
2690 * @param filename the file to read
2691 */
2692void readGeneratedFile(maps* m,map* content,char* filename){
2693  FILE * file=fopen(filename,"rb");
[564]2694  if(file==NULL){
2695    fprintf(stderr,"Failed to open file %s for reading purpose.\n",filename);
2696    setMapInMaps(m,"lenv","message","Unable to read produced file. Please try again later");
2697    return ;
2698  }
[550]2699  fseek(file, 0, SEEK_END);
2700  long count = ftell(file);
2701  rewind(file);
2702  struct stat file_status; 
2703  stat(filename, &file_status);
2704  map* tmpMap1=getMap(content,"value");
2705  if(tmpMap1==NULL){
2706    addToMap(content,"value","");
2707    tmpMap1=getMap(content,"value");
2708  }
2709  free(tmpMap1->value);
2710  tmpMap1->value=(char*) malloc((count+1)*sizeof(char)); 
2711  fread(tmpMap1->value,1,count*sizeof(char),file);
2712  fclose(file);
2713  char rsize[100];
[576]2714  sprintf(rsize,"%ld",count*sizeof(char));
[550]2715  addToMap(tmpMap1,"size",rsize);
2716}
2717
[579]2718/**
2719 * Generate the output response (RawDataOutput or ResponseDocument)
2720 *
2721 * @param s the service structure containing the metadata informations
2722 * @param request_inputs the inputs provided to the service for execution
2723 * @param request_outputs the outputs updated by the service execution
2724 * @param request_inputs1 the map containing the HTTP request
2725 * @param cpid the process identifier attached to a service execution
2726 * @param m the conf maps containing the main.cfg settings
2727 * @param res the value returned by the service execution
2728 */
[1]2729void outputResponse(service* s,maps* request_inputs,maps* request_outputs,
2730                    map* request_inputs1,int cpid,maps* m,int res){
2731#ifdef DEBUG
2732  dumpMaps(request_inputs);
2733  dumpMaps(request_outputs);
2734  fprintf(stderr,"printProcessResponse\n");
2735#endif
2736  map* toto=getMap(request_inputs1,"RawDataOutput");
2737  int asRaw=0;
2738  if(toto!=NULL)
2739    asRaw=1;
[9]2740 
[379]2741  maps* tmpSess=getMaps(m,"senv");
2742  if(tmpSess!=NULL){
2743    map *_tmp=getMapFromMaps(m,"lenv","cookie");
[490]2744    char* sessId=NULL;
[379]2745    if(_tmp!=NULL){
[442]2746      printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value);
[379]2747      printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n");
2748      char session_file_path[100];
[92]2749      char *tmp1=strtok(_tmp->value,";");
2750      if(tmp1!=NULL)
[379]2751        sprintf(session_file_path,"%s",strstr(tmp1,"=")+1);
[92]2752      else
[379]2753        sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1);
2754      sessId=strdup(session_file_path);
2755    }else{
2756      maps* t=getMaps(m,"senv");
2757      map*p=t->content;
2758      while(p!=NULL){
2759        if(strstr(p->name,"ID")!=NULL){
2760          sessId=strdup(p->value);
2761          break;
2762        }
2763        p=p->next;
2764      }
[92]2765    }
[379]2766    char session_file_path[1024];
2767    map *tmpPath=getMapFromMaps(m,"main","sessPath");
2768    if(tmpPath==NULL)
2769      tmpPath=getMapFromMaps(m,"main","tmpPath");
2770    sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId);
[387]2771    FILE* teste=fopen(session_file_path,"w");
2772    if(teste==NULL){
2773      char tmpMsg[1024];
2774      sprintf(tmpMsg,_("Unable to create the file : \"%s\" for storing the session maps."),session_file_path);
[576]2775      errorException(m,tmpMsg,"InternalError",NULL);
2776
[387]2777      return;
2778    }
2779    else{
2780      fclose(teste);
2781      dumpMapsToFile(tmpSess,session_file_path);
2782    }
[92]2783  }
[379]2784 
[576]2785  if(res==SERVICE_FAILED){
2786    map *lenv;
2787    lenv=getMapFromMaps(m,"lenv","message");
2788    char *tmp0;
2789    if(lenv!=NULL){
2790      tmp0=(char*)malloc((strlen(lenv->value)+strlen(_("Unable to run the Service. The message returned back by the Service was the following: "))+1)*sizeof(char));
2791      sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value);
[550]2792    }
[576]2793    else{
2794      tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));
2795      sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service."));
2796    }
2797    errorException(m,tmp0,"InternalError",NULL);
2798    free(tmp0);
2799    return;
2800  }
[453]2801
[550]2802
[576]2803  map *tmp1=getMapFromMaps(m,"main","tmpPath");
[1]2804  if(asRaw==0){
[9]2805#ifdef DEBUG
2806    fprintf(stderr,"REQUEST_OUTPUTS FINAL\n");
2807    dumpMaps(request_outputs);
2808#endif
[70]2809    maps* tmpI=request_outputs;
[576]2810
[70]2811    while(tmpI!=NULL){
[297]2812#ifdef USE_MS
[364]2813      map* testMap=getMap(tmpI->content,"useMapserver");       
[297]2814#endif
[70]2815      toto=getMap(tmpI->content,"asReference");
[297]2816#ifdef USE_MS
[453]2817      if(toto!=NULL && strcasecmp(toto->value,"true")==0 && testMap==NULL)
[297]2818#else
[453]2819      if(toto!=NULL && strcasecmp(toto->value,"true")==0)
[297]2820#endif
[453]2821        {
[550]2822          elements* in=getElements(s->outputs,tmpI->name);
2823          char *format=NULL;
2824          if(in!=NULL){
2825            format=strdup(in->format);
2826          }else
2827            format=strdup("LiteralData");
2828          if(strcasecmp(format,"BoundingBoxData")==0){
2829            addToMap(tmpI->content,"extension","xml");
2830            addToMap(tmpI->content,"mimeType","text/xml");
2831            addToMap(tmpI->content,"encoding","UTF-8");
2832            addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
[70]2833          }
[550]2834
2835          map *gfile=getMap(tmpI->content,"generated_file");
2836          char *file_name;
2837          if(gfile!=NULL){
[565]2838            gfile=getMap(tmpI->content,"expected_generated_file");
2839            if(gfile==NULL){
2840              gfile=getMap(tmpI->content,"generated_file");
2841            }
[550]2842            readGeneratedFile(m,tmpI->content,gfile->value);       
2843            file_name=(char*)malloc((strlen(gfile->value)+strlen(tmp1->value)+1)*sizeof(char));
2844            for(int i=0;i<strlen(gfile->value);i++)
2845              file_name[i]=gfile->value[i+strlen(tmp1->value)];
2846          }
2847          else{
2848            map *ext=getMap(tmpI->content,"extension");
2849            char *file_path;
2850            bool hasExt=true;
2851            if(ext==NULL){
2852              // We can fallback to a default list of supported formats using
2853              // mimeType information if present here. Maybe we can add more formats
2854              // here.
2855              // If mimeType was not found, we then set txt as the default extension
2856              map* mtype=getMap(tmpI->content,"mimeType");
2857              if(mtype!=NULL) {
2858                if(strncasecmp(mtype->value,"text/xml",8)==0)
2859                  ext=createMap("extension","xml");
2860                else if(strncasecmp(mtype->value,"application/zip",15)==0)
2861                  ext=createMap("extension","zip");
2862                else if(strncasecmp(mtype->value,"application/json",16)==0)
2863                  ext=createMap("extension","js");
2864                else if(strncmp(mtype->value,"application/vnd.google-earth.kml",32)==0)
2865                  ext=createMap("extension","kml");
2866                else if(strncmp(mtype->value,"image/",6)==0)
2867                  ext=createMap("extension",strstr(mtype->value,"/")+1);
2868                else
2869                  ext=createMap("extension","txt");
2870              }
2871              else
2872                ext=createMap("extension","txt");
2873              hasExt=false;
2874            }
2875            file_name=(char*)malloc((strlen(s->name)+strlen(ext->value)+strlen(tmpI->name)+1024)*sizeof(char));
2876            int cpid0=cpid+time(NULL);
2877            sprintf(file_name,"%s_%s_%i.%s",s->name,tmpI->name,cpid0,ext->value);
2878            file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char));
2879            sprintf(file_path,"%s/%s",tmp1->value,file_name);
2880            FILE *ofile=fopen(file_path,"wb");
2881            if(ofile==NULL){
2882              char tmpMsg[1024];
2883              sprintf(tmpMsg,_("Unable to create the file : \"%s\" for storing the %s final result."),file_name,tmpI->name);
[576]2884              errorException(m,tmpMsg,"InternalError",NULL);
[550]2885              free(file_name);
2886              free(file_path);
2887              return;
2888            }
2889            free(file_path);
2890            if(!hasExt){
2891              freeMap(&ext);
2892              free(ext);
2893            }
2894            toto=getMap(tmpI->content,"value");
2895            if(strcasecmp(format,"BoundingBoxData")!=0){
2896              map* size=getMap(tmpI->content,"size");
2897              if(size!=NULL && toto!=NULL)
2898                fwrite(toto->value,1,atoi(size->value)*sizeof(char),ofile);
2899              else
2900                if(toto!=NULL && toto->value!=NULL)
2901                  fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);
2902            }else{
2903              printBoundingBoxDocument(m,tmpI,ofile);
2904            }
2905            fclose(ofile);
2906
2907          }
2908          map *tmp2=getMapFromMaps(m,"main","tmpUrl");
2909          map *tmp3=getMapFromMaps(m,"main","serverAddress");
2910          char *file_url;
2911          if(strncasecmp(tmp2->value,"http://",7)==0 ||
2912             strncasecmp(tmp2->value,"https://",8)==0){
2913            file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));
2914            sprintf(file_url,"%s/%s",tmp2->value,file_name);
2915          }else{
2916            file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));
2917            sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);
2918          }
2919          addToMap(tmpI->content,"Reference",file_url);
2920          free(format);
[453]2921          free(file_name);
[550]2922          free(file_url);       
2923         
[386]2924        }
[297]2925#ifdef USE_MS
2926      else{
2927        if(testMap!=NULL){
2928          setReferenceUrl(m,tmpI);
2929        }
2930      }
2931#endif
[70]2932      tmpI=tmpI->next;
[9]2933    }
[1]2934    map *r_inputs=getMap(s->content,"serviceProvider");
2935#ifdef DEBUG
2936    fprintf(stderr,"SERVICE : %s\n",r_inputs->value);
2937    dumpMaps(m);
2938#endif
[9]2939    printProcessResponse(m,request_inputs1,cpid,
[26]2940                         s,r_inputs->value,res,
2941                         request_inputs,
2942                         request_outputs);
[550]2943  }
2944  else{
2945    /**
2946     * We get the requested output or fallback to the first one if the
2947     * requested one is not present in the resulting outputs maps.
2948     */
2949    maps* tmpI=NULL;
2950    map* tmpIV=getMap(request_inputs1,"RawDataOutput");
2951    if(tmpIV!=NULL){
2952      tmpI=getMaps(request_outputs,tmpIV->value);
[453]2953    }
[550]2954    if(tmpI==NULL)
2955      tmpI=request_outputs;
2956    elements* e=getElements(s->outputs,tmpI->name);
2957    if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
2958      printBoundingBoxDocument(m,tmpI,NULL);
2959    }else{
2960      map *gfile=getMap(tmpI->content,"generated_file");
2961      if(gfile!=NULL){
[576]2962        gfile=getMap(tmpI->content,"expected_generated_file");
2963        if(gfile==NULL){
2964          gfile=getMap(tmpI->content,"generated_file");
2965        }
[550]2966        readGeneratedFile(m,tmpI->content,gfile->value);
2967      }
2968      toto=getMap(tmpI->content,"value");
2969      if(toto==NULL){
2970        char tmpMsg[1024];
2971        sprintf(tmpMsg,_("Wrong RawDataOutput parameter, unable to fetch any result for the name your provided : \"%s\"."),tmpI->name);
[576]2972        errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput");
[481]2973        return;
2974      }
[550]2975      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
2976      if(fname!=NULL)
2977        printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
2978      map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
2979      if(rs!=NULL)
2980        printf("Content-Length: %s\r\n",rs->value);
2981      printHeaders(m);
2982      char mime[1024];
2983      map* mi=getMap(tmpI->content,"mimeType");
[1]2984#ifdef DEBUG
[550]2985      fprintf(stderr,"SERVICE OUTPUTS\n");
2986      dumpMaps(request_outputs);
2987      fprintf(stderr,"SERVICE OUTPUTS\n");
[1]2988#endif
[550]2989      map* en=getMap(tmpI->content,"encoding");
2990      if(mi!=NULL && en!=NULL)
2991        sprintf(mime,
2992                "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
2993                mi->value,en->value);
2994      else
2995        if(mi!=NULL)
[26]2996          sprintf(mime,
[550]2997                  "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
2998                  mi->value);
[26]2999        else
[550]3000          sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
3001      printf("%s",mime);
3002      if(rs!=NULL)
3003        fwrite(toto->value,1,atoi(rs->value),stdout);
3004      else
3005        fwrite(toto->value,1,strlen(toto->value),stdout);
[1]3006#ifdef DEBUG
[550]3007      dumpMap(toto);
[1]3008#endif
[26]3009    }
[550]3010  }
[1]3011}
3012
[579]3013
3014/**
3015 * Base64 encoding of a char*
3016 *
3017 * @param input the value to encode
3018 * @param length the value length
3019 * @return the buffer containing the base64 value
3020 * @warning make sure to free the returned value
3021 */
[216]3022char *base64(const char *input, int length)
[1]3023{
3024  BIO *bmem, *b64;
3025  BUF_MEM *bptr;
3026
3027  b64 = BIO_new(BIO_f_base64());
[94]3028  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
[1]3029  bmem = BIO_new(BIO_s_mem());
3030  b64 = BIO_push(b64, bmem);
[500]3031  BIO_write(b64, input, length+1);
[1]3032  BIO_flush(b64);
3033  BIO_get_mem_ptr(b64, &bptr);
3034
[500]3035  char *buff = (char *)malloc((bptr->length+1)*sizeof(char));
3036  memcpy(buff, bptr->data, bptr->length);
[1]3037  buff[bptr->length-1] = 0;
3038
3039  BIO_free_all(b64);
3040
3041  return buff;
3042}
3043
[579]3044/**
3045 * Base64 decoding of a char*
3046 *
3047 * @param input the value to decode
3048 * @param length the value length
3049 * @param red the value length
3050 * @return the buffer containing the base64 value
3051 * @warning make sure to free the returned value
3052 */
[216]3053char *base64d(const char *input, int length,int* red)
[88]3054{
3055  BIO *b64, *bmem;
3056
3057  char *buffer = (char *)malloc(length);
[94]3058  if(buffer){
3059    memset(buffer, 0, length);
3060    b64 = BIO_new(BIO_f_base64());
3061    if(b64){
[216]3062      bmem = BIO_new_mem_buf((unsigned char*)input,length);
[94]3063      bmem = BIO_push(b64, bmem);
3064      *red=BIO_read(bmem, buffer, length);
3065      buffer[length-1]=0;
3066      BIO_free_all(bmem);
3067    }
3068  }
[88]3069  return buffer;
3070}
3071
[579]3072/**
3073 * Make sure that each value encoded in base64 in a maps is decoded.
3074 *
3075 * @param in the maps containing the values
3076 */
[88]3077void ensureDecodedBase64(maps **in){
3078  maps* cursor=*in;
3079  while(cursor!=NULL){
3080    map *tmp=getMap(cursor->content,"encoding");
3081    if(tmp!=NULL && strncasecmp(tmp->value,"base64",6)==0){
3082      tmp=getMap(cursor->content,"value");
3083      addToMap(cursor->content,"base64_value",tmp->value);
[94]3084      int size=0;
[88]3085      char *s=strdup(tmp->value);
3086      free(tmp->value);
3087      tmp->value=base64d(s,strlen(s),&size);
[94]3088      free(s);
[88]3089      char sizes[1024];
3090      sprintf(sizes,"%d",size);
3091      addToMap(cursor->content,"size",sizes);
3092    }
3093    cursor=cursor->next;
3094  }
3095}
3096
[579]3097/**
3098 * Add the default values defined in the zcfg to a maps.
3099 *
3100 * @param out the maps containing the inputs or outputs given in the initial
3101 *  HTTP request
3102 * @param in the description of all inputs or outputs available for a service
3103 * @param m the maps containing the settings of the main.cfg file
3104 * @param type 0 for inputs and 1 for outputs
3105 * @param err the map to store potential missing mandatory input parameters or
3106 *  wrong output names depending on the type.
3107 * @return "" if no error was detected, the name of last input or output causing
3108 *  an error.
3109 */
[576]3110char* addDefaultValues(maps** out,elements* in,maps* m,int type,map** err){
3111  map *res=*err;
[1]3112  elements* tmpInputs=in;
3113  maps* out1=*out;
[576]3114  char *result=NULL;
3115  int nb=0;
[280]3116  if(type==1){
3117    while(out1!=NULL){
[576]3118      if(getElements(in,out1->name)==NULL){
3119        if(res==NULL){
3120          res=createMap("value",out1->name);
3121        }else{
3122          setMapArray(res,"value",nb,out1->name);
3123        }
3124        nb++;
3125        result=out1->name;
3126      }
[280]3127      out1=out1->next;
3128    }
[576]3129    if(res!=NULL){
3130      *err=res;
3131      return result;
3132    }
[280]3133    out1=*out;
3134  }
[1]3135  while(tmpInputs!=NULL){
3136    maps *tmpMaps=getMaps(out1,tmpInputs->name);
3137    if(tmpMaps==NULL){
[9]3138      maps* tmpMaps2=(maps*)malloc(MAPS_SIZE);
[57]3139      tmpMaps2->name=strdup(tmpInputs->name);
[9]3140      tmpMaps2->content=NULL;
3141      tmpMaps2->next=NULL;
[63]3142     
3143      if(type==0){
3144        map* tmpMapMinO=getMap(tmpInputs->content,"minOccurs");
[490]3145        if(tmpMapMinO!=NULL){
[63]3146          if(atoi(tmpMapMinO->value)>=1){
3147            freeMaps(&tmpMaps2);
3148            free(tmpMaps2);
[576]3149            if(res==NULL){
3150              res=createMap("value",tmpInputs->name);
3151            }else{
3152              setMapArray(res,"value",nb,tmpInputs->name);
3153            }
3154            nb++;
3155            result=tmpInputs->name;
[63]3156          }
3157          else{
3158            if(tmpMaps2->content==NULL)
3159              tmpMaps2->content=createMap("minOccurs",tmpMapMinO->value);
3160            else
3161              addToMap(tmpMaps2->content,"minOccurs",tmpMapMinO->value);
3162          }
[490]3163        }
[576]3164        if(res==NULL){
3165          map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
3166          if(tmpMaxO!=NULL){
3167            if(tmpMaps2->content==NULL)
3168              tmpMaps2->content=createMap("maxOccurs",tmpMaxO->value);
3169            else
3170              addToMap(tmpMaps2->content,"maxOccurs",tmpMaxO->value);
3171          }
3172          map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");
3173          if(tmpMaxMB!=NULL){
3174            if(tmpMaps2->content==NULL)
3175              tmpMaps2->content=createMap("maximumMegabytes",tmpMaxMB->value);
3176            else
3177              addToMap(tmpMaps2->content,"maximumMegabytes",tmpMaxMB->value);
3178          }
[490]3179        }
[63]3180      }
3181
[576]3182      if(res==NULL){
3183        iotype* tmpIoType=tmpInputs->defaults;
3184        if(tmpIoType!=NULL){
3185          map* tmpm=tmpIoType->content;
3186          while(tmpm!=NULL){
3187            if(tmpMaps2->content==NULL)
3188              tmpMaps2->content=createMap(tmpm->name,tmpm->value);
3189            else
3190              addToMap(tmpMaps2->content,tmpm->name,tmpm->value);
3191            tmpm=tmpm->next;
3192          }
[63]3193        }
[576]3194        addToMap(tmpMaps2->content,"inRequest","false");
3195        if(type==0){
3196          map *tmpMap=getMap(tmpMaps2->content,"value");
3197          if(tmpMap==NULL)
3198            addToMap(tmpMaps2->content,"value","NULL");
3199        }
3200        if(out1==NULL){
3201          *out=dupMaps(&tmpMaps2);
3202          out1=*out;
3203        }
3204        else
3205          addMapsToMaps(&out1,tmpMaps2);
3206        freeMap(&tmpMaps2->content);
3207        free(tmpMaps2->content);
3208        tmpMaps2->content=NULL;
3209        freeMaps(&tmpMaps2);
3210        free(tmpMaps2);
3211        tmpMaps2=NULL;
[1]3212      }
3213    }
3214    else{
[57]3215      iotype* tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,
3216                                             tmpMaps->content);
[63]3217      if(type==0) {
[76]3218        /**
3219         * In case of an Input maps, then add the minOccurs and maxOccurs to the
3220         * content map.
3221         */
[63]3222        map* tmpMap1=getMap(tmpInputs->content,"minOccurs");
3223        if(tmpMap1!=NULL){
3224          if(tmpMaps->content==NULL)
3225            tmpMaps->content=createMap("minOccurs",tmpMap1->value);
3226          else
3227            addToMap(tmpMaps->content,"minOccurs",tmpMap1->value);
3228        }
3229        map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
3230        if(tmpMaxO!=NULL){
3231          if(tmpMaps->content==NULL)
[485]3232            tmpMaps->content=createMap("maxOccurs",tmpMaxO->value);
[63]3233          else
[485]3234            addToMap(tmpMaps->content,"maxOccurs",tmpMaxO->value);
[63]3235        }
[485]3236        map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");
[490]3237        if(tmpMaxMB!=NULL){
[485]3238          if(tmpMaps->content==NULL)
3239            tmpMaps->content=createMap("maximumMegabytes",tmpMaxMB->value);
3240          else
3241            addToMap(tmpMaps->content,"maximumMegabytes",tmpMaxMB->value);
[490]3242        }
[76]3243        /**
3244         * Parsing BoundingBoxData, fill the following map and then add it to
3245         * the content map of the Input maps:
3246         * lowerCorner, upperCorner, srs and dimensions
3247         * cf. parseBoundingBox
3248         */
3249        if(strcasecmp(tmpInputs->format,"BoundingBoxData")==0){
3250          maps* tmpI=getMaps(*out,tmpInputs->name);
3251          if(tmpI!=NULL){
3252            map* tmpV=getMap(tmpI->content,"value");
3253            if(tmpV!=NULL){
3254              char *tmpVS=strdup(tmpV->value);
3255              map* tmp=parseBoundingBox(tmpVS);
3256              free(tmpVS);
3257              map* tmpC=tmp;
3258              while(tmpC!=NULL){
3259                addToMap(tmpMaps->content,tmpC->name,tmpC->value);
3260                tmpC=tmpC->next;
3261              }
3262              freeMap(&tmp);
3263              free(tmp);
3264            }
3265          }
3266        }
[63]3267      }
3268
[57]3269      if(tmpIoType!=NULL){
3270        map* tmpContent=tmpIoType->content;
3271        map* cval=NULL;
[360]3272        int hasPassed=-1;
[57]3273        while(tmpContent!=NULL){
3274          if((cval=getMap(tmpMaps->content,tmpContent->name))==NULL){
[9]3275#ifdef DEBUG
[57]3276            fprintf(stderr,"addDefaultValues %s => %s\n",tmpContent->name,tmpContent->value);
[9]3277#endif
[63]3278            if(tmpMaps->content==NULL)
3279              tmpMaps->content=createMap(tmpContent->name,tmpContent->value);
3280            else
3281              addToMap(tmpMaps->content,tmpContent->name,tmpContent->value);
[360]3282           
3283            if(hasPassed<0 && type==0 && getMap(tmpMaps->content,"isArray")!=NULL){
3284              map* length=getMap(tmpMaps->content,"length");
3285              int i;
3286              char *tcn=strdup(tmpContent->name);
3287              for(i=1;i<atoi(length->value);i++){
[364]3288#ifdef DEBUG
[360]3289                dumpMap(tmpMaps->content);
3290                fprintf(stderr,"addDefaultValues %s_%d => %s\n",tcn,i,tmpContent->value);
[364]3291#endif
3292                int len=strlen((char*) tcn);
3293                char *tmp1=(char *)malloc((len+10)*sizeof(char));
[360]3294                sprintf(tmp1,"%s_%d",tcn,i);
[364]3295#ifdef DEBUG
[360]3296                fprintf(stderr,"addDefaultValues %s => %s\n",tmp1,tmpContent->value);
[364]3297#endif
[360]3298                addToMap(tmpMaps->content,tmp1,tmpContent->value);
3299                free(tmp1);
3300                hasPassed=1;
3301              }
3302              free(tcn);
3303            }
[57]3304          }
3305          tmpContent=tmpContent->next;
[9]3306        }
[297]3307#ifdef USE_MS
3308        /**
3309         * check for useMapServer presence
3310         */
3311        map* tmpCheck=getMap(tmpIoType->content,"useMapServer");
3312        if(tmpCheck!=NULL){
3313          // Get the default value
3314          tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,NULL);
3315          tmpCheck=getMap(tmpMaps->content,"mimeType");
3316          addToMap(tmpMaps->content,"requestedMimeType",tmpCheck->value);
3317          map* cursor=tmpIoType->content;
3318          while(cursor!=NULL){
3319            addToMap(tmpMaps->content,cursor->name,cursor->value);
3320            cursor=cursor->next;
3321          }
3322         
3323          cursor=tmpInputs->content;
3324          while(cursor!=NULL){
3325            if(strcasecmp(cursor->name,"Title")==0 ||
3326               strcasecmp(cursor->name,"Abstract")==0)
3327              addToMap(tmpMaps->content,cursor->name,cursor->value);
3328           cursor=cursor->next;
3329          }
3330        }
3331#endif
[1]3332      }
[92]3333      if(tmpMaps->content==NULL)
3334        tmpMaps->content=createMap("inRequest","true");
3335      else
3336        addToMap(tmpMaps->content,"inRequest","true");
[280]3337
[1]3338    }
3339    tmpInputs=tmpInputs->next;
3340  }
[576]3341  if(res!=NULL){
3342    *err=res;
3343    return result;
3344  }
[9]3345  return "";
[1]3346}
[76]3347
3348/**
[579]3349 * Parse a BoundingBox string
[76]3350 *
[579]3351 * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040):
3352 *  10.2 Bounding box
3353 *
[76]3354 *
[579]3355 * Value is provided as : lowerCorner,upperCorner,crs,dimension
3356 * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
[76]3357 *
[579]3358 * A map to store boundingbox informations should contain:
[76]3359 *  - lowerCorner : double,double (minimum within this bounding box)
3360 *  - upperCorner : double,double (maximum within this bounding box)
3361 *  - crs : URI (Reference to definition of the CRS)
3362 *  - dimensions : int
3363 *
3364 * Note : support only 2D bounding box.
[579]3365 *
3366 * @param value the char* containing the KVP bouding box
3367 * @return a map containing all the bounding box keys
[76]3368 */
[114]3369map* parseBoundingBox(const char* value){
[76]3370  map *res=NULL;
3371  if(value!=NULL){
3372    char *cv,*cvp;
[114]3373    cv=strtok_r((char*) value,",",&cvp);
[76]3374    int cnt=0;
3375    int icnt=0;
3376    char *currentValue=NULL;
3377    while(cv){
3378      if(cnt<2)
3379        if(currentValue!=NULL){
3380          char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));
3381          sprintf(finalValue,"%s%s",currentValue,cv);
3382          switch(cnt){
3383          case 0:
3384            res=createMap("lowerCorner",finalValue);
3385            break;
3386          case 1:
3387            addToMap(res,"upperCorner",finalValue);
3388            icnt=-1;
3389            break;
3390          }
3391          cnt++;
3392          free(currentValue);
3393          currentValue=NULL;
3394          free(finalValue);
3395        }
3396        else{
3397          currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));
3398          sprintf(currentValue,"%s ",cv);
3399        }
3400      else
3401        if(cnt==2){
3402          addToMap(res,"crs",cv);
3403          cnt++;
3404        }
3405        else
3406          addToMap(res,"dimensions",cv);
3407      icnt++;
3408      cv=strtok_r(NULL,",",&cvp);
3409    }
3410  }
3411  return res;
3412}
3413
3414/**
[579]3415 * Create required XML nodes for boundingbox and update the current XML node
3416 *
3417 * @param ns_ows the ows XML namespace
3418 * @param n the XML node to update
3419 * @param boundingbox the map containing the boundingbox definition
[76]3420 */
3421void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
3422
[490]3423  xmlNodePtr lw=NULL,uc=NULL;
[76]3424
3425  map* tmp=getMap(boundingbox,"value");
3426
3427  tmp=getMap(boundingbox,"lowerCorner");
3428  if(tmp!=NULL){
3429    lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");
3430    xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));
3431  }
3432
3433  tmp=getMap(boundingbox,"upperCorner");
3434  if(tmp!=NULL){
3435    uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");
3436    xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));
3437  }
3438
3439  tmp=getMap(boundingbox,"crs");
3440  if(tmp!=NULL)
3441    xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);
3442
3443  tmp=getMap(boundingbox,"dimensions");
3444  if(tmp!=NULL)
3445    xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);
3446
3447  xmlAddChild(n,lw);
3448  xmlAddChild(n,uc);
3449
3450}
3451
[579]3452/**
3453 * Print an ows:BoundingBox XML document
3454 *
3455 * @param m the maps containing the settings of the main.cfg file
3456 * @param boundingbox the maps containing the boundingbox definition
3457 * @param file the file to print the BoundingBox (if NULL then print on stdout)
3458 * @see parseBoundingBox, printBoundingBox
3459 */
[76]3460void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){
3461  if(file==NULL)
3462    rewind(stdout);
3463  xmlNodePtr n;
3464  xmlDocPtr doc;
3465  xmlNsPtr ns_ows,ns_xsi;
3466  xmlChar *xmlbuff;
3467  int buffersize;
3468  char *encoding=getEncoding(m);
3469  map *tmp;
3470  if(file==NULL){
3471    int pid=0;
3472    tmp=getMapFromMaps(m,"lenv","sid");
3473    if(tmp!=NULL)
3474      pid=atoi(tmp->value);
3475    if(pid==getpid()){
3476      printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
3477    }
3478    fflush(stdout);
3479  }
3480
3481  doc = xmlNewDoc(BAD_CAST "1.0");
3482  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
3483  ns_ows=usedNs[owsId];
3484  n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");
[216]3485  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
[76]3486  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
3487  ns_xsi=usedNs[xsiId];
3488  xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
3489  map *tmp1=getMap(boundingbox->content,"value");
3490  tmp=parseBoundingBox(tmp1->value);
3491  printBoundingBox(ns_ows,n,tmp);
3492  xmlDocSetRootElement(doc, n);
3493
3494  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
3495  if(file==NULL)
[114]3496    printf("%s",xmlbuff);
[76]3497  else{
3498    fprintf(file,"%s",xmlbuff);
3499  }
3500
3501  if(tmp!=NULL){
3502    freeMap(&tmp);
3503    free(tmp);
3504  }
3505  xmlFree(xmlbuff);
3506  xmlFreeDoc(doc);
3507  xmlCleanupParser();
3508  zooXmlCleanupNs();
3509 
3510}
[280]3511
[579]3512/**
3513 * Compute md5
3514 *
3515 * @param url the char*
3516 * @return a char* representing the md5 of the url
3517 * @warning make sure to free ressources returned by this function
3518 */
[364]3519char* getMd5(char* url){
[291]3520  EVP_MD_CTX md5ctx;
[364]3521  char* fresult=(char*)malloc((EVP_MAX_MD_SIZE+1)*sizeof(char));
[291]3522  unsigned char result[EVP_MAX_MD_SIZE];
3523  unsigned int len;
3524  EVP_DigestInit(&md5ctx, EVP_md5());
3525  EVP_DigestUpdate(&md5ctx, url, strlen(url));
3526  EVP_DigestFinal_ex(&md5ctx,result,&len);
3527  EVP_MD_CTX_cleanup(&md5ctx);
3528  int i;
3529  for(i = 0; i < len; i++){
3530    if(i>0){
3531      char *tmp=strdup(fresult);
3532      sprintf(fresult,"%s%02x", tmp,result[i]);
3533      free(tmp);
3534    }
3535    else
3536      sprintf(fresult,"%02x",result[i]);
3537  }
3538  return fresult;
3539}
3540
[280]3541/**
[579]3542 * Cache a file for a given request.
3543 * For each cached file, the are two files stored, a .zca and a .zcm containing
3544 * the downloaded content and the mimeType respectively.
3545 *
3546 * @param conf the maps containing the settings of the main.cfg file
3547 * @param request the url used too fetch the content
3548 * @param content the downloaded content
3549 * @param mimeType the content mimeType
3550 * @param length the content size
[280]3551 */
[446]3552void addToCache(maps* conf,char* request,char* content,char* mimeType,int length){
[280]3553  map* tmp=getMapFromMaps(conf,"main","cacheDir");
3554  if(tmp!=NULL){
[364]3555    char* md5str=getMd5(request);
[292]3556    char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
3557    sprintf(fname,"%s/%s.zca",tmp->value,md5str);
[291]3558#ifdef DEBUG
[280]3559    fprintf(stderr,"Cache list : %s\n",fname);
3560    fflush(stderr);
[291]3561#endif
[293]3562    FILE* fo=fopen(fname,"w+");
[471]3563    if(fo==NULL){
3564      fprintf (stderr, "Failed to open %s for writting: %s\n",fname, strerror(errno));
3565      return;
3566    }
[293]3567    fwrite(content,sizeof(char),length,fo);
3568    fclose(fo);
[446]3569
3570    sprintf(fname,"%s/%s.zcm",tmp->value,md5str);
3571    fo=fopen(fname,"w+");
3572#ifdef DEBUG
3573    fprintf(stderr,"MIMETYPE: %s\n",mimeType);
3574#endif
[492]3575    fwrite(mimeType,sizeof(char),strlen(mimeType),fo);
[446]3576    fclose(fo);
3577
[293]3578    free(md5str);
3579    free(fname);
[280]3580  }
3581}
3582
[579]3583/**
3584 * Verify if a url is available in the cache
3585 *
3586 * @param conf the maps containing the settings of the main.cfg file
3587 * @param request the url
3588 * @return the full name of the cached file if any, NULL in other case
3589 * @warning make sure to free ressources returned by this function (if not NULL)
3590 */
[280]3591char* isInCache(maps* conf,char* request){
[291]3592  map* tmpM=getMapFromMaps(conf,"main","cacheDir");
3593  if(tmpM!=NULL){
[364]3594    char* md5str=getMd5(request);
[291]3595#ifdef DEBUG
3596    fprintf(stderr,"MD5STR : (%s)\n\n",md5str);
3597#endif
[392]3598    char* fname=(char*)malloc(sizeof(char)*(strlen(tmpM->value)+strlen(md5str)+6));
[292]3599    sprintf(fname,"%s/%s.zca",tmpM->value,md5str);
[280]3600    struct stat f_status;
3601    int s=stat(fname, &f_status);
[292]3602    if(s==0 && f_status.st_size>0){
3603      free(md5str);
3604      return fname;
3605    }
[291]3606    free(md5str);
3607    free(fname);
[280]3608  }
3609  return NULL;
3610}
[281]3611
[579]3612/**
3613 * Effectively run all the HTTP requests in the queue
3614 *
3615 * @param m the maps containing the settings of the main.cfg file
3616 * @param inputs the maps containing the inputs (defined in the requests+added
3617 *  per default based on the zcfg file)
3618 * @param hInternet the HINTERNET pointer
3619 * @return 0 on success
3620 */
[492]3621int runHttpRequests(maps** m,maps** inputs,HINTERNET* hInternet){
3622  if(hInternet->nb>0){
3623    processDownloads(hInternet);
3624    maps* content=*inputs;
3625    map* tmp1;
3626    int index=0;
3627    while(content!=NULL){
[550]3628     
3629      map* length=getMap(content->content,"length");
3630      int shouldClean=-1;
3631      if(length==NULL){
3632        length=createMap("length","1");
3633        shouldClean=1;
3634      }
3635      for(int i=0;i<atoi(length->value);i++){
3636       
3637        char* fcontent;
3638        char *mimeType=NULL;
3639        int fsize=0;
3640        char cname[15];
3641        char vname[11];
3642        char vname1[11];
3643        char sname[9];
3644        char icname[14];
3645        char xname[16];
3646        if(index>0)
3647          sprintf(vname1,"value_%d",index);
3648        else
3649          sprintf(vname1,"value");
[492]3650
[550]3651        if(i>0){
3652          tmp1=getMap(content->content,cname);
3653          sprintf(cname,"cache_file_%d",i);
3654          sprintf(vname,"value_%d",i);
3655          sprintf(sname,"size_%d",i);
3656          sprintf(icname,"isCached_%d",i);
3657          sprintf(xname,"Reference_%d",i);
3658        }else{
3659          sprintf(cname,"cache_file");
3660          sprintf(vname,"value");
3661          sprintf(icname,"isCached");
3662          sprintf(sname,"size");
3663          sprintf(xname,"Reference");
3664        }
3665
3666        map* tmap=getMapFromMaps(*m,"orequests",vname1);
3667        if((tmp1=getMap(content->content,xname))!=NULL && strcasecmp(tmap->value,tmp1->value)==0 ){
3668          if(getMap(content->content,icname)==NULL){
3669           
3670            fcontent=(char*)malloc((hInternet->ihandle[index].nDataLen+1)*sizeof(char));
3671            if(fcontent == NULL){
3672              return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);
3673            }
3674            size_t dwRead;
3675            InternetReadFile(hInternet->ihandle[index], 
3676                             (LPVOID)fcontent, 
3677                             hInternet->ihandle[index].nDataLen, 
3678                             &dwRead);
3679            fcontent[hInternet->ihandle[index].nDataLen]=0;
3680            fsize=hInternet->ihandle[index].nDataLen;
3681            if(hInternet->ihandle[index].mimeType==NULL)
3682              mimeType=strdup("none");
3683            else
[554]3684                  mimeType=strdup(hInternet->ihandle[index].mimeType);       
[550]3685           
3686            map* tmpMap=getMapOrFill(&content->content,vname,"");
3687            free(tmpMap->value);
3688            tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
3689            if(tmpMap->value==NULL){
3690              return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);
3691            }
3692            memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
3693           
3694            char ltmp1[256];
3695            sprintf(ltmp1,"%d",fsize);
3696            map* tmp=getMapFromMaps(*m,"main","cacheDir");
3697            if(tmp!=NULL){
3698              char* md5str=getMd5(tmp1->value);
3699              char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
3700              sprintf(fname,"%s/%s.zca",tmp->value,md5str);
3701              addToMap(content->content,cname,fname);
3702              free(fname);
3703            }
3704            addToMap(content->content,sname,ltmp1);
3705            addToCache(*m,tmp1->value,fcontent,mimeType,fsize);
3706            free(fcontent);
3707            free(mimeType);
3708            dumpMaps(content);
3709            index++;
3710
[492]3711          }
3712        }
3713      }
[550]3714      if(shouldClean>0){
3715        freeMap(&length);
3716        free(length);
3717      }
3718     
[492]3719      content=content->next;
3720    }
[550]3721   
[492]3722  }
[576]3723  return 0;
[492]3724}
3725
[281]3726/**
3727 * Try to load file from cache or download a remote file if not in cache
[579]3728 *
3729 * @param m the maps containing the settings of the main.cfg file
3730 * @param content the map to update
3731 * @param hInternet the HINTERNET pointer
3732 * @param url the url to fetch
3733 * @return 0
[281]3734 */
[492]3735int loadRemoteFile(maps** m,map** content,HINTERNET* hInternet,char *url){
[281]3736  char* fcontent;
[471]3737  char* cached=isInCache(*m,url);
[446]3738  char *mimeType=NULL;
[490]3739  int fsize=0;
[550]3740
3741  map* t=getMap(*content,"xlink:href");
3742  if(t==NULL){
3743    t=getMap((*content),"href");
3744    addToMap(*content,"xlink:href",url);
3745  }
3746
[281]3747  if(cached!=NULL){
[550]3748
[281]3749    struct stat f_status;
3750    int s=stat(cached, &f_status);
3751    if(s==0){
3752      fcontent=(char*)malloc(sizeof(char)*(f_status.st_size+1));
[375]3753      FILE* f=fopen(cached,"rb");
[490]3754      fread(fcontent,f_status.st_size,1,f);
[281]3755      fsize=f_status.st_size;
[392]3756      fcontent[fsize]=0;
[446]3757      fclose(f);
[550]3758      addToMap(*content,"cache_file",cached);
[281]3759    }
[446]3760    cached[strlen(cached)-1]='m';
3761    s=stat(cached, &f_status);
3762    if(s==0){
3763      mimeType=(char*)malloc(sizeof(char)*(f_status.st_size+1));
3764      FILE* f=fopen(cached,"rb");
[490]3765      fread(mimeType,f_status.st_size,1,f);
[446]3766      mimeType[f_status.st_size]=0;
3767      fclose(f);
3768    }
[550]3769
[281]3770  }else{
[492]3771    hInternet->waitingRequests[hInternet->nb]=strdup(url);
3772    InternetOpenUrl(hInternet,hInternet->waitingRequests[hInternet->nb],NULL,0,INTERNET_FLAG_NO_CACHE_WRITE,0);
[550]3773    maps *oreq=getMaps(*m,"orequests");
3774    if(oreq==NULL){
3775      oreq=(maps*)malloc(MAPS_SIZE);
3776      oreq->name=zStrdup("orequests");
3777      oreq->content=createMap("value",url);
3778      oreq->next=NULL;
3779      addMapsToMaps(m,oreq);
3780      freeMaps(&oreq);
3781      free(oreq);
3782    }else{
3783      setMapArray(oreq->content,"value",hInternet->nb-1,url);
3784    }
[492]3785    return 0;
[281]3786  }
[344]3787  if(fsize==0){
[471]3788    return errorException(*m, _("Unable to download the file."), "InternalError",NULL);
[344]3789  }
[446]3790  if(mimeType!=NULL){
[471]3791    addToMap(*content,"fmimeType",mimeType);
[446]3792  }
3793
[282]3794  map* tmpMap=getMapOrFill(content,"value","");
[360]3795   
[281]3796  free(tmpMap->value);
[550]3797
[281]3798  tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
[379]3799  if(tmpMap->value==NULL)
[478]3800    return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);
[392]3801  memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
[550]3802
[281]3803  char ltmp1[256];
3804  sprintf(ltmp1,"%d",fsize);
[471]3805  addToMap(*content,"size",ltmp1);
[550]3806  if(cached==NULL){
[471]3807    addToCache(*m,url,fcontent,mimeType,fsize);
[550]3808  }
3809  else{
[492]3810    addToMap(*content,"isCached","true");
[550]3811
3812    map* tmp=getMapFromMaps(*m,"main","cacheDir");
3813    if(tmp!=NULL){
3814      map *c=getMap((*content),"xlink:href");
3815      char* md5str=getMd5(c->value);
3816      char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
3817      sprintf(fname,"%s/%s.zca",tmp->value,md5str);
3818      addToMap(*content,"cache_file",fname);
3819      free(fname);
3820    }
3821  }
[490]3822  free(fcontent);
3823  free(mimeType);
3824  free(cached);
[364]3825  return 0;
[281]3826}
3827
[579]3828/**
3829 * Read a file using the GDAL VSI API
3830 *
3831 * @param conf the maps containing the settings of the main.cfg file
3832 * @param dataSource the datasource name to read
3833 * @warning make sure to free ressources returned by this function
3834 */
[469]3835char *readVSIFile(maps* conf,const char* dataSource){
3836    VSILFILE * fichier=VSIFOpenL(dataSource,"rb");
3837    VSIStatBufL file_status;
3838    VSIStatL(dataSource, &file_status);
3839    if(fichier==NULL){
3840      char tmp[1024];
[576]3841      sprintf(tmp,"Failed to open file %s for reading purpose. File seems empty %lld.",
[469]3842              dataSource,file_status.st_size);
3843      setMapInMaps(conf,"lenv","message",tmp);
3844      return NULL;
3845    }
3846    char *res1=(char *)malloc(file_status.st_size*sizeof(char));
[490]3847    VSIFReadL(res1,1,file_status.st_size*sizeof(char),fichier);
3848    res1[file_status.st_size-1]=0;
[469]3849    VSIFCloseL(fichier);
3850    VSIUnlink(dataSource);
3851    return res1;
3852}
3853
[579]3854/**
3855 * Extract the service identifier from the full service identifier
3856 * ie:
3857 *  - Full service name: OTB.BandMath
3858 *  - Service name: BandMath
3859 *
3860 * @param conf the maps containing the settings of the main.cfg file
3861 * @param conf_dir the full path to the ZOO-Kernel directory
3862 * @param identifier the full service name (potentialy including a prefix, ie:
3863 *  Prefix.MyService)
3864 * @param buffer the resulting service identifier (without any prefix)
3865 */
[469]3866void parseIdentifier(maps* conf,char* conf_dir,char *identifier,char* buffer){
[539]3867  setMapInMaps(conf,"lenv","oIdentifier",identifier);
3868  char *lid=zStrdup(identifier);
[469]3869  char *saveptr1;
[539]3870  char *tmps1=strtok_r(lid,".",&saveptr1);
[469]3871  int level=0;
3872  char key[25];
3873  char levels[18];
3874  while(tmps1!=NULL){
3875    char *test=zStrdup(tmps1);
3876    char* tmps2=(char*)malloc((strlen(test)+2)*sizeof(char));
3877    sprintf(key,"sprefix_%d",level);
3878    sprintf(tmps2,"%s.",test);
3879    sprintf(levels,"%d",level);
3880    setMapInMaps(conf,"lenv","level",levels);
3881    setMapInMaps(conf,"lenv",key,tmps2);
3882    free(tmps2);
[470]3883    free(test);
[469]3884    level++;
3885    tmps1=strtok_r(NULL,".",&saveptr1);
3886  }
3887  int i=0;
3888  sprintf(buffer,"%s",conf_dir);
3889  for(i=0;i<level;i++){
3890    char *tmp0=zStrdup(buffer);
3891    sprintf(key,"sprefix_%d",i);
3892    map* tmp00=getMapFromMaps(conf,"lenv",key);
[503]3893    if(tmp00!=NULL)
3894      sprintf(buffer,"%s/%s",tmp0,tmp00->value);
[469]3895    free(tmp0);
3896    buffer[strlen(buffer)-1]=0;
3897    if(i+1<level){
3898      map* tmpMap=getMapFromMaps(conf,"lenv","metapath");
3899      if(tmpMap==NULL || strlen(tmpMap->value)==0){
3900        char *tmp01=zStrdup(tmp00->value);
[505]3901        tmp01[strlen(tmp01)-1]=0;
[469]3902        setMapInMaps(conf,"lenv","metapath",tmp01);
3903        free(tmp01);
[503]3904        tmp01=NULL;
[469]3905      }
3906      else{
[503]3907        if(tmp00!=NULL && tmpMap!=NULL){
[505]3908          char *tmp00s=zStrdup(tmp00->value);
3909          tmp00s[strlen(tmp00s)-1]=0;
3910          char *value=(char*)malloc((strlen(tmp00s)+strlen(tmpMap->value)+2)*sizeof(char));
3911          sprintf(value,"%s/%s",tmpMap->value,tmp00s);
[503]3912          setMapInMaps(conf,"lenv","metapath",value);
3913          free(value);
[505]3914          free(tmp00s);
[503]3915          value=NULL;
3916        }
[469]3917      }
3918    }else{
[470]3919      char *tmp01=zStrdup(tmp00->value);
3920      tmp01[strlen(tmp01)-1]=0;
3921      setMapInMaps(conf,"lenv","Identifier",tmp01);
3922      free(tmp01);
[469]3923    }
3924  }
3925  char *tmp0=zStrdup(buffer);
3926  sprintf(buffer,"%s.zcfg",tmp0);
3927  free(tmp0);
[539]3928  free(lid);
[469]3929}
3930
[579]3931/**
3932 * Update the status of an ongoing service
3933 *
3934 * @param conf the maps containing the settings of the main.cfg file
3935 * @param percentCompleted percentage of completude of execution of the service
3936 * @param message information about the current step executed
3937 * @return the value of _updateStatus
3938 * @see _updateStatus
3939 */
[471]3940int updateStatus( maps* conf, const int percentCompleted, const char* message ){
3941  char tmp[4];
3942  snprintf(tmp,4,"%d",percentCompleted);
3943  setMapInMaps( conf, "lenv", "status", tmp );
3944  setMapInMaps( conf, "lenv", "message", message);
3945  return _updateStatus( conf );
3946}
3947
[579]3948/**
3949 * Access an input value
3950 *
3951 * @param inputs the maps to search for the input value
3952 * @param parameterName the input name to fetch the value
3953 * @param numberOfBytes the resulting size of the value to add (for binary
3954 *  values), -1 for basic char* data
3955 * @return a pointer to the input value if found, NULL in other case.
3956 */
[471]3957char* getInputValue( maps* inputs, const char* parameterName, size_t* numberOfBytes){
3958  map* res=getMapFromMaps(inputs,parameterName,"value");
3959  if(res!=NULL){
3960    map* size=getMapFromMaps(inputs,parameterName,"size");
3961    if(size!=NULL){
3962      *numberOfBytes=(size_t)atoi(size->value);
3963      return res->value;
3964    }else{
3965      *numberOfBytes=strlen(res->value);
3966      return res->value;
3967    }
3968  }
3969  return NULL;
3970}
3971
[579]3972/**
3973 * Set an output value
3974 *
3975 * @param outputs the maps to define the output value
3976 * @param parameterName the output name to set the value
3977 * @param data the value to set
3978 * @param numberOfBytes size of the value to add (for binary values), -1 for
3979 *  basic char* data
3980 * @return 0
3981 */
[471]3982int  setOutputValue( maps* outputs, const char* parameterName, char* data, size_t numberOfBytes ){
3983  if(numberOfBytes==-1){
3984    setMapInMaps(outputs,parameterName,"value",data);
3985  }else{
3986    char size[1024];
3987    map* tmp=getMapFromMaps(outputs,parameterName,"value");
[539]3988    if(tmp==NULL){
3989      setMapInMaps(outputs,parameterName,"value","");
3990      tmp=getMapFromMaps(outputs,parameterName,"value");
3991    }
[471]3992    free(tmp->value);
3993    tmp->value=(char*) malloc((numberOfBytes+1)*sizeof(char));
3994    memcpy(tmp->value,data,numberOfBytes);
[490]3995    sprintf(size,"%lu",numberOfBytes);
[471]3996    setMapInMaps(outputs,parameterName,"size",size);
3997  }
3998  return 0;
3999}
[576]4000
4001/**
4002 * Verify if a parameter value is valid.
4003 *
4004 * @param request the request map
4005 * @param res the error map potentially generated
[579]4006 * @param toCheck the parameter to use
[576]4007 * @param avalues the acceptable values (or null if testing only for presence)
4008 * @param mandatory verify the presence of the parameter if mandatory > 0
4009 */
4010void checkValidValue(map* request,map** res,const char* toCheck,const char** avalues,int mandatory){
4011  map* lres=*res;
4012  map* r_inputs = getMap (request,toCheck);
4013  if (r_inputs == NULL){
4014    if(mandatory>0){
4015      char *replace=_("Mandatory parameter <%s> was not specified");
4016      char *message=(char*)malloc((strlen(replace)+strlen(toCheck)+1)*sizeof(char));
4017      sprintf(message,replace,toCheck);
4018      if(lres==NULL){
4019        lres=createMap("code","MissingParameterValue");
4020        addToMap(lres,"text",message);
4021        addToMap(lres,"locator",toCheck);       
4022      }else{
4023        int length=1;
4024        map* len=getMap(lres,"length");
4025        if(len!=NULL){
4026          length=atoi(len->value);
4027        }
4028        setMapArray(lres,"text",length,message);
4029        setMapArray(lres,"locator",length,toCheck);
4030        setMapArray(lres,"code",length,"MissingParameter");
4031      }
4032      free(message);
4033    }
4034  }else{
4035    if(avalues==NULL)
4036      return;
4037    int nb=0;
4038    int hasValidValue=-1;
4039    while(avalues[nb]!=NULL){
4040      if(strcasecmp(avalues[nb],r_inputs->value)==0){
4041        hasValidValue=1;
4042        break;
4043      }
4044      nb++;
4045    }
4046    if(hasValidValue<0){
4047      char *replace=_("Ununderstood <%s> value, %s %s the only acceptable value.");
4048      nb=0;
4049      char *vvalues=NULL;
4050      char* num=_("is");
4051      while(avalues[nb]!=NULL){
4052        char *tvalues;
4053        if(vvalues==NULL){
4054          vvalues=(char*)malloc((strlen(avalues[nb])+3)*sizeof(char));
4055          sprintf(vvalues,"%s",avalues[nb]);
4056        }
4057        else{
4058          tvalues=zStrdup(vvalues);
4059          vvalues=(char*)realloc(vvalues,(strlen(tvalues)+strlen(avalues[nb])+3)*sizeof(char));
4060          sprintf(vvalues,"%s, %s",tvalues,avalues[nb]);
4061          free(tvalues);
4062          num=_("are");
4063        }
4064        nb++;
4065      }
4066      char *message=(char*)malloc((strlen(replace)+strlen(num)+strlen(vvalues)+strlen(toCheck)+1)*sizeof(char));
4067      sprintf(message,replace,toCheck,vvalues,num);
4068      if(lres==NULL){
4069        lres=createMap("code","InvalidParameterValue");
4070        addToMap(lres,"text",message);
4071        addToMap(lres,"locator",toCheck);       
4072      }else{
4073        int length=1;
4074        map* len=getMap(lres,"length");
4075        if(len!=NULL){
4076          length=atoi(len->value);
4077        }
4078        setMapArray(lres,"text",length,message);
4079        setMapArray(lres,"locator",length,toCheck);
4080        setMapArray(lres,"code",length,"InvalidParameterValue");
4081      }
4082    }
4083  }
4084  if(lres!=NULL){
4085    *res=lres;
4086  }
4087}
[578]4088
[579]4089/**
4090 * Access the last error message returned by the OS when trying to dynamically
4091 * load a shared library.
4092 *
4093 * @return the last error message
4094 * @warning The character string returned from getLastErrorMessage resides
[578]4095 * in a static buffer. The application should not write to this
4096 * buffer or attempt to free() it.
4097 */ 
[579]4098char* getLastErrorMessage() {                                             
4099#ifdef WIN32
4100  LPVOID lpMsgBuf;
4101  DWORD errCode = GetLastError();
4102  static char msg[ERROR_MSG_MAX_LENGTH];
4103  size_t i;
4104 
4105  DWORD length = FormatMessage(
4106                               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
4107                               FORMAT_MESSAGE_FROM_SYSTEM |
4108                               FORMAT_MESSAGE_IGNORE_INSERTS,
4109                               NULL,
4110                               errCode,
4111                               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
4112                               (LPTSTR) &lpMsgBuf,
4113                               0, NULL );       
4114 
4115#ifdef UNICODE         
4116  wcstombs_s( &i, msg, ERROR_MSG_MAX_LENGTH,
4117              (wchar_t*) lpMsgBuf, _TRUNCATE );
[578]4118#else
[579]4119  strcpy_s( msg, ERROR_MSG_MAX_LENGTH,
4120            (char *) lpMsgBuf );               
4121#endif 
4122  LocalFree(lpMsgBuf);
4123 
4124  return msg;
4125#else
4126  return dlerror();
[578]4127#endif
[579]4128}
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