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

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

Search

Context Navigation

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