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

Last change on this file since 601 was 601, checked in by knut, 9 years ago

Implemented default result file extensions for many MIME types, based on Apache's mime.types list. Added file mimetypes.h. Made function printIOType more general with respect to media content. Rewrote the XML parsing of the <ResponseDocument?> block in Execute requests to fix problem caused by one output variable inheriting properties from another. Minor memory allocation modification in zoo_loader.c.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 114.0 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
1228 * @param nc the XML node to add the Process node
1229 * @param serv the service structure created from the zcfg file
1230 * @return the generated wps:ProcessOfferings xmlNodePtr
1231 */
[1]1232void printGetCapabilitiesForProcess(maps* m,xmlNodePtr nc,service* serv){
[9]1233  xmlNsPtr ns,ns_ows,ns_xlink;
[490]1234  xmlNodePtr n=NULL,nc1,nc2;
[9]1235  /**
1236   * Initialize or get existing namspaces
1237   */
1238  int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");
1239  ns=usedNs[wpsId];
1240  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
1241  ns_ows=usedNs[owsId];
1242  int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
1243  ns_xlink=usedNs[xlinkId];
[1]1244
1245  map* tmp1;
1246  if(serv->content!=NULL){
1247    nc1 = xmlNewNode(ns, BAD_CAST "Process");
1248    tmp1=getMap(serv->content,"processVersion");
1249    if(tmp1!=NULL)
[9]1250      xmlNewNsProp(nc1,ns,BAD_CAST "processVersion",BAD_CAST tmp1->value);
[469]1251    map* tmp3=getMapFromMaps(m,"lenv","level");
1252    addPrefix(m,tmp3,serv);
[1]1253    printDescription(nc1,ns_ows,serv->name,serv->content);
1254    tmp1=serv->metadata;
1255    while(tmp1!=NULL){
1256      nc2 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
[9]1257      xmlNewNsProp(nc2,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
[1]1258      xmlAddChild(nc1,nc2);
1259      tmp1=tmp1->next;
1260    }
1261    xmlAddChild(nc,nc1);
1262  }
1263}
1264
[579]1265/**
1266 * Generate a ProcessDescription node for a servie and add it to a given node.
1267 *
1268 * @param m the conf maps containing the main.cfg settings
1269 * @param nc the XML node to add the Process node
1270 * @param serv the servive structure created from the zcfg file
1271 * @return the generated wps:ProcessOfferings xmlNodePtr
1272 */
[469]1273void printDescribeProcessForProcess(maps* m,xmlNodePtr nc,service* serv){
[490]1274  xmlNsPtr ns,ns_ows,ns_xlink;
1275  xmlNodePtr n,nc1;
[1]1276
1277  n=nc;
1278 
[9]1279  int wpsId=zooXmlAddNs(NULL,"http://schemas.opengis.net/wps/1.0.0","wps");
1280  ns=usedNs[wpsId];
1281  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
1282  ns_ows=usedNs[owsId];
1283  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
1284  ns_xlink=usedNs[xlinkId];
[1]1285
1286  nc = xmlNewNode(NULL, BAD_CAST "ProcessDescription");
[490]1287  const char *tmp4[3];
[1]1288  tmp4[0]="processVersion";
1289  tmp4[1]="storeSupported";
1290  tmp4[2]="statusSupported";
1291  int j=0;
1292  map* tmp1=NULL;
1293  for(j=0;j<3;j++){
[9]1294    tmp1=getMap(serv->content,tmp4[j]);
[1]1295    if(tmp1!=NULL){
1296      if(j==0)
[9]1297        xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp1->value);     
[1]1298      else
1299        xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST tmp1->value);     
1300    }
1301    else{
1302      if(j>0)
1303        xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST "false");     
1304    }
1305  }
1306 
[469]1307  tmp1=getMapFromMaps(m,"lenv","level");
1308  addPrefix(m,tmp1,serv);
[9]1309  printDescription(nc,ns_ows,serv->name,serv->content);
[1]1310
[9]1311  tmp1=serv->metadata;
[1]1312  while(tmp1!=NULL){
1313    nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
[9]1314    xmlNewNsProp(nc1,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
[1]1315    xmlAddChild(nc,nc1);
1316    tmp1=tmp1->next;
1317  }
1318
[9]1319  tmp1=getMap(serv->content,"Profile");
[1]1320  if(tmp1!=NULL){
1321    nc1 = xmlNewNode(ns, BAD_CAST "Profile");
1322    xmlAddChild(nc1,xmlNewText(BAD_CAST tmp1->value));
1323    xmlAddChild(nc,nc1);
1324  }
1325
[471]1326  if(serv->inputs!=NULL){
1327    nc1 = xmlNewNode(NULL, BAD_CAST "DataInputs");
1328    elements* e=serv->inputs;
[490]1329    printFullDescription(1,e,"Input",ns_ows,nc1);
[471]1330    xmlAddChild(nc,nc1);
1331  }
[1]1332
[76]1333  nc1 = xmlNewNode(NULL, BAD_CAST "ProcessOutputs");
[471]1334  elements* e=serv->outputs;
[490]1335  printFullDescription(0,e,"Output",ns_ows,nc1);
[76]1336  xmlAddChild(nc,nc1);
[1]1337
[76]1338  xmlAddChild(n,nc);
[1]1339
[76]1340}
[1]1341
[579]1342/**
1343 * Generate the required XML tree for the detailled metadata informations of
1344 * inputs or outputs
1345 *
1346 * @param in 1 in case of inputs, 0 for outputs
1347 * @param elem the elements structure containing the metadata informations
1348 * @param type the name ("Input" or "Output") of the XML node to create
1349 * @param ns_ows the ows XML namespace
1350 * @param nc1 the XML node to use to add the created tree
1351 */
[490]1352void printFullDescription(int in,elements *elem,const char* type,xmlNsPtr ns_ows,xmlNodePtr nc1){
1353  const char *orderedFields[13];
[76]1354  orderedFields[0]="mimeType";
1355  orderedFields[1]="encoding";
1356  orderedFields[2]="schema";
1357  orderedFields[3]="dataType";
1358  orderedFields[4]="uom";
1359  orderedFields[5]="CRS";
1360  orderedFields[6]="value";
[459]1361  orderedFields[7]="AllowedValues";
[465]1362  orderedFields[8]="range";
1363  orderedFields[9]="rangeMin";
1364  orderedFields[10]="rangeMax";
1365  orderedFields[11]="rangeClosure";
1366  orderedFields[12]="rangeSpace";
[76]1367
[471]1368  xmlNodePtr nc2,nc3,nc4,nc5,nc6,nc7,nc8,nc9;
[76]1369  elements* e=elem;
[471]1370
[76]1371  map* tmp1=NULL;
[1]1372  while(e!=NULL){
[76]1373    int default1=0;
1374    int isAnyValue=1;
1375    nc2 = xmlNewNode(NULL, BAD_CAST type);
[471]1376    if(strncmp(type,"Input",5)==0){
1377      tmp1=getMap(e->content,"minOccurs");
1378      if(tmp1!=NULL){
1379        xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
1380      }else
1381        xmlNewProp(nc2,BAD_CAST "minOccurs",BAD_CAST "0");
1382      tmp1=getMap(e->content,"maxOccurs");
1383      if(tmp1!=NULL){
1384        if(strcasecmp(tmp1->value,"unbounded")!=0)
1385          xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
1386        else
1387          xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1000");
1388      }else
1389        xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1");
[485]1390      if((tmp1=getMap(e->content,"maximumMegabytes"))!=NULL){
1391        xmlNewProp(nc2,BAD_CAST "maximumMegabytes",BAD_CAST tmp1->value);
1392      }
[1]1393    }
1394
1395    printDescription(nc2,ns_ows,e->name,e->content);
1396
[471]1397    /**
1398     * Build the (Literal/Complex/BoundingBox)Data node
1399     */
[76]1400    if(strncmp(type,"Output",6)==0){
1401      if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0)
1402        nc3 = xmlNewNode(NULL, BAD_CAST "LiteralOutput");
1403      else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
[1]1404        nc3 = xmlNewNode(NULL, BAD_CAST "ComplexOutput");
[76]1405      else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
1406        nc3 = xmlNewNode(NULL, BAD_CAST "BoundingBoxOutput");
[1]1407      else
1408        nc3 = xmlNewNode(NULL, BAD_CAST e->format);
[76]1409    }else{
[79]1410      if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0){
[76]1411        nc3 = xmlNewNode(NULL, BAD_CAST "LiteralData");
[79]1412      }
[76]1413      else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
1414        nc3 = xmlNewNode(NULL, BAD_CAST "ComplexData");
1415      else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
1416        nc3 = xmlNewNode(NULL, BAD_CAST "BoundingBoxData");
1417      else
1418        nc3 = xmlNewNode(NULL, BAD_CAST e->format);
1419    }
[471]1420
[465]1421    iotype* _tmp0=NULL;
[1]1422    iotype* _tmp=e->defaults;
1423    int datatype=0;
[79]1424    bool hasUOM=false;
[471]1425    bool hasUOM1=false;
[1]1426    if(_tmp!=NULL){
[79]1427      if(strcmp(e->format,"LiteralOutput")==0 ||
1428         strcmp(e->format,"LiteralData")==0){
[1]1429        datatype=1;
1430        nc4 = xmlNewNode(NULL, BAD_CAST "UOMs");
1431        nc5 = xmlNewNode(NULL, BAD_CAST "Default");
[79]1432      }
1433      else if(strcmp(e->format,"BoundingBoxOutput")==0 ||
1434              strcmp(e->format,"BoundingBoxData")==0){
1435        datatype=2;
1436        nc5 = xmlNewNode(NULL, BAD_CAST "Default");
1437      }
1438      else{
1439        nc4 = xmlNewNode(NULL, BAD_CAST "Default");
1440        nc5 = xmlNewNode(NULL, BAD_CAST "Format");
1441      }
1442     
1443      tmp1=_tmp->content;
[459]1444
[471]1445      if((tmp1=getMap(_tmp->content,"DataType"))!=NULL){
1446        nc8 = xmlNewNode(ns_ows, BAD_CAST "DataType");
1447        xmlAddChild(nc8,xmlNewText(BAD_CAST tmp1->value));
1448        char tmp[1024];
1449        sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
1450        xmlNewNsProp(nc8,ns_ows,BAD_CAST "reference",BAD_CAST tmp);
1451        xmlAddChild(nc3,nc8);
1452        datatype=1;
1453      }
1454     
1455      if(strncmp(type,"Input",5)==0){
[465]1456
[471]1457        if((tmp1=getMap(_tmp->content,"AllowedValues"))!=NULL){
1458          nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
1459          char *token,*saveptr1;
1460          token=strtok_r(tmp1->value,",",&saveptr1);
1461          while(token!=NULL){
1462            nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
1463            char *tmps=strdup(token);
1464            tmps[strlen(tmps)]=0;
1465            xmlAddChild(nc7,xmlNewText(BAD_CAST tmps));
1466            free(tmps);
1467            xmlAddChild(nc6,nc7);
1468            token=strtok_r(NULL,",",&saveptr1);
1469          }
1470          if(getMap(_tmp->content,"range")!=NULL ||
1471             getMap(_tmp->content,"rangeMin")!=NULL ||
1472             getMap(_tmp->content,"rangeMax")!=NULL ||
1473             getMap(_tmp->content,"rangeClosure")!=NULL )
1474            goto doRange;
1475          xmlAddChild(nc3,nc6);
1476          isAnyValue=-1;
1477        }
[465]1478
[471]1479        tmp1=getMap(_tmp->content,"range");
1480        if(tmp1==NULL)
1481          tmp1=getMap(_tmp->content,"rangeMin");
1482        if(tmp1==NULL)
1483          tmp1=getMap(_tmp->content,"rangeMax");
1484       
1485        if(tmp1!=NULL && isAnyValue==1){
1486          nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
1487        doRange:
1488         
1489          /**
1490           * Range: Table 46 OGC Web Services Common Standard
1491           */
1492          nc8 = xmlNewNode(ns_ows, BAD_CAST "Range");
1493         
1494          map* tmp0=getMap(tmp1,"range");
1495          if(tmp0!=NULL){
1496            char* pToken;
1497            char* orig=zStrdup(tmp0->value);
1498            /**
1499             * RangeClosure: Table 47 OGC Web Services Common Standard
1500             */
[490]1501            const char *tmp="closed";
[471]1502            if(orig[0]=='[' && orig[strlen(orig)-1]=='[')
1503              tmp="closed-open";
1504            else
1505              if(orig[0]==']' && orig[strlen(orig)-1]==']')
1506                tmp="open-closed";
1507              else
1508                if(orig[0]==']' && orig[strlen(orig)-1]=='[')
1509                  tmp="open";
1510            xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
1511            pToken=strtok(orig,",");
1512            int nci0=0;
1513            while(pToken!=NULL){
1514              char *tmpStr=(char*) malloc((strlen(pToken))*sizeof(char));
1515              if(nci0==0){
1516                nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
[507]1517                strncpy( tmpStr, pToken+1, strlen(pToken)-1 );
1518                tmpStr[strlen(pToken)-1] = '\0';
1519              }else{
[471]1520                nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
[507]1521                const char* bkt;
1522                if ( ( bkt = strchr(pToken, '[') ) != NULL || ( bkt = strchr(pToken, ']') ) != NULL ){
1523                    strncpy( tmpStr, pToken, bkt - pToken );
1524                    tmpStr[bkt - pToken] = '\0';
1525                  }
[459]1526              }
[471]1527              xmlAddChild(nc7,xmlNewText(BAD_CAST tmpStr));
1528              free(tmpStr);
1529              xmlAddChild(nc8,nc7);
1530              nci0++;
1531              pToken = strtok(NULL,",");
1532            }               
1533            if(getMap(tmp1,"rangeSpacing")==NULL){
1534              nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
1535              xmlAddChild(nc7,xmlNewText(BAD_CAST "1"));
1536              xmlAddChild(nc8,nc7);
[79]1537            }
[471]1538            free(orig);
1539          }else{
1540           
1541            tmp0=getMap(tmp1,"rangeMin");
1542            if(tmp0!=NULL){
1543              nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
1544              xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1545              xmlAddChild(nc8,nc7);
1546            }else{
1547              nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
1548              xmlAddChild(nc8,nc7);
[79]1549            }
[471]1550            tmp0=getMap(tmp1,"rangeMax");
1551            if(tmp0!=NULL){
1552              nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
1553              xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1554              xmlAddChild(nc8,nc7);
1555            }else{
1556              nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
1557              xmlAddChild(nc8,nc7);
1558            }
1559            tmp0=getMap(tmp1,"rangeSpacing");
1560            if(tmp0!=NULL){
1561              nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
1562              xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1563              xmlAddChild(nc8,nc7);
1564            }
1565            tmp0=getMap(tmp1,"rangeClosure");
1566            if(tmp0!=NULL){
[490]1567              const char *tmp="closed";
[471]1568              if(strcasecmp(tmp0->value,"co")==0)
1569                tmp="closed-open";
1570              else
1571                if(strcasecmp(tmp0->value,"oc")==0)
1572                  tmp="open-closed";
1573                else
1574                  if(strcasecmp(tmp0->value,"o")==0)
1575                    tmp="open";
1576              xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
1577            }else
1578              xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST "closed");
1579          }
1580          if(_tmp0==NULL){
1581            xmlAddChild(nc6,nc8);
1582            _tmp0=e->supported;
[507]1583            if(_tmp0!=NULL &&
1584               (getMap(_tmp0->content,"range")!=NULL ||
1585                getMap(_tmp0->content,"rangeMin")!=NULL ||
1586                getMap(_tmp0->content,"rangeMax")!=NULL ||
1587                getMap(_tmp0->content,"rangeClosure")!=NULL )){
[476]1588              tmp1=_tmp0->content;
1589              goto doRange;
1590            }
[79]1591          }else{
[471]1592            _tmp0=_tmp0->next;
1593            if(_tmp0!=NULL){
1594              xmlAddChild(nc6,nc8);
[476]1595              if(getMap(_tmp0->content,"range")!=NULL ||
1596                 getMap(_tmp0->content,"rangeMin")!=NULL ||
1597                 getMap(_tmp0->content,"rangeMax")!=NULL ||
1598                 getMap(_tmp0->content,"rangeClosure")!=NULL ){
1599                tmp1=_tmp0->content;
1600                goto doRange;
1601              }
[79]1602            }
1603          }
[471]1604          xmlAddChild(nc6,nc8);
1605          xmlAddChild(nc3,nc6);
1606          isAnyValue=-1;
[1]1607        }
[471]1608       
1609      }
1610   
1611     
1612    int oI=0;
1613    for(oI=0;oI<13;oI++)
1614      if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
1615#ifdef DEBUG
1616        printf("DATATYPE DEFAULT ? %s\n",tmp1->name);
1617#endif
1618        if(strcmp(tmp1->name,"asReference")!=0 &&
1619           strncasecmp(tmp1->name,"DataType",8)!=0 &&
1620           strcasecmp(tmp1->name,"extension")!=0 &&
1621           strcasecmp(tmp1->name,"value")!=0 &&
1622           strcasecmp(tmp1->name,"AllowedValues")!=0 &&
1623           strncasecmp(tmp1->name,"range",5)!=0){
1624          if(datatype!=1){
1625            char *tmp2=zCapitalize1(tmp1->name);
1626            nc9 = xmlNewNode(NULL, BAD_CAST tmp2);
1627            free(tmp2);
1628          }
1629          else{
1630            char *tmp2=zCapitalize(tmp1->name);
1631            nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);
1632            free(tmp2);
1633          }
1634          xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));
1635          xmlAddChild(nc5,nc9);
1636          if(strcasecmp(tmp1->name,"uom")==0)
1637            hasUOM1=true;
1638          hasUOM=true;
1639        }else 
1640         
1641          tmp1=tmp1->next;
1642      }
1643   
1644   
1645      if(datatype!=2){
1646        if(hasUOM==true){
1647          xmlAddChild(nc4,nc5);
1648          xmlAddChild(nc3,nc4);
1649        }else{
1650          if(hasUOM1==false){
1651            xmlFreeNode(nc5);
1652            if(datatype==1)
1653              xmlFreeNode(nc4);
1654          }
[459]1655        }
[471]1656      }else{
1657        xmlAddChild(nc3,nc5);
[459]1658      }
[465]1659     
[471]1660      if(datatype!=1 && default1<0){
1661        xmlFreeNode(nc5);
1662        if(datatype!=2)
1663          xmlFreeNode(nc4);
1664      }
1665
[465]1666      map* metadata=e->metadata;
[490]1667      xmlNodePtr n=NULL;
[465]1668      int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
1669      xmlNsPtr ns_xlink=usedNs[xlinkId];
1670
1671      while(metadata!=NULL){
[471]1672        nc6=xmlNewNode(ns_ows, BAD_CAST "Metadata");
[465]1673        xmlNewNsProp(nc6,ns_xlink,BAD_CAST metadata->name,BAD_CAST metadata->value);
1674        xmlAddChild(nc2,nc6);
1675        metadata=metadata->next;
1676      }
[471]1677
[1]1678    }
[280]1679
[1]1680    _tmp=e->supported;
[471]1681    if(_tmp==NULL && datatype!=1)
[280]1682      _tmp=e->defaults;
1683
[71]1684    int hasSupported=-1;
[471]1685
[1]1686    while(_tmp!=NULL){
[71]1687      if(hasSupported<0){
1688        if(datatype==0){
1689          nc4 = xmlNewNode(NULL, BAD_CAST "Supported");
1690          nc5 = xmlNewNode(NULL, BAD_CAST "Format");
1691        }
1692        else
1693          nc5 = xmlNewNode(NULL, BAD_CAST "Supported");
1694        hasSupported=0;
1695      }else
[76]1696        if(datatype==0)
1697          nc5 = xmlNewNode(NULL, BAD_CAST "Format");
[1]1698      tmp1=_tmp->content;
[71]1699      int oI=0;
[76]1700      for(oI=0;oI<6;oI++)
[71]1701        if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
[1]1702#ifdef DEBUG
[71]1703          printf("DATATYPE SUPPORTED ? %s\n",tmp1->name);
[1]1704#endif
[71]1705          if(strcmp(tmp1->name,"asReference")!=0 && 
[471]1706             strcmp(tmp1->name,"value")!=0 && 
[71]1707             strcmp(tmp1->name,"DataType")!=0 &&
1708             strcasecmp(tmp1->name,"extension")!=0){
[76]1709            if(datatype!=1){
[71]1710              char *tmp2=zCapitalize1(tmp1->name);
1711              nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
1712              free(tmp2);
1713            }
1714            else{
1715              char *tmp2=zCapitalize(tmp1->name);
1716              nc6 = xmlNewNode(ns_ows, BAD_CAST tmp2);
1717              free(tmp2);
1718            }
[76]1719            if(datatype==2){
1720              char *tmpv,*tmps;
1721              tmps=strtok_r(tmp1->value,",",&tmpv);
1722              while(tmps){
1723                xmlAddChild(nc6,xmlNewText(BAD_CAST tmps));
1724                tmps=strtok_r(NULL,",",&tmpv);
1725                if(tmps){
1726                  char *tmp2=zCapitalize1(tmp1->name);
1727                  nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
1728                  free(tmp2);
1729                }
1730              }
1731            }
1732            else{
1733              xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
1734            }
[471]1735            xmlAddChild(nc5,nc6);
[9]1736          }
[71]1737          tmp1=tmp1->next;
[1]1738        }
[71]1739      if(hasSupported<=0){
[471]1740        if(datatype==0){
[71]1741          xmlAddChild(nc4,nc5);
1742          xmlAddChild(nc3,nc4);
[471]1743        }else{
1744          if(datatype!=1)
1745            xmlAddChild(nc3,nc5);
1746        }
[71]1747        hasSupported=1;
[1]1748      }
[71]1749      else
[471]1750        if(datatype==0){
[76]1751          xmlAddChild(nc4,nc5);
[471]1752          xmlAddChild(nc3,nc4);
[76]1753        }
1754        else
[471]1755          if(datatype!=1)
1756            xmlAddChild(nc3,nc5);
1757
[76]1758      _tmp=_tmp->next;
[1]1759    }
[471]1760
1761    if(hasSupported==0){
1762      if(datatype==0)
1763        xmlFreeNode(nc4);
1764      xmlFreeNode(nc5);
1765    }
1766
1767    _tmp=e->defaults;
1768    if(datatype==1 && hasUOM1==true){
1769      xmlAddChild(nc4,nc5);
1770      xmlAddChild(nc3,nc4);
1771    }
1772
[490]1773    if(in>0 && datatype==1 &&
[471]1774       getMap(_tmp->content,"AllowedValues")==NULL &&
1775       getMap(_tmp->content,"range")==NULL &&
1776       getMap(_tmp->content,"rangeMin")==NULL &&
1777       getMap(_tmp->content,"rangeMax")==NULL &&
1778       getMap(_tmp->content,"rangeClosure")==NULL ){
1779      tmp1=getMap(_tmp->content,"dataType");
[542]1780      if(tmp1!=NULL && strcasecmp(tmp1->value,"boolean")==0){
1781        nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
1782        nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
1783        xmlAddChild(nc7,xmlNewText(BAD_CAST "true"));
1784        xmlAddChild(nc6,nc7);
1785        nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
1786        xmlAddChild(nc7,xmlNewText(BAD_CAST "false"));
1787        xmlAddChild(nc6,nc7);
1788        xmlAddChild(nc3,nc6);
1789      }
1790      else
1791        xmlAddChild(nc3,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
[471]1792    }
1793   
1794    if((tmp1=getMap(_tmp->content,"value"))!=NULL){
1795      nc7 = xmlNewNode(NULL, BAD_CAST "DefaultValue");
1796      xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value));
1797      xmlAddChild(nc3,nc7);
1798    }
1799   
[1]1800    xmlAddChild(nc2,nc3);
1801   
1802    xmlAddChild(nc1,nc2);
1803   
1804    e=e->next;
1805  }
1806}
1807
[579]1808/**
1809 * Generate a wps:Execute XML document.
1810 *
1811 * @param m the conf maps containing the main.cfg settings
1812 * @param request the map representing the HTTP request
1813 * @param pid the process identifier linked to a service
1814 * @param serv the serv structure created from the zcfg file
1815 * @param service the service name
1816 * @param status the status returned by the service
1817 * @param inputs the inputs provided
1818 * @param outputs the outputs generated by the service
1819 */
[114]1820void printProcessResponse(maps* m,map* request, int pid,service* serv,const char* service,int status,maps* inputs,maps* outputs){
[576]1821  xmlNsPtr ns,ns_ows,ns_xlink;
[490]1822  xmlNodePtr nr,n,nc,nc1=NULL,nc3;
[9]1823  xmlDocPtr doc;
1824  time_t time1; 
1825  time(&time1);
[280]1826  nr=NULL;
[9]1827  doc = xmlNewDoc(BAD_CAST "1.0");
[576]1828  n = printWPSHeader(doc,m,"Execute","ExecuteResponse");
[9]1829  int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");
1830  ns=usedNs[wpsId];
[576]1831  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
[9]1832  ns_ows=usedNs[owsId];
[576]1833  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
[9]1834  ns_xlink=usedNs[xlinkId];
[34]1835
[9]1836  char tmp[256];
[26]1837  char url[1024];
[72]1838  char stored_path[1024];
[9]1839  memset(tmp,0,256);
[72]1840  memset(url,0,1024);
1841  memset(stored_path,0,1024);
[9]1842  maps* tmp_maps=getMaps(m,"main");
1843  if(tmp_maps!=NULL){
[26]1844    map* tmpm1=getMap(tmp_maps->content,"serverAddress");
1845    /**
1846     * Check if the ZOO Service GetStatus is available in the local directory.
1847     * If yes, then it uses a reference to an URL which the client can access
1848     * to get information on the status of a running Service (using the
1849     * percentCompleted attribute).
1850     * Else fallback to the initial method using the xml file to write in ...
1851     */
1852    char ntmp[1024];
1853#ifndef WIN32
1854    getcwd(ntmp,1024);
1855#else
1856    _getcwd(ntmp,1024);
1857#endif
1858    struct stat myFileInfo;
1859    int statRes;
1860    char file_path[1024];
1861    sprintf(file_path,"%s/GetStatus.zcfg",ntmp);
1862    statRes=stat(file_path,&myFileInfo);
1863    if(statRes==0){
1864      char currentSid[128];
1865      map* tmpm=getMap(tmp_maps->content,"rewriteUrl");
1866      map *tmp_lenv=NULL;
[514]1867      tmp_lenv=getMapFromMaps(m,"lenv","usid");
[26]1868      if(tmp_lenv==NULL)
1869        sprintf(currentSid,"%i",pid);
1870      else
1871        sprintf(currentSid,"%s",tmp_lenv->value);
1872      if(tmpm==NULL || strcasecmp(tmpm->value,"false")==0){
[280]1873        sprintf(url,"%s?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
[26]1874      }else{
1875        if(strlen(tmpm->value)>0)
1876          if(strcasecmp(tmpm->value,"true")!=0)
1877            sprintf(url,"%s/%s/GetStatus/%s",tmpm1->value,tmpm->value,currentSid);
1878          else
1879            sprintf(url,"%s/GetStatus/%s",tmpm1->value,currentSid);
1880        else
[41]1881          sprintf(url,"%s/?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
[26]1882      }
1883    }else{
[514]1884      int lpid;
1885      map* tmpm2=getMapFromMaps(m,"lenv","usid");
1886      lpid=atoi(tmpm2->value);
1887      tmpm2=getMap(tmp_maps->content,"tmpUrl");
[26]1888      if(tmpm1!=NULL && tmpm2!=NULL){
[453]1889        if( strncasecmp( tmpm2->value, "http://", 7) == 0 ||
1890            strncasecmp( tmpm2->value, "https://", 8 ) == 0 ){
[514]1891          sprintf(url,"%s/%s_%i.xml",tmpm2->value,service,lpid);
[378]1892        }else
[514]1893          sprintf(url,"%s/%s/%s_%i.xml",tmpm1->value,tmpm2->value,service,lpid);
[26]1894      }
[9]1895    }
[26]1896    if(tmpm1!=NULL)
[280]1897      sprintf(tmp,"%s",tmpm1->value);
[514]1898    int lpid;
1899    tmpm1=getMapFromMaps(m,"lenv","usid");
1900    lpid=atoi(tmpm1->value);
[72]1901    tmpm1=getMapFromMaps(m,"main","TmpPath");
[514]1902    sprintf(stored_path,"%s/%s_%i.xml",tmpm1->value,service,lpid);
[9]1903  }
1904
[72]1905
[364]1906
[9]1907  xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp);
[72]1908  map* test=getMap(request,"storeExecuteResponse");
1909  bool hasStoredExecuteResponse=false;
1910  if(test!=NULL && strcasecmp(test->value,"true")==0){
[9]1911    xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url);
[72]1912    hasStoredExecuteResponse=true;
[9]1913  }
1914
1915  nc = xmlNewNode(ns, BAD_CAST "Process");
1916  map* tmp2=getMap(serv->content,"processVersion");
1917  if(tmp2!=NULL)
1918    xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp2->value);
1919 
[539]1920  map* tmpI=getMapFromMaps(m,"lenv","oIdentifier");
1921  printDescription(nc,ns_ows,tmpI->value,serv->content);
[9]1922
1923  xmlAddChild(n,nc);
1924
1925  nc = xmlNewNode(ns, BAD_CAST "Status");
1926  const struct tm *tm;
1927  size_t len;
1928  time_t now;
1929  char *tmp1;
[26]1930  map *tmpStatus;
[9]1931 
1932  now = time ( NULL );
1933  tm = localtime ( &now );
1934
1935  tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char));
1936
1937  len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
1938
[26]1939  xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
1940
1941  char sMsg[2048];
[9]1942  switch(status){
1943  case SERVICE_SUCCEEDED:
1944    nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded");
[34]1945    sprintf(sMsg,_("Service \"%s\" run successfully."),serv->name);
[26]1946    nc3=xmlNewText(BAD_CAST sMsg);
1947    xmlAddChild(nc1,nc3);
[9]1948    break;
1949  case SERVICE_STARTED:
1950    nc1 = xmlNewNode(ns, BAD_CAST "ProcessStarted");
[26]1951    tmpStatus=getMapFromMaps(m,"lenv","status");
1952    xmlNewProp(nc1,BAD_CAST "percentCompleted",BAD_CAST tmpStatus->value);
[34]1953    sprintf(sMsg,_("ZOO Service \"%s\" is currently running. Please, reload this document to get the up-to-date status of the Service."),serv->name);
[26]1954    nc3=xmlNewText(BAD_CAST sMsg);
1955    xmlAddChild(nc1,nc3);
[9]1956    break;
1957  case SERVICE_ACCEPTED:
1958    nc1 = xmlNewNode(ns, BAD_CAST "ProcessAccepted");
[34]1959    sprintf(sMsg,_("Service \"%s\" was accepted by the ZOO Kernel and it run as a background task. Please consult the statusLocation attribtue providen in this document to get the up-to-date document."),serv->name);
[26]1960    nc3=xmlNewText(BAD_CAST sMsg);
1961    xmlAddChild(nc1,nc3);
[9]1962    break;
1963  case SERVICE_FAILED:
1964    nc1 = xmlNewNode(ns, BAD_CAST "ProcessFailed");
[26]1965    map *errorMap;
1966    map *te;
1967    te=getMapFromMaps(m,"lenv","code");
1968    if(te!=NULL)
1969      errorMap=createMap("code",te->value);
1970    else
1971      errorMap=createMap("code","NoApplicableCode");
1972    te=getMapFromMaps(m,"lenv","message");
1973    if(te!=NULL)
[57]1974      addToMap(errorMap,"text",_ss(te->value));
[26]1975    else
[34]1976      addToMap(errorMap,"text",_("No more information available"));
[26]1977    nc3=createExceptionReportNode(m,errorMap,0);
[59]1978    freeMap(&errorMap);
1979    free(errorMap);
[26]1980    xmlAddChild(nc1,nc3);
[9]1981    break;
1982  default :
[34]1983    printf(_("error code not know : %i\n"),status);
[26]1984    //exit(1);
[9]1985    break;
1986  }
1987  xmlAddChild(nc,nc1);
1988  xmlAddChild(n,nc);
1989  free(tmp1);
1990
1991#ifdef DEBUG
1992  fprintf(stderr,"printProcessResponse 1 161\n");
1993#endif
1994
1995  map* lineage=getMap(request,"lineage");
[87]1996  if(lineage!=NULL && strcasecmp(lineage->value,"true")==0){
[9]1997    nc = xmlNewNode(ns, BAD_CAST "DataInputs");
1998    maps* mcursor=inputs;
[65]1999    elements* scursor=NULL;
[9]2000    while(mcursor!=NULL /*&& scursor!=NULL*/){
[65]2001      scursor=getElements(serv->inputs,mcursor->name);
[76]2002      printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Input");
[9]2003      mcursor=mcursor->next;
2004    }
2005    xmlAddChild(n,nc);
2006   
2007#ifdef DEBUG
2008    fprintf(stderr,"printProcessResponse 1 177\n");
2009#endif
2010
2011    nc = xmlNewNode(ns, BAD_CAST "OutputDefinitions");
2012    mcursor=outputs;
[65]2013    scursor=NULL;
2014    while(mcursor!=NULL){
2015      scursor=getElements(serv->outputs,mcursor->name);
[576]2016      printOutputDefinitions(doc,nc,ns,ns_ows,scursor,mcursor,"Output");
[9]2017      mcursor=mcursor->next;
2018    }
2019    xmlAddChild(n,nc);
2020  }
2021#ifdef DEBUG
2022  fprintf(stderr,"printProcessResponse 1 190\n");
2023#endif
2024
2025  /**
2026   * Display the process output only when requested !
2027   */
2028  if(status==SERVICE_SUCCEEDED){
2029    nc = xmlNewNode(ns, BAD_CAST "ProcessOutputs");
2030    maps* mcursor=outputs;
2031    elements* scursor=serv->outputs;
[379]2032    map* testResponse=getMap(request,"RawDataOutput");
2033    if(testResponse==NULL)
2034      testResponse=getMap(request,"ResponseDocument");
[63]2035    while(mcursor!=NULL){
[379]2036      map* tmp0=getMap(mcursor->content,"inRequest");
[65]2037      scursor=getElements(serv->outputs,mcursor->name);
[280]2038      if(scursor!=NULL){
[403]2039        if(testResponse==NULL || tmp0==NULL)
[379]2040          printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
2041        else
[403]2042          if(tmp0!=NULL && strncmp(tmp0->value,"true",4)==0)
[379]2043            printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
[449]2044      }else
2045        /**
2046         * In case there was no definition found in the ZCFG file but
2047         * present in the service code
2048         */
2049        printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
[9]2050      mcursor=mcursor->next;
2051    }
2052    xmlAddChild(n,nc);
2053  }
[364]2054
[507]2055  if(hasStoredExecuteResponse==true && status!=SERVICE_STARTED){
2056    semid lid=getShmLockId(m,1);
2057    if(lid<0)
[393]2058      return;
[507]2059    else{
2060#ifdef DEBUG
2061      fprintf(stderr,"LOCK %s %d !\n",__FILE__,__LINE__);
2062#endif
2063      lockShm(lid);
2064      /* We need to write the ExecuteResponse Document somewhere */
2065      FILE* output=fopen(stored_path,"w");
2066      if(output==NULL){
2067        /* If the file cannot be created return an ExceptionReport */
2068        char tmpMsg[1024];
2069        sprintf(tmpMsg,_("Unable to create the file : \"%s\" for storing the ExecuteResponse."),stored_path);
[576]2070
2071        errorException(m,tmpMsg,"InternalError",NULL);
[507]2072        xmlFreeDoc(doc);
2073        xmlCleanupParser();
2074        zooXmlCleanupNs();
2075        unlockShm(lid);
2076        return;
2077      }
2078      xmlChar *xmlbuff;
2079      int buffersize;
2080      xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1);
2081      fwrite(xmlbuff,1,xmlStrlen(xmlbuff)*sizeof(char),output);
2082      xmlFree(xmlbuff);
2083      fclose(output);
2084#ifdef DEBUG
2085      fprintf(stderr,"UNLOCK %s %d !\n",__FILE__,__LINE__);
2086#endif
2087      unlockShm(lid);
2088      map* test1=getMap(request,"status");
2089      if(test1==NULL || strcasecmp(test1->value,"true")!=0){
2090        removeShmLock(m,1);
2091      }
[393]2092    }
[72]2093  }
[9]2094  printDocument(m,doc,pid);
2095
2096  xmlCleanupParser();
2097  zooXmlCleanupNs();
2098}
2099
[579]2100/**
2101 * Print a XML document.
2102 *
2103 * @param m the conf maps containing the main.cfg settings
2104 * @param doc the XML document
2105 * @param pid the process identifier linked to a service
2106 */
[9]2107void printDocument(maps* m, xmlDocPtr doc,int pid){
2108  char *encoding=getEncoding(m);
2109  if(pid==getpid()){
[384]2110    printHeaders(m);
[9]2111    printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
2112  }
2113  fflush(stdout);
2114  xmlChar *xmlbuff;
2115  int buffersize;
[1]2116  /*
[9]2117   * Dump the document to a buffer and print it on stdout
[1]2118   * for demonstration purposes.
2119   */
[9]2120  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
[114]2121  printf("%s",xmlbuff);
[216]2122  fflush(stdout);
[1]2123  /*
2124   * Free associated memory.
2125   */
2126  xmlFree(xmlbuff);
[9]2127  xmlFreeDoc(doc);
2128  xmlCleanupParser();
2129  zooXmlCleanupNs();
[1]2130}
2131
[579]2132/**
2133 * Print a XML document.
2134 *
2135 * @param doc the XML document (unused)
2136 * @param nc the XML node to add the output definition
2137 * @param ns_wps the wps XML namespace
2138 * @param ns_ows the ows XML namespace
2139 * @param e the output elements
2140 * @param m the conf maps containing the main.cfg settings
2141 * @param type the type (unused)
2142 */
[576]2143void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,const char* type){
[1]2144  xmlNodePtr nc1;
2145  nc1=xmlNewNode(ns_wps, BAD_CAST type);
2146  map *tmp=NULL; 
2147  if(e!=NULL && e->defaults!=NULL)
2148    tmp=e->defaults->content;
2149  else{
2150    /*
2151    dumpElements(e);
2152    */
2153    return;
2154  }
2155  while(tmp!=NULL){
[9]2156    if(strncasecmp(tmp->name,"MIMETYPE",strlen(tmp->name))==0
2157       || strncasecmp(tmp->name,"ENCODING",strlen(tmp->name))==0
2158       || strncasecmp(tmp->name,"SCHEMA",strlen(tmp->name))==0
2159       || strncasecmp(tmp->name,"UOM",strlen(tmp->name))==0)
[1]2160    xmlNewProp(nc1,BAD_CAST tmp->name,BAD_CAST tmp->value);
2161    tmp=tmp->next;
2162  }
2163  tmp=getMap(e->defaults->content,"asReference");
2164  if(tmp==NULL)
2165    xmlNewProp(nc1,BAD_CAST "asReference",BAD_CAST "false");
2166
2167  tmp=e->content;
2168
2169  printDescription(nc1,ns_ows,m->name,e->content);
2170
2171  xmlAddChild(nc,nc1);
2172
2173}
2174
[579]2175/**
2176 * Generate XML nodes describing inputs or outputs metadata.
2177 *
2178 * @param doc the XML document
2179 * @param nc the XML node to add the definition
2180 * @param ns_wps the wps namespace
2181 * @param ns_ows the ows namespace
2182 * @param ns_xlink the xlink namespace
2183 * @param e the output elements
2184 * @param m the conf maps containing the main.cfg settings
2185 * @param type the type
2186 */
[114]2187void printIOType(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,elements* e,maps* m,const char* type){
[601]2188
[1]2189  xmlNodePtr nc1,nc2,nc3;
2190  nc1=xmlNewNode(ns_wps, BAD_CAST type);
[65]2191  map *tmp=NULL;
2192  if(e!=NULL)
2193    tmp=e->content;
2194  else
2195    tmp=m->content;
[601]2196
[1]2197  nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier");
[65]2198  if(e!=NULL)
2199    nc3=xmlNewText(BAD_CAST e->name);
2200  else
2201    nc3=xmlNewText(BAD_CAST m->name);
[601]2202
[9]2203  xmlAddChild(nc2,nc3);
[1]2204  xmlAddChild(nc1,nc2);
2205  xmlAddChild(nc,nc1);
[65]2206  if(e!=NULL)
2207    tmp=getMap(e->content,"Title");
2208  else
2209    tmp=getMap(m->content,"Title");
2210 
2211  if(tmp!=NULL){
[43]2212    nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
2213    nc3=xmlNewText(BAD_CAST _ss(tmp->value));
2214    xmlAddChild(nc2,nc3); 
2215    xmlAddChild(nc1,nc2);
[65]2216  }
2217
2218  if(e!=NULL)
2219    tmp=getMap(e->content,"Abstract");
2220  else
2221    tmp=getMap(m->content,"Abstract");
[601]2222
[65]2223  if(tmp!=NULL){
2224    nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
2225    nc3=xmlNewText(BAD_CAST _ss(tmp->value));
2226    xmlAddChild(nc2,nc3); 
2227    xmlAddChild(nc1,nc2);
[43]2228    xmlAddChild(nc,nc1);
2229  }
[1]2230
2231  /**
2232   * IO type Reference or full Data ?
2233   */
[9]2234  map *tmpMap=getMap(m->content,"Reference");
2235  if(tmpMap==NULL){
2236    nc2=xmlNewNode(ns_wps, BAD_CAST "Data");
[65]2237    if(e!=NULL){
[76]2238      if(strncasecmp(e->format,"LiteralOutput",strlen(e->format))==0)
[601]2239         nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
[9]2240      else
[601]2241        if(strncasecmp(e->format,"ComplexOutput",strlen(e->format))==0)
2242                   nc3=xmlNewNode(ns_wps, BAD_CAST "ComplexData");
2243          else if(strncasecmp(e->format,"BoundingBoxOutput",strlen(e->format))==0)
2244            nc3=xmlNewNode(ns_wps, BAD_CAST "BoundingBoxData");
2245          else
2246            nc3=xmlNewNode(ns_wps, BAD_CAST e->format);
[65]2247    }
[601]2248    else {
[65]2249      map* tmpV=getMapFromMaps(m,"format","value");
2250      if(tmpV!=NULL)
[601]2251            nc3=xmlNewNode(ns_wps, BAD_CAST tmpV->value);
[65]2252      else
[601]2253            nc3=xmlNewNode(ns_wps, BAD_CAST "LitteralData");
[76]2254    } 
[9]2255    tmp=m->content;
[601]2256
[9]2257    while(tmp!=NULL){
[70]2258      if(strcasecmp(tmp->name,"mimeType")==0 ||
[601]2259             strcasecmp(tmp->name,"encoding")==0 ||
2260             strcasecmp(tmp->name,"schema")==0 ||
2261             strcasecmp(tmp->name,"datatype")==0 ||
2262             strcasecmp(tmp->name,"uom")==0) {
2263
2264            xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
[490]2265      }
[9]2266      tmp=tmp->next;
2267      xmlAddChild(nc2,nc3);
[1]2268    }
[601]2269    if(e!=NULL && e->format!=NULL && strcasecmp(e->format,"BoundingBoxData")==0) {
[76]2270      map* bb=getMap(m->content,"value");
[601]2271      if(bb!=NULL) {
2272            map* tmpRes=parseBoundingBox(bb->value);
2273            printBoundingBox(ns_ows,nc3,tmpRes);
2274            freeMap(&tmpRes);
2275            free(tmpRes);
[9]2276      }
[601]2277    }
2278        else {
[76]2279      if(e!=NULL)
[601]2280            tmp=getMap(e->defaults->content,"mimeType");
[76]2281      else
[601]2282            tmp=NULL;
2283       
2284        map* tmp1=getMap(m->content,"encoding");
2285        map* tmp2=getMap(m->content,"mimeType");
2286        map* tmp3=getMap(m->content,"value");
2287        int hasValue=1;
2288        if(tmp3==NULL){
2289              tmp3=createMap("value","");
2290              hasValue=-1;
2291        }
2292
2293       if( ( tmp1 != NULL && strncmp(tmp1->value,"base64",6) == 0 )  // if encoding is base64
2294                ||                                                           // or if
2295                ( tmp2 != NULL && ( strstr(tmp2->value,"text") == NULL //  mime type is not text
2296                                    &&                                   //  nor
2297                                                            strstr(tmp2->value,"xml") == NULL  //  xml
2298                                                                &&                                          // nor
2299                                                                strstr(tmp2->value,"javascript") == NULL  // javascript
2300                                                                &&
2301                                                                strstr(tmp2->value,"json") == NULL
2302                                                                &&
2303                                                                strstr(tmp2->value,"ecmascript") == NULL
2304                                                                &&
2305                                                                // include for backwards compatibility,
2306                                                                // although correct mime type is ...kml+xml:
2307                                                                strstr(tmp2->value,"google-earth.kml") == NULL                                                         
2308                                                          )
2309                )
2310                  ) {                                                      // then     
2311              map* rs=getMap(m->content,"size");                       // obtain size
2312              bool isSized=true;
2313              if(rs==NULL){
2314                char tmp1[1024];
2315                sprintf(tmp1,"%ld",strlen(tmp3->value));
2316                rs=createMap("size",tmp1);
2317                isSized=false;
2318              }
2319
2320            xmlAddChild(nc3,xmlNewText(BAD_CAST base64(tmp3->value, atoi(rs->value))));  // base 64 encode in XML
2321               
2322            if(tmp1==NULL || (tmp1!=NULL && strncmp(tmp1->value,"base64",6)!=0)) {
2323               xmlAttrPtr ap = xmlHasProp(nc3, BAD_CAST "encoding");
2324               if (ap != NULL) {
2325                  xmlRemoveProp(ap);
2326               }                       
2327               xmlNewProp(nc3,BAD_CAST "encoding",BAD_CAST "base64");
2328                }
2329               
2330            if(!isSized){
2331              freeMap(&rs);
2332              free(rs);
2333            }
[297]2334      }
[601]2335      else if (tmp2!=NULL) {                                 // else (text-based format)
2336            if(strstr(tmp2->value, "javascript") != NULL ||      //    if javascript put code in CDATA block
2337               strstr(tmp2->value, "json") != NULL ||            //    (will not be parsed by XML reader)
2338               strstr(tmp2->value, "ecmascript") != NULL
2339                  ) {
2340               xmlAddChild(nc3,xmlNewCDataBlock(doc,BAD_CAST tmp3->value,strlen(tmp3->value)));
2341                }   
2342            else {                                                     // else
2343               if (strstr(tmp2->value, "xml") != NULL ||                 // if XML-based format
2344                           // include for backwards compatibility,
2345                           // although correct mime type is ...kml+xml:           
2346                   strstr(tmp2->value, "google-earth.kml") != NULL
2347                          ) { 
2348                         
2349                  int li=zooXmlAddDoc(tmp3->value);
2350                  xmlDocPtr doc = iDocs[li];
2351                  xmlNodePtr ir = xmlDocGetRootElement(doc);
2352                  xmlAddChild(nc3,ir);
2353               }
2354               else                                                     // else
2355                  xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value));    //   add text node
2356            }
2357            xmlAddChild(nc2,nc3);
[379]2358      }
[601]2359      else {
[379]2360            xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value));
[76]2361      }
[601]2362         
2363      if(hasValue<0) {
2364            freeMap(&tmp3);
2365            free(tmp3);
[379]2366      }
[9]2367    }
[1]2368  }
[601]2369  else { // Reference
[297]2370    tmpMap=getMap(m->content,"Reference");
[9]2371    nc3=nc2=xmlNewNode(ns_wps, BAD_CAST "Reference");
[76]2372    if(strcasecmp(type,"Output")==0)
2373      xmlNewProp(nc3,BAD_CAST "href",BAD_CAST tmpMap->value);
2374    else
2375      xmlNewNsProp(nc3,ns_xlink,BAD_CAST "href",BAD_CAST tmpMap->value);
[601]2376   
2377        tmp=m->content;
2378    while(tmp!=NULL) {
[70]2379      if(strcasecmp(tmp->name,"mimeType")==0 ||
[601]2380             strcasecmp(tmp->name,"encoding")==0 ||
2381             strcasecmp(tmp->name,"schema")==0 ||
2382             strcasecmp(tmp->name,"datatype")==0 ||
2383             strcasecmp(tmp->name,"uom")==0){
2384
2385            if(strcasecmp(tmp->name,"datatype")==0)
2386              xmlNewProp(nc3,BAD_CAST "mimeType",BAD_CAST "text/plain");
2387            else
2388              xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
[490]2389      }
[9]2390      tmp=tmp->next;
2391      xmlAddChild(nc2,nc3);
2392    }
[1]2393  }
2394  xmlAddChild(nc1,nc2);
2395  xmlAddChild(nc,nc1);
2396}
2397
[579]2398/**
2399 * Create XML node with basic ows metadata informations (Identifier,Title,Abstract)
2400 *
2401 * @param root the root XML node to add the description
2402 * @param ns_ows the ows XML namespace
2403 * @param identifier the identifier to use
2404 * @param amap the map containing the ows metadata informations
2405 */
[114]2406void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map* amap){
[1]2407  xmlNodePtr nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
[469]2408 
[1]2409  xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
2410  xmlAddChild(root,nc2);
2411  map* tmp=amap;
[490]2412  const char *tmp2[2];
[1]2413  tmp2[0]="Title";
2414  tmp2[1]="Abstract";
2415  int j=0;
2416  for(j=0;j<2;j++){
2417    map* tmp1=getMap(tmp,tmp2[j]);
2418    if(tmp1!=NULL){
2419      nc2 = xmlNewNode(ns_ows, BAD_CAST tmp2[j]);
[34]2420      xmlAddChild(nc2,xmlNewText(BAD_CAST _ss(tmp1->value)));
[1]2421      xmlAddChild(root,nc2);
2422    }
2423  }
2424}
2425
[579]2426/**
2427 * Access the value of the encoding key in a maps
2428 *
2429 * @param m the maps to search for the encoding key
2430 * @return the value of the encoding key in a maps if encoding key exists,
2431 *  "UTF-8" in other case.
2432 */
[9]2433char* getEncoding(maps* m){
2434  if(m!=NULL){
2435    map* tmp=getMap(m->content,"encoding");
[1]2436    if(tmp!=NULL){
[9]2437      return tmp->value;
[1]2438    }
2439    else
[490]2440      return (char*)"UTF-8";
[1]2441  }
2442  else
[490]2443    return (char*)"UTF-8"; 
[9]2444}
[1]2445
[579]2446/**
2447 * Access the value of the version key in a maps
2448 *
2449 * @param m the maps to search for the version key
2450 * @return the value of the version key in a maps if encoding key exists,
2451 *  "1.0.0" in other case.
2452 */
[9]2453char* getVersion(maps* m){
2454  if(m!=NULL){
2455    map* tmp=getMap(m->content,"version");
[1]2456    if(tmp!=NULL){
[9]2457      return tmp->value;
[1]2458    }
2459    else
[490]2460      return (char*)"1.0.0";
[1]2461  }
2462  else
[490]2463    return (char*)"1.0.0";
[9]2464}
[1]2465
[576]2466/**
2467 * Print an OWS ExceptionReport Document and HTTP headers (when required)
2468 * depending on the code.
2469 * Set hasPrinted value to true in the [lenv] section.
2470 *
[579]2471 * @param m the maps containing the settings of the main.cfg file
[576]2472 * @param s the map containing the text,code,locator keys
2473 */
[9]2474void printExceptionReportResponse(maps* m,map* s){
[469]2475  if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL)
2476    return;
[9]2477  int buffersize;
2478  xmlDocPtr doc;
2479  xmlChar *xmlbuff;
[34]2480  xmlNodePtr n;
[1]2481
[483]2482  zooXmlCleanupNs();
[9]2483  doc = xmlNewDoc(BAD_CAST "1.0");
2484  maps* tmpMap=getMaps(m,"main");
2485  char *encoding=getEncoding(tmpMap);
[490]2486  const char *exceptionCode;
[459]2487 
2488  map* tmp=getMap(s,"code");
2489  if(tmp!=NULL){
[576]2490    if(strcmp(tmp->value,"OperationNotSupported")==0 ||
2491       strcmp(tmp->value,"NoApplicableCode")==0)
[459]2492      exceptionCode="501 Not Implemented";
2493    else
2494      if(strcmp(tmp->value,"MissingParameterValue")==0 ||
2495         strcmp(tmp->value,"InvalidUpdateSequence")==0 ||
2496         strcmp(tmp->value,"OptionNotSupported")==0 ||
2497         strcmp(tmp->value,"VersionNegotiationFailed")==0 ||
2498         strcmp(tmp->value,"InvalidParameterValue")==0)
2499        exceptionCode="400 Bad request";
2500      else
[576]2501        exceptionCode="501 Internal Server Error";
[459]2502  }
2503  else
2504    exceptionCode="501 Internal Server Error";
2505
[32]2506  if(m!=NULL){
2507    map *tmpSid=getMapFromMaps(m,"lenv","sid");
2508    if(tmpSid!=NULL){
[384]2509      if( getpid()==atoi(tmpSid->value) ){
2510        printHeaders(m);
[459]2511        printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
[384]2512      }
[32]2513    }
[384]2514    else{
2515      printHeaders(m);
[459]2516      printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
[384]2517    }
[385]2518  }else{
[459]2519    printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
[385]2520  }
[34]2521  n=createExceptionReportNode(m,s,1);
[1]2522  xmlDocSetRootElement(doc, n);
[9]2523  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2524  printf("%s",xmlbuff);
2525  fflush(stdout);
2526  xmlFreeDoc(doc);
[1]2527  xmlFree(xmlbuff);
[9]2528  xmlCleanupParser();
[57]2529  zooXmlCleanupNs();
[471]2530  if(m!=NULL)
2531    setMapInMaps(m,"lenv","hasPrinted","true");
[1]2532}
2533
[576]2534/**
2535 * Create an OWS ExceptionReport Node.
2536 *
2537 * @param m the conf maps
2538 * @param s the map containing the text,code,locator keys
2539 * @param use_ns (0/1) choose if you want to generate an ExceptionReport or
2540 *  ows:ExceptionReport node respectively
2541 * @return the ExceptionReport/ows:ExceptionReport node
2542 */
[26]2543xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){
2544 
[490]2545  xmlNsPtr ns,ns_xsi;
2546  xmlNodePtr n,nc,nc1;
[1]2547
[469]2548  int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows");
[57]2549  ns=usedNs[nsid];
[576]2550  if(use_ns==0){
[481]2551    ns=NULL;
2552  }
[26]2553  n = xmlNewNode(ns, BAD_CAST "ExceptionReport");
2554  if(use_ns==1){
[576]2555    xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST"ows");
[26]2556    int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
2557    ns_xsi=usedNs[xsiId];
[469]2558    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]2559  }
[481]2560
2561
[34]2562  addLangAttr(n,m);
[26]2563  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.1.0");
2564 
[576]2565  int length=1;
2566  int cnt=0;
2567  map* len=getMap(s,"length");
2568  if(len!=NULL)
2569    length=atoi(len->value);
2570  for(cnt=0;cnt<length;cnt++){
2571    nc = xmlNewNode(ns, BAD_CAST "Exception");
2572   
2573    map* tmp=getMapArray(s,"code",cnt);
2574    if(tmp==NULL)
2575      tmp=getMap(s,"code");
2576    if(tmp!=NULL)
2577      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST tmp->value);
2578    else
2579      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode");
2580   
2581    tmp=getMapArray(s,"locator",cnt);
2582    if(tmp==NULL)
2583      tmp=getMap(s,"locator");
2584    if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0)
2585      xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value);
[26]2586
[576]2587    tmp=getMapArray(s,"text",cnt);
2588    nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
2589    if(tmp!=NULL){
2590      xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value);
2591      xmlAddChild(nc1,txt);
2592    }
2593    else{
2594      xmlNodeSetContent(nc1, BAD_CAST _("No debug message available"));
2595    }
2596    xmlAddChild(nc,nc1);
2597    xmlAddChild(n,nc);
[26]2598  }
2599  return n;
2600}
2601
[576]2602/**
2603 * Print an OWS ExceptionReport.
2604 *
2605 * @param m the conf maps
2606 * @param message the error message
2607 * @param errorcode the error code
2608 * @param locator the potential locator
2609 */
2610int errorException(maps *m, const char *message, const char *errorcode, const char *locator) 
2611{
2612  map* errormap = createMap("text", message);
2613  addToMap(errormap,"code", errorcode);
2614  if(locator!=NULL)
2615    addToMap(errormap,"locator", locator);
2616  else
2617    addToMap(errormap,"locator", "NULL");
2618  printExceptionReportResponse(m,errormap);
2619  freeMap(&errormap);
2620  free(errormap);
2621  return -1;
2622}
2623
[550]2624/**
2625 * Read a file generated by a service.
2626 *
2627 * @param m the conf maps
2628 * @param content the output item
2629 * @param filename the file to read
2630 */
2631void readGeneratedFile(maps* m,map* content,char* filename){
2632  FILE * file=fopen(filename,"rb");
[564]2633  if(file==NULL){
2634    fprintf(stderr,"Failed to open file %s for reading purpose.\n",filename);
2635    setMapInMaps(m,"lenv","message","Unable to read produced file. Please try again later");
2636    return ;
2637  }
[550]2638  fseek(file, 0, SEEK_END);
2639  long count = ftell(file);
2640  rewind(file);
2641  struct stat file_status; 
2642  stat(filename, &file_status);
2643  map* tmpMap1=getMap(content,"value");
2644  if(tmpMap1==NULL){
2645    addToMap(content,"value","");
2646    tmpMap1=getMap(content,"value");
2647  }
2648  free(tmpMap1->value);
2649  tmpMap1->value=(char*) malloc((count+1)*sizeof(char)); 
2650  fread(tmpMap1->value,1,count*sizeof(char),file);
2651  fclose(file);
2652  char rsize[100];
[576]2653  sprintf(rsize,"%ld",count*sizeof(char));
[550]2654  addToMap(tmpMap1,"size",rsize);
2655}
2656
[579]2657/**
2658 * Generate the output response (RawDataOutput or ResponseDocument)
2659 *
2660 * @param s the service structure containing the metadata informations
2661 * @param request_inputs the inputs provided to the service for execution
2662 * @param request_outputs the outputs updated by the service execution
2663 * @param request_inputs1 the map containing the HTTP request
2664 * @param cpid the process identifier attached to a service execution
2665 * @param m the conf maps containing the main.cfg settings
2666 * @param res the value returned by the service execution
2667 */
[1]2668void outputResponse(service* s,maps* request_inputs,maps* request_outputs,
2669                    map* request_inputs1,int cpid,maps* m,int res){
2670#ifdef DEBUG
2671  dumpMaps(request_inputs);
2672  dumpMaps(request_outputs);
2673  fprintf(stderr,"printProcessResponse\n");
2674#endif
2675  map* toto=getMap(request_inputs1,"RawDataOutput");
2676  int asRaw=0;
2677  if(toto!=NULL)
2678    asRaw=1;
[9]2679 
[379]2680  maps* tmpSess=getMaps(m,"senv");
2681  if(tmpSess!=NULL){
2682    map *_tmp=getMapFromMaps(m,"lenv","cookie");
[490]2683    char* sessId=NULL;
[379]2684    if(_tmp!=NULL){
[442]2685      printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value);
[379]2686      printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n");
2687      char session_file_path[100];
[92]2688      char *tmp1=strtok(_tmp->value,";");
2689      if(tmp1!=NULL)
[379]2690        sprintf(session_file_path,"%s",strstr(tmp1,"=")+1);
[92]2691      else
[379]2692        sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1);
2693      sessId=strdup(session_file_path);
2694    }else{
2695      maps* t=getMaps(m,"senv");
2696      map*p=t->content;
2697      while(p!=NULL){
2698        if(strstr(p->name,"ID")!=NULL){
2699          sessId=strdup(p->value);
2700          break;
2701        }
2702        p=p->next;
2703      }
[92]2704    }
[379]2705    char session_file_path[1024];
2706    map *tmpPath=getMapFromMaps(m,"main","sessPath");
2707    if(tmpPath==NULL)
2708      tmpPath=getMapFromMaps(m,"main","tmpPath");
2709    sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId);
[387]2710    FILE* teste=fopen(session_file_path,"w");
2711    if(teste==NULL){
2712      char tmpMsg[1024];
2713      sprintf(tmpMsg,_("Unable to create the file : \"%s\" for storing the session maps."),session_file_path);
[576]2714      errorException(m,tmpMsg,"InternalError",NULL);
2715
[387]2716      return;
2717    }
2718    else{
2719      fclose(teste);
2720      dumpMapsToFile(tmpSess,session_file_path);
2721    }
[92]2722  }
[379]2723 
[576]2724  if(res==SERVICE_FAILED){
2725    map *lenv;
2726    lenv=getMapFromMaps(m,"lenv","message");
2727    char *tmp0;
2728    if(lenv!=NULL){
2729      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));
2730      sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value);
[550]2731    }
[576]2732    else{
2733      tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));
2734      sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service."));
2735    }
2736    errorException(m,tmp0,"InternalError",NULL);
2737    free(tmp0);
2738    return;
2739  }
[453]2740
[550]2741
[576]2742  map *tmp1=getMapFromMaps(m,"main","tmpPath");
[1]2743  if(asRaw==0){
[9]2744#ifdef DEBUG
2745    fprintf(stderr,"REQUEST_OUTPUTS FINAL\n");
2746    dumpMaps(request_outputs);
2747#endif
[70]2748    maps* tmpI=request_outputs;
[576]2749
[70]2750    while(tmpI!=NULL){
[297]2751#ifdef USE_MS
[364]2752      map* testMap=getMap(tmpI->content,"useMapserver");       
[297]2753#endif
[70]2754      toto=getMap(tmpI->content,"asReference");
[297]2755#ifdef USE_MS
[453]2756      if(toto!=NULL && strcasecmp(toto->value,"true")==0 && testMap==NULL)
[297]2757#else
[453]2758      if(toto!=NULL && strcasecmp(toto->value,"true")==0)
[297]2759#endif
[453]2760        {
[550]2761          elements* in=getElements(s->outputs,tmpI->name);
2762          char *format=NULL;
2763          if(in!=NULL){
2764            format=strdup(in->format);
2765          }else
2766            format=strdup("LiteralData");
2767          if(strcasecmp(format,"BoundingBoxData")==0){
2768            addToMap(tmpI->content,"extension","xml");
2769            addToMap(tmpI->content,"mimeType","text/xml");
2770            addToMap(tmpI->content,"encoding","UTF-8");
2771            addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
[70]2772          }
[550]2773
2774          map *gfile=getMap(tmpI->content,"generated_file");
2775          char *file_name;
2776          if(gfile!=NULL){
[565]2777            gfile=getMap(tmpI->content,"expected_generated_file");
2778            if(gfile==NULL){
2779              gfile=getMap(tmpI->content,"generated_file");
2780            }
[550]2781            readGeneratedFile(m,tmpI->content,gfile->value);       
2782            file_name=(char*)malloc((strlen(gfile->value)+strlen(tmp1->value)+1)*sizeof(char));
2783            for(int i=0;i<strlen(gfile->value);i++)
2784              file_name[i]=gfile->value[i+strlen(tmp1->value)];
2785          }
2786          else{
2787            map *ext=getMap(tmpI->content,"extension");
2788            char *file_path;
[601]2789                char file_ext[32];
2790
2791            if( ext != NULL && ext->value != NULL) {
2792                        strncpy(file_ext, ext->value, 32);
2793                }
2794                else {
2795              // Obtain default file extension (see mimetypes.h).             
2796              // If the MIME type is not recognized, txt is used as the default extension
[550]2797              map* mtype=getMap(tmpI->content,"mimeType");
[601]2798                  getFileExtension(mtype != NULL ? mtype->value : NULL, file_ext, 32);
[550]2799            }
[601]2800               
2801                file_name=(char*)malloc((strlen(s->name)+strlen(file_ext)+strlen(tmpI->name)+1024)*sizeof(char));
2802            int cpid0=cpid+time(NULL);     
2803                sprintf(file_name,"%s_%s_%i.%s",s->name,tmpI->name,cpid0,file_ext);
[550]2804            file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char));
2805            sprintf(file_path,"%s/%s",tmp1->value,file_name);
[601]2806           
2807                FILE *ofile=fopen(file_path,"wb");
[550]2808            if(ofile==NULL){
2809              char tmpMsg[1024];
2810              sprintf(tmpMsg,_("Unable to create the file : \"%s\" for storing the %s final result."),file_name,tmpI->name);
[576]2811              errorException(m,tmpMsg,"InternalError",NULL);
[550]2812              free(file_name);
2813              free(file_path);
2814              return;
2815            }
2816            free(file_path);
[601]2817
[550]2818            toto=getMap(tmpI->content,"value");
2819            if(strcasecmp(format,"BoundingBoxData")!=0){
2820              map* size=getMap(tmpI->content,"size");
2821              if(size!=NULL && toto!=NULL)
2822                fwrite(toto->value,1,atoi(size->value)*sizeof(char),ofile);
2823              else
2824                if(toto!=NULL && toto->value!=NULL)
2825                  fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);
2826            }else{
2827              printBoundingBoxDocument(m,tmpI,ofile);
2828            }
2829            fclose(ofile);
2830
2831          }
2832          map *tmp2=getMapFromMaps(m,"main","tmpUrl");
2833          map *tmp3=getMapFromMaps(m,"main","serverAddress");
2834          char *file_url;
2835          if(strncasecmp(tmp2->value,"http://",7)==0 ||
2836             strncasecmp(tmp2->value,"https://",8)==0){
2837            file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));
2838            sprintf(file_url,"%s/%s",tmp2->value,file_name);
2839          }else{
2840            file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));
2841            sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);
2842          }
2843          addToMap(tmpI->content,"Reference",file_url);
2844          free(format);
[453]2845          free(file_name);
[550]2846          free(file_url);       
2847         
[386]2848        }
[297]2849#ifdef USE_MS
2850      else{
2851        if(testMap!=NULL){
2852          setReferenceUrl(m,tmpI);
2853        }
2854      }
2855#endif
[70]2856      tmpI=tmpI->next;
[9]2857    }
[1]2858    map *r_inputs=getMap(s->content,"serviceProvider");
2859#ifdef DEBUG
2860    fprintf(stderr,"SERVICE : %s\n",r_inputs->value);
2861    dumpMaps(m);
2862#endif
[9]2863    printProcessResponse(m,request_inputs1,cpid,
[26]2864                         s,r_inputs->value,res,
2865                         request_inputs,
2866                         request_outputs);
[550]2867  }
2868  else{
2869    /**
2870     * We get the requested output or fallback to the first one if the
2871     * requested one is not present in the resulting outputs maps.
2872     */
2873    maps* tmpI=NULL;
2874    map* tmpIV=getMap(request_inputs1,"RawDataOutput");
2875    if(tmpIV!=NULL){
2876      tmpI=getMaps(request_outputs,tmpIV->value);
[453]2877    }
[550]2878    if(tmpI==NULL)
2879      tmpI=request_outputs;
2880    elements* e=getElements(s->outputs,tmpI->name);
2881    if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
2882      printBoundingBoxDocument(m,tmpI,NULL);
2883    }else{
2884      map *gfile=getMap(tmpI->content,"generated_file");
2885      if(gfile!=NULL){
[576]2886        gfile=getMap(tmpI->content,"expected_generated_file");
2887        if(gfile==NULL){
2888          gfile=getMap(tmpI->content,"generated_file");
2889        }
[550]2890        readGeneratedFile(m,tmpI->content,gfile->value);
2891      }
2892      toto=getMap(tmpI->content,"value");
2893      if(toto==NULL){
2894        char tmpMsg[1024];
2895        sprintf(tmpMsg,_("Wrong RawDataOutput parameter, unable to fetch any result for the name your provided : \"%s\"."),tmpI->name);
[576]2896        errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput");
[481]2897        return;
2898      }
[550]2899      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
2900      if(fname!=NULL)
2901        printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
2902      map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
2903      if(rs!=NULL)
2904        printf("Content-Length: %s\r\n",rs->value);
2905      printHeaders(m);
2906      char mime[1024];
2907      map* mi=getMap(tmpI->content,"mimeType");
[1]2908#ifdef DEBUG
[550]2909      fprintf(stderr,"SERVICE OUTPUTS\n");
2910      dumpMaps(request_outputs);
2911      fprintf(stderr,"SERVICE OUTPUTS\n");
[1]2912#endif
[550]2913      map* en=getMap(tmpI->content,"encoding");
2914      if(mi!=NULL && en!=NULL)
2915        sprintf(mime,
2916                "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
2917                mi->value,en->value);
2918      else
2919        if(mi!=NULL)
[26]2920          sprintf(mime,
[550]2921                  "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
2922                  mi->value);
[26]2923        else
[550]2924          sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
2925      printf("%s",mime);
2926      if(rs!=NULL)
2927        fwrite(toto->value,1,atoi(rs->value),stdout);
2928      else
2929        fwrite(toto->value,1,strlen(toto->value),stdout);
[1]2930#ifdef DEBUG
[550]2931      dumpMap(toto);
[1]2932#endif
[26]2933    }
[550]2934  }
[1]2935}
2936
[579]2937
2938/**
2939 * Base64 encoding of a char*
2940 *
2941 * @param input the value to encode
2942 * @param length the value length
2943 * @return the buffer containing the base64 value
2944 * @warning make sure to free the returned value
2945 */
[216]2946char *base64(const char *input, int length)
[1]2947{
2948  BIO *bmem, *b64;
2949  BUF_MEM *bptr;
2950
2951  b64 = BIO_new(BIO_f_base64());
[94]2952  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
[1]2953  bmem = BIO_new(BIO_s_mem());
2954  b64 = BIO_push(b64, bmem);
[500]2955  BIO_write(b64, input, length+1);
[1]2956  BIO_flush(b64);
2957  BIO_get_mem_ptr(b64, &bptr);
2958
[500]2959  char *buff = (char *)malloc((bptr->length+1)*sizeof(char));
2960  memcpy(buff, bptr->data, bptr->length);
[1]2961  buff[bptr->length-1] = 0;
2962
2963  BIO_free_all(b64);
2964
2965  return buff;
2966}
2967
[579]2968/**
2969 * Base64 decoding of a char*
2970 *
2971 * @param input the value to decode
2972 * @param length the value length
2973 * @param red the value length
2974 * @return the buffer containing the base64 value
2975 * @warning make sure to free the returned value
2976 */
[216]2977char *base64d(const char *input, int length,int* red)
[88]2978{
2979  BIO *b64, *bmem;
2980
2981  char *buffer = (char *)malloc(length);
[94]2982  if(buffer){
2983    memset(buffer, 0, length);
2984    b64 = BIO_new(BIO_f_base64());
2985    if(b64){
[216]2986      bmem = BIO_new_mem_buf((unsigned char*)input,length);
[94]2987      bmem = BIO_push(b64, bmem);
2988      *red=BIO_read(bmem, buffer, length);
2989      buffer[length-1]=0;
2990      BIO_free_all(bmem);
2991    }
2992  }
[88]2993  return buffer;
2994}
2995
[579]2996/**
2997 * Make sure that each value encoded in base64 in a maps is decoded.
2998 *
2999 * @param in the maps containing the values
3000 */
[88]3001void ensureDecodedBase64(maps **in){
3002  maps* cursor=*in;
3003  while(cursor!=NULL){
3004    map *tmp=getMap(cursor->content,"encoding");
3005    if(tmp!=NULL && strncasecmp(tmp->value,"base64",6)==0){
3006      tmp=getMap(cursor->content,"value");
3007      addToMap(cursor->content,"base64_value",tmp->value);
[94]3008      int size=0;
[88]3009      char *s=strdup(tmp->value);
3010      free(tmp->value);
3011      tmp->value=base64d(s,strlen(s),&size);
[94]3012      free(s);
[88]3013      char sizes[1024];
3014      sprintf(sizes,"%d",size);
3015      addToMap(cursor->content,"size",sizes);
3016    }
3017    cursor=cursor->next;
3018  }
3019}
3020
[579]3021/**
3022 * Add the default values defined in the zcfg to a maps.
3023 *
3024 * @param out the maps containing the inputs or outputs given in the initial
3025 *  HTTP request
3026 * @param in the description of all inputs or outputs available for a service
3027 * @param m the maps containing the settings of the main.cfg file
3028 * @param type 0 for inputs and 1 for outputs
3029 * @param err the map to store potential missing mandatory input parameters or
3030 *  wrong output names depending on the type.
3031 * @return "" if no error was detected, the name of last input or output causing
3032 *  an error.
3033 */
[576]3034char* addDefaultValues(maps** out,elements* in,maps* m,int type,map** err){
3035  map *res=*err;
[1]3036  elements* tmpInputs=in;
3037  maps* out1=*out;
[576]3038  char *result=NULL;
3039  int nb=0;
[280]3040  if(type==1){
3041    while(out1!=NULL){
[576]3042      if(getElements(in,out1->name)==NULL){
3043        if(res==NULL){
3044          res=createMap("value",out1->name);
3045        }else{
3046          setMapArray(res,"value",nb,out1->name);
3047        }
3048        nb++;
3049        result=out1->name;
3050      }
[280]3051      out1=out1->next;
3052    }
[576]3053    if(res!=NULL){
3054      *err=res;
3055      return result;
3056    }
[280]3057    out1=*out;
3058  }
[1]3059  while(tmpInputs!=NULL){
3060    maps *tmpMaps=getMaps(out1,tmpInputs->name);
3061    if(tmpMaps==NULL){
[9]3062      maps* tmpMaps2=(maps*)malloc(MAPS_SIZE);
[57]3063      tmpMaps2->name=strdup(tmpInputs->name);
[9]3064      tmpMaps2->content=NULL;
3065      tmpMaps2->next=NULL;
[63]3066     
3067      if(type==0){
3068        map* tmpMapMinO=getMap(tmpInputs->content,"minOccurs");
[490]3069        if(tmpMapMinO!=NULL){
[63]3070          if(atoi(tmpMapMinO->value)>=1){
3071            freeMaps(&tmpMaps2);
3072            free(tmpMaps2);
[576]3073            if(res==NULL){
3074              res=createMap("value",tmpInputs->name);
3075            }else{
3076              setMapArray(res,"value",nb,tmpInputs->name);
3077            }
3078            nb++;
3079            result=tmpInputs->name;
[63]3080          }
3081          else{
3082            if(tmpMaps2->content==NULL)
3083              tmpMaps2->content=createMap("minOccurs",tmpMapMinO->value);
3084            else
3085              addToMap(tmpMaps2->content,"minOccurs",tmpMapMinO->value);
3086          }
[490]3087        }
[576]3088        if(res==NULL){
3089          map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
3090          if(tmpMaxO!=NULL){
3091            if(tmpMaps2->content==NULL)
3092              tmpMaps2->content=createMap("maxOccurs",tmpMaxO->value);
3093            else
3094              addToMap(tmpMaps2->content,"maxOccurs",tmpMaxO->value);
3095          }
3096          map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");
3097          if(tmpMaxMB!=NULL){
3098            if(tmpMaps2->content==NULL)
3099              tmpMaps2->content=createMap("maximumMegabytes",tmpMaxMB->value);
3100            else
3101              addToMap(tmpMaps2->content,"maximumMegabytes",tmpMaxMB->value);
3102          }
[490]3103        }
[63]3104      }
3105
[576]3106      if(res==NULL){
3107        iotype* tmpIoType=tmpInputs->defaults;
3108        if(tmpIoType!=NULL){
3109          map* tmpm=tmpIoType->content;
3110          while(tmpm!=NULL){
3111            if(tmpMaps2->content==NULL)
3112              tmpMaps2->content=createMap(tmpm->name,tmpm->value);
3113            else
3114              addToMap(tmpMaps2->content,tmpm->name,tmpm->value);
3115            tmpm=tmpm->next;
3116          }
[63]3117        }
[576]3118        addToMap(tmpMaps2->content,"inRequest","false");
3119        if(type==0){
3120          map *tmpMap=getMap(tmpMaps2->content,"value");
3121          if(tmpMap==NULL)
3122            addToMap(tmpMaps2->content,"value","NULL");
3123        }
3124        if(out1==NULL){
3125          *out=dupMaps(&tmpMaps2);
3126          out1=*out;
3127        }
3128        else
3129          addMapsToMaps(&out1,tmpMaps2);
3130        freeMap(&tmpMaps2->content);
3131        free(tmpMaps2->content);
3132        tmpMaps2->content=NULL;
3133        freeMaps(&tmpMaps2);
3134        free(tmpMaps2);
3135        tmpMaps2=NULL;
[1]3136      }
3137    }
3138    else{
[57]3139      iotype* tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,
3140                                             tmpMaps->content);
[63]3141      if(type==0) {
[76]3142        /**
3143         * In case of an Input maps, then add the minOccurs and maxOccurs to the
3144         * content map.
3145         */
[63]3146        map* tmpMap1=getMap(tmpInputs->content,"minOccurs");
3147        if(tmpMap1!=NULL){
3148          if(tmpMaps->content==NULL)
3149            tmpMaps->content=createMap("minOccurs",tmpMap1->value);
3150          else
3151            addToMap(tmpMaps->content,"minOccurs",tmpMap1->value);
3152        }
3153        map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
3154        if(tmpMaxO!=NULL){
3155          if(tmpMaps->content==NULL)
[485]3156            tmpMaps->content=createMap("maxOccurs",tmpMaxO->value);
[63]3157          else
[485]3158            addToMap(tmpMaps->content,"maxOccurs",tmpMaxO->value);
[63]3159        }
[485]3160        map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");
[490]3161        if(tmpMaxMB!=NULL){
[485]3162          if(tmpMaps->content==NULL)
3163            tmpMaps->content=createMap("maximumMegabytes",tmpMaxMB->value);
3164          else
3165            addToMap(tmpMaps->content,"maximumMegabytes",tmpMaxMB->value);
[490]3166        }
[76]3167        /**
3168         * Parsing BoundingBoxData, fill the following map and then add it to
3169         * the content map of the Input maps:
3170         * lowerCorner, upperCorner, srs and dimensions
3171         * cf. parseBoundingBox
3172         */
3173        if(strcasecmp(tmpInputs->format,"BoundingBoxData")==0){
3174          maps* tmpI=getMaps(*out,tmpInputs->name);
3175          if(tmpI!=NULL){
3176            map* tmpV=getMap(tmpI->content,"value");
3177            if(tmpV!=NULL){
3178              char *tmpVS=strdup(tmpV->value);
3179              map* tmp=parseBoundingBox(tmpVS);
3180              free(tmpVS);
3181              map* tmpC=tmp;
3182              while(tmpC!=NULL){
3183                addToMap(tmpMaps->content,tmpC->name,tmpC->value);
3184                tmpC=tmpC->next;
3185              }
3186              freeMap(&tmp);
3187              free(tmp);
3188            }
3189          }
3190        }
[63]3191      }
3192
[57]3193      if(tmpIoType!=NULL){
3194        map* tmpContent=tmpIoType->content;
3195        map* cval=NULL;
[360]3196        int hasPassed=-1;
[57]3197        while(tmpContent!=NULL){
3198          if((cval=getMap(tmpMaps->content,tmpContent->name))==NULL){
[9]3199#ifdef DEBUG
[57]3200            fprintf(stderr,"addDefaultValues %s => %s\n",tmpContent->name,tmpContent->value);
[9]3201#endif
[63]3202            if(tmpMaps->content==NULL)
3203              tmpMaps->content=createMap(tmpContent->name,tmpContent->value);
3204            else
3205              addToMap(tmpMaps->content,tmpContent->name,tmpContent->value);
[360]3206           
3207            if(hasPassed<0 && type==0 && getMap(tmpMaps->content,"isArray")!=NULL){
3208              map* length=getMap(tmpMaps->content,"length");
3209              int i;
3210              char *tcn=strdup(tmpContent->name);
3211              for(i=1;i<atoi(length->value);i++){
[364]3212#ifdef DEBUG
[360]3213                dumpMap(tmpMaps->content);
3214                fprintf(stderr,"addDefaultValues %s_%d => %s\n",tcn,i,tmpContent->value);
[364]3215#endif
3216                int len=strlen((char*) tcn);
3217                char *tmp1=(char *)malloc((len+10)*sizeof(char));
[360]3218                sprintf(tmp1,"%s_%d",tcn,i);
[364]3219#ifdef DEBUG
[360]3220                fprintf(stderr,"addDefaultValues %s => %s\n",tmp1,tmpContent->value);
[364]3221#endif
[360]3222                addToMap(tmpMaps->content,tmp1,tmpContent->value);
3223                free(tmp1);
3224                hasPassed=1;
3225              }
3226              free(tcn);
3227            }
[57]3228          }
3229          tmpContent=tmpContent->next;
[9]3230        }
[297]3231#ifdef USE_MS
3232        /**
3233         * check for useMapServer presence
3234         */
3235        map* tmpCheck=getMap(tmpIoType->content,"useMapServer");
3236        if(tmpCheck!=NULL){
3237          // Get the default value
3238          tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,NULL);
3239          tmpCheck=getMap(tmpMaps->content,"mimeType");
3240          addToMap(tmpMaps->content,"requestedMimeType",tmpCheck->value);
3241          map* cursor=tmpIoType->content;
3242          while(cursor!=NULL){
3243            addToMap(tmpMaps->content,cursor->name,cursor->value);
3244            cursor=cursor->next;
3245          }
3246         
3247          cursor=tmpInputs->content;
3248          while(cursor!=NULL){
3249            if(strcasecmp(cursor->name,"Title")==0 ||
3250               strcasecmp(cursor->name,"Abstract")==0)
3251              addToMap(tmpMaps->content,cursor->name,cursor->value);
3252           cursor=cursor->next;
3253          }
3254        }
3255#endif
[1]3256      }
[92]3257      if(tmpMaps->content==NULL)
3258        tmpMaps->content=createMap("inRequest","true");
3259      else
3260        addToMap(tmpMaps->content,"inRequest","true");
[280]3261
[1]3262    }
3263    tmpInputs=tmpInputs->next;
3264  }
[576]3265  if(res!=NULL){
3266    *err=res;
3267    return result;
3268  }
[9]3269  return "";
[1]3270}
[76]3271
3272/**
[579]3273 * Parse a BoundingBox string
[76]3274 *
[579]3275 * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040):
3276 *  10.2 Bounding box
3277 *
[76]3278 *
[579]3279 * Value is provided as : lowerCorner,upperCorner,crs,dimension
3280 * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
[76]3281 *
[579]3282 * A map to store boundingbox informations should contain:
[76]3283 *  - lowerCorner : double,double (minimum within this bounding box)
3284 *  - upperCorner : double,double (maximum within this bounding box)
3285 *  - crs : URI (Reference to definition of the CRS)
3286 *  - dimensions : int
3287 *
3288 * Note : support only 2D bounding box.
[579]3289 *
3290 * @param value the char* containing the KVP bouding box
3291 * @return a map containing all the bounding box keys
[76]3292 */
[114]3293map* parseBoundingBox(const char* value){
[76]3294  map *res=NULL;
3295  if(value!=NULL){
3296    char *cv,*cvp;
[114]3297    cv=strtok_r((char*) value,",",&cvp);
[76]3298    int cnt=0;
3299    int icnt=0;
3300    char *currentValue=NULL;
3301    while(cv){
3302      if(cnt<2)
3303        if(currentValue!=NULL){
3304          char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));
3305          sprintf(finalValue,"%s%s",currentValue,cv);
3306          switch(cnt){
3307          case 0:
3308            res=createMap("lowerCorner",finalValue);
3309            break;
3310          case 1:
3311            addToMap(res,"upperCorner",finalValue);
3312            icnt=-1;
3313            break;
3314          }
3315          cnt++;
3316          free(currentValue);
3317          currentValue=NULL;
3318          free(finalValue);
3319        }
3320        else{
3321          currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));
3322          sprintf(currentValue,"%s ",cv);
3323        }
3324      else
3325        if(cnt==2){
3326          addToMap(res,"crs",cv);
3327          cnt++;
3328        }
3329        else
3330          addToMap(res,"dimensions",cv);
3331      icnt++;
3332      cv=strtok_r(NULL,",",&cvp);
3333    }
3334  }
3335  return res;
3336}
3337
3338/**
[579]3339 * Create required XML nodes for boundingbox and update the current XML node
3340 *
3341 * @param ns_ows the ows XML namespace
3342 * @param n the XML node to update
3343 * @param boundingbox the map containing the boundingbox definition
[76]3344 */
3345void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
3346
[490]3347  xmlNodePtr lw=NULL,uc=NULL;
[76]3348
3349  map* tmp=getMap(boundingbox,"value");
3350
3351  tmp=getMap(boundingbox,"lowerCorner");
3352  if(tmp!=NULL){
3353    lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");
3354    xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));
3355  }
3356
3357  tmp=getMap(boundingbox,"upperCorner");
3358  if(tmp!=NULL){
3359    uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");
3360    xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));
3361  }
3362
3363  tmp=getMap(boundingbox,"crs");
3364  if(tmp!=NULL)
3365    xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);
3366
3367  tmp=getMap(boundingbox,"dimensions");
3368  if(tmp!=NULL)
3369    xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);
3370
3371  xmlAddChild(n,lw);
3372  xmlAddChild(n,uc);
3373
3374}
3375
[579]3376/**
3377 * Print an ows:BoundingBox XML document
3378 *
3379 * @param m the maps containing the settings of the main.cfg file
3380 * @param boundingbox the maps containing the boundingbox definition
3381 * @param file the file to print the BoundingBox (if NULL then print on stdout)
3382 * @see parseBoundingBox, printBoundingBox
3383 */
[76]3384void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){
3385  if(file==NULL)
3386    rewind(stdout);
3387  xmlNodePtr n;
3388  xmlDocPtr doc;
3389  xmlNsPtr ns_ows,ns_xsi;
3390  xmlChar *xmlbuff;
3391  int buffersize;
3392  char *encoding=getEncoding(m);
3393  map *tmp;
3394  if(file==NULL){
3395    int pid=0;
3396    tmp=getMapFromMaps(m,"lenv","sid");
3397    if(tmp!=NULL)
3398      pid=atoi(tmp->value);
3399    if(pid==getpid()){
3400      printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
3401    }
3402    fflush(stdout);
3403  }
3404
3405  doc = xmlNewDoc(BAD_CAST "1.0");
3406  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
3407  ns_ows=usedNs[owsId];
3408  n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");
[216]3409  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
[76]3410  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
3411  ns_xsi=usedNs[xsiId];
3412  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");
3413  map *tmp1=getMap(boundingbox->content,"value");
3414  tmp=parseBoundingBox(tmp1->value);
3415  printBoundingBox(ns_ows,n,tmp);
3416  xmlDocSetRootElement(doc, n);
3417
3418  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
3419  if(file==NULL)
[114]3420    printf("%s",xmlbuff);
[76]3421  else{
3422    fprintf(file,"%s",xmlbuff);
3423  }
3424
3425  if(tmp!=NULL){
3426    freeMap(&tmp);
3427    free(tmp);
3428  }
3429  xmlFree(xmlbuff);
3430  xmlFreeDoc(doc);
3431  xmlCleanupParser();
3432  zooXmlCleanupNs();
3433 
3434}
[280]3435
[579]3436/**
3437 * Compute md5
3438 *
3439 * @param url the char*
3440 * @return a char* representing the md5 of the url
3441 * @warning make sure to free ressources returned by this function
3442 */
[364]3443char* getMd5(char* url){
[291]3444  EVP_MD_CTX md5ctx;
[364]3445  char* fresult=(char*)malloc((EVP_MAX_MD_SIZE+1)*sizeof(char));
[291]3446  unsigned char result[EVP_MAX_MD_SIZE];
3447  unsigned int len;
3448  EVP_DigestInit(&md5ctx, EVP_md5());
3449  EVP_DigestUpdate(&md5ctx, url, strlen(url));
3450  EVP_DigestFinal_ex(&md5ctx,result,&len);
3451  EVP_MD_CTX_cleanup(&md5ctx);
3452  int i;
3453  for(i = 0; i < len; i++){
3454    if(i>0){
3455      char *tmp=strdup(fresult);
3456      sprintf(fresult,"%s%02x", tmp,result[i]);
3457      free(tmp);
3458    }
3459    else
3460      sprintf(fresult,"%02x",result[i]);
3461  }
3462  return fresult;
3463}
3464
[280]3465/**
[579]3466 * Cache a file for a given request.
3467 * For each cached file, the are two files stored, a .zca and a .zcm containing
3468 * the downloaded content and the mimeType respectively.
3469 *
3470 * @param conf the maps containing the settings of the main.cfg file
3471 * @param request the url used too fetch the content
3472 * @param content the downloaded content
3473 * @param mimeType the content mimeType
3474 * @param length the content size
[587]3475 * @param filepath a buffer for storing the path of the cached file; may be NULL
3476 * @param max_path the size of the allocated filepath buffer 
[280]3477 */
[587]3478void addToCache(maps* conf,char* request,char* content,char* mimeType,int length, 
3479                char* filepath, size_t max_path){
[280]3480  map* tmp=getMapFromMaps(conf,"main","cacheDir");
3481  if(tmp!=NULL){
[364]3482    char* md5str=getMd5(request);
[292]3483    char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
3484    sprintf(fname,"%s/%s.zca",tmp->value,md5str);
[291]3485#ifdef DEBUG
[280]3486    fprintf(stderr,"Cache list : %s\n",fname);
3487    fflush(stderr);
[291]3488#endif
[293]3489    FILE* fo=fopen(fname,"w+");
[471]3490    if(fo==NULL){
[587]3491#ifdef DEBUG           
3492      fprintf (stderr, "Failed to open %s for writing: %s\n",fname, strerror(errno));
3493#endif
3494      filepath = NULL; 
[471]3495      return;
3496    }
[293]3497    fwrite(content,sizeof(char),length,fo);
3498    fclose(fo);
[587]3499       
3500        if (filepath != NULL) {
3501                strncpy(filepath, fname, max_path);
3502        }       
[446]3503
3504    sprintf(fname,"%s/%s.zcm",tmp->value,md5str);
3505    fo=fopen(fname,"w+");
3506#ifdef DEBUG
3507    fprintf(stderr,"MIMETYPE: %s\n",mimeType);
3508#endif
[492]3509    fwrite(mimeType,sizeof(char),strlen(mimeType),fo);
[446]3510    fclose(fo);
3511
[293]3512    free(md5str);
3513    free(fname);
[280]3514  }
[587]3515  else {
3516          filepath = NULL;
3517  }       
[280]3518}
3519
[579]3520/**
3521 * Verify if a url is available in the cache
3522 *
3523 * @param conf the maps containing the settings of the main.cfg file
3524 * @param request the url
3525 * @return the full name of the cached file if any, NULL in other case
3526 * @warning make sure to free ressources returned by this function (if not NULL)
3527 */
[280]3528char* isInCache(maps* conf,char* request){
[291]3529  map* tmpM=getMapFromMaps(conf,"main","cacheDir");
3530  if(tmpM!=NULL){
[364]3531    char* md5str=getMd5(request);
[291]3532#ifdef DEBUG
3533    fprintf(stderr,"MD5STR : (%s)\n\n",md5str);
3534#endif
[392]3535    char* fname=(char*)malloc(sizeof(char)*(strlen(tmpM->value)+strlen(md5str)+6));
[292]3536    sprintf(fname,"%s/%s.zca",tmpM->value,md5str);
[280]3537    struct stat f_status;
3538    int s=stat(fname, &f_status);
[292]3539    if(s==0 && f_status.st_size>0){
3540      free(md5str);
3541      return fname;
3542    }
[291]3543    free(md5str);
3544    free(fname);
[280]3545  }
3546  return NULL;
3547}
[281]3548
[579]3549/**
3550 * Effectively run all the HTTP requests in the queue
3551 *
3552 * @param m the maps containing the settings of the main.cfg file
3553 * @param inputs the maps containing the inputs (defined in the requests+added
3554 *  per default based on the zcfg file)
3555 * @param hInternet the HINTERNET pointer
3556 * @return 0 on success
3557 */
[492]3558int runHttpRequests(maps** m,maps** inputs,HINTERNET* hInternet){
3559  if(hInternet->nb>0){
3560    processDownloads(hInternet);
3561    maps* content=*inputs;
3562    map* tmp1;
3563    int index=0;
3564    while(content!=NULL){
[550]3565     
3566      map* length=getMap(content->content,"length");
3567      int shouldClean=-1;
3568      if(length==NULL){
3569        length=createMap("length","1");
3570        shouldClean=1;
3571      }
3572      for(int i=0;i<atoi(length->value);i++){
3573       
3574        char* fcontent;
3575        char *mimeType=NULL;
3576        int fsize=0;
3577        char cname[15];
3578        char vname[11];
3579        char vname1[11];
3580        char sname[9];
3581        char icname[14];
3582        char xname[16];
3583        if(index>0)
3584          sprintf(vname1,"value_%d",index);
3585        else
3586          sprintf(vname1,"value");
[492]3587
[550]3588        if(i>0){
3589          tmp1=getMap(content->content,cname);
3590          sprintf(cname,"cache_file_%d",i);
3591          sprintf(vname,"value_%d",i);
3592          sprintf(sname,"size_%d",i);
3593          sprintf(icname,"isCached_%d",i);
3594          sprintf(xname,"Reference_%d",i);
3595        }else{
3596          sprintf(cname,"cache_file");
3597          sprintf(vname,"value");
3598          sprintf(icname,"isCached");
3599          sprintf(sname,"size");
3600          sprintf(xname,"Reference");
3601        }
3602
3603        map* tmap=getMapFromMaps(*m,"orequests",vname1);
3604        if((tmp1=getMap(content->content,xname))!=NULL && strcasecmp(tmap->value,tmp1->value)==0 ){
3605          if(getMap(content->content,icname)==NULL){
3606           
3607            fcontent=(char*)malloc((hInternet->ihandle[index].nDataLen+1)*sizeof(char));
3608            if(fcontent == NULL){
3609              return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);
3610            }
3611            size_t dwRead;
3612            InternetReadFile(hInternet->ihandle[index], 
3613                             (LPVOID)fcontent, 
3614                             hInternet->ihandle[index].nDataLen, 
3615                             &dwRead);
3616            fcontent[hInternet->ihandle[index].nDataLen]=0;
3617            fsize=hInternet->ihandle[index].nDataLen;
3618            if(hInternet->ihandle[index].mimeType==NULL)
3619              mimeType=strdup("none");
3620            else
[554]3621                  mimeType=strdup(hInternet->ihandle[index].mimeType);       
[550]3622           
3623            map* tmpMap=getMapOrFill(&content->content,vname,"");
3624            free(tmpMap->value);
3625            tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
3626            if(tmpMap->value==NULL){
3627              return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);
3628            }
3629            memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
3630           
3631            char ltmp1[256];
3632            sprintf(ltmp1,"%d",fsize);
3633            map* tmp=getMapFromMaps(*m,"main","cacheDir");
3634            if(tmp!=NULL){
3635              char* md5str=getMd5(tmp1->value);
3636              char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
3637              sprintf(fname,"%s/%s.zca",tmp->value,md5str);
3638              addToMap(content->content,cname,fname);
3639              free(fname);
3640            }
3641            addToMap(content->content,sname,ltmp1);
[587]3642            addToCache(*m,tmp1->value,fcontent,mimeType,fsize, NULL, 0);
[550]3643            free(fcontent);
3644            free(mimeType);
3645            dumpMaps(content);
3646            index++;
3647
[492]3648          }
3649        }
3650      }
[550]3651      if(shouldClean>0){
3652        freeMap(&length);
3653        free(length);
3654      }
3655     
[492]3656      content=content->next;
3657    }
[550]3658   
[492]3659  }
[576]3660  return 0;
[492]3661}
3662
[281]3663/**
3664 * Try to load file from cache or download a remote file if not in cache
[579]3665 *
3666 * @param m the maps containing the settings of the main.cfg file
3667 * @param content the map to update
3668 * @param hInternet the HINTERNET pointer
3669 * @param url the url to fetch
3670 * @return 0
[281]3671 */
[492]3672int loadRemoteFile(maps** m,map** content,HINTERNET* hInternet,char *url){
[281]3673  char* fcontent;
[471]3674  char* cached=isInCache(*m,url);
[446]3675  char *mimeType=NULL;
[490]3676  int fsize=0;
[550]3677
3678  map* t=getMap(*content,"xlink:href");
3679  if(t==NULL){
3680    t=getMap((*content),"href");
3681    addToMap(*content,"xlink:href",url);
3682  }
3683
[281]3684  if(cached!=NULL){
[550]3685
[281]3686    struct stat f_status;
3687    int s=stat(cached, &f_status);
3688    if(s==0){
3689      fcontent=(char*)malloc(sizeof(char)*(f_status.st_size+1));
[375]3690      FILE* f=fopen(cached,"rb");
[490]3691      fread(fcontent,f_status.st_size,1,f);
[281]3692      fsize=f_status.st_size;
[392]3693      fcontent[fsize]=0;
[446]3694      fclose(f);
[550]3695      addToMap(*content,"cache_file",cached);
[281]3696    }
[446]3697    cached[strlen(cached)-1]='m';
3698    s=stat(cached, &f_status);
3699    if(s==0){
3700      mimeType=(char*)malloc(sizeof(char)*(f_status.st_size+1));
3701      FILE* f=fopen(cached,"rb");
[490]3702      fread(mimeType,f_status.st_size,1,f);
[446]3703      mimeType[f_status.st_size]=0;
3704      fclose(f);
3705    }
[550]3706
[281]3707  }else{
[492]3708    hInternet->waitingRequests[hInternet->nb]=strdup(url);
3709    InternetOpenUrl(hInternet,hInternet->waitingRequests[hInternet->nb],NULL,0,INTERNET_FLAG_NO_CACHE_WRITE,0);
[550]3710    maps *oreq=getMaps(*m,"orequests");
3711    if(oreq==NULL){
3712      oreq=(maps*)malloc(MAPS_SIZE);
3713      oreq->name=zStrdup("orequests");
3714      oreq->content=createMap("value",url);
3715      oreq->next=NULL;
3716      addMapsToMaps(m,oreq);
3717      freeMaps(&oreq);
3718      free(oreq);
3719    }else{
3720      setMapArray(oreq->content,"value",hInternet->nb-1,url);
3721    }
[492]3722    return 0;
[281]3723  }
[344]3724  if(fsize==0){
[471]3725    return errorException(*m, _("Unable to download the file."), "InternalError",NULL);
[344]3726  }
[446]3727  if(mimeType!=NULL){
[471]3728    addToMap(*content,"fmimeType",mimeType);
[446]3729  }
3730
[282]3731  map* tmpMap=getMapOrFill(content,"value","");
[360]3732   
[281]3733  free(tmpMap->value);
[550]3734
[281]3735  tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
[379]3736  if(tmpMap->value==NULL)
[478]3737    return errorException(*m, _("Unable to allocate memory."), "InternalError",NULL);
[392]3738  memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
[550]3739
[281]3740  char ltmp1[256];
3741  sprintf(ltmp1,"%d",fsize);
[471]3742  addToMap(*content,"size",ltmp1);
[550]3743  if(cached==NULL){
[587]3744    addToCache(*m,url,fcontent,mimeType,fsize, NULL, 0);
[550]3745  }
3746  else{
[492]3747    addToMap(*content,"isCached","true");
[550]3748
3749    map* tmp=getMapFromMaps(*m,"main","cacheDir");
3750    if(tmp!=NULL){
3751      map *c=getMap((*content),"xlink:href");
3752      char* md5str=getMd5(c->value);
3753      char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
3754      sprintf(fname,"%s/%s.zca",tmp->value,md5str);
3755      addToMap(*content,"cache_file",fname);
3756      free(fname);
3757    }
3758  }
[490]3759  free(fcontent);
3760  free(mimeType);
3761  free(cached);
[364]3762  return 0;
[281]3763}
3764
[579]3765/**
3766 * Read a file using the GDAL VSI API
3767 *
3768 * @param conf the maps containing the settings of the main.cfg file
3769 * @param dataSource the datasource name to read
3770 * @warning make sure to free ressources returned by this function
3771 */
[469]3772char *readVSIFile(maps* conf,const char* dataSource){
3773    VSILFILE * fichier=VSIFOpenL(dataSource,"rb");
3774    VSIStatBufL file_status;
3775    VSIStatL(dataSource, &file_status);
3776    if(fichier==NULL){
3777      char tmp[1024];
[576]3778      sprintf(tmp,"Failed to open file %s for reading purpose. File seems empty %lld.",
[469]3779              dataSource,file_status.st_size);
3780      setMapInMaps(conf,"lenv","message",tmp);
3781      return NULL;
3782    }
3783    char *res1=(char *)malloc(file_status.st_size*sizeof(char));
[490]3784    VSIFReadL(res1,1,file_status.st_size*sizeof(char),fichier);
3785    res1[file_status.st_size-1]=0;
[469]3786    VSIFCloseL(fichier);
3787    VSIUnlink(dataSource);
3788    return res1;
3789}
3790
[579]3791/**
3792 * Extract the service identifier from the full service identifier
3793 * ie:
3794 *  - Full service name: OTB.BandMath
3795 *  - Service name: BandMath
3796 *
3797 * @param conf the maps containing the settings of the main.cfg file
3798 * @param conf_dir the full path to the ZOO-Kernel directory
3799 * @param identifier the full service name (potentialy including a prefix, ie:
3800 *  Prefix.MyService)
3801 * @param buffer the resulting service identifier (without any prefix)
3802 */
[469]3803void parseIdentifier(maps* conf,char* conf_dir,char *identifier,char* buffer){
[539]3804  setMapInMaps(conf,"lenv","oIdentifier",identifier);
3805  char *lid=zStrdup(identifier);
[469]3806  char *saveptr1;
[539]3807  char *tmps1=strtok_r(lid,".",&saveptr1);
[469]3808  int level=0;
3809  char key[25];
3810  char levels[18];
3811  while(tmps1!=NULL){
3812    char *test=zStrdup(tmps1);
3813    char* tmps2=(char*)malloc((strlen(test)+2)*sizeof(char));
3814    sprintf(key,"sprefix_%d",level);
3815    sprintf(tmps2,"%s.",test);
3816    sprintf(levels,"%d",level);
3817    setMapInMaps(conf,"lenv","level",levels);
3818    setMapInMaps(conf,"lenv",key,tmps2);
3819    free(tmps2);
[470]3820    free(test);
[469]3821    level++;
3822    tmps1=strtok_r(NULL,".",&saveptr1);
3823  }
3824  int i=0;
3825  sprintf(buffer,"%s",conf_dir);
3826  for(i=0;i<level;i++){
3827    char *tmp0=zStrdup(buffer);
3828    sprintf(key,"sprefix_%d",i);
3829    map* tmp00=getMapFromMaps(conf,"lenv",key);
[503]3830    if(tmp00!=NULL)
3831      sprintf(buffer,"%s/%s",tmp0,tmp00->value);
[469]3832    free(tmp0);
3833    buffer[strlen(buffer)-1]=0;
3834    if(i+1<level){
3835      map* tmpMap=getMapFromMaps(conf,"lenv","metapath");
3836      if(tmpMap==NULL || strlen(tmpMap->value)==0){
3837        char *tmp01=zStrdup(tmp00->value);
[505]3838        tmp01[strlen(tmp01)-1]=0;
[469]3839        setMapInMaps(conf,"lenv","metapath",tmp01);
3840        free(tmp01);
[503]3841        tmp01=NULL;
[469]3842      }
3843      else{
[503]3844        if(tmp00!=NULL && tmpMap!=NULL){
[505]3845          char *tmp00s=zStrdup(tmp00->value);
3846          tmp00s[strlen(tmp00s)-1]=0;
3847          char *value=(char*)malloc((strlen(tmp00s)+strlen(tmpMap->value)+2)*sizeof(char));
3848          sprintf(value,"%s/%s",tmpMap->value,tmp00s);
[503]3849          setMapInMaps(conf,"lenv","metapath",value);
3850          free(value);
[505]3851          free(tmp00s);
[503]3852          value=NULL;
3853        }
[469]3854      }
3855    }else{
[470]3856      char *tmp01=zStrdup(tmp00->value);
3857      tmp01[strlen(tmp01)-1]=0;
3858      setMapInMaps(conf,"lenv","Identifier",tmp01);
3859      free(tmp01);
[469]3860    }
3861  }
3862  char *tmp0=zStrdup(buffer);
3863  sprintf(buffer,"%s.zcfg",tmp0);
3864  free(tmp0);
[539]3865  free(lid);
[469]3866}
3867
[579]3868/**
3869 * Update the status of an ongoing service
3870 *
3871 * @param conf the maps containing the settings of the main.cfg file
3872 * @param percentCompleted percentage of completude of execution of the service
3873 * @param message information about the current step executed
3874 * @return the value of _updateStatus
3875 * @see _updateStatus
3876 */
[471]3877int updateStatus( maps* conf, const int percentCompleted, const char* message ){
3878  char tmp[4];
3879  snprintf(tmp,4,"%d",percentCompleted);
3880  setMapInMaps( conf, "lenv", "status", tmp );
3881  setMapInMaps( conf, "lenv", "message", message);
3882  return _updateStatus( conf );
3883}
3884
[579]3885/**
3886 * Access an input value
3887 *
3888 * @param inputs the maps to search for the input value
3889 * @param parameterName the input name to fetch the value
3890 * @param numberOfBytes the resulting size of the value to add (for binary
3891 *  values), -1 for basic char* data
3892 * @return a pointer to the input value if found, NULL in other case.
3893 */
[471]3894char* getInputValue( maps* inputs, const char* parameterName, size_t* numberOfBytes){
3895  map* res=getMapFromMaps(inputs,parameterName,"value");
3896  if(res!=NULL){
3897    map* size=getMapFromMaps(inputs,parameterName,"size");
3898    if(size!=NULL){
3899      *numberOfBytes=(size_t)atoi(size->value);
3900      return res->value;
3901    }else{
3902      *numberOfBytes=strlen(res->value);
3903      return res->value;
3904    }
3905  }
3906  return NULL;
3907}
3908
[579]3909/**
3910 * Set an output value
3911 *
3912 * @param outputs the maps to define the output value
3913 * @param parameterName the output name to set the value
3914 * @param data the value to set
3915 * @param numberOfBytes size of the value to add (for binary values), -1 for
3916 *  basic char* data
3917 * @return 0
3918 */
[471]3919int  setOutputValue( maps* outputs, const char* parameterName, char* data, size_t numberOfBytes ){
3920  if(numberOfBytes==-1){
3921    setMapInMaps(outputs,parameterName,"value",data);
3922  }else{
3923    char size[1024];
3924    map* tmp=getMapFromMaps(outputs,parameterName,"value");
[539]3925    if(tmp==NULL){
3926      setMapInMaps(outputs,parameterName,"value","");
3927      tmp=getMapFromMaps(outputs,parameterName,"value");
3928    }
[471]3929    free(tmp->value);
3930    tmp->value=(char*) malloc((numberOfBytes+1)*sizeof(char));
3931    memcpy(tmp->value,data,numberOfBytes);
[490]3932    sprintf(size,"%lu",numberOfBytes);
[471]3933    setMapInMaps(outputs,parameterName,"size",size);
3934  }
3935  return 0;
3936}
[576]3937
3938/**
3939 * Verify if a parameter value is valid.
3940 *
3941 * @param request the request map
3942 * @param res the error map potentially generated
[579]3943 * @param toCheck the parameter to use
[576]3944 * @param avalues the acceptable values (or null if testing only for presence)
3945 * @param mandatory verify the presence of the parameter if mandatory > 0
3946 */
3947void checkValidValue(map* request,map** res,const char* toCheck,const char** avalues,int mandatory){
3948  map* lres=*res;
3949  map* r_inputs = getMap (request,toCheck);
3950  if (r_inputs == NULL){
3951    if(mandatory>0){
3952      char *replace=_("Mandatory parameter <%s> was not specified");
3953      char *message=(char*)malloc((strlen(replace)+strlen(toCheck)+1)*sizeof(char));
3954      sprintf(message,replace,toCheck);
3955      if(lres==NULL){
3956        lres=createMap("code","MissingParameterValue");
3957        addToMap(lres,"text",message);
3958        addToMap(lres,"locator",toCheck);       
3959      }else{
3960        int length=1;
3961        map* len=getMap(lres,"length");
3962        if(len!=NULL){
3963          length=atoi(len->value);
3964        }
3965        setMapArray(lres,"text",length,message);
3966        setMapArray(lres,"locator",length,toCheck);
3967        setMapArray(lres,"code",length,"MissingParameter");
3968      }
3969      free(message);
3970    }
3971  }else{
3972    if(avalues==NULL)
3973      return;
3974    int nb=0;
3975    int hasValidValue=-1;
3976    while(avalues[nb]!=NULL){
3977      if(strcasecmp(avalues[nb],r_inputs->value)==0){
3978        hasValidValue=1;
3979        break;
3980      }
3981      nb++;
3982    }
3983    if(hasValidValue<0){
3984      char *replace=_("Ununderstood <%s> value, %s %s the only acceptable value.");
3985      nb=0;
3986      char *vvalues=NULL;
3987      char* num=_("is");
3988      while(avalues[nb]!=NULL){
3989        char *tvalues;
3990        if(vvalues==NULL){
3991          vvalues=(char*)malloc((strlen(avalues[nb])+3)*sizeof(char));
3992          sprintf(vvalues,"%s",avalues[nb]);
3993        }
3994        else{
3995          tvalues=zStrdup(vvalues);
3996          vvalues=(char*)realloc(vvalues,(strlen(tvalues)+strlen(avalues[nb])+3)*sizeof(char));
3997          sprintf(vvalues,"%s, %s",tvalues,avalues[nb]);
3998          free(tvalues);
3999          num=_("are");
4000        }
4001        nb++;
4002      }
4003      char *message=(char*)malloc((strlen(replace)+strlen(num)+strlen(vvalues)+strlen(toCheck)+1)*sizeof(char));
4004      sprintf(message,replace,toCheck,vvalues,num);
4005      if(lres==NULL){
4006        lres=createMap("code","InvalidParameterValue");
4007        addToMap(lres,"text",message);
4008        addToMap(lres,"locator",toCheck);       
4009      }else{
4010        int length=1;
4011        map* len=getMap(lres,"length");
4012        if(len!=NULL){
4013          length=atoi(len->value);
4014        }
4015        setMapArray(lres,"text",length,message);
4016        setMapArray(lres,"locator",length,toCheck);
4017        setMapArray(lres,"code",length,"InvalidParameterValue");
4018      }
4019    }
4020  }
4021  if(lres!=NULL){
4022    *res=lres;
4023  }
4024}
[578]4025
[579]4026/**
4027 * Access the last error message returned by the OS when trying to dynamically
4028 * load a shared library.
4029 *
4030 * @return the last error message
4031 * @warning The character string returned from getLastErrorMessage resides
[578]4032 * in a static buffer. The application should not write to this
4033 * buffer or attempt to free() it.
4034 */ 
[579]4035char* getLastErrorMessage() {                                             
4036#ifdef WIN32
4037  LPVOID lpMsgBuf;
4038  DWORD errCode = GetLastError();
4039  static char msg[ERROR_MSG_MAX_LENGTH];
4040  size_t i;
4041 
4042  DWORD length = FormatMessage(
4043                               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
4044                               FORMAT_MESSAGE_FROM_SYSTEM |
4045                               FORMAT_MESSAGE_IGNORE_INSERTS,
4046                               NULL,
4047                               errCode,
4048                               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
4049                               (LPTSTR) &lpMsgBuf,
4050                               0, NULL );       
4051 
4052#ifdef UNICODE         
4053  wcstombs_s( &i, msg, ERROR_MSG_MAX_LENGTH,
4054              (wchar_t*) lpMsgBuf, _TRUNCATE );
[578]4055#else
[579]4056  strcpy_s( msg, ERROR_MSG_MAX_LENGTH,
4057            (char *) lpMsgBuf );               
4058#endif 
4059  LocalFree(lpMsgBuf);
4060 
4061  return msg;
4062#else
4063  return dlerror();
[578]4064#endif
[579]4065}
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