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

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

Fix issue with OTB multiple inputs potentially encoded in base64.

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