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

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

Fix issue when adding map with size in a map array.

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