source: branches/PublicaMundi_David_integration_01-devel/zoo-project/zoo-kernel/zoo_service_loader.c @ 677

Last change on this file since 677 was 677, checked in by david, 9 years ago
  • add add zcfg files loading
  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 50.7 KB
RevLine 
[607]1/*
[1]2 * Author : Gérald FENOY
3 *
[392]4 *  Copyright 2008-2013 GeoLabs SARL. All rights reserved.
[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
[541]25extern "C" int yylex ();
26extern "C" int crlex ();
[9]27
[550]28#ifdef USE_OTB
29#include "service_internal_otb.h"
30#else
31#define length(x) (sizeof(x) / sizeof(x[0]))
32#endif
33
[376]34#include "cgic.h"
35
[541]36extern "C"
37{
[1]38#include <libxml/tree.h>
39#include <libxml/xmlmemory.h>
40#include <libxml/parser.h>
41#include <libxml/xpath.h>
42#include <libxml/xpathInternals.h>
43}
[677]44#include "zoo_zcfg.h"
[1]45#include "ulinet.h"
46
[34]47#include <libintl.h>
48#include <locale.h>
[1]49#include <string.h>
50
51#include "service.h"
[34]52
[1]53#include "service_internal.h"
[640]54#include "server_internal.h"
55#include "response_print.h"
[621]56#include "request_parser.h"
[640]57#include "sqlapi.h"
[33]58
59#ifdef USE_PYTHON
[1]60#include "service_internal_python.h"
[33]61#endif
[1]62
[634]63#ifdef USE_SAGA
64#include "service_internal_saga.h"
65#endif
66
[1]67#ifdef USE_JAVA
68#include "service_internal_java.h"
69#endif
70
71#ifdef USE_PHP
72#include "service_internal_php.h"
73#endif
74
75#ifdef USE_JS
76#include "service_internal_js.h"
77#endif
78
[453]79#ifdef USE_RUBY
80#include "service_internal_ruby.h"
81#endif
82
[25]83#ifdef USE_PERL
84#include "service_internal_perl.h"
85#endif
[1]86
87#include <dirent.h>
88#include <signal.h>
89#include <unistd.h>
90#ifndef WIN32
91#include <dlfcn.h>
92#include <libgen.h>
93#else
94#include <windows.h>
95#include <direct.h>
[364]96#include <sys/types.h>
97#include <sys/stat.h>
98#include <unistd.h>
99#define pid_t int;
[1]100#endif
101#include <fcntl.h>
102#include <time.h>
103#include <stdarg.h>
104
[364]105#ifdef WIN32
[541]106extern "C"
107{
108  __declspec (dllexport) char *strcasestr (char const *a, char const *b)
[370]109#ifndef USE_MS
[541]110  {
111    char *x = zStrdup (a);
112    char *y = zStrdup (b);
113
114      x = _strlwr (x);
115      y = _strlwr (y);
116    char *pos = strstr (x, y);
117    char *ret = pos == NULL ? NULL : (char *) (a + (pos - x));
118      free (x);
119      free (y);
120      return ret;
121  };
[370]122#else
[541]123   ;
[370]124#endif
[364]125}
126#endif
127
[607]128/**
129 * Translation function for zoo-kernel
130 */
[34]131#define _(String) dgettext ("zoo-kernel",String)
[607]132/**
133 * Translation function for zoo-service
134 */
[376]135#define __(String) dgettext ("zoo-service",String)
[34]136
[582]137#ifdef WIN32
138  #ifndef PROGRAMNAME
139    #define PROGRAMNAME "zoo_loader.cgi"
140  #endif
141#endif
142
[541]143extern int getServiceFromFile (maps *, const char *, service **);
[34]144
[607]145/**
146 * Parse the service file using getServiceFromFile or use getServiceFromYAML
147 * if YAML support was activated.
148 *
149 * @param conf the conf maps containing the main.cfg settings
150 * @param file the file name to parse
151 * @param service the service to update witht the file content
152 * @param name the service name
153 * @return true if the file can be parsed or false
154 * @see getServiceFromFile, getServiceFromYAML
155 */
[541]156int
157readServiceFile (maps * conf, char *file, service ** service, char *name)
158{
159  int t = getServiceFromFile (conf, file, service);
[467]160#ifdef YAML
[541]161  if (t < 0)
162    {
163      t = getServiceFromYAML (conf, file, service, name);
164    }
[467]165#endif
166  return t;
167}
168
[607]169/**
170 * Replace a char by another one in a string
171 *
172 * @param str the string to update
173 * @param toReplace the char to replace
174 * @param toReplaceBy the char that will be used
175 */
[541]176void
177translateChar (char *str, char toReplace, char toReplaceBy)
178{
179  int i = 0, len = strlen (str);
180  for (i = 0; i < len; i++)
181    {
182      if (str[i] == toReplace)
183        str[i] = toReplaceBy;
184    }
[34]185}
[607]186/**
187 * Signal handling function which simply call exit(0).
188 *
189 * @param sig the signal number
190 */
[541]191void
192donothing (int sig)
193{
[478]194#ifdef DEBUG
[605]195  fprintf (stderr, "Signal %d after the ZOO-Kernel returned result!\n", sig);
[478]196#endif
[541]197  exit (0);
[105]198}
199
[607]200/**
201 * Signal handling function which create an ExceptionReport node containing the
202 * information message corresponding to the signal number.
203 *
204 * @param sig the signal number
205 */
[541]206void
207sig_handler (int sig)
208{
[9]209  char tmp[100];
[114]210  const char *ssig;
[541]211  switch (sig)
212    {
213    case SIGSEGV:
214      ssig = "SIGSEGV";
215      break;
216    case SIGTERM:
217      ssig = "SIGTERM";
218      break;
219    case SIGINT:
220      ssig = "SIGINT";
221      break;
222    case SIGILL:
223      ssig = "SIGILL";
224      break;
225    case SIGFPE:
226      ssig = "SIGFPE";
227      break;
228    case SIGABRT:
229      ssig = "SIGABRT";
230      break;
231    default:
232      ssig = "UNKNOWN";
233      break;
234    }
235  sprintf (tmp,
236           _
[605]237           ("ZOO Kernel failed to process your request, receiving signal %d = %s"),
[541]238           sig, ssig);
239  errorException (NULL, tmp, "InternalError", NULL);
[10]240#ifdef DEBUG
[541]241  fprintf (stderr, "Not this time!\n");
[10]242#endif
[541]243  exit (0);
[1]244}
245
[607]246/**
247 * Load a service provider and run the service function.
248 *
249 * @param myMap the conf maps containing the main.cfg settings
250 * @param s1 the service structure
251 * @param request_inputs map storing all the request parameters
252 * @param inputs the inputs maps
253 * @param ioutputs the outputs maps
254 * @param eres the result returned by the service execution
255 */
[541]256void
257loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs,
258                   maps ** inputs, maps ** ioutputs, int *eres)
259{
[34]260  char tmps1[1024];
261  char ntmp[1024];
[541]262  maps *m = *myMap;
263  maps *request_output_real_format = *ioutputs;
264  maps *request_input_real_format = *inputs;
[34]265  /**
266   * Extract serviceType to know what kind of service should be loaded
267   */
[541]268  map *r_inputs = NULL;
[34]269#ifndef WIN32
[541]270  getcwd (ntmp, 1024);
[34]271#else
[541]272  _getcwd (ntmp, 1024);
[34]273#endif
[541]274  r_inputs = getMap (s1->content, "serviceType");
[34]275#ifdef DEBUG
[541]276  fprintf (stderr, "LOAD A %s SERVICE PROVIDER \n", r_inputs->value);
277  fflush (stderr);
[34]278#endif
[605]279
280  map* libp = getMapFromMaps(m, "main", "libPath");
281 
[541]282  if (strlen (r_inputs->value) == 1
283      && strncasecmp (r_inputs->value, "C", 1) == 0)
[605]284  {
285     if (libp != NULL && libp->value != NULL) {
286            r_inputs = getMap (s1->content, "ServiceProvider");
287                sprintf (tmps1, "%s/%s", libp->value, r_inputs->value);
288         }
[677]289     else {
290        char *tmp_path = (char *) malloc ((strlen (s1->zcfg) + 1) * sizeof (char *));
291        sprintf (tmp_path, "%s", s1->zcfg);
292        char *dir = dirname (tmp_path);
[605]293        r_inputs = getMap (s1->content, "ServiceProvider");
[677]294        sprintf (tmps1, "%s/%s", dir, r_inputs->value);
295        free (tmp_path);
296
[605]297         }
[34]298#ifdef DEBUG
[541]299      fprintf (stderr, "Trying to load %s\n", tmps1);
[34]300#endif
301#ifdef WIN32
[541]302      HINSTANCE so =
303        LoadLibraryEx (tmps1, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
[34]304#else
[541]305      void *so = dlopen (tmps1, RTLD_LAZY);
[34]306#endif
[57]307#ifdef WIN32
[578]308      char* errstr = getLastErrorMessage();
[34]309#else
[541]310      char *errstr;
311      errstr = dlerror ();
[34]312#endif
[478]313#ifdef DEBUG
[578]314          fprintf (stderr, "%s loaded (%s) \n", tmps1, errstr);
[478]315#endif
[541]316      if (so != NULL)
317        {
[34]318#ifdef DEBUG
[541]319          fprintf (stderr, "Library loaded %s \n", errstr);
320          fprintf (stderr, "Service Shared Object = %s\n", r_inputs->value);
[34]321#endif
[541]322          r_inputs = getMap (s1->content, "serviceType");
[34]323#ifdef DEBUG
[541]324          dumpMap (r_inputs);
325          fprintf (stderr, "%s\n", r_inputs->value);
326          fflush (stderr);
[34]327#endif
[541]328          if (strncasecmp (r_inputs->value, "C-FORTRAN", 9) == 0)
329            {
330              r_inputs = getMap (request_inputs, "Identifier");
331              char fname[1024];
332              sprintf (fname, "%s_", r_inputs->value);
[34]333#ifdef DEBUG
[541]334              fprintf (stderr, "Try to load function %s\n", fname);
[34]335#endif
336#ifdef WIN32
[541]337              typedef int (CALLBACK * execute_t) (char ***, char ***,
338                                                  char ***);
339              execute_t execute = (execute_t) GetProcAddress (so, fname);
[34]340#else
[541]341              typedef int (*execute_t) (char ***, char ***, char ***);
342              execute_t execute = (execute_t) dlsym (so, fname);
[34]343#endif
344#ifdef DEBUG
345#ifdef WIN32
[578]346                          errstr = getLastErrorMessage();
[34]347#else
[541]348              errstr = dlerror ();
[34]349#endif
[541]350              fprintf (stderr, "Function loaded %s\n", errstr);
351#endif
[34]352
[541]353              char main_conf[10][30][1024];
354              char inputs[10][30][1024];
355              char outputs[10][30][1024];
356              for (int i = 0; i < 10; i++)
357                {
358                  for (int j = 0; j < 30; j++)
359                    {
360                      memset (main_conf[i][j], 0, 1024);
361                      memset (inputs[i][j], 0, 1024);
362                      memset (outputs[i][j], 0, 1024);
363                    }
364                }
365              mapsToCharXXX (m, (char ***) main_conf);
366              mapsToCharXXX (request_input_real_format, (char ***) inputs);
367              mapsToCharXXX (request_output_real_format, (char ***) outputs);
368              *eres =
369                execute ((char ***) &main_conf[0], (char ***) &inputs[0],
370                         (char ***) &outputs[0]);
[34]371#ifdef DEBUG
[541]372              fprintf (stderr, "Function run successfully \n");
[34]373#endif
[541]374              charxxxToMaps ((char ***) &outputs[0],
375                             &request_output_real_format);
376            }
377          else
378            {
[34]379#ifdef DEBUG
380#ifdef WIN32
[578]381                          errstr = getLastErrorMessage();
382              fprintf (stderr, "Function %s failed to load because of %s\n",
[541]383                       r_inputs->value, errstr);
[34]384#endif
385#endif
[541]386              typedef int (*execute_t) (maps **, maps **, maps **);
[677]387
388              fprintf(stderr,"%s \n",s1->name);
[34]389#ifdef WIN32
[541]390              execute_t execute =
[677]391                (execute_t) GetProcAddress (so, s1->name);
[34]392#else
[677]393              execute_t execute = (execute_t) dlsym (so, s1->name);
[34]394#endif
395
[541]396              if (execute == NULL)
397                {
[469]398#ifdef WIN32
[578]399                                  errstr = getLastErrorMessage();
[469]400#else
[541]401                  errstr = dlerror ();
[469]402#endif
[541]403                  char *tmpMsg =
[677]404                    (char *) malloc (2048 + strlen (s1->name));
[541]405                  sprintf (tmpMsg,
406                           _
407                           ("Error occured while running the %s function: %s"),
[677]408                           s1->name, errstr);
[541]409                  errorException (m, tmpMsg, "InternalError", NULL);
410                  free (tmpMsg);
[478]411#ifdef DEBUG
[677]412                  fprintf (stderr, "Function %s error %s\n", s1->name,
[541]413                           errstr);
[478]414#endif
[541]415                  *eres = -1;
416                  return;
417                }
[469]418
[34]419#ifdef DEBUG
420#ifdef WIN32
[578]421                          errstr = getLastErrorMessage();
[34]422#else
[541]423              errstr = dlerror ();
[34]424#endif
[541]425              fprintf (stderr, "Function loaded %s\n", errstr);
426#endif
[34]427
428#ifdef DEBUG
[541]429              fprintf (stderr, "Now run the function \n");
430              fflush (stderr);
[34]431#endif
[541]432              *eres =
433                execute (&m, &request_input_real_format,
434                         &request_output_real_format);
[34]435#ifdef DEBUG
[541]436              fprintf (stderr, "Function loaded and returned %d\n", eres);
437              fflush (stderr);
[34]438#endif
[541]439            }
[216]440#ifdef WIN32
[541]441          *ioutputs = dupMaps (&request_output_real_format);
442          FreeLibrary (so);
[216]443#else
[541]444          dlclose (so);
[216]445#endif
[541]446        }
447      else
448        {
[34]449      /**
450       * Unable to load the specified shared library
451       */
[541]452          char tmps[1024];
[34]453#ifdef WIN32
[578]454                  errstr = getLastErrorMessage();
[34]455#else
[578]456              errstr = dlerror ();
[34]457#endif
[605]458          sprintf (tmps, _("Unable to load C Library %s"), errstr);
[576]459          errorException(m,tmps,"InternalError",NULL);
[541]460          *eres = -1;
461        }
[34]462    }
463  else
[550]464
[634]465#ifdef USE_SAGA
466  if (strncasecmp (r_inputs->value, "SAGA", 6) == 0)
467    {
468      *eres =
469        zoo_saga_support (&m, request_inputs, s1,
470                            &request_input_real_format,
471                            &request_output_real_format);
472    }
473  else
474#endif
475
[550]476#ifdef USE_OTB
477  if (strncasecmp (r_inputs->value, "OTB", 6) == 0)
478    {
479      *eres =
480        zoo_otb_support (&m, request_inputs, s1,
481                            &request_input_real_format,
482                            &request_output_real_format);
483    }
484  else
485#endif
486
[34]487#ifdef USE_PYTHON
[541]488  if (strncasecmp (r_inputs->value, "PYTHON", 6) == 0)
489    {
490      *eres =
491        zoo_python_support (&m, request_inputs, s1,
492                            &request_input_real_format,
493                            &request_output_real_format);
[34]494    }
[541]495  else
[34]496#endif
[541]497
[34]498#ifdef USE_JAVA
[541]499  if (strncasecmp (r_inputs->value, "JAVA", 4) == 0)
500    {
501      *eres =
502        zoo_java_support (&m, request_inputs, s1, &request_input_real_format,
503                          &request_output_real_format);
504    }
505  else
[34]506#endif
507
508#ifdef USE_PHP
[541]509  if (strncasecmp (r_inputs->value, "PHP", 3) == 0)
510    {
511      *eres =
512        zoo_php_support (&m, request_inputs, s1, &request_input_real_format,
513                         &request_output_real_format);
514    }
515  else
[34]516#endif
[541]517
518
[34]519#ifdef USE_PERL
[541]520  if (strncasecmp (r_inputs->value, "PERL", 4) == 0)
521    {
522      *eres =
523        zoo_perl_support (&m, request_inputs, s1, &request_input_real_format,
524                          &request_output_real_format);
525    }
526  else
[34]527#endif
528
529#ifdef USE_JS
[541]530  if (strncasecmp (r_inputs->value, "JS", 2) == 0)
531    {
532      *eres =
533        zoo_js_support (&m, request_inputs, s1, &request_input_real_format,
534                        &request_output_real_format);
535    }
536  else
[34]537#endif
[453]538
539#ifdef USE_RUBY
[541]540  if (strncasecmp (r_inputs->value, "Ruby", 4) == 0)
541    {
542      *eres =
543        zoo_ruby_support (&m, request_inputs, s1, &request_input_real_format,
544                          &request_output_real_format);
545    }
546  else
[453]547#endif
548
[541]549    {
550      char tmpv[1024];
551      sprintf (tmpv,
552               _
553               ("Programming Language (%s) set in ZCFG file is not currently supported by ZOO Kernel.\n"),
554               r_inputs->value);
[576]555      errorException (m, tmpv, "InternalError", NULL);
[541]556      *eres = -1;
557    }
558  *myMap = m;
559  *ioutputs = request_output_real_format;
[34]560}
561
[384]562
[216]563#ifdef WIN32
564/**
565 * createProcess function: create a new process after setting some env variables
566 */
[541]567void
568createProcess (maps * m, map * request_inputs, service * s1, char *opts,
569               int cpid, maps * inputs, maps * outputs)
570{
[216]571  STARTUPINFO si;
572  PROCESS_INFORMATION pi;
[541]573  ZeroMemory (&si, sizeof (si));
574  si.cb = sizeof (si);
575  ZeroMemory (&pi, sizeof (pi));
576  char *tmp = (char *) malloc ((1024 + cgiContentLength) * sizeof (char));
577  char *tmpq = (char *) malloc ((1024 + cgiContentLength) * sizeof (char));
578  map *req = getMap (request_inputs, "request");
579  map *id = getMap (request_inputs, "identifier");
580  map *di = getMap (request_inputs, "DataInputs");
[216]581
[583]582  // The required size for the dataInputsKVP and dataOutputsKVP buffers
583  // may exceed cgiContentLength, hence a 2 kb extension. However, a
584  // better solution would be to have getMapsAsKVP() determine the required
585  // buffer size before allocating memory.     
586  char *dataInputsKVP = getMapsAsKVP (inputs, cgiContentLength + 2048, 0);
587  char *dataOutputsKVP = getMapsAsKVP (outputs, cgiContentLength + 2048, 1);
[384]588#ifdef DEBUG
[541]589  fprintf (stderr, "DATAINPUTSKVP %s\n", dataInputsKVP);
590  fprintf (stderr, "DATAOUTPUTSKVP %s\n", dataOutputsKVP);
[384]591#endif
[541]592  map *sid = getMapFromMaps (m, "lenv", "sid");
593  map *r_inputs = getMapFromMaps (m, "main", "tmpPath");
594  map *r_inputs1 = getMap (request_inputs, "metapath");
[605]595 
[541]596  int hasIn = -1;
597  if (r_inputs1 == NULL)
598    {
599      r_inputs1 = createMap ("metapath", "");
600      hasIn = 1;
601    }
602  map *r_inputs2 = getMap (request_inputs, "ResponseDocument");
603  if (r_inputs2 == NULL)
604    r_inputs2 = getMap (request_inputs, "RawDataOutput");
605  map *tmpPath = getMapFromMaps (m, "lenv", "cwd");
[216]606
[541]607  map *tmpReq = getMap (request_inputs, "xrequest");
[587]608 
609  if(r_inputs2 != NULL && tmpReq != NULL) {
610        const char key[] = "rfile=";
611        char* kvp = (char*) malloc((FILENAME_MAX + strlen(key))*sizeof(char));
612        char* filepath = kvp + strlen(key);
613        strncpy(kvp, key, strlen(key));
614        addToCache(m, tmpReq->value, tmpReq->value, "text/xml", strlen(tmpReq->value), 
615                   filepath, FILENAME_MAX);                               
616    if (filepath == NULL) {
617        errorException( m, _("Unable to cache HTTP POST Execute request."), "InternalError", NULL); 
618                return;
619    }   
620        sprintf(tmp,"\"metapath=%s&%s&cgiSid=%s",
621                r_inputs1->value,kvp,sid->value);
622    sprintf(tmpq,"metapath=%s&%s",
623                r_inputs1->value,kvp);
624        free(kvp);             
625  }
626  else if (r_inputs2 != NULL)
[541]627    {
628      sprintf (tmp,
[587]629               "\"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&%s=%s&cgiSid=%s",
[541]630               r_inputs1->value, req->value, id->value, dataInputsKVP,
631               r_inputs2->name, dataOutputsKVP, sid->value);
632      sprintf (tmpq,
633               "metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&%s=%s",
634               r_inputs1->value, req->value, id->value, dataInputsKVP,
[587]635               r_inputs2->name, dataOutputsKVP);                   
[541]636    }
637  else
638    {
639      sprintf (tmp,
[587]640               "\"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&cgiSid=%s",
[541]641               r_inputs1->value, req->value, id->value, dataInputsKVP,
642               sid->value);
643      sprintf (tmpq,
644               "metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s",
645               r_inputs1->value, req->value, id->value, dataInputsKVP,
[587]646               sid->value);   
[541]647    }
648
649  if (hasIn > 0)
650    {
651      freeMap (&r_inputs1);
652      free (r_inputs1);
653    }
654  char *tmp1 = zStrdup (tmp);
[587]655  sprintf (tmp, "\"%s\" %s \"%s\"", PROGRAMNAME, tmp1, sid->value); 
[541]656  free (dataInputsKVP);
657  free (dataOutputsKVP);
[384]658#ifdef DEBUG
[541]659  fprintf (stderr, "REQUEST IS : %s \n", tmp);
[384]660#endif
[554]661
662  map* usid = getMapFromMaps (m, "lenv", "usid");
663  if (usid != NULL && usid->value != NULL) {
664    SetEnvironmentVariable("USID", TEXT (usid->value));
665  }
666
[541]667  SetEnvironmentVariable ("CGISID", TEXT (sid->value));
668  SetEnvironmentVariable ("QUERY_STRING", TEXT (tmpq));
[587]669  // knut: Prevent REQUEST_METHOD=POST in background process call to cgic:main (process hangs when reading cgiIn):
670  SetEnvironmentVariable("REQUEST_METHOD", "GET");
671 
[216]672  char clen[1000];
[541]673  sprintf (clen, "%d", strlen (tmpq));
674  SetEnvironmentVariable ("CONTENT_LENGTH", TEXT (clen));
675
676  if (!CreateProcess (NULL,     // No module name (use command line)
677                      TEXT (tmp),       // Command line
678                      NULL,     // Process handle not inheritable
679                      NULL,     // Thread handle not inheritable
680                      FALSE,    // Set handle inheritance to FALSE
681                      CREATE_NO_WINDOW, // Apache won't wait until the end
682                      NULL,     // Use parent's environment block
683                      NULL,     // Use parent's starting directory
684                      &si,      // Pointer to STARTUPINFO struct
685                      &pi)      // Pointer to PROCESS_INFORMATION struct
686    )
687    {
[384]688#ifdef DEBUG
[541]689      fprintf (stderr, "CreateProcess failed (%d).\n", GetLastError ());
[384]690#endif
[587]691      if (tmp != NULL) {
692        free(tmp);
693      }
694      if (tmpq != NULL) {
695        free(tmpq);
696      }         
[541]697      return;
698    }
699  else
700    {
[384]701#ifdef DEBUG
[587]702      fprintf (stderr, "CreateProcess successful (%d).\n\n\n\n",
[541]703               GetLastError ());
[384]704#endif
[541]705    }
706  CloseHandle (pi.hProcess);
707  CloseHandle (pi.hThread);
[587]708 
709  if (tmp != NULL) {
710    free(tmp);
711  }
712  if (tmpq != NULL) {
713    free(tmpq);
714  }
715 
[384]716#ifdef DEBUG
[541]717  fprintf (stderr, "CreateProcess finished !\n");
[384]718#endif
[216]719}
720#endif
721
[607]722/**
723 * Process the request.
724 *
725 * @param inputs the request parameters map
726 * @return 0 on sucess, other value on failure
727 * @see conf_read,recursReaddirF
728 */
[541]729int
730runRequest (map ** inputs)
[1]731{
[541]732
[53]733#ifndef USE_GDB
[554]734#ifndef WIN32
[541]735  signal (SIGCHLD, SIG_IGN);
[554]736#endif 
[541]737  signal (SIGSEGV, sig_handler);
738  signal (SIGTERM, sig_handler);
739  signal (SIGINT, sig_handler);
740  signal (SIGILL, sig_handler);
741  signal (SIGFPE, sig_handler);
742  signal (SIGABRT, sig_handler);
[53]743#endif
[9]744
[541]745  map *r_inputs = NULL;
746  map *request_inputs = *inputs;
[605]747#ifdef IGNORE_METAPATH
748  addToMap(request_inputs, "metapath", "");
749#endif 
[541]750  maps *m = NULL;
751  char *REQUEST = NULL;
[1]752  /**
753   * Parsing service specfic configuration file
754   */
[541]755  m = (maps *) malloc (MAPS_SIZE);
756  if (m == NULL)
757    {
758      return errorException (m, _("Unable to allocate memory."),
759                             "InternalError", NULL);
760    }
[1]761  char ntmp[1024];
762#ifndef WIN32
[541]763  getcwd (ntmp, 1024);
[1]764#else
[541]765  _getcwd (ntmp, 1024);
[1]766#endif
[541]767  r_inputs = getMapOrFill (&request_inputs, "metapath", "");
[282]768
[9]769  char conf_file[10240];
[541]770  snprintf (conf_file, 10240, "%s/%s/main.cfg", ntmp, r_inputs->value);
771  if (conf_read (conf_file, m) == 2)
772    {
773      errorException (NULL, _("Unable to load the main.cfg file."),
774                      "InternalError", NULL);
775      free (m);
776      return 1;
777    }
[9]778#ifdef DEBUG
[541]779  fprintf (stderr, "***** BEGIN MAPS\n");
780  dumpMaps (m);
781  fprintf (stderr, "***** END MAPS\n");
[9]782#endif
783
[541]784  map *getPath = getMapFromMaps (m, "main", "gettextPath");
785  if (getPath != NULL)
786    {
787      bindtextdomain ("zoo-kernel", getPath->value);
788      bindtextdomain ("zoo-services", getPath->value);
789    }
790  else
791    {
792      bindtextdomain ("zoo-kernel", "/usr/share/locale/");
793      bindtextdomain ("zoo-services", "/usr/share/locale/");
794    }
[364]795
[381]796
[364]797  /**
798   * Manage our own error log file (usefull to separate standard apache debug
799   * messages from the ZOO-Kernel ones but also for IIS users to avoid wrong
800   * headers messages returned by the CGI due to wrong redirection of stderr)
801   */
[541]802  FILE *fstde = NULL;
803  map *fstdem = getMapFromMaps (m, "main", "logPath");
804  if (fstdem != NULL)
805    fstde = freopen (fstdem->value, "a+", stderr);
[364]806
[541]807  r_inputs = getMap (request_inputs, "language");
808  if (r_inputs == NULL)
[640]809    r_inputs = getMap (request_inputs, "AcceptLanguages");
810  if (r_inputs == NULL)
[541]811    r_inputs = getMapFromMaps (m, "main", "language");
812  if (r_inputs != NULL)
813    {
814      if (isValidLang (m, r_inputs->value) < 0)
815        {
816          char tmp[1024];
817          sprintf (tmp,
818                   _
819                   ("The value %s is not supported for the <language> parameter"),
820                   r_inputs->value);
821          errorException (m, tmp, "InvalidParameterValue", "language");
822          freeMaps (&m);
823          free (m);
824          free (REQUEST);
825          return 1;
[501]826
[541]827        }
828      char *tmp = zStrdup (r_inputs->value);
829      setMapInMaps (m, "main", "language", tmp);
[466]830#ifdef DEB
[541]831      char tmp2[12];
832      sprintf (tmp2, "%s.utf-8", tmp);
833      translateChar (tmp2, '-', '_');
834      setlocale (LC_ALL, tmp2);
[466]835#else
[541]836      translateChar (tmp, '-', '_');
837      setlocale (LC_ALL, tmp);
[466]838#endif
[444]839#ifndef WIN32
[541]840      setenv ("LC_ALL", tmp, 1);
[444]841#else
[541]842      char tmp1[12];
843      sprintf (tmp1, "LC_ALL=%s", tmp);
844      putenv (tmp1);
[376]845#endif
[541]846      free (tmp);
847    }
848  else
849    {
850      setlocale (LC_ALL, "en_US");
[444]851#ifndef WIN32
[541]852      setenv ("LC_ALL", "en_US", 1);
[444]853#else
[541]854      char tmp1[12];
855      sprintf (tmp1, "LC_ALL=en_US");
856      putenv (tmp1);
[376]857#endif
[541]858      setMapInMaps (m, "main", "language", "en-US");
859    }
[34]860  setlocale (LC_NUMERIC, "en_US");
[541]861  bind_textdomain_codeset ("zoo-kernel", "UTF-8");
862  textdomain ("zoo-kernel");
863  bind_textdomain_codeset ("zoo-services", "UTF-8");
864  textdomain ("zoo-services");
[34]865
[541]866  map *lsoap = getMap (request_inputs, "soap");
867  if (lsoap != NULL && strcasecmp (lsoap->value, "true") == 0)
868    setMapInMaps (m, "main", "isSoap", "true");
[280]869  else
[541]870    setMapInMaps (m, "main", "isSoap", "false");
[34]871
[584]872  if(strlen(cgiServerName)>0)
[654]873    {
874      char tmpUrl[1024];
[584]875       
[654]876      if ( getenv("HTTPS") != NULL && strncmp(getenv("HTTPS"), "on", 2) == 0 ) { // Knut: check if non-empty instead of "on"?           
877        if ( strncmp(cgiServerPort, "443", 3) == 0 ) { 
878          sprintf(tmpUrl, "https://%s%s", cgiServerName, cgiScriptName);
[584]879        }
880        else {
[654]881          sprintf(tmpUrl, "https://%s:%s%s", cgiServerName, cgiServerPort, cgiScriptName);
[584]882        }
[654]883      }
884      else {
885        if ( strncmp(cgiServerPort, "80", 2) == 0 ) { 
886          sprintf(tmpUrl, "http://%s%s", cgiServerName, cgiScriptName);
887        }
888        else {
889          sprintf(tmpUrl, "http://%s:%s%s", cgiServerName, cgiServerPort, cgiScriptName);
890        }
891      }
[445]892#ifdef DEBUG
[654]893      fprintf(stderr,"*** %s ***\n",tmpUrl);
[445]894#endif
[654]895      setMapInMaps(m,"main","serverAddress",tmpUrl);
896    }
[381]897
[654]898  //Check for minimum inputs
899  map* version=getMap(request_inputs,"version");
900  if(version==NULL)
901    version=getMapFromMaps(m,"main","version");
902  setMapInMaps(m,"main","rversion",version->value);
903  int vid=getVersionId(version->value);
904  if(vid<0)
905    vid=0;
[576]906  map* err=NULL;
[654]907  const char **vvr=(const char**)requests[vid];
908  checkValidValue(request_inputs,&err,"request",vvr,1);
[576]909  const char *vvs[]={
910    "WPS",
911    NULL
912  };
913  if(err!=NULL){
914    checkValidValue(request_inputs,&err,"service",(const char**)vvs,1);
915    printExceptionReportResponse (m, err);
916    freeMap(&err);
917    free(err);
918    if (count (request_inputs) == 1)
919      {
920        freeMap (&request_inputs);
921        free (request_inputs);
922      }
923    freeMaps (&m);
924    free (m);
925    return 1;
926  }
927  checkValidValue(request_inputs,&err,"service",(const char**)vvs,1);
[640]928
[576]929  const char *vvv[]={
930    "1.0.0",
[640]931    "2.0.0",
[576]932    NULL
933  };
[541]934  r_inputs = getMap (request_inputs, "Request");
[576]935  REQUEST = zStrdup (r_inputs->value);
[654]936  int reqId=-1;
[576]937  if (strncasecmp (REQUEST, "GetCapabilities", 15) != 0){
938    checkValidValue(request_inputs,&err,"version",(const char**)vvv,1);
[654]939    int j=0;
940    for(j=0;j<nbSupportedRequests;j++){
941      if(requests[vid][j]!=NULL && requests[vid][j+1]!=NULL){
942        if(j<nbReqIdentifier && strncasecmp(REQUEST,requests[vid][j+1],strlen(REQUEST))==0){
943          checkValidValue(request_inputs,&err,"identifier",NULL,1);
944          reqId=j+1;
945          break;
946        }
947        else
948          if(j>=nbReqIdentifier && j<nbReqIdentifier+nbReqJob && 
949             strncasecmp(REQUEST,requests[vid][j+1],strlen(REQUEST))==0){
950            checkValidValue(request_inputs,&err,"jobid",NULL,1);
951            reqId=j+1;
952            break;
953          }
954      }else
955        break;
956    }
[576]957  }else{
958    checkValidValue(request_inputs,&err,"AcceptVersions",(const char**)vvv,-1);
[658]959    map* version1=getMap(request_inputs,"AcceptVersions");
960    if(version1!=NULL){
961      if(strstr(version1->value,schemas[1][0])!=NULL)
[640]962        addToMap(request_inputs,"version",schemas[1][0]);
963      else
[658]964        addToMap(request_inputs,"version",version1->value);
965      version=getMap(request_inputs,"version");
966      setMapInMaps(m,"main","rversion",version->value);
967      vid=getVersionId(version->value);
[640]968    }
[576]969  }
970  if(err!=NULL){
971    printExceptionReportResponse (m, err);
972    freeMap(&err);
973    free(err);
974    if (count (request_inputs) == 1)
975      {
976        freeMap (&request_inputs);
977        free (request_inputs);
978      }
979    free(REQUEST);
980    freeMaps (&m);
981    free (m);
982    return 1;
983  }
[1]984
[541]985  r_inputs = getMap (request_inputs, "serviceprovider");
986  if (r_inputs == NULL)
987    {
988      addToMap (request_inputs, "serviceprovider", "");
989    }
[1]990
[541]991  maps *request_output_real_format = NULL;
992  map *tmpm = getMapFromMaps (m, "main", "serverAddress");
993  if (tmpm != NULL)
994    SERVICE_URL = zStrdup (tmpm->value);
[1]995  else
[541]996    SERVICE_URL = zStrdup (DEFAULT_SERVICE_URL);
[1]997
[607]998
999
[541]1000  service *s1;
1001  int scount = 0;
[1]1002#ifdef DEBUG
[541]1003  dumpMap (r_inputs);
[1]1004#endif
1005  char conf_dir[1024];
1006  int t;
1007  char tmps1[1024];
1008
[541]1009  r_inputs = NULL;
1010  r_inputs = getMap (request_inputs, "metapath");
[605]1011 
[541]1012  if (r_inputs != NULL)
1013    snprintf (conf_dir, 1024, "%s/%s", ntmp, r_inputs->value);
[9]1014  else
[541]1015    snprintf (conf_dir, 1024, "%s", ntmp);
[9]1016
[607]1017
[541]1018  if (strncasecmp (REQUEST, "GetCapabilities", 15) == 0)
1019    {
[1]1020#ifdef DEBUG
[541]1021      dumpMap (r_inputs);
[1]1022#endif
[541]1023      xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0");
[656]1024      xmlNodePtr n=printGetCapabilitiesHeader(doc,m,(version!=NULL?version->value:"1.0.0"));
[677]1025      CapabilitiesAllProcess(m,n);
[576]1026      /**
1027       * Here we need to close stdout to ensure that unsupported chars
1028       * has been found in the zcfg and then printed on stdout
1029       */
[677]1030      /*
[541]1031      int saved_stdout = dup (fileno (stdout));
1032      dup2 (fileno (stderr), fileno (stdout));
[584]1033      if (int res =               
[607]1034          recursReaddirF (m, zooRegistry, n, conf_dir, NULL, saved_stdout, 0,
[541]1035                          printGetCapabilitiesForProcess) < 0)
1036        {
1037          freeMaps (&m);
1038          free (m);
[607]1039          if(zooRegistry!=NULL){
1040            freeRegistry(&zooRegistry);
1041            free(zooRegistry);
1042          }
[541]1043          free (REQUEST);
1044          free (SERVICE_URL);
1045          fflush (stdout);
1046          return res;
1047        }
[656]1048      fflush (stdout);
[541]1049      dup2 (saved_stdout, fileno (stdout));
[677]1050      */
[541]1051      printDocument (m, doc, getpid ());
1052      freeMaps (&m);
1053      free (m);
[677]1054      /*
[607]1055      if(zooRegistry!=NULL){
1056        freeRegistry(&zooRegistry);
1057        free(zooRegistry);
1058      }
[677]1059*/
[541]1060      free (REQUEST);
1061      free (SERVICE_URL);
1062      fflush (stdout);
[9]1063      return 0;
[1]1064    }
[541]1065  else
1066    {
[654]1067      r_inputs = getMap (request_inputs, "JobId");
1068      if(reqId>nbReqIdentifier){
1069        if (strncasecmp (REQUEST, "GetStatus", strlen(REQUEST)) == 0 ||
1070            strncasecmp (REQUEST, "GetResult", strlen(REQUEST)) == 0){
1071          runGetStatus(m,r_inputs->value,REQUEST);
1072          freeMaps (&m);
1073          free (m);
1074          free (REQUEST);
1075          free (SERVICE_URL);
1076          return 0;
1077        }
1078        else
1079          if (strncasecmp (REQUEST, "Dismiss", strlen(REQUEST)) == 0){
1080            runDismiss(m,r_inputs->value);
1081            freeMaps (&m);
1082            free (m);
1083            free (REQUEST);
1084            free (SERVICE_URL);
1085            return 0;
1086           
1087          }
1088        return 0;
1089      }
1090      if(reqId<=nbReqIdentifier){
1091        r_inputs = getMap (request_inputs, "Identifier");
[9]1092
[654]1093        struct dirent *dp;
1094        DIR *dirp = opendir (conf_dir);
1095        if (dirp == NULL)
1096          {
1097            errorException (m, _("The specified path path does not exist."),
1098                            "InvalidParameterValue", conf_dir);
1099            freeMaps (&m);
1100            free (m);
1101            free (REQUEST);
1102            free (SERVICE_URL);
1103            return 0;
1104          }
1105        if (strncasecmp (REQUEST, "DescribeProcess", 15) == 0)
1106          {
1107            /**
1108             * Loop over Identifier list
1109             */
1110            xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0");
1111            r_inputs = NULL;
1112            r_inputs = getMap (request_inputs, "version");
1113            xmlNodePtr n = printWPSHeader(doc,m,"DescribeProcess",
[656]1114                                          root_nodes[vid][1],(version!=NULL?version->value:"1.0.0"),1);
[469]1115
[654]1116            r_inputs = getMap (request_inputs, "Identifier");
[503]1117
[654]1118            char *orig = zStrdup (r_inputs->value);
[541]1119
[677]1120        DescribeProcess(m,n,orig);
[654]1121            fflush (stdout);
[677]1122        int saved_stdout;
[654]1123            dup2 (saved_stdout, fileno (stdout));
1124            free (orig);
1125            printDocument (m, doc, getpid ());
1126            freeMaps (&m);
1127            free (m);
1128            free (REQUEST);
1129            free (SERVICE_URL);
1130            fflush (stdout);
1131            return 0;
[607]1132          }
[654]1133        else if (strncasecmp (REQUEST, "Execute", strlen (REQUEST)) != 0)
1134          {
1135            map* version=getMapFromMaps(m,"main","rversion");
1136            int vid=getVersionId(version->value);
1137            int len,j=0;
1138            for(j=0;j<nbSupportedRequests;j++){
1139              if(requests[vid][j]!=NULL)
1140                len+=strlen(requests[vid][j])+2;
1141              else{
1142                len+=4;
1143                break;
1144              }
1145            }
1146            char *tmpStr=(char*)malloc(len*sizeof(char));
1147            int it=0;
1148            for(j=0;j<nbSupportedRequests;j++){
1149              if(requests[vid][j]!=NULL){
1150                if(it==0){
1151                  sprintf(tmpStr,"%s",requests[vid][j]);
1152                  it++;
1153                }else{
1154                  char *tmpS=zStrdup(tmpStr);
1155                  if(j+1<nbSupportedRequests && requests[vid][j+1]==NULL){
1156                    sprintf(tmpStr,"%s and %s",tmpS,requests[vid][j]);
1157                  }else{
1158                    sprintf(tmpStr,"%s, %s",tmpS,requests[vid][j]);
1159                 
1160                  }
1161                  free(tmpS);
1162                }
1163              }
1164              else{
1165                len+=4;
1166                break;
1167              }
1168            }
1169            char* message=(char*)malloc((61+len)*sizeof(char));
1170            sprintf(message,"The <request> value was not recognized. Allowed values are %s.",tmpStr);
1171            errorException (m,_(message),"InvalidParameterValue", "request");
[541]1172#ifdef DEBUG
[654]1173            fprintf (stderr, "No request found %s", REQUEST);
[541]1174#endif
[654]1175            closedir (dirp);
1176            freeMaps (&m);
1177            free (m);
1178            free (REQUEST);
1179            free (SERVICE_URL);
1180            fflush (stdout);
1181            return 0;
[607]1182          }
[654]1183        closedir (dirp);
1184      }
[1]1185    }
[541]1186
[654]1187  map *postRequest = NULL;
1188  postRequest = getMap (request_inputs, "xrequest");
1189
1190  if(vid==1 && postRequest==NULL){
1191    errorException (m,_("Unable to run Execute request using the GET HTTP method"),"InvalidParameterValue", "request"); 
1192    freeMaps (&m);
1193    free (m);
1194    free (REQUEST);
1195    free (SERVICE_URL);
1196    fflush (stdout);
1197    return 0;
1198  }
1199 
[541]1200  s1 = NULL;
[677]1201  r_inputs = getMap (request_inputs, "Identifier");
1202  s1 = search_service (r_inputs->value);
1203 int saved_stdout = dup (fileno (stdout));
1204 
1205 
[541]1206  if (s1 == NULL)
1207    {
1208      char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value));
1209      sprintf (tmpMsg,
1210               _
[605]1211               ("The value for <identifier> seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."),
[541]1212               r_inputs->value);
1213      errorException (m, tmpMsg, "InvalidParameterValue", "identifier");
1214      free (tmpMsg);
1215      freeMaps (&m);
1216      free (m);
1217      free (REQUEST);
1218      free (SERVICE_URL);
1219      return 0;
1220    }
1221  close (saved_stdout);
[1]1222
1223#ifdef DEBUG
[541]1224  dumpService (s1);
[1]1225#endif
1226  int j;
[381]1227
[541]1228
[1]1229  /**
[344]1230   * Create the input and output maps data structure
[1]1231   */
[541]1232  int i = 0;
[1]1233  HINTERNET hInternet;
1234  HINTERNET res;
[541]1235  hInternet = InternetOpen (
[1]1236#ifndef WIN32
[654]1237                            (LPCTSTR)
[1]1238#endif
[654]1239                            "ZooWPSClient\0",
1240                            INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
[1]1241
1242#ifndef WIN32
[541]1243  if (!CHECK_INET_HANDLE (hInternet))
1244    fprintf (stderr, "WARNING : hInternet handle failed to initialize");
[1]1245#endif
[541]1246  maps *request_input_real_format = NULL;
1247  maps *tmpmaps = request_input_real_format;
1248
1249
[621]1250  if(parseRequest(&m,&request_inputs,s1,&request_input_real_format,&request_output_real_format,&hInternet)<0){
1251    freeMaps (&m);
1252    free (m);
1253    free (REQUEST);
1254    free (SERVICE_URL);
1255    InternetCloseHandle (&hInternet);
1256    return 0;
1257  }
[1]1258
[652]1259
1260  // Define each env variable in runing environment
[541]1261  maps *curs = getMaps (m, "env");
1262  if (curs != NULL)
1263    {
1264      map *mapcs = curs->content;
1265      while (mapcs != NULLMAP)
1266        {
[1]1267#ifndef WIN32
[541]1268          setenv (mapcs->name, mapcs->value, 1);
[1]1269#else
1270#ifdef DEBUG
[541]1271          fprintf (stderr, "[ZOO: setenv (%s=%s)]\n", mapcs->name,
1272                   mapcs->value);
[1]1273#endif
[541]1274          if (mapcs->value[strlen (mapcs->value) - 2] == '\r')
1275            {
[1]1276#ifdef DEBUG
[541]1277              fprintf (stderr, "[ZOO: Env var finish with \r]\n");
[1]1278#endif
[541]1279              mapcs->value[strlen (mapcs->value) - 1] = 0;
1280            }
[1]1281#ifdef DEBUG
[541]1282          if (SetEnvironmentVariable (mapcs->name, mapcs->value) == 0)
1283            {
1284              fflush (stderr);
1285              fprintf (stderr, "setting variable... %s\n", "OK");
1286            }
1287          else
1288            {
1289              fflush (stderr);
1290              fprintf (stderr, "setting variable... %s\n", "OK");
1291            }
[1]1292#else
[541]1293
1294
1295          SetEnvironmentVariable (mapcs->name, mapcs->value);
[1]1296#endif
[541]1297          char *toto =
1298            (char *)
1299            malloc ((strlen (mapcs->name) + strlen (mapcs->value) +
1300                     2) * sizeof (char));
1301          sprintf (toto, "%s=%s", mapcs->name, mapcs->value);
1302          putenv (toto);
[1]1303#ifdef DEBUG
[541]1304          fflush (stderr);
[1]1305#endif
1306#endif
1307#ifdef DEBUG
[541]1308          fprintf (stderr, "[ZOO: setenv (%s=%s)]\n", mapcs->name,
1309                   mapcs->value);
1310          fflush (stderr);
[1]1311#endif
[541]1312          mapcs = mapcs->next;
1313        }
[1]1314    }
[541]1315
[1]1316#ifdef DEBUG
[541]1317  dumpMap (request_inputs);
[1]1318#endif
1319
[541]1320  map *status = getMap (request_inputs, "status");
[654]1321  if(vid==0){
1322    // Need to check if we need to fork to load a status enabled
1323    r_inputs = NULL;
1324    map *store = getMap (request_inputs, "storeExecuteResponse");
1325    /**
1326     * 05-007r7 WPS 1.0.0 page 57 :
1327     * 'If status="true" and storeExecuteResponse is "false" then the service
1328     * shall raise an exception.'
1329     */
1330    if (status != NULL && strcmp (status->value, "true") == 0 &&
1331        store != NULL && strcmp (store->value, "false") == 0)
1332      {
1333        errorException (m,
1334                        _
1335                        ("The status parameter cannot be set to true if storeExecuteResponse is set to false. Please modify your request parameters."),
1336                        "InvalidParameterValue", "storeExecuteResponse");
[677]1337        //freeService (&s1);
[654]1338        free (s1);
1339        freeMaps (&m);
1340        free (m);
1341       
1342        freeMaps (&request_input_real_format);
1343        free (request_input_real_format);
1344       
1345        freeMaps (&request_output_real_format);
1346        free (request_output_real_format);
[94]1347
[654]1348        free (REQUEST);
1349        free (SERVICE_URL);
1350        return 1;
1351      }
1352    r_inputs = getMap (request_inputs, "storeExecuteResponse");
1353  }else{
1354    // Define status depending on the WPS 2.0.0 mode attribute
1355    status = getMap (request_inputs, "mode");
1356    map* mode=getMap(s1->content,"mode");
1357    if(strcasecmp(status->value,"async")==0){
1358      if(mode!=NULL && strcasecmp(mode->value,"async")==0)
1359        addToMap(request_inputs,"status","true");
1360      else{
1361        if(mode!=NULL){
1362          // see ref. http://docs.opengeospatial.org/is/14-065/14-065.html#61
1363          errorException (m,_("The process does not permit the desired execution mode."),"NoSuchMode", mode->value); 
1364          fflush (stdout);
1365          freeMaps (&m);
1366          free (m);
1367          freeMaps (&request_input_real_format);
1368          free (request_input_real_format);
1369          freeMaps (&request_output_real_format);
1370          free (request_output_real_format);
1371          free (REQUEST);
1372          free (SERVICE_URL);
1373          return 0;
1374        }else
1375          addToMap(request_inputs,"status","true");
1376      }
1377    }
1378    else{
1379      if(strcasecmp(status->value,"auto")==0){
1380        if(mode!=NULL){
1381          if(strcasecmp(mode->value,"async")==0)
1382            addToMap(request_inputs,"status","false");
1383          else
1384            addToMap(request_inputs,"status","true");
1385        }
1386        else
1387          addToMap(request_inputs,"status","false");
1388      }else
1389        addToMap(request_inputs,"status","false");
1390    }
1391    status = getMap (request_inputs, "status");
1392  }
[541]1393
1394  int eres = SERVICE_STARTED;
1395  int cpid = getpid ();
1396
[453]1397  /**
1398   * Initialize the specific [lenv] section which contains runtime variables:
1399   *
1400   *  - usid : it is an unique identification number
1401   *  - sid : it is the process idenfitication number (OS)
[640]1402   *  - uusid : it is an universally unique identification number
[453]1403   *  - status : value between 0 and 100 to express the  completude of
1404   * the operations of the running service
1405   *  - message : is a string where you can store error messages, in case
1406   * service is failing, or o provide details on the ongoing operation.
1407   *  - cwd : is the current working directory
1408   *  - soap : is a boolean value, true if the request was contained in a SOAP
1409   * Envelop
1410   *  - sessid : string storing the session identifier (only when cookie is
1411   * used)
1412   *  - cgiSid : only defined on Window platforms (for being able to identify
1413   * the created process)
1414   *
1415   */
[541]1416  maps *_tmpMaps = (maps *) malloc (MAPS_SIZE);
1417  _tmpMaps->name = zStrdup ("lenv");
[32]1418  char tmpBuff[100];
[514]1419  struct ztimeval tp;
[541]1420  if (zGettimeofday (&tp, NULL) == 0)
1421    sprintf (tmpBuff, "%i", (cpid + ((int) tp.tv_sec + (int) tp.tv_usec)));
[514]1422  else
[541]1423    sprintf (tmpBuff, "%i", (cpid + (int) time (NULL)));
[652]1424  _tmpMaps->content = createMap ("osid", tmpBuff);
[541]1425  _tmpMaps->next = NULL;
1426  sprintf (tmpBuff, "%i", cpid);
1427  addToMap (_tmpMaps->content, "sid", tmpBuff);
[640]1428  char* tmpUuid=get_uuid();
1429  addToMap (_tmpMaps->content, "uusid", tmpUuid);
[652]1430  addToMap (_tmpMaps->content, "usid", tmpUuid);
[640]1431  free(tmpUuid);
[541]1432  addToMap (_tmpMaps->content, "status", "0");
1433  addToMap (_tmpMaps->content, "cwd", ntmp);
1434  addToMap (_tmpMaps->content, "message", _("No message provided"));
1435  map *ltmp = getMap (request_inputs, "soap");
1436  if (ltmp != NULL)
1437    addToMap (_tmpMaps->content, "soap", ltmp->value);
[280]1438  else
[541]1439    addToMap (_tmpMaps->content, "soap", "false");
[654]1440
1441  // Parse the session file and add it to the main maps
[541]1442  if (cgiCookie != NULL && strlen (cgiCookie) > 0)
1443    {
1444      int hasValidCookie = -1;
1445      char *tcook = zStrdup (cgiCookie);
1446      char *tmp = NULL;
1447      map *testing = getMapFromMaps (m, "main", "cookiePrefix");
1448      if (testing == NULL)
1449        {
1450          tmp = zStrdup ("ID=");
1451        }
[390]1452      else
[541]1453        {
1454          tmp =
1455            (char *) malloc ((strlen (testing->value) + 2) * sizeof (char));
1456          sprintf (tmp, "%s=", testing->value);
1457        }
1458      if (strstr (cgiCookie, ";") != NULL)
1459        {
1460          char *token, *saveptr;
1461          token = strtok_r (cgiCookie, ";", &saveptr);
1462          while (token != NULL)
1463            {
1464              if (strcasestr (token, tmp) != NULL)
1465                {
1466                  if (tcook != NULL)
1467                    free (tcook);
1468                  tcook = zStrdup (token);
1469                  hasValidCookie = 1;
1470                }
1471              token = strtok_r (NULL, ";", &saveptr);
1472            }
1473        }
1474      else
1475        {
1476          if (strstr (cgiCookie, "=") != NULL
1477              && strcasestr (cgiCookie, tmp) != NULL)
1478            {
1479              tcook = zStrdup (cgiCookie);
1480              hasValidCookie = 1;
1481            }
1482          if (tmp != NULL)
1483            {
1484              free (tmp);
1485            }
1486        }
1487      if (hasValidCookie > 0)
1488        {
1489          addToMap (_tmpMaps->content, "sessid", strstr (tcook, "=") + 1);
1490          char session_file_path[1024];
1491          map *tmpPath = getMapFromMaps (m, "main", "sessPath");
1492          if (tmpPath == NULL)
1493            tmpPath = getMapFromMaps (m, "main", "tmpPath");
1494          char *tmp1 = strtok (tcook, ";");
1495          if (tmp1 != NULL)
1496            sprintf (session_file_path, "%s/sess_%s.cfg", tmpPath->value,
1497                     strstr (tmp1, "=") + 1);
1498          else
1499            sprintf (session_file_path, "%s/sess_%s.cfg", tmpPath->value,
1500                     strstr (cgiCookie, "=") + 1);
1501          free (tcook);
1502          maps *tmpSess = (maps *) malloc (MAPS_SIZE);
1503          struct stat file_status;
1504          int istat = stat (session_file_path, &file_status);
1505          if (istat == 0 && file_status.st_size > 0)
1506            {
1507              conf_read (session_file_path, tmpSess);
1508              addMapsToMaps (&m, tmpSess);
1509              freeMaps (&tmpSess);
1510              free (tmpSess);
1511            }
1512        }
[92]1513    }
[541]1514  addMapsToMaps (&m, _tmpMaps);
1515  freeMaps (&_tmpMaps);
1516  free (_tmpMaps);
[654]1517  maps* bmap=NULL;
[1]1518#ifdef DEBUG
[541]1519  dumpMap (request_inputs);
[1]1520#endif
[216]1521#ifdef WIN32
[541]1522  char *cgiSidL = NULL;
1523  if (getenv ("CGISID") != NULL)
1524    addToMap (request_inputs, "cgiSid", getenv ("CGISID"));
[554]1525
1526  char* usidp;
1527  if ( (usidp = getenv("USID")) != NULL ) {
1528    setMapInMaps (m, "lenv", "usid", usidp);
1529  }
1530
[541]1531  map *test1 = getMap (request_inputs, "cgiSid");
1532  if (test1 != NULL)
1533    {
1534      cgiSid = test1->value;
1535      addToMap (request_inputs, "storeExecuteResponse", "true");
1536      addToMap (request_inputs, "status", "true");
1537      setMapInMaps (m, "lenv", "sid", test1->value);
1538      status = getMap (request_inputs, "status");
1539    }
[216]1540#endif
[654]1541  char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog;
[541]1542  FILE *f0, *f1;
1543  if (status != NULL)
1544    if (strcasecmp (status->value, "false") == 0)
1545      status = NULLMAP;
1546  if (status == NULLMAP)
1547    {
[621]1548      if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){
1549        free (s1);
1550        freeMaps (&m);
1551        free (m);
1552        free (REQUEST);
1553        free (SERVICE_URL);
1554        freeMaps (&request_input_real_format);
1555        free (request_input_real_format);
1556        freeMaps (&request_output_real_format);
1557        free (request_output_real_format);
1558        freeMaps (&tmpmaps);
1559        free (tmpmaps);
1560        return -1;
1561      }
1562
[541]1563      loadServiceAndRun (&m, s1, request_inputs, &request_input_real_format,
1564                         &request_output_real_format, &eres);
1565    }
1566  else
1567    {
1568      int pid;
[1]1569#ifdef DEBUG
[541]1570      fprintf (stderr, "\nPID : %d\n", cpid);
[1]1571#endif
[9]1572
[1]1573#ifndef WIN32
[541]1574      pid = fork ();
[1]1575#else
[541]1576      if (cgiSid == NULL)
1577        {
1578          createProcess (m, request_inputs, s1, NULL, cpid,
1579                         request_input_real_format,
1580                         request_output_real_format);
1581          pid = cpid;
1582        }
1583      else
1584        {
1585          pid = 0;
1586          cpid = atoi (cgiSid);
1587        }
[1]1588#endif
[541]1589      if (pid > 0)
1590        {
[654]1591          /**
1592           * dady :
1593           * set status to SERVICE_ACCEPTED
1594           */
[1]1595#ifdef DEBUG
[541]1596          fprintf (stderr, "father pid continue (origin %d) %d ...\n", cpid,
1597                   getpid ());
[1]1598#endif
[541]1599          eres = SERVICE_ACCEPTED;
1600        }
1601      else if (pid == 0)
1602        {
[621]1603          /**
1604           * son : have to close the stdout, stdin and stderr to let the parent
1605           * process answer to http client.
1606           */
[652]1607          map* usid = getMapFromMaps (m, "lenv", "uusid");
[654]1608          map* tmpm = getMapFromMaps (m, "lenv", "osid");
1609          int cpid = atoi (tmpm->value);
[541]1610          r_inputs = getMapFromMaps (m, "main", "tmpPath");
[652]1611          map* r_inputs1 = createMap("ServiceName", s1->name);
[605]1612
[654]1613          // Create the filename for the result file (.res)
1614          fbkpres =
1615            (char *)
1616            malloc ((strlen (r_inputs->value) +
1617                     strlen (usid->value) + 7) * sizeof (char));
1618          sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value);
1619          bmap = (maps *) malloc (MAPS_SIZE);
1620          bmap->name=zStrdup("status");
1621          bmap->content=createMap("usid",usid->value);
1622          bmap->next=NULL;
1623          addToMap(bmap->content,"sid",tmpm->value);
1624          addIntToMap(bmap->content,"pid",getpid());
1625         
[652]1626          // Create PID file referencing the OS process identifier
1627          fbkpid =
1628            (char *)
1629            malloc ((strlen (r_inputs->value) +
1630                     strlen (usid->value) + 7) * sizeof (char));
1631          sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value);
1632
1633          f0 = freopen (fbkpid, "w+", stdout);
1634          fprintf(stdout,"%d",getpid());
1635          fflush(stdout);
1636
1637          // Create SID file referencing the semaphore name
[541]1638          fbkp =
1639            (char *)
1640            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
[652]1641                     strlen (usid->value) + 7) * sizeof (char));
1642          sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value);
1643
1644          FILE* f2 = fopen (fbkp, "w+");
1645          fprintf(f2,"%s",tmpm->value);
1646          fflush(f2);
1647          fclose(f2);
1648          free(fbkp);
1649
1650          fbkp =
[541]1651            (char *)
1652            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
[652]1653                     strlen (usid->value) + 7) * sizeof (char));
1654          sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value,
1655                   usid->value);
1656          flog =
1657            (char *)
1658            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
1659                     strlen (usid->value) + 13) * sizeof (char));
1660          sprintf (flog, "%s/%s_%s_error.log", r_inputs->value,
1661                   r_inputs1->value, usid->value);
[1]1662#ifdef DEBUG
[541]1663          fprintf (stderr, "RUN IN BACKGROUND MODE \n");
1664          fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid,
1665                   getpid ());
1666          fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value);
[1]1667#endif
[541]1668          freopen (flog, "w+", stderr);
1669          fflush (stderr);
[654]1670          f0 = freopen (fbkp, "w+", stdout);
1671          rewind (stdout);
[458]1672#ifndef WIN32
[654]1673          fclose (stdin);
[458]1674#endif
[631]1675
[652]1676#ifdef RELY_ON_DB
1677          init_sql(m);
1678          recordServiceStatus(m);
1679#endif
[654]1680          if(vid==0){
1681            /**
1682             * set status to SERVICE_STARTED and flush stdout to ensure full
1683             * content was outputed (the file used to store the ResponseDocument).
1684             * The rewind stdout to restart writing from the bgining of the file,
1685             * this way the data will be updated at the end of the process run.
1686             */
1687            printProcessResponse (m, request_inputs, cpid, s1, r_inputs1->value,
1688                                  SERVICE_STARTED, request_input_real_format,
1689                                  request_output_real_format);
1690            fflush (stdout);
1691#ifdef RELY_ON_DB
1692            recordResponse(m,fbkp);
1693#endif
1694          }
1695
[631]1696          fflush (stderr);
[654]1697
[631]1698          fbkp1 =
1699            (char *)
1700            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
[652]1701                     strlen (usid->value) + 13) * sizeof (char));
1702          sprintf (fbkp1, "%s/%s_final_%s.xml", r_inputs->value,
1703                   r_inputs1->value, usid->value);
[631]1704
1705          f1 = freopen (fbkp1, "w+", stdout);
1706
[621]1707          if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){
[677]1708            //freeService (&s1);
[621]1709            free (s1);
1710            freeMaps (&m);
1711            free (m);
1712            free (REQUEST);
1713            free (SERVICE_URL);
1714            freeMaps (&request_input_real_format);
1715            free (request_input_real_format);
1716            freeMaps (&request_output_real_format);
1717            free (request_output_real_format);
1718            freeMaps (&tmpmaps);
1719            free (tmpmaps);
1720            fflush (stdout);
1721            fflush (stderr);
[652]1722            unhandleStatus (m);
[621]1723            return -1;
1724          }
[541]1725          loadServiceAndRun (&m, s1, request_inputs,
1726                             &request_input_real_format,
1727                             &request_output_real_format, &eres);
[631]1728
[541]1729        }
1730      else
1731        {
[652]1732          /**
1733           * error server don't accept the process need to output a valid
1734           * error response here !!!
1735           */
[541]1736          eres = -1;
1737          errorException (m, _("Unable to run the child process properly"),
1738                          "InternalError", NULL);
1739        }
[1]1740    }
1741
1742#ifdef DEBUG
[541]1743  dumpMaps (request_output_real_format);
[1]1744#endif
[541]1745  if (eres != -1)
1746    outputResponse (s1, request_input_real_format,
1747                    request_output_real_format, request_inputs,
1748                    cpid, m, eres);
1749  fflush (stdout);
[605]1750 
[105]1751  /**
1752   * Ensure that if error occurs when freeing memory, no signal will return
1753   * an ExceptionReport document as the result was already returned to the
1754   * client.
1755   */
1756#ifndef USE_GDB
[541]1757  signal (SIGSEGV, donothing);
1758  signal (SIGTERM, donothing);
1759  signal (SIGINT, donothing);
1760  signal (SIGILL, donothing);
1761  signal (SIGFPE, donothing);
1762  signal (SIGABRT, donothing);
[105]1763#endif
[541]1764  if (((int) getpid ()) != cpid || cgiSid != NULL)
1765    {
1766      fclose (stdout);
[654]1767      //fclose (stderr);
[652]1768      /**
1769       * Dump back the final file fbkp1 to fbkp
1770       */
[541]1771      fclose (f0);
1772      fclose (f1);
[654]1773
[541]1774      FILE *f2 = fopen (fbkp1, "rb");
[652]1775#ifndef RELY_ON_DB
[541]1776      semid lid = getShmLockId (m, 1);
1777      if (lid < 0)
1778        return -1;
1779      lockShm (lid);
[652]1780#endif
[654]1781      fclose(f0);
[541]1782      FILE *f3 = fopen (fbkp, "wb+");
1783      free (fbkp);
1784      fseek (f2, 0, SEEK_END);
1785      long flen = ftell (f2);
1786      fseek (f2, 0, SEEK_SET);
1787      char *tmps1 = (char *) malloc ((flen + 1) * sizeof (char));
1788      fread (tmps1, flen, 1, f2);
1789      fwrite (tmps1, 1, flen, f3);
1790      fclose (f2);
1791      fclose (f3);
[652]1792      unlink (fbkpid);
[654]1793      switch(eres){
1794      default:
1795      case SERVICE_FAILED:
1796        setMapInMaps(bmap,"status","status",wpsStatus[1]);
1797        setMapInMaps(m,"lenv","fstate",wpsStatus[1]);
1798        break;
1799      case SERVICE_SUCCEEDED:
1800        setMapInMaps(bmap,"status","status",wpsStatus[0]);
1801        setMapInMaps(m,"lenv","fstate",wpsStatus[0]);
1802        break;
1803      }
[652]1804#ifndef RELY_ON_DB
[654]1805      dumpMapsToFile(bmap,fbkpres);
[652]1806      removeShmLock (m, 1);
1807#else
1808      recordResponse(m,fbkp1);
1809#endif
[654]1810      freeMaps(&bmap);
1811      free(bmap);
[541]1812      unlink (fbkp1);
[652]1813      unlink (flog);
1814      unhandleStatus (m);
1815      free(fbkpid);
[654]1816      free(fbkpres);
[652]1817      free (flog);
[541]1818      free (fbkp1);
1819      free (tmps1);
1820    }
[32]1821
[677]1822  //freeService (&s1);
[541]1823  free (s1);
1824  freeMaps (&m);
1825  free (m);
1826
1827  freeMaps (&request_input_real_format);
1828  free (request_input_real_format);
1829
1830  freeMaps (&request_output_real_format);
1831  free (request_output_real_format);
1832
1833  free (REQUEST);
1834  free (SERVICE_URL);
[1]1835#ifdef DEBUG
[541]1836  fprintf (stderr, "Processed response \n");
1837  fflush (stdout);
1838  fflush (stderr);
[1]1839#endif
1840
[541]1841  if (((int) getpid ()) != cpid || cgiSid != NULL)
1842    {
1843      exit (0);
1844    }
[516]1845
[1]1846  return 0;
1847}
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