diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/oas.cfg b/3ty/proc-comm-zoo-1.2-alpha/assets/oas.cfg index 2cd738fc..38d8610b 100644 --- a/3ty/proc-comm-zoo-1.2-alpha/assets/oas.cfg +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/oas.cfg @@ -1,17 +1,32 @@ [openapi] -rootUrl=/watchjob -links=/,/api,/conformance,/processes -paths=/root,/api,/conformance,/processes,/processes/{id},/processes/{id}/jobs,/processes/{id}/jobs/{jobID},/processes/{id}/jobs/{jobID}/result -parameters=id,jobID,resultID -header_parameters=oas-header1,oas-header2 -version=3.0.1 +use_content=false +rootUrl=http://localhost/ogc-api +rootHost=http://localhost +rootPath=ogc-api +links=/,/api,/conformance,/processes,/jobs +paths=/root,/api,/conformance,/processes,/processes/{processID},/processes/SAGA.shapes_points.12/execution,/processes/OTB.BandMath/execution,/processes/{processID}/execution,/jobs,/jobs/{jobID},/jobs/{jobID}/results +parameters=processID,jobID,resultID +header_parameters=oas-header1,oas-header2,limitParam,skipParam,processIdParam,statusParam,minDurationParam,maxDurationParam,typeParam,datetimeParam +version=3.0.3 +license_name=OGC license +license_url=https://raw.githubusercontent.com/opengeospatial/ogcapi-processes/master/LICENSE +full_html_support=false +partial_html_support=true +wsUrl=ws://localhost:8888/ +publisherUrl=http://zookernel/cgi-bin/publish.py?jobid= +link_href=http://zoo-project.org/dl/link.json +tags=Home,API,Conformance,GetCapabilities,ProcessDescription,ExecuteEndpoint,JobList,GetStatus,GetResult,Dismiss +examplesPath=/var/www/html/examples/ +examplesUrl=http://localhost/examples/ +exceptionsUrl=http://www.opengis.net/def/exceptions/ogcapi-processes-1/1.0 [oas-header1] in=header name=Prefer type=string -required=false -enum=respond-async +required=true +enum=return=representation,return=minimal,respond-async;return=representation +enum1=,return=representation,return=minimal,respond-async;return=representation,respond-async;return=minimal [oas-header2] in=header @@ -20,6 +35,26 @@ type=string required=false enum=return=representation,return=minimal +[limitParam] +name=limit +title=The limit parameter +abstract=The limit parameter indicates the number of elements to return in an array +in=query +type=integer +schema_minimum=1 +schema_maximum=10000 +schema_default=1000 +required=false + +[skipParam] +name=skip +title=The skip parameter +abstract=The skip parameter indicates the number of elements to skip before starting returning values in an array +in=query +type=integer +schema_minimum=0 +required=false + [/] rel=self type=application/json @@ -31,13 +66,24 @@ title=landing page of this API abstract=The landing page provides links to the API definition, the Conformance statements and the metadata about the processes offered by this service. tags=Home tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/root.yaml +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/LandingPage.yaml + +[/index.html] +rel=alternate +type=text/html [/api] -rel=service -type=application/openapi+json;version=3.0 +rel=service-desc +type=application/vnd.oai.openapi+json;version=3.0 title=the API definition +[/api.html] +rel=service-doc +type=text/html + +[api.html] +href=http://localhost/swagger-ui/oapip/ + [api] method=get title=This document @@ -47,20 +93,24 @@ tags_description= schema= [/conformance] -rel=conformance +rel=http://www.opengis.net/def/rel/ogc/1.0/conformance type=application/json -title=WPS 2.0 REST/JSON Binding Extension conformance classes implemented by this server +title=OGC API - Processes conformance classes implemented by this server [conformance] method=get title=information about standards that this API conforms to -abstract==list all requirements classes specified in a standard (e.g., WPS REST/JSON Binding Core) that the server conforms to +abstract=list all requirements classes specified in a standard (e.g., WPS REST/JSON Binding Core) that the server conforms to tags=Conformance tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/req-classes.yaml +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ConformanceDeclaration.yaml + +[/conformance.html] +rel=alternate +type=text/html [/processes] -rel=processes +rel=http://www.opengis.net/def/rel/ogc/1.0/processes type=application/json title=The processes offered by this server @@ -70,90 +120,146 @@ title=retrieve available processes abstract=Information about the available processes tags=GetCapabilities tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/processCollection.yaml +parameters=/components/parameters/limitParam,/components/parameters/skipParam +schema=https://raw.githubusercontent.com/GeoLabs/ogcapi-processes/rel-1.0/core/openapi/responses/ProcessList.yaml + +[/processes.html] +rel=alternate +type=text/html -[processes/{id}] +[processes/{processID}] +prel=http://www.opengis.net/def/rel/iana/1.0/describedby +rel=self +length=1 method=get title=retrieve a process description abstract=A process description. tags=ProcessDescription tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/process.yaml -parameters=/components/parameters/id +schema=https://raw.githubusercontent.com/GeoLabs/ogcapi-processes/rel-1.0/core/openapi/responses/swagger/ProcessDescription.yaml +ecode=404 +parameters=/components/parameters/processID +[processes/{processID}/execution] +rel=http://www.opengis.net/def/rel/ogc/1.0/execute +length=1 +method=post +title=execute a job +abstract=An execute endpoint. +tags=ExecuteEndpoint +tags_description= +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteSync.yaml +parameters=/components/parameters/processID,/components/parameters/oas-header1 +ecode=400,404,500 +eschema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteAsync.yaml -[/processes/{id}/jobs] -rel=canonical +[processes/SAGA.shapes_points.12/execution] +length=1 +pname=SAGA.shapes_points.12 +method=post +title=execute a job +abstract=An execute endpoint. +tags=ExecuteEndpoint +tags_description= +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteSync.yaml +parameters=/components/parameters/oas-header1 +ecode=400,404,500 +eschema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteAsync.yaml +examples=sample1.json,sample2.json +examples_summary=output as json by value +examples_summary_1=output as xml by value + +[processes/OTB.BandMath/execution] +length=1 +pname=OTB.BandMath +method=post +title=execute a job +abstract=An execute endpoint. +tags=ExecuteEndpoint +tags_description= +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteSync.yaml +parameters=/components/parameters/oas-header1 +ecode=400,404,500 +eschema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteAsync.yaml +examples=sample1.json,sample2.json +examples_summary=output as reference / image/tiff / document +examples_summary_1=output as reference / image/jpeg / raw + +[/jobs] +rel=http://www.opengis.net/def/rel/ogc/1.0/job-list type=application/json -title=Process Description +title=Job Management -[processes/{id}/jobs] -length=2 +[jobs] +length=1 method=get title=retrieve a list of jobs run abstract=A list of jobs run. tags=JobList tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/jobCollection.yaml -parameters=/components/parameters/id +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/JobList.yaml +parameters=/components/parameters/limitParam,/components/parameters/skipParam,/components/parameters/processIdParam,/components/parameters/statusParam,/components/parameters/minDurationParam,/components/parameters/maxDurationParam,/components/parameters/typeParam,/components/parameters/datetimeParam +ecode=404,500 method_1=post title_1=execute a job abstract_1=An execute endpoint. -tags_1=Execute Endpoint +tags_1=ExecuteEndpoint tags_description_1= -schema_1=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/result.yaml -parameters_1=/components/parameters/id,/components/parameters/oas-header1 +schema_1=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteSync.yaml +parameters_1= +ecode_1=400,404,500 +eschema_1=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteAsync.yaml +ep=,/components/parameters/oas-header1 [requestBody] abstract=Mandatory execute request in JSON format type=application/json -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/execute.yaml +schema=https://raw.githubusercontent.com/GeoLabs/ogcapi-processes/rel-1.0/core/openapi/schemas/execute.yaml + +[/jobs.html] +rel=alternate +type=text/html -[/processes/{id}/jobs/{jobID}] +[/jobs/{jobID}] rel=canonical type=application/json title=Status -[processes/{id}/jobs/{jobID}] +[jobs/{jobID}] +length=2 method=get title=The status of a job. abstract=The status of a job. tags=GetStatus tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/statusInfo.yaml -parameters=/components/parameters/id,/components/parameters/jobID +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/Status.yaml +parameters=/components/parameters/jobID +method_1=delete +title_1=Cancel a job +abstract_1=Cancel the job execution. +tags_1=Dismiss +tags_description_1=Cancel a job execution +schema_1=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/Status.yaml +parameters_1=/components/parameters/jobID +ecode_1=404,500 -[/processes/{id}/jobs/{jobID}/result] -rel=canonical +[/jobs/{jobID}/results] +rel=http://www.opengis.net/def/rel/ogc/1.0/results type=application/json title=Get Result -[processes/{id}/jobs/{jobID}/result] +[jobs/{jobID}/results] method=get title=The result of a job execution. abstract=The result of a job execution. tags=GetResult tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/result.yaml -parameters=/components/parameters/id,/components/parameters/jobID +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/Results.yaml +parameters=/components/parameters/jobID +ecode=404,500 ep=,/components/parameters/oas-header2 -[/processes/{id}/jobs/{jobID}/result/{resultID}] -rel=canonical -type=application/json -title=Get Result - -[processes/{id}/jobs/{jobID}/result/{resultID}] -method=get -title=The result of a job execution. -abstract=The result of a job execution. -tags=GetResult -tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/valueType.yaml -parameters=/components/parameters/id,/components/parameters/jobID,/components/parameters/resultID,/components/parameters/oas-header2 - - -[{id}] +[{processID}] type=string title=The id of a process abstract=The id of a process @@ -175,6 +281,24 @@ abstract=The id of an output in=path required=true +[statusParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/status.yaml + +[processIdParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/processIdQueryParam.yaml + +[minDurationParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/minDuration.yaml + +[maxDurationParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/maxDuration.yaml + +[typeParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/type.yaml + +[datetimeParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/datetime.yaml + [{f}] default=json enum=json @@ -183,14 +307,87 @@ abstract=The optional f parameter indicates the output format which the server s in=query required=false -[conformTo] -rootUrl=http://www.opengis.net/spec/WPS/2.0/req/service/binding/rest-json/ +[conformsTo] +rootUrl=http://www.opengis.net/spec/ogcapi-processes/1.0/req/ +rootUrl0=http://www.opengis.net/spec/WPS/2.0/req/service/binding/rest-json/ link=core link_1=oas30 link_2=json -length=3 +link_3=job-list +link_4=dismiss +link_5=callback +link_6=ogc-process-description +link_7=html +length=8 [exception] abstract=Exception type=application/json -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/exception.yaml +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/NotFound.yaml +default_schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ServerError.yaml + +[responses] +length=5 +code=404 +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/NotFound.yaml +type=application/json +title=NotFound +code_1=500 +schema_1=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ServerError.yaml +type_1=application/json +title_1=ServerError +code_2=400 +schema_2=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/InvalidParameter.yaml +type_2=appliction/json +title_2=InvalidParameter +code_3=405 +schema_3=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/NotAllowed.yaml +type_3=appliction/json +title_3=NotAllowed +code_4=406 +schema_4=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/NotSupported.yaml +type_4=appliction/json +title_4=NotSupported + +[callbacks] +length=3 +state=jobSuccess +uri=successUri +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/schemas/results.yaml +type=application/json +title=Results received successfully +state_1=jobInProgress +uri_1=inProgressUri +schema_1=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/schemas/statusInfo.yaml +type_1=application/json +title_1=Status received successfully +state_2=jobFailed +uri_2=failedUri +schema_2=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/schemas/exception.yaml +type_2=application/json +title_2=Exception received successfully + +[provider_alt] +addressDeliveryPoint=streetAddress +addressCity=addressLocality +addressAdministrativeArea=addressRegion +addressPostalCode=postalCode +addressCountry=addressCountry +addressElectronicMailAddress=email +phoneVoice=telephone +phoneFacsimile=faxNumber +hoursOfService=hoursAvailable +contactInstructions=contactOption + +[links_title] +self=View this document in JSON. +alternate=View the alternative version in HTML. +conformance=View the conformance classes that the link's context conforms to. +service-desc=View the service description. +service-doc=View service documentation. +processes=View the list of processes the API offers. +results=View the results of a process. +status=View the current status of a job execution. +execute=View the execution endpoint of a process. +job-list=View the list of job available on this server. + diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/Makefile.in b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/Makefile.in new file mode 100644 index 00000000..f1a1505b --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/Makefile.in @@ -0,0 +1,154 @@ +include ZOOMakefile.opts + +all: version.h zoo_loader.cgi ${YAML_FILE1} ${ZOOFPM_FILE} + +version.h: Makefile + echo "#define ZOO_VERSION \"2.0.0-dev\"" > version.h + echo "@ETC_DEF@" >> version.h + echo "#define LOCALEDIR \"@localedir@\"" >> version.h + +service.o: service.c service.h + $(CXX) ${YAML_CFLAGS} ${XML2CFLAGS} ${CPPFLAGS} -fPIC -c service.c + +main_conf_read.tab.c: main_conf_read.y service.h + bison -p cr -d main_conf_read.y + +main_conf_read.tab.o: main_conf_read.tab.c service.h + $(CXX) ${CFLAGS} -c main_conf_read.tab.c + +lex.cr.c: main_conf_read.y main_conf_read.l main_conf_read.tab.c service.h + flex -P cr --header-file main_conf_read.l + +lex.cr.o: lex.cr.c service.h + $(CXX) ${CFLAGS} -c lex.cr.c + +service_conf.tab.c: service_conf.y service.h + bison -p sr -d service_conf.y + +service_conf.tab.o: service_conf.tab.c service.h + $(CXX) ${CFLAGS} -c service_conf.tab.c + +lex.sr.c: service_conf.y service_conf.l service_conf.tab.c service.h + flex -P sr --header-file service_conf.l + +lex.sr.o: lex.sr.c service.h + $(CXX) ${CFLAGS} -c lex.sr.c + +ulinet.o: ulinet.c + $(CC) -fPIC ${XML2CFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c ulinet.c + +sshapi.o: sshapi.c + $(CXX) -fPIC ${CFLAGS} -c sshapi.c + +service_json.o: service_json.c + $(CXX) -fPIC ${JS_ENABLED} ${GDAL_CFLAGS} ${XML2CFLAGS} ${CFLAGS} ${JSON_CFLAGS} ${MS_CFLAGS} -c service_json.c + +service_callback.o: service_callback.c + $(CXX) -fPIC ${XML2CFLAGS} ${GDAL_CFLAGS} ${JSON_CFLAGS} ${CFLAGS} -c service_callback.c + +request_parser.o: request_parser.c request_parser.h + $(CXX) -fPIC ${RABBITMQ_CPPFLAGS} ${XML2CFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c request_parser.c + +sqlapi.o: sqlapi.c sqlapi.h + $(CXX) -fPIC ${JSON_CFLAGS} ${METADB_ENABLED} ${GDAL_CFLAGS} ${XML2CFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c sqlapi.c + +caching.o: caching.c + $(CXX) -fPIC ${XML2CFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c caching.c + +service_internal_amqp.o: service_internal_amqp.c + $(CXX) ${CFLAGS} -c service_internal_amqp.c + +response_print.o: response_print.c response_print.h + $(CXX) -fPIC ${JSON_CFLAGS} ${GDAL_CFLAGS} ${XML2CFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} ${HPC_ENABLED} -c response_print.c + +server_internal.o: server_internal.c server_internal.h service.h mimetypes.h + $(CXX) ${JSON_CFLAGS} ${GDAL_CFLAGS} ${JS_ENABLED} ${JSCFLAGS} ${XML2CFLAGS} ${CFLAGS} -fPIC -c server_internal.c + +service_internal.o: service_internal.c service_internal.h service.h + $(CC) ${JSON_CFLAGS} ${GDAL_CFLAGS} ${JS_ENABLED} ${JSCFLAGS} ${XML2CFLAGS} ${CFLAGS} -fPIC -c service_internal.c + +service_yaml.o: service_yaml.c service.h + $(CC) ${YAML_CFLAGS} ${XML2CFLAGS} ${CFLAGS} -fPIC -c service_yaml.c + +meta_sql.o: meta_sql.c meta_sql.h service.h + $(CXX) ${METADB_ENABLED} ${GDAL_CFLAGS} ${XML2CFLAGS} ${CFLAGS} -c meta_sql.c + +service_internal_ms.o: service_internal_ms.c + $(CC) ${JS_ENABLED} ${GDAL_CFLAGS} ${JSCFLAGS} ${XML2CFLAGS} ${CFLAGS} -fPIC -c service_internal_ms.c + echo "SYMBOLSET\nEND" > symbols.sym + +service_internal_python.o: service_internal_python.c service.h + $(CXX) ${XML2CFLAGS} ${PYTHONCFLAGS} ${CFLAGS} -c service_internal_python.c + +service_internal_r.o: service_internal_r.c service.h + $(CXX) ${XML2CFLAGS} ${RCFLAGS} ${CFLAGS} -c service_internal_r.c + +service_internal_otb.o: service_internal_otb.c service_internal_otb.h service.h + $(CXX) ${XML2CFLAGS} ${OTBCFLAGS} ${CFLAGS} -c service_internal_otb.c + +service_internal_hpc.o: service_internal_hpc.c service_internal_hpc.h service.h + $(CXX) ${JSON_CFLAGS} ${XML2CFLAGS} ${HPCCFLAGS} ${CFLAGS} -c service_internal_hpc.c + +service_internal_saga.o: service_internal_saga.c service_internal_saga.h service.h + $(CXX) ${XML2CFLAGS} ${SAGA_CFLAGS} ${CFLAGS} -c service_internal_saga.c + +otbZooWatcher.o: otbZooWatcher.cxx otbZooWatcher.h service.h + $(CXX) ${OTBCFLAGS} ${CFLAGS} -c otbZooWatcher.cxx + +service_internal_php.o: service_internal_php.c service.h + $(CXX) -c ${XML2CFLAGS} ${PHPCFLAGS} ${CFLAGS} ${PHP_ENABLED} service_internal_php.c + +service_internal_php7.o: service_internal_php7.c service.h + $(CXX) -c ${XML2CFLAGS} ${PHPCFLAGS} ${CFLAGS} ${PHP_ENABLED} service_internal_php7.c + +service_internal_perl.o: service_internal_perl.c service.h + $(CC) -c ${XML2CFLAGS} ${PERLCFLAGS} ${CFLAGS} ${PERL_ENABLED} service_internal_perl.c + +service_internal_java.o: service_internal_java.c service.h + $(CC) -c ${XML2CFLAGS} ${JAVACFLAGS} ${CFLAGS} ${JAVA_ENABLED} service_internal_java.c + +service_internal_js.o: service_internal_js.c service_internal_js.h + $(CC) -fPIC ${XML2CFLAGS} ${JSCFLAGS} ${CFLAGS} ${JS_ENABLED} -c service_internal_js.c + +service_internal_mono.o: service_internal_mono.h service_internal_mono.c service.h + $(CC) -c ${XML2CFLAGS} ${MONO_CFLAGS} ${CFLAGS} ${MONO_ENABLED} service_internal_mono.c + +service_internal_ruby.o: service_internal_ruby.c service_internal_ruby.h + $(CXX) ${XML2CFLAGS} ${RUBYCFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c service_internal_ruby.c + +service_loader.o: service_loader.c service.h + $(CXX) -c ${XML2CFLAGS} ${PYTHONCFLAGS} ${CFLAGS} service_loader.c + +zoo_service_loader.o: zoo_service_loader.c service.h version.h ${MS_FILE} ${R_FILE} ${PYTHON_FILE} ${PHP_FILE} ${JAVA_FILE} ${JS_FILE} ${PERL_FILE} ${RUBY_FILE} ${YAML_FILE} ${OTB_FILE} ${SAGA_FILE} ${MONO_FILE} ${HPC_FILES} ${METADB_FILE} ${RABBITMQ_FILE} + $(CXX) -g -O2 ${JSON_CFLAGS} ${GDAL_CFLAGS} ${XML2CFLAGS} ${CFLAGS} ${MONO_CFLAGS} ${SAGA_CFLAGS} ${OTBCFLAGS} ${RCFLAGS} ${PYTHONCFLAGS} ${JAVACFLAGS} ${JSCFLAGS} ${PERLCFLAGS} ${PHPCFLAGS} ${SAGA_ENABLED} ${OTB_ENABLED} ${HPC_ENABLED} ${PYTHON_ENABLED} ${R_ENABLED} ${JS_ENABLED} ${PHP_ENABLED} ${PERL_ENABLED} ${JAVA_ENABLED} ${MONO_ENABLED} ${METADB_ENABLED} -c zoo_service_loader.c -fno-common -DPIC -o zoo_service_loader.o + +libzoo_service.${EXT}: version.h service_internal.o service.o sqlapi.o ${CALLBACK_FILE} + $(CXX) -shared ${GDAL_CFLAGS} ${DEFAULT_OPTS} -fpic -o libzoo_service.${EXT} ${CFLAGS} service_internal.o service.o sqlapi.o ${CALLBACK_FILE} ${FCGI_LDFLAGS} ${GDAL_LIBS} ${ZOO_LDFLAGS} ${MACOS_LD_FLAGS} + +zoo_loader.cgi: version.h libzoo_service.${EXT} zoo_loader.c zoo_service_loader.o ulinet.o service.h lex.sr.o service_conf.tab.o service_conf.y ulinet.o main_conf_read.tab.o lex.cr.o request_parser.o response_print.o server_internal.o caching.o ${MS_FILE} ${PYTHON_FILE} ${PHP_FILE} ${JAVA_FILE} ${JS_FILE} ${PERL_FILE} ${RUBY_FILE} ${YAML_FILE} ${OTB_FILE} ${R_FILE} ${SAGA_FILE} ${HPC_FILES} ${METADB_FILE} ${JSON_FILE} + $(CXX) -g -O2 ${JSON_CFLAGS} ${JSCFLAGS} ${PHPCFLAGS} ${PERLCFLAGS} ${RUBYCFLAGS} ${JAVACFLAGS} ${XML2CFLAGS} ${PYTHONCFLAGS} ${CFLAGS} -c zoo_loader.c -fno-common -DPIC -o zoo_loader.o + $(CXX) ${JSON_CFLAGS} ${JSCFLAGS} ${SAGA_CFLAGS} ${OTBCFLAGS} ${GDAL_CFLAGS} ${XML2CFLAGS} ${PHPCFLAGS} ${PERLCFLAGS} ${JAVACFLAGS} ${PYTHONCFLAGS} ${CFLAGS} zoo_loader.o zoo_service_loader.o ${RABBITMQ_FILE} ${MS_FILE} ${PYTHON_FILE} ${PERL_FILE} ${PHP_FILE} ${JS_FILE} ${JAVA_FILE} ${YAML_FILE} ${OTB_FILE} ${SAGA_FILE} ${MONO_FILE} ${HPC_FILES} ${METADB_FILE} ${JSON_FILE} ${R_FILE} response_print.o server_internal.o caching.o request_parser.o ulinet.o lex.cr.o lex.sr.o service_conf.tab.o main_conf_read.tab.o -o zoo_loader.cgi -L. ${LDFLAGS} + + +zoo_loader_fpm: version.h libzoo_service.${EXT} zoo_loader_fpm.c zoo_service_loader.o ulinet.o service.h lex.sr.o service_conf.tab.o service_conf.y ulinet.o main_conf_read.tab.o lex.cr.o request_parser.o response_print.o server_internal.o caching.o ${MS_FILE} ${PYTHON_FILE} ${PHP_FILE} ${JAVA_FILE} ${JS_FILE} ${PERL_FILE} ${RUBY_FILE} ${YAML_FILE} ${OTB_FILE} ${R_FILE} ${SAGA_FILE} ${HPC_FILES} ${METADB_FILE} ${JSON_FILE} ${CALLBACK_FILE} ${RABBITMQ_FILE} + $(CXX) -g -O2 ${JSON_CFLAGS} ${JSCFLAGS} ${PHPCFLAGS} ${PERLCFLAGS} ${RUBYCFLAGS} ${JAVACFLAGS} ${XML2CFLAGS} ${PYTHONCFLAGS} ${JSON_CPPFLAGS} ${GDAL_CFLAGS} ${SAGA_CFLAGS} ${OTBCFLAGS} ${CFLAGS} -c zoo_loader_fpm.c -fno-common -DPIC -o zoo_loader_fpm.o + $(CXX) ${JSON_CFLAGS} ${JSCFLAGS} ${SAGA_CFLAGS} ${OTBCFLAGS} ${GDAL_CFLAGS} ${XML2CFLAGS} ${PHPCFLAGS} ${PERLCFLAGS} ${JAVACFLAGS} ${PYTHONCFLAGS} ${CFLAGS} zoo_loader_fpm.o zoo_service_loader.o ${RABBITMQ_FILE} ${MS_FILE} ${PYTHON_FILE} ${PERL_FILE} ${PHP_FILE} ${JS_FILE} ${JAVA_FILE} ${YAML_FILE} ${OTB_FILE} ${SAGA_FILE} ${MONO_FILE} ${HPC_FILES} ${METADB_FILE} ${JSON_FILE} ${R_FILE} ${CALLBACK_FILE} ${IRODS_FILE} response_print.o server_internal.o caching.o request_parser.o ulinet.o lex.cr.o lex.sr.o service_conf.tab.o main_conf_read.tab.o -o zoo_loader_fpm -L. ${LDFLAGS} + + +zcfg2yaml: zcfg2yaml.c service.h lex.sr.o service_conf.tab.o service_conf.y main_conf_read.tab.o lex.cr.o response_print.o server_internal.o service_internal.o ${MS_FILE} ${YAML_FILE} + $(CXX) -g -O2 ${JSCFLAGS} ${RUBYCFLAGS} ${XML2CFLAGS} ${CFLAGS} -c zcfg2yaml.c -fno-common -DPIC -o zcfg2yaml.o + $(CXX) ${XML2CFLAGS} ${CFLAGS} zcfg2yaml.o caching.o ulinet.o server_internal.o service_internal.o ${MS_FILE} response_print.o lex.cr.o lex.sr.o service_conf.tab.o main_conf_read.tab.o ${YAML_FILE} -o zcfg2yaml -L. ${LDFLAGS} + +install: zoo_loader.cgi + install -d ${DESTDIR}${CGI_DIR} + install zoo_loader.cgi ${DESTDIR}${CGI_DIR}/ + install libzoo_service.${EXT} ${DESTDIR}${INST_LIB}/${LIBZOO_SERVICE} + (cd ${DESTDIR}${INST_LIB} ; \ + if [ -e "libzoo_service.${EXT}" ]; then rm libzoo_service.${EXT}; fi ; \ + ln -s ${LIBZOO_SERVICE} libzoo_service.${EXT}) + if [ -z "${MS_FILE}" ] ; then echo "No symbols.sym" ; else install -d ${DESTDIR}${SHAREDSTATEDIR}; install -m644 symbols.sym ${DESTDIR}${SHAREDSTATEDIR}; fi + install -d ${DESTDIR}${INST_INCLUDE}/zoo + install sqlapi.h service.h service_internal.h ${DESTDIR}${INST_INCLUDE}/zoo + +clean: + rm -f version.h symbols.sym *.o *.cgi *.eo *.tab.c *.tab.h *.sr.c* service_loader lex.* *.lreg *.sibling service_loader.dSYM *${EXT} diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/ZOOMakefile.opts.in b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/ZOOMakefile.opts.in new file mode 100644 index 00000000..87b5a902 --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/ZOOMakefile.opts.in @@ -0,0 +1,135 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +PREFIX=@prefix@ +INST_LIB=@libdir@ +INST_INCLUDE=@includedir@ +VERSION=1.8 +REVISION=0 +EXT=so +DEFAULT_OPTS=-Wl,-soname,libzoo_service.so.${VERSION} +OS:=$(shell uname -s) +ifeq ($(OS),Darwin) + MACOS_LD_FLAGS=-lintl + MACOS_LD_NET_FLAGS=-framework SystemConfiguration -framework CoreFoundation + MACOS_CFLAGS=-arch $(shell uname -m) + EXT=dylib + DEFAULT_OPTS=-Wl,-compatibility_version,${VERSION},-current_version,${VERSION},-install_name,${DESTDIR}${INST_LIB}/libzoo_service.${VERSION}.${REVISION}.dylib + LIBZOO_SERVICE=libzoo_service.${VERSION}.${REVISION}.${EXT} +else + LIBZOO_SERVICE=libzoo_service.${EXT}.${VERSION} +endif + +CGI_DIR=@CGI_DIR@ + +FCGI_CFLAGS=@FCGI_CPPFLAGS@ +FCGI_LDFLAGS=@FCGI_LDFLAGS@ + +YAML_CFLAGS=@YAML_CPPFLAGS@ +YAML_LDFLAGS=@YAML_LDFLAGS@ +YAML_FILE=@YAML_FILE@ +YAML_FILE1=@YAML_FILE1@ + +JSON_CFLAGS=@JSON_CPPFLAGS@ +JSON_LDFLAGS=@JSON_LDFLAGS@ +JSON_FILE=@JSON_FILE@ + +METADB_ENABLED=@METADB@ +METADB_FILE=@METADB_FILE@ + + +GDAL_CFLAGS=@GDAL_CFLAGS@ +GDAL_LIBS=@GDAL_LIBS@ + +XML2CFLAGS=@XML2_CPPFLAGS@ +XML2LDFLAGS=@XML2_LDFLAGS@ + +XSLT_CFLAGS=@XSLT_CPPFLAGS@ +XSLT_LDFLAGS=@XSLT_LDFLAGS@ + +GEOS_CFLAGS=@GEOS_CPPFLAGS@ +GEOS_LDFLAGS=@GEOS_LDFLAGS@ + +CGAL_CFLAGS=@CGAL_CPPFLAGS@ +CGAL_LDFLAGS=@CGAL_LDFLAGS@ + +PYTHONCFLAGS=@PYTHON_CPPFLAGS@ +PYTHONLDFLAGS=@PYTHON_LDFLAGS@ +PYTHON_ENABLED=@PYTHON_ENABLED@ +PYTHON_FILE=@PYTHON_FILE@ + +RCFLAGS=@R_CPPFLAGS@ +RLDFLAGS=@R_LDFLAGS@ +R_ENABLED=@R_ENABLED@ +R_FILE=@R_FILE@ + +RUBYCFLAGS=@RUBY_CPPFLAGS@ +RUBYLDFLAGS=@RUBY_LDFLAGS@ +RUBY_ENABLED=@RUBY_ENABLED@ +RUBY_FILE=@RUBY_FILE@ + +RABBITMQ_LDFLAGS=@RABBITMQ_LDFLAGS@ +RABBITMQ_CPPFLAGS=@RABBITMQ_CPPFLAGS@ +RABBITMQ_FILE=@RABBITMQ_FILE@ +ZOOFPM_FILE=@ZOOFPM_FILE@ + +JS_ENABLED=@JS_ENABLED@ +JSCFLAGS=@JS_CPPFLAGS@ +JSLDFLAGS=@JS_LDFLAGS@ +JS_FILE=@JS_FILE@ +ifeq ($(JS_ENABLED),-DUSE_JS) + JS_LDFLAGS=${ZRPATH}/zoo-kernel/ulinet.o ${ZRPATH}/zoo-kernel/service_internal_js.o -lcurl +endif + +MS_CFLAGS=@MS_CFLAGS@ @PROJ_CPPFLAGS@ +MS_LDFLAGS=@MS_LIBS@ +MS_FILE=@MS_FILE@ + +ZOO_CFLAGS=-I${ZRPATH}/../thirds/cgic206/ -I${ZRPATH}/zoo-kernel/ +ZOO_LDFLAGS=@OPENSSL_LDFLAGS@ + +JAVACFLAGS=@JAVA_CPPFLAGS@ +JAVALDFLAGS=@JAVA_LDFLAGS@ +JAVA_ENABLED=@JAVA_ENABLED@ +JAVA_FILE=@JAVA_FILE@ + +PHPCFLAGS=@PHP_CPPFLAGS@ +PHPLDFLAGS=@PHP_LDFLAGS@ +PHP_ENABLED=@PHP_ENABLED@ +PHP_FILE=@PHP_FILE@ + +PERLCFLAGS=@PERL_CPPFLAGS@ +PERLLDFLAGS=@PERL_LDFLAGS@ +PERL_ENABLED=@PERL_ENABLED@ +PERL_FILE=@PERL_FILE@ + +HPCCFLAGS=@SSH2_CPPFLAGS@ @HPC_CPPFLAGS@ +HPCLDFLAGS=@SSH2_LDFLAGS@ @HPC_LDFLAGS@ +HPC_ENABLED=@HPC_ENABLED@ +HPC_FILES=@HPC_FILES@ + +CALLBACK_FILE=@CALLBACK_FILE@ +CALLBACK_USE=@CALLBACK_USE@ + +OTBCFLAGS=@OTB_CPPFLAGS@ +OTBLDFLAGS=@OTB_LDFLAGS@ +OTB_ENABLED=@OTB_ENABLED@ +OTB_FILE=@OTB_FILE@ + +SAGA_CFLAGS=@SAGA_CPPFLAGS@ +SAGA_LDFLAGS=@SAGA_LDFLAGS@ +SAGA_ENABLED=@SAGA_ENABLED@ +SAGA_FILE=@SAGA_FILE@ + +MONO_CFLAGS=@MONO_CFLAGS@ +MONO_LDFLAGS=@MONO_LDFLAGS@ +MONO_ENABLED=@MONO_ENABLED@ +MONO_FILE=@MONO_FILE@ + +CFLAGS=@CALLBACK_USE@ @SSH2_CPPFLAGS@ @PROJ_CPPFLAGS@ @RELY_ON_DB@ @DEB_DEF@ -fpic @OPENSSL_CFLAGS@ @UUID_CFLAGS@ ${FCGI_CFLAGS} ${YAML_CFLAGS} ${MACOS_CFLAGS} ${MS_CFLAGS} ${RABBITMQ_CPPFLAGS} -I../../thirds/cgic206 -I. -DLINUX_FREE_ISSUE #-DDEBUG #-DDEBUG_SERVICE_CONF + +CPPFLAGS=@CALLBACK_USE@ @SSH2_CPPFLAGS@ @PROJ_CPPFLAGS@ @RELY_ON_DB@ @DEB_DEF@ -fpic @OPENSSL_CFLAGS@ @UUID_CFLAGS@ ${FCGI_CFLAGS} ${YAML_CFLAGS} ${MACOS_CFLAGS} ${MS_CFLAGS} ${RABBITMQ_CPPFLAGS} ${IRODS_CPPFLAGS} -I../../thirds/cgic206 -I. -DLINUX_FREE_ISSUE #-DDEBUG #-DDEBUG_SERVICE_CONF + +LDFLAGS=-lpthread @UUID_LDFLAGS@ -lzoo_service @SSH2_LDFLAGS@ @PROJ_LDFLAGS@ @DEFAULT_LIBS@ -L../../thirds/cgic206 -lcgic ${GDAL_LIBS} ${XML2LDFLAGS} ${PYTHONLDFLAGS} ${PERLLDFLAGS} ${RABBITMQ_LDFLAGS} ${PHPLDFLAGS} ${JAVALDFLAGS} ${JSLDFLAGS} ${FCGI_LDFLAGS} @OPENSSL_LDFLAGS@ @UUID_LDFLAGS@ ${MS_LDFLAGS} ${MACOS_LD_FLAGS} ${MACOS_LD_NET_FLAGS} ${YAML_LDFLAGS} ${OTBLDFLAGS} ${SAGA_LDFLAGS} ${MONO_LDFLAGS} ${RLDFLAGS} @JSON_LDFLAGS@ @XSLT_LDFLAGS@ + +DATAROOTDIR=@datarootdir@/zoo-project +SHAREDSTATEDIR=@sharedstatedir@/zoo-project diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/configure.ac b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/configure.ac new file mode 100644 index 00000000..6f8891df --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/configure.ac @@ -0,0 +1,1163 @@ +AC_INIT([ZOO Kernel], [1.9.0], [bugs@zoo-project.org]) + +AC_CONFIG_MACRO_DIR([macros]) + +# Checks for programs. +AC_PROG_YACC +AC_PROG_CC +AC_PROG_CXX +AC_PROG_SED +AC_PROG_AWK + +dnl autoconf 2.69 AC_PROG_LEX has no parameters +dnl autoconf 2.70 AC_PROG_LEX prints a deprecation warning without params +m4_if(m4_version_compare(m4_defn([AC_AUTOCONF_VERSION]), [2.70]), [-1], [dnl + dnl autoconf < 2.70 + AC_PROG_LEX +], [ + dnl autoconf >= 2.70 + AC_PROG_LEX([noyywrap]) +]) + +# Checks for libraries. +AC_CHECK_LIB([curl], [curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform]) +AC_CHECK_LIB([dl], [dlopen,dlsym,dlerror,dlclose]) +AC_CHECK_LIB([crypto], [EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new]) + +DEFAULT_LIBS="$LIBS" +AC_SUBST([DEFAULT_LIBS]) + + +# Checks for header files. +AC_FUNC_ALLOCA +AC_CHECK_HEADERS([fcntl.h inttypes.h malloc.h stddef.h stdlib.h string.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_STDBOOL +AC_TYPE_INT16_T +AC_TYPE_INT32_T +AC_TYPE_INT8_T +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T +AC_TYPE_UINT8_T + +# Checks for library functions. +AC_FUNC_FORK +AC_FUNC_MALLOC +AC_FUNC_REALLOC +AC_CHECK_FUNCS([dup2 getcwd memset setenv strdup strstr]) + +#============================================================================ +# Detect if uuid is available +#============================================================================ + +AC_ARG_WITH([uuid], + [AS_HELP_STRING([--with-uuid=PATH], [Specifies an alternative location for the ossp-uuid library])], + [UUID_DIR="$withval"], [UUID_DIR="/usr/"]) +UUID_CFLAGS="-I$UUID_DIR/include" +UUID_LDFLAGS="-L$UUID_DIR/lib -luuid" +CPPFLAGS_SAVE="$CPPFLAGS" +CPPFLAGS="$UUID_CFLAGS" +LIBS_SAVE="$LIBS" +LIBS="$UUID_LDFLAGS" +AC_CHECK_HEADERS([uuid/uuid.h], + [], [AC_MSG_ERROR([could not find header file uuid.h])]) +AC_CHECK_LIB([uuid], [uuid_generate_time], + [], [AC_MSG_ERROR([could not find function in uuid library])]) +CPPFLAGS="$CPPFLAGS_SAVE" +AC_SUBST([UUID_CFLAGS]) +AC_SUBST([UUID_LDFLAGS]) + +#============================================================================ +# Detect if json-c is available +#============================================================================ + +AC_ARG_WITH([callback], + [AS_HELP_STRING([--with-callback=yes], [Activate callback invocation during HPC execution])], + [CALLBACK_ACTIVATED="$withval"], [CALLBACK_ACTIVATED="no"]) + +AC_ARG_WITH([json], + [AS_HELP_STRING([--with-json=PATH], [Specifies an alternative location for the json-c library])], + [JSON_DIR="$withval"], [JSON_DIR="/usr/"]) +if test "x$JSON_DIR" != "x" +then + JSON_CPPFLAGS="-DUSE_JSON -I$JSON_DIR/include/json-c/" + JSON_LDFLAGS="-L$JSON_DIR/lib -ljson-c" + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$JSON_CPPFLAGS" + LIBS_SAVE="$LIBS" + LIBS="$JSON_LDFLAGS" + AC_CHECK_HEADERS([json_object.h], + [], [AC_MSG_ERROR([could not find header file json_object.h])]) + AC_CHECK_LIB([json-c], [json_object_new_object], + [], [AC_MSG_ERROR([could not find function in json-c library])]) + CPPFLAGS="$CPPFLAGS_SAVE" + JSON_FILE="service_json.o service_callback.o" + JSON_ENABLED="-DJSON" + if test "x$CALLBACK_ACTIVATED" == "xyes" + then + CALLBACK_FILE="" + CALLBACK_USE="-DUSE_CALLBACK" + fi +fi +AC_SUBST([JSON_CPPFLAGS]) +AC_SUBST([JSON_LDFLAGS]) +AC_SUBST([JSON_FILE]) +AC_SUBST([JSON_ENABLED]) +AC_SUBST([CALLBACK_FILE]) +AC_SUBST([CALLBACK_USE]) + +#============================================================================ +# Detect if rabbitmq is available +#============================================================================ + +AC_ARG_WITH([rabbitmq], + [AS_HELP_STRING([--with-rabbitmq], [asynchronous requests management with rabbitmq ])], + [AMQP="-DUSE_AMQP"], [AMQP=""]) + +if test -z "$AMQP" +then + RABBITMQ_LDFLAGS="" + RABBITMQ_CPPFLAGS="" + RABBITMQ_FILE="" +else + AC_CHECK_LIB([rabbitmq], [main]) + RABBITMQ_LDFLAGS=`pkg-config --libs librabbitmq` + RABBITMQ_CPPFLAGS="-DUSE_AMQP" `pkg-config --cflags librabbitmq` + RABBITMQ_FILE="service_internal_amqp.o" + ZOOFPM_FILE="zoo_loader_fpm" + RELY_ON_DB="-DRELY_ON_DB" + AC_SUBST([RELY_ON_DB]) +fi +AC_SUBST([RABBITMQ_LDFLAGS]) +AC_SUBST([RABBITMQ_CPPFLAGS]) +AC_SUBST([RABBITMQ_FILE]) +AC_SUBST([ZOOFPM_FILE]) + +#============================================================================ +# Detect if openssl is available +#============================================================================ + +AC_ARG_WITH([openssl], + [AS_HELP_STRING([--with-openssl=PATH], [Specifies an alternative location for the openssl library])], + [OPENSSL_DIR="$withval"], [OPENSSL_DIR="/usr/"]) +OPENSSL_CFLAGS="-I$OPENSSL_DIR/include" +OPENSSL_LDFLAGS="-lcrypto -L$OPENSSL_DIR/lib -lssl" +CPPFLAGS_SAVE="$CPPFLAGS" +CPPFLAGS="$OPENSSL_CFLAGS" +LIBS_SAVE="$LIBS" +LIBS="$OPENSSL_LDFLAGS" +AC_CHECK_HEADERS([openssl/md5.h openssl/hmac.h openssl/evp.h openssl/bio.h openssl/buffer.h], + [], [AC_MSG_ERROR([could not find header file $i related to openssl])]) +AC_CHECK_LIB(crypto, BIO_f_base64, + [], [AC_MSG_ERROR([could not find $i function in openssl library])]) +CPPFLAGS="$CPPFLAGS_SAVE" +AC_SUBST([OPENSSL_CFLAGS]) +AC_SUBST([OPENSSL_LDFLAGS]) + +#============================================================================ +# Detect if gettext is available +#============================================================================ + +#AC_ARG_WITH([gettext], +# [AS_HELP_STRING([--with-gettext=PATH], [Specifies an alternative location for the openssl library])], +# [GETTEXT_DIR="$withval"], [GETTEXT_DIR="/usr/"]) + +#GETTEXT_CFLAGS="-I$GETTEXT_DIR/include" +#GETTEXT_LDFLAGS="-L$GETTEXT_DIR/lib -lintl" +#CFLAGS_SAVE="$CFLAGS" +#CFLAGS="$GETTEXT_CFLAGS" +#LIBS_SAVE="$LIBS" +#LIBS="$GETTEXT_LDFLAGS" +#AM_GNU_GETTEXT([external], [], []) +#AC_CHECK_LIB(intl, +# [dgettext], [] , [AC_MSG_ERROR([could not find $i function in gettext library])]) +#AC_SUBST([GETTEXT_CFLAGS]) +#AC_SUBST([GETTEXT_LDFLAGS]) + +#============================================================================ +# Detect if run on debian / ubuntu +#============================================================================ +if test -f "/usr/bin/dpkg" +then + DEB_DEF=-DDEB +fi +AC_SUBST([DEB_DEF]) + +AC_ARG_WITH([etc-dir], + [AS_HELP_STRING([--with-etc-dir=PATH], [Specifies an alternative path to store the main.cfg file ( default: ZOO-Kernel location) ])], + [ETC_DEF="#define ETC_DIR \\\"${sysconfdir}\\\""], [ETC_DEF=""]) +AC_SUBST([ETC_DEF]) + +AC_ARG_WITH([cgi-dir], + [AS_HELP_STRING([--with-cgi-dir=PATH], [Specifies an alternative cgi directory path ( default: /usr/lib/cgi-bin) ])], + [CGI_DIR="$withval"], [CGI_DIR="/usr/lib/cgi-bin"]) +AC_SUBST([CGI_DIR]) + +AC_ARG_WITH([db-backend], + [AS_HELP_STRING([--with-db-backend], [Relies on a database for storing status messages and response files ])], + [RELY_ON_DB="-DRELY_ON_DB"], [RELY_ON_DB=""]) +AC_SUBST([RELY_ON_DB]) + + +# =========================================================================== +# Detect if libyaml is available +# =========================================================================== + +AC_ARG_WITH([yaml], + [AS_HELP_STRING([--with-yaml=PATH], [Specifies an alternative location for the yaml library])], + [YAMLPATH="$withval"], [YAMLPATH=""]) + +if test -z "$YAMLPATH" +then + YAML_LDFLAGS="" + YAML_CPPFLAGS="" + YAML_FILE="" + YAML_FILE1="" +else + + # Extract the linker and include flags + YAML_LDFLAGS="-L$YAMLPATH/lib -lyaml" + YAML_CPPFLAGS="-I$YAMLPATH/include -DYAML" + YAML_FILE="service_yaml.o" + YAML_FILE1="zcfg2yaml" + + # Check headers file + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$YAML_CPPFLAGS" + LIBS_SAVE="$LIBS" + LIBS="$YAML_LDFLAGS" + AC_CHECK_LIB([yaml], [yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan]) + AC_CHECK_HEADERS([yaml.h], + [], [AC_MSG_ERROR([could not find headers include related to YAML])]) + LIBS="$LIBS_SAVE" +fi +AC_SUBST([YAML_CPPFLAGS]) +AC_SUBST([YAML_LDFLAGS]) +AC_SUBST([YAML_FILE]) +AC_SUBST([YAML_FILE1]) + +# =========================================================================== +# Detect if fastcgi is available +# =========================================================================== + +AC_ARG_WITH([fastcgi], + [AS_HELP_STRING([--with-fastcgi=PATH], [Specifies an alternative location for the fastcgi library])], + [FCGIPATH="$withval"], [FCGIPATH="/usr"]) + +# Extract the linker and include flags +FCGI_LDFLAGS="-L$FCGIPATH/lib -lfcgi" +FCGI_CPPFLAGS="-I$FCGIPATH/include" + +# Check headers file +CPPFLAGS_SAVE="$CPPFLAGS" +CPPFLAGS="$FCGI_CPPFLAGS" +LIBS_SAVE="$LIBS" +LIBS="$FCGI_LDFLAGS" +AC_CHECK_LIB([fcgi], [main]) +AC_CHECK_HEADERS([fcgi_stdio.h], + [], [AC_MSG_ERROR([could not find headers include related to fastcgi])]) +LIBS="$LIBS_SAVE" +AC_SUBST([FCGI_CPPFLAGS]) +AC_SUBST([FCGI_LDFLAGS]) + +AC_ARG_WITH([metadb], + [AS_HELP_STRING([--with-metadb=yes], [Activates the metadata database support])], + [WITHMETADB="$withval"], [WITHMETADB=""]) + +if test "x$WITHMETADB" = "xyes"; then + METADB="-DMETA_DB" + METADB_FILE="meta_sql.o sqlapi.o" +else + METADB="" + METADB_FILE="" +fi + +AC_SUBST([METADB]) +AC_SUBST([METADB_FILE]) + +AC_ARG_WITH([hpc], + [AS_HELP_STRING([--with-hpc=yes], [Specifies if you need to activate HPC support])], + [HPCWITH="$withval"], [HPCWITH="no"]) + + +AC_ARG_WITH([ssh2], + [AS_HELP_STRING([--with-ssh2=PATH], [Specifies an alternative location for the ssh2 library])], + [SSH2PATH="$withval"], [SSH2PATH="/usr"]) + +if test "x$HPCWITH" = "xyes"; then + HPC_FILES="service_internal_hpc.o sshapi.o" + HPC_ENABLED="-DUSE_HPC" + HPC_CPPFLAGS="" + HPC_LDFLAGS="" + # Extract the linker and include flags + SSH2_LDFLAGS="-L$SSH2PATH/lib -lssh2" + SSH2_CPPFLAGS="-I$SSH2PATH/include" + # Check headers file + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$SSH2_CPPFLAGS" + LIBS_SAVE="$LIBS" + LIBS="$SSH2_LDFLAGS" + + AC_CHECK_HEADERS([libssh2.h], + [], [AC_MSG_ERROR([could not find headers related to libssh2])]) + AC_CHECK_LIB([ssh2], [libssh2_session_init]) + + LIBS="$LIBS_SAVE" +fi + +AC_SUBST([HPC_CPPFLAGS]) +AC_SUBST([HPC_LDFLAGS]) +AC_SUBST([HPC_ENABLED]) +AC_SUBST([HPC_FILES]) + +AC_SUBST([SSH2_CPPFLAGS]) +AC_SUBST([SSH2_LDFLAGS]) + +# =========================================================================== +# Detect if libxml2 is installed +# =========================================================================== + +AC_ARG_WITH([xml2config], + [AS_HELP_STRING([--with-xml2config=FILE], [Specifies an alternative xml2-config file])], + [XML2CONFIG="$withval"], [XML2CONFIG=""]) + +if test "x$XML2CONFIG" = "x"; then + # XML2CONFIG was not specified, so search within the current path + AC_PATH_PROG([XML2CONFIG], [xml2-config]) + + # If we couldn't find xml2-config, display a warning + if test "x$XML2CONFIG" = "x"; then + AC_MSG_ERROR([could not find xml2-config from libxml2 within the current path. You may need to try re-running configure with a --with-xml2config parameter.]) + fi +else + # XML2CONFIG was specified; display a message to the user + if test "x$XML2CONFIG" = "xyes"; then + AC_MSG_ERROR([you must Specifies a parameter to --with-xml2config, e.g. --with-xml2config=/path/to/xml2-config]) + else + if test -f $XML2CONFIG; then + AC_MSG_RESULT([Using user-specified xml2-config file: $XML2CONFIG]) + else + AC_MSG_ERROR([the user-specified xml2-config file $XML2CONFIG does not exist]) + fi + fi +fi + +# Extract the linker and include flags +XML2_LDFLAGS=`$XML2CONFIG --libs` +XML2_CPPFLAGS=`$XML2CONFIG --cflags` + +# Check headers file +CPPFLAGS_SAVE="$CPPFLAGS" +CPPFLAGS="$XML2_CPPFLAGS" +AC_CHECK_HEADERS([libxml/tree.h libxml/parser.h libxml/xpath.h libxml/xpathInternals.h], + [], [AC_MSG_ERROR([could not find headers include related to libxml2])]) + +# Ensure we can link against libxml2 +LIBS_SAVE="$LIBS" +LIBS="$XML2_LDFLAGS" +AC_CHECK_LIB([xml2], [xmlInitParser], [], [AC_MSG_ERROR([could not find libxml2])], []) + +AC_SUBST([XML2_CPPFLAGS]) +AC_SUBST([XML2_LDFLAGS]) +LIBS="$LIBS_SAVE" + + +# =========================================================================== +# Detect if libxslt is installed +# =========================================================================== + +AC_ARG_WITH([xsltconfig], + [AS_HELP_STRING([--with-xsltconfig=FILE], [Specifies an alternative xslt-config file])], + [XSLTCONFIG="$withval"], [XSLTCONFIG=""]) + +if test "x$XSLTCONFIG" = "x"; then + # XSLTCONFIG was not specified, so search within the current path + AC_PATH_PROG([XSLTCONFIG], [xslt-config]) + + # If we couldn't find xslt-config, display a warning + if test "x$XSLTCONFIG" = "x"; then + AC_MSG_ERROR([could not find xslt-config from libxslt within the current path. You may need to try re-running configure with a --with-xtltconfig parameter.]) + fi +else + # XSLTCONFIG was specified; display a message to the user + if test "x$XSLTCONFIG" = "xyes"; then + AC_MSG_ERROR([you must Specifies a parameter to --with-xsltconfig, e.g. --with-xsltconfig=/path/to/xslt-config]) + else + if test -f $XSLTCONFIG; then + AC_MSG_RESULT([Using user-specified xslt-config file: $XSLTCONFIG]) + else + AC_MSG_ERROR([the user-specified xslt-config file $XSLTCONFIG does not exist]) + fi + fi +fi + +# Extract the linker and include flags +XSLT_LDFLAGS=`$XSLTCONFIG --libs` +XSLT_CPPFLAGS=`$XSLTCONFIG --cflags` + +# Check headers file +CPPFLAGS_SAVE="$CPPFLAGS" +CPPFLAGS="$XSLT_CPPFLAGS" +AC_CHECK_HEADERS([libxslt/xslt.h libxslt/xsltInternals.h libxslt/transform.h libxslt/xsltutils.h], + [], [AC_MSG_ERROR([could not find headers include related to libxlst])]) + +AC_SUBST([XSLT_CPPFLAGS]) +AC_SUBST([XSLT_LDFLAGS]) + +#============================================================================ +# Detect if gdal is installed +#============================================================================ + +AC_ARG_WITH([gdal-config], + [AS_HELP_STRING([--with-gdal-config=FILE], [Specifies an alternative gdal-config file])], + [GDAL_CONFIG="$withval"], [GDAL_CONFIG=""]) +if test -z $GDAL_CONFIG; +then + AC_PATH_PROG([GDAL_CONFIG], [gdal-config]) + if test -z $GDAL_CONFIG; + then + AC_MSG_ERROR([could not find gdal-config from libgdal within the current path. You may need to try re-running configure with a --with-gdal-config parameter.]) + fi + +else + if test -f $GDAL_CONFIG; then + AC_MSG_RESULT([Using user-specified gdal-config file: $GDAL_CONFIG]) + else + AC_MSG_ERROR([the user-specified gdal-config file $GDAL_CONFIG does not exist]) + fi +fi + +GDAL_CFLAGS="`$GDAL_CONFIG --cflags`" +GDAL_LIBS="`$GDAL_CONFIG --libs`" + +AC_SUBST([GDAL_CFLAGS]) +AC_SUBST([GDAL_LIBS]) + +# =========================================================================== +# Detect if proj is installed +# =========================================================================== + +AC_ARG_WITH([proj], + [AS_HELP_STRING([--with-proj=PATH], [Specifies an alternative location for PROJ4 setup])], + [PROJPATH="$withval"], [PROJPATH="/usr"]) + +# Extract the linker and include flags +if test -f $PROJPATH/include/proj_api.h ; then + PJ_FULL_VERSION="$(grep 'define PJ_VERSION' /usr/include/proj_api.h | awk {'print $3'})" + PROJ_MAJOR_VERSION="$(echo ${PJ_FULL_VERSION:0:1})" + PROJ_VERSION="-DACCEPT_USE_OF_DEPRECATED_PROJ_API_H -DPROJ_VERSION_MAJOR=${PROJ_MAJOR_VERSION}" +else + PROJ_MAJOR_VERSION="$(grep "define PROJ_VERSION_MAJOR" -rni $PROJPATH/include/proj.h | awk {'print $3'})" + PROJ_VERSION="-DPROJ_VERSION_MAJOR=${PROJ_MAJOR_VERSION}" +fi +PROJ_CPPFLAGS="-I$PROJPATH/include ${PROJ_VERSION}" +PROJ_LDFLAGS="-L$PROJPATH/lib" + +# Check headers file +CPPFLAGS_SAVE="$CPPFLAGS" +CPPFLAGS="$PROJ_CPPFLAGS" + +AC_SUBST([PROJ_CPPFLAGS]) +AC_SUBST([PROJ_LDFLAGS]) + +# =========================================================================== +# Detect if libgeos is installed +# =========================================================================== + +AC_ARG_WITH([geosconfig], + [AS_HELP_STRING([--with-geosconfig=FILE], [Specifies an alternative geos-config file])], + [GEOSCONFIG="$withval"], [GEOSCONFIG=""]) + +if test "x$GEOSCONFIG" = "x"; then + # GEOSCONFIG was not specified, so search within the current path + AC_PATH_PROG([GEOSCONFIG], [geos-config]) + + # If we couldn't find geos-config, display a warning + if test "x$GEOSCONFIG" = "x"; then + AC_MSG_WARN([could not find geos-config from libgeos within the current path. You may need to try re-running configure with a --with-geosconfig parameter.]) + fi +else + # GEOSCONFIG was specified; display a message to the user + if test "x$GEOSCONFIG" = "xyes"; then + AC_MSG_WARN([you must Specifies a parameter to --with-geosconfig, e.g. --with-geosconfig=/path/to/geos-config]) + else + if test -f $GEOSCONFIG; then + AC_MSG_RESULT([Using user-specified geos-config file: $GEOSCONFIG]) + else + AC_MSG_ERROR([the user-specified geos-config file $GEOSCONFIG does not exist]) + fi + fi +fi + +GEOS_LDFLAGS=`$GEOSCONFIG --clibs` +GEOS_CPPFLAGS=`$GEOSCONFIG --cflags` + +# Check headers file +CPPFLAGS_SAVE="$CPPFLAGS" +CPPFLAGS="$GEOS_CPPFLAGS" +AC_CHECK_HEADERS([geos_c.h], + [], [AC_MSG_WARN([could not find headers include related to libgeos])]) + +AC_SUBST([GEOS_CPPFLAGS]) +AC_SUBST([GEOS_LDFLAGS]) + + +# =========================================================================== +# Detect if cgal is installed +# =========================================================================== + +AC_ARG_WITH([cgal], + [AS_HELP_STRING([--with-cgal=PATH], [Specifies an alternative location for CGAL setup])], + [CGALPATH="$withval"], [CGALPATH="/usr"]) + + +# Check headers file +CPPFLAGS_SAVE="$CPPFLAGS" +CGAL_CPPFLAGS="-I$CGALPATH/include" +CPPFLAGS="$CGAL_CPPFLAGS" +AC_CHECK_HEADERS([CGAL/Delaunay_triangulation_2.h], + [], [AC_MSG_WARN([could not find headers include related to libCGAL])]) + +# Extract the linker and include flags +CGAL_LDFLAGS="-L$CGALPATH/lib" +CGAL_CPPFLAGS="-I$CGALPATH/include" + + +AC_SUBST([CGAL_CPPFLAGS]) +AC_SUBST([CGAL_LDFLAGS]) +#============================================================================ +# Detect if mapserver is installed +#============================================================================ + +AC_ARG_WITH([mapserver], + [AS_HELP_STRING([--with-mapserver=PATH], [Specifies the path for MapServer compiled source tree])], + [MS_SRC_PATH="$withval"], [MS_SRC_PATH=""]) + +AC_ARG_WITH([ms-version], + [AS_HELP_STRING([--with-ms-version=VERSION], [Specifies the MapServer version to build against])], + [MS_VERSION="$withval"], [MS_VERSION=""]) + +if test -z $MS_SRC_PATH; +then + MS_CPPFLAGS="" + MS_LDFLAGS="" +else + if test "x$MS_SRC_PATH" = "xmacos"; + then + MS_LDFLAGS="/Library/Frameworks/MapServer.framework//Versions/6.0/MapServer -lintl" + MS_CPPFLAGS="-DUSE_MS `/Library/Frameworks/MapServer.framework/Programs/mapserver-config --includes` -I/Library/Frameworks/MapServer.framework/Versions/Current/Headers/ -I../mapserver " + AC_MSG_WARN([Please make sure that ../mapserver exists and contains MapServer source tree]) + AC_MSG_RESULT([Using MacOS X Framework for MapServer]) + else + if test "x$MS_VERSION" = "x7"; + then + MS_LDFLAGS="-L$MS_SRC_PATH/lib -lmapserver" + MS_CPPFLAGS="-DUSE_MS -I$MS_SRC_PATH/include/mapserver " + AC_MSG_RESULT([Using user-specified MapServer src path: $MS_SRC_PATH]) + else + if test -d $MS_SRC_PATH; then + MS_LDFLAGS="-L$MS_SRC_PATH -lmapserver `$MS_SRC_PATH/mapserver-config --libs`" + MS_CPPFLAGS="-DUSE_MS `$MS_SRC_PATH/mapserver-config --includes` `$MS_SRC_PATH/mapserver-config --cflags` -I$MS_SRC_PATH " + + AC_MSG_RESULT([Using user-specified MapServer src path: $MS_SRC_PATH]) + else + AC_MSG_ERROR([the user-specified mapserver-config file $MS_SRC_PATH does not exist]) + fi + fi + fi + MS_FILE="service_internal_ms.o" +fi + +MS_CFLAGS="$MS_CPPFLAGS" +MS_LIBS="$MS_LDFLAGS" + +AC_SUBST([MS_CFLAGS]) +AC_SUBST([MS_LIBS]) +AC_SUBST([MS_FILE]) +AC_SUBST([MS_VERSION]) + +# =========================================================================== +# Detect if R is installed +# =========================================================================== + +AC_ARG_WITH([r], + [AS_HELP_STRING([--with-r=PATH], [To enable R support or Specifies an alternative directory for R installation, disabled by default])], + [R_PATH="$withval"; R_ENABLED="-DUSE_R"], [R_ENABLED=""]) + +if test -z "$R_ENABLED" +then + R_FILE="" +else + R_FILE="service_internal_r.o" + # Extract the linker and include flags + R_LDFLAGS="-L$R_PATH/lib/ -lR" + R_CPPFLAGS="-I$R_PATH/include/ -I$R_PATH/share/R/include/" + + # Check headers file + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$R_CPPFLAGS" + AC_CHECK_HEADERS([Rinternals.h], + [], [AC_MSG_ERROR([could not find headers include related to R])]) + + # Ensure we can link against libphp + #LIBS_SAVE="$LIBS" + #LIBS="$R_LDFLAGS" + #AC_CHECK_LIB([$LIBS], [R_tryEval], [], [AC_MSG_ERROR([could not find libR])], []) + #LIBS="$LIBS_SAVE" +fi + +AC_SUBST([R_CPPFLAGS]) +AC_SUBST([R_LDFLAGS]) +AC_SUBST([R_ENABLED]) +AC_SUBST([R_FILE]) + + +# =========================================================================== +# Detect if python is installed +# =========================================================================== + +AC_ARG_WITH([python], + [AS_HELP_STRING([--with-python=PATH], [To enable python support or Specifies an alternative directory for python installation, disabled by default])], + [PYTHON_PATH="$withval"; PYTHON_ENABLED="-DUSE_PYTHON"], [PYTHON_ENABLED=""]) + +AC_ARG_WITH([pyvers], + [AS_HELP_STRING([--with-pyvers=NUM], [To use a specific python version])], + [PYTHON_VERS="$withval"], [PYTHON_VERS=""]) + + +if test -z "$PYTHON_ENABLED" +then + PYTHON_FILE="" +else + PYTHONCONFIG="$PYTHON_PATH/bin/python${PYTHON_VERS}-config" + PYTHON_FILE="service_internal_python.o" + if test "$PYTHON_PATH" = "yes" + then + # PYTHON was not specified, so search within the current path + PYTHONCFG_PATH=`which python${PYTHON_VERS}-config` + if test -z "${PYTHONCFG_PATH}" ; then + AC_PATH_PROG([PYTHONCONFIG], [python-config-${PYTHON_VERS}]) + else + AC_PATH_PROG([PYTHONCONFIG], [python${PYTHON_VERS}-config]) + fi + else + PYTHONCONFIG="$PYTHON_PATH/bin/python${PYTHON_VERS}-config" + fi + + echo $PYTHONCONFIG + # Extract the linker and include flags + #PYTHON_LDFLAGS=`$PYTHONCONFIG --ldflags` + PYTHON_LDFLAGS=$($PYTHONCONFIG --ldflags | sed "s:python${PYTHON_VERS}/config-${PYTHON_VERS}-::g") + PYTHON_CPPFLAGS=`$PYTHONCONFIG --includes` + + # Check headers file + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$PYTHON_CPPFLAGS" + AC_CHECK_HEADERS([Python.h], + [], [AC_MSG_ERROR([could not find headers include related to libpython])]) + + # Ensure we can link against libphp + LIBS_SAVE="$LIBS" + #LIBS="$PYTHON_LDFLAGS" + #PY_LIB=`$PYTHONCONFIG --libs | sed \ + # -e 's/.*\(python[[0-9]]\.[[0-9]]\).*/\1/'` + #AC_CHECK_LIB([$PY_LIB], [PyObject_CallObject], [], [AC_MSG_ERROR([could not find libpython])], []) + LIBS="m $PYTHON_LDFLAGS -lpython${PYTHON_VERS}" + PYTHON_LDFLAGS="-l$LIBS" + LDFLAGS=$PYTHON_LDFLAGS + AC_CHECK_LIB([], [PyObject_CallObject], [], [AC_MSG_ERROR([could not find libpython])], []) + LIBS="$LIBS_SAVE" +fi + +AC_SUBST([PYTHON_CPPFLAGS]) +AC_SUBST([PYTHON_LDFLAGS]) +AC_SUBST([PYTHON_ENABLED]) +AC_SUBST([PYTHON_FILE]) + +# =========================================================================== +# Detect if spidermonkey is installed +# =========================================================================== + +AC_ARG_WITH([js], + [AS_HELP_STRING([--with-js=PATH], [Specifies --with-js=path-to-js to enable js support, specify --with-js on linux debian like, js support is disabled by default ])], + [JSHOME="$withval";JS_ENABLED="-DUSE_JS"], [JS_ENABLED=""]) + +if test -z "$JS_ENABLED" +then + JS_FILE="" +else + JS_FILE="service_internal_js.o" + if test "$JSHOME" = "yes" + then + + #on teste si on est sous debian like + if test -f "/usr/bin/dpkg" + then + if test -n "`dpkg -l | grep libmozjs185-dev`" + then + JS_CPPFLAGS="-I/usr/include/js/" + JS_LDFLAGS="-L/usr/lib -lmozjs185 -lm" + JS_LIB="mozjs185" + else + XUL_VERSION="`dpkg -l | grep xulrunner | grep dev | head -1| awk '{print $3;}' | cut -d'+' -f1`" + if test -n "$XUL_VERSION" + then + JS_CPPFLAGS="-I/usr/include/xulrunner-$XUL_VERSION" + JS_LDFLAGS="-L/usr/lib/xulrunner-$XUL_VERSION -lmozjs -lm" + JS_LIB="mozjs" + else + AC_MSG_ERROR([You must install libmozjs185-dev or xulrunner-dev ]) + fi + fi + else + AC_MSG_ERROR([You must specify your custom install of libmozjs185]) + fi + else + JS_CPPFLAGS="-I$JSHOME/include/js/" + JS_LDFLAGS="-L$JSHOME/lib -lmozjs185 -lm" + JS_LIB="mozjs185" + + fi + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$JS_CPPFLAGS" + AC_LANG_PUSH([C++]) + AC_CHECK_HEADERS([jsapi.h], + [], [AC_MSG_ERROR([could not find headers include related to libjs])]) + + AC_LANG_POP([C++]) + LIBS_SAVE="$LIBS" + LIBS="$JS_LDFLAGS" + + AC_CHECK_LIB([$JS_LIB], [JS_CompileFile,JS_CallFunctionName], [], [AC_MSG_ERROR([could not find $JS_LIB])], []) + LIBS="$LIBS_SAVE" + + AC_SUBST([JS_CPPFLAGS]) + AC_SUBST([JS_LDFLAGS]) +fi + +AC_SUBST([JS_ENABLED]) +AC_SUBST([JS_FILE]) + +# =========================================================================== +# Detect if php is installed +# =========================================================================== + +AC_ARG_WITH([php], + [AS_HELP_STRING([--with-php=PATH], [To enable php support or specify an alternative directory for php installation, disabled by default])], + [PHP_PATH="$withval"; PHP_ENABLED="-DUSE_PHP"], [PHP_ENABLED=""]) + +AC_ARG_WITH([php-version], + [AS_HELP_STRING([--with-phpvers=NUM], [To use a specific php version])], + [PHP_VERS="$withval"], [PHP_VERS=""]) + + +if test -z "$PHP_ENABLED" +then + PHP_FILE="" +else + PHPCONFIG="$PHP_PATH/bin/php-config" + if test "x$PHP_VERS" = "x7" + then + PHP_FILE="service_internal_php7.o" + else + PHP_FILE="service_internal_php.o" + fi + if test "$PHP_PATH" = "yes" + then + # PHP was not specified, so search within the current path + AC_PATH_PROG([PHPCONFIG], [php-config]) + else + PHPCONFIG="$PHP_PATH/bin/php-config" + fi + + # Extract the linker and include flags + if test "x$PHP_VERS" = "x7" + then + PHP_LDFLAGS="-L/`$PHPCONFIG --prefix`/lib64 -lphp7" + else + PHP_LDFLAGS="-L/`$PHPCONFIG --prefix`/lib -lphp5" + fi + PHP_CPPFLAGS=`$PHPCONFIG --includes` + + # Check headers file + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$PHP_CPPFLAGS" + AC_CHECK_HEADERS([sapi/embed/php_embed.h], + [], [AC_MSG_ERROR([could not find headers include related to libphp])]) + + # Ensure we can link against libphp + LIBS_SAVE="$LIBS" + LIBS="$PHP_LDFLAGS" + # Shouldn't we get php here rather than php5 :) ?? + if test "x$PHP_VERS" = "x7" + then + echo $LIBS + #AC_CHECK_LIB([php7], [call_user_function], [], [AC_MSG_ERROR([could not find libphp])], []) + else + AC_CHECK_LIB([php5], [call_user_function], [], [AC_MSG_ERROR([could not find libphp])], []) + fi + LIBS="$LIBS_SAVE" + AC_SUBST([PHP_CPPFLAGS]) + AC_SUBST([PHP_LDFLAGS]) +fi + +AC_SUBST([PHP_ENABLED]) +AC_SUBST([PHP_FILE]) + +# =========================================================================== +# Detect if java is installed +# =========================================================================== + +AC_ARG_WITH([java], + [AS_HELP_STRING([--with-java=PATH], [To enable java support, specify a JDK_HOME, disabled by default])], + [JDKHOME="$withval"; JAVA_ENABLED="-DUSE_JAVA"], [JAVA_ENABLED=""]) + +AC_ARG_WITH([java-rpath], + [AS_HELP_STRING([--with-java-rpath=yes], [To set rpath for java support, disabled by default])], + [JAVA_RPATH="$withval"], [JAVA_RPATH=""]) + +if test -z "$JAVA_ENABLED" +then + JAVA_FILE="" +else + JAVA_FILE="service_internal_java.o" + if test "x$JDKHOME" = "x"; + then + AC_MSG_ERROR([could not find java installation path within the current path. You may need to try re-running configure with a --with-java parameter.]) + fi # JAVA was specified; display a message to the user + if test "x$JDKHOME" = "xyes"; + then + AC_MSG_ERROR([you must specify a parameter to --with-java, e.g. --with-java=/path/to/java]) + fi + + # Extract the linker and include flags + if test "x$JDKHOME" = "xmacos"; + then + JAVA_LDFLAGS="-framework JavaVM" + for i in `ls /Applications/Xcode.app/Contents/Developer//Platforms/MacOSX.platform/Developer/SDKs/`; do + JAVA_CPPFLAGS="-I/Applications/Xcode.app/Contents/Developer//Platforms/MacOSX.platform/Developer/SDKs/$i/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/" + done + else + if test -d "$JDKHOME/jre/lib/i386"; + then + JAVA_LDFLAGS="-L$JDKHOME/jre/lib/i386/server/ -ljvm -lpthread" + JAVA_CPPFLAGS="-I$JDKHOME/include -I$JDKHOME/include/linux" + if test x$JAVA_RPATH = "xyes"; then + JAVA_LDFLAGS="$JAVA_LDFLAGS -Wl,-rpath,$JDKHOME/jre/lib/i386/server/" + fi + else + if test -d "$JDKHOME/jre/lib/amd64"; then + JAVA_LDFLAGS="-L$JDKHOME/jre/lib/amd64/server/ -ljvm -lpthread" + JAVA_CPPFLAGS="-I$JDKHOME/include -I$JDKHOME/include/linux" + if test x$JAVA_RPATH = "xyes"; then + JAVA_LDFLAGS="$JAVA_LDFLAGS -Wl,-rpath,$JDKHOME/jre/lib/amd64/server/" + fi + else + JAVA_LDFLAGS="-L$JDKHOME/jre/lib/server/ -ljvm -lpthread" + JAVA_CPPFLAGS="-I$JDKHOME/include/ -I$JDKHOME/include/darwin" + if test x$JAVA_RPATH = "xyes"; then + JAVA_LDFLAGS="$JAVA_LDFLAGS -Wl,-rpath,$JDKHOME/jre/lib/server/" + fi + fi + fi + fi + + AC_LANG([C++]) + #echo $JAVA_CPPFLAGS + # Check headers file (second time we check that in fact) + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$JAVA_CPPFLAGS" + AC_CHECK_HEADERS([jni.h], + [], [AC_MSG_ERROR([could not find jni.h file])]) + CPPFLAGS="$CPPFLAGS_SAVE" + # Ensure we can link against libjava + LIBS_SAVE="$LIBS" + LIBS="$JAVA_LDFLAGS" + if test "x$JDKHOME" != "xmacos"; + then + AC_CHECK_LIB([jvm], [JNI_CreateJavaVM], [], [AC_MSG_ERROR([could not find libjvm])], []) + fi + LIBS="$LIBS_SAVE" + + AC_SUBST([JAVA_CPPFLAGS]) + AC_SUBST([JAVA_LDFLAGS]) +fi + +AC_SUBST([JAVA_ENABLED]) +AC_SUBST([JAVA_FILE]) + +# =========================================================================== +# Detect if mono is installed +# =========================================================================== + +AC_ARG_WITH([mono], + [AS_HELP_STRING([--with-mono=PATH], [To enable mono support, specify the path to find pkg-config, disabled by default])], + [MONOHOME="$withval"; MONO_ENABLED="-DUSE_MONO"], [MONO_ENABLED=""]) + +if test -z "$MONO_ENABLED" +then + MONO_FILE="" +else + MONO_FILE="service_internal_mono.o" + if test "x$MONOHOME" = "x"; + then + MONOHOME="/usr" + fi + if test "x$MONOHOME" = "xyes"; + then + MONOHOME="/usr" + fi + + # Extract the linker and include flags + MONO_CFLAGS=`$MONOHOME/bin/pkg-config --cflags mono-2` + MONO_LDFLAGS=`$MONOHOME/bin/pkg-config --libs mono-2` + + AC_LANG([C++]) + #echo $JAVA_CPPFLAGS + # Check headers file (second time we check that in fact) + CPPFLAGS_SAVE="$CFLAGS" + CPPFLAGS="$MONO_CFLAGS" + AC_CHECK_HEADERS([mono/jit/jit.h], + [], [AC_MSG_ERROR([could not find jit.h file])]) + CPPFLAGS="$CPPFLAGS_SAVE" + # Ensure we can link against libmono-2.0 + LIBS_SAVE="$LIBS" + LIBS="$MONO_LDFLAGS" + AC_CHECK_LIB([mono-2.0], [mono_runtime_invoke], [], [AC_MSG_ERROR([could not find libmono])], []) + LIBS="$LIBS_SAVE" + + AC_SUBST([MONO_CFLAGS]) + AC_SUBST([MONO_LDFLAGS]) +fi + +AC_SUBST([MONO_ENABLED]) +AC_SUBST([MONO_FILE]) + +# =========================================================================== +# Detect if ruby is installed +# =========================================================================== +AC_ARG_WITH([ruby], + [AS_HELP_STRING([--with-ruby=PATH], [To enable ruby support or specify an alternative directory for ruby installation, disabled by default])], + [RUBY_PATH="$withval"; RUBY_ENABLED="-DUSE_RUBY"], [RUBY_ENABLED=""]) + +AC_ARG_WITH([rvers], + [AS_HELP_STRING([--with-rvers=NUM], [To use a specific ruby version])], + [RUBY_VERS="$withval"], [RUBY_VERS=""]) + + +if test -z "$RUBY_ENABLED" +then + RUBY_FILE="" +else + RUBY_FILE="service_internal_ruby.o" + + # Extract the linker and include flags + RUBY_LDFLAGS="-lruby" + RUBY_CPPFLAGS="-I$RUBY_PATH -I$RUBY_PATH/x86_64-darwin13.0/ -DZRUBY_VERSION=$RUBY_VERS" + + # Check headers file + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$RUBY_CPPFLAGS" + AC_CHECK_HEADERS([ruby.h], + [], [AC_MSG_ERROR([could not find headers include related to libruby])]) + + # Ensure we can link against libphp + LIBS_SAVE="$LIBS" + LIBS="$RUBY_LDFLAGS" + # AC_CHECK_LIB([lruby], [PyObject_CallObject], [], [AC_MSG_ERROR([could not find libpython])], []) + LIBS="$LIBS_SAVE" + AC_SUBST([RUBY_CPPFLAGS]) + AC_SUBST([RUBY_LDFLAGS]) +fi + +AC_SUBST([RUBY_ENABLED]) +AC_SUBST([RUBY_FILE]) + +# =========================================================================== +# Detect if perl is installed +# =========================================================================== + +AC_ARG_WITH([perl], + [AS_HELP_STRING([--with-perl=PATH], [To enable perl support or specify an alternative directory for perl installation, disabled by default])], + [PERL_PATH="$withval"; PERL_ENABLED="-DUSE_PERL"], [PERL_ENABLED=""]) + + +if test -z "$PERL_ENABLED" +then + PERL_FILE="" +else + PERL_FILE="service_internal_perl.o" + if test "$PERL_PATH" = "yes" + then + # Perl was not specified, so search within the current path + AC_PATH_PROG([PERLCONFIG], [perl]) + else + PERLCONFIG="$PERL_PATH/bin/perl" + fi + + # Extract the linker and include flags + PERL_LDFLAGS=`$PERLCONFIG -MExtUtils::Embed -e ldopts` + PERL_CPPFLAGS=`$PERLCONFIG -MExtUtils::Embed -e ccopts` + + # Check headers file + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$PERL_CPPFLAGS" + AC_CHECK_HEADERS([EXTERN.h], + [], [AC_MSG_ERROR([could not find headers include related to libperl])]) + + AC_SUBST([PERL_CPPFLAGS]) + AC_SUBST([PERL_LDFLAGS]) +fi + +AC_SUBST([PERL_ENABLED]) +AC_SUBST([PERL_FILE]) + +# =========================================================================== +# Detect if otb is available +# =========================================================================== + +AC_ARG_WITH([itk], + [AS_HELP_STRING([--with-itk=PATH], [Specifies an alternative location for the itk library])], + [ITKPATH="$withval"], [ITKPATH=""]) + +AC_ARG_WITH([itk-version], + [AS_HELP_STRING([--with-itk-version=VERSION], [Specifies an alternative version for the itk library])], + [ITKVERS="$withval"], [ITKVERS=""]) + +AC_ARG_WITH([otb], + [AS_HELP_STRING([--with-otb=PATH], [Specifies an alternative location for the otb library])], + [OTBPATH="$withval"], [OTBPATH=""]) + +AC_ARG_WITH([otb-version], + [AS_HELP_STRING([--with-otb-version=PATH], [Specifies an alternative location for the otb library])], + [OTBVERS="$withval"], [OTBVERS=""]) + +if test -z "$OTBPATH" +then + OTB_LDFLAGS="" + OTB_CPPFLAGS="" + OTB_FILE="" + OTB_ENABLED="" +else + if test -z "$ITKVERS" + then + ITKVERS="4.5" + fi + OTB_ENABLED="-DUSE_OTB" + IVERS="$(echo -e '4.10\n$ITKVERS' | sort -r | head -n1)" + if test "$IVERS" == "$ITKVERS"; then + ITK_LDFLAGS="-lITKBiasCorrection-$ITKVERS -lITKCommon-$ITKVERS -lITKIOImageBase-$ITKVERS -lITKKLMRegionGrowing-$ITKVERS -lITKLabelMap-$ITKVERS -lITKMesh-$ITKVERS -lITKMetaIO-$ITKVERS -lITKOptimizers-$ITKVERS -lITKPath-$ITKVERS -lITKPolynomials-$ITKVERS -lITKQuadEdgeMesh-$ITKVERS -lITKSpatialObjects-$ITKVERS -lITKStatistics-$ITKVERS -lITKVNLInstantiation-$ITKVERS -lITKWatersheds-$ITKVERS -litkNetlibSlatec-$ITKVERS -litksys-$ITKVERS -litkv3p_netlib-$ITKVERS -litkvcl-$ITKVERS -litkvnl-$ITKVERS" + else + ITK_LDFLAGS="-lITKBiasCorrection-$ITKVERS -lITKCommon-$ITKVERS -lITKIOImageBase-$ITKVERS -lITKKLMRegionGrowing-$ITKVERS -lITKLabelMap-$ITKVERS -lITKMesh-$ITKVERS -lITKMetaIO-$ITKVERS -lITKOptimizers-$ITKVERS -lITKPath-$ITKVERS -lITKPolynomials-$ITKVERS -lITKQuadEdgeMesh-$ITKVERS -lITKSpatialObjects-$ITKVERS -lITKStatistics-$ITKVERS -lITKVNLInstantiation-$ITKVERS -lITKWatersheds-$ITKVERS -litkNetlibSlatec-$ITKVERS -litksys-$ITKVERS -litkv3p_netlib-$ITKVERS -litkvcl-$ITKVERS -litkvnl-$ITKVERS -litkvnl_algo-$ITKVERS" + fi + if test -a "${OTBPATH}/include/OTB-${OTBVERS}" ; then + OTB_RPATH="$OTBPATH/include/OTB-${OTBVERS}/" + OTB_CPPFLAGS="-I${OTB_RPATH} -I${OTB_RPATH}ApplicationEngine -I$OTB_RPATH/Common -I$ITKPATH/include/ITK-$ITKVERS -I$OTB_RPATH/Utilities/ITK -I$OTB_RPATH/ -I$OTB_RPATH/IO -I$OTB_RPATH/UtilitiesAdapters/OssimAdapters -I$OTB_RPATH/UtilitiesAdapters/CurlAdapters -I$OTB_RPATH/Utilities/BGL -I$OTB_RPATH/UtilitiesAdapters/ITKPendingPatches -I$OTB_RPATH/Utilities/otbconfigfile $GDAL_CFLAGS" + OTB_LDFLAGS="-L/usr/lib/x86_64-linux-gnu/ -lOTBImageIO-$OTBVERS -lOTBCommon-$OTBVERS -lOTBApplicationEngine-$OTBVERS -L$ITKPATH/lib $ITK_LDFLAGS" + else + OTB_CPPFLAGS="-I$OTBPATH/include/otb/ApplicationEngine -I$OTBPATH/include/otb/Common -I$ITKPATH/include/ITK-$ITKVERS -I$OTBPATH/include/otb/Utilities/ITK -I$OTBPATH/include/otb/ -I$OTBPATH/include/otb/IO -I$OTBPATH/include/otb/UtilitiesAdapters/OssimAdapters -I$OTBPATH/include/otb/UtilitiesAdapters/CurlAdapters -I$OTBPATH/include/otb/Utilities/BGL -I$OTBPATH/include/otb/UtilitiesAdapters/ITKPendingPatches -I$OTBPATH/include/otb/Utilities/otbconfigfile $GDAL_CFLAGS" + OTB_LDFLAGS="-L$OTBPATH/lib/otb -lOTBIO -lOTBCommon -lOTBApplicationEngine -L$ITKPATH/lib $ITK_LDFLAGS" + + fi + OTB_FILE="otbZooWatcher.o service_internal_otb.o" + + AC_LANG_PUSH([C++]) + # Check headers file + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$OTB_CPPFLAGS" + LDFLAGS_SAVE="$LDFLAGS" + LIBS="$LIBS_SAVE $OTB_LDFLAGS" + #echo $OTB_CPPFLAGS + AC_CHECK_HEADERS([otbWrapperApplication.h otbWrapperInputImageListParameter.h otbWrapperApplicationRegistry.h], + [], [AC_MSG_ERROR([could not find header file $i related to OTB])]) + LDFLAGS_SAVE="$LDFLAGS" + LDFLAGS="$OTB_LDFLAGS" + #echo $OTB_LDFLAGS + #UVERS="$(echo -e '5.8\n$OTBVERS' | sort -r | head -n1)" + #if test "$OTBVERS" == "$UVERS" ; then + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "otbWrapperApplicationRegistry.h"]],[[std::vector list = otb::Wrapper::ApplicationRegistry::GetAvailableApplications();]])], + [AC_MSG_RESULT([checking for GetAvailableApplications... yes])],[AC_MSG_WARN([checking for GetAvailableApplications... failed])]) + #else + # AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "otbWrapperApplication.h"]],[[std::vector list = otb::Wrapper::ApplicationRegistry::GetAvailableApplication();]])], + # [AC_MSG_RESULT([checking for GetAvailableApplication... yes])],[AC_MSG_ERROR([checking for GetAvailableApplication... failed])]) + #fi + + LDFLAGS="$LDFLAGS_SAVE" + AC_LANG_POP([C++]) + AC_LANG(C++) + +fi +AC_SUBST([OTB_CPPFLAGS]) +AC_SUBST([OTB_LDFLAGS]) +AC_SUBST([OTB_FILE]) +AC_SUBST([OTB_ENABLED]) + +# =========================================================================== +# Detect if saga-gis is available +# =========================================================================== + +AC_ARG_WITH([wx-config], + [AS_HELP_STRING([--with-wx-config=PATH], [Specifies an alternative path for the wx-config tool])], + [WXCFG="$withval"], [WXCFG=""]) + +AC_ARG_WITH([saga], + [AS_HELP_STRING([--with-saga=PATH], [Specifies an alternative location for the SAGA-GIS library])], + [SAGAPATH="$withval"], [SAGAPATH=""]) + +AC_ARG_WITH([saga-version], + [AS_HELP_STRING([--with-saga-version=VERSION], [Specifies the SAGA-GIS version number])], + [SAGAVERS="$withval"], [SAGAVERS="2"]) + +if test -z "$SAGAPATH" +then + SAGA_LDFLAGS="" + SAGA_CPPFLAGS="" + SAGA_FILE="" + SAGA_ENABLED="" +else + if test -z "$WXCFG" ; then + WXCFG="$(which wx-config)" + fi + if test "`$WXCFG --list | grep unicode`" == "" ; then + AC_MSG_ERROR(SAGA requires a unicode build of wxGTK) + fi + WX_ISSUE="-D_WX_WXCRTVARARG_H_" + SAGA_DEFS="-D_SAGA_LINUX -D_TYPEDEF_BYTE -D_TYPEDEF_WORD -DMODULE_LIBRARY_PATH=\\\"$SAGAPATH/lib/saga\\\"" + SAGA_CPPFLAGS="-DSAGA_VERSION=${SAGAVERS} -fPIC -I$SAGAPATH/include/saga/saga_core/saga_api/ -I$SAGAPATH/include/saga_api/ `$WXCFG --unicode=yes --static=no --cxxflags` -D_SAGA_UNICODE $SAGA_DEFS $WX_ISSUE" + SAGA_LDFLAGS="-fPIC `$WXCFG --unicode=yes --static=no --libs` -lsaga_api" + SAGA_ENABLED="-DUSE_SAGA" + SAGA_FILE="service_internal_saga.o" + + AC_LANG_PUSH([C++]) + # Check headers file + CPPFLAGS_SAVE="$CPPFLAGS" + CPPFLAGS="$SAGA_CPPFLAGS" + LIBS_SAVE="$LIBS" + LIBS="$SAGA_LDFLAGS" + if test "$SAGAVERS" == "2"; then + AC_CHECK_HEADERS([module_library.h], + [], [AC_MSG_ERROR([could not find header file $i related to SAGA-GIS])]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "module_library.h"],[SG_Get_Module_Library_Manager();]])], + [AC_MSG_RESULT([checking for SG_Get_Module_Library_Manager... yes])],[AC_MSG_ERROR([checking for SG_Get_Module_Library_Manager... failed])]) + else + AC_CHECK_HEADERS([tool_library.h], + [], [AC_MSG_ERROR([could not find header file $i related to SAGA-GIS])]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "tool_library.h"],[SG_Get_Tool_Library_Manager();]])], + [AC_MSG_RESULT([checking for SG_Get_Tool_Library_Manager... yes])],[AC_MSG_ERROR([checking for SG_Get_Tool_Library_Manager... failed])]) + fi + + LIBS="$LIBS_SAVE" + AC_LANG_POP([C++]) +fi +AC_SUBST([SAGA_CPPFLAGS]) +AC_SUBST([SAGA_LDFLAGS]) +AC_SUBST([SAGA_FILE]) +AC_SUBST([SAGA_ENABLED]) + +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([ZOOMakefile.opts]) +AC_CONFIG_FILES([main.cfg]) +AC_OUTPUT diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/response_print.c b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/response_print.c index 5e8926d7..50bc9a64 100644 --- a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/response_print.c +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/response_print.c @@ -1,7 +1,7 @@ /* * Author : Gérald FENOY * - * Copyright (c) 2009-2015 GeoLabs SARL + * Copyright (c) 2009-2020 GeoLabs SARL * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -40,42 +40,43 @@ #endif #include "mimetypes.h" +#include "service_json.h" /** * Add prefix to the service name. * - * @param conf the conf maps containing the main.cfg settings - * @param level the map containing the level information - * @param serv the service structure created from the zcfg file + * @param pmsConf the conf maps containing the main.cfg settings + * @param pmLevel the map containing the level information + * @param psService the service structure created from the zcfg file */ -void addPrefix(maps* conf,map* level,service* serv){ - if(level!=NULL){ - char key[25]; - char* prefix=NULL; - int clevel=atoi(level->value); - int cl=0; - for(cl=0;clvalue); + int iCl=0; + for(iCl=0;iClvalue); + if(pcaPrefix==NULL) + pcaPrefix=zStrdup(tmp2->value); else{ - int plen=strlen(prefix); - prefix=(char*)realloc(prefix,(plen+strlen(tmp2->value)+2)*sizeof(char)); - memcpy(prefix+plen,tmp2->value,strlen(tmp2->value)*sizeof(char)); - prefix[plen+strlen(tmp2->value)]=0; + int plen=strlen(pcaPrefix); + pcaPrefix=(char*)realloc(pcaPrefix,(plen+strlen(tmp2->value)+2)*sizeof(char)); + memcpy(pcaPrefix+plen,tmp2->value,strlen(tmp2->value)*sizeof(char)); + pcaPrefix[plen+strlen(tmp2->value)]=0; } } } - if(prefix!=NULL){ - char* tmp0=zStrdup(serv->name); - free(serv->name); - serv->name=(char*)malloc((strlen(prefix)+strlen(tmp0)+1)*sizeof(char)); - sprintf(serv->name,"%s%s",prefix,tmp0); - free(tmp0); - free(prefix); - prefix=NULL; + if(pcaPrefix!=NULL){ + char* pcaTmp=zStrdup(psService->name); + free(psService->name); + psService->name=(char*)malloc((strlen(pcaPrefix)+strlen(pcaTmp)+1)*sizeof(char)); + sprintf(psService->name,"%s%s",pcaPrefix,pcaTmp); + free(pcaTmp); + free(pcaPrefix); + pcaPrefix=NULL; } } } @@ -83,17 +84,81 @@ void addPrefix(maps* conf,map* level,service* serv){ /** * Print the HTTP headers based on a map. * - * @param m the map containing the headers information + * @param pmsConf the map containing the headers information */ -void printHeaders(maps* m){ - maps *_tmp=getMaps(m,"headers"); - if(_tmp!=NULL){ - map* _tmp1=_tmp->content; - while(_tmp1!=NULL){ - printf("%s: %s\r\n",_tmp1->name,_tmp1->value); - _tmp1=_tmp1->next; +void printHeaders(maps* pmsConf){ + maps *pmsTmp=getMaps(pmsConf,"headers"); + if(pmsTmp!=NULL){ + map* pmTmp=pmsTmp->content; + while(pmTmp!=NULL){ + printf("%s: %s\r\n",pmTmp->name,pmTmp->value); + pmTmp=pmTmp->next; } } + printSessionHeaders(pmsConf); +} + +/** + * Print the Set-Cookie header if necessary (conf["lenv"]["cookie"]) and save + * the session file. + * + * The session file (sess__.cfg where is the cookie value) is + * stored in the conf["main"]["tmpPath"] directory. + * @param pmsConf the main configuration map + */ +void printSessionHeaders(maps* pmsConf){ + maps* pmsSess=getMaps(pmsConf,"senv"); + if(pmsSess!=NULL){ + map *pmTmp=getMapFromMaps(pmsConf,"lenv","cookie"); + char* sessId=NULL; + if(pmTmp!=NULL){ + printf("Set-Cookie: %s; HttpOnly\r\n",pmTmp->value); + map *pmTmp1=getMapFromMaps(pmsConf,"senv","ecookie_length"); + if(pmTmp1!=NULL){ + int len=atoi(pmTmp1->value); + int cnt=0; + for(cnt=0;cntcontent,"ecookie",cnt); + if(pmTmp2!=NULL) + printf("Set-Cookie: %s; HttpOnly\r\n",pmTmp2->value); + } + } + printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n"); + char session_file_path[100]; + char *tmp1=strtok(pmTmp->value,";"); + if(tmp1!=NULL) + sprintf(session_file_path,"%s",strstr(tmp1,"=")+1); + else + sprintf(session_file_path,"%s",strstr(pmTmp->value,"=")+1); + sessId=zStrdup(session_file_path); + }else{ + maps* t=getMaps(pmsConf,"senv"); + map*p=t->content; + while(p!=NULL){ + if(strstr(p->name,"ID")!=NULL){ + sessId=zStrdup(p->value); + break; + } + p=p->next; + } + } + char session_file_path[1024]; + map *tmpPath=getMapFromMaps(pmsConf,"main","sessPath"); + if(tmpPath==NULL) + tmpPath=getMapFromMaps(pmsConf,"main","tmpPath"); + sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId); + FILE* teste=fopen(session_file_path,"w"); + if(teste==NULL){ + char tmpMsg[1024]; + sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the session maps."),session_file_path); + errorException(pmsConf,tmpMsg,"InternalError",NULL); + return; + } + else{ + fclose(teste); + dumpMapsToFile(pmsSess,session_file_path,1); + } + } } /** @@ -800,7 +865,7 @@ void addMetadata(map* meta,xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_ows,xmlNsPtr snprintf(tmp,index,"%s",meta->name); xmlNewNsProp(nc1,ns_xlink,BAD_CAST tmp,BAD_CAST meta->value); free(tmp); - } + } if(ctitle!=NULL) free(ctitle); ctitle=zStrdup(meta->value); @@ -831,6 +896,8 @@ void addMetadata(map* meta,xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_ows,xmlNsPtr if(oMeta!=NULL && hasValue<0 && nc1!=NULL){ xmlAddChild(nc,nc1); } + if(ctitle!=NULL) + free(ctitle); } /** @@ -896,7 +963,7 @@ void addAdditionalParameters(map* meta,xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_o snprintf(tmp,index,"%s",meta->name); xmlNewNsProp(nc1,ns_xlink,BAD_CAST tmp,BAD_CAST meta->value); free(tmp); - } + } if(ctitle!=NULL) free(ctitle); ctitle=zStrdup(meta->value); @@ -941,8 +1008,9 @@ void addAdditionalParameters(map* meta,xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_o len=1; if(cnt1){ - pWorkspace = ++baseU; - } - } - // fprintf(stderr, "------> %s \n", s); - s = *(orig+ei); - } - - if (pWorkspace){ - const char *HTTP_HOST = std::getenv("HTTP_HOST"); - const char *REQUEST_SCHEME = std::getenv("REQUEST_SCHEME"); - const char *REQUEST_URI = std::getenv("REQUEST_URI"); - sprintf(workspace, "%s://%s/%s/zoo", REQUEST_SCHEME, HTTP_HOST,pWorkspace); - fprintf(stderr, "------> >>>>>>%s://%s<<<<<\n", REQUEST_SCHEME, HTTP_HOST); - fprintf(stderr,"---------WORKSPACE: %s--------------\n",workspace); - } - doc = xmlNewDoc(BAD_CAST "1.0"); map* version=getMapFromMaps(m,"main","rversion"); int vid=getVersionId(version->value); @@ -1863,12 +1902,6 @@ void printProcessResponse(maps* m,map* request, int pid,service* serv,const char * percentCompleted attribute). * Else fallback to the initial method using the xml file to write in ... */ - - if (strlen(workspace)>0 && tmpm1 && tmpm1->value ){ - free(tmpm1->value); - tmpm1->value = zStrdup(workspace); - } - map* cwdMap=getMapFromMaps(m,"main","servicePath"); struct stat myFileInfo; int statRes; @@ -1896,26 +1929,14 @@ void printProcessResponse(maps* m,map* request, int pid,service* serv,const char sprintf(currentSid,"%s",tmp_lenv->value); if(tmpm==NULL || strcasecmp(tmpm->value,"false")==0){ sprintf(url,"%s?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid); - - // fprintf(stderr,"---------THEPATH: %s--------------\n",tmpm1->value); - // fprintf(stderr,"---------WORKSPACE1: %s--------------\n",workspace); - - }else{ + }else{ if(strlen(tmpm->value)>0) if(strcasecmp(tmpm->value,"true")!=0) - { - // fprintf(stderr,"---------WORKSPACE2: %s--------------\n",workspace); - sprintf(url,"%s/%s/GetStatus/%s",tmpm1->value,tmpm->value,currentSid); - } + sprintf(url,"%s/%s/GetStatus/%s",tmpm1->value,tmpm->value,currentSid); else - { - // fprintf(stderr,"---------WORKSPACE3: %s--------------\n",workspace); - sprintf(url,"%s/GetStatus/%s",tmpm1->value,currentSid); - } - else{ - // fprintf(stderr,"---------WORKSPACE4: %s--------------\n",workspace); + sprintf(url,"%s/GetStatus/%s",tmpm1->value,currentSid); + else sprintf(url,"%s/?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid); - } } }else{ int lpid; @@ -1930,7 +1951,7 @@ void printProcessResponse(maps* m,map* request, int pid,service* serv,const char } } if(tmpm1!=NULL){ - sprintf(tmp,"%s",tmpm1->value); + sprintf(tmp,"%s",tmpm1->value); } int lpid; map* tmpm2=getMapFromMaps(m,"lenv","usid"); @@ -1941,16 +1962,6 @@ void printProcessResponse(maps* m,map* request, int pid,service* serv,const char xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp); map* test=getMap(request,"storeExecuteResponse"); if(test!=NULL && strcasecmp(test->value,"true")==0){ - - - fprintf(stderr,"---------URL: %s--------------\n",url); -// fprintf(stderr,"-----------------------\n"); -// //maps* m,map* request, int pid,service* serv,const char* service,int status,maps* inputs,maps* outputs -// dumpMaps(m); -// fprintf(stderr,"-----------------------\n"); -// dumpMap(request); -// fprintf(stderr,"-----------------------\n"); - xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url); hasStoredExecuteResponse=true; } @@ -2087,7 +2098,7 @@ void printProcessResponse(maps* m,map* request, int pid,service* serv,const char if(tmp0!=NULL && strncmp(tmp0->value,"true",4)==0){ if(vid==0) printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid); - else + else printIOType(doc,n,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid); } }else @@ -2525,6 +2536,32 @@ void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map } } +/** + * Produce the status string used in HTTP headers. + * + * @param pmConf the maps containing the settings of the main.cfg file + * @param pmCode the map containing the error code (or a map array of the same keys) + */ +const char* produceStatusString(maps* pmConf,map* pmCode){ + if(pmCode!=NULL){ + int iI=0; + for(iI=0;iI<3;iI++){ + int iJ=0; + for(iJ=1;;iJ++){ + if(aapccStatusCodes[iI][iJ]==NULL) + break; + else{ + if(strcmp(aapccStatusCodes[iI][iJ],pmCode->value)==0) + return aapccStatusCodes[iI][0]; + } + } + } + } + else{ + return aapccStatusCodes[3][0]; + } +} + /** * Print an OWS ExceptionReport Document and HTTP headers (when required) * depending on the code. @@ -2533,9 +2570,7 @@ void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map * @param m the maps containing the settings of the main.cfg file * @param s the map containing the text,code,locator keys (or a map array of the same keys) */ -void printExceptionReportResponse(maps* m,map* s){ - if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL) - return; +void _printExceptionReportResponse(maps* m,map* s){ int buffersize; xmlDocPtr doc; xmlChar *xmlbuff; @@ -2548,30 +2583,12 @@ void printExceptionReportResponse(maps* m,map* s){ const char *exceptionCode; map* tmp=getMap(s,"code"); - if(tmp!=NULL){ - if(strcmp(tmp->value,"OperationNotSupported")==0 || - strcmp(tmp->value,"NoApplicableCode")==0) - exceptionCode="501 Not Implemented"; - else - //rdr/* - if(strcmp(tmp->value,"MissingParameterValue")==0){ - exceptionCode="404 Not Found"; - } - //rdr*/ - else - if(strcmp(tmp->value,"InvalidUpdateSequence")==0 || - strcmp(tmp->value,"OptionNotSupported")==0 || - strcmp(tmp->value,"VersionNegotiationFailed")==0 || - strcmp(tmp->value,"InvalidParameterValue")==0) - exceptionCode="400 Bad request"; - else - exceptionCode="501 Internal Server Error"; - } - else - exceptionCode="501 Internal Server Error"; + exceptionCode=produceStatusString(m,tmp); tmp=getMapFromMaps(m,"lenv","status_code"); if(tmp!=NULL) exceptionCode=tmp->value; + if(exceptionCode==NULL) + exceptionCode=aapccStatusCodes[3][0]; if(m!=NULL){ map *tmpSid=getMapFromMaps(m,"lenv","sid"); if(tmpSid!=NULL){ @@ -2597,7 +2614,24 @@ void printExceptionReportResponse(maps* m,map* s){ xmlCleanupParser(); zooXmlCleanupNs(); if(m!=NULL) - setMapInMaps(m,"lenv","hasPrinted","true"); + setMapInMaps(m,"lenv","hasPrinted","true"); +} + +/** + * Print an OWS ExceptionReport or exception.yaml Document and HTTP headers + * (when required) depending on the code. + * + * @param pmsConf the maps containing the settings of the main.cfg file + * @param psService the service + */ +void printExceptionReportResponse(maps* pmsConf,map* psService){ + if(getMapFromMaps(pmsConf,"lenv","hasPrinted")!=NULL) + return; + map* pmExecutionType=getMapFromMaps(pmsConf,"main","executionType"); + if(pmExecutionType!=NULL && strncasecmp(pmExecutionType->value,"xml",3)==0) + _printExceptionReportResponse(pmsConf,psService); + else + printExceptionReportResponseJ(pmsConf,psService); } /** @@ -2690,18 +2724,123 @@ xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){ */ int errorException(maps *m, const char *message, const char *errorcode, const char *locator) { + map* pmExectionType=getMapFromMaps(m,"main","executionType"); map* errormap = createMap("text", message); addToMap(errormap,"code", errorcode); if(locator!=NULL) addToMap(errormap,"locator", locator); else addToMap(errormap,"locator", "NULL"); - printExceptionReportResponse(m,errormap); + if(pmExectionType!=NULL && strncasecmp(pmExectionType->value,"xml",3)==0) + printExceptionReportResponse(m,errormap); + else{ + printExceptionReportResponseJ(m,errormap); + setMapInMaps(m,"lenv","no-headers","true"); + } freeMap(&errormap); free(errormap); return -1; } +/** + * Produce a copy file and the corresponding url in case it is required + * Please, free the returned ressource while used + * + * @param pmConf maps* pointing to the main configuration file + */ +char* produceFileUrl(service* psService,maps* pmsConf,maps* pmsOutputs,const char* pccFormat, int itn){ + // Create file for reference data if not existing + map *pmGFile=getMap(pmsOutputs->content,"generated_file"); + map *pmTmpPath=getMapFromMaps(pmsConf,"main","tmpPath"); + map *pmTmpUrl=getMapFromMaps(pmsConf,"main","tmpUrl"); + char *pcaFileName=NULL; + char *pcaFilePath=NULL; + char *pcaFileUrl=NULL; + if(pmGFile!=NULL){ + pmGFile=getMap(pmsOutputs->content,"expected_generated_file"); + if(pmGFile==NULL){ + pmGFile=getMap(pmsOutputs->content,"generated_file"); + } + if(strstr(pmGFile->value,pmTmpPath->value)!=NULL) + pcaFileName=zStrdup(strstr(pmGFile->value,pmTmpPath->value)+strlen(pmTmpPath->value)); + } + // Create file for reference data + map *pmUsid=getMapFromMaps(pmsConf,"lenv","usid"); + map *pmExt=getMap(pmsOutputs->content,"extension"); + if(pmGFile==NULL){ + char acFileExt[32]; + if( pmExt != NULL && pmExt->value != NULL) { + strncpy(acFileExt, pmExt->value, 32); + } + else { + // Obtain default file extension (see mimetypes.h). + // If the MIME type is not recognized, txt is used as the default extension + map* pmType=getMap(pmsOutputs->content,"mimeType"); + getFileExtension(pmType != NULL ? pmType->value : NULL, acFileExt, 32); + } + if(pcaFileName!=NULL) + free(pcaFileName); + + pcaFileName=(char*)malloc((strlen(psService->name)+strlen(pmUsid->value)+strlen(acFileExt)+strlen(pmsOutputs->name)+45)*sizeof(char)); + sprintf(pcaFileName,"ZOO_DATA_%s_%s_%s_%d.%s",psService->name,pmsOutputs->name,pmUsid->value,itn,acFileExt); + + pcaFilePath=(char*)malloc((strlen(pmTmpPath->value)+strlen(pcaFileName)+2)*sizeof(char)); + sprintf(pcaFilePath,"%s/%s",pmTmpPath->value,pcaFileName); + }else{ + pcaFilePath=(char*)malloc((strlen(pmGFile->value)+1)*sizeof(char)); + sprintf(pcaFilePath,"%s",pmGFile->value); + } + + pcaFileUrl=(char*)malloc((strlen(pmTmpUrl->value)+ + strlen(pcaFileName)+2)*sizeof(char)); + sprintf(pcaFileUrl,"%s/%s",pmTmpUrl->value,pcaFileName); + + if(pmGFile==NULL) { + FILE *pfOfile=fopen(pcaFilePath,"wb"); + if(pfOfile==NULL){ + char acTmpMsg[1024]; + sprintf(acTmpMsg, + _("Unable to create the file \"%s\" for storing the %s final result."), + pcaFileName,pmsOutputs->name); + map* pmError=createMap("code","InternalError"); + addToMap(pmError,"message",acTmpMsg); + printExceptionReportResponseJ(pmsConf,pmError); + free(pcaFileName); + free(pcaFilePath); + return NULL; + } + + map* pmValue=getMap(pmsOutputs->content,"value"); + if(pmValue==NULL){ + char acTmpMsg[1024]; + sprintf(acTmpMsg, + _("No value found for the requested output %s."), + pmsOutputs->name); + map* pmError=createMap("code","InternalError"); + addToMap(pmError,"message",acTmpMsg); + printExceptionReportResponseJ(pmsConf,pmError); + fclose(pfOfile); + free(pcaFileName); + free(pcaFilePath); + return NULL; + } + if(pccFormat==NULL || strcasecmp(pccFormat,"BoundingBoxData")!=0){ + map* size=getMap(pmsOutputs->content,"size"); + if(size!=NULL && pmValue!=NULL) + fwrite(pmValue->value,1,(atoi(size->value))*sizeof(char),pfOfile); + else + if(pmValue!=NULL && pmValue->value!=NULL) + fwrite(pmValue->value,1, + strlen(pmValue->value)*sizeof(char),pfOfile); + }else + printBoundingBoxDocument(pmsConf,pmsOutputs,pfOfile); + fclose(pfOfile); + } + free(pcaFileName); + free(pcaFilePath); + return pcaFileUrl; +} + /** * Generate the output response (RawDataOutput or ResponseDocument) * @@ -2720,77 +2859,15 @@ void outputResponse(service* s,maps* request_inputs,maps* request_outputs, dumpMaps(request_outputs); fprintf(stderr,"printProcessResponse\n"); #endif - map* toto=getMap(request_inputs1,"RawDataOutput"); + map* pmRawData=getMap(request_inputs1,"RawDataOutput"); int asRaw=0; - if(toto!=NULL) + if(pmRawData!=NULL) asRaw=1; map* version=getMapFromMaps(m,"main","rversion"); int vid=getVersionId(version->value); - maps* tmpSess=getMaps(m,"senv"); - if(tmpSess!=NULL){ - map *_tmp=getMapFromMaps(m,"lenv","cookie"); - maps *tmps=getMaps(m,"senv"); - char* sessId=NULL; - if(_tmp!=NULL){ - printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value); - map *_tmp1=getMapFromMaps(m,"senv","ecookie_length"); - if(_tmp1!=NULL){ - int len=atoi(_tmp1->value); - int cnt=0; - for(cnt=0;cntcontent,"ecookie",cnt); - if(_tmp2!=NULL) - printf("Set-Cookie: %s; HttpOnly\r\n",_tmp2->value); - } - } - printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n"); - char session_file_path[100]; - char *tmp1=strtok(_tmp->value,";"); - if(tmp1!=NULL) - sprintf(session_file_path,"%s",strstr(tmp1,"=")+1); - else - sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1); - sessId=zStrdup(session_file_path); - }else{ - maps* t=getMaps(m,"senv"); - map*p=t->content; - while(p!=NULL){ - if(strstr(p->name,"ID")!=NULL){ - sessId=zStrdup(p->value); - break; - } - p=p->next; - } - } - char session_file_path[1024]; - map *tmpPath=getMapFromMaps(m,"main","sessPath"); - if(tmpPath==NULL) - tmpPath=getMapFromMaps(m,"main","tmpPath"); - sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId); - FILE* teste=fopen(session_file_path,"w"); - if(teste==NULL){ - char tmpMsg[1024]; - sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the session maps."),session_file_path); - errorException(m,tmpMsg,"InternalError",NULL); - return; - } - else{ - fclose(teste); - dumpMapsToFile(tmpSess,session_file_path,1); - } - } + printSessionHeaders(m); if(res==SERVICE_FAILED){ - map *lenv; - lenv=getMapFromMaps(m,"lenv","message"); - char *tmp0; - if(lenv!=NULL){ - tmp0=(char*)malloc((strlen(lenv->value)+strlen(_("Unable to run the Service. The message returned back by the Service was the following: "))+1)*sizeof(char)); - sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value); - } - else{ - tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char)); - sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service.")); - } + char* tmp0=produceErrorMessage(m); errorException(m,tmp0,"InternalError",NULL); free(tmp0); return; @@ -2834,7 +2911,7 @@ void outputResponse(service* s,maps* request_inputs,maps* request_outputs, #ifdef USE_MS map* testMap=getMap(tmpI->content,"useMapserver"); #endif - map *gfile=getMap(tmpI->content,"generated_file"); + /*map *gfile=getMap(tmpI->content,"generated_file"); char *file_name=NULL; if(gfile!=NULL){ gfile=getMap(tmpI->content,"expected_generated_file"); @@ -2843,16 +2920,17 @@ void outputResponse(service* s,maps* request_inputs,maps* request_outputs, } readGeneratedFile(m,tmpI->content,gfile->value); file_name=zStrdup((gfile->value)+strlen(tmp1->value)); - } - toto=getMap(tmpI->content,"asReference"); + }*/ + char *pcaFileUrl=NULL; + pmRawData=getMap(tmpI->content,"asReference"); #ifdef USE_MS map* geodatatype=getMap(tmpI->content,"geodatatype"); - if(toto!=NULL && strcasecmp(toto->value,"true")==0 && + if(pmRawData!=NULL && strcasecmp(pmRawData->value,"true")==0 && (testMap==NULL || strncasecmp(testMap->value,"true",4)!=0 || (geodatatype!=NULL && strcasecmp(geodatatype->value,"other")==0) ) ) #else - if(toto!=NULL && strcasecmp(toto->value,"true")==0) + if(pmRawData!=NULL && strcasecmp(pmRawData->value,"true")==0) #endif { elements* in=getElements(s->outputs,tmpI->name); @@ -2869,79 +2947,12 @@ void outputResponse(service* s,maps* request_inputs,maps* request_outputs, addToMap(tmpI->content,"mimeType","text/xml"); addToMap(tmpI->content,"encoding","UTF-8"); addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd"); - } - char *file_path=NULL; - if(gfile==NULL) { - map *ext=getMap(tmpI->content,"extension"); - char file_ext[32]; - - if( ext != NULL && ext->value != NULL) { - strncpy(file_ext, ext->value, 32); - } - else { - // Obtain default file extension (see mimetypes.h). - // If the MIME type is not recognized, txt is used as the default extension - map* mtype=getMap(tmpI->content,"mimeType"); - getFileExtension(mtype != NULL ? mtype->value : NULL, file_ext, 32); - } - if(file_name!=NULL) - free(file_name); - file_name=(char*)malloc((strlen(s->name)+strlen(usid->value)+strlen(file_ext)+strlen(tmpI->name)+45)*sizeof(char)); - sprintf(file_name,"ZOO_DATA_%s_%s_%s_%d.%s",s->name,tmpI->name,usid->value,itn,file_ext); - itn++; - file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char)); - sprintf(file_path,"%s/%s",tmp1->value,file_name); - - FILE *ofile=fopen(file_path,"wb"); - if(ofile==NULL){ - char tmpMsg[1024]; - sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the %s final result."),file_name,tmpI->name); - errorException(m,tmpMsg,"InternalError",NULL); - free(file_name); - free(file_path); - return; - } - - toto=getMap(tmpI->content,"value"); - if(toto==NULL){ - char tmpMsg[1024]; - sprintf(tmpMsg,_("No value found for the requested output %s."),tmpI->name); - errorException(m,tmpMsg,"InternalError",NULL); - fclose(ofile); - free(file_name); - free(file_path); - return; - } - if(strcasecmp(format,"BoundingBoxData")!=0){ - map* size=getMap(tmpI->content,"size"); - if(size!=NULL && toto!=NULL) - fwrite(toto->value,1,(atoi(size->value))*sizeof(char),ofile); - else - if(toto!=NULL && toto->value!=NULL) - fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile); - }else{ - printBoundingBoxDocument(m,tmpI,ofile); - } - fclose(ofile); } - - map *tmp2=getMapFromMaps(m,"main","tmpUrl"); - map *tmp3=getMapFromMaps(m,"main","serverAddress"); - char *file_url=NULL; - if(strncasecmp(tmp2->value,"http://",7)==0 || - strncasecmp(tmp2->value,"https://",8)==0){ - file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char)); - sprintf(file_url,"%s/%s",tmp2->value,file_name); - }else{ - file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char)); - sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name); - } - addToMap(tmpI->content,"Reference",file_url); - if(file_name!=NULL) - free(file_name); - if(file_url!=NULL) - free(file_url); - file_name=NULL; + pcaFileUrl=produceFileUrl(s,m,tmpI,format,itn); + itn++; + if(pcaFileUrl==NULL) + return; + addToMap(tmpI->content,"Reference",pcaFileUrl); } #ifdef USE_MS else{ @@ -2959,9 +2970,9 @@ void outputResponse(service* s,maps* request_inputs,maps* request_outputs, } } #endif - if(file_name!=NULL){ - free(file_name); - file_name=NULL; + if(pcaFileUrl!=NULL){ + free(pcaFileUrl); + pcaFileUrl=NULL; } tmpI=tmpI->next; } @@ -3005,57 +3016,175 @@ void outputResponse(service* s,maps* request_inputs,maps* request_outputs, if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){ printBoundingBoxDocument(m,tmpI,NULL); }else{ - map *gfile=getMap(tmpI->content,"generated_file"); - if(gfile!=NULL){ - gfile=getMap(tmpI->content,"expected_generated_file"); - if(gfile==NULL){ - gfile=getMap(tmpI->content,"generated_file"); - } - readGeneratedFile(m,tmpI->content,gfile->value); - } - toto=getMap(tmpI->content,"value"); - if(toto==NULL){ - char tmpMsg[1024]; - sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),tmpI->name); - errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput"); - return; - } - map* fname=getMapFromMaps(tmpI,tmpI->name,"filename"); - if(fname!=NULL) - printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value); - map* rs=getMapFromMaps(tmpI,tmpI->name,"size"); - if(rs!=NULL) - printf("Content-Length: %s\r\n",rs->value); - printHeaders(m); - char mime[1024]; - map* mi=getMap(tmpI->content,"mimeType"); -#ifdef DEBUG - fprintf(stderr,"SERVICE OUTPUTS\n"); - dumpMaps(request_outputs); - fprintf(stderr,"SERVICE OUTPUTS\n"); -#endif - map* en=getMap(tmpI->content,"encoding"); - if(mi!=NULL && en!=NULL) - sprintf(mime, - "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n", - mi->value,en->value); - else - if(mi!=NULL) + printRawdataOutput(m,tmpI); + } + } +} + +/** + * Get the number of outputs provided in the execute request body. + * + * @param conf the main configuration + * @param outputs the outputs to count + */ +int getNumberOfOutputs(maps* conf,maps* outputs){ + int res=0; + maps* pmsOut=outputs; + while(pmsOut!=NULL){ + map* pmTmp=getMap(pmsOut->content,"inRequest"); + if(pmTmp!=NULL && strcmp(pmTmp->value,"true")==0) + res++; + pmsOut=pmsOut->next; + } + return res; +} + +/** + * Print all outputs as raw + * + * @param conf the main configuration maps + * @param outputs the output to be print as raw + */ +void* printRawdataOutputs(maps* conf,service* s,maps* outputs){ + maps* pmsOut=outputs; + if(pmsOut!= NULL && pmsOut->next!=NULL && getNumberOfOutputs(conf,outputs)>1){ + map* pmUsid=getMapFromMaps(conf,"lenv","usid"); + char* pcaBoundary=(char*)malloc(strlen(pmUsid->value)+2+1); + sprintf(pcaBoundary,"--%s",pmUsid->value); + map* mi=getMap(pmsOut->content,"mimeType"); + if(mi!=NULL) + printf("Content-Type: Multipart/Related; boundary=\"%s\"; type=%s; start=%s\r\nStatus: 200 OK\r\n\r\n",pcaBoundary,mi->value,pmsOut->name); + else + printf("Content-Type: Multipart/Related; boundary=\"%s\"; type=text/plain; start=%s\r\nStatus: 200 OK\r\n\r\n",pcaBoundary,pmsOut->name); + int itn=0; + while(pmsOut!=NULL){ + map* pmPresence=getMap(pmsOut->content,"inRequest"); + if(pmPresence!=NULL && strcmp(pmPresence->value,"true")==0){ + mi=getMap(pmsOut->content,"mimeType"); + printf("--%s\r\n",pcaBoundary); + printf("Content-ID: %s\r\n",pmsOut->name); + map* pmDescription=getMap(pmsOut->content,"abstract"); + if(pmDescription==NULL) + pmDescription=getMap(pmsOut->content,"title"); + if(pmDescription!=NULL) + printf("Content-Description: %s\r\n",pmDescription->value); + + char mime[1024]; + map* en=getMap(outputs->content,"encoding"); + if(mi!=NULL && en!=NULL) sprintf(mime, - "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n", - mi->value); + "Content-Type: %s; charset=%s\r\n", + mi->value,en->value); else - sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n"); - printf("%s",mime); - if(rs!=NULL) - fwrite(toto->value,1,atoi(rs->value),stdout); - else - fwrite(toto->value,1,strlen(toto->value),stdout); -#ifdef DEBUG - dumpMap(toto); -#endif + if(mi!=NULL) + sprintf(mime, + "Content-Type: %s; charset=UTF-8\r\n", + mi->value); + else + sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n"); + map* pmTransmissionMode=getMap(pmsOut->content,"transmissionMode"); + if(pmTransmissionMode!=NULL && strcasecmp(pmTransmissionMode->value,"reference")==0){ + char *pcaFileUrl=produceFileUrl(s,conf,pmsOut,NULL,itn); + printf("%s",mime); + printf("Content-Location: %s\r\n",pcaFileUrl); + itn++; + }else{ + map *gfile=getMap(pmsOut->content,"generated_file"); + if(gfile!=NULL){ + gfile=getMap(pmsOut->content,"expected_generated_file"); + if(gfile==NULL){ + gfile=getMap(pmsOut->content,"generated_file"); + } + readGeneratedFile(conf,pmsOut->content,gfile->value); + } + map* pmValue=getMap(pmsOut->content,"value"); + if(pmValue==NULL){ + char tmpMsg[1024]; + sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),outputs->name); + map* pmExecutionType=getMapFromMaps(conf,"main","executionType"); + if(pmExecutionType!=NULL && strncasecmp(pmExecutionType->value,"xml",3)==0) + errorException(conf,tmpMsg,"InvalidParameterValue","RawDataOutput"); + else{ + setMapInMaps(conf,"lenv","error","true"); + setMapInMaps(conf,"lenv","code","InvalidParameterValue"); + setMapInMaps(conf,"lenv","message",tmpMsg); + } + return NULL; + } + printf("%s",mime); + map* rs=getMap(pmsOut->content,"size"); + map* fname=getMap(pmsOut->content,"filename"); + if(fname!=NULL) + printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value); + else + printf("Content-Disposition: INLINE\r\n"); + if(rs!=NULL) + fwrite(pmValue->value,1,atoi(rs->value),stdout); + else + fwrite(pmValue->value,1,strlen(pmValue->value),stdout); + } + } + pmsOut=pmsOut->next; + } + printf("--%s--\r\n",pcaBoundary); + } + else printRawdataOutput(conf,outputs); +} + +/** + * Print one outputs as raw + * + * @param conf the main configuration maps + * @param outputs the output to be print as raw + */ +void* printRawdataOutput(maps* conf,maps* outputs){ + map *gfile=getMap(outputs->content,"generated_file"); + if(gfile!=NULL){ + gfile=getMap(outputs->content,"expected_generated_file"); + if(gfile==NULL){ + gfile=getMap(outputs->content,"generated_file"); } + readGeneratedFile(conf,outputs->content,gfile->value); } + map* toto=getMap(outputs->content,"value"); + if(toto==NULL){ + char tmpMsg[1024]; + sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),outputs->name); + map* pmExecutionType=getMapFromMaps(conf,"main","executionType"); + if(pmExecutionType!=NULL && strncasecmp(pmExecutionType->value,"xml",3)==0) + errorException(conf,tmpMsg,"InvalidParameterValue","RawDataOutput"); + else{ + setMapInMaps(conf,"lenv","error","true"); + setMapInMaps(conf,"lenv","code","InvalidParameterValue"); + setMapInMaps(conf,"lenv","message",tmpMsg); + } + return NULL; + } + map* fname=getMapFromMaps(outputs,outputs->name,"filename"); + if(fname!=NULL) + printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value); + map* rs=getMapFromMaps(outputs,outputs->name,"size"); + if(rs!=NULL) + printf("Content-Length: %s\r\n",rs->value); + char mime[1024]; + map* mi=getMap(outputs->content,"mimeType"); + map* en=getMap(outputs->content,"encoding"); + if(mi!=NULL && en!=NULL) + sprintf(mime, + "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n", + mi->value,en->value); + else + if(mi!=NULL) + sprintf(mime, + "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n", + mi->value); + else + sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n"); + printf("%s",mime); + if(rs!=NULL) + fwrite(toto->value,1,atoi(rs->value),stdout); + else + fwrite(toto->value,1,strlen(toto->value),stdout); } /** diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/response_print.h b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/response_print.h new file mode 100644 index 00000000..1a2b3caa --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/response_print.h @@ -0,0 +1,279 @@ +/* + * Author : Gérald FENOY + * + * Copyright (c) 2009-2013 GeoLabs SARL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ZOO_RESPONSE_PRINT_H +#define ZOO_RESPONSE_PRINT_H 1 + +#pragma once + +/** + * The default service url (overriden by serverAddress) + */ +#define DEFAULT_SERVICE_URL "http://www.zoo-project.org/" +/** + * The time size + */ +#define TIME_SIZE 40 + +#include +#include + +/** + * ZOO-Kernel internal messages translation function + */ +#define _(String) dgettext ("zoo-kernel",String) +/** + * ZOO-Services messages translation function + */ +#define _ss(String) dgettext ("zoo-services",String) + +/** + * ZOO-Kernel was unable to create a lock + */ +#define ZOO_LOCK_CREATE_FAILED -4 +/** + * ZOO-Kernel was unable to acquire a lock + */ +#define ZOO_LOCK_ACQUIRE_FAILED -5 +/** + * ZOO-Kernel was unable to release a lock + */ +#define ZOO_LOCK_RELEASE_FAILED -6 + +#include +#include +#ifndef WIN32 +#include +#include +#include +#else +#include +#endif +#include +#include +#include +#ifdef WIN32 +#ifndef USE_RUBY +#include +#endif +#endif +#ifndef WIN32 +//#include +#include // knut: this appears to be a non-standard header file that has been removed in newer versions of glibc; it may be sufficient to include (see above) +#endif + +#include "service.h" +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + /** + * Maximum number of XML namespaces + */ +#define ZOO_NS_MAX 10 + /** + * Maximum number of XML docs + */ +#define ZOO_DOC_MAX 20 + + /** + * Global char* to store the serverAddress value of the [main] section + */ + static char* SERVICE_URL; + + /** + * Array of xmlNsPtr storing all used XML namespace + */ + static xmlNsPtr usedNs[ZOO_NS_MAX]; + /** + * Array storing names of the used XML namespace + */ + static char* nsName[ZOO_NS_MAX]; + /** + * Number of XML namespaces + */ + static int nbNs=0; + /** + * Array of xmlDocPtr storing XML docs + */ + static xmlDocPtr iDocs[ZOO_DOC_MAX]; + /** + * Number of XML docs + */ + static int nbDocs=0; + + /** + * Definitions of acceptable final status + */ + static char wpsStatus[3][11]={ + "Succeeded", + "Failed", + "Running" + }; + /** + * Definitions of schemas depending on the WPS version + */ + static const char* schemas[2][8]={ + {"1.0.0","http://www.opengis.net/ows/1.1","http://www.opengis.net/wps/1.0.0","http://schemas.opengis.net/wps/1.0.0","%s %s/wps%s_response.xsd","http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd","1.1.0"}, + {"2.0.0","http://www.opengis.net/ows/2.0","http://www.opengis.net/wps/2.0","http://schemas.opengis.net/wps/2.0","http://www.opengis.net/wps/2.0 http://schemas.opengis.net/wps/2.0/wps.xsd","http://schemas.opengis.net/ows/2.0/owsExceptionReport.xsd","2.0.2","http://www.opengis.net/spec/wps/2.0/def/process-profile/"}, + }; + /** + * Definitions of support requests (depending on the WPS version) + */ + static int nbSupportedRequests=7; + /** + * Definitions of requests depending on the WPS version + */ + static const char* requests[2][7]={ + {"GetCapabilities","DescribeProcess","Execute",NULL}, + {"GetCapabilities","DescribeProcess","Execute","GetStatus","GetResult","Dismiss",NULL}, + }; + /** + * Definitions requests requiring identifier (depending on the WPS version) + */ + static int nbReqIdentifier=2; + /** + * Definitions requests requiring jobid (only for WPS version 2.0.0) + */ + static int nbReqJob=3; + /** + * Definitions of root node for response depending on the request and the WPS version + */ + static const char* root_nodes[2][4]={ + {"ProcessOfferings","ProcessDescriptions","ExecuteResponse",NULL}, + {"Contents","ProcessOfferings","Result",NULL} + }; + + /** + * Name and corresponding attributes depending on the WPS version + */ + static const char* capabilities[2][7]={ + { + "Process", + "processVersion","1", + "storeSupported","true", + "statusSupported","true" + }, + { + "ProcessSummary", + "processVersion","1.0.0", + "jobControlOptions","sync-execute async-execute dismiss", + "outputTransmission","value reference" + } + }; + + /** + * Correspondance between HTTP status code and exception code + */ + static const char* const aapccStatusCodes[][10] = { + { + "500 Internal Server Error", + "OperationNotSupported", + "NoApplicableCode", + "InvalidQueryParameterValue", + NULL + }, + { + "400 Bad request", + "MissingParameterValue" + "InvalidParameterValue", + "InvalidUpdateSequence", + "OptionNotSupported", + "VersionNegotiationFailed", + "NoSuchMode", + "BadRequest", + // ref. https://github.com/opengeospatial/ogcapi-processes/issues/250 + //"InvalidQueryParameterValue", + NULL + }, + { + "404 Not Found", + "NotFound", + "NoSuchProcess", + "NoSuchJob", + "ResultNotReady", + NULL + }, + { + "501 Not Implemented", + NULL + } + }; + + void addLangAttr(xmlNodePtr,maps*); + + void printHeaders(maps*); + void printSessionHeaders(maps*); + + int zooXmlSearchForNs(const char*); + int zooXmlAddNs(xmlNodePtr,const char*,const char*); + void zooXmlCleanupNs(); + + int zooXmlAddDoc(xmlNodePtr,const char*,const char*); + void zooXmlCleanupDocs(); + + const char* produceStatusString(maps*,map*); + void printExceptionReportResponse(maps*,map*); + xmlNodePtr createExceptionReportNode(maps*,map*,int); + void printProcessResponse(maps*,map*,int,service*,const char*,int,maps*,maps*); + xmlNodePtr printWPSHeader(xmlDocPtr,maps*,const char*,const char*,const char*,int); + xmlNodePtr printGetCapabilitiesHeader(xmlDocPtr,maps*,const char*); + void printGetCapabilitiesForProcess(registry*,maps*,void*,void*,service*); + void printDescribeProcessForProcess(registry*,maps*,void*,void*,service*); + void printFullDescription(xmlDocPtr,int,elements*,const char*,xmlNsPtr,xmlNsPtr,xmlNodePtr,int,int,const map*); + void printDocument(maps*,xmlDocPtr,int); + void printDescription(xmlNodePtr,xmlNsPtr,const char*,map*,int); + void printIOType(xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,xmlNsPtr,elements*,maps*,const char*,int); + void* printRawdataOutput(maps*,maps*); + void* printRawdataOutputs(maps*,service*,maps*); + map* parseBoundingBox(const char*); + void printBoundingBox(xmlNsPtr,xmlNodePtr,map*); + void printBoundingBoxDocument(maps*,maps*,FILE*); + void printOutputDefinitions(xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,elements*,maps*,const char*); + void printStatusInfo(maps*,map*,char*); + void addAdditionalParameters(map*,xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,int); + void addMetadata(map*,xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,int); + + char* produceFileUrl(service*,maps*,maps*,const char*, int); + void outputResponse(service*,maps*,maps*,map*,int,maps*,int); + + int errorException(maps *, const char *, const char *, const char*); + + xmlNodePtr soapEnvelope(maps*,xmlNodePtr); + int checkForSoapEnvelope(xmlDocPtr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/server_internal.c b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/server_internal.c new file mode 100644 index 00000000..6380fdda --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/server_internal.c @@ -0,0 +1,1398 @@ +/* + * Author : Gérald Fenoy + * + * Copyright 2008-2015 GeoLabs SARL. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "server_internal.h" +#include "service_internal.h" +#include "response_print.h" +//#include "service_callback.h" +#include "mimetypes.h" +#ifndef WIN32 +#include +#include +#else +#include +#define ERROR_MSG_MAX_LENGTH 1024 +#endif +#include + +// #include +/* + * Compare two file path strings to see if they refer to the same file. + * + * @param path1 the first file path + * @param path2 the second file path + * + * @return 0 if the files are identical + */ +#define PATHBUFSIZE 4096 +int zoo_path_compare(char* path1, char* path2) { + + if (path1 == NULL || path2 == NULL) { + return -1; + } + + char realpath1[PATHBUFSIZE]; + char realpath2[PATHBUFSIZE]; + +#ifdef WIN32 + int res1 = GetFullPathName(path1, PATHBUFSIZE, realpath1, NULL); + int res2 = GetFullPathName(path2, PATHBUFSIZE, realpath2, NULL); + + if (res1 == 0 || res2 == 0) { + return -1; + } + else { + return strncasecmp(realpath1, realpath2, PATHBUFSIZE); + } +#else + char* ptr1 = realpath(path1, realpath1); + char* ptr2 = realpath(path2, realpath2); + + if (ptr1 == NULL || ptr2 == NULL) { + return -1; + } + else { + return strncmp(realpath1, realpath2, PATHBUFSIZE); + } +#endif +} + +/** + * Detect WPS version used (1.0.0 or 2.0.0). + * + * @param version number as char* (1.0.0 or 2.0.0) + * @return 0 in case of version 1.0.0, 1 for 2.0.0, -1 in other case + */ +int getVersionId(const char* version){ + int schemaId=0; + for(;schemaId<2;schemaId++){ + if(strncasecmp(version,schemas[schemaId][0],5)==0) + return schemaId; + } + return -1; +} + +/** + * Generate a UUID. + * ref: https://www.ietf.org/rfc/rfc4122.txt / 4.2 + * + * @return a new char* containing the UUID, make sure to free the returned + * resource once used. + */ +char *get_uuid(){ + char *res=(char*)malloc(37*sizeof(char)); +#ifdef WIN32 + UUID uuid; + UuidCreate(&uuid); + RPC_CSTR rest = NULL; + UuidToString(&uuid,&rest); +#else + uuid_t uuid; + uuid_generate_time(uuid); + char rest[128]; + uuid_unparse(uuid,rest); +#endif + sprintf(res,"%s",rest); +#ifdef WIN32 + RpcStringFree(&rest); +#endif + return res; +} + +/** + * Extract the service identifier from the full service identifier + * ie: + * - Full service name: OTB.BandMath + * - Service name: BandMath + * + * @param conf the maps containing the settings of the main.cfg file + * @param conf_dir the full path to the ZOO-Kernel directory + * @param identifier the full service name (potentialy including a prefix, ie: + * Prefix.MyService) + * @param buffer the resulting service identifier (without any prefix) + */ +void parseIdentifier(maps* conf,char* conf_dir,char *identifier,char* buffer){ + setMapInMaps(conf,"lenv","oIdentifier",identifier); + char *lid=zStrdup(identifier); + char *saveptr1; + char *tmps1=strtok_r(lid,".",&saveptr1); + int level=0; + char key[25]; + char levels[18]; + while(tmps1!=NULL){ + char *test=zStrdup(tmps1); + char* tmps2=(char*)malloc((strlen(test)+2)*sizeof(char)); + sprintf(key,"sprefix_%d",level); + sprintf(tmps2,"%s.",test); + sprintf(levels,"%d",level); + setMapInMaps(conf,"lenv","level",levels); + setMapInMaps(conf,"lenv",key,tmps2); + free(tmps2); + free(test); + level++; + tmps1=strtok_r(NULL,".",&saveptr1); + } + int i=0; + sprintf(buffer,"%s",conf_dir); + for(i=0;ivalue); + free(tmp0); + buffer[strlen(buffer)-1]=0; + if(i+1value)==0){ + char *tmp01=zStrdup(tmp00->value); + tmp01[strlen(tmp01)-1]=0; + setMapInMaps(conf,"lenv","metapath",tmp01); + free(tmp01); + tmp01=NULL; + } + else{ + if(tmp00!=NULL && tmpMap!=NULL){ + char *tmp00s=zStrdup(tmp00->value); + tmp00s[strlen(tmp00s)-1]=0; + char *value=(char*)malloc((strlen(tmp00s)+strlen(tmpMap->value)+2)*sizeof(char)); + sprintf(value,"%s/%s",tmpMap->value,tmp00s); + setMapInMaps(conf,"lenv","metapath",value); + free(value); + free(tmp00s); + value=NULL; + } + } + }else{ + char *tmp01=zStrdup(tmp00->value); + tmp01[strlen(tmp01)-1]=0; + setMapInMaps(conf,"lenv","Identifier",tmp01); + free(tmp01); + } + } + char *tmp0=zStrdup(buffer); + sprintf(buffer,"%s.zcfg",tmp0); + free(tmp0); + free(lid); +} + +/** + * Converts a hex character to its integer value + * + * @param ch the char to convert + * @return the converted char + */ +char from_hex(char ch) { + return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; +} + +/** + * Converts an integer value to its hec character + * + * @param code the char to convert + * @return the converted char + */ +char to_hex(char code) { + static char hex[] = "0123456789abcdef"; + return hex[code & 15]; +} + +/** + * URLEncode an url + * + * @param str the url to encode + * @return a url-encoded version of str + * @warning be sure to free() the returned string after use + */ +char *url_encode(char *str) { + char *pstr = str, *buf = (char*) malloc(strlen(str) * 3 + 1), *pbuf = buf; + while (*pstr) { + if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') + *pbuf++ = *pstr; + else if (*pstr == ' ') + *pbuf++ = '+'; + else + *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15); + pstr++; + } + *pbuf = '\0'; + return buf; +} + +/** + * Decode an URLEncoded url + * + * @param str the URLEncoded url to decode + * @return a url-decoded version of str + * @warning be sure to free() the returned string after use + */ +char *url_decode(char *str) { + char *pstr = str, *buf = (char*) malloc(strlen(str) + 1), *pbuf = buf; + while (*pstr) { + if (*pstr == '%') { + if (pstr[1] && pstr[2]) { + *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]); + pstr += 2; + } + } else if (*pstr == '+') { + *pbuf++ = ' '; + } else { + *pbuf++ = *pstr; + } + pstr++; + } + *pbuf = '\0'; + return buf; +} + +/** + * Verify if a given language is listed in the lang list defined in the [main] + * section of the main.cfg file. + * + * @param conf the map containing the settings from the main.cfg file + * @param str the specific language + * @return 1 if the specific language is listed, -1 in other case. + */ +int isValidLang(maps* conf,const char *str){ + map *tmpMap=getMapFromMaps(conf,"main","language"); + char *tmp0=NULL,*tmp=NULL,*tmp1=NULL; + if(tmpMap!=NULL) + tmp0=zStrdup(tmpMap->value); + tmpMap=getMapFromMaps(conf,"main","lang"); + if(tmpMap!=NULL) + tmp=zStrdup(tmpMap->value); + if(tmp0!=NULL && tmp!=NULL){ + tmp1=(char*)malloc((strlen(tmp0)+strlen(tmp)+2)*sizeof(char)); + sprintf(tmp1,"%s,%s",tmp0,tmp); + free(tmp0); + free(tmp); + }else{ + if(tmp!=NULL){ + tmp1=zStrdup(tmp); + free(tmp); + }else{ + if(tmp0!=NULL){ + tmp1=zStrdup(tmp0); + free(tmp0); + } + } + } + char *pToken,*saveptr; + pToken=strtok_r(tmp1,",",&saveptr); + int res=-1; + while(pToken!=NULL){ + if(strcasecmp(str,pToken)==0){ + res=1; + break; + } + pToken=strtok_r(NULL,",",&saveptr); + } + if(tmp1!=NULL) + free(tmp1); + return res; +} + + +/** + * Access the value of the encoding key in a maps + * + * @param m the maps to search for the encoding key + * @return the value of the encoding key in a maps if encoding key exists, + * "UTF-8" in other case. + */ +char* getEncoding(maps* m){ + if(m!=NULL){ + map* tmp=getMap(m->content,"encoding"); + if(tmp!=NULL){ + return tmp->value; + } + else + return (char*)"UTF-8"; + } + else + return (char*)"UTF-8"; +} + +/** + * Access the value of the version key in a maps + * + * @param m the maps to search for the version key + * @return the value of the version key in a maps if encoding key exists, + * "1.0.0" in other case. + */ +char* getVersion(maps* m){ + if(m!=NULL){ + map* tmp=getMap(m->content,"version"); + if(tmp!=NULL){ + return tmp->value; + } + else + return (char*)"1.0.0"; + } + else + return (char*)"1.0.0"; +} + +/** + * Read a file generated by a service. + * + * @param m the conf maps + * @param content the output item + * @param filename the file to read + */ +void readGeneratedFile(maps* m,map* content,char* filename){ + char rsize[1024]; + FILE * file=fopen(filename,"rb"); + if(file==NULL){ + setMapInMaps(m,"lenv","message","Unable to read produced file. Please try again later"); + return ; + } + zStatStruct f_status; + int s=zStat(filename, &f_status); + sprintf(rsize,"%ld",f_status.st_size); + if(getMap(content,"storage")==NULL){ + map* tmpMap1=getMap(content,"value"); + if(tmpMap1==NULL){ + addToMap(content,"value",""); + tmpMap1=getMap(content,"value"); + } + free(tmpMap1->value); + tmpMap1->value=(char*) malloc((f_status.st_size+1)*sizeof(char)); + if(tmpMap1->value==NULL){ + setMapInMaps(m,"lenv","message","Unable to allocate the memory required to read the produced file."); + return; + } + fread(tmpMap1->value,1,f_status.st_size,file); + tmpMap1->value[f_status.st_size]=0; + } + fclose(file); + if(content!=NULL) + addToMap(content,"size",rsize); +} + + +/** + * Write a file from value and length + * + * @param fname the file name + * @param val the value + * @param length the value length + */ +int writeFile(char* fname,char* val,int length){ + FILE* of=fopen(fname,"wb"); + if(of==NULL){ + return -1; + } + size_t ret=fwrite(val,sizeof(char),length,of); + if(retcontent,"mimeType")!=NULL && + getMap(inputs->content,"cache_file")==NULL){ + map* cMap=inputs->content; + if(getMap(cMap,"length")!=NULL){ + map* tmpLength=getMap(cMap,"length"); + int len=atoi(tmpLength->value); + int k=0; + for(k=0;kvalue : NULL, file_ext, 32); + char* val=(char*)malloc((strlen(tmpPath->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char)); + sprintf(val,"%s/Input_%s_%s_%d.%s",tmpPath->value,inputs->name,tmpSid->value,k,file_ext); + length=0; + if(cSize!=NULL){ + length=atoi(cSize->value); + }else + length=strlen(cValue->value); + writeFile(val,cValue->value,length); + setMapArray(cMap,"cache_file",k,val); + free(val); + val=(char*)malloc((strlen(tmpUrl->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char)); + sprintf(val,"%s/Input_%s_%s_%d.%s",tmpUrl->value,inputs->name,tmpSid->value,k,file_ext); + setMapArray(cMap,"cache_url",k,val); + setMapArray(cMap,"byValue",k,"true"); + free(val); + } + }else{ + int length=0; + map* cMimeType=getMap(cMap,"mimeType"); + map* cValue=getMap(cMap,"value"); + map* cSize=getMap(cMap,"size"); + char file_ext[32]; + getFileExtension(cMimeType != NULL ? cMimeType->value : NULL, file_ext, 32); + char *val=(char*)malloc((strlen(tmpPath->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char)); + sprintf(val,"%s/Input_%s_%s_%d.%s",tmpPath->value,inputs->name,tmpSid->value,0,file_ext); + if(cSize!=NULL){ + length=atoi(cSize->value); + }else + length=strlen(cValue->value); + writeFile(val,cValue->value,length); + addToMap(cMap,"cache_file",val); + free(val); + val=(char*)malloc((strlen(tmpUrl->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char)); + sprintf(val,"%s/Input_%s_%s_%d.%s",tmpUrl->value,inputs->name,tmpSid->value,0,file_ext); + addToMap(cMap,"cache_url",val); + addToMap(cMap,"byValue",val); + free(val); + } + } + inputs=inputs->next; + } +} + + +/** + * Base64 encoding of a char* + * + * @param input the value to encode + * @param length the value length + * @return the buffer containing the base64 value + * @warning make sure to free the returned value + */ +char *base64(const char *input, int length) +{ + BIO *bmem, *b64; + BUF_MEM *bptr; + + b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + bmem = BIO_new(BIO_s_mem()); + b64 = BIO_push(b64, bmem); + BIO_write(b64, input, length); + BIO_flush(b64); + BIO_get_mem_ptr(b64, &bptr); + + char *buff = (char *)malloc((bptr->length+1)*sizeof(char)); + memcpy(buff, bptr->data, bptr->length); + buff[bptr->length] = 0; + + BIO_free_all(b64); + + return buff; +} + +/** + * Base64 decoding of a char* + * + * @param input the value to decode + * @param length the value length + * @param red the value length + * @return the buffer containing the base64 value + * @warning make sure to free the returned value + */ +char *base64d(const char *input, int length,int* red) +{ + BIO *b64, *bmem; + + char *buffer = (char *)malloc(length); + if(buffer){ + memset(buffer, 0, length); + b64 = BIO_new(BIO_f_base64()); + if(b64){ + bmem = BIO_new_mem_buf((unsigned char*)input,length); + bmem = BIO_push(b64, bmem); + *red=BIO_read(bmem, buffer, length); + buffer[length-1]=0; + BIO_free_all(bmem); + } + } + return buffer; +} + +/** + * Read Base64 value and split it value by lines of 64 char. + * + * @param in the map containing the value to split + */ +void readBase64(map **in){ + char *res = NULL; + char *curs = (*in)->value; + int i = 0; + for (i = 0; i <= strlen ((*in)->value) / 64; + i++) + { + if (res == NULL) + res = + (char *) malloc (65 * sizeof (char)); + else + res = + (char *) realloc (res, + (((i + 1) * 65) + + i) * sizeof (char)); + int csize = i * 65; + strncpy (res + csize, curs, 64); + if (i == strlen ((*in)->value) / 64) + strcat (res, "\n\0"); + else + { + strncpy (res + (((i + 1) * 64) + i), + "\n\0", 2); + curs += 64; + } + } + free ((*in)->value); + (*in)->value = zStrdup (res); + free (res); +} + + +/** + * Add the default values defined in the zcfg to a maps. + * + * @param out the maps containing the inputs or outputs given in the initial + * HTTP request + * @param in the description of all inputs or outputs available for a service + * @param m the maps containing the settings of the main.cfg file + * @param type 0 for inputs and 1 for outputs + * @param err the map to store potential missing mandatory input parameters or + * wrong output names depending on the type. + * @return "" if no error was detected, the name of last input or output causing + * an error. + */ +char* addDefaultValues(maps** out,elements* in,maps* m,int type,map** err){ + map *res=*err; + elements* tmpInputs=in; + elements* tmpInputss=NULL; + maps* out1=*out; + maps* out1s=NULL; + char *result=NULL; + int nb=0; + int inb=0; + loopOnInputs: + if(type==1){ + while(out1!=NULL){ + if(getElements(in,out1->name)==NULL){ + if(res==NULL){ + res=createMap("value",out1->name); + }else{ + setMapArray(res,"value",nb,out1->name); + } + nb++; + result=out1->name; + } + inb++; + out1=out1->next; + } + if(res!=NULL){ + fflush(stderr); + *err=res; + return result; + } + if(out1==NULL && inb>=1) + out1=*out; + } + while(tmpInputs!=NULL){ + maps *tmpMaps=getMaps(out1,tmpInputs->name); + if(tmpMaps==NULL){ + maps* tmpMaps2=createMaps(tmpInputs->name); + if(type==0){ + map* tmpMapMinO=getMap(tmpInputs->content,"minOccurs"); + if(tmpMapMinO!=NULL){ + if(atoi(tmpMapMinO->value)>=1){ + freeMaps(&tmpMaps2); + free(tmpMaps2); + if(res==NULL){ + res=createMap("value",tmpInputs->name); + }else{ + setMapArray(res,"value",nb,tmpInputs->name); + } + nb++; + result=tmpInputs->name; + } + else{ + if(tmpMaps2->content==NULL) + tmpMaps2->content=createMap("minOccurs",tmpMapMinO->value); + else + addToMap(tmpMaps2->content,"minOccurs",tmpMapMinO->value); + } + } + if(res==NULL){ + map* tmpMaxO0=getMap(tmpInputs->content,"useMapserver"); + if(tmpMaxO0!=NULL){ + if(tmpMaps2->content==NULL) + tmpMaps2->content=createMap("useMapserver",tmpMaxO0->value); + else + addToMap(tmpMaps2->content,"useMapserver",tmpMaxO0->value); + } + map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs"); + if(tmpMaxO!=NULL){ + if(tmpMaps2->content==NULL) + tmpMaps2->content=createMap("maxOccurs",tmpMaxO->value); + else + addToMap(tmpMaps2->content,"maxOccurs",tmpMaxO->value); + } + map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes"); + if(tmpMaxMB!=NULL){ + if(tmpMaps2->content==NULL) + tmpMaps2->content=createMap("maximumMegabytes",tmpMaxMB->value); + else + addToMap(tmpMaps2->content,"maximumMegabytes",tmpMaxMB->value); + } + } + } + + if(res==NULL){ + iotype* tmpIoType=tmpInputs->defaults; + if(tmpIoType!=NULL){ + map* tmpm=tmpIoType->content; + while(tmpm!=NULL){ + if(tmpMaps2->content==NULL) + tmpMaps2->content=createMap(tmpm->name,tmpm->value); + else{ + addToMap(tmpMaps2->content,tmpm->name,tmpm->value); + } + tmpm=tmpm->next; + } + } + if(tmpMaps2->content==NULL){ + tmpMaps2->content=createMap("inRequest","false"); + dumpMaps(tmpMaps2); + } + else + addToMap(tmpMaps2->content,"inRequest","false"); + if(type==0){ + map *tmpMap=getMap(tmpMaps2->content,"value"); + if(tmpMap==NULL) + addToMap(tmpMaps2->content,"value","NULL"); + } + elements* tmpElements=getElements(in,tmpMaps2->name); + if(tmpElements!=NULL && tmpElements->child!=NULL){ + char *res=addDefaultValues(&tmpMaps2->child,tmpElements->child,m,type,err); + if(strlen(res)>0){ + return res; + } + } + } + + if(out1==NULL){ + *out=dupMaps(&tmpMaps2); + out1=*out; + } + else + addMapsToMaps(&out1,tmpMaps2); + freeMap(&tmpMaps2->content); + free(tmpMaps2->content); + tmpMaps2->content=NULL; + freeMaps(&tmpMaps2); + free(tmpMaps2); + tmpMaps2=NULL; + } + else /*toto*/{ + iotype* tmpIoType=NULL; + if(tmpMaps->content!=NULL){ + tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name, + tmpMaps->content); + if(type==0) { + /** + * In case of an Input maps, then add the minOccurs and maxOccurs to the + * content map. + */ + const char* keys[4]={ + "minOccurs", + "maxOccurs", + "maximumMegabytes", + "useMapserver" + }; + int i=0; + for(i=0;i<4;i++){ + map* tmpMap1=getMap(tmpInputs->content,keys[i]); + if(tmpMap1!=NULL){ + addToMap(tmpMaps->content,keys[i],tmpMap1->value); + } + } + /** + * Parsing BoundingBoxData, fill the following map and then add it to + * the content map of the Input maps: + * lowerCorner, upperCorner, srs and dimensions + * cf. parseBoundingBox + */ + if(tmpInputs->format!=NULL && strcasecmp(tmpInputs->format,"BoundingBoxData")==0){ + maps* tmpI=getMaps(*out,tmpInputs->name); + if(tmpI!=NULL){ + map* tmpV=getMap(tmpI->content,"value"); + if(tmpV!=NULL){ + char *tmpVS=zStrdup(tmpV->value); + map* tmp=parseBoundingBox(tmpVS); + free(tmpVS); + map* tmpC=tmp; + while(tmpC!=NULL){ + addToMap(tmpMaps->content,tmpC->name,tmpC->value); + tmpC=tmpC->next; + } + freeMap(&tmp); + free(tmp); + } + } + } + } + }else{ + if(tmpInputs!=NULL){ + tmpIoType=tmpInputs->defaults; + } + } + + if(tmpIoType!=NULL){ + map* tmpContent=tmpIoType->content; + map* cval=NULL; + int hasPassed=-1; + while(tmpContent!=NULL){ + if((cval=getMap(tmpMaps->content,tmpContent->name))==NULL){ +#ifdef DEBUG + fprintf(stderr,"addDefaultValues %s => %s\n",tmpContent->name,tmpContent->value); +#endif + if(tmpMaps->content==NULL) + tmpMaps->content=createMap(tmpContent->name,tmpContent->value); + else + addToMap(tmpMaps->content,tmpContent->name,tmpContent->value); + + if(hasPassed<0 && type==0 && getMap(tmpMaps->content,"isArray")!=NULL){ + map* length=getMap(tmpMaps->content,"length"); + int i; + char *tcn=zStrdup(tmpContent->name); + for(i=1;ivalue);i++){ +#ifdef DEBUG + dumpMap(tmpMaps->content); + fprintf(stderr,"addDefaultValues %s_%d => %s\n",tcn,i,tmpContent->value); +#endif + int len=strlen((char*) tcn); + char *tmp1=(char *)malloc((len+10)*sizeof(char)); + sprintf(tmp1,"%s_%d",tcn,i); +#ifdef DEBUG + fprintf(stderr,"addDefaultValues %s => %s\n",tmp1,tmpContent->value); +#endif + addToMap(tmpMaps->content,tmp1,tmpContent->value); + free(tmp1); + hasPassed=1; + } + free(tcn); + } + } + tmpContent=tmpContent->next; + } +#ifdef USE_MS + /** + * check for useMapServer presence + */ + if(tmpIoType!=NULL){ + map* tmpCheck=getMap(tmpIoType->content,"useMapserver"); + if(tmpCheck!=NULL && strncasecmp(tmpCheck->value,"true",4)==0){ + // Get the default value + addToMap(tmpMaps->content,"useMapserver","true"); + tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,NULL); + tmpCheck=getMap(tmpMaps->content,"mimeType"); + addToMap(tmpMaps->content,"requestedMimeType",tmpCheck->value); + map* cursor=tmpIoType->content; + while(cursor!=NULL){ + addToMap(tmpMaps->content,cursor->name,cursor->value); + cursor=cursor->next; + } + + cursor=tmpInputs->content; + while(cursor!=NULL){ + if(strcasecmp(cursor->name,"Title")==0 || + strcasecmp(cursor->name,"Abstract")==0) + addToMap(tmpMaps->content,cursor->name,cursor->value); + cursor=cursor->next; + } + } + } +#endif + } + if(tmpMaps->content==NULL) + tmpMaps->content=createMap("inRequest","true"); + else + addToMap(tmpMaps->content,"inRequest","true"); + elements* tmpElements=getElements(in,tmpMaps->name); + if(/*tmpMaps->child!=NULL && */tmpElements!=NULL && tmpElements->child!=NULL){ + char *res=addDefaultValues(&tmpMaps->child,tmpElements->child,m,type,err); + if(strlen(res)>0){ + return res; + } + } + } + if(tmpInputs->child!=NULL){ + tmpInputss=tmpInputs->next; + tmpInputs=tmpInputs->child; + if(tmpMaps!=NULL){ + out1=tmpMaps->child; + out1s=tmpMaps; + } + } + tmpInputs=tmpInputs->next; + } + if(tmpInputss!=NULL){ + out1=out1s; + tmpInputs=tmpInputss; + tmpInputss=NULL; + out1s=NULL; + goto loopOnInputs; + } + if(res!=NULL){ + *err=res; + return result; + } + return ""; +} + +/** + * Access the last error message returned by the OS when trying to dynamically + * load a shared library. + * + * @return the last error message + * @warning The character string returned from getLastErrorMessage resides + * in a static buffer. The application should not write to this + * buffer or attempt to free() it. + */ +char* getLastErrorMessage() { +#ifdef WIN32 + LPVOID lpMsgBuf; + DWORD errCode = GetLastError(); + static char msg[ERROR_MSG_MAX_LENGTH]; + size_t i; + + DWORD length = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + errCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + +#ifdef UNICODE + wcstombs_s( &i, msg, ERROR_MSG_MAX_LENGTH, + (wchar_t*) lpMsgBuf, _TRUNCATE ); +#else + strcpy_s( msg, ERROR_MSG_MAX_LENGTH, + (char *) lpMsgBuf ); +#endif + LocalFree(lpMsgBuf); + + return msg; +#else + return dlerror(); +#endif +} + +#include +#ifndef RELY_ON_DB +/** + * Read the Result file (.res). + * + * @param conf the maps containing the setting of the main.cfg file + * @param pid the service identifier (usid key from the [lenv] section) + */ +void readFinalRes(maps* conf,char* pid,map* statusInfo){ + map* r_inputs = getMapFromMaps (conf, "main", "tmpPath"); + char* fbkpid = + (char *) + malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char)); + sprintf (fbkpid, "%s/%s.res", r_inputs->value, pid); + struct stat file_status; + int istat = stat (fbkpid, &file_status); + if (istat == 0 && file_status.st_size > 0) + { + maps *res = (maps *) malloc (MAPS_SIZE); + res->content = NULL; + res->child = NULL; + res->next = NULL; + conf_read (fbkpid, res); + res->child=NULL; + map* status=getMapFromMaps(res,"status","status"); + addToMap(statusInfo,"Status",status->value); + freeMaps(&res); + free(res); + } + else{ + addToMap(statusInfo,"Status","Failed"); + addToMap(statusInfo,"NotFound",pid); + } + free(fbkpid); +} + +/** + * Check if a service is running. + * + * @param conf the maps containing the setting of the main.cfg file + * @param pid the unique service identifier (usid from the lenv section) + * @return 1 in case the service is still running, 0 otherwise + */ +int isRunning(maps* conf,char* pid){ + int res=0; + map* r_inputs = getMapFromMaps (conf, "main", "tmpPath"); + char* fbkpid = + (char *) + malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char)); + sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid); + FILE* f0 = fopen (fbkpid, "r"); + if(f0!=NULL){ + fclose(f0); + res=1; + } + free(fbkpid); + return res; +} +#else +#include "sqlapi.h" +#endif + +/** + * Run GetStatus requests. + * + * @param conf the maps containing the setting of the main.cfg file + * @param pid the service identifier (usid key from the [lenv] section) + * @param req the request (GetStatus / GetResult) + */ +void runGetStatus(maps* conf,char* pid,char* req){ + map* r_inputs = getMapFromMaps (conf, "main", "tmpPath"); + map* e_type = getMapFromMaps (conf, "main", "executionType"); + char *sid=getStatusId(conf,pid); + if(sid==NULL){ + if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0) + errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"), + "NoSuchJob", pid); + else{ + setMapInMaps(conf,"lenv","error","true"); + setMapInMaps(conf,"lenv","code","NoSuchJob"); + setMapInMaps(conf,"lenv","message",_("The JobID from the request does not match any of the Jobs running on this server")); + } + }else{ + map* statusInfo=createMap("JobID",pid); + if(isRunning(conf,pid)>0){ + if(strncasecmp(req,"GetResult",strlen(req))==0){ + if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0) + errorException (conf, _("The result for the requested JobID has not yet been generated. The service is currently running."), + "ResultNotReady", pid); + else{ + setMapInMaps(conf,"lenv","error","true"); + setMapInMaps(conf,"lenv","code","ResultNotReady"); + setMapInMaps(conf,"lenv","message",_("The result for the requested JobID has not yet been generated. The service is currently running.")); + } + return; + } + else{ + if(strncasecmp(req,"GetStatus",strlen(req))==0){ + addToMap(statusInfo,"Status","Running"); + setMapInMaps(conf,"lenv","status","Running"); + char* tmpStr=_getStatus(conf,pid); + if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){ + char *tmpStr1=zStrdup(tmpStr); + char *tmpStr0=zStrdup(strstr(tmpStr,"|")+1); + free(tmpStr); + tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0'; + addToMap(statusInfo,"PercentCompleted",tmpStr1); + addToMap(statusInfo,"Message",tmpStr0); + setMapInMaps(conf,"lenv","PercentCompleted",tmpStr1); + setMapInMaps(conf,"lenv","Message",tmpStr0); + free(tmpStr0); + free(tmpStr1); + } + } + } + } + else{ + if(strncasecmp(req,"GetResult",strlen(req))==0){ + char* result=_getStatusFile(conf,pid); + if(result!=NULL){ + char *encoding=getEncoding(conf); + printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding); + printf("%s",result); + fflush(stdout); + free(sid); + freeMap(&statusInfo); + free(statusInfo); + free(result); + return; + }else{ + errorException (conf, _("The result for the requested JobID has not yet been generated. The service ends but it still needs to produce the outputs."), + "ResultNotReady", pid); + freeMap(&statusInfo); + free(statusInfo); + return; + } + }else + if(strncasecmp(req,"GetStatus",strlen(req))==0){ + readFinalRes(conf,pid,statusInfo); + if(e_type==NULL || strncasecmp(e_type->value,"json",4)==0){ + map* pmStatus=getMap(statusInfo,"status"); + if(pmStatus!=NULL) + setMapInMaps(conf,"lenv","status",pmStatus->value); + } + char* tmpStr=_getStatus(conf,pid); + if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){ + char *tmpStr1=zStrdup(tmpStr); + char *tmpStr0=zStrdup(strstr(tmpStr,"|")+1); + free(tmpStr); + tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0'; + addToMap(statusInfo,"PercentCompleted",tmpStr1); + addToMap(statusInfo,"Message",tmpStr0); + setMapInMaps(conf,"lenv","PercentCompleted",tmpStr1); + setMapInMaps(conf,"lenv","Message",tmpStr0); + free(tmpStr0); + free(tmpStr1); + } + } + } + free(sid); + if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0) + printStatusInfo(conf,statusInfo,req); + else + setMapInMaps(conf,"lenv","error","false"); + freeMap(&statusInfo); + free(statusInfo); + } + return; +} + +/** + * Run Dismiss requests. + * + * @param conf the maps containing the setting of the main.cfg file + * @param pid the service identifier (usid key from the [lenv] section) + */ +void runDismiss(maps* conf,char* pid){ + map* r_inputs = getMapFromMaps (conf, "main", "tmpPath"); + map* e_type = getMapFromMaps (conf, "main", "executionType"); + char *sid=getStatusId(conf,pid); + if(sid==NULL){ + if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0) + errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"), + "NoSuchJob", pid); + else{ + setMapInMaps(conf,"lenv","error","true"); + setMapInMaps(conf,"lenv","code","NoSuchJob"); + setMapInMaps(conf,"lenv","message",_("The JobID from the request does not match any of the Jobs running on this server")); + } + return; + }else{ + // We should send the Dismiss request to the target host if it differs + char* fbkpid = + (char *) + malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char)); + sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid); + FILE* f0 = fopen (fbkpid, "r"); + if(f0!=NULL){ + long flen; + char *fcontent; + fseek (f0, 0, SEEK_END); + flen = ftell (f0); + fseek (f0, 0, SEEK_SET); + fcontent = (char *) malloc ((flen + 1) * sizeof (char)); + fread(fcontent,flen,1,f0); + fcontent[flen]=0; + fclose(f0); +#ifndef WIN32 + kill(atoi(fcontent),SIGKILL); +#else + HANDLE myZooProcess=OpenProcess(PROCESS_ALL_ACCESS,false,atoi(fcontent)); + TerminateProcess(myZooProcess,1); + CloseHandle(myZooProcess); +#endif + free(fcontent); + } + free(fbkpid); + struct dirent *dp; + DIR *dirp = opendir(r_inputs->value); + char fileName[1024]; + int hasFile=-1; + if(dirp!=NULL){ + while ((dp = readdir(dirp)) != NULL){ + if(strstr(dp->d_name,pid)!=0){ + sprintf(fileName,"%s/%s",r_inputs->value,dp->d_name); + if(zUnlink(fileName)!=0){ + if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0) + errorException (conf, + _("The job cannot be removed, a file cannot be removed"), + "NoApplicableCode", NULL); + else{ + setMapInMaps(conf,"lenv","error","true"); + setMapInMaps(conf,"lenv","code","NoApplicableCode"); + setMapInMaps(conf,"lenv","message",_("The job cannot be removed, a file cannot be removed")); + } + return; + } + + } + } + } +#ifdef RELY_ON_DB + removeService(conf,pid); +#endif + if(e_type==NULL || strncasecmp(e_type->value,"json",4)!=0){ + map* statusInfo=createMap("JobID",pid); + addToMap(statusInfo,"Status","Dismissed"); + printStatusInfo(conf,statusInfo,"Dismiss"); + free(statusInfo); + }else{ + setMapInMaps(conf,"lenv","error","false"); + } + } + return; +} + +extern int getServiceFromFile (maps *, const char *, service **); + +/** + * Parse the service file using getServiceFromFile or use getServiceFromYAML + * if YAML support was activated. + * + * @param conf the conf maps containing the main.cfg settings + * @param file the file name to parse + * @param service the service to update witht the file content + * @param name the service name + * @return true if the file can be parsed or false + * @see getServiceFromFile, getServiceFromYAML + */ +int readServiceFile (maps * conf, char *file, service ** service, char *name){ + int t = getServiceFromFile (conf, file, service); +#ifdef YAML + if (t < 0){ + t = getServiceFromYAML (conf, file, service, name); + } +#endif + return t; +} + +/** + * Create the profile registry. + * + * The profile registry is optional (created only if the registry key is + * available in the [main] section of the main.cfg file) and can be used to + * store the profiles hierarchy. The registry is a directory which should + * contain the following sub-directories: + * * concept: direcotry containing .html files describing concept + * * generic: directory containing .zcfg files for wps:GenericProcess + * * implementation: directory containing .zcfg files for wps:Process + * + * @param m the conf maps containing the main.cfg settings + * @param r the registry to update + * @param reg_dir the resgitry + * @return 0 if the resgitry is null or was correctly updated, -1 on failure + */ +int createRegistry (maps* m,registry ** r, char *reg_dir) +{ + char registryKeys[3][15]={ + "concept", + "generic", + "implementation" + }; + int scount = 0,i=0; + if (reg_dir == NULL) + return 0; + for(i=0;i<3;i++){ + char * tmpName = + (char *) malloc ((strlen (reg_dir) + strlen (registryKeys[i]) + 2) * + sizeof (char)); + sprintf (tmpName, "%s/%s", reg_dir, registryKeys[i]); + + DIR *dirp1 = opendir (tmpName); + if(dirp1==NULL){ + setMapInMaps(m,"lenv","message",_("Unable to open the registry directory.")); + setMapInMaps(m,"lenv","type","InternalError"); + return -1; + } + struct dirent *dp1; + while ((dp1 = readdir (dirp1)) != NULL){ + char* extn = strstr(dp1->d_name, ".zcfg"); + if(dp1->d_name[0] != '.' && extn != NULL && strlen(extn) == 5) + { + int t; + char *tmps1= + (char *) malloc ((strlen (tmpName) + strlen (dp1->d_name) + 2) * + sizeof (char)); + sprintf (tmps1, "%s/%s", tmpName, dp1->d_name); + char *tmpsn = zStrdup (dp1->d_name); + tmpsn[strlen (tmpsn) - 5] = 0; + service* s1 = (service *) malloc (SERVICE_SIZE); + if (s1 == NULL) + { + setMapInMaps(m,"lenv","message",_("Unable to allocate memory.")); + setMapInMaps(m,"lenv","type","InternalError"); + return -2; + } + t = readServiceFile (m, tmps1, &s1, tmpsn); + free (tmpsn); + if (t < 0) + { + map *tmp00 = getMapFromMaps (m, "lenv", "message"); + char tmp01[1024]; + if (tmp00 != NULL) + sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"), + dp1->d_name, tmp00->value); + else + sprintf (tmp01, _("Unable to parse the ZCFG file: %s."), + dp1->d_name); + setMapInMaps(m,"lenv","message",tmp01); + setMapInMaps(m,"lenv","type","InternalError"); + return -1; + } + if(strncasecmp(registryKeys[i],"implementation",14)==0){ + inheritance(*r,&s1); + } + addServiceToRegistry(r,registryKeys[i],s1); + freeService (&s1); + free (s1); + scount++; + } + } + (void) closedir (dirp1); + } + return 0; +} + +/** + * Create a string containing the basic error message. + * + * @param pmConf the main configuration maps pointer + * @return a new char* containing the error message (ressource should be freed) + */ +char* produceErrorMessage(maps* pmConf){ + char *pacTmp; + map *pmLenv=getMapFromMaps(pmConf,"lenv","message"); + if(pmLenv!=NULL){ + pacTmp=(char*)malloc((strlen(pmLenv->value)+strlen(_("Unable to run the Service. The message returned back by the Service was the following: "))+1)*sizeof(char)); + sprintf(pacTmp,_("Unable to run the Service. The message returned back by the Service was the following: %s"),pmLenv->value); + } + else{ + pacTmp=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char)); + sprintf(pacTmp,"%s",_("Unable to run the Service. No more information was returned back by the Service.")); + } + return pacTmp; +} + +#ifdef WIN32 +/** + * Create a KVP request for executing background task. + * TODO: use the XML request in case of input POST request. + * + * @param m the maps containing the parameters from the main.cfg file + * @param length the total length of the KVP parameters + * @param type + */ +char* getMapsAsKVP(maps* m,int length,int type){ + char *dataInputsKVP=(char*) malloc(length*sizeof(char)); + char *dataInputsKVPi=NULL; + maps* curs=m; + int i=0; + while(curs!=NULL){ + map *inRequest=getMap(curs->content,"inRequest"); + map *hasLength=getMap(curs->content,"length"); + if((inRequest!=NULL && strncasecmp(inRequest->value,"true",4)==0) || + inRequest==NULL){ + if(i==0) + if(type==0){ + sprintf(dataInputsKVP,"%s=",curs->name); + if(hasLength!=NULL){ + dataInputsKVPi=(char*)malloc((strlen(curs->name)+2)*sizeof(char)); + sprintf(dataInputsKVPi,"%s=",curs->name); + } + } + else + sprintf(dataInputsKVP,"%s",curs->name); + else{ + char *temp=zStrdup(dataInputsKVP); + if(type==0) + sprintf(dataInputsKVP,"%s;%s=",temp,curs->name); + else + sprintf(dataInputsKVP,"%s;%s",temp,curs->name); + } + map* icurs=curs->content; + if(type==0){ + char *temp=zStrdup(dataInputsKVP); + if(getMap(curs->content,"xlink:href")!=NULL) + sprintf(dataInputsKVP,"%sReference",temp); + else{ + if(hasLength!=NULL){ + int j; + for(j=0;jvalue);j++){ + map* tmp0=getMapArray(curs->content,"value",j); + if(j==0) + free(temp); + temp=zStrdup(dataInputsKVP); + if(j==0) + sprintf(dataInputsKVP,"%s%s",temp,tmp0->value); + else + sprintf(dataInputsKVP,"%s;%s%s",temp,dataInputsKVPi,tmp0->value); + } + } + else + sprintf(dataInputsKVP,"%s%s",temp,icurs->value); + } + free(temp); + } + while(icurs!=NULL){ + if(strncasecmp(icurs->name,"value",5)!=0 && + strncasecmp(icurs->name,"mimeType_",9)!=0 && + strncasecmp(icurs->name,"dataType_",9)!=0 && + strncasecmp(icurs->name,"size",4)!=0 && + strncasecmp(icurs->name,"length",4)!=0 && + strncasecmp(icurs->name,"isArray",7)!=0 && + strcasecmp(icurs->name,"Reference")!=0 && + strcasecmp(icurs->name,"minOccurs")!=0 && + strcasecmp(icurs->name,"maxOccurs")!=0 && + strncasecmp(icurs->name,"fmimeType",9)!=0 && + strcasecmp(icurs->name,"inRequest")!=0){ + char *itemp=zStrdup(dataInputsKVP); + if(strcasecmp(icurs->name,"xlink:href")!=0) + sprintf(dataInputsKVP,"%s@%s=%s",itemp,icurs->name,icurs->value); + else + sprintf(dataInputsKVP,"%s@%s=%s",itemp,icurs->name,url_encode(icurs->value)); + free(itemp); + } + icurs=icurs->next; + } + } + curs=curs->next; + i++; + } + return dataInputsKVP; +} +#endif diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/server_internal.h b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/server_internal.h new file mode 100644 index 00000000..d6a866c4 --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/server_internal.h @@ -0,0 +1,83 @@ +/* + * Author : Gérald Fenoy + * + * Copyright 2008-2015 GeoLabs SARL. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef WIN32 +#pragma comment(lib, "rpcrt4.lib") +#endif + +#ifndef IMPORTSERVICE +#define IMPORTSERVICE "include" // default name of [include] block in main.cfg + +#include "service.h" +#include +#include +#include +#include +#include +#include + +extern int conf_read(const char*,maps*); + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + char *get_uuid(); + char *base64(const char*,int); + char *base64d(const char*,int,int*); + void readBase64(map **); + char *url_decode(char *); + int getVersionId(const char*); + void readGeneratedFile(maps*,map*,char*); + int getServiceFromYAML(maps*,char*,service**,char *name); + char* addDefaultValues(maps**,elements*,maps*,int,map**); + char* getEncoding(maps*); + void parseIdentifier(maps*,char*,char*,char*); + void dumpMapsValuesToFiles(maps**,maps**); + void runDismiss(maps*,char*); + int isRunning(maps*,char*); + void runGetStatus(maps*,char*,char*); + void readFinalRes(maps*,char*,map*); + + int isValidLang(maps*,const char*); + + char* getLastErrorMessage(); + int readServiceFile (maps *, char *, service **, char *); + int createRegistry (maps*,registry **,char *); + char* produceErrorMessage(maps*); + + int zoo_path_compare(char* path1, char* path2); + +#ifdef WIN32 + char* getMapsAsKVP(maps*,int,int); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service.c b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service.c new file mode 100644 index 00000000..e1c8478b --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service.c @@ -0,0 +1,2049 @@ +/* + * Author : Gérald FENOY + * + * Copyright (c) 2015-2019 GeoLabs SARL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "service.h" + +// knut: time utilities required for new log function (logMessage) +#include +#include +#ifdef WIN32 +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1800 +#include +/** + * snprintf for Visual Studio compiler. + * + * See https://dxr.mozilla.org/mozilla-central/source/media/mtransport/third_party/nrappkit/src/util/util.c + */ +int snprintf(char *pcBuffer, size_t n, const char *pccFormat, ...) +{ + va_list argp; + int ret; + va_start(argp, pccFormat); + ret = _vscprintf(pccFormat, argp); + vsnprintf_s(pcBuffer, n, _TRUNCATE, pccFormat, argp); + va_end(argp); + return ret; +} +#endif + +/** + * Dump a map on stderr + * + * @param pmMap the map to dump + */ +void _dumpMap(map* pmMap){ + if(pmMap!=NULL){ + fprintf(stderr,"%s: %s\n",pmMap->name,pmMap->value); + fflush(stderr); + }else{ + fprintf(stderr,"NULL\n"); + fflush(stderr); + } +} + +/** + * Dump a map on stderr, see _dumpMap() + * + * @param pmMap the map to dump + */ +void dumpMap(map* pmMap){ + map* pmTmp=pmMap; + while(pmTmp!=NULL){ + _dumpMap(pmTmp); + pmTmp=pmTmp->next; + } +} + +/** + * Dump a map to a file + * + * @param pmMap the map to dump to file + * @param pfFile the file pointer to store the map + */ +void dumpMapToFile(map* pmMap,FILE* pfFile){ + map* pmTmp=pmMap; + while(pmTmp!=NULL){ + fprintf(pfFile,"%s = %s\n",pmTmp->name,pmTmp->value); + pmTmp=pmTmp->next; + } +} + +/** + * Dump a maps on stderr, see dumpMap(). + * + * @param pmMap the map to dump + */ +void dumpMaps(maps* pmMap){ + maps* pmTmp=pmMap; + while(pmTmp!=NULL){ + fprintf(stderr,"MAP => [%s] \n",pmTmp->name); + fprintf(stderr," * CONTENT [%s] \n",pmTmp->name); + dumpMap(pmTmp->content); + if(pmTmp->child!=NULL){ + fprintf(stderr," * CHILD [%s] \n",pmTmp->name); + dumpMaps(pmTmp->child); + fprintf(stderr," * /CHILD [%s] \n",pmTmp->name); + } + pmTmp=pmTmp->next; + } +} + +/** + * Dump a maps to a file, see dumpMapToFile(). + * + * @param pmsMaps the map to dump + * @param psFile the the file pointer to store the map + * @param iLimit the number of maps to print (0 for no limit) + */ +void _dumpMapsToFile(maps* pmsMaps,FILE* psFile,int iLimit){ + maps* tmp=pmsMaps; + int cnt=0; + while(tmp!=NULL){ + fprintf(psFile,"[%s]\n",tmp->name); + if(tmp->child!=NULL){ + _dumpMapsToFile(tmp->child,psFile,iLimit); + }else + dumpMapToFile(tmp->content,psFile); + fflush(psFile); + tmp=tmp->next; + cnt++; + if(iLimit>=0 && cnt==iLimit) + tmp=NULL; + } + fflush(psFile); +} + +/** + * Dump a maps to a file, see _dumpMapsToFile(). + * + * @param pmsMaps the map to dump + * @param pcaFilePath the the file pointer to store the map + * @param iLimit the number of maps to print (0 for no limit) + */ +void dumpMapsToFile(maps* pmsMaps,char* pcaFilePath,int iLimit){ + FILE* psFile=fopen(pcaFilePath,"w+"); + _dumpMapsToFile(pmsMaps,psFile,iLimit); + fflush(psFile); + fclose(psFile); +} + +/** + * Create a new iotype* + * + * @return a pointer to the allocated iotype + */ +iotype* createIoType(){ + iotype* pioIO=(iotype*)malloc(IOTYPE_SIZE); + pioIO->content=NULL; + pioIO->next=NULL; + return pioIO; +} + +/** + * Create a new map + * + * @param pccName the key to add to the map + * @param pccValue the corresponding value to add to the map + * @return a pointer to the allocated map + */ +map* createMap(const char* pccName,const char* pccValue){ + map* pmTtmp=(map *)malloc(MAP_SIZE); + pmTtmp->name=zStrdup(pccName); + pmTtmp->value=zStrdup(pccValue); + pmTtmp->next=NULL; + return pmTtmp; +} + +/** + * Create a new maps with the given name + * + * @param pccName of the maps + * @return the allocated map + */ +maps* createMaps(const char* pccName){ + maps* pmTmp = (maps *) malloc (MAPS_SIZE); + pmTmp->name = zStrdup (pccName); + pmTmp->content = NULL; + pmTmp->child = NULL; + pmTmp->next = NULL; + return pmTmp; +} + +/** + * Count number of map in a map + * + * @param pmMap the map to count + * @return number of map in a map + */ +int count(map* pmMap){ + map* pmTmp=pmMap; + int c=0; + while(pmTmp!=NULL){ + c++; + pmTmp=pmTmp->next; + } + return c; +} + +/** + * Count number of maps in a maps + * + * @param pmsMap the maps to count + * @return number of maps in a maps + */ +int countMaps(maps* pmsMap){ + maps* pmsTmp=pmsMap; + int c=0; + while(pmsTmp!=NULL){ + c++; + pmsTmp=pmsTmp->next; + } + return c; +} + +/** + * Count number of a specific map in a map + * + * @param pmMap the map to count + * @return number of map in a map + */ +int countMapName(map* pmMap,const char* value){ + map* pmTmp=pmMap; + int c=0; + while(pmTmp!=NULL){ + if(strncasecmp(pmTmp->name,value,strlen(value))==0) + c++; + pmTmp=pmTmp->next; + } + return c; +} + +/** + * Count number of a specific map value in a map + * + * @param pmMap the map to count + * @return number of map in a map + */ +int countMapNameValue(map* pmMap,const char* value){ + map* pmTmp=pmMap; + int c=0; + map* tmpValues=NULL; + while(pmTmp!=NULL){ + if(strncasecmp(pmTmp->name,value,strlen(value))==0){ + if(tmpValues==NULL){ + tmpValues=createMap(pmTmp->value,""); + c++; + } + else{ + if(countMapName(tmpValues,pmTmp->value)==0) + c++; + } + } + pmTmp=pmTmp->next; + } + return c; +} + + +/** + * Count number of maps in a maps + * + * @param pmMap the maps to count + * @return number of maps in a maps + */ +int maps_length(maps* pmMap){ + maps* pmTmp=pmMap; + int c=0; + while(pmTmp!=NULL){ + c++; + pmTmp=pmTmp->next; + } + return c; +} + +/** + * Verify if a key exist in a map + * + * @param pmMap the map to search for the key + * @param pccKey the key to search in the map + * @return true if the key wwas found, false in other case + */ +bool hasKey(map* pmMap,const char *pccKey){ + map* pmTmp=pmMap; + while(pmTmp!=NULL){ + if(strcasecmp(pmTmp->name,pccKey)==0) + return true; + pmTmp=pmTmp->next; + } +#ifdef DEBUG_MAP + fprintf(stderr,"NOT FOUND \n"); +#endif + return false; +} + +/** + * Access a specific maps + * + * @param pmMap the maps to search for the key + * @param pccKey the key to search in the maps + * @return a pointer on the maps found or NULL if not found + */ +maps* getMaps(maps* pmsMaps,const char *pccKey){ + maps* pmTmp=pmsMaps; + while(pmTmp!=NULL){ + if(strcasecmp(pmTmp->name,pccKey)==0){ + return pmTmp; + } + pmTmp=pmTmp->next; + } + return NULL; +} + +/** + * Access a specific map + * + * @param pmMap the map to search for the key + * @param pccKey the key to search in the map + * @return a pointer on the map found or NULL if not found + */ +map* getMap(map* pmMap,const char *pccKey){ + map* pmTmp=pmMap; + while(pmTmp!=NULL){ + if(strcasecmp(pmTmp->name,pccKey)==0){ + return pmTmp; + } + pmTmp=pmTmp->next; + } + return NULL; +} + + +/** + * Access the last map + * + * @param pmMap the map to search for the lastest map + * @return a pointer on the lastest map found or NULL if not found + */ +map* getLastMap(map* pmMap){ + map* pmTmp=pmMap; + while(pmTmp!=NULL){ + if(pmTmp->next==NULL){ + return pmTmp; + } + pmTmp=pmTmp->next; + } + return NULL; +} + +/** + * Access a specific map from a maps + * + * @param pmMap the maps to search for the key + * @param pccKey the key to search in the maps + * @param pccSubkey the key to search in the map (found for the key, if any) + * @return a pointer on the map found or NULL if not found + */ +map* getMapFromMaps(maps* pmMap,const char* pccKey,const char* pccSubkey){ + maps* pmTmp=getMaps(pmMap,pccKey); + if(pmTmp!=NULL){ + map* pmTmp1=getMap(pmTmp->content,pccSubkey); + return pmTmp1; + } + else return NULL; +} + +/** + * Free allocated memory of a map. + * Require to call free on mo after calling this function. + * + * @param pmMap the map to free + */ +void freeMap(map** pmMap){ + map* pmCursor=*pmMap; + if(pmCursor!=NULL){ +#ifdef DEBUG + fprintf(stderr,"freeMap\n"); +#endif + if(pmCursor->name!=NULL) + free(pmCursor->name); + if(pmCursor->value!=NULL) + free(pmCursor->value); + if(pmCursor->next!=NULL){ + freeMap(&pmCursor->next); + if(pmCursor->next!=NULL) + free(pmCursor->next); + } + } +} + +/** + * Free allocated memory of a maps. + * Require to call free on mo after calling this function. + * + * @param pmMap the maps to free + */ +void freeMaps(maps** pmMap){ + maps* pmCursor=*pmMap; + if(pmCursor && pmCursor!=NULL){ +#ifdef DEBUG + fprintf(stderr,"freeMaps\n"); +#endif + free(pmCursor->name); + if(pmCursor->content!=NULL){ + freeMap(&pmCursor->content); + free(pmCursor->content); + } + if(pmCursor->child!=NULL){ + freeMaps(&pmCursor->child); + free(pmCursor->child); + } + if(pmCursor->next!=NULL){ + freeMaps(&pmCursor->next); + free(pmCursor->next); + } + } +} + +/** + * Verify if an elements contains a name equal to the given key. + * + * @param peElem the elements to search for the key + * @param pccKey the elements name to search + * @return true if the elements contains the name, false in other cases. + */ +bool hasElement(elements* peElem,const char* pccKey){ + elements* peTmp=peElem; + while(peTmp!=NULL){ + if(strcasecmp(pccKey,peTmp->name)==0) + return true; + peTmp=peTmp->next; + } + return false; +} + +/** + * Access a specific elements named key. + * + * @param peElem the elements to search + * @param pccKey the elements name to search + * @return a pointer to the specific element if found, NULL in other case. + */ +elements* getElements(elements* peElem,const char *pccKey){ + elements* peTmp=peElem; + while(peTmp!=NULL){ + if(strcasecmp(peTmp->name,pccKey)==0) + return peTmp; + peTmp=peTmp->next; + } + return NULL; +} + +/** + * Free allocated memory of an iotype. + * Require to call free on i after calling this function. + * + * @param piotIO the iotype to free + */ +void freeIOType(iotype** piotIO){ + iotype* piotCursor=*piotIO; + if(piotCursor!=NULL){ + if(piotCursor->next!=NULL){ + freeIOType(&piotCursor->next); + free(piotCursor->next); + } + freeMap(&piotCursor->content); + free(piotCursor->content); + } +} + +/** + * Free allocated memory of an elements. + * Require to call free on e after calling this function. + * + * @param peElem the iotype to free + */ +void freeElements(elements** peElem){ + elements* peTmp=*peElem; + if(peTmp!=NULL){ + if(peTmp->name!=NULL) + free(peTmp->name); + freeMap(&peTmp->content); + if(peTmp->content!=NULL) + free(peTmp->content); + freeMap(&peTmp->metadata); + if(peTmp->metadata!=NULL) + free(peTmp->metadata); + freeMap(&peTmp->additional_parameters); + if(peTmp->additional_parameters!=NULL) + free(peTmp->additional_parameters); + if(peTmp->format!=NULL) + free(peTmp->format); + freeElements(&peTmp->child); + if(peTmp->child!=NULL){ + free(peTmp->child); + } + if(peTmp->defaults!=NULL){ + freeIOType(&peTmp->defaults); + free(peTmp->defaults); + } + if(peTmp->supported!=NULL){ + freeIOType(&peTmp->supported); + free(peTmp->supported); + } + if(peTmp->next!=NULL){ + freeElements(&peTmp->next); + free(peTmp->next); + } + } +} + + +/** + * Allocate memory for a service. + * Require to call free after calling this function. + * + * @return the service + */ +service* createService(){ + service *psService = (service *) malloc (SERVICE_SIZE); + psService->name=NULL; + psService->content=NULL; + psService->metadata=NULL; + psService->additional_parameters=NULL; + psService->inputs=NULL; + psService->outputs=NULL; + return psService; +} + +/** + * Free allocated memory of a service. + * Require to be invoked for every createService call. + * + * @param psService the service to free + */ +void freeService(service** psService){ + service* psTmp=*psService; + if(psTmp!=NULL){ + if(psTmp->name!=NULL) + free(psTmp->name); + freeMap(&psTmp->content); + if(psTmp->content!=NULL) + free(psTmp->content); + freeMap(&psTmp->metadata); + if(psTmp->metadata!=NULL) + free(psTmp->metadata); + freeMap(&psTmp->additional_parameters); + if(psTmp->additional_parameters!=NULL) + free(psTmp->additional_parameters); + freeElements(&psTmp->inputs); + if(psTmp->inputs!=NULL) + free(psTmp->inputs); + freeElements(&psTmp->outputs); + if(psTmp->outputs!=NULL) + free(psTmp->outputs); + } +} + +/** + * Add key value pair to an existing map. + * + * @param pMap the map to add the KVP + * @param pccName the key to add + * @param pccValue the corresponding value to add + */ +void addToMap(map* pMap,const char* pccName,const char* pccValue){ + if (pMap != NULL) { // knut: add NULL-pointer check + if (hasKey(pMap, pccName) == false) { + map* pmCursor = pMap; + while (pmCursor->next != NULL) { + pmCursor = pmCursor->next; + } + pmCursor->next = createMap(pccName, pccValue); + } + else { + map *tmp = getMap(pMap, pccName); + if (tmp->value != NULL){ + free(tmp->value); + } + tmp->value = zStrdup(pccValue); + } + } +} + +/** + * Add key value pair to an existing map or append the value. + * + * @param pMap the map to add the KVP + * @param pccName the key to add + * @param pccValue the corresponding value to add + */ +void addToMapA(map* pMap,const char* pccName,const char* pccValue){ + if (pMap != NULL) { // knut: add NULL-pointer check + if (hasKey(pMap, pccName) == false) { + map* pmCursor = pMap; + while (pmCursor->next != NULL) { + pmCursor = pmCursor->next; + } + pmCursor->next = createMap(pccName, pccValue); + } + else { + map *tmp = getMap(pMap, pccName); + if (tmp->value != NULL){ + char* pcaTmp = zStrdup(tmp->value); + free(tmp->value); + if(strcmp(pcaTmp,pccValue)!=0){ + char *pcaRes=(char*) malloc((strlen(pcaTmp)+strlen(pccValue)+2)*sizeof(char)); + sprintf(pcaRes,"%s,%s",pcaTmp,pccValue); + tmp->value = zStrdup(pcaRes); + free(pcaRes); + }else + tmp->value = zStrdup(pccValue); + free(pcaTmp); + }else + tmp->value = zStrdup(pccValue); + } + } +} + +/** + * Add a key and an integer value to an existing map. + * + * @param pMap the map to add the KVP + * @param pccName the key to add + * @param iValue the corresponding value to add + */ +void addIntToMap(map* pMap,const char* pccName,const int iValue){ + char acValue[10]; + sprintf(acValue,"%d",iValue); + if(hasKey(pMap,pccName)==false){ + map* pmCursor=pMap; + while(pmCursor->next!=NULL){ + pmCursor=pmCursor->next; + } + pmCursor->next=createMap(pccName,acValue); + } + else{ + map *pmTmp=getMap(pMap,pccName); + if(pmTmp->value!=NULL) + free(pmTmp->value); + pmTmp->value=zStrdup(acValue); + } +} + +/** + * Add a key and a binary value to an existing map. + * + * @param pMap the map to add the KVP + * @param pccName the key to add + * @param pccValue the corresponding value to add + * @param iSize the size of the given value + * @return a pointer to the updated map m + */ +map* addToMapWithSize(map* pMap,const char* pccName,const char* pccValue,int iSize){ + char acIn[128]; + char acName[10]="size"; + map *pmTmp; + if(hasKey(pMap,pccName)==false){ + map* _cursor=pMap; + if(_cursor!=NULL){ + addToMap(pMap,pccName,""); + }else{ + pMap=createMap(pccName,""); + } + } + if(strlen(pccName)>5) + sprintf(acName,"size_%s",pccName+6); + pmTmp=getMap(pMap,pccName); + if(pmTmp->value!=NULL) + free(pmTmp->value); + pmTmp->value=(char*)malloc((iSize+1)*sizeof(char)); + if(pccValue!=NULL) + memmove(pmTmp->value,pccValue,iSize*sizeof(char)); + pmTmp->value[iSize]=0; + sprintf(acIn,"%d",iSize); + addToMap(pMap,acName,acIn); + return pMap; +} + +/** + * Add a map at the end of another map. + * + * @param pmMapOut the map to add pmMapIn to + * @param pmMapIn the map to add to pmMapOut + */ +void addMapToMap(map** pmMapOut,map* pmMapIn){ + map* pmTmp=pmMapIn; + map* pmCursor=*pmMapOut; + while(pmTmp!=NULL){ + if(pmCursor==NULL){ + *pmMapOut=createMap(pmTmp->name,pmTmp->value); + (*pmMapOut)->next=NULL; + } + else{ + map* pmTmp1=getMap(*pmMapOut,pmTmp->name); + if(pmTmp1==NULL){ + while(pmCursor->next!=NULL) + pmCursor=pmCursor->next; + pmCursor->next=createMap(pmTmp->name,pmTmp->value); + } + else{ + addToMap(*pmMapOut,pmTmp->name,pmTmp->value); + } + } + pmCursor=*pmMapOut; + pmTmp=pmTmp->next; + } +} + +/** + * Add a map to iotype. + * + * @param piotType the iotype to add the map + * @param pmMap the map to add to io + */ +void addMapToIoType(iotype** piotType,map* pmMap){ + iotype* piotTmp=*piotType; + while(piotTmp->next!=NULL){ + piotTmp=piotTmp->next; + } + piotTmp->next=(iotype*)malloc(IOTYPE_SIZE); + piotTmp->next->content=NULL; + addMapToMap(&piotTmp->next->content,pmMap); + piotTmp->next->next=NULL; +} + +/** + * Access a specific map or set its value. + * + * @param ppmMap the map to search for the key + * @param pccKey the key to search/add in the map + * @param pccValue the value to add if the key does not exist + * @return a pointer on the map found or NULL if not found + */ +map* getMapOrFill(map** ppmMap,const char *pccKey,const char* pccValue){ + map* pmTmp=*ppmMap; + map* pmTmp1=getMap(pmTmp,pccKey); + if(pmTmp1==NULL){ + if(pmTmp!=NULL){ + addToMap((*ppmMap),pccKey,pccValue); + } + else + (*ppmMap)=createMap(pccKey,pccValue); + pmTmp1=getMap(*ppmMap,pccKey); + } + return pmTmp1; +} + +/** + * Verify if a map is contained in another map. + * + * @param pmMap the map to search for i + * @param pmSearch the map to search in m + * @return true if i was found in m, false in other case + */ +bool contains(map* pmMap,map* pmSearch){ + while(pmSearch!=NULL){ + if(strcasecmp(pmSearch->name,"value")!=0 && + strcasecmp(pmSearch->name,"xlink:href")!=0 && + strcasecmp(pmSearch->name,"useMapServer")!=0 && + strcasecmp(pmSearch->name,"asReference")!=0){ + map *tmp; + if(hasKey(pmMap,pmSearch->name) && + (tmp=getMap(pmMap,pmSearch->name))!=NULL && + strcasecmp(pmSearch->value,tmp->value)!=0) + return false; + } + pmSearch=pmSearch->next; + } + return true; +} + +/** + * Access a specific iotype from an elements. + * + * @param peElem the elements to search for the name + * @param pcName the name to search in the elements e + * @param pcValues the map to verify it was contained in the defaults or + * supported content of the elements e + * @return a pointer on the iotype found or NULL if not found + */ +iotype* getIoTypeFromElement(elements* peElem,char *pcName, map* pcValues){ + elements* peCursor=peElem; + if(pcValues!=NULL){ + while(peCursor!=NULL){ + if(strcasecmp(peCursor->name,pcName)==0 && (peCursor->defaults!=NULL || peCursor->supported!=NULL)){ + if(contains(peCursor->defaults->content,pcValues)==true) + return peCursor->defaults; + else{ + iotype* tmp=peCursor->supported; + while(tmp!=NULL){ + if(contains(tmp->content,pcValues)==true) + return tmp; + tmp=tmp->next; + } + } + } + peCursor=peCursor->next; + } + }else{ + while(peCursor!=NULL){ + if(strcasecmp(peCursor->name,pcName)==0 && peCursor->defaults!=NULL){ + return peCursor->defaults; + } + peCursor=peCursor->next; + } + } + return NULL; +} + +/** + * Load binary values from a map (in) and add them to another map (out) + * + * @param pmOut the map to add binaries values + * @param pmIn the map containing the binary values to add ti out + * @param iPos index of the binary in an array (in case of "MapArray") + */ +void loadMapBinary(map** ppmOut,map* pmIn,int iPos){ + map* pmSize=getMap(pmIn,"size"); + map *pmOut=*ppmOut; + map *pmTmpVin,*pmTmpVout; + if(pmSize!=NULL && iPos>0){ + char tmp[11]; + sprintf(tmp,"size_%d",iPos); + pmSize=getMap(pmIn,tmp); + sprintf(tmp,"value_%d",iPos); + pmTmpVin=getMap(pmIn,tmp); + pmTmpVout=getMap(pmOut,tmp); + free(pmTmpVout->value); + pmTmpVout->value=(char*)malloc((atoi(pmSize->value)+1)*sizeof(char)); + memmove(pmTmpVout->value,pmTmpVin->value,atoi(pmSize->value)*sizeof(char)); + pmTmpVout->value[atoi(pmSize->value)]=0; + }else{ + if(pmSize!=NULL){ + pmTmpVin=getMap(pmIn,"value"); + pmTmpVout=getMap(pmOut,"value"); + free(pmTmpVout->value); + pmTmpVout->value=(char*)malloc((atoi(pmSize->value)+1)*sizeof(char)); + memmove(pmTmpVout->value,pmTmpVin->value,atoi(pmSize->value)*sizeof(char)); + pmTmpVout->value[atoi(pmSize->value)]=0; + } + } +} + +/** + * Load binary values from a map (in) and add them to another map (out). + * This function will take care of MapArray. + * @see loadMapBinary + * + * @param ppmOut the map to add binaries values + * @param pmIn the map containing the binary values to add ti out + */ +void loadMapBinaries(map** ppmOut,map* pmIn){ + map* pmSize=getMap(pmIn,"size"); + map* pmLength=getMap(pmIn,"length"); + map* pmToload=getMap(pmIn,"to_load"); + if(pmToload!=NULL && strcasecmp(pmToload->value,"false")==0){ +#ifdef DEBUG + fprintf(stderr,"NO LOAD %s %d \n",__FILE__,__LINE__); +#endif + return ; + } + if(pmLength!=NULL){ + int len=atoi(pmLength->value); + int i=0; + for(i=0;icontent; + maps* pmsChild=pmsCursor->child; + pmRes=createMaps(pmsCursor->name); + if(pmContent!=NULL){ + addMapToMap(&pmRes->content,pmContent); + loadMapBinaries(&pmRes->content,pmContent); + } + if(pmsChild!=NULL){ + pmRes->child=dupMaps(&pmsChild); + } + pmRes->next=dupMaps(&pmsCursor->next); + } + return pmRes; +} + +/** + * Add a maps at the end of another maps. + * + * @see addMapToMap, dupMaps, getMaps + * @param ppmsOut the maps to add mi + * @param pmIn the maps to add to mo + */ +void addMapsToMaps(maps** ppmsOut,maps* pmIn){ + maps* pmsTmp=pmIn; + maps* pmsCursor=*ppmsOut; + while(pmsTmp!=NULL){ + if(pmsCursor==NULL){ + *ppmsOut=dupMaps(&pmIn); + } + else{ + maps* pmsTmp1=getMaps(*ppmsOut,pmsTmp->name); + if(pmsTmp1==NULL){ + while(pmsCursor->next!=NULL) + pmsCursor=pmsCursor->next; + pmsCursor->next=dupMaps(&pmsTmp); + if(pmsTmp->child!=NULL) + pmsCursor->next->child=dupMaps(&pmsTmp->child); + else + pmsCursor->next->child=NULL; + return; + } + else{ + addMapToMap(&pmsTmp1->content,pmsTmp->content); + if(pmsTmp->child!=NULL) + pmsTmp1->child=dupMaps(&pmsTmp->child); + else + pmsTmp1->child=NULL; + } + pmsCursor=*ppmsOut; + } + pmsTmp=pmsTmp->next; + } +} + +/** + * Access a specific map array element + * + * @param pmMap the map to search for the key + * @param pccKey the key to search in the map + * @param iIndex of the MapArray + * @return a pointer on the map found or NULL if not found + */ +map* getMapArray(map* pmMap,const char* pccKey,int iIndex){ + char acTmp[1024]; + map* pmTmp; + if(iIndex>0) + sprintf(acTmp,"%s_%d",pccKey,iIndex); + else + sprintf(acTmp,"%s",pccKey); +#ifdef DEBUG + fprintf(stderr,"** KEY %s\n",acTmp); +#endif + pmTmp=getMap(pmMap,acTmp); +#ifdef DEBUG + if(pmTmp!=NULL) + dumpMap(pmTmp); +#endif + return pmTmp; +} + +/** + * Add a key value in a MapArray for a specific index + * + * @param pmMap the map to search for the key + * @param pccKey the key to search in the map + * @param iIndex the index of the MapArray + * @param pccValue the value to set in the MapArray + * @return a pointer on the map found or NULL if not found + */ +void setMapArray(map* pmMap,const char* pccKey,int iIndex,const char* pccValue){ + char acTmp[1024]; + map* pmSize; + if(iIndex>0){ + map* pmLen=getMap(pmMap,"length"); + sprintf(acTmp,"%s_%d",pccKey,iIndex); + if((pmLen!=NULL && atoi(pmLen->value)value); +#endif + free(pmPtr->value); + pmPtr->value=(char*)malloc((atoi(pmSize->value)+1)*sizeof(char)); + memcpy(pmPtr->value,pccValue,atoi(pmSize->value)); + } + else + addToMap(pmMap,acTmp,pccValue); +} + +/** + * Add a key and an integer value to an existing map array. + * + * @param pmMap the map to add the KVP + * @param pccName the key to add + * @param iIndex the index of the MapArray + * @param icValue the corresponding value to add + */ +void addIntToMapArray(map* pmMap,const char* pccName,int iIndex,const unsigned long icValue){ + char acValue[12]; + sprintf(acValue,"%lu",icValue); + setMapArray(pmMap,pccName,iIndex,acValue); +} + +/** + * Access the map "type" + * + * @param pmMap the map + * @return a pointer on the map for mimeType/dataType/CRS if found, NULL in + * other case + */ +map* getMapType(map* pmMap){ + map* pmMime=getMap(pmMap,(char *)"mimeType"); + if(pmMime==NULL){ + pmMime=getMap(pmMap,"dataType"); + if(pmMime==NULL){ + pmMime=getMap(pmMap,"CRS"); + } + } +#ifdef DEBUG + dumpMap(pmMime); +#endif + return pmMime; +} + +/** + * Add a Maps containing a MapArray to a Maps + * + * @see getMapType + * @param pmsOut the maps + * @param pmsIn the maps + * @param pcType the map "type" + * @return + */ +int addMapsArrayToMaps(maps** pmsOut,maps* pmsIn,char* pcType){ + maps* pmsTmp=pmsIn; + maps* pmsCursor=getMaps(*pmsOut,pmsTmp->name); + char acLen[10]; + int iLen=1; + char *acV[14]={ + (char*)"size", + (char*)"value", + (char*)"uom", + (char*)"Reference", + (char*)"Order", + (char*)"cache_file", + (char*)"fmimeType", + (char*)"xlink:href", + pcType, + (char*)"schema", + (char*)"encoding", + (char*)"isCached", + (char*)"LowerCorner", + (char*)"UpperCorner" + }; + int iCounter=0; + map* pmLength; + + if(pmsCursor==NULL) + return -1; + + pmLength=getMap(pmsCursor->content,"length"); + if(pmLength!=NULL){ + iLen=atoi(pmLength->value); + } + + sprintf(acLen,"%d",iLen+1); + addToMap(pmsCursor->content,"length",acLen); + for(iCounter=0;iCounter<14;iCounter++){ + map* pmTmp=getMap(pmsTmp->content,acV[iCounter]); + if(pmTmp!=NULL){ +#ifdef DEBUG + fprintf(stderr,"%s = %s\n",pmTmp[iCounter],pmTmp->value); +#endif + setMapArray(pmsCursor->content,acV[iCounter],iLen,pmTmp->value); + } + } + + addToMap(pmsCursor->content,"isArray","true"); + return 0; +} + +/** + * Set a key value pair to a map contained in a Maps + * + * @param pmsMaps the maps + * @param pccKey the maps name + * @param pccSubkey the map name included in the maps corresponding to key + * @param pccValue the corresponding value to add in the map + */ +void setMapInMaps(maps* pmsMaps,const char* pccKey,const char* pccSubkey,const char *pccValue){ + maps* pmsTmp=getMaps(pmsMaps,pccKey); + if(pmsTmp!=NULL){ + map* pmTmpSub=getMap(pmsTmp->content,pccSubkey); + if(pmTmpSub!=NULL){ + if(pmTmpSub->value!=NULL) + free(pmTmpSub->value); + pmTmpSub->value=zStrdup(pccValue); + }else{ + maps *pmsToAdd=createMaps(pccKey); + pmsToAdd->content=createMap(pccSubkey,pccValue); + addMapsToMaps(&pmsTmp,pmsToAdd); + freeMaps(&pmsToAdd); + free(pmsToAdd); + } + }else{ + maps *pmsToAdd=createMaps(pccKey); + pmsToAdd->content=createMap(pccSubkey,pccValue); + addMapsToMaps(&pmsMaps,pmsToAdd); + freeMaps(&pmsToAdd); + free(pmsToAdd); + } +} + +/** + * Create an empty elements + * + * @return a pointer to the allocated elements + */ +elements* createEmptyElements(){ + elements* peRes=(elements*)malloc(ELEMENTS_SIZE); + peRes->name=NULL; + peRes->content=NULL; + peRes->metadata=NULL; + peRes->additional_parameters=NULL; + peRes->format=NULL; + peRes->defaults=NULL; + peRes->supported=NULL; + peRes->child=NULL; + peRes->next=NULL; + return peRes; +} + +/** + * Create a named elements + * + * @param pcName the elements name + * @return a pointer to the allocated elements + */ +elements* createElements(const char* pcName){ + elements* peRes=(elements*)malloc(ELEMENTS_SIZE); + peRes->name=zStrdup(pcName); + peRes->content=NULL; + peRes->metadata=NULL; + peRes->additional_parameters=NULL; + peRes->format=NULL; + peRes->defaults=NULL; + peRes->supported=NULL; + peRes->child=NULL; + peRes->next=NULL; + return peRes; +} + +/** + * Set the name of an elements + * + * @param peElem the elements to modify + * @param pcName the elements name + * @return a pointer to the allocated elements + */ +void setElementsName(elements** ppeElem,char* pcName){ + elements* peRes=*ppeElem; + peRes->name=zStrdup(pcName); + peRes->content=NULL; + peRes->metadata=NULL; + peRes->format=NULL; + peRes->defaults=NULL; + peRes->supported=NULL; + peRes->child=NULL; + peRes->next=NULL; +} + +/** + * Dump an elements on stderr + * + * @param peElem the elements to dump + */ +void dumpElements(elements* peElem){ + elements* peTmp=peElem; + while(peTmp!=NULL){ + iotype* piotTmp=peTmp->defaults; + int ioc=0; + fprintf(stderr,"ELEMENT [%s]\n",peTmp->name); + fprintf(stderr," > CONTENT [%s]\n",peTmp->name); + dumpMap(peTmp->content); + fprintf(stderr," > METADATA [%s]\n",peTmp->name); + dumpMap(peTmp->metadata); + fprintf(stderr," > ADDITIONAL PARAMETERS [%s]\n",peTmp->name); + dumpMap(peTmp->additional_parameters); + fprintf(stderr," > FORMAT [%s]\n",peTmp->format); + while(piotTmp!=NULL){ + fprintf(stderr," > DEFAULTS [%s] (%i)\n",peTmp->name,ioc); + dumpMap(piotTmp->content); + piotTmp=piotTmp->next; + ioc++; + } + piotTmp=peTmp->supported; + ioc=0; + while(piotTmp!=NULL){ + fprintf(stderr," > SUPPORTED [%s] (%i)\n",peTmp->name,ioc); + dumpMap(piotTmp->content); + piotTmp=piotTmp->next; + ioc++; + } + if(peTmp->child!=NULL){ + fprintf(stderr," > CHILD \n"); + dumpElements(peTmp->child); + } + fprintf(stderr,"------------------\n"); + peTmp=peTmp->next; + } +} + +/** + * Dump an elements on stderr using the YAML syntaxe + * + * @param peElem the elements to dump + * @param iLevel the current level + */ +void dumpElementsAsYAML(elements* peElem,int iLevel){ + elements* peTmp=peElem; + int i; + while(peTmp!=NULL){ + map* pmCurs=peTmp->content; + int ioc=0; + iotype* piotTmp; + for(i=0;i<2+(4*iLevel);i++) + fprintf(stderr," "); + fprintf(stderr,"%s:\n",peTmp->name); + while(pmCurs!=NULL){ + for(i=0;i<4+(4*iLevel);i++) + fprintf(stderr," "); + _dumpMap(pmCurs); + pmCurs=pmCurs->next; + } + pmCurs=peTmp->metadata; + if(pmCurs!=NULL){ + for(i=0;i<4+(4*iLevel);i++) + fprintf(stderr," "); + fprintf(stderr,"MetaData:\n"); + while(pmCurs!=NULL){ + for(i=0;i<6+(4*iLevel);i++) + fprintf(stderr," "); + _dumpMap(pmCurs); + pmCurs=pmCurs->next; + } + } + for(i=0;i<4+(4*iLevel);i++) + fprintf(stderr," "); + if(peTmp->format!=NULL) + fprintf(stderr,"%s:\n",peTmp->format); + else{ + fprintf(stderr,"Child:\n"); + if(peTmp->child!=NULL) + dumpElementsAsYAML(peTmp->child,iLevel+1); + } + piotTmp=peTmp->defaults; + while(piotTmp!=NULL){ + for(i=0;i<6+(4*iLevel);i++) + fprintf(stderr," "); + fprintf(stderr,"default:\n"); + pmCurs=piotTmp->content; + while(pmCurs!=NULL){ + for(i=0;i<8+(4*iLevel);i++) + fprintf(stderr," "); + if(strcasecmp(pmCurs->name,"range")==0){ + fprintf(stderr,"range: \"%s\"\n",pmCurs->value); + }else + _dumpMap(pmCurs); + pmCurs=pmCurs->next; + } + piotTmp=piotTmp->next; + ioc++; + } + piotTmp=peTmp->supported; + ioc=0; + while(piotTmp!=NULL){ + for(i=0;i<6+(4*iLevel);i++) + fprintf(stderr," "); + fprintf(stderr,"supported:\n"); + pmCurs=piotTmp->content; + while(pmCurs!=NULL){ + for(i=0;i<8+(4*iLevel);i++) + fprintf(stderr," "); + if(strcasecmp(pmCurs->name,"range")==0){ + fprintf(stderr,"range: \"%s\"\n",pmCurs->value); + }else + _dumpMap(pmCurs); + pmCurs=pmCurs->next; + } + piotTmp=piotTmp->next; + ioc++; + } + peTmp=peTmp->next; + } +} + +/** + * Duplicate an elements + * + * @param peElem the elements to clone + * @return the allocated elements containing a copy of the elements e + */ +elements* dupElements(elements* peElem){ + elements* peCursor=peElem; + elements* peTmp=NULL; + if(peCursor!=NULL && peCursor->name!=NULL){ +#ifdef DEBUG + fprintf(stderr,">> %s %i\n",__FILE__,__LINE__); + dumpElements(e); + fprintf(stderr,">> %s %i\n",__FILE__,__LINE__); +#endif + peTmp=(elements*)malloc(ELEMENTS_SIZE); + peTmp->name=zStrdup(peCursor->name); + peTmp->content=NULL; + addMapToMap(&peTmp->content,peCursor->content); + peTmp->metadata=NULL; + addMapToMap(&peTmp->metadata,peCursor->metadata); + peTmp->additional_parameters=NULL; + addMapToMap(&peTmp->additional_parameters,peCursor->additional_parameters); + if(peCursor->format!=NULL) + peTmp->format=zStrdup(peCursor->format); + else + peTmp->format=NULL; + if(peCursor->defaults!=NULL){ + peTmp->defaults=(iotype*)malloc(IOTYPE_SIZE); + peTmp->defaults->content=NULL; + addMapToMap(&peTmp->defaults->content,peCursor->defaults->content); + peTmp->defaults->next=NULL; +#ifdef DEBUG + fprintf(stderr,">> %s %i\n",__FILE__,__LINE__); + dumpMap(peTmp->defaults->content); +#endif + }else + peTmp->defaults=NULL; + if(peCursor->supported!=NULL && peCursor->supported->content!=NULL){ + iotype *piotTmp=peCursor->supported->next; + peTmp->supported=(iotype*)malloc(IOTYPE_SIZE); + peTmp->supported->content=NULL; + addMapToMap(&peTmp->supported->content,peCursor->supported->content); + peTmp->supported->next=NULL; + while(piotTmp!=NULL){ + addMapToIoType(&peTmp->supported,piotTmp->content); +#ifdef DEBUG + fprintf(stderr,">> %s %i\n",__FILE__,__LINE__); + dumpMap(peTmp->defaults->content); +#endif + piotTmp=piotTmp->next; + } + } + else + peTmp->supported=NULL; + if(peCursor->child!=NULL) + peTmp->child=dupElements(peCursor->child); + else + peTmp->child=NULL; + if(peCursor->next!=NULL) + peTmp->next=dupElements(peCursor->next); + else + peTmp->next=NULL; + } + return peTmp; +} + +/** + * Add an elements to another elements. + * + * @see dupElements + * @param ppeElem the elements to add the e + * @param peELem the elements to be added to m + */ +void addToElements(elements** ppeElem,elements* peELem){ + elements* peTmp=peELem; + if(*ppeElem==NULL){ + (*ppeElem)=dupElements(peTmp); + }else{ + addToElements(&(*ppeElem)->next,peTmp); + } +} + +/** + * Set the name of a service + * + * @param ppsServ the service + * @param pcName the service name + */ +void setServiceName(service** ppsServ,char* pcName){ + service* psRes=*ppsServ; + psRes->name=zStrdup(pcName); + psRes->content=NULL; + psRes->metadata=NULL; + psRes->inputs=NULL; + psRes->outputs=NULL; +} + +/** + * Dump a service on stderr + * + * @param psServ the service to dump + */ +void dumpService(service* psServ){ + if(psServ==NULL) + return; + fprintf(stderr,"++++++++++++++++++\nSERVICE [%s]\n++++++++++++++++++\n",psServ->name); + if(psServ->content!=NULL){ + fprintf(stderr,"CONTENT MAP\n"); + dumpMap(psServ->content); + if(psServ->metadata!=NULL) + fprintf(stderr,"CONTENT METADATA\n"); + dumpMap(psServ->metadata); + if(psServ->additional_parameters!=NULL) + fprintf(stderr,"CONTENT AdditionalParameters\n"); + dumpMap(psServ->additional_parameters); + } + if(psServ->inputs!=NULL){ + fprintf(stderr,"INPUT ELEMENTS [%s]\n------------------\n",psServ->name); + dumpElements(psServ->inputs); + } + if(psServ->outputs!=NULL){ + fprintf(stderr,"OUTPUT ELEMENTS [%s]\n------------------\n",psServ->name); + dumpElements(psServ->outputs); + } + fprintf(stderr,"++++++++++++++++++\n"); +} + +/** + * Dump a service on stderr using the YAML syntaxe + * + * @param psServ the service to dump + */ +void dumpServiceAsYAML(service* psServ){ + int i; + fprintf(stderr,"# %s\n\n",psServ->name); + if(psServ->content!=NULL){ + map* pmCurs=psServ->content; + dumpMap(pmCurs); + pmCurs=psServ->metadata; + if(pmCurs!=NULL){ + fprintf(stderr,"MetaData:\n"); + while(pmCurs!=NULL){ + for(i=0;i<2;i++) + fprintf(stderr," "); + _dumpMap(pmCurs); + pmCurs=pmCurs->next; + } + } + } + if(psServ->inputs!=NULL){ + fprintf(stderr,"\ninputs:\n"); + dumpElementsAsYAML(psServ->inputs,0); + } + if(psServ->outputs!=NULL){ + fprintf(stderr,"\noutputs:\n"); + dumpElementsAsYAML(psServ->outputs,0); + } +} + +/** + * Duplicate a service + * + * @param psServ the service to clone + * @return the allocated service containing a copy of the serfvice s + */ +service* dupService(service* psServ){ + service *psRes=(service*)malloc(SERVICE_SIZE); + psRes->name=zStrdup(psServ->name); + psRes->content=NULL; + addMapToMap(&psRes->content,psServ->content); + psRes->metadata=NULL; + addMapToMap(&psRes->metadata,psServ->metadata); + psRes->additional_parameters=NULL; + addMapToMap(&psRes->additional_parameters,psServ->additional_parameters); + psRes->inputs=dupElements(psServ->inputs); + psRes->outputs=dupElements(psServ->outputs); + return psRes; +} + +/** + * Print the registry on stderr. + * + * @param prReg the registry + */ +void dumpRegistry(registry* prReg){ + registry* prCurs=prReg; + while(prCurs!=NULL){ + services* psServ=prCurs->content; + fprintf(stderr,"%s \n",prCurs->name); + psServ=prCurs->content; + while(psServ!=NULL){ + dumpService(psServ->content); + psServ=psServ->next; + } + prCurs=prCurs->next; + } +} + +/** + * Add a service to the registry + * + * @param prReg the resgitry to add the service + * @param pcName the registry name to update + * @param psContent the service to add + */ +bool addServiceToRegistry(registry** prReg,char* pcName,service* psContent){ + registry *l=*prReg; + int isInitial=-1; + if(l==NULL){ + l=(registry*)malloc(REGISTRY_SIZE); + isInitial=1; + } + if(l!=NULL){ + int hasLevel=-1; + while(isInitial<0 && l!=NULL){ + if(l->name!=NULL && strcasecmp(pcName,l->name)==0){ + hasLevel=1; + break; + } + l=l->next; + } + if(hasLevel<0){ + if(isInitial<0) + l=(registry*)malloc(REGISTRY_SIZE); + l->name=zStrdup(pcName); + l->content=NULL; + l->next=NULL; + } + if(l->content==NULL){ + l->content=(services*)malloc(SERVICES_SIZE); + l->content->content=dupService(psContent); + l->content->next=NULL; + } + else{ + services* psServ=l->content; + while(psServ->next!=NULL) + psServ=psServ->next; + psServ->next=(services*)malloc(SERVICES_SIZE); + psServ->next->content=dupService(psContent); + psServ->next->next=NULL; + } + l->next=NULL; + if(isInitial>0) + *prReg=l; + else{ + registry *prCurs=*prReg; + while(prCurs->next!=NULL) + prCurs=prCurs->next; + prCurs->next=l; + prCurs->next->next=NULL; + } + return true; + } + else + return false; +} + +/** + * Free memory allocated for the registry + * + * @param prReg the registry + */ +void freeRegistry(registry** prReg){ + registry* prLocalRef=*prReg; + while(prLocalRef!=NULL){ + services* psServ=prLocalRef->content; + free(prLocalRef->name); + while(psServ!=NULL){ + service* psServ1=psServ->content; + psServ=psServ->next; + if(psServ1!=NULL){ + freeService(&psServ1); + free(psServ1); + psServ1=NULL; + } + } + prLocalRef=prLocalRef->next; + } +} + +/** + * Access a service in the registry + * + * @param prReg the registry + * @param pcLevel the regitry to search ("concept", "generic" or "implementation") + * @param pcName the service name + * @return the service pointer if a corresponding service was found or NULL + */ +service* getServiceFromRegistry(registry* prReg,char *pcLevel,char* pcName){ + registry *prLocalRef=prReg; + while(prLocalRef!=NULL){ + if(strcasecmp(prLocalRef->name,pcLevel)==0){ + services* psServ=prLocalRef->content; + while(psServ!=NULL){ + if(psServ->content!=NULL && strcasecmp(psServ->content->name,pcName)==0) + return psServ->content; + psServ=psServ->next; + } + break; + } + prLocalRef=prLocalRef->next; + } + return NULL; +} + +/** + * Apply inheritance to an out map from a reference in map + * + * @param ppmOut the map to update + * @param pmIn the reference map (containing inherited properties) + */ +void inheritMap(map** ppmOut,map* pmIn){ + map* pmContent=pmIn; + if((*ppmOut)==NULL){ + addMapToMap(ppmOut,pmIn); + return; + } + while(pmContent!=NULL){ + map* pmCurrent=getMap(*ppmOut,pmContent->name); + if(pmCurrent==NULL) + addToMap(*ppmOut,pmCurrent->name,pmCurrent->value); + pmCurrent=pmCurrent->next; + } +} + +/** + * Apply inheritance to an out iotype from a reference in iotype + * + * @param ppiotOut the iotype to update + * @param piotIn the reference iotype (containing inherited properties) + */ +void inheritIOType(iotype** ppiotOut,iotype* piotIn){ + iotype* piotInCurosor=piotIn; + iotype* ppiotOutCursor=*ppiotOut; + if(piotInCurosor!=NULL){ + if(*ppiotOut==NULL){ + *ppiotOut=(iotype*)malloc(IOTYPE_SIZE); + (*ppiotOut)->content=NULL; + addMapToMap(&(*ppiotOut)->content,piotInCurosor->content); + (*ppiotOut)->next=NULL; + ppiotOutCursor=*ppiotOut; + inheritIOType(&ppiotOutCursor->next,piotInCurosor->next); + }else{ + inheritIOType(&ppiotOutCursor->next,piotInCurosor->next); + } + } +} + +/** + * Apply inheritance to an out elements from a reference in elements + * + * @param ppeOut the elements to update + * @param peIn the reference elements (containing inherited properties) + */ +void inheritElements(elements** ppeOut,elements* peIn){ + elements* peContent=peIn; + while(peContent!=NULL && *ppeOut!=NULL){ + elements* peCurrent=getElements(*ppeOut,peContent->name); + if(peCurrent==NULL) + addToElements(ppeOut,peContent); + else{ + inheritMap(&peCurrent->content,peContent->content); + inheritMap(&peCurrent->metadata,peContent->metadata); + if(peCurrent->format==NULL && peContent->format!=NULL) + peCurrent->format=zStrdup(peContent->format); + inheritIOType(&peCurrent->defaults,peContent->defaults); + if(peCurrent->supported==NULL) + inheritIOType(&peCurrent->supported,peContent->supported); + else{ + iotype* piotTmp=peContent->supported; + while(piotTmp!=NULL){ + addMapToIoType(&peCurrent->supported,piotTmp->content); + piotTmp=piotTmp->next; + } + } + } + peContent=peContent->next; + } +} + +/** + * Apply inheritance to a service based on a registry + * + * @param prReg the registry storing profiles hierarchy + * @param psServ the service to update depending on its inheritance + */ +void inheritance(registry *prReg,service** psServ){ + service* psCursor=*psServ; + map *profile,*level; + if(prReg==NULL) + return; + if(psCursor==NULL || psCursor->content==NULL) + return; + profile=getMap(psCursor->content,"extend"); + level=getMap(psCursor->content,"level"); + if(profile!=NULL&&level!=NULL){ + service* s1; + if(strncasecmp(level->value,"profile",7)==0) + s1=getServiceFromRegistry(prReg,(char*)"generic",profile->value); + else + s1=getServiceFromRegistry(prReg,level->value,profile->value); + + inheritMap(&psCursor->content,s1->content); + inheritMap(&psCursor->metadata,s1->metadata); + if(psCursor->inputs==NULL && s1->inputs!=NULL){ + psCursor->inputs=dupElements(s1->inputs); + }else{ + inheritElements(&psCursor->inputs,s1->inputs); + } + if(psCursor->outputs==NULL && s1->outputs!=NULL){ + psCursor->outputs=dupElements(s1->outputs); + }else + inheritElements(&psCursor->outputs,s1->outputs); + } +} + +/** + * Convert a maps to a char*** (only used for Fortran support) + * + * @param pmsMap the maps to convert + * @param pppcValues the resulting array + */ +void mapsToCharXXX(maps* pmsMap,char*** pppcValues){ + maps* pmsCursor=pmsMap; + int i=0; + int j=0; + char aaacTmp[10][30][1024]; + memset(aaacTmp,0,1024*10*10); + while(pmsCursor!=NULL){ + map* pmContent=pmsCursor->content; + if(i>=10) + break; + strcpy(aaacTmp[i][j],"name"); + j++; + strcpy(aaacTmp[i][j],pmsCursor->name); + j++; + while(pmContent!=NULL){ + if(j>=30) + break; + strcpy(aaacTmp[i][j],pmContent->name); + j++; + strcpy(aaacTmp[i][j],pmContent->value); + j++; + pmContent=pmContent->next; + } + pmsCursor=pmsCursor->next; + j=0; + i++; + } + memcpy(pppcValues,aaacTmp,10*10*1024); +} + +/** + * Convert a char*** to a maps (only used for Fortran support) + * + * @param pppcValues the array to convert + * @param ppmsMaps the resulting maps + */ +void charxxxToMaps(char*** pppcValues,maps** ppmsMaps){ + maps* pmsCursor=*ppmsMaps; + int i,j; + char aaaTmp[10][30][1024]; + memcpy(aaaTmp,pppcValues,10*30*1024); + for(i=0;i<10;i++){ + if(strlen(aaaTmp[i][1])==0) + break; + pmsCursor->name=aaaTmp[i][1]; + pmsCursor->content=NULL; + pmsCursor->next=NULL; + for(j=2;j<29;j+=2){ + if(strlen(aaaTmp[i][j+1])==0) + break; + if(pmsCursor->content==NULL) + pmsCursor->content=createMap(aaaTmp[i][j],aaaTmp[i][j+1]); + else + addToMap(pmsCursor->content,aaaTmp[i][j],aaaTmp[i][j+1]); + } + pmsCursor=pmsCursor->next; + } + ppmsMaps=&pmsCursor; +} + +/** + * Verify that a map has a value + * + * @param pmMap pointer to map that should be checked + * @return true if map has a value or false if value is missing/empty/NULL + */ +bool nonempty(map* pmMap) { + return (pmMap != NULL && pmMap->value != NULL && strlen(pmMap->value) > 0 && strcmp(pmMap->value, "NULL") != 0); +} + +/** + * Verify that a particular map value exists in a maps + * data structure, and obtain that value + * + * @param pmsSource pointer to maps structure + * @param pccNode name of maps node to search + * @param pccKey name of map node to find + * @param ppmKvp address to the map* if it exists, otherwise NULL + * @return true if map has a value or false if value is missing/NULL + * + * @note The map assigned to kvp is owned by the source maps + */ +bool hasvalue(maps* pmsSource, const char* pccNode, const char* pccKey, map** ppmKvp) { + *ppmKvp = getMapFromMaps(pmsSource, pccNode, pccKey); + return (*ppmKvp != NULL && (*ppmKvp)->value != NULL && + strlen((*ppmKvp)->value) > 0 && strcmp((*ppmKvp)->value, "NULL") != 0); +} + +/* + * Set error message in configuration maps + * + * @param pmsaConf reference to configuration maps + * @param pccService name of service + * @param weExc WPSException code + * @param pccMessage exception text (default: exception text in WPS specification) + */ +void setErrorMessage(maps*& pmsaConf, const char* pccService, WPSException weExc, const char* pccMessage) { + if (pccMessage == NULL) { + pccMessage = WPSExceptionText[weExc]; + } + size_t len = strlen(pccService) + strlen(": ") + strlen(pccMessage) + strlen(": ") + strlen(WPSExceptionCode[weExc]) + 16; + char* pcMsg = (char*)malloc(len * sizeof(char)); + if (pcMsg != NULL) { + snprintf(pcMsg, len * sizeof(char), "\n%s: %s: %s\n", pccService, pccMessage, WPSExceptionCode[weExc]); + setMapInMaps(pmsaConf, "lenv", "message", pcMsg); + free(pcMsg); + } +} + +/** + * Print debug message + * + * @param pccSource the file invoking the function + * @param pccFunction the function calling for logMessage + * @param iLine the line number + * @param pccFile the file to log informations + * @param pccMessage the message to be print + */ +void logMessage(const char* pccSource, const char* pccFunction, int iLne, const char* pccFile, const char* pccMessage) { //, const char* source, const char* function, int line) { + + size_t msglen = 512; + const char empty[] = ""; + + FILE* pfLog; + + // system time, process time [nanoseconds] + unsigned long long sys_t, proc_t; + + // processor time consumed by the program: + clock_t t = clock(); + + // system time: + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + + std::time_t now_t = std::chrono::system_clock::to_time_t(now); + std::tm* tm = localtime(&now_t); + char* pcStr = asctime(tm); + pcStr[strlen(pcStr) - 1] = '\0'; // remove newline + + sys_t = std::chrono::duration_cast(now.time_since_epoch()).count(); + //proc_t = (unsigned long long)(1.0e9*t/CLOCKS_PER_SEC); + proc_t = t; + + if (pccMessage != NULL) { + msglen += strlen(pccMessage); + } + else { + pccMessage = empty; + } + //getLastErrorMessage(); // cgiScriptName + char* pcText = (char*)malloc(sizeof(char)*msglen); + + snprintf(pcText, msglen, "pid: %d %s line %d %s() %s systime: %lld ns ticks: %lld %s\n", + zGetpid(), pccSource, iLne, pccFunction, pcStr, sys_t, proc_t, pccMessage); // __FILE__ __LINE__ __func__ // + + if (pccFile != NULL && (pfLog = fopen(pccFile, "a+")) != NULL) { + fputs(pcText, pfLog); + fclose(pfLog); + } + else { +#ifdef MSG_LOG_FILE + if ((pfLog = fopen(MSG_LOG_FILE, "a+")) != NULL) { + fputs(pcText, pfLog); + fclose(pfLog); + } +#endif + } + + if (pcText != NULL) free(pcText); +} + +// knut: +// Example: +// zooLog; +// zooLogMsg(NULL, getLastErrorMessage()); +// zooLogMsg("log.txt", getLastErrorMessage()); + +#ifdef WIN32 +#ifndef USE_MS +char *strcasestr (char const *pccA, char const *pccB) + { + char *pcX = zStrdup (pccA); + char *pcY = zStrdup (pccB); + + pcX = _strlwr (pcX); + pcY = _strlwr (pcY); + char *pos = strstr (pcX, pcY); + char *ret = pos == NULL ? NULL : (char *) (pccA + (pos - pcX)); + free (pcX); + free (pcY); + return ret; + }; +#else + ; +#endif +#endif + +/* + * Dynamically allocate memory for a map value + * + * @param node the map for which the value buffer should be allocated + * @param num_bytes the number of bytes to allocate + * @return pointer to the allocated memory buffer + * + * This function will free, and hence delete, any existing value in the map. + * The memory should be deallocated by calling freeMap. + */ +char* allocateMapValue(map* pmNode, size_t sNumBytes) +{ + if (pmNode == NULL) { + return NULL; + } + + if (pmNode->value != NULL) { + free(pmNode->value); + } + pmNode->value = (char*) malloc(sNumBytes); + + return pmNode->value; +} + +/* + * Find the value corresponding to an input (cache_file content or value field) + * + * @param inputs the maps for searching the corresponding value + * @param name the field name to search within the maps + * @return string the value if any, or NULL + * + * This function return a new string that should be freed after use. + */ +char* getValueFromMaps(maps* inputs,const char* name){ + char* res=NULL; + map* pmTmp=getMapFromMaps(inputs,name,"cache_file"); + if(pmTmp!=NULL){ + FILE* f0 = fopen (pmTmp->value, "rb"); + if(f0!=NULL){ + long flen; + char *fcontent; + fseek (f0, 0, SEEK_END); + flen = ftell (f0); + fseek (f0, 0, SEEK_SET); + fcontent = (char *) malloc ((flen + 1) * sizeof (char)); + fread(fcontent,flen,1,f0); + fcontent[flen]=0; + fclose(f0); + res=zStrdup(fcontent); + fprintf(stderr,"%s %d (%s)\n",__FILE__,__LINE__,fcontent); + free(fcontent); + } + }else{ + pmTmp=getMapFromMaps(inputs,name,"value"); + if(pmTmp!=NULL && strncasecmp(pmTmp->value,"NULL",4)!=0){ + res = zStrdup(pmTmp->value); + } + } + return res; +} + +/** + * Replace a char by another one in a string + * + * @param str the string to update + * @param toReplace the char to replace + * @param toReplaceBy the char that will be used + */ +void +_translateChar (char *str, char toReplace, char toReplaceBy) +{ + int i = 0, len = strlen (str); + for (i = 0; i < len; i++) + { + if (str[i] == toReplace) + str[i] = toReplaceBy; + } +} + +/** + * Replace all "val" occurence with the corresponding "rep" value in a string + * + * @param str the string to update + * @param toReplace the char to replace + * @param toReplaceBy the char that will be used + */ +char* +translateCharMap (const char *str, map* rep) +{ + char* res=zStrdup(str); + if(rep!=NULL){ + int i = 0, len=1; + map* pmLen=getMap(rep,"length"); + if(pmLen!=NULL) + len=atoi(pmLen->value); + for (i = 0; i < len; i++) + { + map* pmVal=getMapArray(rep,"val",i); + map* pmRep=getMapArray(rep,"rep",i); + _translateChar(res,pmVal->value[0],pmRep->value[0]); + } + } + return res; +} + diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service.h b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service.h new file mode 100644 index 00000000..8a8d29bf --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service.h @@ -0,0 +1,536 @@ +/* + * Author : Gérald FENOY + * + * Copyright (c) 2009-2019 GeoLabs SARL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ZOO_SERVICE_H +#define ZOO_SERVICE_H 1 + +#pragma once + +#ifdef WIN32 +#define ZOO_DLL_EXPORT __declspec( dllexport ) +#else +#define ZOO_DLL_EXPORT +#endif + + // knut: add bool if necessary +#ifndef __cplusplus +#ifndef WIN32 +#include +#else +typedef int bool; +#define false 0 +#define true 1 +#endif +#endif +#ifndef __bool_true_false_are_defined +#define __bool_true_false_are_defined 1 +#endif + +#ifdef WIN32 +#define strtok_r strtok_s +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif +#define zStrdup _strdup +#define zMkdir _mkdir +#define zGetpid _getpid +#define zOpen _open +#define zClose _close +#define zUnlink _unlink +#define zDup _dup +#define zDup2 _dup2 +#define zWrite _write +#define zSleep Sleep +#include +struct ztimeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +static int zGettimeofday(struct ztimeval* tp, void* tzp) +{ + if (tp == 0) { + return -1; + } + + struct _timeb theTime; + _ftime(&theTime); + tp->tv_sec = theTime.time; + tp->tv_usec = theTime.millitm * 1000; + + return 0; // The gettimeofday() function shall return 0 on success +} + +#define zStatStruct struct _stati64 +#define zStat _stati64 + +#else +#include +/** + * The crossplatform strdup alias + */ +#define zStrdup strdup +/** + * The crossplatform mkdir alias + */ +static int zMkdir(const char* pccPath){ + return mkdir(pccPath,0777); +} +/** + * The crossplatform open alias + */ +#define zOpen open +/** + * The crossplatform close alias + */ +#define zClose close +/** + * The crossplatform unlink alias + */ +#define zUnlink unlink +/** + * The crossplatform dup alias + */ +#define zDup dup +/** + * The crossplatform dup2 alias + */ +#define zDup2 dup2 +/** + * The crossplatform write alias + */ +#define zWrite write +#include "unistd.h" +/** + * The crossplatform sleep alias + */ +static int zSleep(const long millisecond){ + return usleep(millisecond*1000); +} +/** + * The crossplatform gettimeofday alias + */ +#define zGettimeofday gettimeofday +/** + * The crossplatform timeval alias + */ +#define ztimeval timeval +/** + * The crossplatform getpid alias + */ +#define zGetpid getpid + +#define zStatStruct struct stat64 +#define zStat stat64 + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +#ifdef USE_MS +#include +#endif +#endif +#include +#include + +#include + +#include +#ifndef WIN32 +#include +#include +#endif + +/** + * The global accepted status for a service + */ +#define SERVICE_ACCEPTED 0 +/** + * The global started status for a service + */ +#define SERVICE_STARTED 1 +/** + * The global paused status for a service + */ +#define SERVICE_PAUSED 2 +/** + * The global succeeded status for a service + */ +#define SERVICE_SUCCEEDED 3 +/** + * The global failed status for a service + */ +#define SERVICE_FAILED 4 +/** + * The global dismissed status for a service + */ +#define SERVICE_DISMISSED 5 + +/** + * The memory size to create an elements + */ +#define ELEMENTS_SIZE (sizeof(char*)+(((2*sizeof(char*))+sizeof(maps*))*3)+sizeof(char*)+((sizeof(map*) + sizeof(iotype*))*2)+(2*sizeof(elements*))) +/** + * The memory size to create a map + */ +//#define MAP_SIZE (2*sizeof(char*))+sizeof(NULL) // knut: size of NULL pointer may be different from regular pointer (platform dependent) +#define MAP_SIZE (2*sizeof(char*))+sizeof(map*) +/** + * The memory size to create an iotype + */ +//#define IOTYPE_SIZE MAP_SIZE+sizeof(NULL) +#define IOTYPE_SIZE sizeof(map*) + sizeof(iotype*) +/** + * The memory size to create a maps + */ +//#define MAPS_SIZE (2*sizeof(char*))+sizeof(map*)+MAP_SIZE +#define MAPS_SIZE sizeof(char*)+sizeof(map*)+(2*sizeof(maps*)) +/** + * The memory size to create a service + */ +//#define SERVICE_SIZE (ELEMENTS_SIZE*2)+(MAP_SIZE*2)+sizeof(char*) +#define SERVICE_SIZE sizeof(char*) + 3*sizeof(map*) + 2*sizeof(elements*) +/** + * The memory size to create a services + */ +//#define SERVICES_SIZE SERVICE_SIZE+sizeof(services*) +#define SERVICES_SIZE sizeof(service*)+sizeof(services*) +/** + * The memory size to create a registry + */ +//#define REGISTRY_SIZE SERVICES_SIZE+sizeof(char*) +#define REGISTRY_SIZE sizeof(char*)+sizeof(services*)+sizeof(registry*) + +#define SHMSZ 27 + +#include "version.h" + +#ifdef DEBUG_STACK + void debugStack(const char* file,const int line){ + int stack; + fprintf(stderr,"stack %p (%s: %d) \n",&stack,file,line); + } +#endif + + /** + * KVP linked list + */ + typedef struct map{ + char* name; //!< the key + char* value; //!< the value + struct map* next; //!< the pointer to the next map if any or NULL + } map; + +#ifdef WIN32 +#define NULLMAP ((map*) 0) +// knut: see new definition above +//#define bool int +//#define true 1 +//#define false 0 +#else +#define NULLMAP NULL +#endif + + /** + * linked list of map pointer + * + * Small object to store WPS KVP set. + */ + typedef struct maps{ + char* name; //!< the maps name + struct map* content; //!< the content map + struct maps* child; //!< the child maps + struct maps* next; //!< the pointer to the next maps if any or NULL + } maps; + + /** + * Not named linked list + * + * Used to store information about formats, such as mimeType, encoding ... + */ + typedef struct iotype{ + struct map* content; //!< the content map + struct iotype* next; //!< the pointer to the next iotype if any or NULL + } iotype; + + /** + * Metadata information about input or output. + * + * The elements are used to store metadata information defined in the ZCFG. + */ + typedef struct elements{ + char* name; //!< the name + struct map* content; //!< the content map + struct map* metadata; //!< the metadata map + struct map* additional_parameters; //!< the additional parameters map + char* format; //!< the format: LiteralData or ComplexData or BoundingBoxData + struct iotype* defaults; //!< the default iotype + struct iotype* supported; //!< the supported iotype + struct elements* child; //!< the pointer to the children element if any (or NULL) + struct elements* next; //!< the pointer to the next element if any (or NULL) + } elements; + + /** + * Metadata information about a full Service. + */ + typedef struct service{ + char* name; //!< the name + struct map* content; //!< the content map + struct map* metadata; //!< the metadata map + struct map* additional_parameters; //!< the additional parameters map + struct elements* inputs; //!< the inputs elements + struct elements* outputs; //!< the outputs elements + } service; + + /** + * Services chained list. + */ + typedef struct services{ + struct service* content; //!< the content service pointer + struct services* next; //!< the pointer to the next services* + } services; + + /** + * Profile registry. + */ + typedef struct registry{ + char *name; //!< the name + struct services* content; //!< the content services pointer + struct registry* next; //!< the next registry pointer + } registry; + + // knut + enum WPSException { + /* + * StatusOK is not a WPS exception, it is added + * here for convenience. + */ + StatusOK, + /* + * See WPS 1.0 specification, Table 38 and Table 62. + */ + MissingParameterValue, + InvalidParameterValue, + NoApplicableCode, + NotEnoughStorage, + ServerBusy, + FileSizeExceeded, + StorageNotSupported, + VersionNegotiationFailed, + /* + * See WPS 2.0 specification, Tables 41, 46, 48, and 50. + */ + NoSuchProcess, + NoSuchMode, + NoSuchInput, + NoSuchOutput, + DataNotAccessible, + SizeExceeded, + TooManyInputs, + TooManyOutputs, + NoSuchFormat, + WrongInputData, + InternalServerError, + NoSuchJob, + ResultNotReady + }; + + /** + * Standard WPS exception codes + * @see WPSExceptionText + */ + static const char* const WPSExceptionCode[] = { + "StatusOK", + "MissingParameterValue", + "InvalidParameterValue", + "NoApplicableCode", + "NotEnoughStorage", + "ServerBusy", + "FileSizeExceeded", + "StorageNotSupported", + "VersionNegotiationFailed", + "NoSuchProcess", + "NoSuchMode", + "NoSuchInput", + "NoSuchOutput", + "DataNotAccessible", + "SizeExceeded", + "TooManyInputs", + "TooManyOutputs", + "NoSuchFormat", + "WrongInputData", + "InternalServerError", + "NoSuchJob", + "ResultNotReady", + "InvalidQueryParameterValue" + }; + + /** + * WPS exception codes to OGC API - Processes ones + * @see WPSExceptionCode, OAPIPExceptionCode + */ + static const int OAPIPCorrespondances[4][2] = { + {9,0}, + {20,1}, + {21,2}, + {22,3} + }; + + /** + * OGC API - Processes exception codes + * @see WPSExceptionCode, OAPIPCorrespondances + */ + static const char* const OAPIPExceptionCode[] = { + "no-such-process", + "no-such-job", + "result-not-ready", + "invalid-query-parameter-value" + }; + + /** + * WPS exception text (associated with the exception code) + * @see WPSExceptionCode + */ + static const char* const WPSExceptionText[] = { + "No problem detected", + "Operation request does not include a parameter value, and this server did not declare a default value for that parameter.", + "Operation request contains an invalid parameter value.", + "No other exceptionCode specified by this service and server applies to this exception.", + "The server does not have enough space available to store the inputs and outputs associated with the request.", + "The server is too busy to accept and queue the request at this time.", + "The file size of one of the input parameters was too large for this process to handle.", + "Execute operation request included transmission=”reference” for one of the outputs, but storage is not offered by this server.", + "Service version for a ComplexData xlink:href input was not supported by the referenced server, and version negotiation failed.", + "One of the identifiers passed does not match with any of the processes offered by this server.", + "The process does not permit the desired execution mode.", + "One or more of the input identifiers passed does not match with any of the input identifiers of this process.", + "One or more of the output identifiers passed does not match with any of the input identifiers of this process.", + "One of the referenced input data sets was inaccessible.", + "The size of one of the input parameters was too large for this process to handle.", + "Too many input items have been specified.", + "Too many output items have been specified.", + "One or more of the input or output formats specified in the request did not match with any of the formats defined for that particular input or output.", + "One or more of inputs for which the service was able to retrieve the data but could not read it.", + "", + "The JobID from the request does not match any of the Jobs running on this server.", + "The result for the requested JobID has not yet been generated." + }; + + ZOO_DLL_EXPORT void _dumpMap(map*); + ZOO_DLL_EXPORT void dumpMap(map*); + ZOO_DLL_EXPORT void dumpMaps(maps* m); + ZOO_DLL_EXPORT void dumpMapToFile(map*,FILE*); // (used only internally) + ZOO_DLL_EXPORT void dumpMapsToFile(maps*,char*,int); + ZOO_DLL_EXPORT map* createMap(const char*,const char*); + ZOO_DLL_EXPORT maps* createMaps(const char*); + ZOO_DLL_EXPORT int count(map*); + ZOO_DLL_EXPORT int countMaps(maps*); + ZOO_DLL_EXPORT int countMapName(map*,const char*); + ZOO_DLL_EXPORT int countMapNameValue(map*,const char*); + ZOO_DLL_EXPORT bool hasKey(map*,const char*); + ZOO_DLL_EXPORT maps* getMaps(maps*,const char*); + ZOO_DLL_EXPORT map* getMap(map*,const char*); + ZOO_DLL_EXPORT map* getLastMap(map*); + ZOO_DLL_EXPORT map* getMapFromMaps(maps*,const char*,const char*); + ZOO_DLL_EXPORT void freeMap(map**); + ZOO_DLL_EXPORT void freeMaps(maps** mo); + ZOO_DLL_EXPORT iotype* createIoType(); + ZOO_DLL_EXPORT elements* createEmptyElements(); + ZOO_DLL_EXPORT elements* createElements(const char*); + ZOO_DLL_EXPORT void setElementsName(elements**,char*); + ZOO_DLL_EXPORT bool hasElement(elements*,const char*); + ZOO_DLL_EXPORT elements* getElements(elements*,const char*); + ZOO_DLL_EXPORT void freeIOType(iotype**); + ZOO_DLL_EXPORT void freeElements(elements**); + ZOO_DLL_EXPORT void setServiceName(service**,char*); + ZOO_DLL_EXPORT service* createService(); + ZOO_DLL_EXPORT void freeService(service**); + ZOO_DLL_EXPORT void addToMap(map*,const char*,const char*); + ZOO_DLL_EXPORT void addToMapA(map*,const char*,const char*); + ZOO_DLL_EXPORT void addIntToMap(map*,const char*,const int); + ZOO_DLL_EXPORT void addIntToMapArray(map*,const char*,int,const unsigned long); + ZOO_DLL_EXPORT map* addToMapWithSize(map*,const char*,const char*,int); + ZOO_DLL_EXPORT void addMapToMap(map**,map*); + ZOO_DLL_EXPORT void addMapToIoType(iotype**,map*); + ZOO_DLL_EXPORT map* getMapOrFill(map**,const char*,const char*); + ZOO_DLL_EXPORT bool contains(map*,map*); + ZOO_DLL_EXPORT iotype* getIoTypeFromElement(elements*,char*, map*); + ZOO_DLL_EXPORT void loadMapBinary(map**,map*,int); + ZOO_DLL_EXPORT void loadMapBinaries(map**,map*); + ZOO_DLL_EXPORT maps* dupMaps(maps**); + ZOO_DLL_EXPORT void addMapsToMaps(maps**,maps*); + ZOO_DLL_EXPORT map* getMapArray(map*,const char*,int); + ZOO_DLL_EXPORT void setMapArray(map*,const char*,int,const char*); + ZOO_DLL_EXPORT map* getMapType(map*); + ZOO_DLL_EXPORT int addMapsArrayToMaps(maps**,maps*,char*); + ZOO_DLL_EXPORT void setMapInMaps(maps*,const char*,const char*,const char*); + ZOO_DLL_EXPORT void dumpElements(elements*); + ZOO_DLL_EXPORT void dumpElementsAsYAML(elements*,int); + ZOO_DLL_EXPORT elements* dupElements(elements*); + ZOO_DLL_EXPORT void addToElements(elements**,elements*); + ZOO_DLL_EXPORT void dumpService(service*); + ZOO_DLL_EXPORT void dumpServiceAsYAML(service*); + ZOO_DLL_EXPORT service* dupService(service*); + ZOO_DLL_EXPORT void dumpRegistry(registry*); + ZOO_DLL_EXPORT bool addServiceToRegistry(registry**,char*,service*); + ZOO_DLL_EXPORT void freeRegistry(registry**); + ZOO_DLL_EXPORT service* getServiceFromRegistry(registry*,char*,char*); + ZOO_DLL_EXPORT void inheritMap(map**,map*); + ZOO_DLL_EXPORT void inheritIOType(iotype**,iotype*); + ZOO_DLL_EXPORT void inheritElements(elements**,elements*); + ZOO_DLL_EXPORT void inheritance(registry*,service**); + ZOO_DLL_EXPORT void mapsToCharXXX(maps*,char***); + ZOO_DLL_EXPORT void charxxxToMaps(char***,maps**); +#if defined(_MSC_VER) && _MSC_VER < 1800 + // snprintf for Visual Studio compiler; + // it is also used by services (e.g., GetStatus), therefore exported to shared library + ZOO_DLL_EXPORT int snprintf(char *buffer, size_t n, const char *format, ...); +#endif + + // knut: some new utility functions; logMessage is primarily intended for debugging + ZOO_DLL_EXPORT bool nonempty(map* map); + ZOO_DLL_EXPORT bool hasvalue(maps* source, const char* node, const char* key, map** kvp); +#ifdef __cplusplus + ZOO_DLL_EXPORT void setErrorMessage(maps*& conf, const char* service, WPSException exc, const char* message = NULL); + ZOO_DLL_EXPORT void logMessage(const char* source, const char* function, int line, const char* file = NULL, const char* message = NULL); +#endif + #define zooLogMsg(file,message) logMessage(__FILE__, __func__, __LINE__, (file), (message)) + #define zooLog logMessage(__FILE__, __func__, __LINE__) + + // knut : function for pre-allocated memory for a map value; + // processing algorithms may be able to write directly to this space, thereby avoiding unneccesary copying of data + ZOO_DLL_EXPORT char* allocateMapValue(map* node, size_t num_bytes); + + ZOO_DLL_EXPORT char* getValueFromMaps(maps*,const char*); + ZOO_DLL_EXPORT char* translateCharMap(const char*, map*); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_callback.c b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_callback.c new file mode 100644 index 00000000..1ee8b3a5 --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_callback.c @@ -0,0 +1,1060 @@ +/* + * Author : Gérald FENOY + * + * Copyright 2017-2019 GeoLabs SARL. All rights reserved. + * + * This work was supported by public funds received in the framework of GEOSUD, + * a project (ANR-10-EQPX-20) of the program "Investissements d'Avenir" managed + * by the French National Research Agency + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef USE_CALLBACK +#include "service_internal_ms.h" +#endif +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "service_callback.h" +#include "service_json.h" +#include "sqlapi.h" +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * Parameter definition to be used for sending parameters to a thread. + */ + typedef struct { + maps *conf; //!< the main configuration file + map *url; //!< the callback url maps + json_object *res;//!< the JSON object to post + int step; //!< the current step [0,6] + int state; //!< the current state [0,1] + } local_params; + + /** + * Number of threads + */ + int nbThreads=0; + /** + * Current step + */ + int cStep=0; + /** + * Maximum value of PercentCompleted + */ + int maxProgress=0; + /** + * Is there any ongoing HTTP request + */ + int isOngoing=0; + /** + * Threads array + */ + pthread_t* myThreads=NULL; + /** + * Steps array + */ + bool steps[7][2]={ + {false,false}, + {false,false}, + {false,false}, + {false,false}, + {false,false}, + {false,false}, + {false,false} + }; + /** + * Arguments array to give to the _invokeCallback thread's function + */ + local_params** local_arguments; + + /** + * Check if a service name is prohibited, meaning that the Kernel doesn't have + * to invoke the callback for this specific service. + * + * @param conf the main configuration file maps + * @param serviceName the serviceName + * @return a bool true if the service is prohibited, false in other case + */ + bool isProhibited(maps* conf,const char* serviceName){ + map* plist=getMapFromMaps(conf,"callback","prohibited"); + if(plist!=NULL){ + char *tmp=plist->value; + char *tmpS=strtok(tmp,","); + while(tmpS!=NULL){ + if(strcmp(serviceName,tmpS)==0) + return true; + tmpS=strtok(NULL,","); + } + } + return false; + } + /** + * Practically invoke the callback, meaning sending the HTTP POST request. + * + * @param args local_params containing all the variables required + */ + void* _invokeBasicCallback(void* args){ +#ifdef CALLBACK_DEBUG + fprintf(stderr,"************************* From thread %d %s %d: REQUEST CONFIGURE (%s)\n",pthread_self(),__FILE__,__LINE__,arg->url->value); + fflush(stderr); +#endif + local_params* arg=(local_params*)args; + if(arg->stateurl->value); + fflush(stderr); +#endif + freeMaps(&arg->conf); + free(arg->conf); + freeMap(&arg->url); + free(arg->url); + pthread_exit(NULL); + return NULL; + } + HINTERNET hInternet,res1; + const struct tm *tm; + size_t len; + char *tmp1; + map *tmpStatus; + map* pmTmp=getMapFromMaps(arg->conf,"lenv","status"); + hInternet=InternetOpen("ZooWPSClient\0", + INTERNET_OPEN_TYPE_PRECONFIG, + NULL,NULL, 0); + if(!CHECK_INET_HANDLE(hInternet)){ + InternetCloseHandle (&hInternet); + return NULL; + } + const char* jsonStr=json_object_to_json_string_ext(arg->res,JSON_C_TO_STRING_PLAIN); + while( arg->state != SERVICE_SUCCEEDED && arg->state != SERVICE_FAILED && isOngoing>0 ){ + zSleep(100); + } + if(arg->state==SERVICE_STARTED && pmTmp!=NULL){ + if(maxProgress<=atoi(pmTmp->value)){ + maxProgress=atoi(pmTmp->value); + }else{ +#ifdef CALLBACK_DEBUG + fprintf(stderr,"************************* From thread %d %s %d: REQUEST CANCELLED (%s) EXIT!\n",pthread_self(),__FILE__,__LINE__,arg->url->value); + fflush(stderr); +#endif + freeMaps(&arg->conf); + free(arg->conf); + freeMap(&arg->url); + free(arg->url); + pthread_exit(NULL); + return NULL; + } + }else + maxProgress=101; + isOngoing=1; + maps* tmpConf=createMaps("main"); + tmpConf->content=createMap("memory","load"); + + hInternet.waitingRequests[0] = zStrdup(arg->url->value); + res1 = InternetOpenUrl (&hInternet, + hInternet.waitingRequests[0], + (char*)jsonStr, strlen(jsonStr), + INTERNET_FLAG_NO_CACHE_WRITE, + 0,tmpConf); + AddHeaderEntries(&hInternet,arg->conf); + AddMissingHeaderEntry(&hInternet.ihandle[hInternet.nb-1],"Content-Type","application/json"); +#ifdef CALLBACK_DEBUG + curl_easy_setopt(hInternet.ihandle[hInternet.nb-1].handle, CURLOPT_VERBOSE, 1); +#endif + if(hInternet.ihandle[hInternet.nb-1].header!=NULL) + curl_easy_setopt(hInternet.ihandle[hInternet.nb-1].handle,CURLOPT_HTTPHEADER,hInternet.ihandle[hInternet.nb-1].header); + processDownloads(&hInternet); + freeMaps(&tmpConf); + free(tmpConf); +#ifdef CALLBACK_DEBUG + char *tmp = (char *) malloc ((hInternet.ihandle[0].nDataLen + 1) + * sizeof (char)); + if (tmp == NULL) + { + setMapInMaps(arg->conf,"lenv","message",_("Unable to allocate memory")); + setMapInMaps(arg->conf,"lenv","code","InternalError"); + return NULL; + } + size_t bRead; + InternetReadFile (hInternet.ihandle[0], + (LPVOID) tmp, + hInternet. + ihandle[0].nDataLen, + &bRead); + tmp[hInternet.ihandle[0].nDataLen] = 0; + fprintf(stderr,"************************* From thread %d %s %d: REQUEST END \n%s",pthread_self(),__FILE__,__LINE__,tmp); + fflush(stderr); + free(tmp); +#endif + json_object_put(arg->res); + InternetCloseHandle(&hInternet); + isOngoing=0; + freeMaps(&arg->conf); + free(arg->conf); + freeMap(&arg->url); + if(arg->url!=NULL) + free(arg->url); + pthread_exit(NULL); + } + + /** + * Invoke the callback in case there is a [subscriber] section containing one + * or more url parameter. + * + * @param conf the maps containing the main configuration file definitions + * @param state the service state SERVICE_SUCCEEDED / STARTED / FAILED + * @return bool true in case of success, false in other cases + */ + bool invokeBasicCallback(maps* conf,int state){ + map* url=getMapFromMaps(conf,"subscriber","inProgressUri"); + if(state==SERVICE_SUCCEEDED) + url=getMapFromMaps(conf,"subscriber","successUri"); + else + if(state==SERVICE_FAILED) + url=getMapFromMaps(conf,"subscriber","failedUri"); + if(url==NULL) + return false; + map* url0=createMap("url",url->value); + map* sname=getMapFromMaps(conf,"lenv","identifier"); + if(sname!=NULL && isProhibited(conf,sname->value)) + return false; + if(statevalue); + } + }else + res=createStatus(conf,state); + if(local_arguments==NULL) + local_arguments=(local_params**)malloc(sizeof(local_params*)); + else + local_arguments=(local_params**)realloc(local_arguments,(nbThreads+1)*sizeof(local_params*)); + local_arguments[nbThreads]=(local_params*)malloc(MAPS_SIZE+MAP_SIZE+sizeof(json_object*)+(2*sizeof(int))); + local_arguments[nbThreads]->conf=dupMaps(&conf); + local_arguments[nbThreads]->url=url0; + local_arguments[nbThreads]->res=res; + local_arguments[nbThreads]->step=0; + local_arguments[nbThreads]->state=state; + cStep=state; + if(myThreads==NULL) + myThreads=(pthread_t*)malloc((nbThreads+1)*sizeof(pthread_t)); + else + myThreads=(pthread_t*)realloc(myThreads,(nbThreads+1)*sizeof(pthread_t)); + if(pthread_create(&myThreads[nbThreads], NULL, _invokeBasicCallback, (void*)local_arguments[nbThreads])==-1){ + setMapInMaps(conf,"lenv","message",_("Unable to create a new thread")); + return false; + } + nbThreads++; + } + return true; + } + +#ifdef USE_CALLBACK + /** + * Practically invoke the callback, meaning sending the HTTP POST request. + * + * @param args local_params containing all the variables required + */ + void* _invokeCallback(void* args){ + local_params* arg=(local_params*)args; + HINTERNET hInternet,res1; + const struct tm *tm; + size_t len; + time_t now; + char *tmp1; + map *tmpStatus; + maps* tmpConf=createMaps("main"); + tmpConf->content=createMap("memory","load"); + hInternet=InternetOpen("ZooWPSClient\0", + INTERNET_OPEN_TYPE_PRECONFIG, + NULL,NULL, 0); + if(!CHECK_INET_HANDLE(hInternet)){ + InternetCloseHandle (&hInternet); + return NULL; + } + char *URL=(char*)malloc((strlen(arg->url->value)+5)*sizeof(char)); + sprintf(URL,"%s%d_%d/",arg->url->value,arg->step,arg->state); + const char* jsonStr=json_object_to_json_string_ext(arg->res,JSON_C_TO_STRING_PLAIN); + hInternet.waitingRequests[0] = zStrdup(URL); + free(URL); +#ifdef CALLBACK_DEBUG + now = time ( NULL ); + tm = localtime ( &now ); + tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char)); + len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm ); + fprintf(stderr,"************************* From thread %d %s %d: REQUEST PARAMETERS cStep %d %d\n",pthread_self(),__FILE__,__LINE__,cStep,isOngoing); + fprintf(stderr," * JSON: [%s] \n",jsonStr); + fprintf(stderr," * URL: %s/ \n\n",hInternet.waitingRequests[0]); + fprintf(stderr," * DATE: %s/ \n\n",tmp1); + fprintf(stderr,"************************* From thread %d %s %d: REQUEST PARAMETERS\n",pthread_self(),__FILE__,__LINE__); + free(tmp1); +#endif + while( (arg->step!=7 || isOngoing>0) && + ( cStep!=arg->step || (arg->state!=0 && steps[arg->step][0]==false) ) + ){ + zSleep(100); + } + isOngoing=1; +#ifdef CALLBACK_DEBUG + fprintf(stderr,"************************* From thread %d %s %d: REQUEST START\n\n",pthread_self(),__FILE__,__LINE__); + int i=0; + for(i=0;i<7;i++){ + fprintf(stderr,"%d) %d %d\n",i,steps[i][0],steps[i][1]); + } +#endif + + now = time ( NULL ); + tm = localtime ( &now ); + + tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char)); + len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm ); + +#ifdef CALLBACK_DEBUG + fprintf(stderr,"************************* From thread %d %s %d: REQUEST START (%s)\n",pthread_self(),__FILE__,__LINE__,tmp1); + fflush(stderr); +#endif + free(tmp1); + res1 = InternetOpenUrl (&hInternet, + hInternet.waitingRequests[0], + (char*)jsonStr, strlen(jsonStr), + INTERNET_FLAG_NO_CACHE_WRITE, + 0,tmpConf); + AddHeaderEntries(&hInternet,arg->conf); + //curl_easy_setopt(hInternet.ihandle[hInternet.nb].handle, CURLOPT_VERBOSE, 1);x + processDownloads(&hInternet); + freeMaps(&tmpConf); + free(tmpConf); + now = time ( NULL ); + tm = localtime ( &now ); + tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char)); + len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm ); + +#ifdef CALLBACK_DEBUG + fprintf(stderr,"************************* From thread %d %s %d: REQUEST END (%s)\n\n",pthread_self(),__FILE__,__LINE__,tmp1); +#endif + free(tmp1); + char *tmp = (char *) malloc ((hInternet.ihandle[0].nDataLen + 1) + * sizeof (char)); + if (tmp == NULL) + { + setMapInMaps(arg->conf,"lenv","message",_("Unable to allocate memory")); + setMapInMaps(arg->conf,"lenv","code","InternalError"); + return NULL; + } + size_t bRead; + InternetReadFile (hInternet.ihandle[0], + (LPVOID) tmp, + hInternet. + ihandle[0].nDataLen, + &bRead); + tmp[hInternet.ihandle[0].nDataLen] = 0; + json_object_put(arg->res); + InternetCloseHandle(&hInternet); + isOngoing=0; + if(cStep==0 || cStep==6 || arg->state==1) + cStep=arg->step+1; +#ifdef CALLBACK_DEBUG + now = time ( NULL ); + tm = localtime ( &now ); + tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char)); + len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm ); + fprintf(stderr,"************************* From thread %d %s %d: RESPONSE CONTENT (%s)\n",pthread_self(),__FILE__,__LINE__,tmp1); + for(i=0;i<7;i++){ + fprintf(stderr,"%d) %d %d\n",i,steps[i][0],steps[i][1]); + } + fprintf(stderr,"Result: \n%s\n\n",tmp); + fprintf(stderr,"************************* From thread %d %s %d\n\n",pthread_self(),__FILE__,__LINE__); + fflush(stderr); + free(tmp1); +#endif + steps[arg->step][arg->state]=true; + free(tmp); +#ifdef CALLBACK_DEBUG + fprintf(stderr,"************************* From thread %d %s %d: EXIT\n\n",pthread_self(),__FILE__,__LINE__); + fflush(stderr); +#endif + pthread_exit(NULL); + } + + /** + * Invoke the callback in case there is a [callback] section containing a url parameter + * + * @param m the maps containing the main configuration file definitions + * @param inputs the inputs defined in the request (can be null if not yet initialized) + * @param inputs the outputs provided in the request (can be null if not yet initialized) + * @param step the step number, steps are defined as: + * 0: Analyze creation + * 1: Fetching Data Inputs + * 2: Uploading data inputs to cluster + * 3: Creating Job Script + * 4: Submitting Job to Cluster + * 5: Downloading processed output from cluster + * 6: Finalize + * 7: Dismiss or Error + * @param state 0 in case the step starts, 1 when it ends + * @return bool true in case of success, false in other cases + */ + bool invokeCallback(maps* conf,maps* inputs,maps* outputs,int step,int state){ + map* url=getMapFromMaps(conf,"callback","url"); + if(url==NULL) + return false; + + maps* lenv=getMaps(conf,"lenv"); + map* sname=getMap(lenv->content,"identifier"); + if(sname!=NULL && isProhibited(conf,sname->value)) + return false; + + json_object *res=json_object_new_object(); + + map* sid=getMapFromMaps(conf,"lenv","usid"); + if(sid!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + json_object_object_add(res,"jobid",jsStr); + } + const struct tm *tm; + size_t len; + time_t now; + char *tmp1; + map *tmpStatus; + + now = time ( NULL ); + tm = localtime ( &now ); + + tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char)); + len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%H:%M:%SZ", tm ); + json_object *jsStr0=json_object_new_string(tmp1); + json_object_object_add(res,"datetime",jsStr0); + free(tmp1); + + switch(step){ + case 0: { + // Create a new analyze + maps* lenv=getMaps(conf,"lenv"); + sid=getMapFromMaps(conf,"renv","xrequest"); + if(sid!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + json_object_object_add(res,"request_execute_content",jsStr); + } + sid=getMapFromMaps(conf,"lenv","identifier"); + if(sid!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + json_object_object_add(res,"process_identifier",jsStr); + } + // Save the Execute request on disk + map* tmpPath=getMapFromMaps(conf,"main","tmpPath"); + map* req=getMapFromMaps(conf,"renv","xrequest"); + sid=getMapFromMaps(conf,"lenv","usid"); + char* executePath=(char*)malloc((strlen(tmpPath->value)+strlen(sid->value)+14)*sizeof(char)); + sprintf(executePath,"%s/execute_%s.xml",tmpPath->value,sid->value); + FILE* saveExecute=fopen(executePath,"wb"); + fwrite(req->value,1,strlen(req->value)*sizeof(char),saveExecute); + fflush(saveExecute); + fclose(saveExecute); + setMapInMaps(conf,"lenv","execute_file",executePath); + free(executePath); + break; + } + + case 1: { + // Update the execute request stored on disk at step 0,0 to modify the references used. + if(state==1){ + maps* curs=inputs; + xmlInitParser(); + map* xmlPath=getMapFromMaps(conf,"lenv","execute_file"); + while(curs!=NULL){ + map* length=getMap(curs->content,"length"); + map* useMS=getMap(curs->content,"useMapserver"); + if(length==NULL){ + addToMap(curs->content,"length","1"); + length=getMap(curs->content,"length"); + } + int len=atoi(length->value); + for(int ii=0;iicontent,"byValue",ii)!=NULL && getMapArray(curs->content,"mimeType",ii)!=NULL && useMS!=NULL && strncasecmp(useMS->value,"true",4)==0){ + map* tmpMap=getMapArray(curs->content,"value",ii); + char tmpStr[100]; + sprintf(tmpStr,"%ld",strlen(tmpMap->value)); + setMapArray(curs->content,"size",ii,tmpStr); + tmpMap=getMapArray(curs->content,"mimeType",ii); + setMapArray(curs->content,"fmimeType",ii,tmpMap->value); + tmpMap=getMapArray(curs->content,"cache_file",ii); + setMapArray(curs->content,"generated_file",ii,tmpMap->value); + setMapArray(curs->content,"storage",ii,tmpMap->value); + setReferenceUrl(conf,curs); + addIntToMap(curs->content,"published_id",ii+1); + const char *params[7]; + int xmlLoadExtDtdDefaultValue; + int hasFile=-1; + map* xslPath=getMapFromMaps(conf,"callback","template"); + map* filePath=getMapArray(curs->content,"ref_wfs_link",ii); + if(filePath==NULL) + filePath=getMap(curs->content,"ref_wcs_link"); + char* inputName=curs->name; + if(xslPath==NULL || xmlPath==NULL || filePath==NULL) + break; + char *tmpParam=(char*)malloc((strlen(curs->name)+11)*sizeof(char)); + char *tmpParam1=(char*)malloc((strlen(filePath->value)+11)*sizeof(char)); + char tmpParam2[16]; + sprintf(tmpParam2,"string(\"%d\")",ii); + setMapArray(curs->content,"href",ii,filePath->value); + setMapArray(curs->content,"xlink:href",ii,filePath->value); + tmpMap=getMapArray(curs->content,"cache_url",ii); + if(tmpMap!=NULL) + setMapArray(curs->content,"xlink:href",ii,tmpMap->value); + else + setMapArray(curs->content,"xlink:href",ii,filePath->value); + sprintf(tmpParam,"string(\"%s\")",curs->name); + sprintf(tmpParam1,"string(\"%s\")",filePath->value); + sprintf(tmpParam2,"string(\"%d\")",ii); + params[0]="attr"; + params[1]=tmpParam; + params[2]="value"; + params[3]=tmpParam1;//filePath->value; + params[4]="cnt"; + params[5]=tmpParam2; + params[6]=NULL; + fprintf(stderr, "## XSLT PARAMETERS ATTR: %s VALUE: %s INDEX: %s\n", + tmpParam,tmpParam1,tmpParam2); + fflush(stderr); + xmlSubstituteEntitiesDefault(1); + xmlLoadExtDtdDefaultValue = 0; + xsltStylesheetPtr cur = NULL; + xmlDocPtr doc, res; + cur = xsltParseStylesheetFile(BAD_CAST xslPath->value); + doc = xmlParseFile(xmlPath->value); + fflush(stderr); + res = xsltApplyStylesheet(cur, doc, params); + xmlChar *xmlbuff; + int buffersize; + xmlDocDumpFormatMemory(res, &xmlbuff, &buffersize, 1); + // Store the executeRequest in file again + free(tmpParam); + free(tmpParam1); + fprintf(stderr," # Request / XSLT: %s\n",xmlbuff); + fflush(stderr); + FILE* saveExecute=fopen(xmlPath->value,"wb"); + if(saveExecute!=NULL){ + fwrite(xmlbuff,1,buffersize,saveExecute); + fflush(saveExecute); + fclose(saveExecute); + } + xmlFree(xmlbuff); + xmlFreeDoc(doc); + xsltFreeStylesheet(cur); + } + } + addIntToMap(curs->content,"published_id",0); + curs=curs->next; + } + xmlCleanupParser(); + FILE* f0=fopen(xmlPath->value,"rb"); + if(f0!=NULL){ + long flen; + char *fcontent; + fseek (f0, 0, SEEK_END); + flen = ftell (f0); + fseek (f0, 0, SEEK_SET); + fcontent = (char *) malloc ((flen + 1) * sizeof (char)); + fread(fcontent,flen,1,f0); + fcontent[flen]=0; + fclose(f0); + map *schema=getMapFromMaps(conf,"database","schema"); + map* sid=getMapFromMaps(conf,"lenv","usid"); + char *req=(char*)malloc((flen+strlen(schema->value)+strlen(sid->value)+66)*sizeof(char)); + sprintf(req,"UPDATE %s.services set request_execute_content=$$%s$$ WHERE uuid=$$%s$$",schema->value,fcontent,sid->value); +#ifdef RELY_ON_DB + execSql(conf,1,req); +#endif + free(fcontent); + free(req); + } + } + + // Fetching data inputs + maps* curs=inputs; + dumpMaps(curs); + const char *keys[11][2]={ + { + "xlink:href", + "ref_download_link" + }, + { + "cache_file", + "cachefile" + }, + { + "fmimeType", + "mimetype" + }, + { + "size", + "size" + }, + { + "ref_wms_link", + "ref_wms_link" + }, + { + "ref_wfs_link", + "ref_wfs_link" + }, + { + "ref_wcs_link", + "ref_wcs_link" + }, + { + "ref_wcs_link", + "ref_wcs_link" + }, + { + "ref_wcs_preview_link", + "ref_wcs_preview_link" + }, + { + "geodatatype", + "datatype" + }, + { + "wgs84_extent", + "boundingbox" + } + }; + json_object *res1=json_object_new_object(); + while(curs!=NULL){ + if(getMap(curs->content,"length")==NULL){ + addToMap(curs->content,"length","1"); + } + map* length=getMap(curs->content,"length"); + int len=atoi(length->value); + json_object *res3; + int hasRef=-1; + for(int ii=0;iicontent,"cache_file",ii); + sid=getMapArray(curs->content,"ref_wms_link",ii); + json_object *res2=json_object_new_object(); + if(tmpMap!=NULL){ + if(sid==NULL){ + setMapArray(curs->content,"generated_file",ii,tmpMap->value); + setMapArray(curs->content,"storage",ii,tmpMap->value); + } + struct stat buf; + char timeStr[ 100 ] = ""; + if (stat(tmpMap->value, &buf)==0){ + strftime(timeStr, 100, "%d-%m-%Y %H:%M:%S", localtime( &buf.st_mtime)); + json_object *jsStr=json_object_new_string(timeStr); + json_object_object_add(res2,"creation_date",jsStr); + } + tmpMap=getMapArray(curs->content,"fmimeType",ii); + if(tmpMap!=NULL){ + setMapArray(curs->content,"mimeType",ii,tmpMap->value); + } + setReferenceUrl(conf,curs); + }else{ + } + addIntToMap(curs->content,"published_id",ii+1); + int i=0; + for(;i<11;i++){ + sid=getMapArray(curs->content,keys[i][0],ii); + if(sid!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + json_object_object_add(res2,keys[i][1],jsStr); + if(i==0){ + hasRef=1; + json_object *jsStr1=json_object_new_string(getProvenance(conf,sid->value)); + json_object_object_add(res2,"dataOrigin",jsStr1); + } + } + } + if(len>1){ + if(ii==0) + res3=json_object_new_array(); + json_object_array_add(res3,res2); + }else + res3=res2; + } + if(hasRef<0) + json_object_put(res3); + else{ + json_object_object_add(res1,curs->name,json_object_get(res3)); + json_object_put(res3); + } + addIntToMap(curs->content,"published_id",0); + curs=curs->next; + } + json_object_object_add(res,"inputs",res1); + break; + } + + case 2: { + // Uploading data input to cluster + maps* in=getMaps(conf,"uploadQueue"); + if(in!=NULL){ + maps* curs=in; + map* length=getMapFromMaps(in,"uploadQueue","length"); + if(length!=NULL){ + json_object *res1=json_object_new_object(); + int limit=atoi(length->value); + int i=0; + maps* uploadQueue=getMaps(in,"uploadQueue"); + map* tmp=uploadQueue->content; + for(;ivalue); + json_object_object_add(res2,"local_path",jsStr); + jsStr=json_object_new_string(tmp2->value); + json_object_object_add(res2,"target_path",jsStr); + json_object *res4=NULL; + if(json_object_object_get_ex(res1,tmp0->value,&res4)!=FALSE){ + if(json_object_is_type(res4,json_type_null)){ + json_object_object_add(res1,tmp0->value,res2); + }else{ + if(json_object_is_type(res4,json_type_object) && !json_object_is_type(res4, json_type_array)){ + json_object *res3=json_object_new_array(); + json_object_array_add(res3,json_object_get(res4)); + json_object_array_add(res3,res2); + json_object_object_del(res1,tmp0->value); + json_object_object_add(res1,tmp0->value,res3); + }else + json_object_array_add(res4,res2); + } + } + } + } + json_object_object_add(res,"inputs",res1); + } + } + break; + } + + case 3: { + // Generating job script + sid=getMapFromMaps(conf,"lenv","local_script"); + if(sid!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + json_object_object_add(res,"script",jsStr); + } + break; + } + + case 4: { + // Submitting job to cluster + sid=getMapFromMaps(conf,"lenv","remote_script"); + if(sid!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + json_object_object_add(res,"script",jsStr); + } + break; + } + + case 5: { + // Downloading process outputs from cluster + maps* curs=outputs; + dumpMaps(curs); + const char *keys[10][2]={ + { + "Reference", + "ref" + }, + { + "generated_file", + "cachefile" + }, + { + "mimeType", + "mimetype" + }, + { + "size", + "size" + }, + { + "geodatatype", + "datatype" + }, + { + "wgs84_extent", + "boundingbox" + }, + { + "ref_wms_link", + "ref_wms_link" + }, + { + "ref_wcs_link", + "ref_wcs_link" + }, + { + "ref_wcs_preview_link", + "ref_wcs_preview_link" + }, + { + "ref_wfs_link", + "ref_wfs_link" + } + }; + const char* specifics[5][2]={ + { + "download_link", + "ref_download_link" + }, + { + "wms_link", + "ref_wms_link" + }, + { + "wfs_link", + "ref_wfs_link" + }, + { + "wcs_link", + "ref_wcs_link" + }, + { + "wcs_link", + "ref_wcs_preview_link" + } + }; + json_object *res1=json_object_new_object(); + while(curs!=NULL){ + json_object *res2=json_object_new_object(); + int i=0; + int hasRef=-1; + for(;i<10;i++){ + sid=getMap(curs->content,keys[i][0]); + if(sid!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + json_object_object_add(res2,keys[i][1],jsStr); + if(i==0){ + hasRef=1; + json_object_object_add(res2,"ref_download_link",jsStr); + } + if(i==1){ + struct stat buf; + char timeStr[ 100 ] = ""; + if (stat(sid->value, &buf)==0){ + strftime(timeStr, 100, "%d-%m-%Y %H:%M:%S", localtime( &buf.st_mtime)); + json_object *jsStr=json_object_new_string(timeStr); + json_object_object_add(res2,"creation_date",jsStr); + } + } + } + } + if(hasRef>0) + json_object_object_add(res1,curs->name,res2); + else{ + maps* curs0=curs->child; + int i=0; + int bypass=-1; + for(i=0;i<5;i++){ + maps* specificMaps; + if((specificMaps=getMaps(curs0,specifics[i][0]))!=NULL){ + int hasRef0=-1; + int i0=0; + for(;i0<6;i0++){ + sid=getMap(specificMaps->content,keys[i0][0]); + if(sid!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + if(i0==0){ + json_object_object_add(res2,specifics[i][1],jsStr); + } + else + json_object_object_add(res2,keys[i0][1],jsStr); + hasRef0=1; + bypass=1; + if(i==1){ + struct stat buf; + char timeStr[ 100 ] = ""; + if (stat(sid->value, &buf)==0){ + strftime(timeStr, 100, "%d-%m-%Y %H:%M:%S", localtime( &buf.st_mtime)); + json_object *jsStr=json_object_new_string(timeStr); + json_object_object_add(res2,"creation_date",jsStr); + } + } + } + } + } + } + if(bypass<0) + while(curs0!=NULL){ + json_object *res3=json_object_new_object(); + int i0=0; + int hasRef0=-1; + for(;i0<10;i0++){ + sid=getMap(curs0->content,keys[i0][0]); + if(sid!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + json_object_object_add(res3,keys[i0][1],jsStr); + hasRef0=1; + } + } + if(hasRef0<0) + json_object_put(res3); + else + json_object_object_add(res2,curs0->name,res3); + curs0=curs0->next; + } + json_object_object_add(res1,curs->name,res2); + } + curs=curs->next; + } + json_object_object_add(res,"outputs",res1); + break; + } + + case 6: { + // Finalize HPC + const char *keys[6][2]={ + { + //"SubmitTime", + "Submit", + "hpc_submission_date" + }, + { + "JobId", + "hpc_job_identifier" + }, + { + "JobName", + "hpc_job_name" + }, + { + //"StartTime", + "Start", + "hpc_start_date" + }, + { + //"EndTime", + "End", + "hpc_end_date" + }, + { + //"JobState", + "State", + "hpc_status" + } + }; + int i=0; + if(getMaps(conf,"henv")!=NULL){ + for(i=0;i<6;i++){ + sid=getMapFromMaps(conf,"henv",keys[i][0]); + if(sid!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + json_object_object_add(res,keys[i][1],jsStr); + } + } + } + if((sid=getMapFromMaps(conf,"henv","billing_nb_cpu"))!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + json_object_object_add(res,"hpc_cpu_usage",jsStr); + }else{ + json_object *jsStr=json_object_new_string("1"); + json_object_object_add(res,"hpc_cpu_usage",jsStr); + } + json_object *jsStr=json_object_new_string("succeeded"); + json_object_object_add(res,"wps_status",jsStr); + break; + } + + case 7: { + // Error or Dismiss + sid=getMapFromMaps(conf,"lenv","message"); + if(sid!=NULL){ + json_object *jsStr=json_object_new_string(sid->value); + json_object_object_add(res,"message",jsStr); + } + json_object *jsStr; + if(state==1) + jsStr=json_object_new_string("dismissed"); + else + jsStr=json_object_new_string("failed"); + json_object_object_add(res,"wps_status",jsStr); + break; + } + others: { + break; + } + } + + if(local_arguments==NULL) + local_arguments=(local_params**)malloc(sizeof(local_params*)); + else + local_arguments=(local_params**)realloc(local_arguments,(nbThreads+1)*sizeof(local_params*)); + local_arguments[nbThreads]=(local_params*)malloc(MAPS_SIZE+MAP_SIZE+sizeof(json_object*)+(2*sizeof(int))); + local_arguments[nbThreads]->conf=conf; + local_arguments[nbThreads]->url=url; + local_arguments[nbThreads]->res=res; + local_arguments[nbThreads]->step=step; + local_arguments[nbThreads]->state=state; + if(myThreads==NULL) + myThreads=(pthread_t*)malloc((nbThreads+1)*sizeof(pthread_t)); + else + myThreads=(pthread_t*)realloc(myThreads,(nbThreads+1)*sizeof(pthread_t)); + if(pthread_create(&myThreads[nbThreads], NULL, _invokeCallback, (void*)local_arguments[nbThreads])==-1){ + setMapInMaps(conf,"lenv","message",_("Unable to create a new thread")); + return false; + } + nbThreads++; + return true; + } +#endif + + /** + * Wait for the threads to end then, clean used memory. + */ + void cleanupCallbackThreads(){ + while( isOngoing>0 ){ + zSleep(100); + } + int i=0; + for(i=0;i + +#ifdef __cplusplus +extern "C" { +#endif + + bool invokeBasicCallback(maps*,int); +#ifdef USE_CALLBACK + bool invokeCallback(maps*,maps*,maps*,int,int); +#endif + void cleanupCallbackThreads(); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_json.c b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_json.c index bcac4056..51a3abc4 100644 --- a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_json.c +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_json.c @@ -1,7 +1,7 @@ /* * Author : Gérald FENOY * - * Copyright 2017-2019 GeoLabs SARL. All rights reserved. + * Copyright 2017-2022 GeoLabs SARL. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,29 +26,70 @@ #include "json.h" #include #include "json_tokener.h" +#include "json_object.h" +#include "json.h" #include "stdlib.h" #include "mimetypes.h" #include "server_internal.h" #include "service_internal.h" +#ifdef USE_MS +#include "service_internal_ms.h" +#endif #include -#include -#include - - #ifdef __cplusplus extern "C" { #endif + /** - * Equivalent range keywords for WPS version 1 and 2 + * Convert a json object to maps + * + * @param jopObj the json object to convert + * @return the allocated maps */ - const char* rangeCorrespondances[4][2]={ - { "rangeMin", "minimumValue" }, - { "rangeMax", "maximumValue"}, - { "rangeSpacing", "spacing" }, - { "rangeClosure", "rangeClosure" } - }; + maps* jsonToMaps(json_object* jopObj){ + maps* res=NULL; + //enum json_type type; + json_object_object_foreach(jopObj, key, val) { /*Passing through every object element*/ + json_object* json_input=NULL; + if(json_object_object_get_ex(jopObj, key, &json_input)!=FALSE){ + map* tmpMap=jsonToMap(json_input); + if(res==NULL){ + res=createMaps(key); + addMapToMap(&(res->content),tmpMap); + }else{ + maps *tres=createMaps(key); + addMapToMap(&(tres->content),tmpMap); + addMapsToMaps(&res,tres); + freeMaps(&tres); + free(tres); + } + } + } + return res; + } + /** + * Convert a json object to map + * + * @param jopObj the json object to convert + * @return the allocated map + */ + map* jsonToMap(json_object* jopObj){ + map* res=NULL; + json_object_object_foreach(jopObj, key, val) { + if(val!=NULL && json_object_is_type (val,json_type_string)){ + const char* pcVal=json_object_get_string(val); + if(strlen(pcVal)>0){ + if(res==NULL) + res=createMap(key,pcVal); + else + addToMap(res,key,pcVal); + } + } + } + return res; + } /** * Convert a map to a json object @@ -60,16 +101,27 @@ extern "C" { map* cursor=myMap; map* sizeMap=getMap(myMap,"size"); map* length=getMap(myMap,"length"); + map* toLoad=getMap(myMap,"to_load"); while(cursor!=NULL){ json_object *val=NULL; - if(length==NULL && sizeMap==NULL) - val=json_object_new_string(cursor->value); + if(length==NULL && sizeMap==NULL){ + if(strstr(cursor->name,"title")!=NULL) + val=json_object_new_string(_(cursor->value)); + else + val=json_object_new_string(cursor->value); + } else{ if(length==NULL && sizeMap!=NULL){ - if(strncasecmp(cursor->name,"value",5)==0) - val=json_object_new_string_len(cursor->value,atoi(sizeMap->value)); - else - val=json_object_new_string(cursor->value); + if(strncasecmp(cursor->name,"value",5)==0){ + if(strlen(cursor->value)!=0 && toLoad!=NULL && strncasecmp(toLoad->value,"true",4)==0) + val=json_object_new_string_len(cursor->value,atoi(sizeMap->value)); + } + else{ + if(strstr(cursor->name,"title")!=NULL) + val=json_object_new_string(_(cursor->value)); + else + val=json_object_new_string(cursor->value); + } } else{ // In other case we should consider array with potential sizes @@ -78,10 +130,15 @@ extern "C" { val=json_object_new_array(); for(i=0;iname,"value",5)==0){ - json_object_array_add(val,json_object_new_string_len(cursor->value,atoi(sizeMap->value))); + if(strlen(cursor->value)!=0 && toLoad!=NULL && strncasecmp(toLoad->value,"true",4)==0) + json_object_array_add(val,json_object_new_string_len(cursor->value,atoi(sizeMap->value))); }else{ - json_object_array_add(val,json_object_new_string(cursor->value)); + if(strstr(cursor->name,"title")!=NULL) + json_object_array_add(val,json_object_new_string(_(cursor->value))); + else + json_object_array_add(val,json_object_new_string(cursor->value)); } } } @@ -147,7 +204,7 @@ extern "C" { } json_object_object_add(cres,"supported",resi); } - + json_object_object_add(cres,"child",elementsToJson(cur->child)); json_object_object_add(res,cur->name,cres); @@ -155,9 +212,10 @@ extern "C" { } return res; } - + /** * Convert an service to a json object + * * @param myService the service pointer to be converted into a json object * @return a json_object pointer to the created json_object */ @@ -174,6 +232,7 @@ extern "C" { /** * Add Allowed Range properties to a json_object + * * @param m the main configuration maps pointer * @param iot the iotype pointer * @param prop the json_object pointer to add the allowed range properties @@ -181,75 +240,130 @@ extern "C" { */ void printAllowedRangesJ(maps* m,iotype* iot,json_object* prop){ map* tmpMap1; + map* pmType=getMap(iot->content,"DataType"); json_object* prop4=json_object_new_object(); + int hasMin=0; + int hasMax=0; for(int i=0;i<4;i++){ tmpMap1=getMap(iot->content,rangeCorrespondances[i][0]); if(tmpMap1!=NULL){ - if(i<3) - json_object_object_add(prop4,rangeCorrespondances[i][1],json_object_new_string(tmpMap1->value)); + if(i>=1 && ( (hasMin==0 && i==1) || (hasMax==0 && i==2)) ){ + map* pmaTmp=createMap("value",tmpMap1->value); + printLiteralValueJ(m,pmType,pmaTmp,prop,rangeCorrespondances[i][1]); + freeMap(&pmaTmp); + free(pmaTmp); + } else{ - char* currentValue=NULL; - int limit=strlen(tmpMap1->value); - for(int j=0;jvalue[j]=='o'){ - tmpS="open"; + char* currentValue=NULL; + map* pmTmp=getMap(iot->content,rangeCorrespondances[1][0]); + if(tmpMap1->value[0]=='o' && pmTmp!=NULL){ + hasMin=1; + map* pmaTmp=createMap("value",pmTmp->value); + printLiteralValueJ(m,pmType,pmaTmp,prop,"exclusiveMinimum"); + freeMap(&pmaTmp); + free(pmaTmp); + if(strlen(tmpMap1->value)==1){ + pmTmp=getMap(iot->content,rangeCorrespondances[2][0]); + if(pmTmp!=NULL){ + hasMax=1; + map* pmaTmp1=createMap("value",pmTmp->value); + printLiteralValueJ(m,pmType,pmaTmp1,prop,"exclusiveMaximum"); + freeMap(&pmaTmp1); + free(pmaTmp1); + } } - if(currentValue==NULL){ - currentValue=(char*)malloc((strlen(tmpS)+1)*sizeof(char)); - sprintf(currentValue,"%s",tmpS); - }else{ - char* tmpS1=zStrdup(currentValue); - currentValue=(char*)realloc(currentValue,(strlen(tmpS1)+strlen(tmpS)+2)*sizeof(char)); - sprintf(currentValue,"%s-%s",tmpS1,tmpS); + } + if(strlen(tmpMap1->value)>1 && tmpMap1->value[1]=='o'){ + pmTmp=getMap(iot->content,rangeCorrespondances[2][0]); + if(pmTmp!=NULL){ + hasMax=1; + map* pmaTmp=createMap("value",pmTmp->value); + printLiteralValueJ(m,pmType,pmaTmp,prop,"exclusiveMaximum"); + freeMap(&pmaTmp); + free(pmaTmp); } } - json_object_object_add(prop4,rangeCorrespondances[i][1],json_object_new_string(currentValue)); } } } - json_object_array_add(prop,prop4); } + /** + * Add literal property depending on the dataType + * + * @param pmConf the main configuration maps pointer + * @param pmType the dataType map pointer + * @param pmContent the iotype content map pointer + * @param schema the json_object pointer to add the value + * @param field the field name string + */ + void printLiteralValueJ(maps* pmConf,map* pmType,map* pmContent,json_object* schema,const char* field){ + map* pmTmp=getMap(pmContent,"value"); + if(pmTmp!=NULL) + if(pmType!=NULL && strncasecmp(pmType->value,"integer",7)==0) + json_object_object_add(schema,field,json_object_new_int(atoi(pmTmp->value))); + else{ + if(pmType!=NULL && strncasecmp(pmType->value,"float",5)==0){ + json_object_object_add(schema,field,json_object_new_double(atof(pmTmp->value))); + json_object_object_add(schema,"format",json_object_new_string("double")); + } + else{ + if(pmType!=NULL && strncasecmp(pmType->value,"bool",4)==0){ + if(strncasecmp(pmType->value,"true",4)==0) + json_object_object_add(schema,field,json_object_new_boolean(true)); + else + json_object_object_add(schema,field,json_object_new_boolean(false)); + } + else + json_object_object_add(schema,field,json_object_new_string(pmTmp->value)); + } + } + } + /** * Add literalDataDomains property to a json_object + * * @param m the main configuration maps pointer * @param in the elements pointer * @param input the json_object pointer to add the literalDataDomains property * @return a json_object pointer to the created json_object */ void printLiteralDataJ(maps* m,elements* in,json_object* input){ - json_object* prop0=json_object_new_array(); - json_object* prop1=json_object_new_object(); - json_object* prop2=json_object_new_object(); + json_object* schema=json_object_new_object(); + map* pmMin=getMap(in->content,"minOccurs"); if(in->defaults!=NULL){ map* tmpMap1=getMap(in->defaults->content,"DataType"); if(tmpMap1!=NULL){ - json_object_object_add(prop2,"name",json_object_new_string(tmpMap1->value)); - json_object_object_add(prop1,"dataType",prop2); + if(strncasecmp(tmpMap1->value,"float",5)==0) + json_object_object_add(schema,"type",json_object_new_string("number")); + else + if(strncasecmp(tmpMap1->value,"bool",5)==0) + json_object_object_add(schema,"type",json_object_new_string("boolean")); + else + if(strstr(tmpMap1->value,"date")!=NULL){ + json_object_object_add(schema,"type",json_object_new_string("string")); + json_object_object_add(schema,"format",json_object_new_string(tmpMap1->value)); + } + else + json_object_object_add(schema,"type",json_object_new_string(tmpMap1->value)); } - tmpMap1=getMap(in->defaults->content,"value"); - if(tmpMap1!=NULL) - json_object_object_add(prop1,"defaultValue",json_object_new_string(tmpMap1->value)); - json_object* prop3=json_object_new_object(); + printLiteralValueJ(m,tmpMap1,in->defaults->content,schema,"default"); tmpMap1=getMap(in->defaults->content,"rangeMin"); if(tmpMap1!=NULL){ - json_object* prop5=json_object_new_array(); - printAllowedRangesJ(m,in->defaults,prop5); + printAllowedRangesJ(m,in->defaults,schema); if(in->supported!=NULL){ iotype* iot=in->supported; while(iot!=NULL){ - printAllowedRangesJ(m,iot,prop5); + printAllowedRangesJ(m,iot,schema); iot=iot->next; } } - json_object_object_add(prop3,"allowedRanges",prop5); } else{ tmpMap1=getMap(in->defaults->content,"range"); if(tmpMap1!=NULL){ - // TODO: parse range = [rangeMin,rangeMax] - }else{ + // TODO: parse range = [rangeMin,rangeMax] (require generic function) + }else{ // AllowedValues tmpMap1=getMap(in->defaults->content,"AllowedValues"); if(tmpMap1!=NULL){ @@ -260,21 +374,217 @@ extern "C" { json_object_array_add(prop5,json_object_new_string(tmps)); tmps = strtok_r (NULL, ",", &saveptr); } - json_object_object_add(prop3,"allowedValues",prop5); - + json_object_object_add(schema,"enum",prop5); }else{ - json_object_object_add(prop3,"anyValue",json_object_new_boolean(true)); + tmpMap1=getMap(in->defaults->content,"DataType"); + if(tmpMap1!=NULL && strncasecmp(tmpMap1->value,"string",6)==0){ + map* pmsLength=getMap(in->defaults->content,"length"); + if(pmsLength!=NULL){ + json_object* prop6=json_object_new_array(); + int len=atoi(pmsLength->value); + int i=0; + for(i=0;idefaults->content,"value",i); + if(pmsCurrent!=NULL) + json_object_array_add(prop6,json_object_new_string(pmsCurrent->value)); + } + json_object_object_add(schema,"default",prop6); + } + else + json_object_object_add(schema,"default",json_object_new_string("Any value")); + } } } } - json_object_object_add(prop1,"valueDefinition",prop3); - json_object_array_add(prop0,prop1); } - json_object_object_add(input,"literalDataDomains",prop0); + if(pmMin!=NULL && atoi(pmMin->value)==0) + json_object_object_add(schema,"nullable",json_object_new_boolean(true)); + json_object_object_add(input,"schema",schema); + } + + /** + * Add support in the extended-schema for links object + * + * @param m the main configuration maps pointer + * @param el the elements pointer + * @param res the json_object pointer on the array + * @param isDefault boolean, try if it is the default value + * @param maxSize map pointer (not used) + */ + void printComplexHref(maps* m,elements* el,json_object* res,bool isDefault,map* maxSize){ + if(el!=NULL && el->defaults!=NULL){ + json_object* prop=json_object_new_object(); + json_object* prop1=json_object_new_array(); + json_object* prop2=json_object_new_object(); + map* tmpMap0=getMapFromMaps(m,"openapi","link_href"); + if(tmpMap0!=NULL) + json_object_object_add(prop2,"$ref",json_object_new_string(tmpMap0->value)); + json_object_array_add(prop1,prop2); + json_object* prop3=json_object_new_object(); + json_object_object_add(prop3,"type",json_object_new_string("object")); + json_object* prop4=json_object_new_object(); + json_object* prop5=json_object_new_array(); + map* tmpMap2=getMap(el->defaults->content,"mimeType"); + if(tmpMap2!=NULL) + json_object_array_add(prop5,json_object_new_string(tmpMap2->value)); + iotype* sup=el->supported; + while(sup!=NULL){ + tmpMap2=getMap(sup->content,"mimeType"); + if(tmpMap2!=NULL) + json_object_array_add(prop5,json_object_new_string(tmpMap2->value)); + sup=sup->next; + } + json_object_object_add(prop4,"enum",prop5); + json_object* prop6=json_object_new_object(); + json_object_object_add(prop6,"type",prop4); + json_object_object_add(prop3,"properties",prop6); + json_object_array_add(prop1,prop3); + json_object_object_add(prop,"allOf",prop1); + json_object_array_add(res,prop); + } + } + + /** + * Add support for type array in extended-schema + * + * + * @param m the main configuration maps pointer + * @param el the elements pointer + */ + json_object* addArray(maps* m,elements* el){ + json_object* res=json_object_new_object(); + json_object_object_add(res,"type",json_object_new_string("array")); + map* tmpMap=getMap(el->content,"minOccurs"); + if(tmpMap!=NULL /*&& strcmp(tmpMap->value,"1")!=0*/){ + json_object_object_add(res,"minItems",json_object_new_int(atoi(tmpMap->value))); + }else{ + json_object_put(res); + res=NULL; + return res; + } + tmpMap=getMap(el->content,"maxOccurs"); + if(tmpMap!=NULL){ + if(atoi(tmpMap->value)>1){ + json_object_object_add(res,"maxItems",json_object_new_int(atoi(tmpMap->value))); + return res; + } + else{ + json_object_put(res); + res=NULL; + return res; + } + }else + return res; + } + + /** + * Add basic schema definition for the BoundingBox type + * + * @param m the main configuration maps pointer + * @param in the main configuration maps pointer + * @param input the json_object pointer used to store the schema definition + */ + void printBoundingBoxJ(maps* m,elements* in,json_object* input){ + map* pmMin=getMap(in->content,"minOccurs"); + json_object* prop20=json_object_new_object(); + json_object_object_add(prop20,"type",json_object_new_string("object")); + json_object* prop21=json_object_new_array(); + json_object_array_add(prop21,json_object_new_string("bbox")); + json_object_array_add(prop21,json_object_new_string("crs")); + json_object_object_add(prop20,"required",prop21); + + json_object* prop22=json_object_new_object(); + + json_object* prop23=json_object_new_object(); + json_object_object_add(prop23,"type",json_object_new_string("array")); + json_object* prop27=json_object_new_object(); + json_object* prop28=json_object_new_object(); + json_object* prop29=json_object_new_array(); + json_object_object_add(prop27,"minItems",json_object_new_int(4)); + json_object_object_add(prop27,"maxItems",json_object_new_int(4)); + json_object_array_add(prop29,prop27); + json_object_object_add(prop28,"minItems",json_object_new_int(6)); + json_object_object_add(prop28,"maxItems",json_object_new_int(6)); + json_object_array_add(prop29,prop28); + json_object_object_add(prop23,"oneOf",prop29); + json_object* prop24=json_object_new_object(); + json_object_object_add(prop24,"type",json_object_new_string("number")); + json_object_object_add(prop24,"format",json_object_new_string("double")); + json_object_object_add(prop23,"items",prop24); + json_object_object_add(prop22,"bbox",prop23); + + json_object* prop25=json_object_new_object(); + json_object_object_add(prop25,"type",json_object_new_string("string")); + json_object_object_add(prop25,"format",json_object_new_string("uri")); + + json_object* prop26=json_object_new_array(); + + map* tmpMap1=getMap(in->defaults->content,"crs"); + if(tmpMap1==NULL) + return; + json_object_array_add(prop26,json_object_new_string(tmpMap1->value)); + json_object_object_add(prop25,"default",json_object_new_string(tmpMap1->value)); + iotype* sup=in->supported; + while(sup!=NULL){ + tmpMap1=getMap(sup->content,"crs"); + if(tmpMap1!=NULL) + json_object_array_add(prop26,json_object_new_string(tmpMap1->value)); + sup=sup->next; + } + json_object_object_add(prop25,"enum",prop26); + + json_object_object_add(prop22,"crs",prop25); + + json_object_object_add(prop20,"properties",prop22); + if(pmMin!=NULL && atoi(pmMin->value)==0) + json_object_object_add(prop20,"nullable",json_object_new_boolean(true)); + json_object_object_add(input,"schema",prop20); } /** - * Add Format properties to a json_object + * Add schema property to a json_object (ComplexData) + * @param m the main configuration maps pointer + * @param iot the current iotype pointer + * @param res the json_object pointer to add the properties to + * @param isDefault boolean specifying if the currrent iotype is default + * @param maxSize a map pointer to the maximumMegabytes param defined in the zcfg file for this input/output + */ + void printFormatJ1(maps* m,iotype* iot,json_object* res,bool isDefault,map* maxSize){ + if(iot!=NULL){ + int i=0; + json_object* prop1=json_object_new_object(); + map* tmpMap1=getMap(iot->content,"encoding"); + map* tmpMap2=getMap(iot->content,"mimeType"); + map* tmpMap3=getMap(iot->content,"schema"); + if(tmpMap2!=NULL && (strncasecmp(tmpMap2->value,"application/json",16)==0 || strstr(tmpMap2->value,"json")!=NULL)){ + json_object_object_add(prop1,"type",json_object_new_string("object")); + if(tmpMap3!=NULL) + json_object_object_add(prop1,"$ref",json_object_new_string(tmpMap3->value)); + json_object_array_add(res,prop1); + return ; + } + //json_object* prop2=json_object_new_object(); + json_object_object_add(prop1,"type",json_object_new_string("string")); + if(tmpMap1!=NULL) + json_object_object_add(prop1,"contentEncoding",json_object_new_string(tmpMap1->value)); + else{ + json_object_object_add(prop1,"contentEncoding",json_object_new_string("base64")); + i=1; + } + if(tmpMap2!=NULL){ + json_object_object_add(prop1,"contentMediaType",json_object_new_string(tmpMap2->value)); + } + // TODO: specific handling of schema?! + if(tmpMap3!=NULL) + json_object_object_add(prop1,"contentSchema",json_object_new_string(tmpMap3->value)); + if(maxSize!=NULL) + json_object_object_add(prop1,"contentMaximumMegabytes",json_object_new_int64(atoll(maxSize->value))); + json_object_array_add(res,prop1); + } + } + + /** + * Add format properties to a json_object * @param m the main configuration maps pointer * @param iot the current iotype pointer * @param res the json_object pointer to add the properties to @@ -286,10 +596,10 @@ extern "C" { map* tmpMap1=getMap(iot->content,"mimeType"); json_object* prop1=json_object_new_object(); json_object_object_add(prop1,"default",json_object_new_boolean(isDefault)); - json_object_object_add(prop1,"mimeType",json_object_new_string(tmpMap1->value)); + json_object_object_add(prop1,"mediaType",json_object_new_string(tmpMap1->value)); tmpMap1=getMap(iot->content,"encoding"); if(tmpMap1!=NULL) - json_object_object_add(prop1,"encoding",json_object_new_string(tmpMap1->value)); + json_object_object_add(prop1,"characterEncoding",json_object_new_string(tmpMap1->value)); tmpMap1=getMap(iot->content,"schema"); if(tmpMap1!=NULL) json_object_object_add(prop1,"schema",json_object_new_string(tmpMap1->value)); @@ -317,7 +627,10 @@ extern "C" { strcasecmp(cmeta->name,"title")!=0 && strcasecmp(cmeta->name,"length")!=0 ){ json_object_object_add(jcmeta,"name",json_object_new_string(cmeta->name)); - json_object_object_add(jcmeta,"value",json_object_new_string(cmeta->value)); + if(strcasecmp(cmeta->name,"title")!=0) + json_object_object_add(jcmeta,"value",json_object_new_string(_(cmeta->value))); + else + json_object_object_add(jcmeta,"value",json_object_new_string(cmeta->value)); json_object_array_add(carr,jcmeta); hasElement++; }else{ @@ -329,6 +642,9 @@ extern "C" { if(hasElement>=0){ json_object_object_add(jcaps,"additionalParameter",carr); json_object_object_add(doc,"additionalParameters",jcaps); + }else{ + json_object_put(carr); + json_object_put(jcaps); } } @@ -347,7 +663,10 @@ extern "C" { if(strcasecmp(cmeta->name,"role")==0 || strcasecmp(cmeta->name,"href")==0 || strcasecmp(cmeta->name,"title")==0 ){ - json_object_object_add(jcmeta,cmeta->name,json_object_new_string(cmeta->value)); + if(strcasecmp(cmeta->name,"title")==0) + json_object_object_add(jcmeta,cmeta->name,json_object_new_string(_(cmeta->value))); + else + json_object_object_add(jcmeta,cmeta->name,json_object_new_string(cmeta->value)); hasElement++; } json_object_array_add(carr,jcmeta); @@ -355,12 +674,14 @@ extern "C" { } if(hasElement>=0) json_object_object_add(doc,"metadata",carr); + else + json_object_put(carr); } /** * Add metadata properties to a json_object * @param m the main configuration maps pointer - * @param io a string + * @param io a string * @param in an elements pointer to the current input/output * @param inputs the json_object pointer to add the property to * @param serv the service pointer to extract the metadata from @@ -368,67 +689,107 @@ extern "C" { void printIOTypeJ(maps* m, const char *io, elements* in,json_object* inputs,service* serv){ while(in!=NULL){ json_object* input=json_object_new_object(); - json_object_object_add(input,"id",json_object_new_string(in->name)); map* tmpMap=getMap(in->content,"title"); + map* pmMin=NULL; + map* pmMax=NULL; + if(strcmp(io,"input")==0){ + pmMin=getMap(in->content,"minOccurs"); + pmMax=getMap(in->content,"maxOccurs"); + } if(tmpMap!=NULL) - json_object_object_add(input,"title",json_object_new_string(tmpMap->value)); + json_object_object_add(input,"title",json_object_new_string(_ss(tmpMap->value))); tmpMap=getMap(in->content,"abstract"); if(tmpMap!=NULL) - json_object_object_add(input,"abstract",json_object_new_string(tmpMap->value)); + json_object_object_add(input,"description",json_object_new_string(_ss(tmpMap->value))); if(strcmp(io,"input")==0){ - tmpMap=getMap(in->content,"minOccurs"); - if(tmpMap!=NULL) - json_object_object_add(input,"minOccurs",json_object_new_string(tmpMap->value)); - tmpMap=getMap(in->content,"maxOccurs"); - if(tmpMap!=NULL) - json_object_object_add(input,"maxOccurs",json_object_new_string(tmpMap->value)); + if(pmMin!=NULL && strcmp(pmMin->value,"1")!=0 && strcmp(pmMin->value,"0")!=0) + json_object_object_add(input,"minOccurs",json_object_new_int(atoi(pmMin->value))); + if(pmMax!=NULL){ + if(strncasecmp(pmMax->value,"unbounded",9)==0) + json_object_object_add(input,"maxOccurs",json_object_new_string(pmMax->value)); + else + if(strcmp(pmMax->value,"1")!=0) + json_object_object_add(input,"maxOccurs",json_object_new_int(atoi(pmMax->value))); + } } if(in->format!=NULL){ - json_object* input1=json_object_new_object(); + //json_object* input1=json_object_new_object(); json_object* prop0=json_object_new_array(); + json_object* prop1=json_object_new_array(); + json_object* pjoSchema=json_object_new_array(); if(strcasecmp(in->format,"LiteralData")==0 || strcasecmp(in->format,"LiteralOutput")==0){ - printLiteralDataJ(m,in,input1); + printLiteralDataJ(m,in,input); + json_object_put(prop0); + json_object_put(prop1); + json_object_put(pjoSchema); }else{ if(strcasecmp(in->format,"ComplexData")==0 || - strcasecmp(in->format,"ComplexOutput")==0){ + strcasecmp(in->format,"ComplexOutput")==0) { map* sizeMap=getMap(in->content,"maximumMegabytes"); + printComplexHref(m,in,prop1,false,sizeMap); printFormatJ(m,in->defaults,prop0,true,sizeMap); + json_object* pjoSchemaPart=json_object_new_array(); + printFormatJ1(m,in->defaults,pjoSchemaPart,true,sizeMap); + + + printFormatJ1(m,in->defaults,pjoSchema,true,sizeMap); iotype* sup=in->supported; while(sup!=NULL){ printFormatJ(m,sup,prop0,false,sizeMap); + printFormatJ1(m,sup,pjoSchemaPart,false,sizeMap); + printFormatJ1(m,sup,pjoSchema,true,sizeMap); sup=sup->next; } - json_object_object_add(input1,"formats",prop0); + + json_object* pjoQualifiedValue=json_object_new_object(); + json_object_object_add(pjoQualifiedValue,"type",json_object_new_string("object")); + + json_object* pjoRequiredArray=json_object_new_array(); + json_object_array_add(pjoRequiredArray,json_object_new_string("value")); + json_object_object_add(pjoQualifiedValue,"required",pjoRequiredArray); + + json_object* pjoProperties=json_object_new_object(); + json_object* pjoValueField=json_object_new_object(); + json_object_object_add(pjoValueField,"oneOf",pjoSchemaPart); + json_object_object_add(pjoProperties,"value",pjoValueField); + json_object_object_add(pjoQualifiedValue,"properties",pjoProperties); + json_object_array_add(prop1,pjoQualifiedValue); + + json_object* prop2=json_object_new_object(); + json_object_object_add(prop2,"oneOf",prop1); + json_object* prop3=addArray(m,in); + if(prop3!=NULL){ + json_object_object_add(prop3,"items",prop2); + if(pmMin!=NULL && atoi(pmMin->value)==0) + json_object_object_add(prop3,"nullable",json_object_new_boolean(true)); + json_object_object_add(input,"extended-schema",prop3); + } + else{ + if(pmMin!=NULL && atoi(pmMin->value)==0) + json_object_object_add(prop2,"nullable",json_object_new_boolean(true)); + json_object_object_add(input,"extended-schema",prop2); + } + + json_object* prop4=json_object_new_object(); + json_object_object_add(prop4,"oneOf",pjoSchema); + json_object_object_add(input,"schema",prop4); + json_object_put(prop0); } else{ - json_object* prop1=json_object_new_object(); - json_object_object_add(prop1,"default",json_object_new_boolean(true)); - map* tmpMap1=getMap(in->defaults->content,"crs"); - if(tmpMap1==NULL) - return; - json_object_object_add(prop1,"crs",json_object_new_string(tmpMap1->value)); - json_object_array_add(prop0,prop1); - iotype* sup=in->supported; - while(sup!=NULL){ - json_object* prop1=json_object_new_object(); - json_object_object_add(prop1,"default",json_object_new_boolean(false)); - tmpMap1=getMap(sup->content,"crs"); - json_object_object_add(prop1,"crs",json_object_new_string(tmpMap1->value)); - json_object_array_add(prop0,prop1); - sup=sup->next; - } - json_object_object_add(input1,"supportedCRS",prop0); + printBoundingBoxJ(m,in,input); + json_object_put(prop0); + json_object_put(prop1); + json_object_put(pjoSchema); } } - json_object_object_add(input,io,input1); } printJMetadata(m,in->metadata,input); printJAdditionalParameters(m,in->additional_parameters,input); - json_object_array_add(inputs,input); + json_object_object_add(inputs,in->name,input); in=in->next; } - + } /** @@ -442,7 +803,12 @@ extern "C" { void printGetCapabilitiesForProcessJ(registry *reg, maps* m,void* doc0,void* nc0,service* serv){ json_object* doc=(json_object*) doc0; json_object* nc=(json_object*) nc0; - json_object *res=json_object_new_object(); + json_object *res; + if(doc!=NULL) + res=json_object_new_object(); + else + res=(json_object*) nc0; + map* tmpMap0=getMapFromMaps(m,"lenv","level"); char* rUrl=serv->name; if(tmpMap0!=NULL && atoi(tmpMap0->value)>0){ @@ -453,43 +819,57 @@ extern "C" { char* key=(char*)malloc(15*sizeof(char)); sprintf(key,"sprefix_%d",i); map* tmpMap1=getMap(tmpMaps->content,key); - if(i+1==atoi(tmpMap0->value)) - if(tmpName==NULL){ - tmpName=(char*) malloc((strlen(serv->name)+strlen(tmpMap1->value)+1)*sizeof(char)); - sprintf(tmpName,"%s%s",tmpMap1->value,serv->name); - }else{ - char* tmpStr=zStrdup(tmpName); - tmpName=(char*) realloc(tmpName,(strlen(tmpStr)+strlen(tmpMap1->value)+strlen(serv->name)+1)*sizeof(char)); - sprintf(tmpName,"%s%s%s",tmpStr,tmpMap1->value,serv->name); - free(tmpStr); - } - else - if(tmpName==NULL){ - tmpName=(char*) malloc((strlen(tmpMap1->value)+1)*sizeof(char)); - sprintf(tmpName,"%s",tmpMap1->value); - }else{ - char* tmpStr=zStrdup(tmpName); - tmpName=(char*) realloc(tmpName,(strlen(tmpStr)+strlen(tmpMap1->value)+1)*sizeof(char)); - sprintf(tmpName,"%s%s",tmpStr,tmpMap1->value); - free(tmpStr); + free(key); + if(tmpMap1!=NULL){ + if(i+1==atoi(tmpMap0->value)) + if(tmpName==NULL){ + tmpName=(char*) malloc((strlen(serv->name)+strlen(tmpMap1->value)+1)*sizeof(char)); + sprintf(tmpName,"%s%s",tmpMap1->value,serv->name); + }else{ + char* tmpStr=zStrdup(tmpName); + tmpName=(char*) realloc(tmpName,(strlen(tmpStr)+strlen(tmpMap1->value)+strlen(serv->name)+1)*sizeof(char)); + sprintf(tmpName,"%s%s%s",tmpStr,tmpMap1->value,serv->name); + free(tmpStr); + } + else + if(tmpName==NULL){ + tmpName=(char*) malloc((strlen(tmpMap1->value)+1)*sizeof(char)); + sprintf(tmpName,"%s",tmpMap1->value); + }else{ + char* tmpStr=zStrdup(tmpName); + tmpName=(char*) realloc(tmpName,(strlen(tmpStr)+strlen(tmpMap1->value)+1)*sizeof(char)); + sprintf(tmpName,"%s%s",tmpStr,tmpMap1->value); + free(tmpStr); } + } } - json_object_object_add(res,"id",json_object_new_string(tmpName)); if(tmpName!=NULL){ + json_object_object_add(res,"id",json_object_new_string(tmpName)); rUrl=zStrdup(tmpName); free(tmpName); } } - else + else{ json_object_object_add(res,"id",json_object_new_string(serv->name)); + rUrl=serv->name; + } if(serv->content!=NULL){ map* tmpMap=getMap(serv->content,"title"); if(tmpMap!=NULL){ - json_object_object_add(res,"title",json_object_new_string(tmpMap->value)); + json_object_object_add(res,"title",json_object_new_string(_ss(tmpMap->value))); } tmpMap=getMap(serv->content,"abstract"); if(tmpMap!=NULL){ - json_object_object_add(res,"abstract",json_object_new_string(tmpMap->value)); + json_object_object_add(res,"description",json_object_new_string(_ss(tmpMap->value))); + } + tmpMap=getMap(serv->content,"mutable"); + if(tmpMap==NULL) + json_object_object_add(res,"mutable",json_object_new_boolean(TRUE)); + else{ + if(strcmp(tmpMap->value,"false")==0) + json_object_object_add(res,"mutable",json_object_new_boolean(FALSE)); + else + json_object_object_add(res,"mutable",json_object_new_boolean(TRUE)); } tmpMap=getMap(serv->content,"processVersion"); if(tmpMap!=NULL){ @@ -501,12 +881,12 @@ extern "C" { } else json_object_object_add(res,"version",json_object_new_string(tmpMap->value)); - } + }else + json_object_object_add(res,"version",json_object_new_string("1.0.0")); int limit=4; int i=0; map* sType=getMap(serv->content,"serviceType"); for(;ivalue,"desc",4)==0){ + //Previous value: "process-desc" + map* pmTmp=getMapFromMaps(m,"processes/{processID}","rel"); + if(pmTmp!=NULL) + json_object_object_add(res2,"rel",json_object_new_string(pmTmp->value)); + else + json_object_object_add(res2,"rel",json_object_new_string("self")); + } + else{ + //Previous value: "execute" + map* pmTmp=getMapFromMaps(m,"processes/{processID}/execution","rel"); + if(pmTmp!=NULL) + json_object_object_add(res2,"rel",json_object_new_string(pmTmp->value)); + } + json_object_object_add(res3,"rel",json_object_new_string("alternate")); + json_object_object_add(res3,"type",json_object_new_string("text/html")); json_object_object_add(res2,"type",json_object_new_string("application/json")); - json_object_object_add(res2,"title",json_object_new_string("Process Description")); map* tmpUrl=getMapFromMaps(m,"openapi","rootUrl"); char* tmpStr=(char*) malloc((strlen(tmpUrl->value)+strlen(rUrl)+13)*sizeof(char)); - sprintf(tmpStr,"%s/processes/%s/",tmpUrl->value,rUrl); - if(doc==NULL){ + sprintf(tmpStr,"%s/processes/%s",tmpUrl->value,rUrl); + if(pmTmp!=NULL && strncasecmp(pmTmp->value,"desc",4)!=0){ json_object_object_add(res2,"title",json_object_new_string("Execute End Point")); + json_object_object_add(res3,"title",json_object_new_string("Execute End Point")); char* tmpStr1=zStrdup(tmpStr); - tmpStr=(char*) realloc(tmpStr,(strlen(tmpStr)+6)*sizeof(char)); - sprintf(tmpStr,"%sjobs/",tmpStr1); + tmpStr=(char*) realloc(tmpStr,(strlen(tmpStr1)+11)*sizeof(char)); + sprintf(tmpStr,"%s/execution",tmpStr1); free(tmpStr1); + }else{ + json_object_object_add(res2,"title",json_object_new_string("Process Description")); + json_object_object_add(res3,"title",json_object_new_string("Process Description")); } + char* tmpStr3=(char*) malloc((strlen(tmpStr)+6)*sizeof(char)); + sprintf(tmpStr3,"%s.html",tmpStr); + json_object_object_add(res3,"href",json_object_new_string(tmpStr3)); + free(tmpStr3); json_object_object_add(res2,"href",json_object_new_string(tmpStr)); free(tmpStr); json_object_array_add(res1,res2); + tmpUrl=getMapFromMaps(m,"openapi","partial_html_support"); + if(tmpUrl!=NULL && strncasecmp(tmpUrl->value,"true",4)==0) + json_object_array_add(res1,res3); + else + json_object_put(res3); json_object_object_add(res,"links",res1); } if(doc==NULL){ elements* in=serv->inputs; - json_object* inputs=json_object_new_array(); + json_object* inputs=json_object_new_object(); printIOTypeJ(m,"input",in,inputs,serv); json_object_object_add(res,"inputs",inputs); in=serv->outputs; - json_object* outputs=json_object_new_array(); + json_object* outputs=json_object_new_object(); printIOTypeJ(m,"output",in,outputs,serv); json_object_object_add(res,"outputs",outputs); @@ -554,78 +963,108 @@ extern "C" { free(rUrl); if(doc!=NULL) json_object_array_add(doc,res); - else - json_object_object_add(nc,"process",json_object_get(res)); - } /** - * Print an OWS ExceptionReport Document and HTTP headers (when required) + * Produce an exception JSON object + * + * @param m the maps containing the settings of the main.cfg file + * @param s the map containing the text,code,locator keys (or a map array of the same keys) + * @return the create JSON object (make sure to free memory) + */ + json_object *createExceptionJ(maps* m,map* s){ + json_object *res=json_object_new_object(); + map* pmTmp=getMap(s,"code"); + if(pmTmp!=NULL){ + json_object_object_add(res,"title",json_object_new_string(_(pmTmp->value))); + int i=0; + int hasType=-1; + for(i=0;i<4;i++){ + if(strcasecmp(pmTmp->value,WPSExceptionCode[OAPIPCorrespondances[i][0]])==0){ + map* pmExceptionUrl=getMapFromMaps(m,"openapi","exceptionsUrl"); + char* pcaTmp=(char*)malloc((strlen(pmExceptionUrl->value)+strlen(OAPIPExceptionCode[OAPIPCorrespondances[i][1]])+2)*sizeof(char)); + sprintf(pcaTmp,"%s/%s",pmExceptionUrl->value,OAPIPExceptionCode[OAPIPCorrespondances[i][1]]); + json_object_object_add(res,"type",json_object_new_string(pcaTmp)); + free(pcaTmp); + hasType=0; + } + } + if(hasType<0){ + json_object_object_add(res,"type",json_object_new_string(pmTmp->value)); + } + } + else{ + json_object_object_add(res,"title",json_object_new_string("NoApplicableCode")); + json_object_object_add(res,"type",json_object_new_string("NoApplicableCode")); + } + pmTmp=getMap(s,"text"); + if(pmTmp==NULL) + pmTmp=getMap(s,"message"); + if(pmTmp==NULL) + pmTmp=getMapFromMaps(m,"lenv","message"); + if(pmTmp!=NULL) + json_object_object_add(res,"detail",json_object_new_string(pmTmp->value)); + //setMapInMaps(m,"headers","Content-Type","application/problem+json;charset=UTF-8"); + return res; + } + + /** + * Print an OWS ExceptionReport Document and HTTP headers (when required) * depending on the code. - * Set hasPrinted value to true in the [lenv] section. - * + * Set hasPrinted value to true in the [lenv] section. + * @see createExceptionJ + * * @param m the maps containing the settings of the main.cfg file * @param s the map containing the text,code,locator keys (or a map array of the same keys) */ void printExceptionReportResponseJ(maps* m,map* s){ - if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL) + map* pmHasprinted=getMapFromMaps(m,"lenv","hasExceptionPrinted"); + if(pmHasprinted!=NULL && strncasecmp(pmHasprinted->value,"true",4)==0) return; + pmHasprinted=getMapFromMaps(m,"lenv","hasPrinted"); int buffersize; - json_object *res=json_object_new_object(); - + //json_object *res=json_object_new_object(); + json_object *res=createExceptionJ(m,s); maps* tmpMap=getMaps(m,"main"); const char *exceptionCode; - - map* tmp=getMap(s,"code"); - if(tmp!=NULL){ - if(strcmp(tmp->value,"OperationNotSupported")==0 || - strcmp(tmp->value,"NoApplicableCode")==0) - exceptionCode="501 Not Implemented"; - else - if(strcmp(tmp->value,"MissingParameterValue")==0 || - strcmp(tmp->value,"InvalidUpdateSequence")==0 || - strcmp(tmp->value,"OptionNotSupported")==0 || - strcmp(tmp->value,"VersionNegotiationFailed")==0 || - strcmp(tmp->value,"InvalidParameterValue")==0) - exceptionCode="400 Bad request"; - else - if(strcmp(tmp->value,"NotFound")==0) - exceptionCode="404 Not Found"; - else - exceptionCode="501 Internal Server Error"; - json_object_object_add(res,"code",json_object_new_string(tmp->value)); - } - else - exceptionCode="501 Internal Server Error"; - printHeaders(m); - - tmp=getMapFromMaps(m,"lenv","status_code"); - if(tmp!=NULL) - exceptionCode=tmp->value; - if(m!=NULL){ - map *tmpSid=getMapFromMaps(m,"lenv","sid"); - if(tmpSid!=NULL){ - if( getpid()==atoi(tmpSid->value) ){ + map* pmTmp=getMap(s,"code"); + exceptionCode=produceStatusString(m,pmTmp); + map* pmNoHeaders=getMapFromMaps(m,"lenv","no-headers"); + if(pmNoHeaders==NULL || strncasecmp(pmNoHeaders->value,"false",5)==0) + printHeaders(m); + pmTmp=getMapFromMaps(m,"lenv","status_code"); + if(pmTmp!=NULL) + exceptionCode=pmTmp->value; + if(exceptionCode==NULL) + exceptionCode=aapccStatusCodes[3][0]; + if(pmNoHeaders==NULL || strncasecmp(pmNoHeaders->value,"false",5)==0){ + if(m!=NULL){ + map *tmpSid=getMapFromMaps(m,"lenv","sid"); + if(tmpSid!=NULL){ + if( getpid()==atoi(tmpSid->value) ){ + printf("Status: %s\r\n\r\n",exceptionCode); + } + } + else{ printf("Status: %s\r\n\r\n",exceptionCode); } - } - else{ + }else{ printf("Status: %s\r\n\r\n",exceptionCode); } - }else{ - printf("Status: %s\r\n\r\n",exceptionCode); - } - tmp=getMap(s,"text"); - if(tmp==NULL) - tmp=getMap(s,"message"); - if(tmp==NULL) - tmp=getMapFromMaps(m,"lenv","message"); - if(tmp!=NULL) - json_object_object_add(res,"description",json_object_new_string(tmp->value)); - const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN); - printf(jsonStr); - if(m!=NULL) - setMapInMaps(m,"lenv","hasPrinted","true"); + } + + const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_NOSLASHESCAPE); + if(getMapFromMaps(m,"lenv","jsonStr")==NULL) + setMapInMaps(m,"lenv","jsonStr",jsonStr); + + if(pmHasprinted==NULL || strncasecmp(pmHasprinted->value,"false",5)==0){ + printf(jsonStr); + if(m!=NULL){ + setMapInMaps(m,"lenv","hasPrinted","true"); + setMapInMaps(m,"lenv","hasExceptionPrinted","true"); + } + } + json_object_put(res); } /** @@ -660,14 +1099,47 @@ extern "C" { addToMap(output->content,tmpStrs[i],json_object_get_string(json_cinput1)); } } - if(json_object_object_get_ex(req,"transmissionMode",&json_cinput)!=FALSE){ - if(output->content==NULL) - output->content=createMap("transmissionMode",json_object_get_string(json_cinput)); - else - addToMap(output->content,"transmissionMode",json_object_get_string(json_cinput)); - } } + /** + * Search field names used in the OGC API - Processes specification and + * replace them by old names from WPS. + * + * @param conf the maps containing the settings of the main.cfg file + * @param req json_object to fetch attributes from + * @param output the maps to store metadata informations as a maps + */ + void checkCorrespondingJFields(maps* conf,json_object* req,maps* output){ + json_object* json_cinput=NULL; + for(int i=0;i<9;i++){ + if(json_object_object_get_ex(req,pccFields[i],&json_cinput)!=FALSE){ + if(output->content==NULL) + output->content=createMap(pccFields[i],json_object_get_string(json_cinput)); + else + addToMap(output->content,pccFields[i],json_object_get_string(json_cinput)); + + if(i==0 || i==3 || i==6){ + if(output->content==NULL) + output->content=createMap(pccRFields[0],json_object_get_string(json_cinput)); + else + addToMap(output->content,pccRFields[0],json_object_get_string(json_cinput)); + } + if(i==1 || i==4 || i==7){ + if(output->content==NULL) + output->content=createMap(pccRFields[1],json_object_get_string(json_cinput)); + else + addToMap(output->content,pccRFields[1],json_object_get_string(json_cinput)); + } + if(i==2 || i==5 || i==8){ + if(output->content==NULL) + output->content=createMap(pccRFields[2],json_object_get_string(json_cinput)); + else + addToMap(output->content,pccRFields[2],json_object_get_string(json_cinput)); + } + } + } + } + /** * Parse ComplexData value * @param conf the maps containing the settings of the main.cfg file @@ -678,55 +1150,39 @@ extern "C" { */ void parseJComplex(maps* conf,json_object* req,elements* element,maps* output,const char* name){ json_object* json_cinput=NULL; - - - if (json_object_object_get_ex(req,"href",&json_cinput)!=FALSE){ - output->content=createMap("xlink:href",json_object_get_string(json_cinput)); - int len=0; - int createdStr=0; - char *tmpStr="url"; - char *tmpStr1="input"; - if(getMaps(conf,"http_requests")==NULL){ - maps* tmpMaps=createMaps("http_requests"); - tmpMaps->content=createMap("length","1"); - freeMaps(&tmpMaps); - free(tmpMaps); - } - } else if(json_object_object_get_ex(req,"value",&json_cinput)!=FALSE){ + if(json_object_object_get_ex(req,"value",&json_cinput)!=FALSE){ + output->content=createMap("value",json_object_get_string(json_cinput)); + } + else{ json_object* json_value=NULL; - if(json_object_object_get_ex(json_cinput,"inlineValue",&json_value)!=FALSE) - output->content=createMap("value",json_object_get_string(json_value)); - else{ - if(json_object_object_get_ex(json_cinput,"href",&json_value)!=FALSE){ - output->content=createMap("xlink:href",json_object_get_string(json_value)); - int len=0; - int createdStr=0; - char *tmpStr="url"; - char *tmpStr1="input"; - if(getMaps(conf,"http_requests")==NULL){ - maps* tmpMaps=createMaps("http_requests"); - tmpMaps->content=createMap("length","1"); -// addMapsToMaps(&conf,tmpMaps);//rdr ERROR!!! - freeMaps(&tmpMaps); - free(tmpMaps); - - }else{ - map* tmpMap=getMapFromMaps(conf,"http_requests","length"); - int len=atoi(tmpMap->value); - createdStr=1; - tmpStr=(char*) malloc((12)*sizeof(char)); - sprintf(tmpStr,"%d",len+1); - setMapInMaps(conf,"http_requests","length",tmpStr); - sprintf(tmpStr,"url_%d",len); - tmpStr1=(char*) malloc((14)*sizeof(char)); - sprintf(tmpStr1,"input_%d",len); - } -// setMapInMaps(conf,"http_requests",tmpStr,json_object_get_string(json_value));//rdr ERROR!!! -// setMapInMaps(conf,"http_requests",tmpStr1,name);//rdr ERROR!!! - if(createdStr>0){ - free(tmpStr); - free(tmpStr1); - } + if(json_object_object_get_ex(req,"href",&json_value)!=FALSE){ + output->content=createMap("xlink:href",json_object_get_string(json_value)); + int len=0; + int createdStr=0; + char *tmpStr="url"; + char *tmpStr1="input"; + if(getMaps(conf,"http_requests")==NULL){ + maps* tmpMaps=createMaps("http_requests"); + tmpMaps->content=createMap("length","1"); + addMapsToMaps(&conf,tmpMaps); + freeMaps(&tmpMaps); + free(tmpMaps); + }else{ + map* tmpMap=getMapFromMaps(conf,"http_requests","length"); + int len=atoi(tmpMap->value); + createdStr=1; + tmpStr=(char*) malloc((12)*sizeof(char)); + sprintf(tmpStr,"%d",len+1); + setMapInMaps(conf,"http_requests","length",tmpStr); + sprintf(tmpStr,"url_%d",len); + tmpStr1=(char*) malloc((14)*sizeof(char)); + sprintf(tmpStr1,"input_%d",len); + } + setMapInMaps(conf,"http_requests",tmpStr,json_object_get_string(json_value)); + setMapInMaps(conf,"http_requests",tmpStr1,name); + if(createdStr>0){ + free(tmpStr); + free(tmpStr1); } } } @@ -736,15 +1192,11 @@ extern "C" { output->content=createMap(key,json_object_get_string(val)); else addToMap(output->content,key,json_object_get_string(val)); - + } + checkCorrespondingJFields(conf,json_cinput,output); } - if(json_object_object_get_ex(req,"transmissionMode",&json_cinput)!=FALSE){ - if(output->content==NULL) - output->content=createMap("transmissionMode",json_object_get_string(json_cinput)); - else - addToMap(output->content,"transmissionMode",json_object_get_string(json_cinput)); - } + checkCorrespondingJFields(conf,req,output); } /** @@ -776,178 +1228,260 @@ extern "C" { else addToMap(output->content,tmpStrs[i],json_object_get_string(json_cinput)); } - if(json_object_object_get_ex(req,"transmissionMode",&json_cinput)!=FALSE){ - if(output->content==NULL) - output->content=createMap("transmissionMode",json_object_get_string(json_cinput)); - else - addToMap(output->content,"transmissionMode",json_object_get_string(json_cinput)); - } } /** - * Parse inputs / outputs + * Parse a single input / output entity + * * @param conf the maps containing the settings of the main.cfg file - * @param req json_object pointing to the input/output * @param ioElements the elements extracted from the zcfg - * @param ioMaps the produced maps containing inputs (or outputs) + * @param ioMaps the produced maps containing inputs (or outputs) * @param ioType the char* set to inputs or outputs + * @param key char* the input/output name + * @param val json_object pointing to the input/output + * @param cMaps the outputed maps containing input (or output) metedata */ - void parseJIO(maps* conf, json_object* req, elements* ioElements, maps** ioMaps,const char* ioType){ - json_object* json_io=NULL; - if(json_object_object_get_ex(req,ioType,&json_io)!=FALSE){ - json_object* json_current_io=NULL; - size_t len=json_object_array_length(json_io); - for(int i=0;iname); - addToMap(error,"message",tmpS); - setMapInMaps(conf,"lenv","status_code","400 Bad Request"); - printExceptionReportResponseJ(conf,error); - return; - }else{ - if(json_object_get_type(json_cinput)==json_type_string){ - parseJLiteral(conf,json_input,cio,cMaps); - }else if(json_object_get_type(json_cinput)==json_type_object){ - json_object* json_ccinput=NULL; - if(json_object_object_get_ex(json_cinput,"bbox",&json_ccinput)!=FALSE){ - parseJComplex(conf,json_input,cio,cMaps,json_object_get_string(cname)); - } - else{ - parseJBoundingBox(conf,json_input,cio,cMaps); - } - }else{ - if(strcmp(ioType,"input")==0){ - map* error=createMap("code","BadRequest"); - char tmpS1[1024]; - sprintf(tmpS1,_("Issue with input %s"),ioElements->name); - addToMap(error,"message",tmpS1); - setMapInMaps(conf,"lenv","status_code","400 Bad Request"); - printExceptionReportResponseJ(conf,error); - return; - } - } - } + void _parseJIOSingle1(maps* conf,elements* cio, maps** ioMaps,const char* ioType,const char* key,json_object* val,maps* cMaps){ + json_object* json_cinput; + if(strncmp(ioType,"inputs",6)==0) { + if(json_object_is_type(val,json_type_object)) { + // ComplexData + if( json_object_object_get_ex(val,"value",&json_cinput) != FALSE || + json_object_object_get_ex(val,"href",&json_cinput) != FALSE ) { + parseJComplex(conf,val,cio,cMaps,key); + } else if( json_object_object_get_ex(val,"bbox",&json_cinput) != FALSE ){ + parseJBoundingBox(conf,val,cio,cMaps); + } + } else if(json_object_is_type(val,json_type_array)){ + // Need to run detection on each item within the array + }else{ + // Basic types + cMaps->content=createMap("value",json_object_get_string(val)); + } + } + else{ + if(json_object_object_get_ex(val,"dataType",&json_cinput)!=FALSE){ + parseJLiteral(conf,val,cio,cMaps); + } else if(json_object_object_get_ex(val,"format",&json_cinput)!=FALSE){ + parseJComplex(conf,val,cio,cMaps,key); + } else if(json_object_object_get_ex(val,"bbox",&json_cinput)!=FALSE){ + parseJBoundingBox(conf,val,cio,cMaps); + }// else error! + else{ + if(json_object_object_get_ex(val,"value",&json_cinput)!=FALSE){ + map* error=createMap("code","BadRequest"); + char tmpS[1024]; + sprintf(tmpS,_("Missing input for %s"),cio->name); + addToMap(error,"message",tmpS); + setMapInMaps(conf,"lenv","status_code","400 Bad Request"); + printExceptionReportResponseJ(conf,error); + return; + }else{ + if(json_object_get_type(val)==json_type_string){ + parseJLiteral(conf,val,cio,cMaps); + }else if(json_object_get_type(val)==json_type_object){ + json_object* json_ccinput=NULL; + if(json_object_object_get_ex(val,"bbox",&json_ccinput)!=FALSE){ + parseJBoundingBox(conf,val,cio,cMaps); + } + else{ + parseJComplex(conf,val,cio,cMaps,key); } }else{ if(strcmp(ioType,"input")==0){ map* error=createMap("code","BadRequest"); char tmpS1[1024]; - sprintf(tmpS1,_("Missing input for %s"),ioElements->name); + sprintf(tmpS1,_("Issue with input %s"),cio->name); addToMap(error,"message",tmpS1); setMapInMaps(conf,"lenv","status_code","400 Bad Request"); printExceptionReportResponseJ(conf,error); return; - }else{ - // Outputs - if(json_object_object_get_ex(json_current_io,"transmissionMode",&json_cinput)!=FALSE){ - if(cMaps->content==NULL) - cMaps->content=createMap("transmissionMode",json_object_get_string(json_cinput)); - else - addToMap(cMaps->content,"transmissionMode",json_object_get_string(json_cinput)); - } - if(json_object_object_get_ex(json_current_io,"format",&json_cinput)!=FALSE){ - json_object_object_foreach(json_cinput, key, val) { - if(cMaps->content==NULL) - cMaps->content=createMap(key,json_object_get_string(val)); - else - addToMap(cMaps->content,key,json_object_get_string(val)); - } - } } } } - addToMap(cMaps->content,"inRequest","true"); - if (ioMaps == NULL) - *ioMaps = dupMaps(&cMaps); - else { - - maps* testIath=getMaps(*ioMaps,cMaps->name); - if(testIath){ - - int cursor=2; - char name[20],cCursor[55]; - memset(name,'\0',20); - memset(cCursor,'\0',55); - - map *getValueMap = getMap(cMaps->content,"value"); - if (getValueMap){ - strcpy(name,"value"); - } - map *getXlink = getMap(cMaps->content,"xlink:href"); - if (getXlink){ - strcpy(name,"xlink:href"); - } - - map* isArray=getMap(testIath->content,"isArray"); - if(isArray){ - - map* le=getMap(testIath->content,"length"); - if (le){ - cursor = atoi(le->value); - cursor=cursor+1; - }else{ - cursor=2; - } - - free(le->value); - le->value=NULL; - - snprintf(cCursor,54,"%d",cursor); - le->value=zStrdup(cCursor); - - }else{ - map *addArray = createMap("isArray","true"); - addMapToMap(&testIath->content,addArray); - - map *addLength = createMap("length","2"); - addMapToMap(&testIath->content,addLength); - } - - if (strlen(name)!=0){ - memset(cCursor,'\0',55); - snprintf(cCursor,54,"%d",cursor-1); - - int newSize=(5+strlen(cCursor) + strlen(name)) +sizeof(char); - char* newValueC=(char*)malloc( newSize); - memset(newValueC,'\n',newSize); - - sprintf(newValueC,"%s_%s",name,cCursor); - map *addValue = createMap(newValueC, getValueMap?getValueMap->value:getXlink->value); - addMapToMap(&testIath->content,addValue); + } + } + } + + /** + * Parse a single input / output entity + * + * @param conf the maps containing the settings of the main.cfg file + * @param ioElements the elements extracted from the zcfg + * @param ioMaps the produced maps containing inputs (or outputs) + * @param ioType the char* set to inputs or outputs + * @param key char* the input/output name + * @param val json_object pointing to the input/output + * @param cMaps the outputed maps containing input (or output) metedata + */ + void _parseJIOSingle(maps* conf,elements* cio, maps** ioMaps,const char* ioType,const char* key,json_object* val,maps* cMaps){ + json_object* json_cinput; + if(json_object_object_get_ex(val,"dataType",&json_cinput)!=FALSE){ + parseJLiteral(conf,val,cio,cMaps); + } else if(json_object_object_get_ex(val,"format",&json_cinput)!=FALSE){ + parseJComplex(conf,val,cio,cMaps,key); + } else if(json_object_object_get_ex(val,"bbox",&json_cinput)!=FALSE){ + parseJBoundingBox(conf,val,cio,cMaps); + }// else error! + else{ + if(json_object_object_get_ex(val,"value",&json_cinput)!=FALSE){ + map* error=createMap("code","BadRequest"); + char tmpS[1024]; + sprintf(tmpS,_("Missing input for %s"),cio->name); + addToMap(error,"message",tmpS); + setMapInMaps(conf,"lenv","status_code","400 Bad Request"); + printExceptionReportResponseJ(conf,error); + return; + }else{ + if(json_object_get_type(json_cinput)==json_type_string){ + parseJLiteral(conf,val,cio,cMaps); + }else if(json_object_get_type(json_cinput)==json_type_object){ + json_object* json_ccinput=NULL; + if(json_object_object_get_ex(json_cinput,"bbox",&json_ccinput)!=FALSE){ + parseJComplex(conf,val,cio,cMaps,key); + } + else{ + parseJBoundingBox(conf,val,cio,cMaps); + } + }else{ + if(strcmp(ioType,"input")==0){ + map* error=createMap("code","BadRequest"); + char tmpS1[1024]; + sprintf(tmpS1,_("Issue with input %s"),cio->name); + addToMap(error,"message",tmpS1); + setMapInMaps(conf,"lenv","status_code","400 Bad Request"); + printExceptionReportResponseJ(conf,error); + return; + } + } + } + } + } + + /** + * Parse a single input / output entity that can be an array + * + * @param conf the maps containing the settings of the main.cfg file + * @param ioElements the elements extracted from the zcfg + * @param ioMaps the produced maps containing inputs (or outputs) + * @param ioType the char* set to inputs or outputs + * @param key char* the input/output name + * @param val json_object pointing to the input/output + */ + void parseJIOSingle(maps* conf,elements* ioElements, maps** ioMaps,const char* ioType,const char* key,json_object* val){ + maps *cMaps=NULL; + cMaps=createMaps(key); + elements* cio=getElements(ioElements,key); + if(json_object_is_type(val,json_type_array)){ + int i=0; + size_t len=json_object_array_length(val); + for(i=0;icontent; + while(pmCtx!=NULL){ + if(cMaps->content==NULL) + cMaps->content=createMap(pmCtx->name,pmCtx->value); + else + setMapArray(cMaps->content,pmCtx->name,i,pmCtx->value); + pmCtx=pmCtx->next; + } + freeMaps(&pmsExtra); + free(pmsExtra); + } + }else{ + _parseJIOSingle1(conf,cio,ioMaps,ioType,key,val,cMaps); + } - free(newValueC); - } + + if(strcmp(ioType,"outputs")==0){ + // Outputs + json_object* json_cinput; + if(json_object_object_get_ex(val,"transmissionMode",&json_cinput)!=FALSE){ + if(cMaps->content==NULL) + cMaps->content=createMap("transmissionMode",json_object_get_string(json_cinput)); + else + addToMap(cMaps->content,"transmissionMode",json_object_get_string(json_cinput)); + }else{ + // Default to transmissionMode value + if(cMaps->content==NULL) + cMaps->content=createMap("transmissionMode","value"); + else + addToMap(cMaps->content,"transmissionMode","value"); + } + if(json_object_object_get_ex(val,"format",&json_cinput)!=FALSE){ + json_object_object_foreach(json_cinput, key1, val1) { + if(cMaps->content==NULL) + cMaps->content=createMap(key1,json_object_get_string(val1)); + else + addToMap(cMaps->content,key1,json_object_get_string(val1)); + } + } + } - }else{ - addMapsToMaps(ioMaps, cMaps); - } + addToMap(cMaps->content,"inRequest","true"); + if (ioMaps == NULL) + *ioMaps = dupMaps(&cMaps); + else + addMapsToMaps (ioMaps, cMaps); - } + freeMaps(&cMaps); + free(cMaps); + } + + /** + * Parse all the inputs / outputs entities + * + * @param conf the maps containing the settings of the main.cfg file + * @param req json_object pointing to the input/output + * @param ioElements the elements extracted from the zcfg + * @param ioMaps the produced maps containing inputs (or outputs) + * @param ioType the char* set to inputs or outputs + */ + void parseJIO(maps* conf, json_object* req, elements* ioElements, maps** ioMaps,const char* ioType){ + json_object* json_io=NULL; + if(json_object_object_get_ex(req,ioType,&json_io)!=FALSE){ + json_object* json_current_io=NULL; + if(json_object_is_type(json_io,json_type_array)){ + size_t len=json_object_array_length(json_io); + for(int i=0;iname); + pmsTmp->content=createMap("transmissionMode","value"); + if(*ioMaps==NULL) + *ioMaps=dupMaps(&pmsTmp); + else + addMapsToMaps(ioMaps,pmsTmp); + freeMaps(&pmsTmp); + free(pmsTmp); + peTmp=peTmp->next; + } } } } - - /** * Parse Json Request * @param conf the maps containing the settings of the main.cfg file @@ -956,23 +1490,110 @@ extern "C" { * @param inputs the produced maps * @param outputs the produced maps */ - void parseJRequest(maps* conf, service* s,json_object* req,maps** inputs,maps** outputs){ + void parseJRequest(maps* conf, service* s,json_object* req, map* request_inputs, maps** inputs,maps** outputs){ elements* io=s->inputs; - json_object* json_io=NULL; int parsed=0; char* tmpS="input"; maps* in=*inputs; parseJIO(conf,req,s->inputs,inputs,"inputs"); + parseJIO(conf,req,s->outputs,outputs,"outputs"); if(parsed==0){ json_io=NULL; - if(json_object_object_get_ex(req,"outputs",&json_io)!=FALSE){ - parseJIO(conf,req,s->outputs,outputs,"outputs"); + if(json_object_object_get_ex(req,"mode",&json_io)!=FALSE){ + addToMap(request_inputs,"mode",json_object_get_string(json_io)); + setMapInMaps(conf,"request","mode",json_object_get_string(json_io)); + } + json_io=NULL; + map* preference=getMapFromMaps(conf,"renv","HTTP_PREFER"); + if(preference!=NULL && strstr(preference->value,"return=minimal")!=NULL){ + addToMap(request_inputs,"response","raw"); + setMapInMaps(conf,"request","response","raw"); + } + else{ + if(preference!=NULL && strstr(preference->value,"return=representation")!=NULL){ + addToMap(request_inputs,"response","document"); + setMapInMaps(conf,"request","response","document"); + } + } + if(json_object_object_get_ex(req,"response",&json_io)!=FALSE){ + if(getMap(request_inputs,"response")==NULL) + addToMap(request_inputs,"response",json_object_get_string(json_io)); + else{ + map* pmTmp=getMap(request_inputs,"response"); + free(pmTmp->value); + pmTmp->value=zStrdup(json_object_get_string(json_io)); + } + setMapInMaps(conf,"request","response",json_object_get_string(json_io)); + }else{ + if(getMap(request_inputs,"response")==NULL){ + addToMap(request_inputs,"response","raw"); + setMapInMaps(conf,"request","response","raw"); + } + } + json_io=NULL; + if(json_object_object_get_ex(req,"subscriber",&json_io)!=FALSE){ + maps* subscribers=createMaps("subscriber"); + json_object* json_subscriber=NULL; + if(json_object_object_get_ex(json_io,"successUri",&json_subscriber)!=FALSE){ + subscribers->content=createMap("successUri",json_object_get_string(json_subscriber)); + } + if(json_object_object_get_ex(json_io,"inProgressUri",&json_subscriber)!=FALSE){ + if(subscribers->content==NULL) + subscribers->content=createMap("inProgressUri",json_object_get_string(json_subscriber)); + else + addToMap(subscribers->content,"inProgressUri",json_object_get_string(json_subscriber)); + } + if(json_object_object_get_ex(json_io,"failedUri",&json_subscriber)!=FALSE){ + if(subscribers->content==NULL) + subscribers->content=createMap("failedUri",json_object_get_string(json_subscriber)); + else + addToMap(subscribers->content,"failedUri",json_object_get_string(json_subscriber)); + } + addMapsToMaps(&conf,subscribers); + freeMaps(&subscribers); + free(subscribers); } } } + /** + * Print the jobs status info + * cf. + * + * @param conf the maps containing the settings of the main.cfg file + * @return the JSON object pointer to the jobs list + */ + json_object* printJobStatus(maps* pmsConf,char* pcJobId){ + json_object* pjoRes=NULL; + runGetStatus(pmsConf,pcJobId,"GetStatus"); + map* pmError=getMapFromMaps(pmsConf,"lenv","error"); + if(pmError!=NULL && strncasecmp(pmError->value,"true",4)==0){ + printExceptionReportResponseJ(pmsConf,getMapFromMaps(pmsConf,"lenv","code")); + return NULL; + }else{ + map* pmStatus=getMapFromMaps(pmsConf,"lenv","status"); + setMapInMaps(pmsConf,"lenv","gs_location","false"); + setMapInMaps(pmsConf,"lenv","gs_usid",pcJobId); + if(pmStatus!=NULL && strncasecmp(pmStatus->value,"Failed",6)==0) + pjoRes=createStatus(pmsConf,SERVICE_FAILED); + else + if(pmStatus!=NULL && strncasecmp(pmStatus->value,"Succeeded",9)==0) + pjoRes=createStatus(pmsConf,SERVICE_SUCCEEDED); + else + if(pmStatus!=NULL && strncasecmp(pmStatus->value,"Running",7)==0){ + /*map* tmpMap=getMapFromMaps(pmsConf,"lenv","Message"); + if(tmpMap!=NULL) + setMapInMaps(pmsConf,"lenv","gs_message",tmpMap->value);*/ + pjoRes=createStatus(pmsConf,SERVICE_STARTED); + } + else + pjoRes=createStatus(pmsConf,SERVICE_FAILED); + } + return pjoRes; + } + /** * Print the jobs list * @@ -981,298 +1602,491 @@ extern "C" { */ json_object* printJobList(maps* conf){ json_object* res=json_object_new_array(); + map* pmJobs=getMapFromMaps(conf,"lenv","selectedJob"); map* tmpPath=getMapFromMaps(conf,"main","tmpPath"); - map* oIdentifier=getMapFromMaps(conf,"lenv","oIdentifier"); - char* cpath=(char*)malloc( (strlen(tmpPath->value)+strlen(oIdentifier->value)+14+/*rdr add user path*/ + 1024)*sizeof(char)) ; - - -// - map *userMap = getMapFromMaps (conf, "eoepcaUser", "user"); - if (userMap && userMap->value && strlen(userMap->value)>0 ){ - sprintf(cpath,"%s/statusInfos/%s/%s",tmpPath->value,userMap->value,oIdentifier->value); - }else{ - sprintf(cpath,"%s/statusInfos/%s",tmpPath->value,oIdentifier->value); + struct dirent *dp; + int cnt=0; + int skip=0; + int limit=10000; + map* pmLimit=getMapFromMaps(conf,"lenv","serviceCntLimit"); + map* pmSkip=getMapFromMaps(conf,"lenv","serviceCntSkip"); + if(pmLimit!=NULL){ + limit=atoi(pmLimit->value); } - fprintf(stderr,"-----------PATH1: %s ---------------\n",cpath); + if(pmSkip!=NULL){ + skip=atoi(pmSkip->value); + } + if(pmJobs!=NULL){ + if(strcmp(pmJobs->value,"-1")==0){ + // Exception invalid-query-paramter-value + map* pmaTmp=createMap("code","InvalidQueryParameterValue"); + addToMap(pmaTmp,"message","The server was unable to parse one of the query pareter provided"); + json_object_put(res); + printExceptionReportResponseJ(conf,pmaTmp); + freeMap(&pmaTmp); + free(pmaTmp); + return NULL; + } + char *saveptr; + char *tmps = strtok_r(pmJobs->value, ",", &saveptr); + while(tmps!=NULL){ + if(cnt>=skip && cnt2){ + char* tmpStr=zStrdup(tmps+1); + tmpStr[strlen(tmpStr)-1]=0; + json_object* cjob=printJobStatus(conf,tmpStr); + json_object_array_add(res,cjob); + free(tmpStr); + } + if(cnt==limit+skip) + setMapInMaps(conf,"lenv","serviceCntNext","true"); + cnt++; + tmps = strtok_r (NULL, ",", &saveptr); + } + }else{ + char* cpath=(char*)malloc( (strlen(tmpPath->value)+14+/*rdr add user path*/ + 1024)*sizeof(char)) ; - struct dirent *dp; - DIR *dirp = opendir (cpath); - if(dirp!=NULL){ - while ((dp = readdir (dirp)) != NULL){ - char* extn = strstr(dp->d_name, ".json"); - if(extn!=NULL){ - - fprintf(stderr,"-----------PATH1: FILE: %s ---------------\n",dp->d_name); - - json_object* cjob=json_object_new_object(); - char* tmpStr=zStrdup(dp->d_name); - tmpStr[strlen(dp->d_name)-5]=0; - json_object_object_add(cjob,"id",json_object_new_string(tmpStr)); - char *tmps1=(char*)malloc((strlen(cpath)+strlen(dp->d_name)+2)*sizeof(char)); - sprintf (tmps1, "%s/%s", cpath, dp->d_name); - - fprintf(stderr,"-----------PATH1: FILE: tmps1: %s ---------------\n",tmps1); - - FILE* cdat=fopen(tmps1,"rb"); - if(cdat!=NULL){ - zStatStruct f_status; - int s=zStat(tmps1, &f_status); - char* mystring=(char*)malloc((f_status.st_size+1)*sizeof(char)); - fread(mystring,1,f_status.st_size,cdat); - mystring[f_status.st_size]=0; - json_object *jobj = NULL; - int slen = 0; - enum json_tokener_error jerr; - struct json_tokener* tok=json_tokener_new(); - do { - slen = strlen(mystring); - jobj = json_tokener_parse_ex(tok, mystring, slen); - } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); - if (jerr != json_tokener_success) { - fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); - return res; - } - if (tok->char_offset < slen){ - return res; + map *userMap = getMapFromMaps (conf, "eoepcaUser", "user"); + if (userMap && userMap->value && strlen(userMap->value)>0 ){ + sprintf(cpath,"%s/%s",tmpPath->value,userMap->value); + }else{ + sprintf(cpath,"%s",tmpPath->value); + } + fprintf(stderr,"-----------PATH1: %s ---------------\n",cpath); + + //DIR *dirp = opendir (tmpPath->value); + DIR *dirp = opendir (cpath); + if(dirp!=NULL){ + while ((dp = readdir (dirp)) != NULL){ + char* extn = strstr(dp->d_name, ".json"); + if(extn!=NULL){ + if(cnt>=skip && cntd_name); + tmpStr[strlen(dp->d_name)-5]=0; + json_object* cjob=printJobStatus(conf,tmpStr); + json_object_array_add(res,cjob); } - json_object_object_add(cjob,"infos",jobj); - free(mystring); - fclose(cdat); + if(cnt==limit+skip) + setMapInMaps(conf,"lenv","serviceCntNext","true"); + cnt++; } - free(tmpStr); - json_object_array_add(res,cjob); } + closedir (dirp); } - closedir (dirp); } - return res; + json_object* resFinal=json_object_new_object(); + json_object_object_add(resFinal,"jobs",res); + setMapInMaps(conf,"lenv","path","jobs"); + char pcCnt[10]; + sprintf(pcCnt,"%d",cnt); + setMapInMaps(conf,"lenv","serviceCnt",pcCnt); + createNextLinks(conf,resFinal); + return resFinal; } - - - /** - * Returns current UTC timestamp - * @param dest - * @return - */ - char *getUtcTimestamp(char *dest) - { - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm *tmp = gmtime(&tv.tv_sec); - char fmt[128]; - strftime(fmt, sizeof(fmt), "%Y-%m-%dT%H:%M:%S.%%06uZ", tmp); - sprintf(dest, fmt, tv.tv_usec); - return dest; - } - + /** * Print the result of an execution * * @param conf the maps containing the settings of the main.cfg file * @param s service pointer to metadata * @param result outputs of the service - * @param res the status of executino SERVICE_FAILED/SERVICE_SUCCEEDED + * @param res the status of execution SERVICE_FAILED/SERVICE_SUCCEEDED * @return the JSON object pointer to the result */ json_object* printJResult(maps* conf,service* s,maps* result,int res){ - printHeaders(conf); - json_object* eres1=json_object_new_object(); - json_object* eres=json_object_new_array(); - maps* resu=result; - int itn=0; - while(resu!=NULL){ - json_object* res1=json_object_new_object(); - json_object_object_add(res1,"id",json_object_new_string(resu->name)); - - // UTC timestamp of the time of the job completion - // the value is temporary as it is not 100% OGC compliant - char dest[12]; - json_object_object_add(res1,"time",json_object_new_string(getUtcTimestamp(dest))); - - map* tmpMap=NULL; - if((tmpMap=getMap(resu->content,"value"))!=NULL || - (getMap(resu->content,"generated_file"))!=NULL){ - json_object* res2=json_object_new_object(); - map* tmpMap1=NULL; - if((tmpMap1=getMap(resu->content,"transmissionMode"))!=NULL) { - if(strcmp(tmpMap1->value,"value")==0) { - map* tmpMap2=getMap(resu->content,"mimeType"); - if(tmpMap2!=NULL && strstr(tmpMap2->value,"json")!=NULL){ - json_object *jobj = NULL; - int slen = 0; - enum json_tokener_error jerr; - struct json_tokener* tok=json_tokener_new(); - do { - slen = strlen(tmpMap->value); - jobj = json_tokener_parse_ex(tok, tmpMap->value, slen); - } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); - if (jerr != json_tokener_success) { - fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); - return eres1; - } - if (tok->char_offset < slen){ - return eres1; - } - json_object_object_add(res2,"inlineValue",jobj); - }else - json_object_object_add(res2,"inlineValue",json_object_new_string(tmpMap->value)); - } - else{ - // Create file for reference data if not existing - map *gfile=getMap(resu->content,"generated_file"); - char *file_name=NULL; - char *file_path=NULL; - char *file_url=NULL; - map *tmp1=getMapFromMaps(conf,"main","tmpPath"); - if(gfile!=NULL){ - gfile=getMap(resu->content,"expected_generated_file"); - if(gfile==NULL){ - gfile=getMap(resu->content,"generated_file"); - } - if(strstr(gfile->value,tmp1->value)!=NULL) - file_name=zStrdup(strstr(gfile->value,tmp1->value)+strlen(tmp1->value)); - }/*else*/ - { - // Create file for reference data - map *tmpUrl=getMapFromMaps(conf,"main","tmpUrl"); - map *usid=getMapFromMaps(conf,"lenv","usid"); - map *ext=getMap(resu->content,"extension"); - if(gfile==NULL){ - char file_ext[32]; - if( ext != NULL && ext->value != NULL) { - strncpy(file_ext, ext->value, 32); + if(res==SERVICE_FAILED){ + char* pacTmp=produceErrorMessage(conf); + map* pamTmp=createMap("message",pacTmp); + free(pacTmp); + map* pmTmp=getMapFromMaps(conf,"lenv","code"); + if(pmTmp!=NULL) + addToMap(pamTmp,"code",pmTmp->value); + printExceptionReportResponseJ(conf,pamTmp); + freeMap(&pamTmp); + free(pamTmp); + return NULL; + } + if(getMapFromMaps(conf,"lenv","no-headers")==NULL) + printHeaders(conf); + map* pmMode=getMapFromMaps(conf,"request","response"); + if(pmMode!=NULL && strncasecmp(pmMode->value,"raw",3)==0){ + maps* resu=result; + printRawdataOutputs(conf,s,resu); + map* pmError=getMapFromMaps(conf,"lenv","error"); + if(pmError!=NULL && strncasecmp(pmError->value,"true",4)==0){ + printExceptionReportResponseJ(conf,pmError); + } + return NULL; + }else{ + json_object* eres1=json_object_new_object(); + map* pmIOAsArray=getMapFromMaps(conf,"openapi","io_as_array"); + json_object* eres; + if(pmIOAsArray!=NULL && strncasecmp(pmIOAsArray->value,"true",4)==0) + eres=json_object_new_array(); + else + eres=json_object_new_object(); + maps* resu=result; + int itn=0; + while(resu!=NULL){ + json_object* res1=json_object_new_object(); + if(pmIOAsArray!=NULL && strncasecmp(pmIOAsArray->value,"true",4)==0) + json_object_object_add(res1,"id",json_object_new_string(resu->name)); + map* tmpMap=getMap(resu->content,"mimeType"); + json_object* res3=json_object_new_object(); + if(tmpMap!=NULL) + json_object_object_add(res3,"mediaType",json_object_new_string(tmpMap->value)); + else{ + json_object_object_add(res3,"mediaType",json_object_new_string("text/plain")); + } + map* pmTransmissionMode=NULL; + map* pmPresence=getMap(resu->content,"inRequest"); + if(((tmpMap=getMap(resu->content,"value"))!=NULL || + (getMap(resu->content,"generated_file"))!=NULL) && + (pmPresence!=NULL && strncmp(pmPresence->value,"true",4)==0)){ + map* tmpMap1=NULL; + if((tmpMap1=getMap(resu->content,"transmissionMode"))!=NULL) { + pmTransmissionMode=getMap(resu->content,"transmissionMode"); + if(strcmp(tmpMap1->value,"value")==0) { + map* tmpMap2=getMap(resu->content,"mimeType"); + if(tmpMap2!=NULL && strstr(tmpMap2->value,"json")!=NULL){ + json_object *jobj = NULL; + map *gfile=getMap(resu->content,"generated_file"); + if(gfile!=NULL){ + gfile=getMap(resu->content,"expected_generated_file"); + if(gfile==NULL){ + gfile=getMap(resu->content,"generated_file"); + } + jobj=json_readFile(conf,gfile->value); } - else { - // Obtain default file extension (see mimetypes.h). - // If the MIME type is not recognized, txt is used as the default extension - map* mtype=getMap(resu->content,"mimeType"); - getFileExtension(mtype != NULL ? mtype->value : NULL, file_ext, 32); + else{ + int slen = 0; + enum json_tokener_error jerr; + struct json_tokener* tok=json_tokener_new(); + do { + slen = strlen(tmpMap->value); + jobj = json_tokener_parse_ex(tok, tmpMap->value, slen); + } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); + if (jerr != json_tokener_success) { + fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); + return eres1; + } + if (tok->char_offset < slen){ + return eres1; + } } - if(file_name!=NULL) - free(file_name); - - file_name=(char*)malloc((strlen(s->name)+strlen(usid->value)+strlen(file_ext)+strlen(resu->name)+45)*sizeof(char)); - sprintf(file_name,"ZOO_DATA_%s_%s_%s_%d.%s",s->name,resu->name,usid->value,itn,file_ext); - - file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char)); - sprintf(file_path,"%s/%s",tmp1->value,file_name); + json_object_object_add(res3,"encoding",json_object_new_string("utf-8")); + json_object_object_add(res1,"value",jobj); }else{ - file_path=(char*)malloc((strlen(gfile->value)+1)*sizeof(char)); - sprintf(file_path,"%s",gfile->value); + map* tmp1=getMapFromMaps(conf,"main","tmpPath"); + map *gfile=getMap(resu->content,"generated_file"); + if(gfile!=NULL){ + gfile=getMap(resu->content,"expected_generated_file"); + if(gfile==NULL){ + gfile=getMap(resu->content,"generated_file"); + } + FILE* pfData=fopen(gfile->value,"rb"); + if(pfData!=NULL){ + zStatStruct f_status; + int s=zStat(gfile->value, &f_status); + if(f_status.st_size>0){ + char* pcaTmp=(char*)malloc((f_status.st_size+1)*sizeof(char)); + fread(pcaTmp,1,f_status.st_size,pfData); + pcaTmp[f_status.st_size]=0; + fclose(pfData); + outputSingleJsonComplexRes(conf,resu,res1,res3,pcaTmp,f_status.st_size); + free(pcaTmp); + } + } + }else{ + json_object_object_add(res3,"encoding",json_object_new_string("utf-8")); + map* tmpMap0=getMap(resu->content,"crs"); + if(tmpMap0!=NULL){ + map* tmpMap2=getMap(resu->content,"value"); + json_object *jobj = NULL; + const char *mystring = NULL; + int slen = 0; + enum json_tokener_error jerr; + struct json_tokener* tok=json_tokener_new(); + do { + mystring = tmpMap2->value; // get JSON string, e.g. read from file, etc... + slen = strlen(mystring); + jobj = json_tokener_parse_ex(tok, mystring, slen); + } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); + if (jerr != json_tokener_success) { + map* pamError=createMap("code","InvalidParameterValue"); + const char* pcTmpErr=json_tokener_error_desc(jerr); + const char* pccErr=_("ZOO-Kernel cannot parse your POST data: %s"); + char* pacMessage=(char*)malloc((strlen(pcTmpErr)+strlen(pccErr)+1)*sizeof(char)); + sprintf(pacMessage,pccErr,pcTmpErr); + addToMap(pamError,"message",pacMessage); + printExceptionReportResponseJ(conf,pamError); + fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); + return NULL; + } + if (tok->char_offset < slen){ + map* pamError=createMap("code","InvalidParameterValue"); + const char* pcTmpErr="None"; + const char* pccErr=_("ZOO-Kernel cannot parse your POST data: %s"); + char* pacMessage=(char*)malloc((strlen(pcTmpErr)+strlen(pccErr)+1)*sizeof(char)); + sprintf(pacMessage,pccErr,pcTmpErr); + addToMap(pamError,"message",pacMessage); + printExceptionReportResponseJ(conf,pamError); + fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); + return NULL; + } + json_object_object_add(res1,"bbox",jobj); + json_object_object_add(res1,"crs",json_object_new_string(tmpMap0->value)); + } + else{ + if(getMap(resu->content,"mimeType")!=NULL){ + map* pmSize=getMap(resu->content,"size"); + long len=0; + if(pmSize!=NULL) + len=atol(pmSize->value); + else + len=strlen(tmpMap->value); + outputSingleJsonComplexRes(conf,resu,res1,res3,tmpMap->value,len); + } + else + json_object_object_add(res1,"value",json_object_new_string(tmpMap->value)); + } + } + if(getMapFromMaps(conf,"oas","noformat")!=NULL){ + // This is an option to not use the format key and allocate + // a the format object keys to the result itself + map* tmpMap0=getMap(resu->content,"crs"); + if(tmpMap0==NULL){ + json_object_object_foreach(res3, key, val) { + if(strncasecmp(key,pccFields[0],4)==0 || + strncasecmp(key,pccFields[3],8)==0 || + strncasecmp(key,pccFields[6],15)==0) + json_object_object_add(res1,pccFields[3],json_object_new_string(json_object_get_string(val))); + if(strncasecmp(key,pccFields[1],4)==0 || + strncasecmp(key,pccFields[4],8)==0 || + strncasecmp(key,pccFields[7],15)==0) + json_object_object_add(res1,pccFields[4],json_object_new_string(json_object_get_string(val))); + if(strncasecmp(key,pccFields[2],4)==0 || + strncasecmp(key,pccFields[5],8)==0 || + strncasecmp(key,pccFields[8],15)==0) + json_object_object_add(res1,pccFields[5],json_object_new_string(json_object_get_string(val))); + } + } + } } - - - itn++; - - file_url=(char*)malloc((strlen(tmpUrl->value)+ - strlen(file_name)+2)*sizeof(char)); - sprintf(file_url,"%s/%s",tmpUrl->value,file_name); - - if(gfile==NULL){ - FILE *ofile=fopen(file_path,"wb"); - if(ofile==NULL){ - char tmpMsg[1024]; - sprintf(tmpMsg, - _("Unable to create the file \"%s\" for storing the %s final result."), - file_name,resu->name); - map* error=createMap("code","InternalError"); - addToMap(error,"message",tmpMsg); - printExceptionReportResponseJ(conf,error); - free(file_name); - free(file_path); - return NULL; + } + else{ +#ifdef USE_MS + map* pmTest=getMap(resu->content,"useMapserver"); + if(pmTest!=NULL){ + map* geodatatype=getMap(resu->content,"geodatatype"); + map* nbFeatures; + setMapInMaps(conf,"lenv","state","out"); + setReferenceUrl(conf,resu); + nbFeatures=getMap(resu->content,"nb_features"); + geodatatype=getMap(resu->content,"geodatatype"); + if((nbFeatures!=NULL && atoi(nbFeatures->value)==0) || + (geodatatype!=NULL && strcasecmp(geodatatype->value,"other")==0)){ + //error=1; + //res=SERVICE_FAILED; + }else{ + map* pmUrl=getMap(resu->content,"Reference"); + json_object_object_add(res1,"href", + json_object_new_string(pmUrl->value)); + map* pmMimeType=getMap(resu->content,"requestedMimeType"); + if(pmMimeType!=NULL) + json_object_object_add(res1,pccFields[0],json_object_new_string(pmMimeType->value)); } - - map* toto=getMap(resu->content,"value"); - if(toto==NULL){ - char tmpMsg[1024]; - sprintf(tmpMsg, - _("No value found for the requested output %s."), - resu->name); - map* error=createMap("code","InternalError"); - addToMap(error,"message",tmpMsg); - printExceptionReportResponseJ(conf,error); - fclose(ofile); - free(file_name); - free(file_path); - return NULL; + }else{ +#endif + char *pcaFileUrl=produceFileUrl(s,conf,resu,NULL,itn); + itn++; + if(pcaFileUrl!=NULL){ + json_object_object_add(res1,"href", + json_object_new_string(pcaFileUrl)); + free(pcaFileUrl); } - map* size=getMap(resu->content,"size"); - if(size!=NULL && toto!=NULL) - fwrite(toto->value,1,(atoi(size->value))*sizeof(char),ofile); - else - if(toto!=NULL && toto->value!=NULL) - fwrite(toto->value,1, - strlen(toto->value)*sizeof(char),ofile); - fclose(ofile); + if(getMapFromMaps(conf,"oas","noformat")!=NULL){ + json_object_object_foreach(res3, key, val) { + if(strncasecmp(key,pccFields[0],4)==0 || + strncasecmp(key,pccFields[3],8)==0 || + strncasecmp(key,pccFields[6],15)==0) + json_object_object_add(res1,pccFields[0],json_object_new_string(json_object_get_string(val))); + } + } +#ifdef USE_MS } - json_object_object_add(res2,"href", - json_object_new_string(file_url)); - free(file_url); - free(file_name); - free(file_path); - +#endif + } + } + // Add format to res1 for complex output except json based ones + map* pmTmp1=getMap(resu->content,"mimeType"); + if(pmTmp1!=NULL && getMapFromMaps(conf,"oas","noformat")==NULL){ + if(pmTmp1!=NULL && strstr(pmTmp1->value,"json")==NULL) + json_object_object_add(res1,"format",res3); + } + else + json_object_put(res3); + if(pmIOAsArray!=NULL && strncasecmp(pmIOAsArray->value,"true",4)==0){ + json_object_array_add(eres,res1); + }else{ + map* pmDataType=getMap(resu->content,"dataType"); + if(pmDataType==NULL || (pmTransmissionMode!=NULL && strncasecmp(pmTransmissionMode->value,"reference",9)==0) ) + json_object_object_add(eres,resu->name,res1); + else{ + if(((tmpMap=getMap(resu->content,"value"))!=NULL)) + json_object_object_add(eres,resu->name,json_object_new_string(tmpMap->value)); } - } } - json_object_object_add(res1,"value",res2); - json_object_array_add(eres,res1); + resu=resu->next; + } + const char* jsonStr = + json_object_to_json_string_ext(eres,JSON_C_TO_STRING_NOSLASHESCAPE); + map *tmpPath = getMapFromMaps (conf, "main", "tmpPath"); + map *cIdentifier = getMapFromMaps (conf, "lenv", "oIdentifier"); + map *sessId = getMapFromMaps (conf, "lenv", "usid"); + char *pacTmp=(char*)malloc((strlen(tmpPath->value)+strlen(cIdentifier->value)+strlen(sessId->value)+8)*sizeof(char)); + sprintf(pacTmp,"%s/%s_%s.json", + tmpPath->value,cIdentifier->value,sessId->value); + zStatStruct zsFStatus; + int iS=zStat(pacTmp, &zsFStatus); + if(iS==0 && zsFStatus.st_size>0){ + map* tmpPath1 = getMapFromMaps (conf, "main", "tmpUrl"); + char* pacTmpUrl=(char*)malloc((strlen(tmpPath1->value)+strlen(cIdentifier->value)+strlen(sessId->value)+8)*sizeof(char));; + sprintf(pacTmpUrl,"%s/%s_%s.json",tmpPath1->value, + cIdentifier->value,sessId->value); + if(getMapFromMaps(conf,"lenv","gs_location")==NULL) + setMapInMaps(conf,"headers","Location",pacTmpUrl); + free(pacTmpUrl); } - resu=resu->next; + free(pacTmp); + if(res==3){ + map* mode=getMapFromMaps(conf,"request","mode"); + if(mode!=NULL && strncasecmp(mode->value,"async",5)==0) + setMapInMaps(conf,"headers","Status","201 Created"); + else + setMapInMaps(conf,"headers","Status","200 OK"); + } + else{ + setMapInMaps(conf,"headers","Status","500 Issue running your service"); + } + return eres; } - json_object_object_add(eres1,"outputs",eres); - const char* jsonStr = - json_object_to_json_string_ext(eres1,JSON_C_TO_STRING_PLAIN); - map *tmpPath = getMapFromMaps (conf, "main", "tmpPath"); - map *cIdentifier = getMapFromMaps (conf, "lenv", "oIdentifier"); - map *sessId = getMapFromMaps (conf, "lenv", "usid"); - char tmp[1024]; - sprintf(tmp,"%s/%s_%s.json", - tmpPath->value,cIdentifier->value,sessId->value); - FILE* foutput=fopen(tmp,"w+"); - - - fprintf(stderr,"/////////////////////%s//////////////////////// \n",tmp ); - - - if(foutput!=NULL){ - fclose(foutput); - char tmpUrl[1024]; - map* tmpPath1 = getMapFromMaps (conf, "main", "tmpUrl"); + } - int wpLen=0; - char* wp=NULL; - map* eoUserMap=getMapFromMaps(conf,"eoepcaUser","user"); - if (eoUserMap && eoUserMap->value){ - wpLen=strlen(eoUserMap->value); - wp=(char*)malloc((10+wpLen)*sizeof(char)); - memset(wp,0,(10+wpLen)*sizeof(char)); - sprintf(wp,"/%s",eoUserMap->value); + /** + * Append required field to Json objects for a complex output + * + * @param conf maps pointer to the main configuration maps + * @param resu maps pointer to the output + * @param res1 json_object pointer to which the value field should be added + * @param res3 json_object pointer to the format object associated with res1 + * @param pacValue char pointer to the value to be allocated + * @param len length of pacValue + */ + void outputSingleJsonComplexRes(maps* conf,maps* resu,json_object* res1,json_object* res3,char* apcValue, long len){ + map* pmMediaType=getMap(resu->content,"mediaType"); + if(pmMediaType==NULL) + pmMediaType=getMap(resu->content,"mimeType"); + if(pmMediaType!=NULL && + (strstr(pmMediaType->value,"json")!=NULL || strstr(pmMediaType->value,"text")!=NULL || strstr(pmMediaType->value,"kml")!=NULL)){ + if(strstr(pmMediaType->value,"json")!=NULL){ + json_object* pjoaTmp=parseJson(conf,apcValue); + json_object_object_add(res1,"value",pjoaTmp); } + else + json_object_object_add(res1,"value",json_object_new_string(apcValue)); + json_object_object_add(res3,"mediaType",json_object_new_string(pmMediaType->value)); + } + else{ + char* pcaB64=base64(apcValue,len); + json_object_object_add(res1,"value",json_object_new_string(pcaB64)); + json_object_object_add(res3,"encoding",json_object_new_string("base64")); + if(pmMediaType!=NULL) + json_object_object_add(res3,"mediaType",json_object_new_string(pmMediaType->value)); + free(pcaB64); + } + } - sprintf(tmpUrl,"%s%s/%s_%s.json", - (wpLen>0?wp:""), - tmpPath1->value, - cIdentifier->value,sessId->value); - setMapInMaps(conf,"headers","Location",tmpUrl); + /** + * Create a link object with ref, type and href. + * + * @param conf maps pointer to the main configuration maps + * @param rel char pointer defining the rel attribute + * @param type char pointer defining the type attribute + * @param href char pointer defining the href attribute + * @return json_object pointer to the link object + */ + json_object* createALink(maps* conf,const char* rel,const char* type,const char* href){ + json_object* val=json_object_new_object(); + json_object_object_add(val,"rel", + json_object_new_string(rel)); + json_object_object_add(val,"type", + json_object_new_string(type)); + json_object_object_add(val,"href",json_object_new_string(href)); + return val; + } + /** + * Create the next links + * + * @param conf the maps containing the settings of the main.cfg file + * @param result an integer (>0 for adding the /result link) + * @param obj the JSON object pointer to add the links to + * @return 0 + */ + int createNextLinks(maps* conf,json_object* obj){ + json_object* res=json_object_new_array(); + map *tmpPath = getMapFromMaps (conf, "openapi", "rootUrl"); + map *sessId = getMapFromMaps (conf, "lenv", "path"); - fprintf(stderr,"/////////////////////%s//////////////////////// \n",tmpUrl ); + char *Url0=(char*) malloc((strlen(tmpPath->value)+ + strlen(sessId->value)+2)*sizeof(char)); + sprintf(Url0,"%s/%s", + tmpPath->value, + sessId->value); + json_object_array_add(res,createALink(conf,"self","application/json",Url0)); + map* pmHtml=getMapFromMaps(conf,"openapi","partial_html_support"); + if(pmHtml!=NULL && strcmp(pmHtml->value,"true")==0){ + char *Url1=(char*) malloc((strlen(tmpPath->value)+ + strlen(sessId->value)+7)*sizeof(char)); + sprintf(Url1,"%s/%s.html", + tmpPath->value, + sessId->value); + json_object_array_add(res,createALink(conf,"alternate","text/html",Url1)); + free(Url1); } - if(res==3){ - setMapInMaps(conf,"headers","Status","201 Created"); + + map* pmTmp=getMapFromMaps(conf,"lenv","serviceCntSkip"); + map* pmLimit=getMapFromMaps(conf,"lenv","serviceCntLimit"); + map* pmCnt=getMapFromMaps(conf,"lenv","serviceCnt"); + if(pmTmp!=NULL && atoi(pmTmp->value)>0){ + char* pcaTmp=(char*) malloc((strlen(Url0)+strlen(pmLimit->value)+25)*sizeof(char)); + int cnt=atoi(pmTmp->value)-atoi(pmLimit->value); + if(cnt>=0) + sprintf(pcaTmp,"%s?limit=%s&skip=%d",Url0,pmLimit->value,cnt); + else + sprintf(pcaTmp,"%s?limit=%s&skip=%d",Url0,pmLimit->value,0); + json_object_array_add(res,createALink(conf,"prev","application/json",pcaTmp)); + free(pcaTmp); } - else{ - setMapInMaps(conf,"headers","Status","500 Issue running your service"); + if(getMapFromMaps(conf,"lenv","serviceCntNext")!=NULL){ + char* pcaTmp=(char*) malloc((strlen(Url0)+strlen(pmLimit->value)+strlen(pmCnt->value)+15)*sizeof(char)); + int cnt=(pmTmp!=NULL?atoi(pmTmp->value):0)+atoi(pmLimit->value); + sprintf(pcaTmp,"%s?limit=%s&skip=%d",Url0,pmLimit->value,cnt); + json_object_array_add(res,createALink(conf,"next","application/json",pcaTmp)); + free(pcaTmp); } + json_object_object_add(obj,"links",res); + free(Url0); + map* pmNb=getMapFromMaps(conf,"lenv","serviceCnt"); + if(pmNb!=NULL) + json_object_object_add(obj,"numberTotal",json_object_new_int(atoi(pmNb->value))); - return eres1; + return 0; } - /** * Create the status links * @@ -1284,71 +2098,59 @@ extern "C" { int createStatusLinks(maps* conf,int result,json_object* obj){ json_object* res=json_object_new_array(); map *tmpPath = getMapFromMaps (conf, "openapi", "rootUrl"); - map *cIdentifier = getMapFromMaps (conf, "lenv", "oIdentifier"); map *sessId = getMapFromMaps (conf, "lenv", "usid"); + if(sessId==NULL){ + sessId = getMapFromMaps (conf, "lenv", "gs_usid"); + } int wpLen=0; char* wp=NULL; - map* eoUserMap=getMapFromMaps(conf,"eoepcaUser","user"); - if (eoUserMap && eoUserMap->value){ - wpLen=strlen(eoUserMap->value); - wp=(char*)malloc((10+wpLen)*sizeof(char)); - memset(wp,0,(10+wpLen)*sizeof(char)); - sprintf(wp,"/%s",eoUserMap->value); - }else{ - fprintf(stderr,"///////////////////////////////////////////// \n" ); - fprintf(stderr,"workspace did not define\n"); - fprintf(stderr,"///////////////////////////////////////////// \n" ); - } - char *Url0=(char*) malloc(wpLen*(strlen(tmpPath->value)+ - strlen(cIdentifier->value)+ + char *Url0=(char*) malloc((strlen(tmpPath->value)+ strlen(sessId->value)+18)*sizeof(char)); int needResult=-1; char *message, *status; - sprintf(Url0,"%s%s/processes/%s/jobs/%s", - (wpLen>0?wp:""), + sprintf(Url0,"%s/jobs/%s", tmpPath->value, - cIdentifier->value, sessId->value); - setMapInMaps(conf,"headers","Location",Url0); + + if(getMapFromMaps(conf,"lenv","gs_location")==NULL) + setMapInMaps(conf,"headers","Location",Url0); json_object* val=json_object_new_object(); - json_object_object_add(val,"Title", + json_object_object_add(val,"title", json_object_new_string(_("Status location"))); + json_object_object_add(val,"rel", + json_object_new_string("status")); + json_object_object_add(val,"type", + json_object_new_string("application/json")); json_object_object_add(val,"href",json_object_new_string(Url0)); json_object_array_add(res,val); if(result>0){ - fprintf(stderr, "Setting Result Location\n"); free(Url0); - - fprintf(stderr, (wpLen>0?" workspace name length is greater than 0\n":"")); - fprintf(stderr, "workspace is %s", wp); - - Url0=(char*) malloc(wpLen*(strlen(tmpPath->value)+ - strlen(cIdentifier->value)+ - strlen(sessId->value)+25)*sizeof(char)); - - fprintf(stderr, "result location is %s%s/processes/%s/jobs/%s/result", - (wpLen>0?wp:""), - tmpPath->value, - cIdentifier->value, - sessId->value); - - sprintf(Url0,"%s%s/processes/%s/jobs/%s/result", - (wpLen>0?wp:""), + Url0=(char*) malloc((strlen(tmpPath->value)+ + strlen(sessId->value)+ + 25)*sizeof(char)); + sprintf(Url0,"%s/jobs/%s/results", tmpPath->value, - cIdentifier->value, sessId->value); json_object* val1=json_object_new_object(); - json_object_object_add(val1,"Title", + json_object_object_add(val1,"title", json_object_new_string(_("Result location"))); + map* pmTmp=getMapFromMaps(conf,"/jobs/{jobID}/results","rel"); + if(pmTmp!=NULL) + json_object_object_add(val1,"rel", + json_object_new_string(pmTmp->value)); + else + json_object_object_add(val1,"rel", + json_object_new_string("results")); + json_object_object_add(val1,"type", + json_object_new_string("application/json")); json_object_object_add(val1,"href",json_object_new_string(Url0)); json_object_array_add(res,val1); } json_object_object_add(obj,"links",res); free(Url0); - free(wp); return 0; } @@ -1359,10 +2161,7 @@ extern "C" { * @return a char* containing the full status file path */ char* json_getStatusFilePath(maps* conf){ - - map *tmpPath = getMapFromMaps (conf, "main", "tmpPath"); - map *cIdentifier = getMapFromMaps (conf, "lenv", "oIdentifier"); map *sessId = getMapFromMaps (conf, "lenv", "usid"); if(sessId!=NULL){ sessId = getMapFromMaps (conf, "lenv", "gs_usid"); @@ -1370,52 +2169,41 @@ extern "C" { sessId = getMapFromMaps (conf, "lenv", "usid"); }else sessId = getMapFromMaps (conf, "lenv", "gs_usid"); - char *tmp1=(char*) malloc((strlen(tmpPath->value)+ - strlen(cIdentifier->value)+14)*sizeof(char) + /*rdr*/ (1024*sizeof(char)) ); + + char *tmp1=(char*) malloc((strlen(tmpPath->value)+14)*sizeof(char) + + /*rdr*/ (1024*sizeof(char)) ); map *userMap = getMapFromMaps (conf, "eoepcaUser", "user"); if (userMap && userMap->value && strlen(userMap->value)>0 ){ - sprintf(tmp1,"%s/statusInfos/%s/%s", - tmpPath->value,userMap->value, - cIdentifier->value); - fprintf(stderr,"--------------1--%s %s\n",tmp1,cIdentifier->value); + sprintf(tmp1,"%s/%s", + tmpPath->value,userMap->value); + fprintf(stderr,"--------------1--%s \n",tmp1); }else{ - sprintf(tmp1,"%s/statusInfos/%s", - tmpPath->value, - cIdentifier->value); - fprintf(stderr,"--------------2--%s %s\n",tmp1,cIdentifier->value); + sprintf(tmp1,"%s/", + tmpPath->value); + fprintf(stderr,"--------------2--%s \n",tmp1); } -// sprintf(tmp1,"%s/statusInfos/%s", -// tmpPath->value, -// cIdentifier->value); -// fprintf(stderr,"--------------2--%s %s\n",tmp1,cIdentifier->value); - - if(mkdir(tmp1,0777) != 0 && errno != EEXIST){ fprintf(stderr,"Issue creating directory %s\n",tmp1); return NULL; } free(tmp1); tmp1=(char*) malloc((strlen(tmpPath->value)+ - strlen(cIdentifier->value)+ strlen(sessId->value)+20)*sizeof(char) + /*rdr*/ (1024*sizeof(char))); int needResult=0; char *message, *rstatus; - if (userMap && userMap->value && strlen(userMap->value)>0 ){ - sprintf(tmp1,"%s/statusInfos/%s/%s/%s.json", + sprintf(tmp1,"%s/%s/%s.json", tmpPath->value,userMap->value, - cIdentifier->value, sessId->value); }else{ - sprintf(tmp1,"%s/statusInfos/%s/%s.json", + sprintf(tmp1,"%s/%s.json", tmpPath->value, - cIdentifier->value, sessId->value); } @@ -1423,21 +2211,93 @@ extern "C" { } /** - * Create the status file + * Get the result path * - * @param conf the maps containing the settings of the main.cfg file - * @param status an integer (SERVICE_ACCEPTED,SERVICE_STARTED...) - * @return an integer (0 in case of success, 1 in case of failure) + * @param conf the conf maps containing the main.cfg settings + * @param jobId the job identifier + * @return the full path to the result file */ - int createStatusFile(maps* conf,int status){ + char* getResultPath(maps* conf,char* jobId){ + map *tmpPath = getMapFromMaps (conf, "main", "tmpPath"); + char *pacUrl=(char*) malloc((strlen(tmpPath->value)+ + strlen(jobId)+8)*sizeof(char)); + sprintf(pacUrl,"%s/%s.json",tmpPath->value,jobId); + return pacUrl; + } + + /** + * Parse a json string + * + * @param conf the conf maps containing the main.cfg settings + * @param myString the string containing the json content + * @return a pointer to the created json_object + */ + json_object* parseJson(maps* conf,char* myString){ + json_object *pajObj = NULL; + enum json_tokener_error jerr; + struct json_tokener* tok=json_tokener_new(); + int slen = 0; + do { + slen = strlen(myString); + pajObj = json_tokener_parse_ex(tok, myString, slen); + } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); + if (jerr != json_tokener_success) { + setMapInMaps(conf,"lenv","message",json_tokener_error_desc(jerr)); + fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); + return NULL; + } + if (tok->char_offset < slen){ + fprintf(stderr, "Error parsing json\n"); + return NULL; + } + return pajObj; + } + + /** + * Read a json file + * + * @param conf the conf maps containing the main.cfg settings + * @praam filePath the file path to read + * @return a pointer to the created json_object + */ + json_object* json_readFile(maps* conf,char* filePath){ + json_object *pajObj = NULL; + zStatStruct zsFStatus; + int iS=zStat(filePath, &zsFStatus); + if(iS==0 && zsFStatus.st_size>0){ + FILE* cdat=fopen(filePath,"rb"); + if(cdat!=NULL){ + char* pacMyString=(char*)malloc((zsFStatus.st_size+1)*sizeof(char)); + fread(pacMyString,1,zsFStatus.st_size,cdat); + pacMyString[zsFStatus.st_size]=0; + fclose(cdat); + pajObj=parseJson(conf,pacMyString); + free(pacMyString); + } + else + return NULL; + }else + return NULL; + return pajObj; + } + + /** + * Create the json object for job status + * + * @param conf the conf maps containing the main.cfg settings + * @param status integer + * @return the created json_object + */ + json_object* createStatus(maps* conf,int status){ + int hasMessage=0; int needResult=0; - const char *message, *rstatus; - char* tmp1=json_getStatusFilePath(conf); + int isDismissed=0; + const char *rstatus; + char *message; // Create statusInfo JSON object // cf. https://github.com/opengeospatial/wps-rest-binding/blob/master/core/ // openapi/schemas/statusInfo.yaml json_object* res=json_object_new_object(); - json_object_object_add(res,"status",json_object_new_string("successful")); switch(status){ case SERVICE_ACCEPTED: { @@ -1448,6 +2308,15 @@ extern "C" { case SERVICE_STARTED: { message=_("ZOO-Kernel is currently running your service!"); + map* pmStatus=getMapFromMaps(conf,"lenv","message"); + if(pmStatus!=NULL){ + setMapInMaps(conf,"lenv","gs_message",pmStatus->value); + message=zStrdup(pmStatus->value); + hasMessage=1; + } + map* mMap=NULL; + if((mMap=getMapFromMaps(conf,"lenv","PercentCompleted"))!=NULL) + json_object_object_add(res,"progress",json_object_new_int(atoi(mMap->value))); rstatus="running"; break; } @@ -1459,30 +2328,107 @@ extern "C" { } case SERVICE_SUCCEEDED: { - message=_("ZOO-Kernel successfully ran your service!"); + message=_("ZOO-Kernel successfully run your service!"); rstatus="successful"; + setMapInMaps(conf,"lenv","PercentCompleted","100"); + needResult=1; + break; + } + case SERVICE_DISMISSED: + { + message=_("ZOO-Kernel successfully dismissed your service!"); + rstatus="dismissed"; needResult=1; + isDismissed=1; break; } default: { - message=_("ZOO-Kernel failed to run your service!"); + map* pmTmp=getMapFromMaps(conf,"lenv","force"); + if(pmTmp==NULL || strncasecmp(pmTmp->value,"false",5)==0){ + char* pacTmp=json_getStatusFilePath(conf); + json_object* pjoStatus=json_readFile(conf,pacTmp); + free(pacTmp); + if(pjoStatus!=NULL){ + json_object* pjoMessage=NULL; + if(json_object_object_get_ex(pjoStatus,"message",&pjoMessage)!=FALSE){ + message=(char*)json_object_get_string(pjoMessage); + } + } + // TODO: Error + }else{ + map* mMap=getMapFromMaps(conf,"lenv","gs_message"); + if(mMap!=NULL) + setMapInMaps(conf,"lenv","message",mMap->value); + message=produceErrorMessage(conf); + hasMessage=1; + needResult=-1; + } rstatus="failed"; break; } } setMapInMaps(conf,"lenv","message",message); - setMapInMaps(conf,"lenv","status",rstatus); - - map* mess=getMapFromMaps(conf,"lenv","message"); - if(mess!=NULL) - json_object_object_add(res,"message",json_object_new_string(mess->value)); - - createStatusLinks(conf,needResult,res); + map *sessId = getMapFromMaps (conf, "lenv", "usid"); + if(sessId!=NULL){ + sessId = getMapFromMaps (conf, "lenv", "gs_usid"); + if(sessId==NULL) + sessId = getMapFromMaps (conf, "lenv", "usid"); + }else + sessId = getMapFromMaps (conf, "lenv", "gs_usid"); + if(sessId!=NULL && isDismissed==0){ + json_object_object_add(res,"jobID",json_object_new_string(sessId->value)); +#ifdef RELY_ON_DB + for(int i=0;i<6;i++){ + char* pcaTmp=_getStatusField(conf,sessId->value,statusFieldsC[i]); + if(pcaTmp!=NULL && strcmp(pcaTmp,"-1")!=0){ + json_object_object_add(res,statusFields[i],json_object_new_string(pcaTmp)); + } + if(pcaTmp!=NULL && strncmp(pcaTmp,"-1",2)==0) + free(pcaTmp); + } +#endif + } + json_object_object_add(res,"status",json_object_new_string(rstatus)); + json_object_object_add(res,"message",json_object_new_string(message)); + if(status!=SERVICE_DISMISSED) + createStatusLinks(conf,needResult,res); + else{ + json_object* res1=json_object_new_array(); + map *tmpPath = getMapFromMaps (conf, "openapi", "rootUrl"); + char *Url0=(char*) malloc((strlen(tmpPath->value)+17)*sizeof(char)); + sprintf(Url0,"%s/jobs",tmpPath->value); + json_object* val=json_object_new_object(); + json_object_object_add(val,"title", + json_object_new_string(_("The job list for the current process"))); + json_object_object_add(val,"rel", + json_object_new_string("parent")); + json_object_object_add(val,"type", + json_object_new_string("application/json")); + json_object_object_add(val,"href",json_object_new_string(Url0)); + json_object_array_add(res1,val); + free(Url0); + json_object_object_add(res,"links",res1); + } + if(hasMessage>0) + free(message); + return res; + } + + /** + * Create the status file + * + * @param conf the maps containing the settings of the main.cfg file + * @param status an integer (SERVICE_ACCEPTED,SERVICE_STARTED...) + * @return an integer (0 in case of success, 1 in case of failure) + */ + int createStatusFile(maps* conf,int status){ + json_object* res=createStatus(conf,status); + char* tmp1=json_getStatusFilePath(conf); FILE* foutput1=fopen(tmp1,"w+"); if(foutput1!=NULL){ - const char* jsonStr1=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN); + const char* jsonStr1=json_object_to_json_string_ext(res,JSON_C_TO_STRING_NOSLASHESCAPE); fprintf(foutput1,"%s",jsonStr1); fclose(foutput1); }else{ @@ -1496,7 +2442,7 @@ extern "C" { } /** - * Create the status file + * Create the status file * * @param conf the maps containing the settings of the main.cfg file * @return an integer (0 in case of success, 1 in case of failure) @@ -1507,18 +2453,21 @@ extern "C" { map* tmpMap=getMapFromMaps(conf,"lenv","gs_usid"); if(tmpMap!=NULL){ - char* tmpStr=_getStatus(conf,tmpMap->value); - if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){ - char *tmpStr1=zStrdup(tmpStr); - char *tmpStr0=zStrdup(strstr(tmpStr,"|")+1); - free(tmpStr); - tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0'; - setMapInMaps(conf,"lenv","PercentCompleted",tmpStr1); - setMapInMaps(conf,"lenv","gs_message",tmpStr0); - free(tmpStr0); - free(tmpStr1); - } + char* tmpStr=_getStatus(conf,tmpMap->value); + if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){ + char *tmpStr1=zStrdup(tmpStr); + char *tmpStr0=zStrdup(strstr(tmpStr,"|")+1); + free(tmpStr); + tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0'; + setMapInMaps(conf,"lenv","PercentCompleted",tmpStr1); + setMapInMaps(conf,"lenv","gs_message",tmpStr0); + free(tmpStr0); + free(tmpStr1); + return 0; + }else{ + } + } } /** @@ -1543,14 +2492,17 @@ extern "C" { } tmpMap=getMapFromMaps(conf,"identification","abstract"); if(tmpMap!=NULL){ - json_object_object_add(res1,"description",json_object_new_string(tmpMap->value)); - json_object_object_add(res5,"description",json_object_new_string(tmpMap->value)); - tmpMap=getMapFromMaps(conf,"openapi","rootUrl"); - json_object_object_add(res5,"url",json_object_new_string(tmpMap->value)); + json_object_object_add(res1,"description",json_object_new_string(_(tmpMap->value))); + json_object_object_add(res5,"description",json_object_new_string(_(tmpMap->value))); } - tmpMap=getMapFromMaps(conf,"identification","title"); + tmpMap=getMapFromMaps(conf,"openapi","rootUrl"); if(tmpMap!=NULL) - json_object_object_add(res1,"title",json_object_new_string(tmpMap->value)); + json_object_object_add(res5,"url",json_object_new_string(tmpMap->value)); + tmpMap=getMapFromMaps(conf,"identification","title"); + if(tmpMap!=NULL){ + json_object_object_add(res1,"title",json_object_new_string(_(tmpMap->value))); + json_object_object_add(res5,"description",json_object_new_string(_(tmpMap->value))); + } json_object_object_add(res1,"version",json_object_new_string(ZOO_VERSION)); tmpMap=getMapFromMaps(conf,"identification","keywords"); if(tmpMap!=NULL){ @@ -1575,19 +2527,125 @@ extern "C" { } json_object *res4=json_object_new_object(); - tmpMap=getMapFromMaps(conf,"main","license_name"); + tmpMap=getMapFromMaps(conf,"openapi","license_name"); if(tmpMap!=NULL){ json_object_object_add(res4,"name",json_object_new_string(tmpMap->value)); - tmpMap=getMapFromMaps(conf,"main","license_url"); + tmpMap=getMapFromMaps(conf,"openapi","license_url"); if(tmpMap!=NULL){ - json_object_object_add(res4,"url",json_object_new_string(tmpMap->value)); + json_object_object_add(res4,"url",json_object_new_string(tmpMap->value)); } } json_object_object_add(res1,"license",res4); - json_object_object_add(res,"info",res1); + json_object_object_add(res,"info",res1); } + // addResponse(pmUseContent,cc3,vMap,tMap,"200","successful operation"); + void addResponse(const map* useContent,json_object* res,const map* pmSchema,const map* pmType,const char* code,const char* msg){ + json_object *cc=json_object_new_object(); + if(pmSchema!=NULL) + json_object_object_add(cc,"$ref",json_object_new_string(pmSchema->value)); + if(useContent!=NULL && strncasecmp(useContent->value,"true",4)!=0){ + json_object_object_add(res,code,cc); + }else{ + json_object *cc0=json_object_new_object(); + if(pmSchema!=NULL) + json_object_object_add(cc0,"schema",cc); + json_object *cc1=json_object_new_object(); + if(pmType!=NULL) + json_object_object_add(cc1,pmType->value,cc0); + else + json_object_object_add(cc1,"application/json",cc0); + json_object *cc2=json_object_new_object(); + json_object_object_add(cc2,"content",cc1); + json_object_object_add(cc2,"description",json_object_new_string(msg)); + json_object_object_add(res,code,cc2); + } + } + + void addParameter(maps* conf,const char* oName,const char* fName,const char* in,json_object* res){ + maps* tmpMaps1=getMaps(conf,oName); + json_object *res8=json_object_new_object(); + int hasSchema=0; + if(tmpMaps1!=NULL){ + map* tmpMap=getMap(tmpMaps1->content,"title"); + if(tmpMap!=NULL) + json_object_object_add(res8,"x-internal-summary",json_object_new_string(_(tmpMap->value))); + tmpMap=getMap(tmpMaps1->content,"schema"); + if(tmpMap!=NULL){ + json_object_object_add(res8,"$ref",json_object_new_string(tmpMap->value)); + hasSchema=1; + } + tmpMap=getMap(tmpMaps1->content,"abstract"); + if(tmpMap!=NULL) + json_object_object_add(res8,"description",json_object_new_string(_(tmpMap->value))); + tmpMap=getMap(tmpMaps1->content,"example"); + if(tmpMap!=NULL) + json_object_object_add(res8,"example",json_object_new_string(tmpMap->value)); + tmpMap=getMap(tmpMaps1->content,"required"); + if(tmpMap!=NULL){ + if(strcmp(tmpMap->value,"true")==0) + json_object_object_add(res8,"required",json_object_new_boolean(TRUE)); + else + json_object_object_add(res8,"required",json_object_new_boolean(FALSE)); + } + else + if(hasSchema==0) + json_object_object_add(res8,"required",json_object_new_boolean(FALSE)); + map* pmTmp=getMap(tmpMaps1->content,"in"); + if(pmTmp!=NULL) + json_object_object_add(res8,"in",json_object_new_string(pmTmp->value)); + else + if(hasSchema==0) + json_object_object_add(res8,"in",json_object_new_string(in)); + tmpMap=getMap(tmpMaps1->content,"name"); + if(tmpMap!=NULL) + json_object_object_add(res8,"name",json_object_new_string(tmpMap->value)); + else + if(hasSchema==0) + json_object_object_add(res8,"name",json_object_new_string(fName)); + tmpMap=getMap(tmpMaps1->content,"schema"); + if(tmpMap==NULL){ + json_object *res6=json_object_new_object(); + tmpMap=getMap(tmpMaps1->content,"type"); + char* pcaType=NULL; + if(tmpMap!=NULL){ + json_object_object_add(res6,"type",json_object_new_string(tmpMap->value)); + pcaType=zStrdup(tmpMap->value); + } + else + json_object_object_add(res6,"type",json_object_new_string("string")); + + tmpMap=getMap(tmpMaps1->content,"enum"); + if(tmpMap!=NULL){ + char *saveptr12; + char *tmps12 = strtok_r (tmpMap->value, ",", &saveptr12); + json_object *pjoEnum=json_object_new_array(); + while(tmps12!=NULL){ + json_object_array_add(pjoEnum,json_object_new_string(tmps12)); + tmps12 = strtok_r (NULL, ",", &saveptr12); + } + json_object_object_add(res6,"enum",pjoEnum); + } + + pmTmp=tmpMaps1->content; + while(pmTmp!=NULL){ + if(strstr(pmTmp->name,"schema_")!=NULL){ + if(pcaType!=NULL && strncmp(pcaType,"integer",7)==0){ + json_object_object_add(res6,strstr(pmTmp->name,"schema_")+7,json_object_new_int(atoi(pmTmp->value))); + }else + json_object_object_add(res6,strstr(pmTmp->name,"schema_")+7,json_object_new_string(pmTmp->value)); + } + pmTmp=pmTmp->next; + } + if(pcaType!=NULL) + free(pcaType); + json_object_object_add(res8,"schema",res6); + } + } + json_object_object_add(res,fName,res8); + } + /** * Produce the JSON object for api parameter * @@ -1601,106 +2659,40 @@ extern "C" { char *saveptr12; char *tmps12 = strtok_r (tmpMap2->value, ",", &saveptr12); while(tmps12!=NULL){ - char* tmpId=(char*) malloc((strlen(tmps12)+3)*sizeof(char)); - sprintf(tmpId,"{%s}",tmps12); - tmpMaps1=getMaps(conf,tmpId); - json_object *res8=json_object_new_object(); - if(tmpMaps1!=NULL){ - map* tmpMap=getMap(tmpMaps1->content,"title"); - if(tmpMap!=NULL) - json_object_object_add(res8,"x-internal-summary",json_object_new_string(tmpMap->value)); - tmpMap=getMap(tmpMaps1->content,"abstract"); - if(tmpMap!=NULL) - json_object_object_add(res8,"description",json_object_new_string(tmpMap->value)); - tmpMap=getMap(tmpMaps1->content,"example"); - if(tmpMap!=NULL) - json_object_object_add(res8,"example",json_object_new_string(tmpMap->value)); - tmpMap=getMap(tmpMaps1->content,"required"); - if(tmpMap!=NULL){ - if(strcmp(tmpMap->value,"true")==0) - json_object_object_add(res8,"required",json_object_new_boolean(TRUE)); - else - json_object_object_add(res8,"required",json_object_new_boolean(FALSE)); - } - else - json_object_object_add(res8,"required",json_object_new_boolean(FALSE)); - json_object_object_add(res8,"in",json_object_new_string("path")); - json_object_object_add(res8,"name",json_object_new_string(tmps12)); - json_object *res6=json_object_new_object(); - json_object *res7=json_object_new_object(); - tmpMap=getMap(tmpMaps1->content,"type"); - if(tmpMap!=NULL) - json_object_object_add(res6,"type",json_object_new_string(tmpMap->value)); - else - json_object_object_add(res6,"type",json_object_new_string("string")); - - json_object_object_add(res8,"schema",res6); - - } - - json_object_object_add(res9,tmps12,res8); + char* pacId=(char*) malloc((strlen(tmps12)+3)*sizeof(char)); + sprintf(pacId,"{%s}",tmps12); + addParameter(conf,pacId,tmps12,"path",res9); + free(pacId); tmps12 = strtok_r (NULL, ",", &saveptr12); - } + } tmpMap2=getMapFromMaps(conf,"openapi","header_parameters"); - char *saveptr13; - char *tmps13 = strtok_r (tmpMap2->value, ",", &saveptr13); - while(tmps13!=NULL){ - char* tmpId=zStrdup(tmps13); - maps *tmpMaps2=getMaps(conf,tmpId); - json_object *res8=json_object_new_object(); - if(tmpMaps2!=NULL){ - map* tmpMap=getMap(tmpMaps2->content,"title"); - if(tmpMap!=NULL) - json_object_object_add(res8,"x-internal-summary",json_object_new_string(tmpMap->value)); - tmpMap=getMap(tmpMaps2->content,"abstract"); - if(tmpMap!=NULL) - json_object_object_add(res8,"description",json_object_new_string(tmpMap->value)); - tmpMap=getMap(tmpMaps2->content,"example"); - if(tmpMap!=NULL) - json_object_object_add(res8,"example",json_object_new_string(tmpMap->value)); - tmpMap=getMap(tmpMaps2->content,"required"); - if(tmpMap!=NULL){ - if(strcmp(tmpMap->value,"true")==0) - json_object_object_add(res8,"required",json_object_new_boolean(TRUE)); - else - json_object_object_add(res8,"required",json_object_new_boolean(FALSE)); - } - else - json_object_object_add(res8,"required",json_object_new_boolean(FALSE)); - json_object_object_add(res8,"in",json_object_new_string("header")); - tmpMap=getMap(tmpMaps2->content,"name"); - if(tmpMap!=NULL) - json_object_object_add(res8,"name",json_object_new_string(tmpMap->value)); - json_object *res6=json_object_new_object(); - json_object *res7=json_object_new_object(); - tmpMap=getMap(tmpMaps2->content,"type"); - if(tmpMap!=NULL) - json_object_object_add(res6,"type",json_object_new_string(tmpMap->value)); - else - json_object_object_add(res6,"type",json_object_new_string("string")); - - { - tmpMap=getMap(tmpMaps2->content,"enum"); - if(tmpMap!=NULL){ - char *saveptr11; - char *tmps11 = strtok_r (tmpMap->value, ",", &saveptr11); - json_object *res71=json_object_new_array(); - while(tmps11!=NULL){ - json_object_array_add(res71,json_object_new_string(tmps11)); - tmps11 = strtok_r (NULL, ",", &saveptr11); - } - json_object_object_add(res6,"enum",res71); - } - } - - json_object_object_add(res8,"schema",res6); - + if(tmpMap2!=NULL){ + char *saveptr13; + char *tmps13 = strtok_r (tmpMap2->value, ",", &saveptr13); + while(tmps13!=NULL){ + char* pacId=zStrdup(tmps13); + addParameter(conf,pacId,pacId,"header",res9); + free(pacId); + tmps13 = strtok_r (NULL, ",", &saveptr13); } - - json_object_object_add(res9,tmpId,res8); - tmps13 = strtok_r (NULL, ",", &saveptr13); } json_object_object_add(res,"parameters",res9); + maps* pmResponses=getMaps(conf,"responses"); + if(pmResponses!=NULL){ + json_object *cc=json_object_new_object(); + map* pmLen=getMap(pmResponses->content,"length"); + int iLen=atoi(pmLen->value); + map* pmUseContent=getMapFromMaps(conf,"openapi","use_content"); + for(int i=0;icontent,"code",i); + map* vMap=getMapArray(pmResponses->content,"schema",i); + map* tMap=getMapArray(pmResponses->content,"type",i); + map* tMap0=getMapArray(pmResponses->content,"title",i); + if(vMap!=NULL) + addResponse(pmUseContent,cc,vMap,tMap,cMap->value,(tMap0==NULL)?"successful operation":tMap0->value); + } + json_object_object_add(res,"responses",cc); + } } void produceApiComponents(maps*conf,json_object* res){ @@ -1708,7 +2700,7 @@ extern "C" { produceApiParameters(conf,res1); json_object_object_add(res,"components",res1); } - + /** * Produce the JSON object for /api * @@ -1716,13 +2708,21 @@ extern "C" { * @param res the JSON object to populate */ void produceApi(maps* conf,json_object* res){ + // TODO: add 401 Gone for dismiss request json_object *res9=json_object_new_object(); json_object *res10=json_object_new_object(); maps* tmpMaps1=getMaps(conf,"{id}"); - produceApiComponents(conf,res); json_object *res4=json_object_new_object(); - setMapInMaps(conf,"headers","Content-Type","application/openapi+json; version=3.0;charset=UTF-8"); + map* pmTmp=getMapFromMaps(conf,"/api","type"); + if(pmTmp!=NULL){ + char* pcaTmp=(char*)malloc((15+strlen(pmTmp->value))*sizeof(char)); + sprintf(pcaTmp,"%s;charset=UTF-8",pmTmp->value); + setMapInMaps(conf,"headers","Content-Type",pcaTmp); + free(pcaTmp); + } + else + setMapInMaps(conf,"headers","Content-Type","application/vnd.oai.openapi+json;version=3.0;charset=UTF-8"); produceApiInfo(conf,res,res4); map* tmpMap=getMapFromMaps(conf,"provider","providerName"); @@ -1733,6 +2733,21 @@ extern "C" { else json_object_object_add(res,"openapi",json_object_new_string("3.0.2")); + tmpMap=getMapFromMaps(conf,"openapi","tags"); + if(tmpMap!=NULL){ + json_object *res5=json_object_new_array(); + char *saveptr; + char *tmps = strtok_r (tmpMap->value, ",", &saveptr); + while(tmps!=NULL){ + json_object *res6=json_object_new_object(); + json_object_object_add(res6,"name",json_object_new_string(tmps)); + json_object_object_add(res6,"description",json_object_new_string(tmps)); + json_object_array_add(res5,res6); + tmps = strtok_r (NULL, ",", &saveptr); + } + json_object_object_add(res,"tags",res5); + } + tmpMap=getMapFromMaps(conf,"openapi","paths"); if(tmpMap!=NULL){ json_object *res5=json_object_new_object(); @@ -1744,86 +2759,82 @@ extern "C" { while (tmps != NULL){ tmpMaps=getMaps(conf,tmps+1); json_object *method=json_object_new_object(); + map* pmName=getMap(tmpMaps->content,"pname"); if(tmpMaps!=NULL){ if(getMap(tmpMaps->content,"length")==NULL) addToMap(tmpMaps->content,"length","1"); map* len=getMap(tmpMaps->content,"length"); - + for(int i=0;ivalue);i++){ json_object *methodc=json_object_new_object(); map* cMap=getMapArray(tmpMaps->content,"method",i); map* vMap=getMapArray(tmpMaps->content,"title",i); if(vMap!=NULL) - json_object_object_add(methodc,"summary",json_object_new_string(vMap->value)); + json_object_object_add(methodc,"summary",json_object_new_string(_(vMap->value))); vMap=getMapArray(tmpMaps->content,"abstract",i); if(vMap!=NULL) - json_object_object_add(methodc,"description",json_object_new_string(vMap->value)); + json_object_object_add(methodc,"description",json_object_new_string(_(vMap->value))); vMap=getMapArray(tmpMaps->content,"tags",i); if(vMap!=NULL){ json_object *cc=json_object_new_array(); json_object_array_add(cc,json_object_new_string(vMap->value)); json_object_object_add(methodc,"tags",cc); + if(pmName!=NULL){ + char* pcaOperationId=(char*)malloc((strlen(vMap->value)+strlen(pmName->value)+1)*sizeof(char)); + sprintf(pcaOperationId,"%s%s",vMap->value,pmName->value); + json_object_object_add(methodc,"operationId",json_object_new_string(pcaOperationId)); + free(pcaOperationId); + } + else + json_object_object_add(methodc,"operationId",json_object_new_string(vMap->value)); } json_object *responses=json_object_new_object(); json_object *cc3=json_object_new_object(); + map* pmUseContent=getMapFromMaps(conf,"openapi","use_content"); + map* pmCode=getMapArray(tmpMaps->content,"code",i); vMap=getMapArray(tmpMaps->content,"schema",i); if(vMap!=NULL){ - json_object *cc=json_object_new_object(); - json_object_object_add(cc,"$ref",json_object_new_string(vMap->value)); - json_object *cc0=json_object_new_object(); - json_object_object_add(cc0,"schema",cc); - json_object *cc1=json_object_new_object(); - map* tmpMap3=getMapFromMaps(conf,tmps,"type"); - if(tmpMap3!=NULL) - json_object_object_add(cc1,tmpMap3->value,cc0); + map* tMap=getMapArray(tmpMaps->content,"type",i); + if(pmCode!=NULL) + addResponse(pmUseContent,cc3,vMap,tMap,pmCode->value,"successful operation"); else - json_object_object_add(cc1,"application/json",cc0); - json_object *cc2=json_object_new_object(); - json_object_object_add(cc2,"content",cc1); - json_object_object_add(cc2,"description",json_object_new_string("successful operation")); - if(i==1) - json_object_object_add(cc3,"201",cc2); - else - json_object_object_add(cc3,"200",cc2); + addResponse(pmUseContent,cc3,vMap,tMap,"200","successful operation"); + vMap=getMapArray(tmpMaps->content,"eschema",i); + if(pmCode==NULL && vMap!=NULL && cMap!=NULL && strncasecmp(cMap->value,"post",4)==0) + addResponse(pmUseContent,cc3,vMap,tMap,"201","successful operation"); }else{ - json_object *cc1=json_object_new_object(); - map* tmpMap3=getMapFromMaps(conf,tmps,"type"); - if(tmpMap3!=NULL) - json_object_object_add(cc1,tmpMap3->value,json_object_new_object()); - else - json_object_object_add(cc1,"application/json",json_object_new_object()); - json_object *cc2=json_object_new_object(); - json_object_object_add(cc2,"content",cc1); - json_object_object_add(cc2,"description",json_object_new_string("successful operation")); - if(i==1) - json_object_object_add(cc3,"201",cc2); + map* tMap=getMapFromMaps(conf,tmps,"type"); + map* pMap=createMap("ok","true"); + if(pmCode!=NULL) + addResponse(pMap,cc3,vMap,tMap,pmCode->value,"successful operation"); else - json_object_object_add(cc3,"200",cc2); + addResponse(pMap,cc3,vMap,tMap,"200","successful operation"); + if(pmCode==NULL && cMap!=NULL && strncasecmp(cMap->value,"post",4)==0) + addResponse(pmUseContent,cc3,vMap,tMap,"201","successful operation"); + freeMap(&pMap); + free(pMap); } - if(strstr(tmps,"{id}")!=NULL){ - vMap=getMapFromMaps(conf,"exception","schema"); - json_object *cc=json_object_new_object(); - json_object_object_add(cc,"$ref",json_object_new_string(vMap->value)); - json_object *cc01=json_object_new_array(); - json_object_array_add(cc01,cc); - - json_object *cc0=json_object_new_object(); - json_object_object_add(cc0,"schema",cc); - json_object *cc1=json_object_new_object(); - map* tmpMap3=getMapFromMaps(conf,"exception","type"); - if(tmpMap3!=NULL) - json_object_object_add(cc1,tmpMap3->value,cc0); - else - json_object_object_add(cc1,"application/json",cc0); - - json_object *cc2=json_object_new_object(); - json_object_object_add(cc2,"content",cc1); - if(strstr(tmps,"{jobID}")==NULL) - json_object_object_add(cc2,"description",json_object_new_string("The process with id {id} does not exist.")); - else - json_object_object_add(cc2,"description",json_object_new_string("The process with id {id} or job with id {jobID} does not exist.")); - json_object_object_add(cc3,"404",cc2); - json_object_object_add(cc3,"default",cc2); + vMap=getMapArray(tmpMaps->content,"ecode",i); + if(vMap!=NULL){ + char *saveptr0; + char *tmps1 = strtok_r (vMap->value, ",", &saveptr0); + while(tmps1!=NULL){ + char* tmpStr=(char*)malloc((strlen(tmps1)+24)*sizeof(char)); + sprintf(tmpStr,"#/components/responses/%s",tmps1); + vMap=createMap("ok",tmpStr); + map* pMap=createMap("ok","false"); + //TODO: fix successful operation with correct value + addResponse(pMap,cc3,vMap,NULL,tmps1,"successful operation"); + tmps1 = strtok_r (NULL, ",", &saveptr0); + } + }else{ + if(strstr(tmps,"{id}")!=NULL){ + vMap=getMapFromMaps(conf,"exception","schema"); + map* tMap=getMapFromMaps(conf,"exception","type"); + if(vMap!=NULL) + addResponse(pmUseContent,cc3,vMap,tMap,"404", + (strstr(tmps,"{jobID}")==NULL)?"The process with id {id} does not exist.":"The process with id {id} or job with id {jobID} does not exist."); + } } json_object_object_add(methodc,"responses",cc3); vMap=getMapArray(tmpMaps->content,"parameters",i); @@ -1844,7 +2855,7 @@ extern "C" { } json_object_object_add(methodc,"parameters",cc2); } - if(i==1){ + if(/*i==1 && */cMap!=NULL && strncasecmp(cMap->value,"post",4)==0){ maps* tmpMaps1=getMaps(conf,"requestBody"); if(tmpMaps1!=NULL){ vMap=getMap(tmpMaps1->content,"schema"); @@ -1853,22 +2864,124 @@ extern "C" { json_object_object_add(cc,"$ref",json_object_new_string(vMap->value)); json_object *cc0=json_object_new_object(); json_object_object_add(cc0,"schema",cc); + // Add examples from here + map* pmExample=getMapArray(tmpMaps->content,"examples",i); + if(pmExample!=NULL){ + int iCnt=0; + char* saveptr; + map* pmExamplesPath=getMapFromMaps(conf,"openapi","examplesPath"); + json_object* prop5=json_object_new_object(); + char *tmps = strtok_r (pmExample->value, ",", &saveptr); + while(tmps!=NULL && strlen(tmps)>0){ + json_object* prop6=json_object_new_object(); + json_object* pjoExempleItem=json_object_new_object(); + char* pcaExempleFile=NULL; + if(pmName!=NULL){ + pcaExempleFile=(char*)malloc((strlen(pmExamplesPath->value)+strlen(pmName->value)+strlen(tmps)+3)*sizeof(char)); + sprintf(pcaExempleFile,"%s/%s/%s",pmExamplesPath->value,pmName->value,tmps); + }else{ + pcaExempleFile=(char*)malloc((strlen(pmExamplesPath->value)+strlen(tmps)+2)*sizeof(char)); + sprintf(pcaExempleFile,"%s/%s",pmExamplesPath->value,tmps); + } + char actmp[10]; + sprintf(actmp,"%d",iCnt); + char* pcaTmp; + map* pmSummary=getMapArray(tmpMaps->content,"examples_summary",iCnt); + if(pmSummary!=NULL){ + pcaTmp=(char*)malloc((strlen(actmp)+strlen(pmSummary->value)+strlen(_("Example "))+3)*sizeof(char)); + sprintf(pcaTmp,"%s%s: %s",_("Example "),actmp,pmSummary->value); + } + else{ + pcaTmp=(char*)malloc((strlen(actmp)+strlen(_("Example "))+3)*sizeof(char)); + sprintf(pcaTmp,"%s%s",_("Example "),actmp); + } + json_object* pjoValue=json_readFile(conf,pcaExempleFile); + json_object_object_add(pjoExempleItem,"summary",json_object_new_string(pcaTmp)); + json_object_object_add(pjoExempleItem,"value",pjoValue); + json_object_object_add(prop5,actmp,pjoExempleItem); + tmps = strtok_r (NULL, ",", &saveptr); + iCnt++; + } + json_object_object_add(cc0,"examples",prop5); + } + json_object *cc1=json_object_new_object(); map* tmpMap3=getMap(tmpMaps->content,"type"); if(tmpMap3!=NULL) json_object_object_add(cc1,tmpMap3->value,cc0); else json_object_object_add(cc1,"application/json",cc0); + json_object *cc2=json_object_new_object(); json_object_object_add(cc2,"content",cc1); vMap=getMap(tmpMaps1->content,"abstract"); if(vMap!=NULL) json_object_object_add(cc2,"description",json_object_new_string(vMap->value)); json_object_object_add(cc2,"required",json_object_new_boolean(true)); + + json_object_object_add(methodc,"requestBody",cc2); } } + tmpMaps1=getMaps(conf,"callbacks"); + if(tmpMaps1!=NULL){ + map* pmTmp2=getMap(tmpMaps1->content,"length"); + int iLen=atoi(pmTmp2->value); + json_object *pajRes=json_object_new_object(); + for(int i=0;icontent,"state",i); + map* pmUri=getMapArray(tmpMaps1->content,"uri",i); + map* pmSchema=getMapArray(tmpMaps1->content,"schema",i); + map* pmType=getMapArray(tmpMaps1->content,"type",i); + map* pmTitle=getMapArray(tmpMaps1->content,"title",i); + json_object *pajSchema=json_object_new_object(); + if(pmSchema!=NULL) + json_object_object_add(pajSchema,"$ref",json_object_new_string(pmSchema->value)); + json_object *pajType=json_object_new_object(); + json_object_object_add(pajType,"schema",pajSchema); + json_object *pajContent=json_object_new_object(); + if(pmType!=NULL) + json_object_object_add(pajContent,pmType->value,pajType); + else + json_object_object_add(pajContent,"application/json",pajType); + json_object *pajRBody=json_object_new_object(); + json_object_object_add(pajRBody,"content",pajContent); + + json_object *pajDescription=json_object_new_object(); + json_object *pajPost=json_object_new_object(); + if(pmTitle!=NULL){ + json_object_object_add(pajDescription,"description",json_object_new_string(_(pmTitle->value))); + json_object_object_add(pajPost,"summary",json_object_new_string(_(pmTitle->value))); + } + json_object *pajResponse=json_object_new_object(); + json_object_object_add(pajResponse,"200",pajDescription); + + json_object_object_add(pajPost,"requestBody",pajRBody); + json_object_object_add(pajPost,"responses",pajResponse); + if(pmName!=NULL){ + char* pcaOperationId=(char*)malloc((strlen(pmState->value)+strlen(pmName->value)+1)*sizeof(char)); + sprintf(pcaOperationId,"%s%s",pmState->value,pmName->value); + json_object_object_add(pajPost,"operationId",json_object_new_string(pcaOperationId)); + free(pcaOperationId); + } + else + json_object_object_add(pajPost,"operationId",json_object_new_string(pmState->value)); + + json_object *pajMethod=json_object_new_object(); + json_object_object_add(pajMethod,"post",pajPost); + + + char* pacUri=(char*) malloc((strlen(pmUri->value)+29)*sizeof(char)); + sprintf(pacUri,"{$request.body#/subscriber/%s}",pmUri->value); + + json_object *pajFinal=json_object_new_object(); + json_object_object_add(pajFinal,pacUri,pajMethod); + json_object_object_add(pajRes,pmState->value,pajFinal); + + } + json_object_object_add(methodc,"callbacks",pajRes); + } } map* mMap=getMapArray(tmpMaps->content,"method",i); if(mMap!=NULL) @@ -1893,18 +3006,43 @@ extern "C" { } json_object_object_add(res,"paths",paths); } - + tmpMap=getMapFromMaps(conf,"openapi","links"); if(tmpMap!=NULL){ - + } - + json_object *res3=json_object_new_array(); json_object_array_add(res3,res4); json_object_object_add(res,"servers",res3); } - + /** + * Print exception report in case Deploy or Undeploy failed to execute + * + * @param conf the main configuration maps pointer + */ + void handleDRUError(maps* conf){ + map* pmError=getMapFromMaps(conf,"lenv","jsonStr"); + setMapInMaps(conf,"lenv","hasPrinted","false"); + setMapInMaps(conf,"lenv","no-headers","false"); + setMapInMaps(conf,"headers","Status","500 Internal Server Error"); + setMapInMaps(conf,"lenv","status_code","500 Internal Server Error"); + if(pmError!=NULL){ + printHeaders(conf); + printf("\r\n"); + printf(pmError->value); + printf("\n"); + }else{ + pmError=createMap("code","InternalError"); + addToMap(pmError,"message",_("Failed to deploy process!")); + printExceptionReportResponseJ(conf,pmError); + freeMap(&pmError); + free(pmError); + } + setMapInMaps(conf,"lenv","no-headers","true"); + setMapInMaps(conf,"lenv","hasPrinted","true"); + } #ifdef __cplusplus } #endif diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_json.h b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_json.h new file mode 100644 index 00000000..cd546aeb --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_json.h @@ -0,0 +1,155 @@ +/* + * Author : Gérald FENOY + * + * Copyright 2014-2021 GeoLabs SARL. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ZOO_JSON_H +#define ZOO_JSON_H 1 + +#pragma once + +#include "response_print.h" +#include +#include +#include +#include +#include "json_c_version.h" + +#if (JSON_C_MINOR_VERSION<=12) +#define JSON_C_TO_STRING_NOSLASHESCAPE (1<<4) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * Names of field to output in the status object + */ + static const char* statusFields[6]={ + "type", "processID","created","started","finished","updated" + }; + + /** + * Coreresponding names of field from the data table to fetch informations + */ + static const char* statusFieldsC[6]={ + "itype", "processid","creation_time","start_time","end_time","updated_time" + }; + + /** + * Coreresponding names of field from the data table to fetch informations + */ + static const char* statusSearchFields[2]={ + "processid","status" + }; + + /** + * Coreresponding names of field from the data table to fetch informations + */ + static const char* statusSearchFieldsReal[2]={ + "processid","fstate" + }; + + /** + * Definitions of acceptable final status + */ + static char oapipStatus[5][11]={ + "successful", + "failed", + "running", + "dismissed", + "accepted" + }; + + /** + * Name and corresponding attributes depending on the WPS version + */ + static const char* jcapabilities[4]={ + "jobControlOptions","sync-execute async-execute dismiss", + "outputTransmission","value reference" + }; + + /** + * Possible field names corresponding to pccRFields + * @see pccRFields + */ + static const char* pccFields[9]={ + "type", + "encoding", + "schema", + "mediaType", + "mediaEncoding", + "mediaSchema", + "contentMediaType", + "contentEncoding", + "contentSchema" + }; + + /** + * Corresponding fields available in WPS for pccFields + * @see pccFields + */ + static const char* pccRFields[3]={ + "mimeType", + "encoding", + "schema" + }; + + /** + * Equivalent range keywords for WPS version 1 and 2 + */ + static const char* rangeCorrespondances[4][2]={ + { "rangeClosure", "rangeClosure" }, + { "rangeMin", "minimum" }, + { "rangeMax", "maximum"}, + { "rangeSpacing", "spacing" } + }; + + maps* jsonToMaps(json_object*); + map* jsonToMap(json_object*); + json_object* mapToJson(map*); + json_object* mapsToJson(maps*); + json_object* serviceToJson(service*); + void printLiteralValueJ(maps*,map*,map*,json_object*,const char*); + void printGetCapabilitiesForProcessJ(registry*, maps*,void*,void*,service*); + void printExceptionReportResponseJ(maps*,map*); + void parseJRequest(maps*,service*,json_object*,map*,maps**,maps**); + json_object* printJResult(maps*,service*,maps*,int); + json_object* printJobStatus(maps*,char*); + json_object* printJobList(maps*); + int createNextLinks(maps*,json_object*); + int createStatusFile(maps*,int); + json_object* createStatus(maps*,int); + char* json_getStatusFilePath(maps*); + json_object* parseJson(maps*,char*); + json_object* json_readFile(maps*,char*); + char* getResultPath(maps*,char*); + int json_getStatusFile(maps*); + void produceApi(maps*,json_object*); + void outputSingleJsonComplexRes(maps*,maps*,json_object*,json_object*,char*,long); + void handleDRUError(maps*); + //void printIOTypeJ(maps*, const char*, elements*,json_object*,service*); +#ifdef __cplusplus +} +#endif +#endif diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/zoo_service_loader.c b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/zoo_service_loader.c index f0af3308..672d73aa 100644 --- a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/zoo_service_loader.c +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/zoo_service_loader.c @@ -1,7 +1,7 @@ /* * Author : Gérald FENOY * - * Copyright 2008-2013 GeoLabs SARL. All rights reserved. + * Copyright 2008-2022 GeoLabs SARL. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,7 +25,7 @@ extern "C" int yylex (); extern "C" int crlex (); -#ifdef META_DB +#if defined(META_DB) || defined(USE_AMQP) #include "ogrsf_frmts.h" #if GDAL_VERSION_MAJOR >= 2 #include @@ -62,19 +62,14 @@ extern "C" int crlex (); #include #include -#include "service.h" - #include "service_internal.h" #include "server_internal.h" #include "response_print.h" #include "request_parser.h" +#include "service.h" -#include -#include - - -#ifdef USE_JSON +#if defined(WIN32) || defined(USE_JSON) #include "caching.h" #endif #include "sqlapi.h" @@ -111,13 +106,19 @@ extern "C" int crlex (); #include "service_internal_mono.h" #endif -#ifdef USE_CALLBACK +#if defined(USE_CALLBACK) || defined(USE_JSON) #include "service_callback.h" #endif #ifdef USE_JSON #include "service_json.h" #include "json_tokener.h" +#include "json.h" +#endif + +#ifdef USE_AMQP +#include "service_internal_amqp.h" +#include #endif #include @@ -153,8 +154,6 @@ extern "C" int crlex (); //rdr //#ifndef WIN32 -#include -#include #include //#endif //rdr @@ -258,16 +257,202 @@ int dumpBackFinalFile(maps* m,char* fbkp,char* fbkp1) return 1; } -char* replace_char(char* str, char find, char replace){ - char *current_pos = strchr(str,find); - while (current_pos){ - *current_pos = replace; - current_pos = strchr(current_pos,find); +/** + * Update the counter value (in conf / lenv / serviceCnt + * + * @param conf the conf maps containing the main.cfg settings + * @param field the value to update (serviceCnt or serviceCounter) + * @param type char pointer can be "incr" for incrementing the value by 1, other + * will descrement the value by 1 + */ +void updateCnt(maps* conf, const char* field, const char* type){ + map* pmTmp=getMapFromMaps(conf,"lenv",field); + if(pmTmp!=NULL){ + int iCnt=atoi(pmTmp->value); + if(strncmp(type,"incr",4)==0) + iCnt++; + else + iCnt--; + char* pcaTmp=(char*) malloc((10+1)*sizeof(char)); + sprintf(pcaTmp,"%d",iCnt); + setMapInMaps(conf,"lenv",field,pcaTmp); + free(pcaTmp); + } +} + +/** + * Compare a value with conf / lenv / serviceCnt + * + * @param conf the conf maps containing the main.cfg settings + * @param field the value to compare with (serviceCntLimit or serviceCntSkip) + * @param type comparison operator can be : elower, lower, eupper, upper, or + * equal + * @return boolean resulting of the comparison between the values + */ +bool compareCnt(maps* conf, const char* field, const char* type){ + map* pmTmp=getMapFromMaps(conf,"lenv","serviceCnt"); + map* pmTmp1=getMapFromMaps(conf,"lenv",field); + + if(pmTmp!=NULL && pmTmp1!=NULL){ + int iCnt=atoi(pmTmp->value); + int iCntOther=atoi(pmTmp1->value); + if(strncmp(field,"serviceCntLimit",15)==0){ + pmTmp1=getMapFromMaps(conf,"lenv","serviceCntSkip"); + if(pmTmp1!=NULL) + iCntOther+=atoi(pmTmp1->value); + } + if(strncmp(type,"lower",5)==0) + return iCnt=iCntOther; + else{ + if(strncmp(type,"upper",5)==0) + return iCnt>iCntOther; + else + return iCnt==iCntOther; + } + } + } + }else + if(strncmp(type,"equal",5)==0) + return false; + else + return true; +} + +/** EOEPCA SPEC **/ + +/** + * Checks if the zooServicesNamespace map is present in the m map; + * if it is, the path to the directory where the ZOO-kernel should search for service providers will be updated. + * + * @param m the conf maps containing the main.cfg settings + * @param oldPath default location where the ZOO-kernel should search for service providers + * @param newPath location where the ZOO-kernel should search for service providers considering the namespace + * @param maxSize maximum number of bytes to be used in the newPath buffer. + */ +int getServicesNamespacePath(maps* m,char* oldPath,char* newPath,int maxSize){ + map *zooServicesNamespaceMap = getMapFromMaps (m, "zooServicesNamespace", "namespace"); + map *servicesNamespaceParentPath = getMapFromMaps (m, "servicesNamespace", "path"); + memset(newPath,0,maxSize); + + if (zooServicesNamespaceMap && strcmp(zooServicesNamespaceMap->value,"anonymous") == 0 ){ + if (oldPath){ + snprintf (newPath,maxSize, "%s", oldPath); + } + } else if (zooServicesNamespaceMap && zooServicesNamespaceMap->value && servicesNamespaceParentPath && servicesNamespaceParentPath->value){ + snprintf (newPath,maxSize, "%s/%s", servicesNamespaceParentPath->value,zooServicesNamespaceMap->value); + } else { + if (oldPath) + snprintf (newPath,maxSize, "%s", oldPath); + } + return 0; +} + +/*** + * Checks if the env variable SERVICES_NAMESPACE is set; + * if it is, the zooServicesNamespace map will be added to the conf map + * + * @param conf the conf maps containing the main.cfg settings + */ +int addServicesNamespaceToMap(maps* conf){ + int ret=0; + int ei = 1; + char **orig = environ; + char *s=*orig; + char* namespaceName=NULL; + + if(orig!=NULL) + for (; s; ei++ ) { + // retrieving service workspace + if(strstr(s,"=")!=NULL && strlen(strstr(s,"="))>1){ + if (strstr(s,"SERVICES_NAMESPACE")!=NULL){ + char* baseU=strchr(s,'='); + if (strlen(baseU)>1) { + namespaceName = ++baseU; +#ifdef DEBUG + fprintf(stderr,"zooServicesNamespace: %s\n",namespaceName); +#endif + + // checking if namespace folder exists + char *namespaceFolder = (char *) malloc(1024); + memset(namespaceFolder, '\0', 1024); + map *servicesNamespaceParentFolder = getMapFromMaps(conf, "servicesNamespace", "path"); + sprintf(namespaceFolder, "%s/%s", servicesNamespaceParentFolder->value, namespaceName); + DIR *dir = opendir(namespaceFolder); + if (dir) { + // creating a zooServicesNamespace map + // the map will contain the namespace name + maps *_tmpMaps = createMaps("zooServicesNamespace"); + if (_tmpMaps->content == NULL) + _tmpMaps->content = createMap("namespace", namespaceName); + else + addToMap(_tmpMaps->content, "namespace", namespaceName); + + // adding the zooServicesNamespace map to the other maps + if (conf) { + addMapsToMaps(&conf, _tmpMaps); + } + } else { + map* error=createMap("code","BadRequest"); + addToMap(error,"message",_("The resource is not available")); + printExceptionReportResponseJ(conf,error); + ret = 1; + freeMap(&error); + free(error); + } + } + } + } + s = *(orig+ei); + } + + return ret; +} + +/*** + * Updates the rootUrl property in the map m by concatenating the rootHost, the namespace and the rootPath + * @param m the conf maps containing the main.cfg and oas.cfg settings + */ +void setRootUrlMap(maps* m){ + map* rootHost=getMapFromMaps(m,"openapi","rootHost"); + map* rootPath=getMapFromMaps(m,"openapi","rootPath"); + int ei = 1; + int canContinue=false; + char **orig = environ; + char *s=*orig; + char workspace[1024*2]; + char* pWorkspace = NULL; + memset(workspace,0,1024*2); + for (; s; ei++ ) { + if (strstr(s,"EOEPCA_WORKSPACE")!=NULL){ + char* baseU=strchr(s,'='); + if (strlen(baseU)>1){ + pWorkspace = ++baseU; + } } - return str; + s = *(orig+ei); + } + if (pWorkspace){ + // TODO: verify if we should optionaly prepend with rootHost + if(rootHost!=NULL) + sprintf(workspace, "%s/%s/%s",rootHost->value,pWorkspace,rootPath->value); + else + sprintf(workspace, "/%s/%s",pWorkspace,rootPath->value); + fprintf(stderr,"---------WORKSPACE: %s--------------\n",workspace); + setMapInMaps(m,"openapi","rootUrl",workspace); + } + + maps* pmsTmp=getMaps(m,"openapi"); + dumpMap(pmsTmp->content); } + //rdr int mkpath(char *file_path, mode_t mode) { // assert(file_path && *file_path); @@ -594,15 +779,21 @@ addUserToMap(maps* conf){ // rwx map *theGrants = createMap("grant","1--"); addMapToMap(&_tmpMaps->content,theGrants); + freeMap(&theGrants); + free(theGrants); }else{ // it is ok! map *theGrants = createMap("grant","111"); addMapToMap(&_tmpMaps->content,theGrants); + freeMap(&theGrants); + free(theGrants); } if(conf){ addMapsToMaps (&conf, _tmpMaps); } + freeMaps(&_tmpMaps); + free(_tmpMaps); } } @@ -777,8 +968,7 @@ addUserToMap(maps* conf){ return ret; } - - +/** EOEPCA SPEC END **/ /** * Recursivelly parse zcfg starting from the ZOO-Kernel cwd. @@ -798,23 +988,25 @@ addUserToMap(maps* conf){ */ int recursReaddirF ( maps * m, registry *r, void* doc1, void* n1, char *conf_dir_, - //( maps * m, registry *r, xmlDocPtr doc, xmlNodePtr n, char *conf_dir, char *prefix, int saved_stdout, int level, void (func) (registry *, maps *, void*, void*, service *) ) - //void (func) (registry *, maps *, xmlDocPtr, xmlNodePtr, service *) ) { - // rdr + // if services namespace is present in the map, conf_dir will + // point to the namespace services path else it will point to + // the default service path char conf_dir[1024]; + /** EOEPCA SPEC **/ + //getServicesNamespacePath(m,conf_dir_,conf_dir,1024); getUserWorkspacePath(m,conf_dir_,conf_dir,1024); - // fprintf(stderr,"2################%s##################\n",conf_dir); - // fprintf(stderr,"2################%s##################\n",conf_dir); + /** EOEPCA SPEC END **/ struct dirent *dp; int scount = 0; xmlDocPtr doc=(xmlDocPtr) doc1; xmlNodePtr n=(xmlNodePtr) n1; + if (conf_dir == NULL) return 1; DIR *dirp = opendir (conf_dir); @@ -874,10 +1066,8 @@ recursReaddirF ( maps * m, registry *r, void* doc1, void* n1, char *conf_dir_, } else { - // map* tmpMap=getMapFromMaps(m,"lenv",tmp1); - fprintf(stderr,"rdr a5b %s \n",dp->d_name); char* extn = strstr(dp->d_name, ".zcfg"); - if(dp->d_name[0] != '.' && extn != NULL && strlen(extn) == 5 && strlen(dp->d_name)>6) + if(dp->d_name[0] != '.' && extn != NULL && strlen(extn) == 5 && strlen(dp->d_name)>5) { int t; char tmps1[1024]; @@ -889,47 +1079,64 @@ recursReaddirF ( maps * m, registry *r, void* doc1, void* n1, char *conf_dir_, snprintf(tmpsn,strlen(dp->d_name)-4,"%s",dp->d_name); map* import = getMapFromMaps (m, IMPORTSERVICE, tmpsn); - if (import == NULL || import->value == NULL || zoo_path_compare(tmps1, import->value) != 0 ) { // service is not in [include] block - service *s1 = createService(); - if (s1 == NULL) - { - zDup2 (saved_stdout, fileno (stdout)); - errorException (m, _("Unable to allocate memory"), - "InternalError", NULL); - return -1; - } - #ifdef DEBUG - fprintf (stderr, "#################\n%s\n#################\n", - tmps1); - #endif - t = readServiceFile (m, tmps1, &s1, tmpsn); - free (tmpsn); - if (t < 0) - { - map *tmp00 = getMapFromMaps (m, "lenv", "message"); - char tmp01[1024]; - if (tmp00 != NULL) - sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"), - dp->d_name, tmp00->value); - else - sprintf (tmp01, _("Unable to parse the ZCFG file: %s."), - dp->d_name); - zDup2 (saved_stdout, fileno (stdout)); - errorException (m, tmp01, "InternalError", NULL); - return -1; - } - #ifdef DEBUG - dumpService (s1); - fflush (stdout); - fflush (stderr); - #endif - if(s1!=NULL) - inheritance(r,&s1); - func (r, m, doc, n, s1); - freeService (&s1); - free (s1); + if (import == NULL || import->value == NULL || zoo_path_compare(tmps1, import->value) != 0 ) { // service is not in [include] block + if(compareCnt(m,"serviceCntSkip","eupper") && compareCnt(m,"serviceCntLimit","lower")){ + service *s1 = createService(); + if (s1 == NULL) + { + zDup2 (saved_stdout, fileno (stdout)); + errorException (m, _("Unable to allocate memory"), + "InternalError", NULL); + return -1; + } +#ifdef DEBUG + fprintf (stderr, "#################\n%s\n#################\n", + tmps1); +#endif + t = readServiceFile (m, tmps1, &s1, tmpsn); + free (tmpsn); + tmpsn=NULL; + if (t < 0) + { + map *tmp00 = getMapFromMaps (m, "lenv", "message"); + char tmp01[1024]; + if (tmp00 != NULL) + sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"), + dp->d_name, tmp00->value); + else + sprintf (tmp01, _("Unable to parse the ZCFG file: %s."), + dp->d_name); + zDup2 (saved_stdout, fileno (stdout)); + errorException (m, tmp01, "InternalError", NULL); + freeService (&s1); + free (s1); + return -1; + } +#ifdef DEBUG + dumpService (s1); + fflush (stdout); + fflush (stderr); +#endif + if(s1!=NULL) + inheritance(r,&s1); + func (r, m, doc, n, s1); + freeService (&s1); + free (s1); + } scount++; + updateCnt(m,"serviceCnt","incr"); + updateCnt(m,"serviceCounter","incr"); + if(compareCnt(m,"serviceCntLimit","equal")){ + // In case we are willing to count the number of services, we + // can still continue and not return any value bellow + if(getMapFromMaps(m,"lenv","serviceCntNext")==NULL) + setMapInMaps(m,"lenv","serviceCntNext","true"); + //(void) closedir (dirp); + //return 1; + } } + if(tmpsn!=NULL) + free(tmpsn); } } (void) closedir (dirp); @@ -961,12 +1168,16 @@ void exitAndCleanUp(registry* zooRegistry, maps* m, sprintf (tmp01, _("Unable to parse the ZCFG file: %s."), zcfg); + map* errormap = createMap("text", tmp01); - addToMap(errormap,"code", code); + map* tmpMap=getMapFromMaps(m,"main","executionType"); + char* errorCode=(char*)code; + if(tmpMap!=NULL && strncasecmp(tmpMap->value,"json",4)==0) + errorCode="NoSuchProcess"; + + addToMap(errormap,"code", errorCode); addToMap(errormap,"locator", locator); funcError(m,errormap); - freeMaps (&m); - free (m); if(zooRegistry!=NULL){ freeRegistry(&zooRegistry); free(zooRegistry); @@ -974,7 +1185,6 @@ void exitAndCleanUp(registry* zooRegistry, maps* m, free (orig); if (corig != NULL) free (corig); - //xmlFreeDoc (doc); xmlCleanupParser (); zooXmlCleanupNs (); freeMap(&errormap); @@ -982,6 +1192,173 @@ void exitAndCleanUp(registry* zooRegistry, maps* m, } +/** + * Parse the ZOO-Service ZCFG to fill the service datastructure + * + * @param zooRegistry the populated registry + * @param m the maps pointer to the content of main.cfg file + * @param spService the pointer to the service pointer to be filled + * @param request_inputs the map pointer for http request inputs + * @param ntmp the path where the ZCFG files are stored + * @param cIdentifier the service identifier + * @param funcError the error function to be used in case of error + */ +int fetchService(registry* zooRegistry,maps* m,service** spService, map* request_inputs,char* ntmp,char* cIdentifier,void (funcError) (maps*, map*)){ + char tmps1[1024]; + map *r_inputs=NULL; + service* s1=*spService; + map* pmExecutionType=getMapFromMaps(m,"main","executionType"); + map* import = getMapFromMaps (m, IMPORTSERVICE, cIdentifier); + if (import != NULL && import->value != NULL) { + strncpy(tmps1, import->value, 1024); + setMapInMaps (m, "lenv", "Identifier", cIdentifier); + setMapInMaps (m, "lenv", "oIdentifier", cIdentifier); + } + else { + /*char conf_dir2[1024*2]; + memset(conf_dir2,0,1024*2); + + strcpy(conf_dir2,ntmp); + getServicesNamespacePath(m,ntmp,conf_dir2,1024); + strcpy(ntmp,conf_dir2);*/ + + /** EOEPCA SPEC **/ + char newPath[1024]; + getUserWorkspacePath(m,ntmp,newPath,1024); + + if ( strcmp(cIdentifier,"DeployProcess")==0 || + strcmp(cIdentifier,"UndeployProcess")==0 ){ + memset(newPath,'\0',1024); + strcpy(newPath,ntmp); + } + if (strcmp(ntmp, newPath )==0) { + snprintf (tmps1, 1024, "%s/%s.zcfg", ntmp, cIdentifier); + }else{ + // fprintf(stderr,"rdr a7 %s/%s.zcfg \n",newPath, cIdentifier); + snprintf (tmps1, 1024, "%s/%s.zcfg", newPath, cIdentifier); + } + /** EOEPCA SPEC END **/ + //snprintf (tmps1, 1024, "%s/%s.zcfg", ntmp, cIdentifier); +#ifdef DEBUG + fprintf (stderr, "Trying to load %s\n", tmps1); +#endif + if (strstr (cIdentifier, ".") != NULL) + { + setMapInMaps (m, "lenv", "oIdentifier", cIdentifier); + char *identifier = zStrdup (cIdentifier); + parseIdentifier (m, ntmp, identifier, tmps1); + map *tmpMap = getMapFromMaps (m, "lenv", "metapath"); + if (tmpMap != NULL) + addToMap (request_inputs, "metapath", tmpMap->value); + free (identifier); + } + else + { + setMapInMaps (m, "lenv", "oIdentifier", cIdentifier); + setMapInMaps (m, "lenv", "Identifier", cIdentifier); + } + } + + r_inputs = getMapFromMaps (m, "lenv", "Identifier"); + +#ifdef META_DB + int metadb_id=_init_sql(m,"metadb"); + //FAILED CONNECTING DB + if(getMapFromMaps(m,"lenv","dbIssue")!=NULL || metadb_id<0){ + fprintf(stderr,"ERROR CONNECTING METADB\n"); + } + if(metadb_id>=0) + *spService=extractServiceFromDb(m,cIdentifier,0); + if(s1!=NULL){ + inheritance(zooRegistry,spService); +#ifdef USE_HPC + addNestedOutputs(spService); +#endif + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + }else /* Not found in MetaDB */{ +#endif + *spService = createService(); + if (*spService == NULL) + { + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + map* error=createMap("code","InternalError"); + if(pmExecutionType!=NULL && strncasecmp(pmExecutionType->value,"xml",3)==0){ + addToMap(error,"locator", "NULL"); + addToMap(error,"text",_("Unable to allocate memory")); + } + else{ + addToMap(error,"message",_("Unable to allocate memory")); + } + + setMapInMaps(m,"lenv","status_code","404 Bad Request"); + funcError(m,error); + freeMap(&error); + free(error); + return 1; /*errorException (m, _("Unable to allocate memory"), + "InternalError", NULL);*/ + } + + int saved_stdout = zDup (fileno (stdout)); + zDup2 (fileno (stderr), fileno (stdout)); + int t = readServiceFile (m, tmps1, spService, cIdentifier); + if(t>=0){ + inheritance(zooRegistry,spService); +#ifdef USE_HPC + addNestedOutputs(spService); +#endif + } + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + fflush(stderr); + fflush (stdout); + zDup2 (saved_stdout, fileno (stdout)); + zClose (saved_stdout); + if (t < 0) + { + r_inputs = getMapFromMaps (m, "lenv", "oIdentifier"); + if(r_inputs!=NULL){ + char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value)); + sprintf (tmpMsg, + _ + ("The value for seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."), + r_inputs->value); + map* error=createMap("code","NoSuchProcess"); + if(pmExecutionType!=NULL && strncasecmp(pmExecutionType->value,"xml",3)==0){ + addToMap(error,"locator", "identifier"); + addToMap(error,"text",tmpMsg); + addToMap(error,"code","InvalidParameterValue"); + } + else{ + addToMap(error,"message",tmpMsg); + } + //setMapInMaps(conf,"lenv","status_code","404 Bad Request"); + funcError(m,error); + //free (*spService); + //errorException (m, tmpMsg, "InvalidParameterValue", "identifier"); + free (tmpMsg); + freeMap(&error); + free(error); + //freeMaps (&m); + //free (m); + return 1; + } + } +#ifdef META_DB + } +#endif + return 0; +} + /** * Search services from various possible sources * @@ -998,13 +1375,8 @@ void exitAndCleanUp(registry* zooRegistry, maps* m, */ int fetchServicesForDescription(registry* zooRegistry, maps* m, char* r_inputs, void (func) (registry *, maps *, void*, void*, service *), - void* doc, void* n, char* conf_dir_, map* request_inputs, + void* doc, void* n, char *conf_dir_, map* request_inputs, void (funcError) (maps*, map*) ){ - - char conf_dir[1024]; - // rdr - getUserWorkspacePath(m,conf_dir_,conf_dir,1024); - char *orig = zStrdup (r_inputs); service* s1=NULL; int saved_stdout = zDup (fileno (stdout)); @@ -1012,6 +1384,15 @@ int fetchServicesForDescription(registry* zooRegistry, maps* m, char* r_inputs, int scount = 0; struct dirent *dp; + char conf_dir[1024]; + /** EOEPCA SPEC **/ + getUserWorkspacePath(m,conf_dir_,conf_dir,1024); + //getServicesNamespacePath(m,conf_dir_,conf_dir,1024); + /** EOEPCA SPEC END **/ + + + fflush(stderr); + fflush (stdout); zDup2 (fileno (stderr), fileno (stdout)); if (strcasecmp ("all", orig) == 0) { @@ -1041,8 +1422,10 @@ int fetchServicesForDescription(registry* zooRegistry, maps* m, char* r_inputs, } if (int res = recursReaddirF (m, zooRegistry, doc, n, conf_dir, NULL, saved_stdout, 0, - func) < 0) + func) < 0){ + zDup2 (saved_stdout, fileno (stdout)); return res; + } #ifdef META_DB fetchServicesFromDb(zooRegistry,m,doc,n,func,0); close_sql(m,0); @@ -1077,6 +1460,8 @@ int fetchServicesForDescription(registry* zooRegistry, maps* m, char* r_inputs, tmps,"InvalidParameterValue","identifier", orig,corig, funcError); + if(dirp!=NULL) + closedir (dirp); return 1; } #ifdef DEBUG @@ -1119,6 +1504,8 @@ int fetchServicesForDescription(registry* zooRegistry, maps* m, char* r_inputs, tmps,"InvalidParameterValue","identifier", orig,corig, funcError); + if(dirp!=NULL) + closedir (dirp); return 1; } #ifdef DEBUG @@ -1158,7 +1545,6 @@ int fetchServicesForDescription(registry* zooRegistry, maps* m, char* r_inputs, }else /*TOTO*/{ #endif memset (buff, 0, 256); - fprintf(stderr,"rdr a6\n"); snprintf (buff, 256, "%s.zcfg", corig); memset (buff1, 0, 1024); #ifdef DEBUG @@ -1174,11 +1560,15 @@ int fetchServicesForDescription(registry* zooRegistry, maps* m, char* r_inputs, s1 = createService(); if (s1 == NULL) { + fflush(stderr); + fflush(stdout); zDup2 (saved_stdout, fileno (stdout)); map* errormap = createMap("text", _("Unable to allocate memory")); addToMap(errormap,"code", "InternalError"); addToMap(errormap,"locator", "NULL"); funcError(m,errormap); + if(dirp!=NULL) + closedir (dirp); return -1; } #ifdef DEBUG_SERVICE_CONF @@ -1192,11 +1582,15 @@ int fetchServicesForDescription(registry* zooRegistry, maps* m, char* r_inputs, free (tmp0); if (t < 0) { + fflush(stderr); + fflush(stdout); zDup2 (saved_stdout, fileno (stdout)); exitAndCleanUp(zooRegistry, m, buff,"InternalError","NULL", orig,corig, funcError); + if(dirp!=NULL) + closedir (dirp); return 1; } #ifdef DEBUG @@ -1225,20 +1619,27 @@ int fetchServicesForDescription(registry* zooRegistry, maps* m, char* r_inputs, buff,"InvalidParameterValue","Identifier", orig,corig, funcError); + if(dirp!=NULL) + closedir (dirp); return 1; } rewinddir (dirp); tmps = strtok_r (NULL, ",", &saveptr); if (corig != NULL) free (corig); - } + } + if(dirp!=NULL) + closedir (dirp); } fflush (stdout); + fflush (stderr); zDup2 (saved_stdout, fileno (stdout)); + zClose(saved_stdout); free (orig); return 0; } +#ifdef USE_JSON /** * Run every HTTP request to download inputs passed as reference * @@ -1247,7 +1648,7 @@ int fetchServicesForDescription(registry* zooRegistry, maps* m, char* r_inputs, */ int loadHttpRequests(maps* conf,maps* inputs){ // Resolve reference - // TODO: add erro gesture + // TODO: add error gesture int eres; maps* tmpMaps=getMaps(conf,"http_requests"); if(tmpMaps!=NULL){ @@ -1281,23 +1682,7 @@ int loadHttpRequests(maps* conf,maps* inputs){ } return 0; } - -/** - * Returns current UTC timestamp - * @param dest - * @return - */ -char *getUtcTimestamp(char *dest) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm *tmp = gmtime(&tv.tv_sec); - char fmt[128]; - strftime(fmt, sizeof(fmt), "%Y-%m-%dT%H:%M:%S.%%06uZ", tmp); - sprintf(dest, fmt, tv.tv_usec); - return dest; -} - +#endif /** * Initialize environment sections, load env, and populate lenv and renv. @@ -1409,10 +1794,6 @@ void initAllEnvironment(maps* conf,map* request_inputs, addToMap (_tmpMaps->content, "usid", tmpUuid); free(tmpUuid); addToMap (_tmpMaps->content, "status", "0"); - - // UTC timestamp of the time of the job start - char dest[12]; - addToMap (_tmpMaps->content, "started", getUtcTimestamp(dest)); map* cwdMap0=getMapFromMaps(conf,"main","servicePath"); if(cwdMap0!=NULL){ addToMap (_tmpMaps->content, "cwd", cwdMap0->value); @@ -1453,7 +1834,9 @@ void initAllEnvironment(maps* conf,map* request_inputs, sessId->value); free (tcook); maps *tmpSess = (maps *) malloc (MAPS_SIZE); - tmpSess->child=NULL; + tmpSess->content = NULL; + tmpSess->child = NULL; + tmpSess->next = NULL; struct stat file_status; int istat = stat (session_file_path, &file_status); if (istat == 0 && file_status.st_size > 0) @@ -1473,6 +1856,7 @@ void initAllEnvironment(maps* conf,map* request_inputs, addMapsToMaps (&conf, _tmpMaps); freeMaps (&_tmpMaps); free (_tmpMaps); + maps* bmap=NULL; #ifdef DEBUG dumpMap (request_inputs); @@ -1549,7 +1933,7 @@ void initAllEnvironment(maps* conf,map* request_inputs, addToMap (request_inputs, "storeExecuteResponse", "true"); addToMap (request_inputs, "status", "true"); setMapInMaps (conf, "lenv", "osid", test1->value); - status = getMap (request_inputs, "status"); + //status = getMap (request_inputs, "status"); } test1 = getMap (request_inputs, "usid"); if (test1 != NULL){ @@ -1574,6 +1958,7 @@ donothing (int sig) exit (0); } + /** * Signal handling function which create an ExceptionReport node containing the * information message corresponding to the signal number. @@ -1621,6 +2006,26 @@ sig_handler (int sig) exit (0); } +/** + * Register signals + * + * @param a function for handling signals + * @see donothing + */ +void register_signals(void (func)(int)){ +#ifndef USE_GDB +#ifndef WIN32 + signal (SIGCHLD, SIG_IGN); +#endif + signal (SIGSEGV, func); + signal (SIGTERM, func); + signal (SIGINT, func); + signal (SIGILL, func); + signal (SIGFPE, func); + signal (SIGABRT, func); +#endif +} + #ifdef USE_JSON /** * Signal handling function which create an ExceptionReport node containing the @@ -1687,6 +2092,7 @@ void loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs, maps ** inputs, maps ** ioutputs, int *eres) { + //char serviceNamespacePath[1024]; char eoUserPath[1024]; char tmps1[1024]; char ntmp[1024]; @@ -1697,19 +2103,26 @@ loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs, * Extract serviceType to know what kind of service should be loaded */ - + /** EOEPCA SPEC **/ memset(eoUserPath,'\0',1024); map* eoUserMap=getMapFromMaps(m,"eoepcaUser","user"); map* eoUserPathMap=getMapFromMaps(m,"eoepca","userworkspace"); if( eoUserMap && strlen(eoUserMap->value)>0 && eoUserPathMap && strlen(eoUserPathMap->value)>0){ - sprintf(eoUserPath,"%s/%s",eoUserPathMap->value,eoUserMap->value); - fprintf(stderr,"MAP ALL:--> %s***************0 \n",eoUserPath); - + setMapInMaps(m, "lenv","cwd", eoUserPath); } + /** EOEPCA SPEC END **/ + + /* memset(serviceNamespacePath,'\0',1024); + map* zooServicesNamespaceMap= getMapFromMaps(m, "zooServicesNamespace", "namespace"); + map* zooServicesNamespacePathMap=getMapFromMaps(m,"servicesNamespace","path"); + if( zooServicesNamespaceMap && strlen(zooServicesNamespaceMap->value)>0 && zooServicesNamespacePathMap && strlen(zooServicesNamespacePathMap->value)>0){ + sprintf(serviceNamespacePath,"%s/%s",zooServicesNamespacePathMap->value,zooServicesNamespaceMap->value); + setMapInMaps(m, "lenv","cwd", serviceNamespacePath); + }*/ map *r_inputs = NULL; map* cwdMap=getMapFromMaps(m,"main","servicePath"); @@ -1728,28 +2141,36 @@ loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs, fflush (stderr); #endif - map* libp = getMapFromMaps(m, "main", "libPath"); + map* libp = getMapFromMaps(m, "main", "libPath"); + if (strlen (r_inputs->value) == 1 && strncasecmp (r_inputs->value, "C", 1) == 0) { - if (libp != NULL && libp->value != NULL) { - r_inputs = getMap (s1->content, "ServiceProvider"); - sprintf (tmps1, "%s/%s", libp->value, r_inputs->value); - } - else { - r_inputs = getMap (request_inputs, "metapath"); - if (r_inputs != NULL) - sprintf (tmps1, "%s/%s", ntmp, r_inputs->value); - else - sprintf (tmps1, "%s/", ntmp); - - char *altPath = zStrdup ( strlen(eoUserPath)>0?eoUserPath:tmps1); + if (libp != NULL && libp->value != NULL) { + r_inputs = getMap (s1->content, "ServiceProvider"); + sprintf (tmps1, "%s/%s", libp->value, r_inputs->value); + fprintf (stderr, "libpath1 + service provider : %s/%s", libp->value, r_inputs->value); + } + else { + r_inputs = getMap (request_inputs, "metapath"); + if (r_inputs != NULL) + sprintf (tmps1, "%s/%s", ntmp, r_inputs->value); + else + sprintf (tmps1, "%s/", ntmp); + /** EOEPCA SPEC **/ + char *altPath = zStrdup ( strlen(eoUserPath)>0?eoUserPath:tmps1); r_inputs = getMap (s1->content, "ServiceProvider"); sprintf (tmps1, "%s/%s", altPath, r_inputs->value); fprintf(stderr,"--->%s \n",tmps1); free (altPath); - } + /** EOEPCA SPEC END **/ + + /*char *altPath = zStrdup ( strlen(serviceNamespacePath)>0?serviceNamespacePath:tmps1); + r_inputs = getMap (s1->content, "ServiceProvider"); + sprintf (tmps1, "%s/%s", altPath, r_inputs->value); + free (altPath);*/ + } #ifdef DEBUG fprintf (stderr, "Trying to load %s\n", tmps1); #endif @@ -1794,13 +2215,7 @@ loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs, execute_t execute = (execute_t) GetProcAddress (so, fname); #else typedef int (*execute_t) (char ***, char ***, char ***); - - char* nS = zStrdup(fname); - replace_char(nS,'.','_'); - replace_char(nS,'-','_'); - fprintf(stderr,"service from %s to %s\n",fname,nS); execute_t execute = (execute_t) dlsym (so, fname); - free(nS); #endif #ifdef DEBUG #ifdef WIN32 @@ -1849,17 +2264,22 @@ loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs, fprintf (stderr, "Try to load function %s\n", r_inputs->value); #endif typedef int (*execute_t) (maps **, maps **, maps **); + /** EOEPCA SPEC **/ + char* nS = zStrdup(r_inputs->value); + maps* pmsTmp=getMaps(m,"fnRewrite"); + if(pmsTmp!=NULL){ + free(nS); + nS=translateCharMap(r_inputs->value,pmsTmp->content); + } + fprintf(stderr,"service from %s to %s\n",r_inputs->value,nS); #ifdef WIN32 execute_t execute = - (execute_t) GetProcAddress (so, r_inputs->value); + (execute_t) GetProcAddress (so, nS); #else - char* nS = zStrdup(r_inputs->value); - replace_char(nS,'.','_'); - replace_char(nS,'-','_'); - fprintf(stderr,"service from %s to %s\n",r_inputs->value,nS); - execute_t execute = (execute_t) dlsym (so, nS); - free(nS); + execute_t execute = (execute_t) dlsym (so, nS); #endif + free(nS); + /** EOEPCA SPEC END **/ if (execute == NULL) { @@ -1886,7 +2306,7 @@ loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs, #ifdef DEBUG #ifdef WIN32 - errstr = getLastErrorMessage(); + errstr = getLastErrorMessage(); #else errstr = dlerror (); #endif @@ -1964,7 +2384,7 @@ loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs, #endif #ifdef USE_PYTHON if (strncasecmp (r_inputs->value, "PYTHON", 6) == 0) - { + { *eres = zoo_python_support (&m, request_inputs, s1, &request_input_real_format, @@ -2232,18 +2652,7 @@ int runRequest (map ** inputs) { -#ifndef USE_GDB -#ifndef WIN32 - signal (SIGCHLD, SIG_IGN); -#endif - signal (SIGSEGV, sig_handler); - signal (SIGTERM, sig_handler); - signal (SIGINT, sig_handler); - signal (SIGILL, sig_handler); - signal (SIGFPE, sig_handler); - signal (SIGABRT, sig_handler); -#endif - + register_signals(sig_handler); map *r_inputs = NULL; map *request_inputs = *inputs; @@ -2261,7 +2670,9 @@ runRequest (map ** inputs) return errorException (NULL, _("Unable to allocate memory"), "InternalError", NULL); } - m->child=NULL; + m->content = NULL; + m->child = NULL; + m->next = NULL; char ntmp[1024]; #ifndef ETC_DIR #ifndef WIN32 @@ -2289,25 +2700,22 @@ runRequest (map ** inputs) fprintf (stderr, "***** END MAPS\n"); #endif + /** EOEPCA SPEC **/ //rdr addUserToMap(m); maps* userMap=getMaps(m,"eoepcaUser"); + /** EOEPCA SPEC END **/ + + int i = addServicesNamespaceToMap(m); + if(i) { + map* error=createMap("code","BadRequest"); + addToMap(error,"message",_("The resource is not available")); + printExceptionReportResponseJ(m,error); + setMapInMaps(m,"lenv","status_code","404 Bad Request"); + return 1; + } - // map *theServicePath = getMapFromMaps (m, "main", "servicePath"); - // if (theServicePath && theServicePath->value ){ - // int theLen=(strlen(theServicePath->value)+1024+1)*sizeof(char); - // char* tmpNewPath=(char*) malloc(theLen); - // memset(tmpNewPath,0,theLen); - // sprintf(tmpNewPath,"%s%s",theServicePath->value,"rdr" ); - // free(theServicePath->value); - // theServicePath->value=tmpNewPath; - // } - -// map* eoUserMap=getMapFromMaps(m,"eoepcaUser","user"); -// if (eoUserMap && eoUserMap->value){ -// fprintf(stderr,"eoUserMap->value=%s a8\n",eoUserMap->value); -// } - + maps* zooServicesNamespaceMap=getMaps(m,"zooServicesNamespace"); map *getPath = getMapFromMaps (m, "main", "gettextPath"); if (getPath != NULL) @@ -2337,6 +2745,34 @@ runRequest (map ** inputs) r_inputs = getMap (request_inputs, "language"); if (r_inputs == NULL) r_inputs = getMap (request_inputs, "AcceptLanguages"); + if (r_inputs == NULL){ + // HTTP_ACCEPT_LANGUAGE + char* pcAcceptLanguages=getenv("HTTP_ACCEPT_LANGUAGE"); + if(pcAcceptLanguages!=NULL){ + char* saveptr; + char *tmps = strtok_r (pcAcceptLanguages, ",", &saveptr); + while(tmps!=NULL){ + if(strstr(tmps,";")==NULL && isValidLang (m, tmps) >=0 ){ + setMapInMaps(m, "main", "language",tmps); + break; + } + else{ + char* saveptr1; + char *tmps1 = strtok_r (tmps, ";", &saveptr1); + int hasValue=-1; + while(tmps1!=NULL && isValidLang (m, tmps) >=0 ){ + setMapInMaps(m, "main", "language",tmps1); + hasValue=1; + break; + tmps1 = strtok_r (NULL, ";", &saveptr1); + } + if(hasValue>0) + break; + } + tmps = strtok_r (NULL, ",", &saveptr); + } + } + } if (r_inputs == NULL) r_inputs = getMapFromMaps (m, "main", "language"); if (r_inputs != NULL) @@ -2409,9 +2845,9 @@ runRequest (map ** inputs) if(strlen(cgiServerName)>0) { char tmpUrl[1024]; - + if ( getenv("HTTPS") != NULL && strncmp(getenv("HTTPS"), "on", 2) == 0 ) { - // Knut: check if non-empty instead of "on"? + // Knut: check if non-empty instead of "on"? if ( strncmp(cgiServerPort, "443", 3) == 0 ) { sprintf(tmpUrl, "https://%s%s", cgiServerName, cgiScriptName); } @@ -2452,23 +2888,30 @@ runRequest (map ** inputs) } // Populate the Registry - char conf_dir[1024*2]; + char conf_dir_[1024]; + char conf_dir[1024]; int t; - char tmps1[1024*2]; + char tmps1[1024]; r_inputs = NULL; r_inputs = getMap (request_inputs, "metapath"); map* cwdMap0=getMapFromMaps(m,"main","servicePath"); if (r_inputs != NULL) if(cwdMap0!=NULL) - snprintf (conf_dir, 1024, "%s/%s", cwdMap0->value, r_inputs->value); + snprintf (conf_dir_, 1024, "%s/%s", cwdMap0->value, r_inputs->value); else - snprintf (conf_dir, 1024, "%s/%s", ntmp, r_inputs->value); + snprintf (conf_dir_, 1024, "%s/%s", ntmp, r_inputs->value); else if(cwdMap0!=NULL) - snprintf (conf_dir, 1024, "%s", cwdMap0->value); + snprintf (conf_dir_, 1024, "%s", cwdMap0->value); else - snprintf (conf_dir, 1024, "%s", ntmp); - map* reg = getMapFromMaps (m, "main", "registry"); + snprintf (conf_dir_, 1024, "%s", ntmp); + + getServicesNamespacePath(m,conf_dir_,conf_dir,1024); +#ifdef DEBUG + fprintf (stderr, "conf_dir: %s\n", conf_dir); + fprintf (stderr, "new conf_dir: %s\n", conf_dir); +#endif + map* reg = getMapFromMaps (m, "main", "registry"); registry* zooRegistry=NULL; if(reg!=NULL){ #ifndef WIN32 @@ -2490,802 +2933,1392 @@ runRequest (map ** inputs) zClose(saved_stdout); #endif } - - setMapInMaps(m,"lenv","executionType","xml"); - if((strlen(cgiQueryString)>0 && cgiQueryString[0]=='/') && strstr(cgiAccept,"json")!=NULL){ - // - // OGC API - Processing starts here - // + + int eres = SERVICE_STARTED; + int cpid = zGetpid (); + maps* bmap=NULL; + char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog; + FILE *f0, *f1; + HINTERNET hInternet; + service *s1=NULL; + maps *request_output_real_format = NULL; + maps *request_input_real_format = NULL; + + if((strlen(cgiQueryString)>0 && cgiQueryString[0]=='/') /*&& strstr(cgiAccept,"json")!=NULL*/){ + // + // OGC API - Processes starts here + // #ifndef USE_JSON - errorException (m, _("OGC API - Processing is not supported by this ZOO-Kernel."), "InternalError", NULL); + errorException (m, _("OGC API - Processes is not supported by this ZOO-Kernel, please contact the service provider."), "InternalError", NULL); return 1; #else -#ifndef USE_GDB -#ifndef WIN32 - signal (SIGCHLD, SIG_IGN); -#endif - signal (SIGSEGV, json_sig_handler); - signal (SIGTERM, json_sig_handler); - signal (SIGINT, json_sig_handler); - signal (SIGILL, json_sig_handler); - signal (SIGFPE, json_sig_handler); - signal (SIGABRT, json_sig_handler); -#endif + register_signals(json_sig_handler); + setMapInMaps(m,"main","executionType","json"); + char *pcaCgiQueryString=NULL; + if(strstr(cgiQueryString,"&")!=NULL){ + char tmp='&'; + char *token,*saveptr; + int iCnt=0; + token=strtok_r(cgiQueryString,"&",&saveptr); + while(token!=NULL){ + if(iCnt>0){ + char *token1,*saveptr1; + char *name=NULL; + char *value=NULL; + token1=strtok_r(token,"=",&saveptr1); + while(token1!=NULL){ + if(name==NULL) + name=zStrdup(token1); + else + value=url_decode(token1); + token1=strtok_r(NULL,"=",&saveptr1); + } + addToMapA(request_inputs,name, value != NULL ? value : ""); + free(name); + free(value); + name=NULL; + value=NULL; + }else{ + pcaCgiQueryString=zStrdup(token); + } + iCnt++; + token=strtok_r(NULL,"&",&saveptr); + } + } + if(pcaCgiQueryString==NULL) + pcaCgiQueryString=zStrdup(cgiQueryString); + + //dumpMap(request_inputs); r_inputs = getMapOrFill (&request_inputs, "metapath", ""); char conf_file1[10240]; maps* m1 = (maps *) malloc (MAPS_SIZE); + m1->content = NULL; + m1->child = NULL; + m1->next = NULL; snprintf (conf_file1, 10240, "%s/%s/oas.cfg", ntmp, r_inputs->value); if (conf_read (conf_file1, m1) == 2) { errorException (NULL, _("Unable to load the oas.cfg file."), "InternalError", NULL); - free (m); + free (m1); return 1; } addMapsToMaps(&m,m1); - setMapInMaps(m,"lenv","executionType","json"); + freeMaps(&m1); + free(m1); + + /** EOEPCA SPEC **/ + // Define specific route for Undeploy/DeployProcess + setMapInMaps(m,"lenv","request_method",cgiRequestMethod); + if(strncasecmp(cgiRequestMethod,"DELETE",6)==0 && strstr(cgiQueryString,"/processes/")!=NULL){ + free(pcaCgiQueryString); + pcaCgiQueryString=zStrdup("/processes/UndeployProcess/execution"); + setMapInMaps(m,"lenv","request_method","POST"); + if(strlen(strstr(cgiQueryString,"/processes/"))>11){ + char* pcaProcessId=zStrdup(strstr(cgiQueryString,"/processes/")+11); + char newPath[1024]; + getUserWorkspacePath(m,ntmp,newPath,1024); + fprintf(stderr,"----+++++++--- %s %d %s \n",__FILE__,__LINE__,newPath); + fprintf(stderr,"----+++++++--- %s %d %s \n",__FILE__,__LINE__,pcaProcessId); + fflush(stderr); + setMapInMaps(m,"lenv","deployedService",pcaProcessId); + char* pcaFileName=(char*)malloc((strlen(newPath)+strlen(pcaProcessId)+7)*sizeof(char)); + sprintf(pcaFileName,"%s/%s.json",newPath,pcaProcessId); + FILE* pfRequest=fopen(pcaFileName,"rb"); + if(pfRequest!=NULL){ + zStatStruct f_status; + int s=zStat(pcaFileName, &f_status); + if(f_status.st_size>0){ + char* pcaTmp=(char*)malloc((f_status.st_size+1)*sizeof(char)); + fread(pcaTmp,1,f_status.st_size,pfRequest); + pcaTmp[f_status.st_size]=0; + addToMap(request_inputs,"jrequest",pcaTmp); + free(pcaTmp); + } + fclose(pfRequest); + }else{ + map* error=createMap("code","NoSuchProcess"); + addToMap(error,"message",_("The process is not yet deployed.")); + setMapInMaps(m,"headers","Content-Type","application/json;charset=UTF-8"); + printExceptionReportResponseJ(m,error); + //json_object_put(res); + // TODO: cleanup memory + return 1; + } + } + } else + if((strcmp(cgiQueryString,"/processes")==0 || strcmp(cgiQueryString,"/processes/")==0) && + (strcasecmp(cgiRequestMethod,"post")==0 || strncasecmp(cgiRequestMethod,"put",6)==0) ){ + free(pcaCgiQueryString); + pcaCgiQueryString=zStrdup("/processes/DeployProcess/execution"); + if(strncasecmp(cgiRequestMethod,"PUT",6)==0) + setMapInMaps(m,"lenv","request_method","POST"); + //dumpMap(request_inputs); + } + map* pmCgiRequestMethod=getMapFromMaps(m,"lenv","request_method"); + setRootUrlMap(m); + + // Redirect using HTTP Status 301 (cf. rfc2616) in case full_html_support is + // set to true + map* pmTmp0=getMapFromMaps(m,"openapi","full_html_support"); + if(strstr(pcaCgiQueryString,".html")==NULL && strstr(cgiAccept,"text/html")!=NULL && pmTmp0!=NULL && strncasecmp(pmTmp0->value,"true",4)==0){ + map* pmTmpUrl=getMapFromMaps(m,"openapi","rootUrl"); + char* pacTmpUrl=NULL; + if(strcmp(pcaCgiQueryString,"/")!=0){ + pacTmpUrl=(char*)malloc((strlen(pcaCgiQueryString)+strlen(pmTmpUrl->value)+6)*sizeof(char)); + sprintf(pacTmpUrl,"%s%s.html",pmTmpUrl->value,pcaCgiQueryString); + } + else{ + pacTmpUrl=(char*)malloc((strlen(pmTmpUrl->value)+6)*sizeof(char)); + sprintf(pacTmpUrl,"%s/index.html",pmTmpUrl->value); + } + setMapInMaps(m,"headers","Location",pacTmpUrl); + printHeaders(m); + printf("Status: 301 Moved permanently \r\n\r\n"); + fflush(stdout); + free(pacTmpUrl); + return 1; + } json_object *res=json_object_new_object(); setMapInMaps(m,"headers","Content-Type","application/json;charset=UTF-8"); - - - if(( - strcmp(cgiQueryString,"/processes")==0 || strcmp(cgiQueryString,"/processes/")==0) && - strcasecmp(cgiRequestMethod,"post")==0 - ){ - - cgiQueryString="/processes/DeployProcess/jobs"; - } - -// if(( -// strcmp(cgiQueryString,"/processes")==0 || strcmp(cgiQueryString,"/processes/")==0) && -// strcasecmp(cgiRequestMethod,"delete")==0 -// ){ -// -// -// -// -// //cgiRequestMethod="post"; -// cgiQueryString="/processes/UndeployProcess/jobs"; -// } - - /* - Root url */ - if(cgiContentLength==1){ + if((strncasecmp(pmCgiRequestMethod->value,"post",4)==0 && + (strstr(pcaCgiQueryString,"/processes/")==NULL || + strlen(pcaCgiQueryString)<=11)) + || + (strncasecmp(pmCgiRequestMethod->value,"DELETE",6)==0 && + (strstr(pcaCgiQueryString,"/jobs/")==NULL || strlen(pcaCgiQueryString)<=6)) ){ + setMapInMaps(m,"lenv","status_code","405"); + map* error=createMap("code","InvalidMethod"); + addToMap(error,"message",_("The request method used to access the current path is not supported.")); + printExceptionReportResponseJ(m,error); + json_object_put(res); + // TODO: cleanup memory + return 1; + } + else if(cgiContentLength==1){ + if(strncasecmp(pmCgiRequestMethod->value,"GET",3)!=0){ + setMapInMaps(m,"lenv","status_code","405"); + map* pamError=createMap("code","InvalidMethod"); + const char* pccErr=_("This API does not support the method."); + addToMap(pamError,"message",pccErr); + printExceptionReportResponseJ(m,pamError); + // TODO: cleanup memory + return 1; + } map* tmpMap=getMapFromMaps(m,"main","serverAddress"); json_object *res1=json_object_new_array(); - const char* urls[4]={ - "/","/api","/conformance","/processes" - }; - map* tmpUrl=getMapFromMaps(m,"main","serverAddress"); - for(int kk=0;kk<4;kk++){ - maps* tmpMaps=getMaps(m,urls[kk]); - json_object *res2; + + map* pmVal=getMapFromMaps(m,"openapi","links"); + char *orig=zStrdup(pmVal->value); + char *saveptr; + char *tmps = strtok_r (orig, ",", &saveptr); + map* tmpUrl=getMapFromMaps(m,"openapi","rootUrl"); + while(tmps!=NULL){ + maps* tmpMaps=getMaps(m,tmps); if(tmpMaps!=NULL){ + json_object *res2; res2=mapToJson(tmpMaps->content); - char* tmpStr=(char*) malloc((strlen(tmpUrl->value)+strlen(urls[kk])+2)*sizeof(char)); - sprintf(tmpStr,"%s%s",tmpUrl->value,urls[kk]); + char* tmpStr=(char*) malloc((strlen(tmpUrl->value)+strlen(tmps)+2)*sizeof(char)); + sprintf(tmpStr,"%s%s",tmpUrl->value,tmps); json_object_object_add(res2,"href",json_object_new_string(tmpStr)); + free(tmpStr); json_object_array_add(res1,res2); + + map* pmTmp=getMap(tmpMaps->content,"title"); + char *pacTitle=NULL; + if(pmTmp!=NULL) + pacTitle=zStrdup(pmTmp->value); + char* pacTmp=(char*) malloc((strlen(tmps)+6)*sizeof(char)); + sprintf(pacTmp,"%s.html",tmps); + tmpMaps=getMaps(m,pacTmp); + if(tmpMaps==NULL && strncasecmp(pacTmp,"/.html",6)==0) + tmpMaps=getMaps(m,"/index.html"); + if(tmpMaps!=NULL){ + json_object *res3; + res3=mapToJson(tmpMaps->content); + if(getMap(tmpMaps->content,"title")==NULL && pacTitle!=NULL){ + json_object_object_add(res3,"title",json_object_new_string(_(pacTitle))); + } + char* tmpStr=NULL; + if(strncasecmp(pacTmp,"/.html",6)==0){ + tmpStr=(char*) malloc((strlen(tmpUrl->value)+12)*sizeof(char)); + sprintf(tmpStr,"%s/index.html",tmpUrl->value); + }else{map* tmpUrl=getMapFromMaps(m,"openapi","rootUrl"); + tmpStr=(char*) malloc((strlen(tmpUrl->value)+strlen(tmps)+6)*sizeof(char)); + sprintf(tmpStr,"%s%s.html",tmpUrl->value,tmps); + } + json_object_object_add(res3,"href",json_object_new_string(tmpStr)); + free(tmpStr); + json_object_array_add(res1,res3); + } + free(pacTmp); + if(pacTitle!=NULL) + free(pacTitle); } + tmps = strtok_r (NULL, ",", &saveptr); } + free(orig); + + map* pmTmp=getMapFromMaps(m,"identification","title"); + if(pmTmp!=NULL) + json_object_object_add(res,"title",json_object_new_string(_(pmTmp->value))); + pmTmp=getMapFromMaps(m,"identification","abstract"); + if(pmTmp!=NULL) + json_object_object_add(res,"description",json_object_new_string(_(pmTmp->value))); json_object_object_add(res,"links",res1); - }else if(strcmp(cgiQueryString,"/conformance")==0){ + }else if(strcmp(pcaCgiQueryString,"/conformance")==0){ /* - /conformance url */ - map* rootUrl=getMapFromMaps(m,"conformTo","rootUrl"); + maps* pmsConformsTo=getMaps(m,"conformsTo"); + map* pmExtentionsLength=getMapFromMaps(m,"conformsTo","extentionsLength"); + int len=0; + map* pmExtentionUrl=NULL; + if(pmExtentionsLength!=NULL){ + len=atoi(pmExtentionsLength->value); + } + map* rootUrl=getMapFromMaps(m,"conformsTo","rootUrl"); json_object *res1=json_object_new_array(); - map* length=getMapFromMaps(m,"conformTo","length"); - maps* tmpMaps=getMaps(m,"conformTo"); + map* length=getMapFromMaps(m,"conformsTo","length"); for(int kk=0;kkvalue);kk++){ - map* tmpMap1=getMapArray(tmpMaps->content,"link",kk); + map* tmpMap1=getMapArray(pmsConformsTo->content,"link",kk); json_object *res2; if(tmpMap1!=NULL){ - char* tmpStr=(char*) malloc((strlen(rootUrl->value)+strlen(tmpMap1->value)+1)*sizeof(char)); - sprintf(tmpStr,"%s%s",rootUrl->value,tmpMap1->value); + char* tmpStr=NULL; + if(getMapArray(pmsConformsTo->content,"extention",kk)!=NULL){ + map* pmCid=getMapArray(pmsConformsTo->content,"extid",kk); + if(pmCid!=NULL){ + pmExtentionUrl=getMapArray(pmsConformsTo->content,"extentionUrl",atoi(pmCid->value)); + if(pmExtentionUrl!=NULL){ + tmpStr=(char*) malloc((strlen(pmExtentionUrl->value)+strlen(tmpMap1->value)+1)*sizeof(char)); + sprintf(tmpStr,"%s%s",pmExtentionUrl->value,tmpMap1->value); + } + } + } + else{ + tmpStr=(char*) malloc((strlen(rootUrl->value)+strlen(tmpMap1->value)+1)*sizeof(char)); + sprintf(tmpStr,"%s%s",rootUrl->value,tmpMap1->value); + } json_object_array_add(res1,json_object_new_string(tmpStr)); + free(tmpStr); } } - json_object_object_add(res,"conformTo",res1); - }else if(strcmp(cgiQueryString,"/api")==0){ - /* - /api url */ - produceApi(m,res); - }else if( strstr(cgiQueryString,"/processes/") && strcasecmp(cgiRequestMethod,"delete")==0 ){ - - - fprintf(stderr,"%s\n",cgiQueryString); - char* p=strstr(cgiQueryString,"/processes/"); - if (strlen(cgiQueryString)>11/*/processes/*/){ - - char *orig = zStrdup (p+11); - if(orig[strlen(orig)-1]=='/') - orig[strlen(orig)-1]=0; - - char *theS=strchr(orig,'/'); - if (theS){ - *theS='\0'; - } - - fprintf(stderr,"%s\n",orig); - - - - int y=removeService(m,orig); - free (orig); - if (y){ - // errorException (conf, _("Unable to allocate memory"),"InternalError", NULL); - return 1; - } - + json_object_object_add(res,"conformsTo",res1); + }else if(strncasecmp(pcaCgiQueryString,"/api",4)==0){ + if(strstr(pcaCgiQueryString,".html")==NULL) + produceApi(m,res); + else{ + char* pacTmp=(char*)malloc(9*sizeof(char)); + sprintf(pacTmp,"%s",pcaCgiQueryString+1); + map* pmTmp=getMapFromMaps(m,pacTmp,"href"); + free(pacTmp); + if(pmTmp!=NULL) + setMapInMaps(m,"headers","Location",pmTmp->value); } - - }else if(strcmp(cgiQueryString,"/processes")==0 || strcmp(cgiQueryString,"/processes/")==0){ + }else if(strcmp(pcaCgiQueryString,"/processes")==0 || strcmp(pcaCgiQueryString,"/processes/")==0){ /* - /processes */ + setMapInMaps(m,"lenv","requestType","desc"); + setMapInMaps(m,"lenv","serviceCnt","0"); + setMapInMaps(m,"lenv","serviceCounter","0"); + map* pmTmp=getMap(request_inputs,"limit"); + if(pmTmp!=NULL) + setMapInMaps(m,"lenv","serviceCntLimit",pmTmp->value); + else{ + pmTmp=getMapFromMaps(m,"limitParam","schema_default"); + if(pmTmp!=NULL) + setMapInMaps(m,"lenv","serviceCntLimit",pmTmp->value); + } + pmTmp=getMap(request_inputs,"skip"); + if(pmTmp!=NULL) + setMapInMaps(m,"lenv","serviceCntSkip",pmTmp->value); json_object *res3=json_object_new_array(); int saved_stdout = zDup (fileno (stdout)); zDup2 (fileno (stderr), fileno (stdout)); - - if (int res = + if (int res0 = recursReaddirF (m, NULL, res3, NULL, ntmp, NULL, saved_stdout, 0, - printGetCapabilitiesForProcessJ) < 0) - { - } - zDup2 (saved_stdout, fileno (stdout)); + printGetCapabilitiesForProcessJ) < 0) { + }else{ + fflush(stderr); + fflush(stdout); + zDup2 (saved_stdout, fileno (stdout)); + } zClose(saved_stdout); - -// json_object_object_add(res,"processes",res3); //rdr - json_object_put(res);//rdr - res = res3;//rdr - }else{ - service* s1=NULL; - int t=0; - if(strstr(cgiQueryString,"/processes/")==NULL){ - map* error=createMap("code","BadRequest"); - addToMap(error,"message",_("The ressource is not available")); - //setMapInMaps(conf,"lenv","status_code","404 Bad Request"); - printExceptionReportResponseJ(m,error); - freeMaps (&m); - free (m); - free (REQUEST); - xmlCleanupParser (); - zooXmlCleanupNs (); - return 1; - } else - if(strstr(cgiQueryString,"/jobs")==NULL && strstr(cgiQueryString,"/jobs/")==NULL){ - /* - /processes/{id}/ */ - DIR *dirp = opendir (ntmp); - json_object *res3=json_object_new_object(); - char *orig = zStrdup (strstr(cgiQueryString,"/processes/")+11); - if(orig[strlen(orig)-1]=='/') - orig[strlen(orig)-1]=0; - json_object* res1=json_object_new_object(); - - int t=fetchServicesForDescription(NULL, m, orig, - printGetCapabilitiesForProcessJ, - NULL, (void*) res3, ntmp, - request_inputs, - printExceptionReportResponseJ); - if(t==1){ - /*map* error=createMap("code","BadRequest"); - addToMap(error,"message",_("Failed to acces the requested service")); - printExceptionReportResponseJ(m,error);*/ + json_object_object_add(res,"processes",res3); + setMapInMaps(m,"lenv","path","processes"); + createNextLinks(m,res); + } + else if(strstr(pcaCgiQueryString,"/processes")==NULL && (strstr(pcaCgiQueryString,"/jobs")!=NULL || strstr(pcaCgiQueryString,"/jobs/")!=NULL)){ + /* - /jobs url */ + if(strncasecmp(pmCgiRequestMethod->value,"DELETE",6)==0) { + char* pcTmp=strstr(pcaCgiQueryString,"/jobs/"); + if(strlen(pcTmp)>6){ + char* jobId=zStrdup(pcTmp+6); + setMapInMaps(m,"lenv","gs_usid",jobId); + setMapInMaps(m,"lenv","file.statusFile",json_getStatusFilePath(m)); + runDismiss(m,jobId); + map* pmError=getMapFromMaps(m,"lenv","error"); + if(pmError!=NULL && strncasecmp(pmError->value,"true",4)==0){ + printExceptionReportResponseJ(m,getMapFromMaps(m,"lenv","code")); return 1; } - res=json_object_get(res3); - }else{ - char* queryString=zStrdup(cgiQueryString); - int len0=strlen(strstr(cgiQueryString,"/processes/")+11); - int len1=strlen(cgiQueryString)-strlen(strstr(cgiQueryString,"/job")); - char* cIdentifier=(char*)malloc((len1-10)*sizeof(char)); - int cnt=0; - for(int j=11;jvalue != NULL) { - strncpy(tmps1, import->value, 1024); - setMapInMaps (m, "lenv", "Identifier", cIdentifier); - setMapInMaps (m, "lenv", "oIdentifier", cIdentifier); - } - else { - //rdr....... - char newPath[1024]; - getUserWorkspacePath(m,ntmp,newPath,1024); - - if ( - strcmp(cIdentifier,"DeployProcess")==0 || - strcmp(cIdentifier,"UndeployProcess")==0 - ){ - memset(newPath,'\0',1024); - strcpy(newPath,ntmp); - } - - if (strcmp(ntmp, newPath )==0) { - snprintf (tmps1, 1024, "%s/%s.zcfg", ntmp, cIdentifier); - }else{ - // fprintf(stderr,"rdr a7 %s/%s.zcfg \n",newPath, cIdentifier); - snprintf (tmps1, 1024, "%s/%s.zcfg", newPath, cIdentifier); + } } - //rdr....... - -#ifdef DEBUG - fprintf (stderr, "Trying to load %s\n", tmps1); -#endif - if (strstr (cIdentifier, ".") != NULL) - { - char *identifier = zStrdup (cIdentifier); - parseIdentifier (m, ntmp, identifier, tmps1); - map *tmpMap = getMapFromMaps (m, "lenv", "metapath"); - if (tmpMap != NULL) - addToMap (request_inputs, "metapath", tmpMap->value); - free (identifier); - } - else - { - setMapInMaps (m, "lenv", "oIdentifier", cIdentifier); - setMapInMaps (m, "lenv", "Identifier", cIdentifier); - } - } - - r_inputs = getMapFromMaps (m, "lenv", "Identifier"); - -#ifdef META_DB - int metadb_id=_init_sql(m,"metadb"); - //FAILED CONNECTING DB - if(getMapFromMaps(m,"lenv","dbIssue")!=NULL || metadb_id<0){ - fprintf(stderr,"ERROR CONNECTING METADB\n"); + else if(strcasecmp(pmCgiRequestMethod->value,"get")==0){ + /* - /jobs List (GET) */ + if(strlen(pcaCgiQueryString)<=6){ + map* pmTmp=getMap(request_inputs,"limit"); + if(pmTmp!=NULL) + setMapInMaps(m,"lenv","serviceCntLimit",pmTmp->value); + else{ + pmTmp=getMapFromMaps(m,"limitParam","schema_default"); + if(pmTmp!=NULL) + setMapInMaps(m,"lenv","serviceCntLimit",pmTmp->value); } - if(metadb_id>=0) - s1=extractServiceFromDb(m,cIdentifier,0); - if(s1!=NULL){ - inheritance(zooRegistry,&s1); -#ifdef USE_HPC - addNestedOutputs(&s1); -#endif - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); - } - }else /* Not found in MetaDB */{ -#endif - s1 = createService(); - if (s1 == NULL) - { - freeMaps (&m); - free (m); - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); + pmTmp=getMap(request_inputs,"skip"); + if(pmTmp!=NULL) + setMapInMaps(m,"lenv","serviceCntSkip",pmTmp->value); + // Build the SQL Clause + char* pcaClause=NULL; + char* pcaClauseFinal=NULL; + for(int k=0;k<2;k++){ + pmTmp=getMap(request_inputs,statusSearchFields[k]); + if(pmTmp!=NULL){ + char *saveptr; + char *tmps = strtok_r(pmTmp->value, ",", &saveptr); + while (tmps != NULL){ + for(int l=0;l<3;l++){ + if(strcmp(tmps,oapipStatus[l])==0){ + tmps=wpsStatus[l]; + break; + } } - free (REQUEST); - free (SERVICE_URL); - map* error=createMap("code","InternalError"); - addToMap(error,"message",_("Unable to allocate memory")); - //setMapInMaps(conf,"lenv","status_code","404 Bad Request"); - printExceptionReportResponseJ(m,error); - - return 1; /*errorException (m, _("Unable to allocate memory"), - "InternalError", NULL);*/ + if(pcaClause==NULL){ + pcaClause=(char*)malloc((strlen(statusSearchFieldsReal[k])+strlen(tmps)+10)*sizeof(char)); + sprintf(pcaClause," (%s=$q$%s$q$",statusSearchFieldsReal[k],tmps); + }else{ + char* pcaTmp=zStrdup(pcaClause); + pcaClause=(char*)realloc(pcaClause,strlen(statusSearchFieldsReal[k])+strlen(tmps)+strlen(pcaTmp)+12); + sprintf(pcaClause,"%s OR %s=$q$%s$q$",pcaTmp,statusSearchFieldsReal[k],tmps); + free(pcaTmp); + } + tmps = strtok_r (NULL, ",", &saveptr); } - - int saved_stdout = zDup (fileno (stdout)); - zDup2 (fileno (stderr), fileno (stdout)); - t = readServiceFile (m, tmps1, &s1, cIdentifier); - if(t>=0){ - inheritance(zooRegistry,&s1); -#ifdef USE_HPC - addNestedOutputs(&s1); -#endif - } - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); + char* pcaTmp=zStrdup(pcaClause); + pcaClause=(char*)realloc(pcaClause,strlen(pcaTmp)+3); + sprintf(pcaClause,"%s) ",pcaTmp); + free(pcaTmp); } - fflush (stdout); - zDup2 (saved_stdout, fileno (stdout)); - if (t < 0) - { - char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value)); - sprintf (tmpMsg, - _ - ("The value for seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."), - r_inputs->value); - map* error=createMap("code","NotFound");//EOEPCA-237 - addToMap(error,"message",tmpMsg); - //setMapInMaps(conf,"lenv","status_code","404 Bad Request"); - printExceptionReportResponseJ(m,error); - - //errorException (m, tmpMsg, "InvalidParameterValue", "identifier"); - free (tmpMsg); - free (s1); - freeMaps (&m); - free (m); - free (REQUEST); - free (SERVICE_URL); - return 0; + if(pcaClause!=NULL){ + if(pcaClauseFinal==NULL){ + pcaClauseFinal=(char*)malloc((strlen(pcaClause)+1)*sizeof(char)); + sprintf(pcaClauseFinal,"%s",pcaClause); + }else{ + char* pcaTmp=zStrdup(pcaClauseFinal); + pcaClauseFinal=(char*)realloc(pcaClauseFinal,strlen(pcaTmp)+(strlen(pcaClause)+6)*sizeof(char)); + sprintf(pcaClauseFinal,"%s AND %s",pcaClause,pcaTmp); + free(pcaTmp); } - zClose (saved_stdout); - -#ifdef META_DB + free(pcaClause); + pcaClause=NULL; + } } -#endif - if(strstr(cgiQueryString,"/jobs/")!=NULL && strlen(strstr(cgiQueryString,"/jobs/"))>6){ - /* - /jobs/{jobID} and /jobs/{jobID}/result urls */ - if(strstr(cgiQueryString,"/result")!=NULL && strlen(strstr(cgiQueryString,"/result"))>=7){ - fprintf(stderr,"For GetResult %s %d \n",__FILE__,__LINE__); + // (min/max)Duration should be set '%s second'::interval + char* pcaClauseMin=NULL; + pmTmp=getMap(request_inputs,"minDuration"); + if(pmTmp!=NULL){ + setMapInMaps(m,"lenv","serviceMinDuration",pmTmp->value); + char *saveptr; + char *tmps = strtok_r(pmTmp->value, ",", &saveptr); + while (tmps != NULL){ + if(pcaClauseMin==NULL){ + pcaClauseMin=(char*)malloc((strlen(tmps)+52)*sizeof(char)); + sprintf(pcaClauseMin," ('%s second'::interval <= (end_time - creation_time)",tmps); + }else{ + char* pcaTmp=zStrdup(pcaClauseMin); + pcaClauseMin=(char*)realloc(pcaClauseMin,strlen(tmps)+strlen(pcaTmp)+54); + sprintf(pcaClauseMin,"%s OR '%s second'::interval <= (end_time - creation_time)",pcaTmp,tmps); + free(pcaTmp); + } + tmps = strtok_r (NULL, ",", &saveptr); + } + char* pcaTmp=zStrdup(pcaClauseMin); + pcaClauseMin=(char*)realloc(pcaClauseMin,strlen(pcaTmp)+3); + sprintf(pcaClauseMin,"%s) ",pcaTmp); + free(pcaTmp); + if(pcaClauseFinal!=NULL){ + char* pcaTmp=zStrdup(pcaClauseFinal); + pcaClauseFinal=(char*)realloc(pcaClauseFinal,strlen(pcaTmp)+(strlen(pcaClauseMin)+6)*sizeof(char)); + sprintf(pcaClauseFinal,"%s AND %s",pcaClauseMin,pcaTmp); + free(pcaTmp); }else{ - char* tmpUrl=strstr(cgiQueryString,"/jobs/"); - if(tmpUrl!=NULL && strlen(tmpUrl)>6){ - char* jobId=zStrdup(strstr(cgiQueryString,"/jobs/")+6); - setMapInMaps(m,"lenv","gs_usid",jobId); - json_getStatusFile(m); - free(jobId); - return 1; + pcaClauseFinal=(char*)malloc((strlen(pcaClauseMin)+1)*sizeof(char)); + sprintf(pcaClauseFinal,"%s",pcaClauseMin); + } + free(pcaClauseMin); + } + char* pcaClauseMax=NULL; + pmTmp=getMap(request_inputs,"maxDuration"); + if(pmTmp!=NULL){ + setMapInMaps(m,"lenv","serviceMaxDuration",pmTmp->value); + char *saveptr; + char *tmps = strtok_r(pmTmp->value, ",", &saveptr); + while (tmps != NULL){ + if(pcaClauseMax==NULL){ + pcaClauseMax=(char*)malloc((strlen(tmps)+52)*sizeof(char)); + sprintf(pcaClauseMax," ('%s second'::interval >= (end_time - creation_time)",tmps); + }else{ + char* pcaTmp=zStrdup(pcaClauseMax); + pcaClauseMax=(char*)realloc(pcaClauseMax,strlen(tmps)+strlen(pcaTmp)+54); + sprintf(pcaClauseMax,"%s OR '%s second'::interval >= (end_time - creation_time)",pcaTmp,tmps); + free(pcaTmp); } + tmps = strtok_r (NULL, ",", &saveptr); } - }else{ - /* - /jobs url */ - fprintf(stderr,"For Execute or Job list %s %d \n",__FILE__,__LINE__); - if(strcasecmp(cgiRequestMethod,"get")==0){ - /* - /jobs List (GET) */ - res=printJobList(m); - }else if(strcasecmp(cgiRequestMethod,"post")==0){ - /* - /jobs Execution (POST) */ - int eres = SERVICE_STARTED; - - initAllEnvironment(m,request_inputs,ntmp,"jrequest"); - map* req=getMapFromMaps(m,"renv","jrequest"); - json_object *jobj = NULL; - const char *mystring = NULL; - int slen = 0; - enum json_tokener_error jerr; - struct json_tokener* tok=json_tokener_new(); - do { - mystring = req->value; // get JSON string, e.g. read from file, etc... - slen = strlen(mystring); - jobj = json_tokener_parse_ex(tok, mystring, slen); - } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); - if (jerr != json_tokener_success) { - fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); - return 1; + char* pcaTmp=zStrdup(pcaClauseMax); + pcaClauseMax=(char*)realloc(pcaClauseMax,strlen(pcaTmp)+3); + sprintf(pcaClauseMax,"%s) ",pcaTmp); + free(pcaTmp); + if(pcaClauseFinal!=NULL){ + char* pcaTmp=zStrdup(pcaClauseFinal); + pcaClauseFinal=(char*)realloc(pcaClauseFinal,strlen(pcaTmp)+(strlen(pcaClauseMax)+6)*sizeof(char)); + sprintf(pcaClauseFinal,"%s AND %s",pcaClauseMax,pcaTmp); + free(pcaTmp); + }else{ + pcaClauseFinal=(char*)malloc((strlen(pcaClauseMax)+1)*sizeof(char)); + sprintf(pcaClauseFinal,"%s",pcaClauseMax); + } + free(pcaClauseMax); + } + char* pcaClauseType=NULL; + pmTmp=getMap(request_inputs,"type"); + if(pmTmp!=NULL){ + setMapInMaps(m,"lenv","serviceType",pmTmp->value); + char *saveptr; + char *tmps = strtok_r(pmTmp->value, ",", &saveptr); + while (tmps != NULL){ + if(strcmp(tmps,"process")==0) + pcaClauseType=zStrdup(tmps); + tmps = strtok_r (NULL, ",", &saveptr); + } + if(pcaClauseType!=NULL){ + if(pcaClauseFinal!=NULL){ + char* pcaTmp=zStrdup(pcaClauseFinal); + pcaClauseFinal=(char*)realloc(pcaClauseFinal, + (strlen(pcaTmp)+18)*sizeof(char)); + sprintf(pcaClauseFinal,"%s AND itype='json'", + pcaTmp); + free(pcaTmp); + }else{ + pcaClauseFinal=(char*)malloc(13*sizeof(char)); + sprintf(pcaClauseFinal,"itype='json'"); } - if (tok->char_offset < slen){ - return 1; + free(pcaClauseType); + } + } + // datetime parameter + char* pcaClauseDate=NULL; + pmTmp=getMap(request_inputs,"datetime"); + if(pmTmp!=NULL){ + if(strstr(pmTmp->value,"/")!=NULL){ + char *saveptr0; + char *tmps0 = strtok_r(pmTmp->value, ",", &saveptr0); + int iCnt0=0; + while(tmps0 != NULL){ + if(iCnt0>0){ + char *saveptr; + char *tmps = strtok_r(tmps0, "/", &saveptr); + int iCnt=0; + while (tmps != NULL){ + if(iCnt==0 && tmps0[0]!='/'){ + if(strlen(tmps)>2){ + pcaClauseDate=(char*)malloc((strlen(tmps)+30+1)*sizeof(char)); + sprintf(pcaClauseDate,"creation_time>='%s'::timestamptz",tmps); + } + }else{ + if(strlen(tmps)>2){ + if(pcaClauseDate==NULL){ + pcaClauseDate=(char*)malloc((strlen(tmps)+30+1)*sizeof(char)); + sprintf(pcaClauseDate,"creation_time<='%s'::timestamptz",tmps); + }else{ + char* pcaTmp=zStrdup(pcaClauseDate); + pcaClauseDate=(char*)realloc(pcaClauseDate,(strlen(pcaTmp)+strlen(tmps)+35+1)*sizeof(char)); + sprintf(pcaClauseDate,"%s AND creation_time<='%s'::timestamptz",pcaTmp,tmps); + free(pcaTmp); + } + } + } + iCnt++; + tmps = strtok_r (NULL, "/", &saveptr); + } + } + iCnt0++; + tmps0 = strtok_r (NULL, ",", &saveptr0); } - fprintf(stderr,"%s %d \n",__FILE__,__LINE__); - // Success, use jobj here. - maps* inputs_real_format=NULL, *outputs_real_format= NULL; - parseJRequest(m,s1,jobj,&inputs_real_format,&outputs_real_format); -#ifdef USE_JSON - int request_type = parseJRequestMode(m,s1,jobj); - switch(request_type){ - case 0: - fprintf(stderr,"REQUEST_TYPE: async\n"); - break; - case 1: - fprintf(stderr,"REQUEST_TYPE: sync\n"); - break; + }else{ + char *saveptr0; + char *tmps0 = strtok_r(pmTmp->value, ",", &saveptr0); + int iCnt0=0; + while(tmps0 != NULL){ + if(iCnt0>0){ + pcaClauseDate=(char*)malloc((strlen(tmps0)+29+1)*sizeof(char)); + sprintf(pcaClauseDate,"creation_time='%s'::timestamptz",tmps0); + } + iCnt0++; + tmps0 = strtok_r (NULL, ",", &saveptr0); } -#endif - map* preference=getMapFromMaps(m,"renv","HTTP_PREFER"); -#ifdef USE_JSON - if(request_type==0){//async -#else - if(preference!=NULL && strcasecmp(preference->value,"respond-async")==0){ -#endif - fprintf(stderr,"Asynchronous call!\n"); - char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog; - FILE *f0, *f1; - int pid; -#ifdef DEBUG - fprintf (stderr, "\nPID : %d\n", cpid); -#endif -#ifndef WIN32 - pid = fork (); + } + if(pcaClauseFinal==NULL) + pcaClauseFinal=zStrdup(pcaClauseDate); + else{ + char* pcaTmp=zStrdup(pcaClauseFinal); + pcaClauseFinal=(char*)realloc(pcaClauseFinal, + (strlen(pcaTmp)+strlen(pcaClauseDate)+6)*sizeof(char)); + sprintf(pcaClauseFinal,"%s AND %s", + pcaTmp,pcaClauseDate); + free(pcaTmp); + } + free(pcaClauseDate); + } + if(pcaClauseFinal==NULL){ + pcaClauseFinal=zStrdup("true"); + } + map *schema=getMapFromMaps(m,"database","schema"); + if(pcaClauseFinal!=NULL && schema!=NULL){ + char* pcaTmp=(char*) malloc((strlen(pcaClauseFinal)+ + strlen(schema->value)+ + 98+1) + *sizeof(char)); + sprintf(pcaTmp, + "select replace(replace(array(select ''''||uuid||'''' " + "from %s.services where %s)::text,'{',''),'}','')", + schema->value,pcaClauseFinal); + free(pcaClauseFinal); + char* tmp1= +#ifdef RELY_ON_DB + runSqlQuery(m,pcaTmp) #else - if (cgiSid == NULL) - { - createProcess (m, request_inputs, s1, NULL, cpid, - request_input_real_format, - request_output_real_format); - pid = cpid; - } - else - { - pid = 0; - cpid = atoi (cgiSid); - updateStatus(m,0,_("Initializing")); - } -#endif - if (pid > 0) - { - // - // dady : - // set status to SERVICE_ACCEPTED - // -#ifdef DEBUG - fprintf (stderr, "father pid continue (origin %d) %d ...\n", cpid, - zGetpid ()); -#endif - eres = SERVICE_ACCEPTED; - createStatusFile(m,eres); - printHeaders(m); - printf("Status: 201 Created \r\n\r\n"); - return 1; - } - else if (pid == 0) - { - eres = SERVICE_STARTED; - // - // son : have to close the stdout, stdin and stderr to let the parent - // process answer to http client. - // - map* usid = getMapFromMaps (m, "lenv", "uusid"); - map* tmpm = getMapFromMaps (m, "lenv", "osid"); - int cpid = atoi (tmpm->value); - pid=cpid; - r_inputs = getMapFromMaps (m, "main", "tmpPath"); - setMapInMaps (m, "lenv", "async","true"); - map* r_inputs1 = createMap("ServiceName", s1->name); - // Create the filename for the result file (.res) - fbkpres = - (char *) - malloc ((strlen (r_inputs->value) + - strlen (usid->value) + 7) * sizeof (char)); - sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value); - maps* bmap = createMaps("status"); - bmap->content=createMap("usid",usid->value); - addToMap(bmap->content,"sid",tmpm->value); - addIntToMap(bmap->content,"pid",zGetpid()); - - // Create PID file referencing the OS process identifier - fbkpid = - (char *) - malloc ((strlen (r_inputs->value) + - strlen (usid->value) + 7) * sizeof (char)); - sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value); - setMapInMaps (m, "lenv", "file.pid", fbkpid); - - f0 = freopen (fbkpid, "w+",stdout); - printf("%d",zGetpid()); - fflush(stdout); - - // Create SID file referencing the semaphore name - fbkp = - (char *) - malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + - strlen (usid->value) + 7) * sizeof (char)); - sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value); - setMapInMaps (m, "lenv", "file.sid", fbkp); - FILE* f2 = freopen (fbkp, "w+",stdout); - printf("%s",tmpm->value); - fflush(f2); - free(fbkp); - - fbkp = - (char *) - malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + - strlen (usid->value) + 7) * sizeof (char)); - sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value, - usid->value); - setMapInMaps (m, "lenv", "file.responseInit", fbkp); - flog = - (char *) - malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + - strlen (usid->value) + 13) * sizeof (char)); - sprintf (flog, "%s/%s_%s_error.log", r_inputs->value, - r_inputs1->value, usid->value); - setMapInMaps (m, "lenv", "file.log", flog); -#ifdef DEBUG - fprintf (stderr, "RUN IN BACKGROUND MODE \n"); - fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid, - zGetpid ()); - fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value); -#endif - freopen (flog, "w+", stderr); - fflush (stderr); - f0 = freopen (fbkp, "w+", stdout); - rewind (stdout); -#ifndef WIN32 - fclose (stdin); + NULL #endif + ; + free(pcaTmp); + if(tmp1!=NULL){ + setMapInMaps(m,"lenv","selectedJob",tmp1); + free(tmp1); + } #ifdef RELY_ON_DB - init_sql(m); - recordServiceStatus(m); -#endif -#ifdef USE_CALLBACK - invokeCallback(m,NULL,NULL,0,0); + else{ + setMapInMaps(m,"lenv","selectedJob","-1"); + } #endif - fprintf(stderr,"%s %d\n",__FILE__,__LINE__); - fflush(stderr); - - createStatusFile(m,eres); - - - fbkp1 = - (char *) - malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + - strlen (usid->value) + 15) * sizeof (char)); - sprintf (fbkp1, "%s/%s_final_%s.json", r_inputs->value, - r_inputs1->value, usid->value); - setMapInMaps (m, "lenv", "file.responseFinal", fbkp1); - - f1 = freopen (fbkp1, "w+", stdout); - - map* serviceTypeMap=getMap(s1->content,"serviceType"); - if(serviceTypeMap!=NULL) - setMapInMaps (m, "lenv", "serviceType", serviceTypeMap->value); - - char *flenv = - (char *) - malloc ((strlen (r_inputs->value) + - strlen (usid->value) + 12) * sizeof (char)); - sprintf (flenv, "%s/%s_lenv.cfg", r_inputs->value, usid->value); - maps* lenvMaps=getMaps(m,"lenv"); - dumpMapsToFile(lenvMaps,flenv,0); - free(flenv); - - map* testMap=getMapFromMaps(m,"main","memory"); - loadHttpRequests(m,inputs_real_format); - loadServiceAndRun (&m, s1, request_inputs, - &inputs_real_format, - &outputs_real_format, &eres); - createStatusFile(m,eres); - res=printJResult(m,s1,outputs_real_format,eres); - char tmpUrl0[1024]; - const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN); - printf(jsonStr); - printf("\n"); + }else{ + free(pcaClauseFinal); + } + maps* pmsTmp=getMaps(m,"lenv"); + dumpMap(pmsTmp->content); + if(res!=NULL) + json_object_put(res); + res=printJobList(m); + } + else{ + char* tmpUrl=strstr(pcaCgiQueryString,"/jobs/"); + if(tmpUrl!=NULL && strlen(tmpUrl)>6){ + if(strncasecmp(pmCgiRequestMethod->value,"DELETE",6)==0){ + char* jobId=zStrdup(tmpUrl+6); + setMapInMaps(m,"lenv","gs_usid",jobId); + setMapInMaps(m,"lenv","file.statusFile",json_getStatusFilePath(m)); + runDismiss(m,jobId); + map* pmError=getMapFromMaps(m,"lenv","error"); + if(pmError!=NULL && strncasecmp(pmError->value,"true",4)==0){ + printExceptionReportResponseJ(m,getMapFromMaps(m,"lenv","code")); + freeMaps(&m); + free(m); + json_object_put(res); + free(jobId); + free(pcaCgiQueryString); + return 1; + } + else{ + setMapInMaps(m,"lenv","gs_location","false"); + if(res!=NULL) + json_object_put(res); + res=createStatus(m,SERVICE_DISMISSED); + } + }else{ + char* jobId=zStrdup(tmpUrl+6); + if(strlen(jobId)==36){ + if(res!=NULL) + json_object_put(res); + res=printJobStatus(m,jobId); + }else{ + // In case the service has run, then forward request to target result file + if(strlen(jobId)>36) + jobId[36]=0; + char *sid=getStatusId(m,jobId); + if(sid==NULL){ + map* error=createMap("code","NoSuchJob"); + addToMap(error,"message",_("The JobID from the request does not match any of the Jobs running on this server")); + printExceptionReportResponseJ(m,error); + free(jobId); + freeMap(&error); + free(error); + freeMaps(&m); + free(m); + json_object_put(res); + free(pcaCgiQueryString); + return 1; + }else{ + if(isRunning(m,jobId)>0){ + map* error=createMap("code","ResultNotReady"); + addToMap(error,"message",_("The job is still running.")); + printExceptionReportResponseJ(m,error); + free(jobId); + freeMap(&error); + free(error); + freeMaps(&m); + free(m); + json_object_put(res); + free(pcaCgiQueryString); return 1; + }else{ + char *Url0=getResultPath(m,jobId); + zStatStruct f_status; + int s=zStat(Url0, &f_status); + if(s==0 && f_status.st_size>0){ + if(f_status.st_size>15){ + json_object* pjoTmp=json_readFile(m,Url0); + json_object* pjoCode=NULL; + json_object* pjoMessage=NULL; + if(pjoTmp!=NULL && + json_object_object_get_ex(pjoTmp,"code",&pjoCode)!=FALSE && + json_object_object_get_ex(pjoTmp,"description",&pjoMessage)!=FALSE){ + map* error=createMap("code",json_object_get_string(pjoCode)); + addToMap(error,"message",json_object_get_string(pjoMessage)); + printExceptionReportResponseJ(m,error); + free(jobId); + freeMap(&error); + free(error); + freeMaps(&m); + free(m); + json_object_put(res); + json_object_put(pjoTmp); + free(pcaCgiQueryString); + return 1; + }else{ + + map* tmpPath = getMapFromMaps (m, "main", "tmpUrl"); + Url0=(char*) realloc(Url0,(strlen(tmpPath->value)+ + //strlen(cIdentifier->value)+ + strlen(jobId)+8)*sizeof(char)); + sprintf(Url0,"%s/%s.json",tmpPath->value,jobId); + setMapInMaps(m,"headers","Location",Url0); + } + if(pjoTmp!=NULL) + json_object_put(pjoTmp); + free(Url0); + }else{ + // Service Failed + map* statusInfo=createMap("JobID",jobId); + readFinalRes(m,jobId,statusInfo); + { + map* pmStatus=getMap(statusInfo,"status"); + if(pmStatus!=NULL) + setMapInMaps(m,"lenv","status",pmStatus->value); + } + char* tmpStr=_getStatus(m,jobId); + if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){ + char *tmpStr1=zStrdup(tmpStr); + char *tmpStr0=zStrdup(strstr(tmpStr,"|")+1); + free(tmpStr); + tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0'; + addToMap(statusInfo,"PercentCompleted",tmpStr1); + addToMap(statusInfo,"Message",tmpStr0); + setMapInMaps(m,"lenv","PercentCompleted",tmpStr1); + setMapInMaps(m,"lenv","Message",tmpStr0); + free(tmpStr0); + free(tmpStr1); + } + map* error=createMap("code","NoApplicableCode"); + addToMap(error,"message",_("The service failed to execute.")); + printExceptionReportResponseJ(m,error); + free(jobId); + freeMap(&error); + free(error); + freeMaps(&m); + free(m); + json_object_put(res); + free(pcaCgiQueryString); + return 1; + } + }else{ + map* error=createMap("code","NoSuchJob"); + addToMap(error,"message",_("The JobID seem to be running on this server but not for this process id")); + printExceptionReportResponseJ(m,error); + free(jobId); + freeMap(&error); + free(error); + freeMaps(&m); + free(m); + json_object_put(res); + free(pcaCgiQueryString); + return 1; + } } - }else{ - loadHttpRequests(m,inputs_real_format); - loadServiceAndRun (&m,s1,request_inputs,&inputs_real_format,&outputs_real_format,&eres); - res=printJResult(m,s1,outputs_real_format,eres); - createStatusFile(m,eres); - printHeaders(m); + } - if (eres==SERVICE_SUCCEEDED){ - printf("Status: 201 Created \r\n\r\n"); - }else{ - printf("Status: 500 failed \r\n\r\n"); - } - const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN); - printf(jsonStr); - printf("\n"); - return 1; } - - - }//else error - + free(jobId); + } } } + + } } - printHeaders(m); - printf("Status: 200 OK \r\n\r\n"); - const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN); - printf(jsonStr); - printf("\n"); - return 1; -#endif - } - - // - // WPS 1.0.0 and 2.0.0 starts here - // - //Check for minimum inputs - map* version=getMap(request_inputs,"version"); - if(version==NULL) - version=getMapFromMaps(m,"main","version"); - setMapInMaps(m,"main","rversion",version->value); - int vid=getVersionId(version->value); - if(vid<0) - vid=0; - map* err=NULL; - const char **vvr=(const char**)requests[vid]; - checkValidValue(request_inputs,&err,"request",vvr,1); - const char *vvs[]={ - "WPS", - NULL - }; - if(err!=NULL){ - checkValidValue(request_inputs,&err,"service",(const char**)vvs,1); - printExceptionReportResponse (m, err); - freeMap(&err); - free(err); - if (count (request_inputs) == 1) - { + else{ + service* s1=NULL; + int t=0; + if(strstr(pcaCgiQueryString,"/processes/")==NULL){ + map* error=createMap("code","BadRequest"); + addToMap(error,"message",_("The resource is not available")); + //setMapInMaps(conf,"lenv","status_code","404 Bad Request"); + printExceptionReportResponseJ(m,error); + freeMaps (&m); + free (m); + free (REQUEST); + json_object_put(res); freeMap (&request_inputs); free (request_inputs); - } - freeMaps (&m); - free (m); - return 1; - } - checkValidValue(request_inputs,&err,"service",(const char**)vvs,1); - - const char *vvv[]={ - "1.0.0", - "2.0.0", - NULL - }; - r_inputs = getMap (request_inputs, "Request"); - if(r_inputs!=NULL) - REQUEST = zStrdup (r_inputs->value); - int reqId=-1; - if (strncasecmp (REQUEST, "GetCapabilities", 15) != 0){ - checkValidValue(request_inputs,&err,"version",(const char**)vvv,1); - int j=0; - for(j=0;jvalue,"post")==0){ + /* - /processes/{processId}/execution Execution (POST) */ + eres = SERVICE_STARTED; + initAllEnvironment(m,request_inputs,ntmp,"jrequest"); + map* req=getMapFromMaps(m,"renv","jrequest"); + json_object *jobj = NULL; + const char *mystring = NULL; + int slen = 0; + enum json_tokener_error jerr; + struct json_tokener* tok=json_tokener_new(); + do { + mystring = req->value; // get JSON string, e.g. read from file, etc... + slen = strlen(mystring); + jobj = json_tokener_parse_ex(tok, mystring, slen); + } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); + if (jerr != json_tokener_success) { + map* pamError=createMap("code","InvalidParameterValue"); + const char* pcTmpErr=json_tokener_error_desc(jerr); + const char* pccErr=_("ZOO-Kernel cannot parse your POST data: %s"); + char* pacMessage=(char*)malloc((strlen(pcTmpErr)+strlen(pccErr)+1)*sizeof(char)); + sprintf(pacMessage,pccErr,pcTmpErr); + addToMap(pamError,"message",pacMessage); + printExceptionReportResponseJ(m,pamError); + fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); + json_tokener_free(tok); + return 1; } - else - if(j>=nbReqIdentifier && jchar_offset < slen){ + map* pamError=createMap("code","InvalidParameterValue"); + const char* pcTmpErr="None"; + const char* pccErr=_("ZOO-Kernel cannot parse your POST data: %s"); + char* pacMessage=(char*)malloc((strlen(pcTmpErr)+strlen(pccErr)+1)*sizeof(char)); + sprintf(pacMessage,pccErr,pcTmpErr); + addToMap(pamError,"message",pacMessage); + printExceptionReportResponseJ(m,pamError); + fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); + json_tokener_free(tok); + return 1; + } + json_tokener_free(tok); + json_object* json_io=NULL; + char* cIdentifier=NULL; + if(json_object_object_get_ex(jobj,"id",&json_io)!=FALSE){ + cIdentifier=zStrdup(json_object_get_string(json_io)); + }else{ + if(strstr(pcaCgiQueryString,"/processes/")!=NULL && strlen(pcaCgiQueryString)>11){ + cIdentifier=zStrdup(strstr(pcaCgiQueryString,"/processes/")+11); + if(strstr(cIdentifier,"execution")!=NULL) + cIdentifier[strlen(cIdentifier)-10]=0; } - }else - break; - } - }else{ - checkValidValue(request_inputs,&err,"AcceptVersions",(const char**)vvv,-1); - map* version1=getMap(request_inputs,"AcceptVersions"); - if(version1!=NULL){ - if(strstr(version1->value,schemas[1][0])!=NULL){ - addToMap(request_inputs,"version",schemas[1][0]); - setMapInMaps(m,"main","rversion",schemas[1][0]); - } - else{ - addToMap(request_inputs,"version",version1->value); - setMapInMaps(m,"main","rversion",version1->value); - } - version=getMap(request_inputs,"version"); - } - } - if(err!=NULL){ - printExceptionReportResponse (m, err); - freeMap(&err); - free(err); - if (count (request_inputs) == 1) - { - freeMap (&request_inputs); - free (request_inputs); + } + if(cIdentifier!=NULL){ + addToMap(request_inputs,"Identifier",cIdentifier); + if(strcmp(cIdentifier,"DeployProcess")==0 || strcmp(cIdentifier,"UndeployProcess")==0){ + addToMap(request_inputs,"response","document"); + setMapInMaps(m,"lenv","no-headers","true"); + setMapInMaps(m,"lenv","hasPrinted","true"); + } + } + + if(fetchService(zooRegistry,m,&s1,request_inputs,ntmp,cIdentifier,printExceptionReportResponseJ)!=0){ + // TODO: cleanup memory + register_signals(donothing); + freeMaps (&m); + free (m); + free (REQUEST); + json_object_put(res); + freeMap (inputs); + free (*inputs); + *inputs=NULL; + free(pcaCgiQueryString); + xmlCleanupParser (); + zooXmlCleanupNs (); + return 1; + } + free(cIdentifier); + parseJRequest(m,s1,jobj,request_inputs,&request_input_real_format,&request_output_real_format); + json_object_put(jobj); + map* preference=getMapFromMaps(m,"renv","HTTP_PREFER"); + map* mode=getMap(request_inputs,"mode"); + if((preference!=NULL && strstr(preference->value,"respond-async")!=NULL) || + (mode!=NULL && strncasecmp(mode->value,"async",5)==0)) { + if(mode==NULL){ + setMapInMaps(m,"request","mode","async"); + addToMap(request_inputs,"mode","async"); + mode=getMap(request_inputs,"mode"); + } + int pid; +#ifdef DEBUG + fprintf (stderr, "\nPID : %d\n", cpid); +#endif + +#ifdef USE_AMQP + + // Publish message in RabbitMQ + // m: the main configuration file + // s1: the service to execute + // request_inputs: the request as it has been parsed till now + // request_input_real_format: input maps + // request_output_real_format: output maps + + init_amqp(m); + eres = SERVICE_ACCEPTED; + json_object *msg_jobj = json_object_new_object(); + + maps* lenv=getMaps(m,"lenv"); + json_object *maps1_obj = mapToJson(lenv->content); + json_object_object_add(msg_jobj,"main_lenv",maps1_obj); + + lenv=getMaps(m,"subscriber"); + if(lenv!=NULL){ + json_object *maps1_obj = mapToJson(lenv->content); + json_object_object_add(msg_jobj,"main_subscriber",maps1_obj); } - free(REQUEST); - freeMaps (&m); - free (m); - return 1; - } - r_inputs = getMap (request_inputs, "serviceprovider"); - if (r_inputs == NULL) - { - addToMap (request_inputs, "serviceprovider", ""); - } + json_object *req_format_jobj = mapsToJson(request_input_real_format); + json_object_object_add(msg_jobj,"request_input_real_format",req_format_jobj); - maps *request_output_real_format = NULL; - map *tmpm = getMapFromMaps (m, "main", "serverAddress"); - if (tmpm != NULL) - SERVICE_URL = zStrdup (tmpm->value); - else - SERVICE_URL = zStrdup (DEFAULT_SERVICE_URL); + json_object *req_jobj = mapToJson(request_inputs); + json_object_object_add(msg_jobj,"request_inputs",req_jobj); + json_object *outputs_jobj = mapsToJson(request_output_real_format); + json_object_object_add(msg_jobj,"request_output_real_format",outputs_jobj); + bind_amqp(); + init_confirmation(); + if ( (send_msg(json_object_to_json_string_ext(msg_jobj,JSON_C_TO_STRING_PLAIN),"application/json") != 0) ){ + eres = SERVICE_FAILED; + } + close_amqp(); + json_object_put(msg_jobj); - service *s1; - int scount = 0; -#ifdef DEBUG - dumpMap (r_inputs); + +#ifdef RELY_ON_DB + init_sql(m); + recordServiceStatus(m); +#endif +#ifdef USE_CALLBACK + invokeCallback(m,NULL,NULL,0,0); #endif + eres = SERVICE_ACCEPTED; + createStatusFile(m,eres); + if(preference!=NULL) + setMapInMaps(m,"headers","Preference-Applied",preference->value); + //invokeBasicCallback(m,SERVICE_ACCEPTED); + printHeaders(m); + printf("Status: 201 Created \r\n\r\n"); + return 1; + // ----- End USE_AMQP ----- - if (strncasecmp (REQUEST, "GetCapabilities", 15) == 0) - { -#ifdef DEBUG - dumpMap (r_inputs); +#else + +#ifndef WIN32 + pid = fork (); +#else + if (cgiSid == NULL) + { + createProcess (m, request_inputs, s1, NULL, cpid, + request_input_real_format, + request_output_real_format); + pid = cpid; + } + else + { + pid = 0; + cpid = atoi (cgiSid); + updateStatus(m,0,_("Initializing")); + } #endif - xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0"); - xmlNodePtr n=printGetCapabilitiesHeader(doc,m,(version!=NULL?version->value:"1.0.0")); - /** - * Here we need to close stdout to ensure that unsupported chars - * has been found in the zcfg and then printed on stdout - */ - int saved_stdout = zDup (fileno (stdout)); - zDup2 (fileno (stderr), fileno (stdout)); + if (pid > 0) + { + // + // dady : + // set status to SERVICE_ACCEPTED + // +#ifdef DEBUG + fprintf (stderr, "father pid continue (origin %d) %d ...\n", cpid, + zGetpid ()); +#endif + eres = SERVICE_ACCEPTED; + createStatusFile(m,eres); + if(preference!=NULL) + setMapInMaps(m,"headers","Preference-Applied",preference->value); + //invokeBasicCallback(m,SERVICE_ACCEPTED); + printHeaders(m); + printf("Status: 201 Created \r\n\r\n"); + return 1; + } + else if (pid == 0) + { + eres = SERVICE_STARTED; + // + // son : have to close the stdout, stdin and stderr to let the parent + // process answer to http client. + // + map* oid = getMapFromMaps (m, "lenv", "oIdentifier"); + map* usid = getMapFromMaps (m, "lenv", "uusid"); + map* tmpm = getMapFromMaps (m, "lenv", "osid"); + int cpid = atoi (tmpm->value); + pid=cpid; + r_inputs = getMapFromMaps (m, "main", "tmpPath"); + setMapInMaps (m, "lenv", "async","true"); + map* r_inputs1 = createMap("ServiceName", s1->name); + // Create the filename for the result file (.res) + fbkpres = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value); + bmap = createMaps("status"); + bmap->content=createMap("usid",usid->value); + addToMap(bmap->content,"sid",tmpm->value); + addIntToMap(bmap->content,"pid",zGetpid()); + + // Create PID file referencing the OS process identifier + fbkpid = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value); + setMapInMaps (m, "lenv", "file.pid", fbkpid); + + f0 = freopen (fbkpid, "w+",stdout); + printf("%d",zGetpid()); + fflush(stdout); - maps* imports = getMaps(m, IMPORTSERVICE); - if (imports != NULL) { - map* zcfg = imports->content; - - while (zcfg != NULL) { - if (zcfg->value != NULL) { - service* svc = (service*) malloc(SERVICE_SIZE); - if (svc == NULL || readServiceFile(m, zcfg->value, &svc, zcfg->name) < 0) { - // pass over silently - zcfg = zcfg->next; - continue; + // Create SID file referencing the semaphore name + fbkp = + (char *) + malloc ((strlen (r_inputs->value) + strlen (oid->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value); + setMapInMaps (m, "lenv", "file.sid", fbkp); + FILE* f2 = freopen (fbkp, "w+",stdout); + printf("%s",tmpm->value); + fflush(f2); + free(fbkp); + + fbkp = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkp, "%s/%s.json", r_inputs->value, + usid->value); + setMapInMaps (m, "lenv", "file.responseInit", fbkp); + flog = + (char *) + malloc ((strlen (r_inputs->value) + strlen (oid->value) + + strlen (usid->value) + 13) * sizeof (char)); + sprintf (flog, "%s/%s_%s_error.log", r_inputs->value, + oid->value, usid->value); + setMapInMaps (m, "lenv", "file.log", flog); +#ifdef DEBUG + fprintf (stderr, "RUN IN BACKGROUND MODE \n"); + fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid, + zGetpid ()); + fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value); +#endif + freopen (flog, "w+", stderr); + fflush (stderr); + f0 = freopen (fbkp, "w+", stdout); + rewind (stdout); +#ifndef WIN32 + fclose (stdin); +#endif +#ifdef RELY_ON_DB + init_sql(m); + recordServiceStatus(m); +#endif +#ifdef USE_CALLBACK + invokeCallback(m,NULL,NULL,0,0); +#endif + invokeBasicCallback(m,SERVICE_STARTED); + createStatusFile(m,SERVICE_STARTED); + fbkp1 = + (char *) + malloc ((strlen (r_inputs->value) + strlen (oid->value) + + strlen (usid->value) + 15) * sizeof (char)); + sprintf (fbkp1, "%s/%s_final_%s.json", r_inputs->value, + oid->value, usid->value); + setMapInMaps (m, "lenv", "file.responseFinal", fbkp1); + + f1 = freopen (fbkp1, "w+", stdout); + + map* serviceTypeMap=getMap(s1->content,"serviceType"); + if(serviceTypeMap!=NULL) + setMapInMaps (m, "lenv", "serviceType", serviceTypeMap->value); + + char *flenv = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 12) * sizeof (char)); + sprintf (flenv, "%s/%s_lenv.cfg", r_inputs->value, usid->value); + maps* lenvMaps=getMaps(m,"lenv"); + dumpMapsToFile(lenvMaps,flenv,1); + free(flenv); + + map* testMap=getMapFromMaps(m,"main","memory"); + loadHttpRequests(m,request_input_real_format); + + if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,NULL)<0) + return -1; + loadServiceAndRun (&m, s1, request_inputs, + &request_input_real_format, + &request_output_real_format, &eres); + setMapInMaps(m,"lenv","force","true"); + createStatusFile(m,eres); + setMapInMaps(m,"lenv","force","false"); + setMapInMaps(m,"lenv","no-headers","true"); + fflush(stdout); + rewind(stdout); + if(res!=NULL) + json_object_put(res); + res=printJResult(m,s1,request_output_real_format,eres); + const char* jsonStr0=json_object_to_json_string_ext(res,JSON_C_TO_STRING_NOSLASHESCAPE); + if(getMapFromMaps(m,"lenv","jsonStr")==NULL) + setMapInMaps(m,"lenv","jsonStr",jsonStr0); + invokeBasicCallback(m,eres); } - inheritance(zooRegistry, &svc); - printGetCapabilitiesForProcess(zooRegistry, m, doc, n, svc); - freeService(&svc); - free(svc); +#endif + }else{ + loadHttpRequests(m,request_input_real_format); + if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,NULL)<0) + return -1; + loadServiceAndRun (&m,s1,request_inputs, + &request_input_real_format, + &request_output_real_format,&eres); + if(res!=NULL) + json_object_put(res); + res=printJResult(m,s1,request_output_real_format,eres); + } + //maps* pmsTmp=getMaps(m,"lenv"); + //dumpMap(pmsTmp->content); + map* pmTmp=getMapFromMaps(m,"lenv","Identifier"); + if(eres==SERVICE_SUCCEEDED && pmTmp!=NULL && + (strcmp(pmTmp->value,"DeployProcess")==0 || strcmp(pmTmp->value,"UndeployProcess")==0) ){ + map* pmDeployed=getMapFromMaps(m,"lenv","deployedService"); + map* pmRootUrl=getMapFromMaps(m,"openapi","rootUrl"); + if(pmDeployed!=NULL){ + char newPath[1024]; + getUserWorkspacePath(m,ntmp,newPath,1024); + char* pcaFileName=(char*)malloc((strlen(newPath)+strlen(pmDeployed->value)+7)*sizeof(char)); + sprintf(pcaFileName,"%s/%s.json",newPath,pmDeployed->value); + if(strcmp(pmTmp->value,"DeployProcess")==0){ + setMapInMaps(m,"lenv","no-headers","true"); + FILE* pfRequest=fopen(pcaFileName,"wb+"); + if(pfRequest!=NULL){ + map* pmJRequest=getMap(request_inputs,"jrequest"); + if(pmJRequest!=NULL) + fwrite(pmJRequest->value,1,strlen(pmJRequest->value),pfRequest); + fclose(pfRequest); + } + setMapInMaps(m,"lenv","requestType","GetCapabilities"); + setMapInMaps(m,"lenv","Identifier",pmDeployed->value); + setMapInMaps(m,"lenv","oIdentifier",pmDeployed->value); + json_object *res3=json_object_new_object(); + json_object *res4=json_object_new_array(); + int saved_stdout = zDup (fileno (stdout)); + int t=fetchServicesForDescription(NULL, m, pmDeployed->value, + printGetCapabilitiesForProcessJ, + (void*) res4, (void*) res3, ntmp, + request_inputs, + printExceptionReportResponseJ); + zDup2 (saved_stdout, fileno (stdout)); + zClose(saved_stdout); + json_object *res5=json_object_array_get_idx(res4,0); + const char* jsonStr=json_object_to_json_string_ext(res5,JSON_C_TO_STRING_NOSLASHESCAPE); + setMapInMaps(m,"lenv","no-headers","false"); + printHeaders(m); + printf("Location: %s/processes/%s\r\n",pmRootUrl->value,pmDeployed->value); + printf("Status: 201 Created\r\n\r\n"); + printf(jsonStr); + printf("\n"); + setMapInMaps(m,"lenv","no-headers","true"); + fflush(stdout); + json_object_put(res3); + json_object_put(res4); + json_object_put(res5); + setMapInMaps(m,"lenv","no-header","true"); + setMapInMaps(m,"lenv","hasPrinted","true"); + }else + if(pmTmp!=NULL && strcmp(pmTmp->value,"UndeployProcess")==0){ + unlink(pcaFileName); + printHeaders(m); + printf("Status: 204 OK\r\n\r\n"); + setMapInMaps(m,"lenv","hasPrinted","true"); + } + free(pcaFileName); + }else{ + handleDRUError(m); } - zcfg = zcfg->next; - } - } + }else{ + if((strcmp(pmTmp->value,"DeployProcess")==0 || strcmp(pmTmp->value,"UndeployProcess")==0) ){ + handleDRUError(m); + } + } + }//else error + else + if(strstr(pcaCgiQueryString,"/jobs")==NULL && strstr(pcaCgiQueryString,"/jobs/")==NULL){ + /* - /processes/{processId}/ */ + //DIR *dirp = opendir (ntmp); + json_object *res3=json_object_new_object(); + char *orig = NULL; + orig = zStrdup (strstr(pcaCgiQueryString,"/processes/")+11); + if(orig[strlen(orig)-1]=='/') + orig[strlen(orig)-1]=0; + setMapInMaps(m,"lenv","requestType","GetCapabilities"); + int t=fetchServicesForDescription(NULL, m, orig, + printGetCapabilitiesForProcessJ, + NULL, (void*) res3, ntmp, + request_inputs, + printExceptionReportResponseJ); + if(t==1){ + /*map* error=createMap("code","BadRequest"); + addToMap(error,"message",_("Failed to acces the requested service")); + printExceptionReportResponseJ(m,error);*/ + json_object_put(res); + json_object_put(res3); + freeMaps(&m); + free(m); + free(orig); + free(pcaCgiQueryString); + return 1; + } + res=json_object_get(res3); + free(orig); + json_object_put(res3); + }else{ + char* cIdentifier=NULL; + if(strstr(pcaCgiQueryString,"/processes/")!=NULL){ + + int len0=strlen(strstr(pcaCgiQueryString,"/processes/")+11); + int len1=strlen(pcaCgiQueryString)-strlen(strstr(pcaCgiQueryString,"/job")); + cIdentifier=(char*)malloc((len1-10)*sizeof(char)); + int cnt=0; + for(int j=11;jvalue,"false",5)==0)){ + if(getMapFromMaps(m,"lenv","no-headers")==NULL){ + printHeaders(m); + printf("Status: 200 OK \r\n\r\n"); + } + const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_NOSLASHESCAPE); + printf(jsonStr); + printf("\n"); + fflush(stdout); + } + if(res!=NULL) + json_object_put(res); + free(pcaCgiQueryString); + //return 1; +#endif + }else{ + // + // WPS 1.0.0 and 2.0.0 starts here + // + setMapInMaps(m,"main","executionType","xml"); + //Check for minimum inputs + map* version=getMap(request_inputs,"version"); + if(version==NULL) + version=getMapFromMaps(m,"main","version"); + setMapInMaps(m,"main","rversion",version->value); + int vid=getVersionId(version->value); + if(vid<0) + vid=0; + map* err=NULL; + const char **vvr=(const char**)requests[vid]; + checkValidValue(request_inputs,&err,"request",vvr,1); + const char *vvs[]={ + "WPS", + NULL + }; + if(err!=NULL){ + checkValidValue(request_inputs,&err,"service",(const char**)vvs,1); + printExceptionReportResponse (m, err); + freeMap(&err); + free(err); + if (count (request_inputs) == 1) + { + freeMap (&request_inputs); + free (request_inputs); + } freeMaps (&m); free (m); - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); + return 1; + } + checkValidValue(request_inputs,&err,"service",(const char**)vvs,1); + + const char *vvv[]={ + "1.0.0", + "2.0.0", + NULL + }; + r_inputs = getMap (request_inputs, "Request"); + if(r_inputs!=NULL) + REQUEST = zStrdup (r_inputs->value); + int reqId=-1; + if (strncasecmp (REQUEST, "GetCapabilities", 15) != 0){ + checkValidValue(request_inputs,&err,"version",(const char**)vvv,1); + int j=0; + for(j=0;j=nbReqIdentifier && jvalue,schemas[1][0])!=NULL){ + addToMap(request_inputs,"version",schemas[1][0]); + setMapInMaps(m,"main","rversion",schemas[1][0]); + } + else{ + addToMap(request_inputs,"version",version1->value); + setMapInMaps(m,"main","rversion",version1->value); + } + version=getMap(request_inputs,"version"); } - free (REQUEST); - free (SERVICE_URL); - fflush (stdout); - return 0; } - else - { - r_inputs = getMap (request_inputs, "JobId"); - if(reqId>nbReqIdentifier){ - if (strncasecmp (REQUEST, "GetStatus", 9) == 0 || - strncasecmp (REQUEST, "GetResult", 9) == 0){ - runGetStatus(m,r_inputs->value,REQUEST); -#ifdef RELY_ON_DB - map* dsNb=getMapFromMaps(m,"lenv","ds_nb"); - if(dsNb!=NULL && atoi(dsNb->value)>1) - close_sql(m,1); - close_sql(m,0); + if(err!=NULL){ + printExceptionReportResponse (m, err); + freeMap(&err); + free(err); + if (count (request_inputs) == 1) + { + freeMap (&request_inputs); + free (request_inputs); + } + free(REQUEST); + freeMaps (&m); + free (m); + return 1; + } + + r_inputs = getMap (request_inputs, "serviceprovider"); + if (r_inputs == NULL) + { + addToMap (request_inputs, "serviceprovider", ""); + } + + map *tmpm = getMapFromMaps (m, "main", "serverAddress"); + if (tmpm != NULL) + SERVICE_URL = zStrdup (tmpm->value); + else + SERVICE_URL = zStrdup (DEFAULT_SERVICE_URL); + + + int scount = 0; +#ifdef DEBUG + dumpMap (r_inputs); #endif - - freeMaps (&m); - free(m); - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); - } - free (REQUEST); - free (SERVICE_URL); - return 0; + + if (strncasecmp (REQUEST, "GetCapabilities", 15) == 0) + { +#ifdef DEBUG + dumpMap (r_inputs); +#endif + xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0"); + xmlNodePtr n=printGetCapabilitiesHeader(doc,m,(version!=NULL?version->value:"1.0.0")); + /** + * Here we need to close stdout to ensure that unsupported chars + * has been found in the zcfg and then printed on stdout + */ + int saved_stdout = zDup (fileno (stdout)); + zDup2 (fileno (stderr), fileno (stdout)); + + maps* imports = getMaps(m, IMPORTSERVICE); + if (imports != NULL) { + map* zcfg = imports->content; + + while (zcfg != NULL) { + if (zcfg->value != NULL) { + service* svc = (service*) malloc(SERVICE_SIZE); + if (svc == NULL || readServiceFile(m, zcfg->value, &svc, zcfg->name) < 0) { + // pass over silently + zcfg = zcfg->next; + continue; + } + inheritance(zooRegistry, &svc); + printGetCapabilitiesForProcess(zooRegistry, m, doc, n, svc); + freeService(&svc); + free(svc); + } + zcfg = zcfg->next; + } } - else - if (strncasecmp (REQUEST, "Dismiss", strlen(REQUEST)) == 0){ - runDismiss(m,r_inputs->value); + + if (int res = + recursReaddirF (m, zooRegistry, doc, n, conf_dir, NULL, saved_stdout, 0, + printGetCapabilitiesForProcess) < 0) + { freeMaps (&m); free (m); if(zooRegistry!=NULL){ @@ -3294,22 +4327,43 @@ runRequest (map ** inputs) } free (REQUEST); free (SERVICE_URL); - return 0; - + fflush (stdout); + return res; } + fflush (stdout); + zDup2 (saved_stdout, fileno (stdout)); +#ifdef META_DB + fetchServicesFromDb(zooRegistry,m,doc,n,printGetCapabilitiesForProcess,1); + close_sql(m,0); +#endif + printDocument (m, doc, zGetpid ()); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + fflush (stdout); return 0; } - if(reqId<=nbReqIdentifier){ - r_inputs = getMap (request_inputs, "Identifier"); - - struct dirent *dp; - DIR *dirp = opendir (conf_dir); - if (dirp == NULL) - { - errorException (m, _("The specified path does not exist."), - "InternalError", NULL); + else + { + r_inputs = getMap (request_inputs, "JobId"); + if(reqId>nbReqIdentifier){ + if (strncasecmp (REQUEST, "GetStatus", 9) == 0 || + strncasecmp (REQUEST, "GetResult", 9) == 0){ + runGetStatus(m,r_inputs->value,REQUEST); +#ifdef RELY_ON_DB + map* dsNb=getMapFromMaps(m,"lenv","ds_nb"); + if(dsNb!=NULL && atoi(dsNb->value)>1) + close_sql(m,1); + close_sql(m,0); +#endif + freeMaps (&m); - free (m); + free(m); if(zooRegistry!=NULL){ freeRegistry(&zooRegistry); free(zooRegistry); @@ -3318,650 +4372,651 @@ runRequest (map ** inputs) free (SERVICE_URL); return 0; } - if (strncasecmp (REQUEST, "DescribeProcess", 15) == 0) - { - /** - * Loop over Identifier list - */ - xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0"); - r_inputs = NULL; - r_inputs = getMap (request_inputs, "version"); + else + if (strncasecmp (REQUEST, "Dismiss", strlen(REQUEST)) == 0){ + runDismiss(m,r_inputs->value); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + return 0; + + } + return 0; + } + if(reqId<=nbReqIdentifier){ + r_inputs = getMap (request_inputs, "Identifier"); + + struct dirent *dp; + DIR *dirp = opendir (conf_dir); + if (dirp == NULL) + { + errorException (m, _("The specified path does not exist."), + "InternalError", NULL); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + return 0; + } + if (strncasecmp (REQUEST, "DescribeProcess", 15) == 0) + { + /** + * Loop over Identifier list + */ + xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0"); + r_inputs = NULL; + r_inputs = getMap (request_inputs, "version"); #ifdef DEBUG - fprintf(stderr," ** DEBUG %s %d \n",__FILE__,__LINE__); - fflush(stderr); + fprintf(stderr," ** DEBUG %s %d \n",__FILE__,__LINE__); + fflush(stderr); #endif - xmlNodePtr n = printWPSHeader(doc,m,"DescribeProcess", - root_nodes[vid][1],(version!=NULL?version->value:"1.0.0"),1); + xmlNodePtr n = printWPSHeader(doc,m,"DescribeProcess", + root_nodes[vid][1],(version!=NULL?version->value:"1.0.0"),1); - r_inputs = getMap (request_inputs, "Identifier"); + r_inputs = getMap (request_inputs, "Identifier"); - fetchServicesForDescription(zooRegistry, m, r_inputs->value, - printDescribeProcessForProcess, - (void*) doc, (void*) n, conf_dir, - request_inputs,printExceptionReportResponse); - - printDocument (m, doc, zGetpid ()); - freeMaps (&m); - free (m); - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); - } - free (REQUEST); - free (SERVICE_URL); - fflush (stdout); + int t=fetchServicesForDescription(zooRegistry, m, r_inputs->value, + printDescribeProcessForProcess, + (void*) doc, (void*) n, conf_dir, + request_inputs,printExceptionReportResponse); + if(t!=0){ + xmlFreeDoc (doc); + closedir (dirp); + free (REQUEST); + return 1; + } + printDocument (m, doc, zGetpid ()); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + fflush (stdout); + closedir (dirp); #ifdef META_DB - close_sql(m,0); - //end_sql(); + close_sql(m,0); + //end_sql(); #endif - return 0; - } - else if (strncasecmp (REQUEST, "Execute", strlen (REQUEST)) != 0) - { - map* version=getMapFromMaps(m,"main","rversion"); - int vid=getVersionId(version->value); - int len = 0; - int j = 0; - for(j=0;jvalue); + int len = 0; + int j = 0; + for(j=0;j value was not recognized. Allowed values are %s.",tmpStr); - errorException (m,_(message),"InvalidParameterValue", "request"); + char* message=(char*)malloc((61+len)*sizeof(char)); + sprintf(message,"The value was not recognized. Allowed values are %s.",tmpStr); + errorException (m,_(message),"InvalidParameterValue", "request"); #ifdef DEBUG - fprintf (stderr, "No request found %s", REQUEST); -#endif - closedir (dirp); - freeMaps (&m); - free (m); - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); + fprintf (stderr, "No request found %s", REQUEST); +#endif + closedir (dirp); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + fflush (stdout); + return 0; } - free (REQUEST); - free (SERVICE_URL); - fflush (stdout); - return 0; - } - closedir (dirp); + closedir (dirp); + } } - } - map *postRequest = NULL; - postRequest = getMap (request_inputs, "xrequest"); + map *postRequest = NULL; + postRequest = getMap (request_inputs, "xrequest"); - if(vid==1 && postRequest==NULL){ - errorException (m,_("Unable to run Execute request using the GET HTTP method"),"InvalidParameterValue", "request"); - freeMaps (&m); - free (m); - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); + if(vid==1 && postRequest==NULL){ + errorException (m,_("Unable to run Execute request using the GET HTTP method"),"InvalidParameterValue", "request"); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + fflush (stdout); + return 0; } - free (REQUEST); - free (SERVICE_URL); - fflush (stdout); - return 0; - } - s1 = NULL; - - r_inputs = getMap (request_inputs, "Identifier"); - map* import = getMapFromMaps (m, IMPORTSERVICE, r_inputs->value); - if (import != NULL && import->value != NULL) { - strncpy(tmps1, import->value, 1024); - setMapInMaps (m, "lenv", "Identifier", r_inputs->value); - setMapInMaps (m, "lenv", "oIdentifier", r_inputs->value); - } - else { + s1 = NULL; - char conf_dir2[1024*2]; - memset(conf_dir2,0,1024*2); - - strcpy(conf_dir2,conf_dir); - getUserWorkspacePath(m,conf_dir,conf_dir2,1024); - strcpy(conf_dir,conf_dir2); - -// fprintf(stderr,"rdr a8--> conf_dir %s -- %s\n", conf_dir, r_inputs->value); -// fprintf(stderr,"rdr a8--> conf_dir2 %s -- %s\n", conf_dir2, r_inputs->value); - - snprintf (tmps1, 1024, "%s/%s.zcfg", conf_dir, r_inputs->value); - -#ifdef DEBUG - fprintf (stderr, "Trying to load %s\n", tmps1); -#endif - if (strstr (r_inputs->value, ".") != NULL) - { - char *identifier = zStrdup (r_inputs->value); - parseIdentifier (m, conf_dir, identifier, tmps1); - map *tmpMap = getMapFromMaps (m, "lenv", "metapath"); - if (tmpMap != NULL) - addToMap (request_inputs, "metapath", tmpMap->value); - free (identifier); - } - else - { - setMapInMaps (m, "lenv", "Identifier", r_inputs->value); - setMapInMaps (m, "lenv", "oIdentifier", r_inputs->value); - } - } + r_inputs = getMap (request_inputs, "Identifier"); - r_inputs = getMapFromMaps (m, "lenv", "Identifier"); - -#ifdef META_DB - int metadb_id=_init_sql(m,"metadb"); - //FAILED CONNECTING DB - if(getMapFromMaps(m,"lenv","dbIssue")!=NULL || metadb_id<0){ - fprintf(stderr,"ERROR CONNECTING METADB\n"); - } - if(metadb_id>=0) - s1=extractServiceFromDb(m,r_inputs->value,0); - //close_sql(m,0); - if(s1!=NULL){ - inheritance(zooRegistry,&s1); -#ifdef USE_HPC - addNestedOutputs(&s1); -#endif - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); - } - }else /* Not found in MetaDB */{ -#endif - s1 = createService(); - if (s1 == NULL) - { - freeMaps (&m); - free (m); - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); - } - free (REQUEST); - free (SERVICE_URL); - return errorException (m, _("Unable to allocate memory"), - "InternalError", NULL); + if(fetchService(zooRegistry,m,&s1,request_inputs,ntmp,r_inputs->value,printExceptionReportResponse)!=0){ + // Service not found clear memory + freeMaps(&m); + free(m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); } - - int saved_stdout = zDup (fileno (stdout)); - zDup2 (fileno (stderr), fileno (stdout)); - t = readServiceFile (m, tmps1, &s1, r_inputs->value); - if(t>=0){ - inheritance(zooRegistry,&s1); -#ifdef USE_HPC - addNestedOutputs(&s1); -#endif - } - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); + free (REQUEST); + free (SERVICE_URL); + return -1; } - fflush (stdout); - zDup2 (saved_stdout, fileno (stdout)); - if (t < 0) - { - char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value)); - sprintf (tmpMsg, - _ - ("The value for seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."), - r_inputs->value); - errorException (m, tmpMsg, "InvalidParameterValue", "identifier"); - free (tmpMsg); - free (s1); - freeMaps (&m); - free (m); - free (REQUEST); - free (SERVICE_URL); - return 0; - } - zClose (saved_stdout); -#ifdef META_DB - } -#endif #ifdef DEBUG - dumpService (s1); + dumpService (s1); #endif - int j; + int j; - /** - * Create the input and output maps data structure - */ - int i = 0; - HINTERNET hInternet; - HINTERNET res; - hInternet = InternetOpen ( + /** + * Create the input and output maps data structure + */ + int i = 0; + HINTERNET res; + hInternet = InternetOpen ( #ifndef WIN32 - (LPCTSTR) + (LPCTSTR) #endif - "ZooWPSClient\0", - INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + "ZooWPSClient\0", + INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); #ifndef WIN32 - if (!CHECK_INET_HANDLE (hInternet)) - fprintf (stderr, "WARNING : hInternet handle failed to initialize"); + if (!CHECK_INET_HANDLE (hInternet)) + fprintf (stderr, "WARNING : hInternet handle failed to initialize"); #endif - maps *request_input_real_format = NULL; - maps *tmpmaps = request_input_real_format; - - if(parseRequest(&m,&request_inputs,s1,&request_input_real_format,&request_output_real_format,&hInternet)<0){ - freeMaps (&m); - free (m); - free (REQUEST); - free (SERVICE_URL); - InternetCloseHandle (&hInternet); - freeService (&s1); - free (s1); - return 0; - } - //InternetCloseHandle (&hInternet); + maps *tmpmaps = request_input_real_format; - initAllEnvironment(m,request_inputs,ntmp,"xrequest"); + if(parseRequest(&m,&request_inputs,s1,&request_input_real_format,&request_output_real_format,&hInternet)<0){ + freeMaps (&m); + free (m); + free (REQUEST); + free (SERVICE_URL); + InternetCloseHandle (&hInternet); + freeService (&s1); + free (s1); + return 0; + } + //InternetCloseHandle (&hInternet); + + initAllEnvironment(m,request_inputs,ntmp,"xrequest"); #ifdef DEBUG - dumpMap (request_inputs); + dumpMap (request_inputs); #endif - map *status = getMap (request_inputs, "status"); - if(vid==0){ - // Need to check if we need to fork to load a status enabled - r_inputs = NULL; - map *store = getMap (request_inputs, "storeExecuteResponse"); - /** - * 05-007r7 WPS 1.0.0 page 57 : - * 'If status="true" and storeExecuteResponse is "false" then the service - * shall raise an exception.' - */ - if (status != NULL && strcmp (status->value, "true") == 0 && - store != NULL && strcmp (store->value, "false") == 0) - { - errorException (m, - _ - ("The status parameter cannot be set to true if storeExecuteResponse is set to false. Please modify your request parameters."), - "InvalidParameterValue", "storeExecuteResponse"); - freeService (&s1); - free (s1); - freeMaps (&m); - free (m); - - freeMaps (&request_input_real_format); - free (request_input_real_format); - - freeMaps (&request_output_real_format); - free (request_output_real_format); - - free (REQUEST); - free (SERVICE_URL); - return 1; - } - r_inputs = getMap (request_inputs, "storeExecuteResponse"); - }else{ - // Define status depending on the WPS 2.0.0 mode attribute - status = getMap (request_inputs, "mode"); - map* mode=getMap(s1->content,"mode"); - if(strcasecmp(status->value,"async")==0){ - if(mode!=NULL && strcasecmp(mode->value,"async")==0) - addToMap(request_inputs,"status","true"); - else{ - if(mode!=NULL){ - // see ref. http://docs.opengeospatial.org/is/14-065/14-065.html#61 - errorException (m,_("The process does not permit the desired execution mode."),"NoSuchMode", mode->value); - fflush (stdout); + map *status = getMap (request_inputs, "status"); + if(vid==0){ + // Need to check if we need to fork to load a status enabled + r_inputs = NULL; + map *store = getMap (request_inputs, "storeExecuteResponse"); + /** + * 05-007r7 WPS 1.0.0 page 57 : + * 'If status="true" and storeExecuteResponse is "false" then the service + * shall raise an exception.' + */ + if (status != NULL && strcmp (status->value, "true") == 0 && + store != NULL && strcmp (store->value, "false") == 0) + { + errorException (m, + _ + ("The status parameter cannot be set to true if storeExecuteResponse is set to false. Please modify your request parameters."), + "InvalidParameterValue", "storeExecuteResponse"); + freeService (&s1); + free (s1); freeMaps (&m); free (m); - if(zooRegistry!=NULL){ - freeRegistry(&zooRegistry); - free(zooRegistry); - } + freeMaps (&request_input_real_format); free (request_input_real_format); + freeMaps (&request_output_real_format); free (request_output_real_format); + free (REQUEST); free (SERVICE_URL); - return 0; - }else + return 1; + } + r_inputs = getMap (request_inputs, "storeExecuteResponse"); + }else{ + // Define status depending on the WPS 2.0.0 mode attribute + status = getMap (request_inputs, "mode"); + map* mode=getMap(s1->content,"mode"); + if(strcasecmp(status->value,"async")==0){ + if(mode!=NULL && strcasecmp(mode->value,"async")==0) addToMap(request_inputs,"status","true"); - } - } - else{ - if(strcasecmp(status->value,"auto")==0){ - if(mode!=NULL){ - if(strcasecmp(mode->value,"async")==0) - addToMap(request_inputs,"status","false"); - else + else{ + if(mode!=NULL){ + // see ref. http://docs.opengeospatial.org/is/14-065/14-065.html#61 + errorException (m,_("The process does not permit the desired execution mode."),"NoSuchMode", mode->value); + fflush (stdout); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + freeMaps (&request_input_real_format); + free (request_input_real_format); + freeMaps (&request_output_real_format); + free (request_output_real_format); + free (REQUEST); + free (SERVICE_URL); + return 0; + }else addToMap(request_inputs,"status","true"); } - else - addToMap(request_inputs,"status","false"); - }else - addToMap(request_inputs,"status","false"); - } - status = getMap (request_inputs, "status"); - } - - int eres = SERVICE_STARTED; - int cpid = zGetpid (); - - maps* bmap=NULL; - char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog; - FILE *f0, *f1; - if (status != NULL) - if (strcasecmp (status->value, "false") == 0) - status = NULLMAP; - if (status == NULLMAP) - { - if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){ - freeService (&s1); - free (s1); - freeMaps (&m); - free (m); - free (REQUEST); - free (SERVICE_URL); - freeMaps (&request_input_real_format); - free (request_input_real_format); - freeMaps (&request_output_real_format); - free (request_output_real_format); - freeMaps (&tmpmaps); - free (tmpmaps); - return -1; } - map* testMap=getMapFromMaps(m,"main","memory"); - if(testMap==NULL || strcasecmp(testMap->value,"load")!=0) - dumpMapsValuesToFiles(&m,&request_input_real_format); - loadServiceAndRun (&m, s1, request_inputs, &request_input_real_format, - &request_output_real_format, &eres); + else{ + if(strcasecmp(status->value,"auto")==0){ + if(mode!=NULL){ + if(strcasecmp(mode->value,"async")==0) + addToMap(request_inputs,"status","false"); + else + addToMap(request_inputs,"status","true"); + } + else + addToMap(request_inputs,"status","false"); + }else + addToMap(request_inputs,"status","false"); + } + status = getMap (request_inputs, "status"); + } + + if (status != NULL) + if (strcasecmp (status->value, "false") == 0) + status = NULLMAP; + if (status == NULLMAP) + { + if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){ + freeService (&s1); + free (s1); + freeMaps (&m); + free (m); + free (REQUEST); + free (SERVICE_URL); + freeMaps (&request_input_real_format); + free (request_input_real_format); + freeMaps (&request_output_real_format); + free (request_output_real_format); + freeMaps (&tmpmaps); + free (tmpmaps); + return -1; + } + map* testMap=getMapFromMaps(m,"main","memory"); + if(testMap==NULL || strcasecmp(testMap->value,"load")!=0) + dumpMapsValuesToFiles(&m,&request_input_real_format); + loadServiceAndRun (&m, s1, request_inputs, &request_input_real_format, + &request_output_real_format, &eres); #ifdef META_DB - close_sql(m,0); + close_sql(m,0); #endif - } - else - { - int pid; + } + else + { + int pid; #ifdef DEBUG - fprintf (stderr, "\nPID : %d\n", cpid); + fprintf (stderr, "\nPID : %d\n", cpid); +#endif + +#ifdef USE_AMQP + + // Publish message in RabbitMQ + // m: the main configuration file + // s1: the service to execute + // request_inputs: the request as it has been parsed till now + // request_input_real_format: input maps + // request_output_real_format: output maps + + init_amqp(m); + eres = SERVICE_ACCEPTED; + json_object *msg_jobj = json_object_new_object(); + + maps* lenv=getMaps(m,"lenv"); + json_object *maps1_obj = mapToJson(lenv->content); + json_object_object_add(msg_jobj,"main_lenv",maps1_obj); + + json_object *req_format_jobj = mapsToJson(request_input_real_format); + json_object_object_add(msg_jobj,"request_input_real_format",req_format_jobj); + + json_object *req_jobj = mapToJson(request_inputs); + json_object_object_add(msg_jobj,"request_inputs",req_jobj); + + json_object *outputs_jobj = mapsToJson(request_output_real_format); + json_object_object_add(msg_jobj,"request_output_real_format",outputs_jobj); + + bind_amqp(); + init_confirmation(); + if ( (send_msg(json_object_to_json_string_ext(msg_jobj,JSON_C_TO_STRING_PLAIN),"application/json") != 0) ){ + eres = SERVICE_FAILED; + } + close_amqp(); + json_object_put(msg_jobj); + +#ifdef RELY_ON_DB + init_sql(m); + recordServiceStatus(m); #endif + eres = SERVICE_ACCEPTED; + + map* usid = getMapFromMaps (m, "lenv", "uusid"); + int saved_stdout = zDup (fileno (stdout)); + map* r_inputs1 = createMap("ServiceName", s1->name); + r_inputs = getMapFromMaps (m, "main", "tmpPath"); + fbkp = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value, + usid->value); + + f0 = freopen (fbkp, "w+", stdout); +#ifdef USE_CALLBACK + invokeCallback(m,NULL,NULL,0,0); +#endif + if(vid==0){ + // + // set status to SERVICE_STARTED and flush stdout to ensure full + // content was outputed (the file used to store the ResponseDocument). + // Then, rewind stdout to restart writing from the begining of the file. + // This way, the data will be updated at the end of the process run. + // + printProcessResponse (m, request_inputs, -1, s1, r_inputs1->value, + SERVICE_STARTED, request_input_real_format, + request_output_real_format); + fflush (stdout); + recordResponse(m,fbkp); + } + zDup2 (saved_stdout, fileno (stdout)); + +#else + #ifndef WIN32 - pid = fork (); + pid = fork (); #else - if (cgiSid == NULL) - { - createProcess (m, request_inputs, s1, NULL, cpid, - request_input_real_format, - request_output_real_format); - pid = cpid; - } - else - { - pid = 0; - cpid = atoi (cgiSid); - updateStatus(m,0,_("Initializing")); - } + if (cgiSid == NULL) + { + createProcess (m, request_inputs, s1, NULL, cpid, + request_input_real_format, + request_output_real_format); + pid = cpid; + } + else + { + pid = 0; + cpid = atoi (cgiSid); + updateStatus(m,0,_("Initializing")); + } #endif - if (pid > 0) - { - // - // dady : - // set status to SERVICE_ACCEPTED - // + if (pid > 0) + { + // + // dady : + // set status to SERVICE_ACCEPTED + // #ifdef DEBUG - fprintf (stderr, "father pid continue (origin %d) %d ...\n", cpid, - zGetpid ()); + fprintf (stderr, "father pid continue (origin %d) %d ...\n", cpid, + zGetpid ()); #endif - eres = SERVICE_ACCEPTED; - } - else if (pid == 0) - { - eres = SERVICE_ACCEPTED; - // - // son : have to close the stdout, stdin and stderr to let the parent - // process answer to http client. - // - map* usid = getMapFromMaps (m, "lenv", "uusid"); - map* tmpm = getMapFromMaps (m, "lenv", "osid"); - int cpid = atoi (tmpm->value); - pid=cpid; - r_inputs = getMapFromMaps (m, "main", "tmpPath"); - setMapInMaps (m, "lenv", "async","true"); - map* r_inputs1 = createMap("ServiceName", s1->name); - - // Create the filename for the result file (.res) - fbkpres = - (char *) - malloc ((strlen (r_inputs->value) + - strlen (usid->value) + 7) * sizeof (char)); - sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value); - bmap = createMaps("status"); - bmap->content=createMap("usid",usid->value); - addToMap(bmap->content,"sid",tmpm->value); - addIntToMap(bmap->content,"pid",zGetpid()); + eres = SERVICE_ACCEPTED; + } + else if (pid == 0) + { + eres = SERVICE_ACCEPTED; + // + // son : have to close the stdout, stdin and stderr to let the parent + // process answer to http client. + // + map* usid = getMapFromMaps (m, "lenv", "uusid"); + map* tmpm = getMapFromMaps (m, "lenv", "osid"); + int cpid = atoi (tmpm->value); + pid=cpid; + r_inputs = getMapFromMaps (m, "main", "tmpPath"); + setMapInMaps (m, "lenv", "async","true"); + map* r_inputs1 = createMap("ServiceName", s1->name); + + // Create the filename for the result file (.res) + fbkpres = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value); + bmap = createMaps("status"); + bmap->content=createMap("usid",usid->value); + addToMap(bmap->content,"sid",tmpm->value); + addIntToMap(bmap->content,"pid",zGetpid()); - // Create PID file referencing the OS process identifier - fbkpid = - (char *) - malloc ((strlen (r_inputs->value) + - strlen (usid->value) + 7) * sizeof (char)); - sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value); - setMapInMaps (m, "lenv", "file.pid", fbkpid); - - f0 = freopen (fbkpid, "w+",stdout); - printf("%d",zGetpid()); - fflush(stdout); - - // Create SID file referencing the semaphore name - fbkp = - (char *) - malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + - strlen (usid->value) + 7) * sizeof (char)); - sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value); - setMapInMaps (m, "lenv", "file.sid", fbkp); - FILE* f2 = freopen (fbkp, "w+",stdout); - printf("%s",tmpm->value); - fflush(f2); - free(fbkp); - - fbkp = - (char *) - malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + - strlen (usid->value) + 7) * sizeof (char)); - sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value, - usid->value); - setMapInMaps (m, "lenv", "file.responseInit", fbkp); - flog = - (char *) - malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + - strlen (usid->value) + 13) * sizeof (char)); - sprintf (flog, "%s/%s_%s_error.log", r_inputs->value, - r_inputs1->value, usid->value); - setMapInMaps (m, "lenv", "file.log", flog); + // Create PID file referencing the OS process identifier + fbkpid = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value); + setMapInMaps (m, "lenv", "file.pid", fbkpid); + + f0 = freopen (fbkpid, "w+",stdout); + printf("%d",zGetpid()); + fflush(stdout); + + // Create SID file referencing the semaphore name + fbkp = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value); + setMapInMaps (m, "lenv", "file.sid", fbkp); + FILE* f2 = freopen (fbkp, "w+",stdout); + printf("%s",tmpm->value); + fflush(f2); + free(fbkp); + + fbkp = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value, + usid->value); + setMapInMaps (m, "lenv", "file.responseInit", fbkp); + flog = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 13) * sizeof (char)); + sprintf (flog, "%s/%s_%s_error.log", r_inputs->value, + r_inputs1->value, usid->value); + setMapInMaps (m, "lenv", "file.log", flog); #ifdef DEBUG - fprintf (stderr, "RUN IN BACKGROUND MODE \n"); - fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid, - zGetpid ()); - fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value); -#endif - freopen (flog, "w+", stderr); - fflush (stderr); - f0 = freopen (fbkp, "w+", stdout); - rewind (stdout); + fprintf (stderr, "RUN IN BACKGROUND MODE \n"); + fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid, + zGetpid ()); + fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value); +#endif + freopen (flog, "w+", stderr); + fflush (stderr); + f0 = freopen (fbkp, "w+", stdout); + rewind (stdout); #ifndef WIN32 - fclose (stdin); + fclose (stdin); #endif #ifdef RELY_ON_DB - init_sql(m); - recordServiceStatus(m); + init_sql(m); + recordServiceStatus(m); #endif #ifdef USE_CALLBACK - invokeCallback(m,NULL,NULL,0,0); -#endif - if(vid==0){ - // - // set status to SERVICE_STARTED and flush stdout to ensure full - // content was outputed (the file used to store the ResponseDocument). - // Then, rewind stdout to restart writing from the begining of the file. - // This way, the data will be updated at the end of the process run. - // - printProcessResponse (m, request_inputs, cpid, s1, r_inputs1->value, - SERVICE_STARTED, request_input_real_format, - request_output_real_format); - fflush (stdout); + invokeCallback(m,NULL,NULL,0,0); +#endif + if(vid==0){ + // + // set status to SERVICE_STARTED and flush stdout to ensure full + // content was outputed (the file used to store the ResponseDocument). + // Then, rewind stdout to restart writing from the begining of the file. + // This way, the data will be updated at the end of the process run. + // + printProcessResponse (m, request_inputs, cpid, s1, r_inputs1->value, + SERVICE_STARTED, request_input_real_format, + request_output_real_format); + fflush (stdout); #ifdef RELY_ON_DB - recordResponse(m,fbkp); + recordResponse(m,fbkp); #endif - } - - fflush (stderr); - - fbkp1 = - (char *) - malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + - strlen (usid->value) + 13) * sizeof (char)); - sprintf (fbkp1, "%s/%s_final_%s.xml", r_inputs->value, - r_inputs1->value, usid->value); - setMapInMaps (m, "lenv", "file.responseFinal", fbkp1); - - f1 = freopen (fbkp1, "w+", stdout); + } - map* serviceTypeMap=getMap(s1->content,"serviceType"); - if(serviceTypeMap!=NULL) - setMapInMaps (m, "lenv", "serviceType", serviceTypeMap->value); + fflush (stderr); - char *flenv = - (char *) - malloc ((strlen (r_inputs->value) + - strlen (usid->value) + 12) * sizeof (char)); - sprintf (flenv, "%s/%s_lenv.cfg", r_inputs->value, usid->value); - maps* lenvMaps=getMaps(m,"lenv"); - dumpMapsToFile(lenvMaps,flenv,0); - free(flenv); + fbkp1 = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 13) * sizeof (char)); + sprintf (fbkp1, "%s/%s_final_%s.xml", r_inputs->value, + r_inputs1->value, usid->value); + setMapInMaps (m, "lenv", "file.responseFinal", fbkp1); + + f1 = freopen (fbkp1, "w+", stdout); + + map* serviceTypeMap=getMap(s1->content,"serviceType"); + if(serviceTypeMap!=NULL) + setMapInMaps (m, "lenv", "serviceType", serviceTypeMap->value); + + char *flenv = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 12) * sizeof (char)); + sprintf (flenv, "%s/%s_lenv.cfg", r_inputs->value, usid->value); + maps* lenvMaps=getMaps(m,"lenv"); + dumpMapsToFile(lenvMaps,flenv,0); + free(flenv); #ifdef USE_CALLBACK - invokeCallback(m,request_input_real_format,NULL,1,0); + invokeCallback(m,request_input_real_format,NULL,1,0); #endif - if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){ - freeService (&s1); - free (s1); - fflush (stdout); - fflush (stderr); - fclose (f0); - fclose (f1); - if(dumpBackFinalFile(m,fbkp,fbkp1)<0) - return -1; + if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){ + freeService (&s1); + free (s1); + fflush (stdout); + fflush (stderr); + fclose (f0); + fclose (f1); + if(dumpBackFinalFile(m,fbkp,fbkp1)<0) + return -1; #ifndef RELY_ON_DB - dumpMapsToFile(bmap,fbkpres,1); - removeShmLock (m, 1); + dumpMapsToFile(bmap,fbkpres,1); + removeShmLock (m, 1); #else - recordResponse(m,fbkp1); + recordResponse(m,fbkp1); #ifdef USE_CALLBACK - invokeCallback(m,NULL,NULL,7,0); + invokeCallback(m,NULL,NULL,7,0); #endif #endif - zUnlink (fbkpid); - unhandleStatus (m); + zUnlink (fbkpid); + unhandleStatus (m); #ifdef RELY_ON_DB #ifdef META_DB - cleanupCallbackThreads(); - close_sql(m,1); -#endif - close_sql(m,0); -#endif - freeMaps (&m); - free (m); - free (REQUEST); - free (SERVICE_URL); - freeMaps (&request_input_real_format); - free (request_input_real_format); - freeMaps (&request_output_real_format); - free (request_output_real_format); - freeMaps (&tmpmaps); - free (tmpmaps); - return -1; - } - if(getMapFromMaps(m,"lenv","mapError")!=NULL){ - setMapInMaps(m,"lenv","message",_("Issue with geographic data")); + cleanupCallbackThreads(); + close_sql(m,1); +#endif + close_sql(m,0); +#endif + freeMaps (&m); + free (m); + free (REQUEST); + free (SERVICE_URL); + freeMaps (&request_input_real_format); + free (request_input_real_format); + freeMaps (&request_output_real_format); + free (request_output_real_format); + freeMaps (&tmpmaps); + free (tmpmaps); + return -1; + } + if(getMapFromMaps(m,"lenv","mapError")!=NULL){ + setMapInMaps(m,"lenv","message",_("Issue with geographic data")); #ifdef USE_CALLBACK - invokeCallback(m,NULL,NULL,7,0); + invokeCallback(m,NULL,NULL,7,0); #endif - eres=-1;//SERVICE_FAILED; - }else{ - map* testMap=getMapFromMaps(m,"main","memory"); - if(testMap==NULL || strcasecmp(testMap->value,"load")!=0) - dumpMapsValuesToFiles(&m,&request_input_real_format); - loadServiceAndRun (&m, s1, request_inputs, - &request_input_real_format, - &request_output_real_format, &eres); + eres=-1;//SERVICE_FAILED; + }else{ + map* testMap=getMapFromMaps(m,"main","memory"); + if(testMap==NULL || strcasecmp(testMap->value,"load")!=0) + dumpMapsValuesToFiles(&m,&request_input_real_format); + loadServiceAndRun (&m, s1, request_inputs, + &request_input_real_format, + &request_output_real_format, &eres); + } } - } - else - { - /** - * error server don't accept the process need to output a valid - * error response here !!! - */ - eres = -1; - errorException (m, _("Unable to run the child process properly"), - "InternalError", NULL); - } - } + else + { + /** + * error server don't accept the process need to output a valid + * error response here !!! + */ + eres = -1; + errorException (m, _("Unable to run the child process properly"), + "InternalError", NULL); + } +#endif + } #ifdef DEBUG - fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__); - dumpMaps (request_output_real_format); - fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__); -#endif - fflush(stdout); - rewind(stdout); - - //fprintf(stderr,"%s %d %d\n",__FILE__,__LINE__,eres); - if (eres != -1) - outputResponse (s1, request_input_real_format, - request_output_real_format, request_inputs, - cpid, m, eres); - fflush (stdout); - + fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__); + dumpMaps (request_output_real_format); + fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__); +#endif + fflush(stdout); + rewind(stdout); + + if (eres != -1) + outputResponse (s1, request_input_real_format, + request_output_real_format, request_inputs, + cpid, m, eres); + fflush (stdout); + } /** * Ensure that if error occurs when freeing memory, no signal will return * an ExceptionReport document as the result was already returned to the * client. */ -#ifndef USE_GDB - signal (SIGSEGV, donothing); - signal (SIGTERM, donothing); - signal (SIGINT, donothing); - signal (SIGILL, donothing); - signal (SIGFPE, donothing); - signal (SIGABRT, donothing); -#endif + register_signals(donothing); if (((int) zGetpid ()) != cpid || cgiSid != NULL) { @@ -3975,6 +5030,7 @@ runRequest (map ** inputs) fclose (stdout); fclose (f0); + fclose (f1); if(dumpBackFinalFile(m,fbkp,fbkp1)<0) @@ -3996,8 +5052,8 @@ runRequest (map ** inputs) removeShmLock (m, 1); #else recordResponse(m,fbkp1); - if (eres == SERVICE_SUCCEEDED) #ifdef USE_CALLBACK + if (eres == SERVICE_SUCCEEDED) invokeCallback(m,NULL,request_output_real_format,6,0); #endif #endif @@ -4005,20 +5061,25 @@ runRequest (map ** inputs) free(bmap); zUnlink (fbkp1); unhandleStatus (m); +#if defined(USE_JSON) || defined(USE_CALLBACK) + cleanupCallbackThreads(); +#endif + #ifdef RELY_ON_DB #ifdef META_DB - cleanupCallbackThreads(); close_sql(m,1); #endif close_sql(m,0); end_sql(); #endif free(fbkpid); - free(fbkpres); + free(fbkpres); free (fbkp1); if(cgiSid!=NULL) free(cgiSid); - InternetCloseHandle (&hInternet); + map* tMap=getMapFromMaps(m,"main","executionType"); + if(tMap!=NULL && strncasecmp(tMap->value,"xml",3)==0) + InternetCloseHandle (&hInternet); fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__); fflush(stderr); fclose (stderr); @@ -4031,12 +5092,13 @@ runRequest (map ** inputs) close_sql(m,0); #endif } - - freeService (&s1); - free (s1); + + if(s1!=NULL){ + freeService (&s1); + free (s1); + } freeMaps (&m); free (m); - freeMaps (&request_input_real_format); free (request_input_real_format); @@ -4045,6 +5107,7 @@ runRequest (map ** inputs) free (REQUEST); free (SERVICE_URL); + #ifdef DEBUG fprintf (stderr, "Processed response \n"); fflush (stdout); @@ -4058,3 +5121,522 @@ runRequest (map ** inputs) return 0; } + + +#ifdef USE_AMQP +/** + * Process the request asyncrhonously. + * + * @param conf the main configuration maps + * @param lenv the lenv map + * @param inputs the request parameters map + * @return 0 on sucess, other value on failure + * @see conf_read,recursReaddirF + */ +int +runAsyncRequest (maps** iconf, map ** lenv, map ** irequest_inputs,json_object *msg_obj) +{ + register_signals(sig_handler); + maps* conf=*iconf; + map* request_inputs=*irequest_inputs; + map* dsNb=getMapFromMaps(conf,"lenv","ds_nb"); + int metadb_id=0; + //if(dsNb==NULL || strncasecmp(dsNb->value,"-1",2)==0){ +#ifdef META_DB + metadb_id=_init_sql(conf,"metadb"); +#endif + init_sql(conf); + //} + map *uusid=getMap(*lenv,"usid"); + map *schema=getMapFromMaps(conf,"database","schema"); + + char* sqlQueryTmp0="SELECT %s.checkAvailableExecutionSlot('%s','%s',%d);"; + char* sqlQuery0=(char*)malloc(((2*strlen(schema->value))+ + strlen(uusid->value)+strlen(sqlQueryTmp0)+129)*sizeof(char)); + sprintf(sqlQuery0,sqlQueryTmp0,schema->value,schema->value,uusid->value,getpid()); + OGRLayer *res=fetchSql(conf,0,sqlQuery0); + free(sqlQuery0); + if(res!=NULL){ + OGRFeature *poFeature = NULL; + const char *tmp1; + poFeature = res->GetNextFeature(); + if( poFeature != NULL ){ + while( poFeature != NULL ){ + if(atoi(poFeature->GetFieldAsString( 0 ))==0){ + fprintf(stderr,"# %d +++++++++++++++++++++++++++ %s %d \n",getpid(),__FILE__,__LINE__); + fprintf(stderr,"No need to run the async request, it has been taken by another worker!\n"); + fprintf(stderr,"# %d +++++++++++++++++++++++++++ %s %d \n",getpid(),__FILE__,__LINE__); + fflush(stderr); + }else{ + + int forkId=fork(); + if(forkId==0){ + char ntmp[1024]; +#ifndef ETC_DIR +#ifndef WIN32 + getcwd (ntmp, 1024); +#else + _getcwd (ntmp, 1024); +#endif +#else + sprintf(ntmp,"%s",ETC_DIR); +#endif + map* r_inputs = getMapOrFill (&request_inputs, "metapath", ""); + setMapInMaps(conf,"lenv","usid",uusid->value); + setMapInMaps(conf,"lenv","uusid",uusid->value); + + maps* lconf=dupMaps(iconf); + // Reset metapath + addToMap(request_inputs,"metapath",""); + setMapInMaps(lconf,"lenv","metapath",""); + maps* pmsTmp=getMaps(lconf,"lenv"); + + // Determine the executionType for this run + if(getMap(request_inputs,"jrequest")!=NULL){ + setMapInMaps(lconf,"main","executionType","json"); + initAllEnvironment(lconf,request_inputs,ntmp,"jrequest"); + register_signals(json_sig_handler); + } + else{ + setMapInMaps(lconf,"main","executionType","xml"); + initAllEnvironment(lconf,request_inputs,ntmp,"xrequest"); + } + // Update every lenv map add add them to the main conf maps lenv section + map* pmTmp0=*lenv; + while(pmTmp0!=NULL){ + setMapInMaps(lconf,"lenv",pmTmp0->name,pmTmp0->value); + pmTmp0=pmTmp0->next; + } + map* pmSubscribers; + json_object *req_subscribers; + if(json_object_object_get_ex(msg_obj,"main_subscriber",&req_subscribers)!=FALSE){ + pmSubscribers=jsonToMap(req_subscribers); + if(pmSubscribers!=NULL){ + maps* pmsaTmp=createMaps("subscriber"); + pmsaTmp->content=pmSubscribers; + addMapsToMaps(&lconf,pmsaTmp); + freeMaps(&pmsaTmp); + free(pmsaTmp); + } + } + pmsTmp=getMaps(lconf,"lenv"); +#ifdef USE_CALLBACK + invokeCallback(lconf,NULL,NULL,0,0); +#endif + invokeBasicCallback(lconf,SERVICE_STARTED); + + + // Populate the Registry + char conf_dir[1024]; + int t; + char tmps1[1024]; + r_inputs = NULL; + r_inputs = getMap (request_inputs, "metapath"); + map* cwdMap0=getMapFromMaps(lconf,"main","servicePath"); + if (r_inputs != NULL) + if(cwdMap0!=NULL) + snprintf (conf_dir, 1024, "%s/%s", cwdMap0->value, r_inputs->value); + else + snprintf (conf_dir, 1024, "%s/%s", ntmp, r_inputs->value); + else + if(cwdMap0!=NULL) + snprintf (conf_dir, 1024, "%s", cwdMap0->value); + else + snprintf (conf_dir, 1024, "%s", ntmp); + map* reg = getMapFromMaps (lconf, "main", "registry"); + registry* zooRegistry=NULL; + if(reg!=NULL){ +#ifndef WIN32 + int saved_stdout = zDup (fileno (stdout)); + zDup2 (fileno (stderr), fileno (stdout)); +#endif + if(createRegistry (lconf,&zooRegistry,reg->value)<0){ + map *message=getMapFromMaps(lconf,"lenv","message"); + map *type=getMapFromMaps(lconf,"lenv","type"); +#ifndef WIN32 + zDup2 (saved_stdout, fileno (stdout)); +#endif + return errorException (lconf, message->value, + type->value, NULL); + } +#ifndef WIN32 + zDup2 (saved_stdout, fileno (stdout)); + zClose(saved_stdout); +#endif + } + r_inputs = getMap (request_inputs, "Identifier"); + // TODO: Remove the following as we are already defining the + // Identifier from the client ZOO-Kernel sending the message + if(r_inputs==NULL){ + // JSON + map* pmTmp=request_inputs; + while(pmTmp!=NULL){ + if(strstr(pmTmp->name,"processes")!=NULL){ + char* pczTmp=strstr(pmTmp->name,"processes")+2; + pczTmp[strlen(pczTmp)-11]=0; + addToMap(request_inputs,"Identifier",pczTmp); + r_inputs = getMap (request_inputs, "Identifier"); + break; + } + pmTmp=pmTmp->next; + } + } + service *s1=NULL; + // Reset metapath + addToMap(request_inputs,"metapath",""); + setMapInMaps(lconf,"lenv","metapath",""); + if(fetchService(zooRegistry,lconf,&s1,request_inputs,ntmp,r_inputs->value,printExceptionReportResponse)!=0){ + // TODO: cleanup memory + freeMaps(&lconf); + free(lconf); + return -1; + } + + /** + * Create the input and output maps data structure + */ + int i = 0; + HINTERNET hInternet; + HINTERNET res; + hInternet = InternetOpen ( +#ifndef WIN32 + (LPCTSTR) +#endif + "ZooWPSClient\0", + INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); +#ifndef WIN32 + if (!CHECK_INET_HANDLE (hInternet)) + fprintf (stderr, "WARNING : hInternet handle failed to initialize"); +#endif + json_object *reqi_format_jobj; + maps *request_input_real_format = NULL; + json_object *reqo_format_jobj; + maps *request_output_real_format = NULL; + maps *tmpmaps = request_input_real_format; + int eres; + map* pmExecutionType=getMapFromMaps(lconf,"main","executionType"); + + if(json_object_object_get_ex(msg_obj,"request_input_real_format",&reqi_format_jobj)!=FALSE) + request_input_real_format=jsonToMaps(reqi_format_jobj); + + if(json_object_object_get_ex(msg_obj,"request_output_real_format",&reqo_format_jobj)!=FALSE) + request_output_real_format=jsonToMaps(reqo_format_jobj); + + map* version=getMap(request_inputs,"version"); + if(version==NULL) + version=getMapFromMaps(lconf,"main","version"); + if(version!=NULL) + setMapInMaps(lconf,"main","rversion",version->value); + + int vid=0; + if(version!=NULL) + vid=getVersionId(version->value); + if(vid<0) + vid=0; + + char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog; + FILE *f0, *f1; + int pid; + + dsNb=getMapFromMaps(conf,"lenv", "ds_nb"); + setMapInMaps(lconf, "lenv", "ds_nb",dsNb->value); + map* usid = getMapFromMaps (lconf, "lenv", "uusid"); + map* tmpm = getMap(*lenv, "osid"); + setMapInMaps(lconf, "lenv", "osid",tmpm->value); + tmpm = getMapFromMaps (lconf, "lenv", "osid"); + + int cpid = atoi (tmpm->value); + pid=cpid; + r_inputs = getMapFromMaps (lconf, "main", "tmpPath"); + setMapInMaps (lconf, "lenv", "async","true"); + map* r_inputs1 = createMap("ServiceName", s1->name); + + // Create the filename for the result file (.res) + fbkpres = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value); + maps* bmap = createMaps("status"); + bmap->content=createMap("usid",usid->value); + addToMap(bmap->content,"sid",tmpm->value); + addIntToMap(bmap->content,"pid",zGetpid()); + + // Create PID file referencing the OS process identifier + fbkpid = + (char *) + malloc ((strlen (r_inputs->value) + + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value); + setMapInMaps (lconf, "lenv", "file.pid", fbkpid); + + f0 = freopen (fbkpid, "w+",stdout); + printf("%d",zGetpid()); + fflush(stdout); + + // Create SID file referencing the semaphore name + fbkp = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value); + setMapInMaps (lconf, "lenv", "file.sid", fbkp); + FILE* f2 = freopen (fbkp, "w+",stdout); + printf("%s",tmpm->value); + fflush(f2); + free(fbkp); + + int iNbChars=7; + if(pmExecutionType!=NULL && strncasecmp(pmExecutionType->value,"xml",3)==0) + iNbChars=8; + fbkp = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkp, "%s/%s_%s.%s", r_inputs->value, r_inputs1->value, + usid->value, pmExecutionType->value); + setMapInMaps (lconf, "lenv", "file.responseInit", fbkp); + flog = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 13) * sizeof (char)); + sprintf (flog, "%s/%s_%s_error.log", r_inputs->value, + r_inputs1->value, usid->value); + setMapInMaps (lconf, "lenv", "file.log", flog); +#ifdef DEBUG + fprintf (stderr, "RUN IN BACKGROUND MODE \n"); + fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid, + zGetpid ()); + fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value); +#endif + freopen (flog, "w+", stderr); + fflush (stderr); + f0 = freopen (fbkp, "w+", stdout); + rewind (stdout); +#ifndef WIN32 + fclose (stdin); +#endif +#ifdef USE_CALLBACK + invokeCallback(lconf,NULL,NULL,0,0); +#endif + if(vid==0 && (pmExecutionType!=NULL && strncasecmp(pmExecutionType->value,"xml",3)==0)){ + // + // set status to SERVICE_STARTED and flush stdout to ensure full + // content was outputed (the file used to store the ResponseDocument). + // Then, rewind stdout to restart writing from the begining of the file. + // This way, the data will be updated at the end of the process run. + // + printProcessResponse (lconf, request_inputs, cpid, s1, r_inputs1->value, + SERVICE_STARTED, request_input_real_format, + request_output_real_format); + fflush (stdout); +#ifdef RELY_ON_DB + recordResponse(lconf,fbkp); +#endif + } + + fflush (stderr); + + // Set Headers from lenv coming form the message + // TODO: append current headers by fetching the renv from the + // message? + map* pmCursor=*lenv; + while(pmCursor!=NULL){ + if(strncasecmp(pmCursor->name,"rb_headers_",11)==0){ + setMapInMaps(lconf,"lenv",pmCursor->name,pmCursor->value); + } + pmCursor=pmCursor->next; + } + // Add the request section in the main conf maps + pmCursor=*irequest_inputs; + while(pmCursor!=NULL){ + setMapInMaps(lconf,"request",pmCursor->name,pmCursor->value); + pmCursor=pmCursor->next; + } + + parseInputHttpRequests(lconf,request_input_real_format,&hInternet); + + fbkp1 = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 13) * sizeof (char)); + sprintf (fbkp1, "%s/%s_final_%s.%s", r_inputs->value, + r_inputs1->value, usid->value, pmExecutionType->value); + setMapInMaps (lconf, "lenv", "file.responseFinal", fbkp1); + + f1 = freopen (fbkp1, "w+", stdout); + + map* serviceTypeMap=getMap(s1->content,"serviceType"); + if(serviceTypeMap!=NULL) + setMapInMaps (lconf, "lenv", "serviceType", serviceTypeMap->value); + + char *flenv = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 12) * sizeof (char)); + sprintf (flenv, "%s/%s_lenv.cfg", r_inputs->value, usid->value); + maps* lenvMaps=getMaps(lconf,"lenv"); + dumpMapsToFile(lenvMaps,flenv,1); + free(flenv); +#ifdef USE_CALLBACK + invokeCallback(lconf,request_input_real_format,NULL,1,0); +#endif + if(validateRequest(&lconf,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){ + freeService (&s1); + free (s1); + fflush (stdout); + fflush (stderr); + fclose (f0); + fclose (f1); + if(dumpBackFinalFile(lconf,fbkp,fbkp1)<0) + return -1; +#ifndef RELY_ON_DB + dumpMapsToFile(bmap,fbkpres,1); + removeShmLock (lconf, 1); +#else + recordResponse(lconf,fbkp1); +#ifdef USE_CALLBACK + invokeCallback(lconf,NULL,NULL,7,0); +#endif +#endif + zUnlink (fbkpid); + unhandleStatus (conf); +#ifdef RELY_ON_DB +#ifdef META_DB + cleanupCallbackThreads(); + close_sql(lconf,1); +#endif + close_sql(lconf,0); +#endif + freeMaps (&request_input_real_format); + free (request_input_real_format); + freeMaps (&request_output_real_format); + free (request_output_real_format); + freeMaps (&tmpmaps); + free (tmpmaps); + return -1; + } + if(getMapFromMaps(lconf,"lenv","mapError")!=NULL){ + setMapInMaps(lconf,"lenv","message",_("Issue with geographic data")); +#ifdef USE_CALLBACK + invokeCallback(lconf,NULL,NULL,7,0); +#endif + eres=-1;//SERVICE_FAILED; + }else{ + map* testMap=getMapFromMaps(lconf,"main","memory"); + if(testMap==NULL || strcasecmp(testMap->value,"load")!=0) + dumpMapsValuesToFiles(&lconf,&request_input_real_format); + loadServiceAndRun (&lconf, s1, request_inputs, + &request_input_real_format, + &request_output_real_format, &eres); + } + pmExecutionType=getMapFromMaps(lconf,"main","executionType"); + if (eres != -1){ + if(pmExecutionType!=NULL && strncasecmp(pmExecutionType->value,"xml",3)==0) + outputResponse (s1, request_input_real_format, + request_output_real_format, request_inputs, + cpid, lconf, eres); + else{ + setMapInMaps(lconf,"lenv","force","true"); + createStatusFile(lconf,eres); + setMapInMaps(lconf,"lenv","force","false"); + setMapInMaps(lconf,"lenv","no-headers","true"); + fflush(stdout); + rewind(stdout); + json_object* res=printJResult(lconf,s1,request_output_real_format,eres); + const char* jsonStr0=json_object_to_json_string_ext(res,JSON_C_TO_STRING_NOSLASHESCAPE); + if(getMapFromMaps(lconf,"lenv","jsonStr")==NULL) + setMapInMaps(lconf,"lenv","jsonStr",jsonStr0); + invokeBasicCallback(lconf,eres); + map* pmHasPrinted=getMapFromMaps(lconf,"lenv","hasPrinted"); + if(res!=NULL && (pmHasPrinted==NULL || strncasecmp(pmHasPrinted->value,"false",5)==0)){ + if(getMapFromMaps(lconf,"lenv","no-headers")==NULL){ + printHeaders(lconf); + printf("Status: 200 OK \r\n\r\n"); + } + const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_NOSLASHESCAPE); + printf(jsonStr); + printf("\n"); + fflush(stdout); + } + if(res!=NULL) + json_object_put(res); + } + } + fflush (stdout); + + fflush(stderr); + + fclose (stdout); + + fclose (f0); + fclose (f1); + + if(dumpBackFinalFile(lconf,fbkp,fbkp1)<0) + return -1; + zUnlink (fbkpid); + switch(eres){ + default: + case SERVICE_FAILED: + setMapInMaps(bmap,"status","status",wpsStatus[1]); + setMapInMaps(lconf,"lenv","fstate",wpsStatus[1]); + break; + case SERVICE_SUCCEEDED: + setMapInMaps(bmap,"status","status",wpsStatus[0]); + setMapInMaps(lconf,"lenv","fstate",wpsStatus[0]); + break; + } +#ifndef RELY_ON_DB + dumpMapsToFile(bmap,fbkpres,1); + removeShmLock (lconf, 1); +#else + recordResponse(lconf,fbkp1); +#ifdef USE_CALLBACK + if (eres == SERVICE_SUCCEEDED) + invokeCallback(lconf,NULL,request_output_real_format,6,0); +#endif +#endif + freeMaps(&bmap); + free(bmap); + zUnlink (fbkp1); + unhandleStatus (lconf); + //zSleep(100000); + fprintf(stderr,"# %d +++++++++++++++++++++++++++ %s %d \n",getpid(),__FILE__,__LINE__); + fprintf(stderr,"This worker can now exit!\n"); + fprintf(stderr,"# %d +++++++++++++++++++++++++++ %s %d \n",getpid(),__FILE__,__LINE__); + char* sqlQuery2=(char*)malloc(((strlen(schema->value))+ + strlen(uusid->value)+36)*sizeof(char)); + sprintf(sqlQuery2,"DELETE FROM %s.workers WHERE uuid='%s'",schema->value,uusid->value); + OGRLayer *res2=fetchSql(lconf,0,sqlQuery2); + free(sqlQuery2); + freeMaps(&lconf); + free(lconf); + }else{ + if(forkId<0){ + fprintf(stderr,"# %d +++++++++++++++++++++++++++ %s %d \n",getpid(),__FILE__,__LINE__); + fprintf(stderr,_("Unable to create a new process, please try later!\n")); + fprintf(stderr,"# %d +++++++++++++++++++++++++++ %s %d \n",getpid(),__FILE__,__LINE__); + fflush(stderr); + }else + wait(0); + } + } + poFeature = res->GetNextFeature(); + } + } + cleanFetchSql(conf,0,res); + }else{ + fprintf(stderr,"Concurrent access on the workers table imply that there is no need to take this request into account!\n"); + fflush(stderr); + } + fflush(stderr); +#ifdef META_DB + close_sql(conf,1); +#endif + close_sql(conf,0); + setMapInMaps(conf,"lenv","ds_nb","-1"); + //end_sql(); + return 0; +} +#endif diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/build.sh b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/build.sh new file mode 100644 index 00000000..51ecb62b --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/build.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +#cd /opt/zoo-project/zoo-project/zoo-kernel && cp /work/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/build.sh /opt/zoo-project/zoo-project/zoo-kernel/c && chmod +x c +cp /work/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/zoo_service_loader.c . +cp /work/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_json.c . +cp /work/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/response_print.c . +make && make install && cp zoo_loader.cgi /var/www/zoo-bin/zoo_loader.cgi \ No newline at end of file diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/response_print.c b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/response_print.c new file mode 100644 index 00000000..5e8926d7 --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/response_print.c @@ -0,0 +1,3294 @@ +/* + * Author : Gérald FENOY + * + * Copyright (c) 2009-2015 GeoLabs SARL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef USE_MS +#include "service_internal_ms.h" +#else +#include "cpl_vsi.h" +#endif +#ifdef USE_CALLBACK +#include "service_callback.h" +#endif +#include "service.h" +#include "service_internal.h" +#include "server_internal.h" +#include "response_print.h" + +#ifndef WIN32 +#include +#endif + +#include "mimetypes.h" + +/** + * Add prefix to the service name. + * + * @param conf the conf maps containing the main.cfg settings + * @param level the map containing the level information + * @param serv the service structure created from the zcfg file + */ +void addPrefix(maps* conf,map* level,service* serv){ + if(level!=NULL){ + char key[25]; + char* prefix=NULL; + int clevel=atoi(level->value); + int cl=0; + for(cl=0;clvalue); + else{ + int plen=strlen(prefix); + prefix=(char*)realloc(prefix,(plen+strlen(tmp2->value)+2)*sizeof(char)); + memcpy(prefix+plen,tmp2->value,strlen(tmp2->value)*sizeof(char)); + prefix[plen+strlen(tmp2->value)]=0; + } + } + } + if(prefix!=NULL){ + char* tmp0=zStrdup(serv->name); + free(serv->name); + serv->name=(char*)malloc((strlen(prefix)+strlen(tmp0)+1)*sizeof(char)); + sprintf(serv->name,"%s%s",prefix,tmp0); + free(tmp0); + free(prefix); + prefix=NULL; + } + } +} + +/** + * Print the HTTP headers based on a map. + * + * @param m the map containing the headers information + */ +void printHeaders(maps* m){ + maps *_tmp=getMaps(m,"headers"); + if(_tmp!=NULL){ + map* _tmp1=_tmp->content; + while(_tmp1!=NULL){ + printf("%s: %s\r\n",_tmp1->name,_tmp1->value); + _tmp1=_tmp1->next; + } + } +} + +/** + * Add a land attribute to a XML node + * + * @param n the XML node to add the attribute + * @param m the map containing the language key to add as xml:lang + */ +void addLangAttr(xmlNodePtr n,maps *m){ + map *tmpLmap=getMapFromMaps(m,"main","language"); + if(tmpLmap!=NULL) + xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST tmpLmap->value); + else + xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST "en-US"); +} + +/** + * Replace the first letter by its upper case version in a new char array + * + * @param tmp the char* + * @return a new char* with first letter in upper case + * @warning be sure to free() the returned string after use + */ +char *zCapitalize1(char *tmp){ + char *res=zStrdup(tmp); + if(res[0]>=97 && res[0]<=122) + res[0]-=32; + return res; +} + +/** + * Replace all letters by their upper case version in a new char array + * + * @param tmp the char* + * @return a new char* with first letter in upper case + * @warning be sure to free() the returned string after use + */ +char *zCapitalize(char *tmp){ + int i=0; + char *res=zStrdup(tmp); + for(i=0;i=97 && res[i]<=122) + res[i]-=32; + return res; +} + +/** + * Search for an existing XML namespace in usedNS. + * + * @param name the name of the XML namespace to search + * @return the index of the XML namespace found or -1 if not found. + */ +int zooXmlSearchForNs(const char* name){ + int i; + int res=-1; + for(i=0;i=0;j--){ +#ifdef DEBUG + fprintf(stderr,"zooXmlCleanup %d\n",j); +#endif + if(j==0) + xmlFreeNs(usedNs[j]); + free(nsName[j]); + nbNs--; + } + nbNs=0; +} + +/** + * Add a XML document to the iDocs. + * + * @param value the string containing the XML document + * @return the index of the XML document added. + */ +int zooXmlAddDoc(const char* value){ + int currId=0; + nbDocs++; + currId=nbDocs-1; + iDocs[currId]=xmlParseMemory(value,strlen(value)); + return currId; +} + +/** + * Free allocated memort to store XML documents + */ +void zooXmlCleanupDocs(){ + int j; + for(j=nbDocs-1;j>=0;j--){ + xmlFreeDoc(iDocs[j]); + } + nbDocs=0; +} + +/** + * Generate a SOAP Envelope node when required (if the isSoap key of the [main] + * section is set to true). + * + * @param conf the conf maps containing the main.cfg settings + * @param n the node used as children of the generated soap:Envelope + * @return the generated soap:Envelope (if isSoap=true) or the input node n + * (when isSoap=false) + */ +xmlNodePtr soapEnvelope(maps* conf,xmlNodePtr n){ + map* soap=getMapFromMaps(conf,"main","isSoap"); + if(soap!=NULL && strcasecmp(soap->value,"true")==0){ + int lNbNs=nbNs; + nsName[lNbNs]=zStrdup("soap"); + usedNs[lNbNs]=xmlNewNs(NULL,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap"); + nbNs++; + xmlNodePtr nr = xmlNewNode(usedNs[lNbNs], BAD_CAST "Envelope"); + nsName[nbNs]=zStrdup("soap"); + usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap"); + nbNs++; + nsName[nbNs]=zStrdup("xsi"); + usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi"); + nbNs++; + xmlNsPtr ns_xsi=usedNs[nbNs-1]; + xmlNewNsProp(nr,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.w3.org/2003/05/soap-envelope http://www.w3.org/2003/05/soap-envelope"); + xmlNodePtr nr1 = xmlNewNode(usedNs[lNbNs], BAD_CAST "Body"); + xmlAddChild(nr1,n); + xmlAddChild(nr,nr1); + return nr; + }else + return n; +} + +/** + * Generate a WPS header. + * + * @param doc the document to add the header + * @param m the conf maps containing the main.cfg settings + * @param req the request type (GetCapabilities,DescribeProcess,Execute) + * @param rname the root node name + * @return the generated wps:rname xmlNodePtr (can be wps: Capabilities, + * wps:ProcessDescriptions,wps:ExecuteResponse) + */ +xmlNodePtr printWPSHeader(xmlDocPtr doc,maps* m,const char* req,const char* rname,const char* version,int reqId){ + + xmlNsPtr ns,ns_xsi; + xmlNodePtr n; + + int vid=getVersionId(version); + + int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps"); + ns=usedNs[wpsId]; + n = xmlNewNode(ns, BAD_CAST rname); + zooXmlAddNs(n,schemas[vid][1],"ows"); + xmlNewNs(n,BAD_CAST schemas[vid][2],BAD_CAST "wps"); + zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink"); + int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi"); + ns_xsi=usedNs[xsiId]; + char *tmp=(char*) malloc((86+strlen(req)+1)*sizeof(char)); + sprintf(tmp,schemas[vid][4],schemas[vid][2],schemas[vid][3],req); + xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST tmp); + free(tmp); + if(vid==0 || reqId==0){ + xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS"); + xmlNewProp(n,BAD_CAST "version",BAD_CAST schemas[vid][0]); + } + if(vid==0) + addLangAttr(n,m); + xmlNodePtr fn=soapEnvelope(m,n); + xmlDocSetRootElement(doc, fn); + return n; +} + +void addLanguageNodes(maps* conf,xmlNodePtr n,xmlNsPtr ns,xmlNsPtr ns_ows){ + xmlNodePtr nc1,nc2,nc3,nc4; + map* version=getMapFromMaps(conf,"main","rversion"); + int vid=getVersionId(version->value); + if(vid==1) + nc1 = xmlNewNode(ns_ows, BAD_CAST "Languages"); + else{ + nc1 = xmlNewNode(ns, BAD_CAST "Languages"); + nc2 = xmlNewNode(ns, BAD_CAST "Default"); + nc3 = xmlNewNode(ns, BAD_CAST "Supported"); + } + + maps* tmp=getMaps(conf,"main"); + if(tmp!=NULL){ + map* tmp1=getMap(tmp->content,"lang"); + char *toto=tmp1->value; + char buff[256]; + int i=0; + int j=0; + int dcount=0; + while(toto[i]){ + if(toto[i]!=',' && toto[i]!=0){ + buff[j]=toto[i]; + buff[j+1]=0; + j++; + } + else{ + if(dcount==0){ + if(vid==0){ + nc4 = xmlNewNode(ns_ows, BAD_CAST "Language"); + xmlAddChild(nc4,xmlNewText(BAD_CAST buff)); + xmlAddChild(nc2,nc4); + xmlAddChild(nc1,nc2); + } + dcount++; + } + nc4 = xmlNewNode(ns_ows, BAD_CAST "Language"); + xmlAddChild(nc4,xmlNewText(BAD_CAST buff)); + if(vid==0) + xmlAddChild(nc3,nc4); + else + xmlAddChild(nc1,nc4); + j=0; + buff[j]=0; + } + i++; + } + if(strlen(buff)>0){ + nc4 = xmlNewNode(ns_ows, BAD_CAST "Language"); + xmlAddChild(nc4,xmlNewText(BAD_CAST buff)); + if(vid==0) + xmlAddChild(nc3,nc4); + else + xmlAddChild(nc1,nc4); + } + } + if(vid==0) + xmlAddChild(nc1,nc3); + xmlAddChild(n,nc1); +} + +/** + * Generate a Capabilities header. + * + * @param doc the document to add the header + * @param m the conf maps containing the main.cfg settings + * @return the generated wps:ProcessOfferings xmlNodePtr + */ +xmlNodePtr printGetCapabilitiesHeader(xmlDocPtr doc,maps* m,const char* version="1.0.0"){ + + xmlNsPtr ns,ns_ows,ns_xlink; + xmlNodePtr n,nc,nc1,nc2,nc3,nc4,nc5,nc6; + n = printWPSHeader(doc,m,"GetCapabilities","Capabilities",version,0); + maps* toto1=getMaps(m,"main"); + char tmp[256]; + map* v=getMapFromMaps(m,"main","rversion"); + int vid=getVersionId(v->value); + + int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps"); + ns=usedNs[wpsId]; + int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink"); + ns_xlink=usedNs[xlinkId]; + int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows"); + ns_ows=usedNs[owsId]; + + nc = xmlNewNode(ns_ows, BAD_CAST "ServiceIdentification"); + maps* tmp4=getMaps(m,"identification"); + if(tmp4!=NULL){ + map* tmp2=tmp4->content; + const char *orderedFields[5]; + orderedFields[0]="Title"; + orderedFields[1]="Abstract"; + orderedFields[2]="Keywords"; + orderedFields[3]="Fees"; + orderedFields[4]="AccessConstraints"; + int oI=0; + for(oI=0;oI<5;oI++) + if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){ + if(strcasecmp(tmp2->name,"abstract")==0 || + strcasecmp(tmp2->name,"title")==0 || + strcasecmp(tmp2->name,"accessConstraints")==0 || + strcasecmp(tmp2->name,"fees")==0){ + tmp2->name[0]=toupper(tmp2->name[0]); + nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name); + xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value)); + xmlAddChild(nc,nc1); + } + else + if(strcmp(tmp2->name,"keywords")==0){ + nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords"); + char *toto=tmp2->value; + char buff[256]; + int i=0; + int j=0; + while(toto[i]){ + if(toto[i]!=',' && toto[i]!=0){ + buff[j]=toto[i]; + buff[j+1]=0; + j++; + } + else{ + nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword"); + xmlAddChild(nc2,xmlNewText(BAD_CAST buff)); + xmlAddChild(nc1,nc2); + j=0; + } + i++; + } + if(strlen(buff)>0){ + nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword"); + xmlAddChild(nc2,xmlNewText(BAD_CAST buff)); + xmlAddChild(nc1,nc2); + } + xmlAddChild(nc,nc1); + nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceType"); + xmlAddChild(nc2,xmlNewText(BAD_CAST "WPS")); + xmlAddChild(nc,nc2); + nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceTypeVersion"); + map* tmpv=getMapFromMaps(m,"main","rversion"); + xmlAddChild(nc2,xmlNewText(BAD_CAST tmpv->value)); + xmlAddChild(nc,nc2); + } + tmp2=tmp2->next; + } + } + else{ + fprintf(stderr,"TMP4 NOT FOUND !!"); + return NULL; + } + xmlAddChild(n,nc); + + nc = xmlNewNode(ns_ows, BAD_CAST "ServiceProvider"); + nc3 = xmlNewNode(ns_ows, BAD_CAST "ServiceContact"); + nc4 = xmlNewNode(ns_ows, BAD_CAST "ContactInfo"); + nc5 = xmlNewNode(ns_ows, BAD_CAST "Phone"); + nc6 = xmlNewNode(ns_ows, BAD_CAST "Address"); + tmp4=getMaps(m,"provider"); + if(tmp4!=NULL){ + map* tmp2=tmp4->content; + const char *tmpAddress[6]; + tmpAddress[0]="addressDeliveryPoint"; + tmpAddress[1]="addressCity"; + tmpAddress[2]="addressAdministrativeArea"; + tmpAddress[3]="addressPostalCode"; + tmpAddress[4]="addressCountry"; + tmpAddress[5]="addressElectronicMailAddress"; + const char *tmpPhone[2]; + tmpPhone[0]="phoneVoice"; + tmpPhone[1]="phoneFacsimile"; + const char *orderedFields[12]; + orderedFields[0]="providerName"; + orderedFields[1]="providerSite"; + orderedFields[2]="individualName"; + orderedFields[3]="positionName"; + orderedFields[4]=tmpPhone[0]; + orderedFields[5]=tmpPhone[1]; + orderedFields[6]=tmpAddress[0]; + orderedFields[7]=tmpAddress[1]; + orderedFields[8]=tmpAddress[2]; + orderedFields[9]=tmpAddress[3]; + orderedFields[10]=tmpAddress[4]; + orderedFields[11]=tmpAddress[5]; + int oI=0; + for(oI=0;oI<12;oI++) + if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){ + if(strcmp(tmp2->name,"keywords")!=0 && + strcmp(tmp2->name,"serverAddress")!=0 && + strcmp(tmp2->name,"lang")!=0){ + tmp2->name[0]=toupper(tmp2->name[0]); + if(strcmp(tmp2->name,"ProviderName")==0){ + nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name); + xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value)); + xmlAddChild(nc,nc1); + } + else{ + if(strcmp(tmp2->name,"ProviderSite")==0){ + nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name); + xmlNewNsProp(nc1,ns_xlink,BAD_CAST "href",BAD_CAST tmp2->value); + xmlAddChild(nc,nc1); + } + else + if(strcmp(tmp2->name,"IndividualName")==0 || + strcmp(tmp2->name,"PositionName")==0){ + nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name); + xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value)); + xmlAddChild(nc3,nc1); + } + else + if(strncmp(tmp2->name,"Phone",5)==0){ + int j; + for(j=0;j<2;j++) + if(strcasecmp(tmp2->name,tmpPhone[j])==0){ + char *tmp4=tmp2->name; + nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+5); + xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value)); + xmlAddChild(nc5,nc1); + } + } + else + if(strncmp(tmp2->name,"Address",7)==0){ + int j; + for(j=0;j<6;j++) + if(strcasecmp(tmp2->name,tmpAddress[j])==0){ + char *tmp4=tmp2->name; + nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+7); + xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value)); + xmlAddChild(nc6,nc1); + } + } + } + } + else + if(strcmp(tmp2->name,"keywords")==0){ + nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords"); + char *toto=tmp2->value; + char buff[256]; + int i=0; + int j=0; + while(toto[i]){ + if(toto[i]!=',' && toto[i]!=0){ + buff[j]=toto[i]; + buff[j+1]=0; + j++; + } + else{ + nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword"); + xmlAddChild(nc2,xmlNewText(BAD_CAST buff)); + xmlAddChild(nc1,nc2); + j=0; + } + i++; + } + if(strlen(buff)>0){ + nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword"); + xmlAddChild(nc2,xmlNewText(BAD_CAST buff)); + xmlAddChild(nc1,nc2); + } + xmlAddChild(nc,nc1); + } + tmp2=tmp2->next; + } + } + else{ + fprintf(stderr,"TMP4 NOT FOUND !!"); + } + xmlAddChild(nc4,nc5); + xmlAddChild(nc4,nc6); + xmlAddChild(nc3,nc4); + xmlAddChild(nc,nc3); + xmlAddChild(n,nc); + + + nc = xmlNewNode(ns_ows, BAD_CAST "OperationsMetadata"); + + int j=0; + + if(toto1!=NULL){ + map* tmp=getMap(toto1->content,"serverAddress"); + if(tmp!=NULL){ + SERVICE_URL = zStrdup(tmp->value); + } + else + SERVICE_URL = zStrdup("not_defined"); + } + else + SERVICE_URL = zStrdup("not_defined"); + + for(j=0;jvalue); + // Initialize or get existing namespaces + int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps"); + ns=usedNs[wpsId]; + int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows"); + ns_ows=usedNs[owsId]; + int xmlId=zooXmlAddNs(NULL,"http://www.w3.org/XML/1998/namespace","xml"); + ns_xml=usedNs[xmlId]; + int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink"); + ns_xlink=usedNs[xlinkId]; + map* tmp1; + if(serv->content!=NULL){ + nc1 = xmlNewNode(ns, BAD_CAST capabilities[vid][0]); + int i=1; + int limit=3; + if(vid==1){ + ns=NULL; + limit=7; + } + nc3=NULL; + map* sType=getMap(serv->content,"serviceType"); + for(;icontent,capabilities[vid][i]); + if(tmp1!=NULL){ + if(vid==1 && i==1 && strlen(tmp1->value)<5){ + char *val=(char*)malloc((strlen(tmp1->value)+5)*sizeof(char)); + sprintf(val,"%s.0.0",tmp1->value); + xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST val); + free(val); + } + else + xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST tmp1->value); + } + else{ + if(i==3 && vid==1 && sType!=NULL && strstr(sType->value,"HPC")!=NULL) + xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST "async-execute dismiss"); + else + xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST capabilities[vid][i+1]); + } + } + } + map* tmp3=getMapFromMaps(m,"lenv","level"); + addPrefix(m,tmp3,serv); + printDescription(nc1,ns_ows,serv->name,serv->content,vid); + tmp1=serv->metadata; + + addMetadata(tmp1,doc,nc1,ns_ows,ns_xlink,vid); + tmp1=serv->additional_parameters; + int fromDb=-1; + map* test=getMap(serv->content,"fromDb"); + if(test!=NULL && strncasecmp(test->value,"true",4)==0) + fromDb=1; + addAdditionalParameters(tmp1,doc,nc1,ns_ows,ns_xlink,fromDb); + + if(nc3!=NULL) + xmlAddChild(nc1,nc3); + xmlAddChild(nc,nc1); + } + +} + +/** + * Attach attributes to a ProcessDescription or a ProcessOffering node. + * + * @param n the XML node to attach the attributes to + * @param ns the XML namespace to create the attributes + * @param content the servive main content created from the zcfg file + * @param vid the version identifier (0 for 1.0.0 and 1 for 2.0.0) + * @param serviceType string containing the current service type + */ +void attachAttributes(xmlNodePtr n,xmlNsPtr ns,map* content,int vid,map* serviceType){ + int limit=7; + for(int i=1;ivalue)<5){ + char *val=(char*)malloc((strlen(tmp1->value)+5)*sizeof(char)); + sprintf(val,"%s.0.0",tmp1->value); + xmlNewNsProp(n,ns,BAD_CAST capabilities[vid][i],BAD_CAST val); + free(val); + } + else{ + if(vid==0 && i>=2) + xmlNewProp(n,BAD_CAST capabilities[vid][i],BAD_CAST tmp1->value); + else + xmlNewNsProp(n,ns,BAD_CAST capabilities[vid][i],BAD_CAST tmp1->value); + } + } + else{ + if(i==3 && vid==1 && serviceType!=NULL && strstr(serviceType->value,"HPC")!=NULL) + xmlNewNsProp(n,ns,BAD_CAST capabilities[vid][i],BAD_CAST "async-execute dismiss"); + else + if(vid==0 && i>=2) + xmlNewProp(n,BAD_CAST capabilities[vid][i],BAD_CAST capabilities[vid][i+1]); + else + xmlNewNsProp(n,ns,BAD_CAST capabilities[vid][i],BAD_CAST capabilities[vid][i+1]); + } + } +} + +/** + * Add a Metadata node to any existing node. + * @param meta the map defining the additional parameters + * @param doc the XML document used + * @param nb the node to add the additional parameters + * @param ns_ows the OWS namespace + * @param ns_xlink the xlink namespace + * @param vid the version of WPS to use (0 for 1.0.0 and 1 for 2.0) + */ +void addMetadata(map* meta,xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,int vid){ + int hasTitle=-1; + int hasValue=-1; + xmlNodePtr nc1; + map* oMeta=meta; + int isAdditionalParameters=-1; + int level=0; + map* test=getMap(meta,"title"); + if(test!=NULL) + level+=1; + test=getMap(meta,"href"); + if(test!=NULL) + level+=1; + test=getMap(meta,"role"); + if(test!=NULL) + level+=1; + if(count(oMeta)>level+1) + isAdditionalParameters=1; + char *ctitle=NULL; + while(meta!=NULL){ + if(hasTitle<0) + if(isAdditionalParameters<0) + nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata"); + else + if(hasValue<0) + nc1 = xmlNewNode(ns_ows, BAD_CAST "AdditionalParameters"); + if(strncasecmp(meta->name,"title",5)==0 || + strcasecmp(meta->name,"href")==0 || + strcasecmp(meta->name,"role")==0 ){ + int index=5; + if(strncasecmp(meta->name,"title",5)==0){ + index=6; + hasTitle=1; + if(ctitle!=NULL && strcasecmp(meta->value,ctitle)!=0){ + xmlAddChild(nc,nc1); + nc1 = xmlNewNode(ns_ows, BAD_CAST "AdditionalParameters"); + free(ctitle); + ctitle=NULL; + } + if(ctitle==NULL){ + char *tmp=(char*)malloc((strlen(meta->name)+1)*sizeof(char)); + snprintf(tmp,index,"%s",meta->name); + xmlNewNsProp(nc1,ns_xlink,BAD_CAST tmp,BAD_CAST meta->value); + free(tmp); + } + if(ctitle!=NULL) + free(ctitle); + ctitle=zStrdup(meta->value); + } + }else{ + xmlNodePtr nc2 = xmlNewNode(ns_ows, BAD_CAST "AdditionalParameter"); + xmlNodePtr nc3 = xmlNewNode(ns_ows, BAD_CAST "Name"); + xmlAddChild(nc3,xmlNewText(BAD_CAST meta->name)); + xmlNodePtr nc4 = xmlNewNode(ns_ows, BAD_CAST "Value"); + xmlAddChild(nc4,xmlNewText(BAD_CAST meta->value)); + xmlAddChild(nc2,nc3); + xmlAddChild(nc2,nc4); + xmlAddChild(nc1,nc2); + hasTitle=-1; + } + meta=meta->next; + if(hasTitle<0){ + hasValue=1; + if(isAdditionalParameters){ + if(vid==0){ + meta=NULL; + break; + }else + xmlAddChild(nc,nc1); + } + } + } + if(oMeta!=NULL && hasValue<0 && nc1!=NULL){ + xmlAddChild(nc,nc1); + } +} + +/** + * Add AdditionalParameters nodes to any existing node. + * @param meta the map defining the additional parameters + * @param doc the XML document used + * @param nb the node to add the additional parameters + * @param ns_ows the OWS namespace + * @param ns_xlink the xlink namespace + * @param fromDb 1 if the metadata has been extracted from the metadb, + * 0 otherwise + */ +void addAdditionalParameters(map* meta,xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,int fromDb){ + int hasTitle=-1; + int hasValue=-1; + int toAddAtEnd=-1; + int cnt=0; + xmlNodePtr* ncr=NULL; + xmlNodePtr nc1; + map* oMeta=meta; + int isAdditionalParameters=-1; + int level=0; + map* test=getMap(meta,"title"); + map* otitle=getMap(meta,"title"); + map* length=getMap(meta,"length"); + int len=0; + char *ctitle=NULL; + + if(test!=NULL) + level+=1; + test=getMap(meta,"href"); + if(test!=NULL) + level+=1; + test=getMap(meta,"role"); + if(test!=NULL) + level+=1; + if(count(oMeta)>level+1) + isAdditionalParameters=1; + + while(meta!=NULL){ + if(hasTitle<0 && hasValue<0){ + nc1 = xmlNewNode(ns_ows, BAD_CAST "AdditionalParameters"); + } + if(strncasecmp(meta->name,"title",5)==0 || + strcasecmp(meta->name,"href")==0 || + strcasecmp(meta->name,"role")==0 ){ + int index=5; + if(strncasecmp(meta->name,"title",5)==0){ + index=6; + hasTitle=1; + if(ctitle!=NULL && strcasecmp(meta->value,ctitle)!=0){ + xmlNodePtr ncTmp = xmlDocCopyNodeList(doc,nc1); + xmlAddChild(nc,ncTmp); + xmlFreeNode(nc1); + toAddAtEnd=1; + cnt++; + nc1 = xmlNewNode(ns_ows, BAD_CAST "AdditionalParameters"); + free(ctitle); + ctitle=NULL; + } + if(ctitle==NULL){ + char *tmp=(char*)malloc((strlen(meta->name)+1)*sizeof(char)); + snprintf(tmp,index,"%s",meta->name); + xmlNewNsProp(nc1,ns_xlink,BAD_CAST tmp,BAD_CAST meta->value); + free(tmp); + } + if(ctitle!=NULL) + free(ctitle); + ctitle=zStrdup(meta->value); + }else{ + xmlNewNsProp(nc1,ns_xlink,BAD_CAST meta->name,BAD_CAST meta->value); + } + }else{ + if(strncasecmp(meta->name,"length",6)!=0 && strncasecmp(meta->name,"fromDb",6)!=0){ + xmlNodePtr nc2 = xmlNewNode(ns_ows, BAD_CAST "AdditionalParameter"); + xmlNodePtr nc3 = xmlNewNode(ns_ows, BAD_CAST "Name"); + xmlAddChild(nc3,xmlNewText(BAD_CAST meta->name)); + xmlAddChild(nc2,nc3); + if(fromDb<0){ + char *mptr; + char* meta_values=strtok_r(meta->value,",",&mptr); + while(meta_values!=NULL){ + xmlNodePtr nc4 = xmlNewNode(ns_ows, BAD_CAST "Value"); + xmlAddChild(nc4,xmlNewText(BAD_CAST meta_values)); + xmlAddChild(nc2,nc4); + meta_values=strtok_r(NULL,",",&mptr); + } + }else{ + xmlNodePtr nc4 = xmlNewNode(ns_ows, BAD_CAST "Value"); + xmlAddChild(nc4,xmlNewCDataBlock(doc,BAD_CAST meta->value,strlen(meta->value))); + xmlAddChild(nc2,nc4); + } + xmlAddChild(nc1,nc2); + } + hasTitle=-1; + } + meta=meta->next; + if(hasTitle<0){ + //xmlAddChild(nc,nc1); + hasValue=1; + }/*else + if(ctitle!=NULL) + free(ctitle);*/ + } + if(length!=NULL) + len=atoi(length->value); + if(otitle!=NULL) + len=1; + if(cntcontent,"extend"); + if(tmp1==NULL) + tmp1=getMap(serv->content,"concept"); + if(tmp1!=NULL){ + map* level=getMap(serv->content,"level"); + if(level!=NULL){ + xmlNodePtr nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata"); + char* ckey=level->value; + if(strncasecmp(level->value,"profile",7)==0) + ckey=(char*)"generic"; + if(strncasecmp(level->value,"generic",7)==0) + ckey=(char*)"concept"; + service* inherited=getServiceFromRegistry(reg,ckey,tmp1->value); + if(inherited!=NULL){ + addInheritedMetadata(n,ns_ows,ns_xlink,reg,main_conf,inherited); + } + char cschema[71]; + sprintf(cschema,"%s%s",schemas[vid][7],ckey); + map* regUrl=getMapFromMaps(main_conf,"main","registryUrl"); + map* regExt=getMapFromMaps(main_conf,"main","registryExt"); + char* registryUrl=(char*)malloc((strlen(regUrl->value)+strlen(ckey)+ + (regExt!=NULL?strlen(regExt->value)+1:0)+ + strlen(tmp1->value)+2)*sizeof(char)); + if(regExt!=NULL) + sprintf(registryUrl,"%s%s/%s.%s",regUrl->value,ckey,tmp1->value,regExt->value); + else + sprintf(registryUrl,"%s%s/%s",regUrl->value,ckey,tmp1->value); + xmlNewNsProp(nc1,ns_xlink,BAD_CAST "role",BAD_CAST cschema); + xmlNewNsProp(nc1,ns_xlink,BAD_CAST "href",BAD_CAST registryUrl); + free(registryUrl); + xmlAddChild(n,nc1); + } + } +} + +/** + * Generate a ProcessDescription node for a servie and add it to a given node. + * + * @param reg the profile registry + * @param m the conf maps containing the main.cfg settings + * @param nc the XML node to add the Process node + * @param serv the servive structure created from the zcfg file + * @return the generated wps:ProcessOfferings xmlNodePtr + */ +void printDescribeProcessForProcess(registry *reg, maps* m,void* doc0,void* nc0,service* serv){ + xmlNsPtr ns,ns_ows,ns_xlink; + xmlNodePtr n,nc1; + xmlDocPtr doc=(xmlDocPtr) doc0; + xmlNodePtr nc=(xmlNodePtr) nc0; + xmlNodePtr nc2 = NULL; + map* version=getMapFromMaps(m,"main","rversion"); + int vid=getVersionId(version->value); + int fromDb=-1; + map* serviceType=getMap(serv->content,"serviceType"); + map* test=getMap(serv->content,"fromDb"); + if(test!=NULL && strncasecmp(test->value,"true",4)==0) + fromDb=1; + + n=nc; + int wpsId=zooXmlAddNs(NULL,schemas[vid][3],"wps"); + ns=usedNs[wpsId]; + int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows"); + ns_ows=usedNs[owsId]; + int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink"); + ns_xlink=usedNs[xlinkId]; + map* tmp1=NULL; + + if(vid==0){ + nc = xmlNewNode(NULL, BAD_CAST "ProcessDescription"); + attachAttributes(nc,ns,serv->content,vid,NULL); + } + else{ + nc2 = xmlNewNode(ns, BAD_CAST "ProcessOffering"); + // In case mode was defined in the ZCFG file then restrict the + // jobControlOptions value to this value. The dismiss is always + // supported whatever you can set in the ZCFG file. + // cf. http://docs.opengeospatial.org/is/14-065/14-065.html#47 (Table 30) + map* mode=getMap(serv->content,"mode"); + if(mode!=NULL){ + if( strncasecmp(mode->value,"sync",strlen(mode->value))==0 || + strncasecmp(mode->value,"async",strlen(mode->value))==0 ){ + char toReplace[22]; + sprintf(toReplace,"%s-execute dismiss",mode->value); + addToMap(serv->content,capabilities[vid][3],toReplace); + } + } + attachAttributes(nc2,NULL,serv->content,vid,serviceType); + map* level=getMap(serv->content,"level"); + if(level!=NULL && strcasecmp(level->value,"generic")==0) + nc = xmlNewNode(ns, BAD_CAST "GenericProcess"); + else + nc = xmlNewNode(ns, BAD_CAST "Process"); + } + + tmp1=getMapFromMaps(m,"lenv","level"); + addPrefix(m,tmp1,serv); + printDescription(nc,ns_ows,serv->name,serv->content,vid); + + if(vid==0){ + tmp1=serv->metadata; + while(tmp1!=NULL){ + addMetadata(tmp1,doc,nc,ns_ows,ns_xlink,vid); + tmp1=tmp1->next; + } + tmp1=getMap(serv->content,"Profile"); + if(tmp1!=NULL && vid==0){ + nc1 = xmlNewNode(ns, BAD_CAST "Profile"); + xmlAddChild(nc1,xmlNewText(BAD_CAST tmp1->value)); + xmlAddChild(nc,nc1); + } + }else{ + tmp1=serv->metadata; + addMetadata(tmp1,doc,nc,ns_ows,ns_xlink,vid); + addInheritedMetadata(nc,ns_ows,ns_xlink,reg,m,serv); + tmp1=serv->additional_parameters; + if(vid!=0) + addAdditionalParameters(tmp1,doc,nc,ns_ows,ns_xlink,fromDb); + } + + if(serv->inputs!=NULL){ + elements* e=serv->inputs; + if(vid==0){ + nc1 = xmlNewNode(NULL, BAD_CAST "DataInputs"); + printFullDescription(doc,1,e,"Input",ns,ns_ows,nc1,vid,fromDb,NULL); + xmlAddChild(nc,nc1); + } + else{ + printFullDescription(doc,1,e,"wps:Input",ns,ns_ows,nc,vid,fromDb,NULL); + } + } + + elements* e=serv->outputs; + if(vid==0){ + nc1 = xmlNewNode(NULL, BAD_CAST "ProcessOutputs"); + printFullDescription(doc,0,e,"Output",ns,ns_ows,nc1,vid,fromDb,NULL); + xmlAddChild(nc,nc1); + } + else{ + printFullDescription(doc,0,e,"wps:Output",ns,ns_ows,nc,vid,fromDb,serviceType); + } + if(vid==0) + xmlAddChild(n,nc); + else if (nc2 != NULL) { + xmlAddChild(nc2,nc); + xmlAddChild(n,nc2); + } + +} + +/** + * Generate the required XML tree for the detailled metadata information of + * inputs or outputs + * + * @param in 1 in case of inputs, 0 for outputs + * @param elem the elements structure containing the metadata information + * @param type the name ("Input" or "Output") of the XML node to create + * @param ns_ows the ows XML namespace + * @param ns_ows the ows XML namespace + * @param nc1 the XML node to use to add the created tree + * @param vid the WPS version id (0 for 1.0.0, 1 for 2.0.0) + * @param fromDb 1 in case the metadata comes from the DB, -1 in other cases + * @param serviceType the serviceType found in the ZCFG file or the DB + */ +void printFullDescription(xmlDocPtr doc,int in,elements *elem,const char* type,xmlNsPtr ns,xmlNsPtr ns_ows,xmlNodePtr nc1,int vid,int fromDb,const map* serviceType){ + xmlNsPtr ns1=NULL; + if(vid==1) + ns1=ns; + + xmlNodePtr nc2,nc3,nc4,nc5,nc6,nc7,nc8,nc9,nc55=NULL,nc56; + elements* e=elem; + nc9=NULL; + map* tmp1=NULL; + while(e!=NULL){ + int default1=0; + int isAnyValue=1; + nc2 = xmlNewNode(NULL, BAD_CAST type); + // Extract min/max Occurence information + if(strstr(type,"Input")!=NULL){ + tmp1=getMap(e->content,"minOccurs"); + if(tmp1!=NULL){ + xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value); + }else + xmlNewProp(nc2,BAD_CAST "minOccurs",BAD_CAST "0"); + tmp1=getMap(e->content,"maxOccurs"); + if(tmp1!=NULL){ + if(strcasecmp(tmp1->value,"unbounded")!=0) + xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value); + else + xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1000"); + }else + xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1"); + if((tmp1=getMap(e->content,"maximumMegabytes"))!=NULL){ + if(vid==0) + xmlNewProp(nc2,BAD_CAST "maximumMegabytes",BAD_CAST tmp1->value); + } + } + + printDescription(nc2,ns_ows,e->name,e->content,vid); + + if(e->format!=NULL){ +#ifdef USE_HPC + DEFAULT_OUT: +#endif + const char orderedFields[13][14]={ + "mimeType", + "encoding", + "schema", + "dataType", + "uom", + "CRS", + "AllowedValues", + "range", + "rangeMin", + "rangeMax", + "rangeClosure", + "rangeSpace" + }; + + //Build the (Literal/Complex/BoundingBox)Data node + if(strncmp(type,"Output",6)==0){ + if(strncasecmp(e->format,"LITERAL",7)==0) + nc3 = xmlNewNode(ns1, BAD_CAST "LiteralOutput"); + else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0) + nc3 = xmlNewNode(ns1, BAD_CAST "ComplexOutput"); + else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0) + nc3 = xmlNewNode(ns1, BAD_CAST "BoundingBoxOutput"); + else + nc3 = xmlNewNode(ns1, BAD_CAST e->format); + }else{ + if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0 || + strncasecmp(e->format,"LITERALOUTPUT",strlen(e->format))==0){ + nc3 = xmlNewNode(ns1, BAD_CAST "LiteralData"); + } + else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0) + nc3 = xmlNewNode(ns1, BAD_CAST "ComplexData"); + else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0) + nc3 = xmlNewNode(ns1, BAD_CAST "BoundingBoxData"); + else + nc3 = xmlNewNode(ns1, BAD_CAST e->format); + } + + iotype* _tmp0=NULL; + iotype* _tmp=e->defaults; + int datatype=0; + bool hasUOM=false; + bool hasUOM1=false; + if(_tmp!=NULL){ + if(strcmp(e->format,"LiteralOutput")==0 || + strcmp(e->format,"LiteralData")==0){ + datatype=1; + if(vid==1){ + nc4 = xmlNewNode(ns1, BAD_CAST "Format"); + xmlNewProp(nc4,BAD_CAST "mimeType",BAD_CAST "text/plain"); + xmlNewProp(nc4,BAD_CAST "default",BAD_CAST "true"); + xmlAddChild(nc3,nc4); + nc5 = xmlNewNode(NULL, BAD_CAST "LiteralDataDomain"); + nc55 = xmlNewNode(NULL, BAD_CAST "LiteralDataDomain"); + xmlNewProp(nc5,BAD_CAST "default",BAD_CAST "true"); + } + else{ + nc4 = xmlNewNode(NULL, BAD_CAST "UOMs"); + nc5 = xmlNewNode(NULL, BAD_CAST "Default"); + } + } + else if(strcmp(e->format,"BoundingBoxOutput")==0 || + strcmp(e->format,"BoundingBoxData")==0){ + datatype=2; + if(vid==0) + nc5 = xmlNewNode(NULL, BAD_CAST "Default"); + else{ + xmlNodePtr nc6 = xmlNewNode(ns1, BAD_CAST "Format"); + xmlNewProp(nc6,BAD_CAST "mimeType",BAD_CAST "text/xml"); + xmlNewProp(nc6,BAD_CAST "default",BAD_CAST "true"); + xmlAddChild(nc3,nc6); + nc5 = xmlNewNode(NULL, BAD_CAST "SupportedCRS"); + } + } + else{ + if(vid==0) + nc4 = xmlNewNode(NULL, BAD_CAST "Default"); + nc5 = xmlNewNode(ns1, BAD_CAST "Format"); + if(vid==1){ + xmlNewProp(nc5,BAD_CAST "default",BAD_CAST "true"); + int oI=0; + for(oI=0;oI<3;oI++) + if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){ + xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value); + } + } + } + + if((tmp1=getMap(e->content,"maximumMegabytes"))!=NULL){ + if(vid==1) + xmlNewProp(nc5,BAD_CAST "maximumMegabytes",BAD_CAST tmp1->value); + } + + + tmp1=_tmp->content; + + if(vid==0) + if((tmp1=getMap(_tmp->content,"DataType"))!=NULL){ + nc8 = xmlNewNode(ns_ows, BAD_CAST "DataType"); + xmlAddChild(nc8,xmlNewText(BAD_CAST tmp1->value)); + char tmp[1024]; + sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value); + xmlNewNsProp(nc8,ns_ows,BAD_CAST "reference",BAD_CAST tmp); + if(vid==0) + xmlAddChild(nc3,nc8); + else + xmlAddChild(nc5,nc8); + datatype=1; + } + + bool isInput=false; + if(strncmp(type,"Input",5)==0 || strncmp(type,"wps:Input",9)==0){ + isInput=true; + if((tmp1=getMap(_tmp->content,"AllowedValues"))!=NULL){ + nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues"); + char *token,*saveptr1; + token=strtok_r(tmp1->value,",",&saveptr1); + while(token!=NULL){ + nc7 = xmlNewNode(ns_ows, BAD_CAST "Value"); + char *tmps=zStrdup(token); + tmps[strlen(tmps)]=0; + nc8 = xmlNewText(BAD_CAST tmps); + xmlAddChild(nc7,nc8); + free(tmps); + xmlAddChild(nc6,nc7); + token=strtok_r(NULL,",",&saveptr1); + } + if(getMap(_tmp->content,"range")!=NULL || + getMap(_tmp->content,"rangeMin")!=NULL || + getMap(_tmp->content,"rangeMax")!=NULL || + getMap(_tmp->content,"rangeClosure")!=NULL ) + goto doRange; + if(vid==0) + xmlAddChild(nc3,nc6); + else + xmlAddChild(nc5,nc6); + isAnyValue=-1; + } + + tmp1=getMap(_tmp->content,"range"); + if(tmp1==NULL) + tmp1=getMap(_tmp->content,"rangeMin"); + if(tmp1==NULL) + tmp1=getMap(_tmp->content,"rangeMax"); + + if(tmp1!=NULL && isAnyValue==1){ + nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues"); + doRange: + + /** + * Range: Table 46 OGC Web Services Common Standard + */ + nc8 = xmlNewNode(ns_ows, BAD_CAST "Range"); + + map* tmp0=getMap(tmp1,"range"); + if(tmp0!=NULL){ + char* pToken; + char* orig=zStrdup(tmp0->value); + /** + * RangeClosure: Table 47 OGC Web Services Common Standard + */ + const char *tmp="closed"; + if(orig[0]=='[' && orig[strlen(orig)-1]=='[') + tmp="closed-open"; + else + if(orig[0]==']' && orig[strlen(orig)-1]==']') + tmp="open-closed"; + else + if(orig[0]==']' && orig[strlen(orig)-1]=='[') + tmp="open"; + xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp); + pToken=strtok(orig,","); + int nci0=0; + while(pToken!=NULL){ + char *tmpStr=(char*) malloc((strlen(pToken))*sizeof(char)); + if(nci0==0){ + nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue"); + strncpy( tmpStr, pToken+1, strlen(pToken)-1 ); + tmpStr[strlen(pToken)-1] = '\0'; + }else{ + nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue"); + const char* bkt; + if ( ( bkt = strchr(pToken, '[') ) != NULL || ( bkt = strchr(pToken, ']') ) != NULL ){ + strncpy( tmpStr, pToken, bkt - pToken ); + tmpStr[bkt - pToken] = '\0'; + } + } + xmlAddChild(nc7,xmlNewText(BAD_CAST tmpStr)); + free(tmpStr); + xmlAddChild(nc8,nc7); + nci0++; + pToken = strtok(NULL,","); + } + if(getMap(tmp1,"rangeSpacing")==NULL){ + nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing"); + xmlAddChild(nc7,xmlNewText(BAD_CAST "1")); + xmlAddChild(nc8,nc7); + } + free(orig); + }else{ + + tmp0=getMap(tmp1,"rangeMin"); + if(tmp0!=NULL){ + nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue"); + xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value)); + xmlAddChild(nc8,nc7); + }else{ + nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue"); + xmlAddChild(nc8,nc7); + } + tmp0=getMap(tmp1,"rangeMax"); + if(tmp0!=NULL){ + nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue"); + xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value)); + xmlAddChild(nc8,nc7); + }else{ + nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue"); + xmlAddChild(nc8,nc7); + } + tmp0=getMap(tmp1,"rangeSpacing"); + if(tmp0!=NULL){ + nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing"); + xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value)); + xmlAddChild(nc8,nc7); + } + tmp0=getMap(tmp1,"rangeClosure"); + if(tmp0!=NULL){ + const char *tmp="closed"; + if(strcasecmp(tmp0->value,"co")==0) + tmp="closed-open"; + else + if(strcasecmp(tmp0->value,"oc")==0) + tmp="open-closed"; + else + if(strcasecmp(tmp0->value,"o")==0) + tmp="open"; + xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp); + }else + xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST "closed"); + } + if(_tmp0==NULL){ + xmlAddChild(nc6,nc8); + _tmp0=e->supported; + if(_tmp0!=NULL && + (getMap(_tmp0->content,"range")!=NULL || + getMap(_tmp0->content,"rangeMin")!=NULL || + getMap(_tmp0->content,"rangeMax")!=NULL || + getMap(_tmp0->content,"rangeClosure")!=NULL )){ + tmp1=_tmp0->content; + goto doRange; + } + }else{ + _tmp0=_tmp0->next; + if(_tmp0!=NULL){ + xmlAddChild(nc6,nc8); + if(getMap(_tmp0->content,"range")!=NULL || + getMap(_tmp0->content,"rangeMin")!=NULL || + getMap(_tmp0->content,"rangeMax")!=NULL || + getMap(_tmp0->content,"rangeClosure")!=NULL ){ + tmp1=_tmp0->content; + goto doRange; + } + } + } + xmlAddChild(nc6,nc8); + if(vid==0) + xmlAddChild(nc3,nc6); + else{ + xmlAddChild(nc5,nc6); + xmlAddChild(nc55,nc6); + } + isAnyValue=-1; + } + + } + + int oI=0; + /*if(vid==0)*/ { + for(oI=0;oI<12;oI++) + if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){ +#ifdef DEBUG + printf("DATATYPE DEFAULT ? %s\n",tmp1->name); +#endif + if(strcmp(tmp1->name,"asReference")!=0 && + strncasecmp(tmp1->name,"DataType",8)!=0 && + strcasecmp(tmp1->name,"extension")!=0 && + strcasecmp(tmp1->name,"value")!=0 && + strcasecmp(tmp1->name,"AllowedValues")!=0 && + strncasecmp(tmp1->name,"range",5)!=0){ + if(datatype!=1){ + if(datatype==2 && vid==1){ + nc9 = xmlNewNode(ns, BAD_CAST "SupportedCRS"); + xmlNewProp(nc9,BAD_CAST "default",BAD_CAST "true"); + } + else{ + char *tmp2=zCapitalize1(tmp1->name); + nc9 = xmlNewNode(NULL, BAD_CAST tmp2); + free(tmp2); + } + } + else{ + char *tmp2=zCapitalize(tmp1->name); + nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2); + free(tmp2); + } + xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value)); + if(vid==0 || oI>=3){ + if(vid==0 || oI!=4){ + if(datatype==2 && vid==1) + xmlAddChild(nc3,nc9); + else + xmlAddChild(nc5,nc9); + } + } + else{ + xmlFreeNode(nc9); + } + if(strcasecmp(tmp1->name,"uom")==0) + hasUOM1=true; + hasUOM=true; + } + } + } + if(datatype!=2){ + if(hasUOM==true){ + if(vid==0){ + xmlAddChild(nc4,nc5); + xmlAddChild(nc3,nc4); + } + else{ + xmlAddChild(nc3,nc5); + } + }else{ + if(hasUOM1==false && vid==0){ + if(nc5!=NULL) + xmlFreeNode(nc5); + if(datatype==1){ + xmlFreeNode(nc4); + } + } + else{ + xmlAddChild(nc3,nc5); + } + } + }else{ + if(vid==0) + xmlAddChild(nc3,nc5); + else + xmlFreeNode(nc5); + } + + if(datatype==0 && default1<0){ + xmlFreeNode(nc5); + if(datatype!=2){ + xmlFreeNode(nc4); + } + } + + + if((isInput || vid==1) && datatype==1 && + getMap(_tmp->content,"AllowedValues")==NULL && + getMap(_tmp->content,"range")==NULL && + getMap(_tmp->content,"rangeMin")==NULL && + getMap(_tmp->content,"rangeMax")==NULL && + getMap(_tmp->content,"rangeClosure")==NULL ){ + tmp1=getMap(_tmp->content,"dataType"); + // We were tempted to define default value for boolean as {true,false} + if(tmp1!=NULL && strcasecmp(tmp1->value,"boolean")==0){ + nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues"); + nc7 = xmlNewNode(ns_ows, BAD_CAST "Value"); + xmlAddChild(nc7,xmlNewText(BAD_CAST "true")); + xmlAddChild(nc6,nc7); + nc7 = xmlNewNode(ns_ows, BAD_CAST "Value"); + xmlAddChild(nc7,xmlNewText(BAD_CAST "false")); + xmlAddChild(nc6,nc7); + if(vid==0) + xmlAddChild(nc3,nc6); + else{ + xmlAddChild(nc5,nc6); + xmlAddChild(nc55,nc6); + } + } + else + if(vid==0) + xmlAddChild(nc3,xmlNewNode(ns_ows, BAD_CAST "AnyValue")); + else{ + xmlAddChild(nc5,xmlNewNode(ns_ows, BAD_CAST "AnyValue")); + xmlAddChild(nc55,xmlNewNode(ns_ows, BAD_CAST "AnyValue")); + } + } + + if(vid==1){ + if((tmp1=getMap(_tmp->content,"DataType"))!=NULL){ + nc8 = xmlNewNode(ns_ows, BAD_CAST "DataType"); + xmlAddChild(nc8,xmlNewText(BAD_CAST tmp1->value)); + char tmp[1024]; + sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value); + xmlNewNsProp(nc8,ns_ows,BAD_CAST "reference",BAD_CAST tmp); + if(vid==0) + xmlAddChild(nc3,nc8); + else{ + xmlAddChild(nc5,nc8); + xmlAddChild(nc55,nc8); + } + datatype=1; + } + if(hasUOM==true){ + tmp1=getMap(_tmp->content,"uom"); + if(tmp1!=NULL){ + xmlAddChild(nc5,nc9); + } + } + if(e->defaults!=NULL && (tmp1=getMap(e->defaults->content,"value"))!=NULL){ + nc7 = xmlNewNode(ns_ows, BAD_CAST "DefaultValue"); + xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value)); + xmlAddChild(nc5,nc7); + xmlAddChild(nc55,nc7); + } + } + + map* metadata=e->metadata; + xmlNodePtr n=NULL; + int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink"); + xmlNsPtr ns_xlink=usedNs[xlinkId]; + + addMetadata(metadata,doc,nc2,ns_ows,ns_xlink,vid); + if(vid!=0) + addAdditionalParameters(e->additional_parameters,doc,nc2,ns_ows,ns_xlink,fromDb); + + } + + _tmp=e->supported; + if(_tmp==NULL && datatype==0) + _tmp=e->defaults; + + int hasSupported=-1; + + while(_tmp!=NULL){ + + if(hasSupported<0){ + if(datatype==0){ + if(vid==0) + nc4 = xmlNewNode(NULL, BAD_CAST "Supported"); + nc5 = xmlNewNode(ns1, BAD_CAST "Format"); + if(vid==1){ + int oI=0; + for(oI=0;oI<3;oI++) + if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){ + xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value); + } + } + } + else + if(vid==0) + nc5 = xmlNewNode(NULL, BAD_CAST "Supported"); + hasSupported=0; + }else + if(datatype==0){ + nc5 = xmlNewNode(ns1, BAD_CAST "Format"); + if(vid==1){ + int oI=0; + for(oI=0;oI<3;oI++) + if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){ + xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value); + } + } + } + + if((tmp1=getMap(e->content,"maximumMegabytes"))!=NULL){ + if(vid==1) + xmlNewProp(nc5,BAD_CAST "maximumMegabytes",BAD_CAST tmp1->value); + } + + tmp1=_tmp->content; + int oI=0; + for(oI=0;oI<6;oI++) + if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){ +#ifdef DEBUG + printf("DATATYPE SUPPORTED ? %s\n",tmp1->name); +#endif + if(strcmp(tmp1->name,"asReference")!=0 && + strcmp(tmp1->name,"value")!=0 && + strcmp(tmp1->name,"DataType")!=0 && + strcasecmp(tmp1->name,"extension")!=0){ + if(datatype!=1){ + if(datatype==2 && vid==1){ + nc6 = xmlNewNode(ns, BAD_CAST "SupportedCRS"); + } + else{ + char *tmp2=zCapitalize1(tmp1->name); + nc6 = xmlNewNode(NULL, BAD_CAST tmp2); + free(tmp2); + } + } + else{ + char *tmp2=zCapitalize(tmp1->name); + nc6 = xmlNewNode(ns_ows, BAD_CAST tmp2); + free(tmp2); + } + if(datatype==2){ + char *tmpv,*tmps; + tmps=strtok_r(tmp1->value,",",&tmpv); + while(tmps){ + xmlAddChild(nc6,xmlNewText(BAD_CAST tmps)); + tmps=strtok_r(NULL,",",&tmpv); + if(tmps){ + char *tmp2=zCapitalize1(tmp1->name); + nc6 = xmlNewNode(NULL, BAD_CAST tmp2); + free(tmp2); + } + } + } + else{ + xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value)); + } + if(vid==0 || oI>=3){ + if(vid==0 || oI!=4){ + if(datatype==2 && vid==1) + xmlAddChild(nc3,nc6); + else + xmlAddChild(nc5,nc6); + } + else{ + if(oI!=4) + xmlFreeNode(nc6); + else{ + nc56=xmlCopyNode(nc55,1); + xmlReplaceNode(xmlGetLastChild(nc56),nc6); + xmlAddChild(nc3,nc56); + } + } + } + else{ + xmlFreeNode(nc6); + } + } + tmp1=tmp1->next; + } + if(hasSupported<=0){ + if(datatype==0){ + if(vid==0){ + xmlAddChild(nc4,nc5); + xmlAddChild(nc3,nc4); + } + else{ + xmlAddChild(nc3,nc5); + } + + }else{ + if(datatype==2 && vid==0) + xmlAddChild(nc3,nc5); + } + hasSupported=1; + } + else + if(datatype==0){ + if(vid==0){ + xmlAddChild(nc4,nc5); + xmlAddChild(nc3,nc4); + } + else{ + xmlAddChild(nc3,nc5); + } + } + else + if(datatype==0){ + xmlFreeNode(nc4); + xmlAddChild(nc3,nc5); + } + + _tmp=_tmp->next; + } + + if(hasSupported==0){ + if(datatype==0 && vid!=0){ + xmlFreeNode(nc4); + } + xmlFreeNode(nc5); + } + + _tmp=e->defaults; + if(datatype==1 && hasUOM1==true){ + if(vid==0){ + xmlAddChild(nc4,nc5); + xmlAddChild(nc3,nc4); + } + else{ + xmlAddChild(nc3,nc5); + } + } + + if(vid==0 && _tmp!=NULL && (tmp1=getMap(_tmp->content,"value"))!=NULL){ + nc7 = xmlNewNode(NULL, BAD_CAST "DefaultValue"); + xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value)); + xmlAddChild(nc3,nc7); + } + xmlAddChild(nc2,nc3); + }else{ + if(e->child!=NULL && vid!=0){ + printFullDescription(doc,in,e->child,type,ns,ns_ows,nc2,vid,fromDb,NULL); + } + } + if(e->child!=NULL && vid==0){ + elements* children=dupElements(e->child); + elements* cursor=children; + while(cursor!=NULL){ + elements* ccursor=cursor; + char* tmp=zStrdup(ccursor->name); + free(ccursor->name); + ccursor->name=(char*)malloc((strlen(tmp)+strlen(e->name)+2)*sizeof(char)); + sprintf(ccursor->name,"%s.%s",e->name,tmp); + cursor=cursor->next; + } + printFullDescription(doc,in,children,type,ns,ns_ows,nc1,vid,fromDb,serviceType); + freeElements(&children); + free(children); + }else{ + if(nc2!=NULL){ + xmlAddChild(nc1,nc2); + } + } + e=e->next; + } +} + +/** + * Generate a wps:Execute XML document. + * + * @param m the conf maps containing the main.cfg settings + * @param request the map representing the HTTP request + * @param pid the process identifier linked to a service + * @param serv the serv structure created from the zcfg file + * @param service the service name + * @param status the status returned by the service + * @param inputs the inputs provided + * @param outputs the outputs generated by the service + */ +void printProcessResponse(maps* m,map* request, int pid,service* serv,const char* service,int status,maps* inputs,maps* outputs){ + xmlNsPtr ns,ns_ows,ns_xlink; + xmlNodePtr nr,n,nc,nc1=NULL,nc3; + xmlDocPtr doc; + time_t time1; + time(&time1); + nr=NULL; + + + + int ei = 1; + int canContinue=false; + char **orig = environ; + char *s=*orig; + char workspace[1024*2]; + char* pWorkspace = NULL; + memset(workspace,0,1024*2); + for (; s; ei++ ) { + if (strstr(s,"EOEPCA_WORKSPACE")!=NULL){ + char* baseU=strchr(s,'='); + if (strlen(baseU)>1){ + pWorkspace = ++baseU; + } + } + // fprintf(stderr, "------> %s \n", s); + s = *(orig+ei); + } + + if (pWorkspace){ + const char *HTTP_HOST = std::getenv("HTTP_HOST"); + const char *REQUEST_SCHEME = std::getenv("REQUEST_SCHEME"); + const char *REQUEST_URI = std::getenv("REQUEST_URI"); + sprintf(workspace, "%s://%s/%s/zoo", REQUEST_SCHEME, HTTP_HOST,pWorkspace); + fprintf(stderr, "------> >>>>>>%s://%s<<<<<\n", REQUEST_SCHEME, HTTP_HOST); + fprintf(stderr,"---------WORKSPACE: %s--------------\n",workspace); + } + + doc = xmlNewDoc(BAD_CAST "1.0"); + map* version=getMapFromMaps(m,"main","rversion"); + int vid=getVersionId(version->value); + n = printWPSHeader(doc,m,"Execute",root_nodes[vid][2],(version!=NULL?version->value:"1.0.0"),2); + int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps"); + ns=usedNs[wpsId]; + int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows"); + ns_ows=usedNs[owsId]; + int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink"); + ns_xlink=usedNs[xlinkId]; + bool hasStoredExecuteResponse=false; + char stored_path[1024]; + memset(stored_path,0,1024); + + if(vid==0){ + char tmp[256]; + char url[1024]; + memset(tmp,0,256); + memset(url,0,1024); + maps* tmp_maps=getMaps(m,"main"); + if(tmp_maps!=NULL && tmp_maps->content!=NULL){ + map* tmpm1=getMap(tmp_maps->content,"serverAddress"); + /** + * Check if the ZOO Service GetStatus is available in the local directory. + * If yes, then it uses a reference to an URL which the client can access + * to get information on the status of a running Service (using the + * percentCompleted attribute). + * Else fallback to the initial method using the xml file to write in ... + */ + + if (strlen(workspace)>0 && tmpm1 && tmpm1->value ){ + free(tmpm1->value); + tmpm1->value = zStrdup(workspace); + } + + map* cwdMap=getMapFromMaps(m,"main","servicePath"); + struct stat myFileInfo; + int statRes; + char file_path[1024]; + if(cwdMap!=NULL){ + sprintf(file_path,"%s/GetStatus.zcfg",cwdMap->value); + }else{ + char ntmp[1024]; +#ifndef WIN32 + getcwd(ntmp,1024); +#else + _getcwd(ntmp,1024); +#endif + sprintf(file_path,"%s/GetStatus.zcfg",ntmp); + } + statRes=stat(file_path,&myFileInfo); + if(statRes==0){ + char currentSid[128]; + map* tmpm=getMap(tmp_maps->content,"rewriteUrl"); + map *tmp_lenv=NULL; + tmp_lenv=getMapFromMaps(m,"lenv","usid"); + if(tmp_lenv==NULL) + sprintf(currentSid,"%i",pid); + else + sprintf(currentSid,"%s",tmp_lenv->value); + if(tmpm==NULL || strcasecmp(tmpm->value,"false")==0){ + sprintf(url,"%s?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid); + + // fprintf(stderr,"---------THEPATH: %s--------------\n",tmpm1->value); + // fprintf(stderr,"---------WORKSPACE1: %s--------------\n",workspace); + + }else{ + if(strlen(tmpm->value)>0) + if(strcasecmp(tmpm->value,"true")!=0) + { + // fprintf(stderr,"---------WORKSPACE2: %s--------------\n",workspace); + sprintf(url,"%s/%s/GetStatus/%s",tmpm1->value,tmpm->value,currentSid); + } + else + { + // fprintf(stderr,"---------WORKSPACE3: %s--------------\n",workspace); + sprintf(url,"%s/GetStatus/%s",tmpm1->value,currentSid); + } + else{ + // fprintf(stderr,"---------WORKSPACE4: %s--------------\n",workspace); + sprintf(url,"%s/?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid); + } + } + }else{ + int lpid; + map* tmpm2=getMapFromMaps(m,"lenv","usid"); + map* tmpm3=getMap(tmp_maps->content,"tmpUrl"); + if(tmpm1!=NULL && tmpm3!=NULL){ + if( strncasecmp( tmpm3->value, "http://", 7) == 0 || + strncasecmp( tmpm3->value, "https://", 8 ) == 0 ){ + sprintf(url,"%s/%s_%s.xml",tmpm3->value,service,tmpm2->value); + }else + sprintf(url,"%s/%s_%s.xml",tmpm1->value,service,tmpm2->value); + } + } + if(tmpm1!=NULL){ + sprintf(tmp,"%s",tmpm1->value); + } + int lpid; + map* tmpm2=getMapFromMaps(m,"lenv","usid"); + tmpm1=getMapFromMaps(m,"main","TmpPath"); + sprintf(stored_path,"%s/%s_%s.xml",tmpm1->value,service,tmpm2->value); + } + + xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp); + map* test=getMap(request,"storeExecuteResponse"); + if(test!=NULL && strcasecmp(test->value,"true")==0){ + + + fprintf(stderr,"---------URL: %s--------------\n",url); +// fprintf(stderr,"-----------------------\n"); +// //maps* m,map* request, int pid,service* serv,const char* service,int status,maps* inputs,maps* outputs +// dumpMaps(m); +// fprintf(stderr,"-----------------------\n"); +// dumpMap(request); +// fprintf(stderr,"-----------------------\n"); + + xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url); + hasStoredExecuteResponse=true; + } + + nc = xmlNewNode(ns, BAD_CAST "Process"); + map* tmp2=getMap(serv->content,"processVersion"); + if(tmp2!=NULL) + xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp2->value); + else + xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST "1"); + + map* tmpI=getMapFromMaps(m,"lenv","oIdentifier"); + printDescription(nc,ns_ows,tmpI->value,serv->content,0); + + xmlAddChild(n,nc); + + nc = xmlNewNode(ns, BAD_CAST "Status"); + const struct tm *tm; + size_t len; + time_t now; + char *tmp1; + map *tmpStatus; + + now = time ( NULL ); + tm = localtime ( &now ); + + tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char)); + + len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm ); + + xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1); + + char sMsg[2048]; + switch(status){ + case SERVICE_SUCCEEDED: + nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded"); + sprintf(sMsg,_("The service \"%s\" ran successfully."),serv->name); + nc3=xmlNewText(BAD_CAST sMsg); + xmlAddChild(nc1,nc3); + break; + case SERVICE_STARTED: + nc1 = xmlNewNode(ns, BAD_CAST "ProcessStarted"); + tmpStatus=getMapFromMaps(m,"lenv","status"); + xmlNewProp(nc1,BAD_CAST "percentCompleted",BAD_CAST tmpStatus->value); + sprintf(sMsg,_("The ZOO service \"%s\" is currently running. Please reload this document to get the up-to-date status of the service."),serv->name); + nc3=xmlNewText(BAD_CAST sMsg); + xmlAddChild(nc1,nc3); + break; + case SERVICE_ACCEPTED: + nc1 = xmlNewNode(ns, BAD_CAST "ProcessAccepted"); + sprintf(sMsg,_("The service \"%s\" was accepted by the ZOO-Kernel and is running as a background task. Please access the URL in the statusLocation attribute provided in this document to get the up-to-date status and results."),serv->name); + nc3=xmlNewText(BAD_CAST sMsg); + xmlAddChild(nc1,nc3); + break; + case SERVICE_FAILED: + nc1 = xmlNewNode(ns, BAD_CAST "ProcessFailed"); + map *errorMap; + map *te; + te=getMapFromMaps(m,"lenv","code"); + if(te!=NULL) + errorMap=createMap("code",te->value); + else + errorMap=createMap("code","NoApplicableCode"); + te=getMapFromMaps(m,"lenv","message"); + if(te!=NULL) + addToMap(errorMap,"text",_ss(te->value)); + else + addToMap(errorMap,"text",_("No more information available")); + nc3=createExceptionReportNode(m,errorMap,0); + freeMap(&errorMap); + free(errorMap); + xmlAddChild(nc1,nc3); + break; + default : + printf(_("error code not know : %i\n"),status); + //exit(1); + break; + } + xmlAddChild(nc,nc1); + xmlAddChild(n,nc); + free(tmp1); + +#ifdef DEBUG + fprintf(stderr,"printProcessResponse %d\n",__LINE__); +#endif + + map* lineage=getMap(request,"lineage"); + if(lineage!=NULL && strcasecmp(lineage->value,"true")==0){ + nc = xmlNewNode(ns, BAD_CAST "DataInputs"); + maps* mcursor=inputs; + elements* scursor=NULL; + while(mcursor!=NULL /*&& scursor!=NULL*/){ + scursor=getElements(serv->inputs,mcursor->name); + printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Input",vid); + mcursor=mcursor->next; + } + xmlAddChild(n,nc); + + nc = xmlNewNode(ns, BAD_CAST "OutputDefinitions"); + mcursor=outputs; + scursor=NULL; + while(mcursor!=NULL){ + scursor=getElements(serv->outputs,mcursor->name); + printOutputDefinitions(doc,nc,ns,ns_ows,scursor,mcursor,"Output"); + mcursor=mcursor->next; + } + xmlAddChild(n,nc); + } + } + + /** + * Display the process output only when requested ! + */ + if(status==SERVICE_SUCCEEDED){ + if(vid==0){ + nc = xmlNewNode(ns, BAD_CAST "ProcessOutputs"); + } + maps* mcursor=outputs; + elements* scursor=serv->outputs; + map* testResponse=getMap(request,"RawDataOutput"); + if(testResponse==NULL) + testResponse=getMap(request,"ResponseDocument"); + while(mcursor!=NULL){ + map* tmp0=getMap(mcursor->content,"inRequest"); + scursor=getElements(serv->outputs,mcursor->name); + if(scursor!=NULL){ + if(testResponse==NULL || tmp0==NULL){ + if(vid==0) + printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid); + else + printIOType(doc,n,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid); + } + else + if(tmp0!=NULL && strncmp(tmp0->value,"true",4)==0){ + if(vid==0) + printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid); + else + printIOType(doc,n,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid); + } + }else + /** + * In case there was no definition found in the ZCFG file but + * present in the service code + */ + if(vid==0) + printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid); + else + printIOType(doc,n,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid); + mcursor=mcursor->next; + } + if(vid==0) + xmlAddChild(n,nc); + } + if(vid==0 && + hasStoredExecuteResponse==true + && status!=SERVICE_STARTED +#ifndef WIN32 + && status!=SERVICE_ACCEPTED +#endif + ){ +#ifndef RELY_ON_DB + semid lid=acquireLock(m);//,1); + if(lid<0){ + /* If the lock failed */ + errorException(m,_("Lock failed."),"InternalError",NULL); + xmlFreeDoc(doc); + xmlCleanupParser(); + zooXmlCleanupNs(); + return; + } + else{ +#endif + /* We need to write the ExecuteResponse Document somewhere */ + FILE* output=fopen(stored_path,"w"); + if(output==NULL){ + /* If the file cannot be created return an ExceptionReport */ + char tmpMsg[1024]; + sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the ExecuteResponse."),stored_path); + + errorException(m,tmpMsg,"InternalError",NULL); + xmlFreeDoc(doc); + xmlCleanupParser(); + zooXmlCleanupNs(); +#ifndef RELY_ON_DB + unlockShm(lid); +#endif + return; + } + xmlChar *xmlbuff; + int buffersize; + xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1); + fwrite(xmlbuff,1,xmlStrlen(xmlbuff)*sizeof(char),output); + xmlFree(xmlbuff); + fclose(output); +#ifndef RELY_ON_DB +#ifdef DEBUG + fprintf(stderr,"UNLOCK %s %d !\n",__FILE__,__LINE__); +#endif + unlockShm(lid); + map* v=getMapFromMaps(m,"lenv","sid"); + // Remove the lock when running as a normal task + if(getpid()==atoi(v->value)){ + removeShmLock (m, 1); + } + } +#endif + } + + printDocument(m,doc,pid); + + xmlCleanupParser(); + zooXmlCleanupNs(); +} + +/** + * Print a XML document. + * + * @param m the conf maps containing the main.cfg settings + * @param doc the XML document + * @param pid the process identifier linked to a service + */ +void printDocument(maps* m, xmlDocPtr doc,int pid){ + char *encoding=getEncoding(m); + if(pid==getpid()){ + printHeaders(m); + printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding); + } + xmlChar *xmlbuff; + int buffersize; + /* + * Dump the document to a buffer and print it on stdout + * for demonstration purposes. + */ + xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1); + printf("%s",xmlbuff); + fflush(stdout); + /* + * Free associated memory. + */ + xmlFree(xmlbuff); + xmlFreeDoc(doc); + xmlCleanupParser(); + zooXmlCleanupNs(); +} + +/** + * Print a XML document. + * + * @param doc the XML document (unused) + * @param nc the XML node to add the output definition + * @param ns_wps the wps XML namespace + * @param ns_ows the ows XML namespace + * @param e the output elements + * @param m the conf maps containing the main.cfg settings + * @param type the type (unused) + */ +void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,const char* type){ + xmlNodePtr nc1; + nc1=xmlNewNode(ns_wps, BAD_CAST type); + map *tmp=NULL; + if(e!=NULL && e->defaults!=NULL) + tmp=e->defaults->content; + else{ + /* + dumpElements(e); + */ + return; + } + while(tmp!=NULL){ + if(strncasecmp(tmp->name,"MIMETYPE",strlen(tmp->name))==0 + || strncasecmp(tmp->name,"ENCODING",strlen(tmp->name))==0 + || strncasecmp(tmp->name,"SCHEMA",strlen(tmp->name))==0 + || strncasecmp(tmp->name,"UOM",strlen(tmp->name))==0) + xmlNewProp(nc1,BAD_CAST tmp->name,BAD_CAST tmp->value); + tmp=tmp->next; + } + tmp=getMap(e->defaults->content,"asReference"); + if(tmp==NULL) + xmlNewProp(nc1,BAD_CAST "asReference",BAD_CAST "false"); + + tmp=e->content; + + printDescription(nc1,ns_ows,m->name,e->content,0); + + xmlAddChild(nc,nc1); + +} + +/** + * Generate XML nodes describing inputs or outputs metadata. + * + * @param doc the XML document + * @param nc the XML node to add the definition + * @param ns_wps the wps namespace + * @param ns_ows the ows namespace + * @param ns_xlink the xlink namespace + * @param e the output elements + * @param m the conf maps containing the main.cfg settings + * @param type the type + */ +void printIOType(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,elements* e,maps* m,const char* type,int vid){ + xmlNodePtr nc1,nc2,nc3; + nc1=xmlNewNode(ns_wps, BAD_CAST type); + map *tmp=NULL; + if(e!=NULL) + tmp=e->content; + else + tmp=m->content; + if(vid==0){ + nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier"); + if(e!=NULL) + nc3=xmlNewText(BAD_CAST e->name); + else + nc3=xmlNewText(BAD_CAST m->name); + + xmlAddChild(nc2,nc3); + xmlAddChild(nc1,nc2); + + xmlAddChild(nc,nc1); + + if(e!=NULL) + tmp=getMap(e->content,"Title"); + else + tmp=getMap(m->content,"Title"); + + if(tmp!=NULL){ + nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name); + nc3=xmlNewText(BAD_CAST _ss(tmp->value)); + xmlAddChild(nc2,nc3); + xmlAddChild(nc1,nc2); + } + + if(e!=NULL) + tmp=getMap(e->content,"Abstract"); + else + tmp=getMap(m->content,"Abstract"); + + if(tmp!=NULL){ + nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name); + nc3=xmlNewText(BAD_CAST _ss(tmp->value)); + xmlAddChild(nc2,nc3); + xmlAddChild(nc1,nc2); + xmlAddChild(nc,nc1); + } + }else{ + xmlNewProp(nc1,BAD_CAST "id",BAD_CAST (e!=NULL?e->name:m->name)); + } + + // IO type nested outputs + if(m->child!=NULL){ + maps* curs=m->child; + elements* ecurs=getElements(e,(e!=NULL?e->name:m->name)); + ecurs=ecurs->child; + while(curs!=NULL/* && ecurs!=NULL*/){ + ecurs=getElements(ecurs,(curs->name)); + map* inRequest=getMap(curs->content,"inRequest"); + if(inRequest!=NULL && strncasecmp(inRequest->value,"true",4)==0) + printIOType(doc,nc1,ns_wps,ns_ows,ns_xlink,ecurs,curs,type,vid); + curs=curs->next; + ecurs=getElements(e,(e!=NULL?e->name:m->name)); + ecurs=ecurs->child; + } + } + else{ + map *tmpMap=getMap(m->content,"Reference"); + if(tmpMap==NULL){ + nc2=xmlNewNode(ns_wps, BAD_CAST "Data"); + if(e!=NULL && e->format!=NULL){ + if (strncasecmp(e->format, "LiteralOutput", strlen(e->format)) == 0) + nc3 = xmlNewNode(ns_wps, BAD_CAST "LiteralData"); + else + if(strncasecmp(e->format,"ComplexOutput",strlen(e->format))==0) + nc3=xmlNewNode(ns_wps, BAD_CAST "ComplexData"); + else if(strncasecmp(e->format,"BoundingBoxOutput",strlen(e->format))==0) + nc3=xmlNewNode(ns_wps, BAD_CAST "BoundingBoxData"); + else + nc3=xmlNewNode(ns_wps, BAD_CAST e->format); + } + else { + map* tmpV=getMapFromMaps(m,"format","value"); + if(tmpV!=NULL) + nc3=xmlNewNode(ns_wps, BAD_CAST tmpV->value); + else + nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData"); + } + tmp=m->content; + + while(tmp!=NULL){ + if(strcasecmp(tmp->name,"mimeType")==0 || + strcasecmp(tmp->name,"encoding")==0 || + strcasecmp(tmp->name,"schema")==0 || + strcasecmp(tmp->name,"datatype")==0 || + strcasecmp(tmp->name,"uom")==0) { + if(vid==0) + xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value); + else{ + if(strcasecmp(tmp->name,"datatype")==0) + xmlNewProp(nc2,BAD_CAST "mimeType",BAD_CAST "text/plain"); + else + if(strcasecmp(tmp->name,"uom")!=0) + xmlNewProp(nc2,BAD_CAST tmp->name,BAD_CAST tmp->value); + } + } + + if(vid==0) + xmlAddChild(nc2,nc3); + tmp=tmp->next; + } + if(e!=NULL && e->format!=NULL && strcasecmp(e->format,"BoundingBoxData")==0) { + map* bb=getMap(m->content,"value"); + if(bb!=NULL) { + map* tmpRes=parseBoundingBox(bb->value); + printBoundingBox(ns_ows,nc3,tmpRes); + freeMap(&tmpRes); + free(tmpRes); + } + } + else { + //if (e != NULL) { + if (e != NULL && e->defaults != NULL) { // knut: add extra NULL pointer check in case user omits block in config file + tmp = getMap(e->defaults->content, "mimeType"); + } + else + tmp=NULL; + map* tmp1=getMap(m->content,"encoding"); + map* tmp2=getMap(m->content,"mimeType"); + map* tmp3=getMap(m->content,"value"); + int hasValue=1; + if(tmp3==NULL){ + tmp3=createMap("value",""); + hasValue=-1; + } + + if( ( tmp1 != NULL && strncmp(tmp1->value,"base64",6) == 0 ) // if encoding is base64 + || // or if + ( tmp2 != NULL && ( strstr(tmp2->value,"text") == NULL // mime type is not text + && // nor + strstr(tmp2->value,"xml") == NULL // xml + && // nor + strstr(tmp2->value,"javascript") == NULL // javascript + && + strstr(tmp2->value,"json") == NULL + && + strstr(tmp2->value,"ecmascript") == NULL + && + // include for backwards compatibility, + // although correct mime type is ...kml+xml: + strstr(tmp2->value,"google-earth.kml") == NULL ) + ) + ) { // then + map* rs=getMap(m->content,"size"); // obtain size + bool isSized=true; + if(rs==NULL){ + char tmp1[1024]; + sprintf(tmp1,"%ld",strlen(tmp3->value)); + rs=createMap("size",tmp1); + isSized=false; + } + + xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST base64(tmp3->value, atoi(rs->value)))); // base 64 encode in XML + + if(tmp1==NULL || (tmp1!=NULL && strncmp(tmp1->value,"base64",6)!=0)) { + xmlAttrPtr ap = xmlHasProp((vid==0?nc3:nc2), BAD_CAST "encoding"); + if (ap != NULL) { + xmlRemoveProp(ap); + } + xmlNewProp((vid==0?nc3:nc2),BAD_CAST "encoding",BAD_CAST "base64"); + } + + if(!isSized){ + freeMap(&rs); + free(rs); + } + } + else if (tmp2!=NULL) { // else (text-based format) + if(strstr(tmp2->value, "javascript") != NULL || // if javascript put code in CDATA block + strstr(tmp2->value, "json") != NULL || // (will not be parsed by XML reader) + strstr(tmp2->value, "ecmascript") != NULL + ) { + xmlAddChild((vid==0?nc3:nc2),xmlNewCDataBlock(doc,BAD_CAST tmp3->value,strlen(tmp3->value))); + } + else { // else + if (strstr(tmp2->value, "xml") != NULL || // if XML-based format + // include for backwards compatibility, + // although correct mime type is ...kml+xml: + strstr(tmp2->value, "google-earth.kml") != NULL + ) { + + int li=zooXmlAddDoc(tmp3->value); + xmlDocPtr doc = iDocs[li]; + xmlNodePtr ir = xmlDocGetRootElement(doc); + xmlAddChild((vid==0?nc3:nc2),ir); + } + else // else + xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST tmp3->value)); // add text node + } + xmlAddChild(nc2,nc3); + } + else { + xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST tmp3->value)); + } + + if(hasValue<0) { + freeMap(&tmp3); + free(tmp3); + } + } + } + else { // Reference + tmpMap=getMap(m->content,"Reference"); + nc3=nc2=xmlNewNode(ns_wps, BAD_CAST "Reference"); + /* Special case to avoid failing to validate against the WPS 2.0 schema */ + if(strcasecmp(type,"Output")==0 && vid==0) + xmlNewProp(nc3,BAD_CAST "href",BAD_CAST tmpMap->value); + else + xmlNewNsProp(nc3,ns_xlink,BAD_CAST "href",BAD_CAST tmpMap->value); + + tmp=m->content; + while(tmp!=NULL) { + if(strcasecmp(tmp->name,"mimeType")==0 || + strcasecmp(tmp->name,"encoding")==0 || + strcasecmp(tmp->name,"schema")==0 || + strcasecmp(tmp->name,"datatype")==0 || + strcasecmp(tmp->name,"uom")==0){ + + if(strcasecmp(tmp->name,"datatype")==0) + xmlNewProp(nc3,BAD_CAST "mimeType",BAD_CAST "text/plain"); + else + xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value); + } + tmp=tmp->next; + xmlAddChild(nc2,nc3); + } + } + xmlAddChild(nc1,nc2); + } + xmlAddChild(nc,nc1); +} + +/** + * Create XML node with basic ows metadata information (Identifier,Title,Abstract) + * + * @param root the root XML node to add the description + * @param ns_ows the ows XML namespace + * @param identifier the identifier to use + * @param amap the map containing the ows metadata information + */ +void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map* amap,int vid=0){ + xmlNodePtr nc2; + if(vid==0){ + nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier"); + xmlAddChild(nc2,xmlNewText(BAD_CAST identifier)); + xmlAddChild(root,nc2); + } + map* tmp=amap; + const char *tmp2[2]; + tmp2[0]="Title"; + tmp2[1]="Abstract"; + int j=0; + for(j=0;j<2;j++){ + map* tmp1=getMap(tmp,tmp2[j]); + if(tmp1!=NULL){ + nc2 = xmlNewNode(ns_ows, BAD_CAST tmp2[j]); + xmlAddChild(nc2,xmlNewText(BAD_CAST _ss(tmp1->value))); + xmlAddChild(root,nc2); + } + } + if(vid==1){ + nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier"); + xmlAddChild(nc2,xmlNewText(BAD_CAST identifier)); + xmlAddChild(root,nc2); + } +} + +/** + * Print an OWS ExceptionReport Document and HTTP headers (when required) + * depending on the code. + * Set hasPrinted value to true in the [lenv] section. + * + * @param m the maps containing the settings of the main.cfg file + * @param s the map containing the text,code,locator keys (or a map array of the same keys) + */ +void printExceptionReportResponse(maps* m,map* s){ + if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL) + return; + int buffersize; + xmlDocPtr doc; + xmlChar *xmlbuff; + xmlNodePtr n; + + zooXmlCleanupNs(); + doc = xmlNewDoc(BAD_CAST "1.0"); + maps* tmpMap=getMaps(m,"main"); + char *encoding=getEncoding(tmpMap); + const char *exceptionCode; + + map* tmp=getMap(s,"code"); + if(tmp!=NULL){ + if(strcmp(tmp->value,"OperationNotSupported")==0 || + strcmp(tmp->value,"NoApplicableCode")==0) + exceptionCode="501 Not Implemented"; + else + //rdr/* + if(strcmp(tmp->value,"MissingParameterValue")==0){ + exceptionCode="404 Not Found"; + } + //rdr*/ + else + if(strcmp(tmp->value,"InvalidUpdateSequence")==0 || + strcmp(tmp->value,"OptionNotSupported")==0 || + strcmp(tmp->value,"VersionNegotiationFailed")==0 || + strcmp(tmp->value,"InvalidParameterValue")==0) + exceptionCode="400 Bad request"; + else + exceptionCode="501 Internal Server Error"; + } + else + exceptionCode="501 Internal Server Error"; + tmp=getMapFromMaps(m,"lenv","status_code"); + if(tmp!=NULL) + exceptionCode=tmp->value; + if(m!=NULL){ + map *tmpSid=getMapFromMaps(m,"lenv","sid"); + if(tmpSid!=NULL){ + if( getpid()==atoi(tmpSid->value) ){ + printHeaders(m); + printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode); + } + } + else{ + printHeaders(m); + printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode); + } + }else{ + printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode); + } + n=createExceptionReportNode(m,s,1); + xmlDocSetRootElement(doc, n); + xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1); + printf("%s",xmlbuff); + fflush(stdout); + xmlFreeDoc(doc); + xmlFree(xmlbuff); + xmlCleanupParser(); + zooXmlCleanupNs(); + if(m!=NULL) + setMapInMaps(m,"lenv","hasPrinted","true"); +} + +/** + * Create an OWS ExceptionReport Node. + * + * @param m the conf maps + * @param s the map containing the text,code,locator keys + * @param use_ns (0/1) choose if you want to generate an ExceptionReport or + * ows:ExceptionReport node respectively + * @return the ExceptionReport/ows:ExceptionReport node + */ +xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){ + + xmlNsPtr ns,ns_xsi; + xmlNodePtr n,nc,nc1; + + int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows"); + ns=usedNs[nsid]; + if(use_ns==0){ + ns=NULL; + } + n = xmlNewNode(ns, BAD_CAST "ExceptionReport"); + map* version=getMapFromMaps(m,"main","rversion"); + int vid=-1; + if(version!=NULL) + vid=getVersionId(version->value); + if(vid<0) + vid=0; + if(use_ns==1){ + xmlNewNs(n,BAD_CAST schemas[vid][1],BAD_CAST"ows"); + int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi"); + ns_xsi=usedNs[xsiId]; + char tmp[1024]; + sprintf(tmp,"%s %s",schemas[vid][1],schemas[vid][5]); + xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST tmp); + } + + + addLangAttr(n,m); + xmlNewProp(n,BAD_CAST "version",BAD_CAST schemas[vid][6]); + + int length=1; + int cnt=0; + map* len=getMap(s,"length"); + if(len!=NULL) + length=atoi(len->value); + for(cnt=0;cntvalue); + else + xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode"); + + tmp=getMapArray(s,"locator",cnt); + if(tmp==NULL) + tmp=getMap(s,"locator"); + if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0) + xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value); + + tmp=getMapArray(s,"text",cnt); + if(tmp==NULL) + tmp=getMapArray(s,"message",cnt); + nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText"); + if(tmp!=NULL){ + xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value); + xmlAddChild(nc1,txt); + if(cnt==0) + setMapInMaps(m,"lenv","message",tmp->value); + } + else{ + xmlNodeSetContent(nc1, BAD_CAST _("No debug message available")); + } + xmlAddChild(nc,nc1); + xmlAddChild(n,nc); + } + return n; +} + +/** + * Print an OWS ExceptionReport. + * + * @param m the conf maps + * @param message the error message + * @param errorcode the error code + * @param locator the potential locator + */ +int errorException(maps *m, const char *message, const char *errorcode, const char *locator) +{ + map* errormap = createMap("text", message); + addToMap(errormap,"code", errorcode); + if(locator!=NULL) + addToMap(errormap,"locator", locator); + else + addToMap(errormap,"locator", "NULL"); + printExceptionReportResponse(m,errormap); + freeMap(&errormap); + free(errormap); + return -1; +} + +/** + * Generate the output response (RawDataOutput or ResponseDocument) + * + * @param s the service structure containing the metadata information + * @param request_inputs the inputs provided to the service for execution + * @param request_outputs the outputs updated by the service execution + * @param request_inputs1 the map containing the HTTP request + * @param cpid the process identifier attached to a service execution + * @param m the conf maps containing the main.cfg settings + * @param res the value returned by the service execution + */ +void outputResponse(service* s,maps* request_inputs,maps* request_outputs, + map* request_inputs1,int cpid,maps* m,int res){ +#ifdef DEBUG + dumpMaps(request_inputs); + dumpMaps(request_outputs); + fprintf(stderr,"printProcessResponse\n"); +#endif + map* toto=getMap(request_inputs1,"RawDataOutput"); + int asRaw=0; + if(toto!=NULL) + asRaw=1; + map* version=getMapFromMaps(m,"main","rversion"); + int vid=getVersionId(version->value); + maps* tmpSess=getMaps(m,"senv"); + if(tmpSess!=NULL){ + map *_tmp=getMapFromMaps(m,"lenv","cookie"); + maps *tmps=getMaps(m,"senv"); + char* sessId=NULL; + if(_tmp!=NULL){ + printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value); + map *_tmp1=getMapFromMaps(m,"senv","ecookie_length"); + if(_tmp1!=NULL){ + int len=atoi(_tmp1->value); + int cnt=0; + for(cnt=0;cntcontent,"ecookie",cnt); + if(_tmp2!=NULL) + printf("Set-Cookie: %s; HttpOnly\r\n",_tmp2->value); + } + } + printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n"); + char session_file_path[100]; + char *tmp1=strtok(_tmp->value,";"); + if(tmp1!=NULL) + sprintf(session_file_path,"%s",strstr(tmp1,"=")+1); + else + sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1); + sessId=zStrdup(session_file_path); + }else{ + maps* t=getMaps(m,"senv"); + map*p=t->content; + while(p!=NULL){ + if(strstr(p->name,"ID")!=NULL){ + sessId=zStrdup(p->value); + break; + } + p=p->next; + } + } + char session_file_path[1024]; + map *tmpPath=getMapFromMaps(m,"main","sessPath"); + if(tmpPath==NULL) + tmpPath=getMapFromMaps(m,"main","tmpPath"); + sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId); + FILE* teste=fopen(session_file_path,"w"); + if(teste==NULL){ + char tmpMsg[1024]; + sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the session maps."),session_file_path); + errorException(m,tmpMsg,"InternalError",NULL); + return; + } + else{ + fclose(teste); + dumpMapsToFile(tmpSess,session_file_path,1); + } + } + if(res==SERVICE_FAILED){ + map *lenv; + lenv=getMapFromMaps(m,"lenv","message"); + char *tmp0; + if(lenv!=NULL){ + tmp0=(char*)malloc((strlen(lenv->value)+strlen(_("Unable to run the Service. The message returned back by the Service was the following: "))+1)*sizeof(char)); + sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value); + } + else{ + tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char)); + sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service.")); + } + errorException(m,tmp0,"InternalError",NULL); + free(tmp0); + return; + } + + if(res==SERVICE_ACCEPTED && vid==1){ + map* statusInfo=createMap("Status","Accepted"); + map *usid=getMapFromMaps(m,"lenv","usid"); + addToMap(statusInfo,"JobID",usid->value); + printStatusInfo(m,statusInfo,(char*)"Execute"); + freeMap(&statusInfo); + free(statusInfo); + return; + } + + if(res!=SERVICE_SUCCEEDED){ + printProcessResponse(m,request_inputs1,cpid, + s, s->name,res, // replace serviceProvider with serviceName in stored response file name + request_inputs, + request_outputs); + return; + } + + map *tmp1=getMapFromMaps(m,"main","tmpPath"); + if(asRaw==0){ +#ifdef DEBUG + fprintf(stderr,"REQUEST_OUTPUTS FINAL\n"); + dumpMaps(request_outputs); +#endif + maps* tmpI=request_outputs; + maps* stmpI=NULL; + map* usid=getMapFromMaps(m,"lenv","usid"); + int itn=0; + int error=-1; + NESTED0: + while(tmpI!=NULL){ + if(tmpI->child!=NULL){ + stmpI=tmpI; + tmpI=tmpI->child; + } +#ifdef USE_MS + map* testMap=getMap(tmpI->content,"useMapserver"); +#endif + map *gfile=getMap(tmpI->content,"generated_file"); + char *file_name=NULL; + if(gfile!=NULL){ + gfile=getMap(tmpI->content,"expected_generated_file"); + if(gfile==NULL){ + gfile=getMap(tmpI->content,"generated_file"); + } + readGeneratedFile(m,tmpI->content,gfile->value); + file_name=zStrdup((gfile->value)+strlen(tmp1->value)); + } + toto=getMap(tmpI->content,"asReference"); +#ifdef USE_MS + map* geodatatype=getMap(tmpI->content,"geodatatype"); + if(toto!=NULL && strcasecmp(toto->value,"true")==0 && + (testMap==NULL || + strncasecmp(testMap->value,"true",4)!=0 || + (geodatatype!=NULL && strcasecmp(geodatatype->value,"other")==0) ) ) +#else + if(toto!=NULL && strcasecmp(toto->value,"true")==0) +#endif + { + elements* in=getElements(s->outputs,tmpI->name); + if(in==NULL && s->outputs->child!=NULL){ + in=getElements(s->outputs->child,tmpI->name); + } + char *format=NULL; + if(in!=NULL && in->format!=NULL){ + format=in->format; + }else + format=(char*)"LiteralData"; + if(format!=NULL && strcasecmp(format,"BoundingBoxData")==0){ + addToMap(tmpI->content,"extension","xml"); + addToMap(tmpI->content,"mimeType","text/xml"); + addToMap(tmpI->content,"encoding","UTF-8"); + addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd"); + } + char *file_path=NULL; + if(gfile==NULL) { + map *ext=getMap(tmpI->content,"extension"); + char file_ext[32]; + + if( ext != NULL && ext->value != NULL) { + strncpy(file_ext, ext->value, 32); + } + else { + // Obtain default file extension (see mimetypes.h). + // If the MIME type is not recognized, txt is used as the default extension + map* mtype=getMap(tmpI->content,"mimeType"); + getFileExtension(mtype != NULL ? mtype->value : NULL, file_ext, 32); + } + if(file_name!=NULL) + free(file_name); + file_name=(char*)malloc((strlen(s->name)+strlen(usid->value)+strlen(file_ext)+strlen(tmpI->name)+45)*sizeof(char)); + sprintf(file_name,"ZOO_DATA_%s_%s_%s_%d.%s",s->name,tmpI->name,usid->value,itn,file_ext); + itn++; + file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char)); + sprintf(file_path,"%s/%s",tmp1->value,file_name); + + FILE *ofile=fopen(file_path,"wb"); + if(ofile==NULL){ + char tmpMsg[1024]; + sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the %s final result."),file_name,tmpI->name); + errorException(m,tmpMsg,"InternalError",NULL); + free(file_name); + free(file_path); + return; + } + + toto=getMap(tmpI->content,"value"); + if(toto==NULL){ + char tmpMsg[1024]; + sprintf(tmpMsg,_("No value found for the requested output %s."),tmpI->name); + errorException(m,tmpMsg,"InternalError",NULL); + fclose(ofile); + free(file_name); + free(file_path); + return; + } + if(strcasecmp(format,"BoundingBoxData")!=0){ + map* size=getMap(tmpI->content,"size"); + if(size!=NULL && toto!=NULL) + fwrite(toto->value,1,(atoi(size->value))*sizeof(char),ofile); + else + if(toto!=NULL && toto->value!=NULL) + fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile); + }else{ + printBoundingBoxDocument(m,tmpI,ofile); + } + fclose(ofile); + } + + map *tmp2=getMapFromMaps(m,"main","tmpUrl"); + map *tmp3=getMapFromMaps(m,"main","serverAddress"); + char *file_url=NULL; + if(strncasecmp(tmp2->value,"http://",7)==0 || + strncasecmp(tmp2->value,"https://",8)==0){ + file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char)); + sprintf(file_url,"%s/%s",tmp2->value,file_name); + }else{ + file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char)); + sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name); + } + addToMap(tmpI->content,"Reference",file_url); + if(file_name!=NULL) + free(file_name); + if(file_url!=NULL) + free(file_url); + file_name=NULL; + } +#ifdef USE_MS + else{ + if(testMap!=NULL){ + map* nbFeatures; + setMapInMaps(m,"lenv","state","out"); + setReferenceUrl(m,tmpI); + nbFeatures=getMap(tmpI->content,"nb_features"); + geodatatype=getMap(tmpI->content,"geodatatype"); + if((nbFeatures!=NULL && atoi(nbFeatures->value)==0) || + (geodatatype!=NULL && strcasecmp(geodatatype->value,"other")==0)){ + error=1; + res=SERVICE_FAILED; + } + } + } +#endif + if(file_name!=NULL){ + free(file_name); + file_name=NULL; + } + tmpI=tmpI->next; + } + if(stmpI!=NULL){ + tmpI=stmpI->next; + stmpI=NULL; + if(tmpI!=NULL) + goto NESTED0; + } +#ifdef DEBUG + fprintf(stderr,"SERVICE : %s\n",s->name); + dumpMaps(m); +#endif + if(error<0) + printProcessResponse(m,request_inputs1,cpid, + s, s->name,res, // replace serviceProvider with serviceName in stored response file name + request_inputs, + request_outputs); + else{ + maps* tmpMaps=getMaps(m,"lenv"); +#ifdef USE_CALLBACK + invokeCallback(m,NULL,NULL,7,0); +#endif + printExceptionReportResponse(m,tmpMaps->content); + } + } + else{ + /** + * We get the requested output or fallback to the first one if the + * requested one is not present in the resulting outputs maps. + */ + maps* tmpI=NULL; + map* tmpIV=getMap(request_inputs1,"RawDataOutput"); + if(tmpIV!=NULL){ + tmpI=getMaps(request_outputs,tmpIV->value); + } + if(tmpI==NULL) + tmpI=request_outputs; + + elements* e=getElements(s->outputs,tmpI->name); + if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){ + printBoundingBoxDocument(m,tmpI,NULL); + }else{ + map *gfile=getMap(tmpI->content,"generated_file"); + if(gfile!=NULL){ + gfile=getMap(tmpI->content,"expected_generated_file"); + if(gfile==NULL){ + gfile=getMap(tmpI->content,"generated_file"); + } + readGeneratedFile(m,tmpI->content,gfile->value); + } + toto=getMap(tmpI->content,"value"); + if(toto==NULL){ + char tmpMsg[1024]; + sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),tmpI->name); + errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput"); + return; + } + map* fname=getMapFromMaps(tmpI,tmpI->name,"filename"); + if(fname!=NULL) + printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value); + map* rs=getMapFromMaps(tmpI,tmpI->name,"size"); + if(rs!=NULL) + printf("Content-Length: %s\r\n",rs->value); + printHeaders(m); + char mime[1024]; + map* mi=getMap(tmpI->content,"mimeType"); +#ifdef DEBUG + fprintf(stderr,"SERVICE OUTPUTS\n"); + dumpMaps(request_outputs); + fprintf(stderr,"SERVICE OUTPUTS\n"); +#endif + map* en=getMap(tmpI->content,"encoding"); + if(mi!=NULL && en!=NULL) + sprintf(mime, + "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n", + mi->value,en->value); + else + if(mi!=NULL) + sprintf(mime, + "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n", + mi->value); + else + sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n"); + printf("%s",mime); + if(rs!=NULL) + fwrite(toto->value,1,atoi(rs->value),stdout); + else + fwrite(toto->value,1,strlen(toto->value),stdout); +#ifdef DEBUG + dumpMap(toto); +#endif + } + } +} + +/** + * Create required XML nodes for boundingbox and update the current XML node + * + * @param ns_ows the ows XML namespace + * @param n the XML node to update + * @param boundingbox the map containing the boundingbox definition + */ +void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){ + + xmlNodePtr lw=NULL,uc=NULL; + + map* tmp=getMap(boundingbox,"value"); + + tmp=getMap(boundingbox,"lowerCorner"); + if(tmp!=NULL){ + lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner"); + xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value)); + } + + tmp=getMap(boundingbox,"upperCorner"); + if(tmp!=NULL){ + uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner"); + xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value)); + } + + tmp=getMap(boundingbox,"crs"); + if(tmp!=NULL) + xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value); + + tmp=getMap(boundingbox,"dimensions"); + if(tmp!=NULL) + xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value); + + xmlAddChild(n,lw); + xmlAddChild(n,uc); + +} + +/** + * Parse a BoundingBox string + * + * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040): + * 10.2 Bounding box + * + * + * Value is provided as : lowerCorner,upperCorner,crs,dimension + * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84 + * + * A map to store boundingbox information should contain: + * - lowerCorner : double,double (minimum within this bounding box) + * - upperCorner : double,double (maximum within this bounding box) + * - crs : URI (Reference to definition of the CRS) + * - dimensions : int + * + * Note : support only 2D bounding box. + * + * @param value the char* containing the KVP bouding box + * @return a map containing all the bounding box keys + */ +map* parseBoundingBox(const char* value){ + map *res=NULL; + if(value!=NULL){ + char *cv,*cvp; + cv=strtok_r((char*) value,",",&cvp); + int cnt=0; + int icnt=0; + char *currentValue=NULL; + while(cv){ + if(cnt<2) + if(currentValue!=NULL){ + char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char)); + sprintf(finalValue,"%s%s",currentValue,cv); + switch(cnt){ + case 0: + res=createMap("lowerCorner",finalValue); + break; + case 1: + addToMap(res,"upperCorner",finalValue); + icnt=-1; + break; + } + cnt++; + free(currentValue); + currentValue=NULL; + free(finalValue); + } + else{ + currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char)); + sprintf(currentValue,"%s ",cv); + } + else + if(cnt==2){ + addToMap(res,"crs",cv); + cnt++; + } + else + addToMap(res,"dimensions",cv); + icnt++; + cv=strtok_r(NULL,",",&cvp); + } + } + return res; +} + +/** + * Print an ows:BoundingBox XML document + * + * @param m the maps containing the settings of the main.cfg file + * @param boundingbox the maps containing the boundingbox definition + * @param file the file to print the BoundingBox (if NULL then print on stdout) + * @see parseBoundingBox, printBoundingBox + */ +void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){ + if(file==NULL) + rewind(stdout); + xmlNodePtr n; + xmlDocPtr doc; + xmlNsPtr ns_ows,ns_xsi; + xmlChar *xmlbuff; + int buffersize; + char *encoding=getEncoding(m); + map *tmp; + if(file==NULL){ + int pid=0; + tmp=getMapFromMaps(m,"lenv","sid"); + if(tmp!=NULL) + pid=atoi(tmp->value); + if(pid==getpid()){ + printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding); + } + fflush(stdout); + } + + doc = xmlNewDoc(BAD_CAST "1.0"); + int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows"); + ns_ows=usedNs[owsId]; + n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox"); + xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows"); + int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi"); + ns_xsi=usedNs[xsiId]; + xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd"); + map *tmp1=getMap(boundingbox->content,"value"); + tmp=parseBoundingBox(tmp1->value); + printBoundingBox(ns_ows,n,tmp); + xmlDocSetRootElement(doc, n); + + xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1); + if(file==NULL) + printf("%s",xmlbuff); + else{ + fprintf(file,"%s",xmlbuff); + } + + if(tmp!=NULL){ + freeMap(&tmp); + free(tmp); + } + xmlFree(xmlbuff); + xmlFreeDoc(doc); + xmlCleanupParser(); + zooXmlCleanupNs(); + +} + +/** + * Print a StatusInfo XML document. + * a statusInfo map should contain the following keys: + * * JobID corresponding to usid key from the lenv section + * * Status the current state (Succeeded,Failed,Accepted,Running) + * * PercentCompleted (optional) the percent completed + * * Message (optional) any messages the service may wish to share + * + * @param conf the maps containing the settings of the main.cfg file + * @param statusInfo the map containing the statusInfo definition + * @param req the WPS requests (GetResult, GetStatus or Dismiss) + */ +void printStatusInfo(maps* conf,map* statusInfo,char* req){ + rewind(stdout); + xmlNodePtr n,n1; + xmlDocPtr doc; + xmlNsPtr ns; + xmlChar *xmlbuff; + int buffersize; + char *encoding=getEncoding(conf); + map *tmp; + int pid=0; + printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding); + + map* version=getMapFromMaps(conf,"main","rversion"); + int vid=getVersionId(version->value); + + doc = xmlNewDoc(BAD_CAST "1.0"); + n1=printWPSHeader(doc,conf,req,"StatusInfo",version->value,1); + + map* val=getMap(statusInfo,"JobID"); + int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps"); + ns=usedNs[wpsId]; + n = xmlNewNode(ns, BAD_CAST "JobID"); + xmlAddChild(n,xmlNewText(BAD_CAST val->value)); + + xmlAddChild(n1,n); + + val=getMap(statusInfo,"Status"); + n = xmlNewNode(ns, BAD_CAST "Status"); + xmlAddChild(n,xmlNewText(BAD_CAST val->value)); + + xmlAddChild(n1,n); + + if(strncasecmp(val->value,"Failed",6)!=0 && + strncasecmp(val->value,"Succeeded",9)!=0){ + val=getMap(statusInfo,"PercentCompleted"); + if(val!=NULL){ + n = xmlNewNode(ns, BAD_CAST "PercentCompleted"); + xmlAddChild(n,xmlNewText(BAD_CAST val->value)); + xmlAddChild(n1,n); + } + + val=getMap(statusInfo,"Message"); + if(val!=NULL){ + xmlAddChild(n1,xmlNewComment(BAD_CAST val->value)); + } + } + xmlDocSetRootElement(doc, n1); + + xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1); + printf("%s",xmlbuff); + + xmlFree(xmlbuff); + xmlFreeDoc(doc); + xmlCleanupParser(); + zooXmlCleanupNs(); + +} + diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/service_json.c b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/service_json.c new file mode 100644 index 00000000..bcac4056 --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/service_json.c @@ -0,0 +1,1910 @@ +/* + * Author : Gérald FENOY + * + * Copyright 2017-2019 GeoLabs SARL. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "service_json.h" +#include "json.h" +#include +#include "json_tokener.h" +#include "stdlib.h" +#include "mimetypes.h" +#include "server_internal.h" +#include "service_internal.h" +#include + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + /** + * Equivalent range keywords for WPS version 1 and 2 + */ + const char* rangeCorrespondances[4][2]={ + { "rangeMin", "minimumValue" }, + { "rangeMax", "maximumValue"}, + { "rangeSpacing", "spacing" }, + { "rangeClosure", "rangeClosure" } + }; + + + /** + * Convert a map to a json object + * @param myMap the map to be converted into json object + * @return a json_object pointer to the created json_object + */ + json_object* mapToJson(map* myMap){ + json_object *res=json_object_new_object(); + map* cursor=myMap; + map* sizeMap=getMap(myMap,"size"); + map* length=getMap(myMap,"length"); + while(cursor!=NULL){ + json_object *val=NULL; + if(length==NULL && sizeMap==NULL) + val=json_object_new_string(cursor->value); + else{ + if(length==NULL && sizeMap!=NULL){ + if(strncasecmp(cursor->name,"value",5)==0) + val=json_object_new_string_len(cursor->value,atoi(sizeMap->value)); + else + val=json_object_new_string(cursor->value); + } + else{ + // In other case we should consider array with potential sizes + int limit=atoi(length->value); + int i=0; + val=json_object_new_array(); + for(i=0;iname,"value",5)==0){ + json_object_array_add(val,json_object_new_string_len(cursor->value,atoi(sizeMap->value))); + }else{ + json_object_array_add(val,json_object_new_string(cursor->value)); + } + } + } + } + if(val!=NULL) + json_object_object_add(res,cursor->name,val); + cursor=cursor->next; + } + return res; + } + + /** + * Convert a maps to a json object + * @param myMap the maps to be converted into json object + * @return a json_object pointer to the created json_object + */ + json_object* mapsToJson(maps* myMap){ + json_object *res=json_object_new_object(); + maps* cursor=myMap; + while(cursor!=NULL){ + json_object *obj=NULL; + if(cursor->content!=NULL){ + obj=mapToJson(cursor->content); + }else + obj=json_object_new_object(); + if(cursor->child!=NULL){ + json_object *child=NULL; + child=mapsToJson(cursor->child); + json_object_object_add(obj,"child",child); + } + json_object_object_add(res,cursor->name,obj); + cursor=cursor->next; + } + return res; + } + + /** + * Convert an elements to a json object + * @param myElements the elements pointer to be converted into a json object + * @return a json_object pointer to the created json_object + */ + json_object* elementsToJson(elements* myElements){ + json_object *res=json_object_new_object(); + elements* cur=myElements; + while(cur!=NULL){ + json_object *cres=json_object_new_object(); + json_object_object_add(cres,"content",mapToJson(cur->content)); + json_object_object_add(cres,"metadata",mapToJson(cur->metadata)); + json_object_object_add(cres,"additional_parameters",mapToJson(cur->additional_parameters)); + if(cur->format!=NULL){ + json_object_object_add(cres,"format",json_object_new_string(cur->format)); + } + if(cur->child==NULL){ + if(cur->defaults!=NULL) + json_object_object_add(cres,"defaults",mapToJson(cur->defaults->content)); + else + json_object_object_add(cres,"defaults",mapToJson(NULL)); + iotype* scur=cur->supported; + json_object *resi=json_object_new_array(); + while(scur!=NULL){ + json_object_array_add(resi,mapToJson(scur->content)); + scur=scur->next; + } + json_object_object_add(cres,"supported",resi); + } + + json_object_object_add(cres,"child",elementsToJson(cur->child)); + + json_object_object_add(res,cur->name,cres); + cur=cur->next; + } + return res; + } + + /** + * Convert an service to a json object + * @param myService the service pointer to be converted into a json object + * @return a json_object pointer to the created json_object + */ + json_object* serviceToJson(service* myService){ + json_object *res=json_object_new_object(); + json_object_object_add(res,"name",json_object_new_string(myService->name)); + json_object_object_add(res,"content",mapToJson(myService->content)); + json_object_object_add(res,"metadata",mapToJson(myService->metadata)); + json_object_object_add(res,"additional_parameters",mapToJson(myService->additional_parameters)); + json_object_object_add(res,"inputs",elementsToJson(myService->inputs)); + json_object_object_add(res,"outputs",elementsToJson(myService->outputs)); + return res; + } + + /** + * Add Allowed Range properties to a json_object + * @param m the main configuration maps pointer + * @param iot the iotype pointer + * @param prop the json_object pointer to add the allowed range properties + * @return a json_object pointer to the created json_object + */ + void printAllowedRangesJ(maps* m,iotype* iot,json_object* prop){ + map* tmpMap1; + json_object* prop4=json_object_new_object(); + for(int i=0;i<4;i++){ + tmpMap1=getMap(iot->content,rangeCorrespondances[i][0]); + if(tmpMap1!=NULL){ + if(i<3) + json_object_object_add(prop4,rangeCorrespondances[i][1],json_object_new_string(tmpMap1->value)); + else{ + char* currentValue=NULL; + int limit=strlen(tmpMap1->value); + for(int j=0;jvalue[j]=='o'){ + tmpS="open"; + } + if(currentValue==NULL){ + currentValue=(char*)malloc((strlen(tmpS)+1)*sizeof(char)); + sprintf(currentValue,"%s",tmpS); + }else{ + char* tmpS1=zStrdup(currentValue); + currentValue=(char*)realloc(currentValue,(strlen(tmpS1)+strlen(tmpS)+2)*sizeof(char)); + sprintf(currentValue,"%s-%s",tmpS1,tmpS); + } + } + json_object_object_add(prop4,rangeCorrespondances[i][1],json_object_new_string(currentValue)); + } + } + } + json_object_array_add(prop,prop4); + } + + /** + * Add literalDataDomains property to a json_object + * @param m the main configuration maps pointer + * @param in the elements pointer + * @param input the json_object pointer to add the literalDataDomains property + * @return a json_object pointer to the created json_object + */ + void printLiteralDataJ(maps* m,elements* in,json_object* input){ + json_object* prop0=json_object_new_array(); + json_object* prop1=json_object_new_object(); + json_object* prop2=json_object_new_object(); + if(in->defaults!=NULL){ + map* tmpMap1=getMap(in->defaults->content,"DataType"); + if(tmpMap1!=NULL){ + json_object_object_add(prop2,"name",json_object_new_string(tmpMap1->value)); + json_object_object_add(prop1,"dataType",prop2); + } + tmpMap1=getMap(in->defaults->content,"value"); + if(tmpMap1!=NULL) + json_object_object_add(prop1,"defaultValue",json_object_new_string(tmpMap1->value)); + json_object* prop3=json_object_new_object(); + tmpMap1=getMap(in->defaults->content,"rangeMin"); + if(tmpMap1!=NULL){ + json_object* prop5=json_object_new_array(); + printAllowedRangesJ(m,in->defaults,prop5); + if(in->supported!=NULL){ + iotype* iot=in->supported; + while(iot!=NULL){ + printAllowedRangesJ(m,iot,prop5); + iot=iot->next; + } + } + json_object_object_add(prop3,"allowedRanges",prop5); + } + else{ + tmpMap1=getMap(in->defaults->content,"range"); + if(tmpMap1!=NULL){ + // TODO: parse range = [rangeMin,rangeMax] + }else{ + // AllowedValues + tmpMap1=getMap(in->defaults->content,"AllowedValues"); + if(tmpMap1!=NULL){ + char* saveptr; + json_object* prop5=json_object_new_array(); + char *tmps = strtok_r (tmpMap1->value, ",", &saveptr); + while(tmps!=NULL){ + json_object_array_add(prop5,json_object_new_string(tmps)); + tmps = strtok_r (NULL, ",", &saveptr); + } + json_object_object_add(prop3,"allowedValues",prop5); + + }else{ + json_object_object_add(prop3,"anyValue",json_object_new_boolean(true)); + } + } + } + json_object_object_add(prop1,"valueDefinition",prop3); + json_object_array_add(prop0,prop1); + } + json_object_object_add(input,"literalDataDomains",prop0); + } + + /** + * Add Format properties to a json_object + * @param m the main configuration maps pointer + * @param iot the current iotype pointer + * @param res the json_object pointer to add the properties to + * @param isDefault boolean specifying if the currrent iotype is default + * @param maxSize a map pointer to the maximumMegabytes param defined in the zcfg file for this input/output + */ + void printFormatJ(maps* m,iotype* iot,json_object* res,bool isDefault,map* maxSize){ + if(iot!=NULL){ + map* tmpMap1=getMap(iot->content,"mimeType"); + json_object* prop1=json_object_new_object(); + json_object_object_add(prop1,"default",json_object_new_boolean(isDefault)); + json_object_object_add(prop1,"mimeType",json_object_new_string(tmpMap1->value)); + tmpMap1=getMap(iot->content,"encoding"); + if(tmpMap1!=NULL) + json_object_object_add(prop1,"encoding",json_object_new_string(tmpMap1->value)); + tmpMap1=getMap(iot->content,"schema"); + if(tmpMap1!=NULL) + json_object_object_add(prop1,"schema",json_object_new_string(tmpMap1->value)); + if(maxSize!=NULL) + json_object_object_add(prop1,"maximumMegabytes",json_object_new_int64(atoll(maxSize->value))); + json_object_array_add(res,prop1); + } + } + + /** + * Add additionalParameters property to a json_object + * @param conf the main configuration maps pointer + * @param meta a map pointer to the current metadata informations + * @param doc the json_object pointer to add the property to + */ + void printJAdditionalParameters(maps* conf,map* meta,json_object* doc){ + map* cmeta=meta; + json_object* carr=json_object_new_array(); + int hasElement=-1; + json_object* jcaps=json_object_new_object(); + while(cmeta!=NULL){ + json_object* jcmeta=json_object_new_object(); + if(strcasecmp(cmeta->name,"role")!=0 && + strcasecmp(cmeta->name,"href")!=0 && + strcasecmp(cmeta->name,"title")!=0 && + strcasecmp(cmeta->name,"length")!=0 ){ + json_object_object_add(jcmeta,"name",json_object_new_string(cmeta->name)); + json_object_object_add(jcmeta,"value",json_object_new_string(cmeta->value)); + json_object_array_add(carr,jcmeta); + hasElement++; + }else{ + if(strcasecmp(cmeta->name,"length")!=0) + json_object_object_add(jcaps,cmeta->name,json_object_new_string(cmeta->value)); + } + cmeta=cmeta->next; + } + if(hasElement>=0){ + json_object_object_add(jcaps,"additionalParameter",carr); + json_object_object_add(doc,"additionalParameters",jcaps); + } + } + + /** + * Add metadata property to a json_object + * @param conf the main configuration maps pointer + * @param meta a map pointer to the current metadata informations + * @param doc the json_object pointer to add the property to + */ + void printJMetadata(maps* conf,map* meta,json_object* doc){ + map* cmeta=meta; + json_object* carr=json_object_new_array(); + int hasElement=-1; + while(cmeta!=NULL){ + json_object* jcmeta=json_object_new_object(); + if(strcasecmp(cmeta->name,"role")==0 || + strcasecmp(cmeta->name,"href")==0 || + strcasecmp(cmeta->name,"title")==0 ){ + json_object_object_add(jcmeta,cmeta->name,json_object_new_string(cmeta->value)); + hasElement++; + } + json_object_array_add(carr,jcmeta); + cmeta=cmeta->next; + } + if(hasElement>=0) + json_object_object_add(doc,"metadata",carr); + } + + /** + * Add metadata properties to a json_object + * @param m the main configuration maps pointer + * @param io a string + * @param in an elements pointer to the current input/output + * @param inputs the json_object pointer to add the property to + * @param serv the service pointer to extract the metadata from + */ + void printIOTypeJ(maps* m, const char *io, elements* in,json_object* inputs,service* serv){ + while(in!=NULL){ + json_object* input=json_object_new_object(); + json_object_object_add(input,"id",json_object_new_string(in->name)); + map* tmpMap=getMap(in->content,"title"); + if(tmpMap!=NULL) + json_object_object_add(input,"title",json_object_new_string(tmpMap->value)); + tmpMap=getMap(in->content,"abstract"); + if(tmpMap!=NULL) + json_object_object_add(input,"abstract",json_object_new_string(tmpMap->value)); + if(strcmp(io,"input")==0){ + tmpMap=getMap(in->content,"minOccurs"); + if(tmpMap!=NULL) + json_object_object_add(input,"minOccurs",json_object_new_string(tmpMap->value)); + tmpMap=getMap(in->content,"maxOccurs"); + if(tmpMap!=NULL) + json_object_object_add(input,"maxOccurs",json_object_new_string(tmpMap->value)); + } + if(in->format!=NULL){ + json_object* input1=json_object_new_object(); + json_object* prop0=json_object_new_array(); + if(strcasecmp(in->format,"LiteralData")==0 || + strcasecmp(in->format,"LiteralOutput")==0){ + printLiteralDataJ(m,in,input1); + }else{ + if(strcasecmp(in->format,"ComplexData")==0 || + strcasecmp(in->format,"ComplexOutput")==0){ + map* sizeMap=getMap(in->content,"maximumMegabytes"); + printFormatJ(m,in->defaults,prop0,true,sizeMap); + iotype* sup=in->supported; + while(sup!=NULL){ + printFormatJ(m,sup,prop0,false,sizeMap); + sup=sup->next; + } + json_object_object_add(input1,"formats",prop0); + } + else{ + json_object* prop1=json_object_new_object(); + json_object_object_add(prop1,"default",json_object_new_boolean(true)); + map* tmpMap1=getMap(in->defaults->content,"crs"); + if(tmpMap1==NULL) + return; + json_object_object_add(prop1,"crs",json_object_new_string(tmpMap1->value)); + json_object_array_add(prop0,prop1); + iotype* sup=in->supported; + while(sup!=NULL){ + json_object* prop1=json_object_new_object(); + json_object_object_add(prop1,"default",json_object_new_boolean(false)); + tmpMap1=getMap(sup->content,"crs"); + json_object_object_add(prop1,"crs",json_object_new_string(tmpMap1->value)); + json_object_array_add(prop0,prop1); + sup=sup->next; + } + json_object_object_add(input1,"supportedCRS",prop0); + } + } + json_object_object_add(input,io,input1); + } + printJMetadata(m,in->metadata,input); + printJAdditionalParameters(m,in->additional_parameters,input); + json_object_array_add(inputs,input); + in=in->next; + } + + } + + /** + * Add all the capabilities properties to a json_object + * @param ref the registry pointer + * @param m the main configuration maps pointer + * @param doc0 the void (json_object) pointer to add the property to + * @param nc0 the void (json_object) pointer to add the property to + * @param serv the service pointer to extract the metadata from + */ + void printGetCapabilitiesForProcessJ(registry *reg, maps* m,void* doc0,void* nc0,service* serv){ + json_object* doc=(json_object*) doc0; + json_object* nc=(json_object*) nc0; + json_object *res=json_object_new_object(); + map* tmpMap0=getMapFromMaps(m,"lenv","level"); + char* rUrl=serv->name; + if(tmpMap0!=NULL && atoi(tmpMap0->value)>0){ + int i=0; + maps* tmpMaps=getMaps(m,"lenv"); + char* tmpName=NULL; + for(i=0;ivalue);i++){ + char* key=(char*)malloc(15*sizeof(char)); + sprintf(key,"sprefix_%d",i); + map* tmpMap1=getMap(tmpMaps->content,key); + if(i+1==atoi(tmpMap0->value)) + if(tmpName==NULL){ + tmpName=(char*) malloc((strlen(serv->name)+strlen(tmpMap1->value)+1)*sizeof(char)); + sprintf(tmpName,"%s%s",tmpMap1->value,serv->name); + }else{ + char* tmpStr=zStrdup(tmpName); + tmpName=(char*) realloc(tmpName,(strlen(tmpStr)+strlen(tmpMap1->value)+strlen(serv->name)+1)*sizeof(char)); + sprintf(tmpName,"%s%s%s",tmpStr,tmpMap1->value,serv->name); + free(tmpStr); + } + else + if(tmpName==NULL){ + tmpName=(char*) malloc((strlen(tmpMap1->value)+1)*sizeof(char)); + sprintf(tmpName,"%s",tmpMap1->value); + }else{ + char* tmpStr=zStrdup(tmpName); + tmpName=(char*) realloc(tmpName,(strlen(tmpStr)+strlen(tmpMap1->value)+1)*sizeof(char)); + sprintf(tmpName,"%s%s",tmpStr,tmpMap1->value); + free(tmpStr); + } + } + json_object_object_add(res,"id",json_object_new_string(tmpName)); + if(tmpName!=NULL){ + rUrl=zStrdup(tmpName); + free(tmpName); + } + } + else + json_object_object_add(res,"id",json_object_new_string(serv->name)); + if(serv->content!=NULL){ + map* tmpMap=getMap(serv->content,"title"); + if(tmpMap!=NULL){ + json_object_object_add(res,"title",json_object_new_string(tmpMap->value)); + } + tmpMap=getMap(serv->content,"abstract"); + if(tmpMap!=NULL){ + json_object_object_add(res,"abstract",json_object_new_string(tmpMap->value)); + } + tmpMap=getMap(serv->content,"processVersion"); + if(tmpMap!=NULL){ + if(strlen(tmpMap->value)<5){ + char *val=(char*)malloc((strlen(tmpMap->value)+5)*sizeof(char)); + sprintf(val,"%s.0.0",tmpMap->value); + json_object_object_add(res,"version",json_object_new_string(val)); + free(val); + } + else + json_object_object_add(res,"version",json_object_new_string(tmpMap->value)); + } + int limit=4; + int i=0; + map* sType=getMap(serv->content,"serviceType"); + for(;ivalue)+strlen(rUrl)+13)*sizeof(char)); + sprintf(tmpStr,"%s/processes/%s/",tmpUrl->value,rUrl); + if(doc==NULL){ + json_object_object_add(res2,"title",json_object_new_string("Execute End Point")); + char* tmpStr1=zStrdup(tmpStr); + tmpStr=(char*) realloc(tmpStr,(strlen(tmpStr)+6)*sizeof(char)); + sprintf(tmpStr,"%sjobs/",tmpStr1); + free(tmpStr1); + } + json_object_object_add(res2,"href",json_object_new_string(tmpStr)); + free(tmpStr); + json_object_array_add(res1,res2); + json_object_object_add(res,"links",res1); + } + if(doc==NULL){ + elements* in=serv->inputs; + json_object* inputs=json_object_new_array(); + printIOTypeJ(m,"input",in,inputs,serv); + json_object_object_add(res,"inputs",inputs); + + in=serv->outputs; + json_object* outputs=json_object_new_array(); + printIOTypeJ(m,"output",in,outputs,serv); + json_object_object_add(res,"outputs",outputs); + + } + if(strcmp(rUrl,serv->name)!=0) + free(rUrl); + if(doc!=NULL) + json_object_array_add(doc,res); + else + json_object_object_add(nc,"process",json_object_get(res)); + + } + + /** + * Print an OWS ExceptionReport Document and HTTP headers (when required) + * depending on the code. + * Set hasPrinted value to true in the [lenv] section. + * + * @param m the maps containing the settings of the main.cfg file + * @param s the map containing the text,code,locator keys (or a map array of the same keys) + */ + void printExceptionReportResponseJ(maps* m,map* s){ + if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL) + return; + int buffersize; + json_object *res=json_object_new_object(); + + maps* tmpMap=getMaps(m,"main"); + const char *exceptionCode; + + map* tmp=getMap(s,"code"); + if(tmp!=NULL){ + if(strcmp(tmp->value,"OperationNotSupported")==0 || + strcmp(tmp->value,"NoApplicableCode")==0) + exceptionCode="501 Not Implemented"; + else + if(strcmp(tmp->value,"MissingParameterValue")==0 || + strcmp(tmp->value,"InvalidUpdateSequence")==0 || + strcmp(tmp->value,"OptionNotSupported")==0 || + strcmp(tmp->value,"VersionNegotiationFailed")==0 || + strcmp(tmp->value,"InvalidParameterValue")==0) + exceptionCode="400 Bad request"; + else + if(strcmp(tmp->value,"NotFound")==0) + exceptionCode="404 Not Found"; + else + exceptionCode="501 Internal Server Error"; + json_object_object_add(res,"code",json_object_new_string(tmp->value)); + } + else + exceptionCode="501 Internal Server Error"; + printHeaders(m); + + tmp=getMapFromMaps(m,"lenv","status_code"); + if(tmp!=NULL) + exceptionCode=tmp->value; + if(m!=NULL){ + map *tmpSid=getMapFromMaps(m,"lenv","sid"); + if(tmpSid!=NULL){ + if( getpid()==atoi(tmpSid->value) ){ + printf("Status: %s\r\n\r\n",exceptionCode); + } + } + else{ + printf("Status: %s\r\n\r\n",exceptionCode); + } + }else{ + printf("Status: %s\r\n\r\n",exceptionCode); + } + tmp=getMap(s,"text"); + if(tmp==NULL) + tmp=getMap(s,"message"); + if(tmp==NULL) + tmp=getMapFromMaps(m,"lenv","message"); + if(tmp!=NULL) + json_object_object_add(res,"description",json_object_new_string(tmp->value)); + const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN); + printf(jsonStr); + if(m!=NULL) + setMapInMaps(m,"lenv","hasPrinted","true"); + } + + /** + * Parse LiteralData value + * @param conf the maps containing the settings of the main.cfg file + * @param req json_object pointing to the input/output + * @param element + * @param output the maps to set current json structure + */ + void parseJLiteral(maps* conf,json_object* req,elements* element,maps* output){ + json_object* json_cinput=NULL; + if(json_object_object_get_ex(req,"value",&json_cinput)!=FALSE){ + output->content=createMap("value",json_object_get_string(json_cinput)); + } + const char* tmpStrs[2]={ + "dataType", + "uom" + }; + for(int i=0;i<2;i++) + if(json_object_object_get_ex(req,tmpStrs[i],&json_cinput)!=FALSE){ + json_object* json_cinput1; + if(json_object_object_get_ex(json_cinput,"name",&json_cinput1)!=FALSE){ + if(output->content==NULL) + output->content=createMap(tmpStrs[i],json_object_get_string(json_cinput1)); + else + addToMap(output->content,tmpStrs[i],json_object_get_string(json_cinput1)); + } + if(json_object_object_get_ex(json_cinput,"reference",&json_cinput1)!=FALSE){ + if(output->content==NULL) + output->content=createMap(tmpStrs[i],json_object_get_string(json_cinput1)); + else + addToMap(output->content,tmpStrs[i],json_object_get_string(json_cinput1)); + } + } + if(json_object_object_get_ex(req,"transmissionMode",&json_cinput)!=FALSE){ + if(output->content==NULL) + output->content=createMap("transmissionMode",json_object_get_string(json_cinput)); + else + addToMap(output->content,"transmissionMode",json_object_get_string(json_cinput)); + } + } + + /** + * Parse ComplexData value + * @param conf the maps containing the settings of the main.cfg file + * @param req json_object pointing to the input/output + * @param element + * @param output the maps to set current json structure + * @param name the name of the request from http_requests + */ + void parseJComplex(maps* conf,json_object* req,elements* element,maps* output,const char* name){ + json_object* json_cinput=NULL; + + + if (json_object_object_get_ex(req,"href",&json_cinput)!=FALSE){ + output->content=createMap("xlink:href",json_object_get_string(json_cinput)); + int len=0; + int createdStr=0; + char *tmpStr="url"; + char *tmpStr1="input"; + if(getMaps(conf,"http_requests")==NULL){ + maps* tmpMaps=createMaps("http_requests"); + tmpMaps->content=createMap("length","1"); + freeMaps(&tmpMaps); + free(tmpMaps); + } + } else if(json_object_object_get_ex(req,"value",&json_cinput)!=FALSE){ + json_object* json_value=NULL; + if(json_object_object_get_ex(json_cinput,"inlineValue",&json_value)!=FALSE) + output->content=createMap("value",json_object_get_string(json_value)); + else{ + if(json_object_object_get_ex(json_cinput,"href",&json_value)!=FALSE){ + output->content=createMap("xlink:href",json_object_get_string(json_value)); + int len=0; + int createdStr=0; + char *tmpStr="url"; + char *tmpStr1="input"; + if(getMaps(conf,"http_requests")==NULL){ + maps* tmpMaps=createMaps("http_requests"); + tmpMaps->content=createMap("length","1"); +// addMapsToMaps(&conf,tmpMaps);//rdr ERROR!!! + freeMaps(&tmpMaps); + free(tmpMaps); + + }else{ + map* tmpMap=getMapFromMaps(conf,"http_requests","length"); + int len=atoi(tmpMap->value); + createdStr=1; + tmpStr=(char*) malloc((12)*sizeof(char)); + sprintf(tmpStr,"%d",len+1); + setMapInMaps(conf,"http_requests","length",tmpStr); + sprintf(tmpStr,"url_%d",len); + tmpStr1=(char*) malloc((14)*sizeof(char)); + sprintf(tmpStr1,"input_%d",len); + } +// setMapInMaps(conf,"http_requests",tmpStr,json_object_get_string(json_value));//rdr ERROR!!! +// setMapInMaps(conf,"http_requests",tmpStr1,name);//rdr ERROR!!! + if(createdStr>0){ + free(tmpStr); + free(tmpStr1); + } + } + } + } + if(json_object_object_get_ex(req,"format",&json_cinput)!=FALSE){ + json_object_object_foreach(json_cinput, key, val) { + if(output->content==NULL) + output->content=createMap(key,json_object_get_string(val)); + else + addToMap(output->content,key,json_object_get_string(val)); + + } + } + if(json_object_object_get_ex(req,"transmissionMode",&json_cinput)!=FALSE){ + if(output->content==NULL) + output->content=createMap("transmissionMode",json_object_get_string(json_cinput)); + else + addToMap(output->content,"transmissionMode",json_object_get_string(json_cinput)); + } + } + + /** + * Parse BoundingBox value + * @param conf the maps containing the settings of the main.cfg file + * @param req json_object pointing to the input/output + * @param element + * @param output the maps to set current json structure + */ + void parseJBoundingBox(maps* conf,json_object* req,elements* element,maps* output){ + json_object* json_cinput=NULL; + if(json_object_object_get_ex(req,"bbox",&json_cinput)!=FALSE){ + output->content=createMap("value",json_object_get_string(json_cinput)); + } + if(json_object_object_get_ex(req,"crs",&json_cinput)!=FALSE){ + if(output->content==NULL) + output->content=createMap("crs",json_object_get_string(json_cinput)); + else + addToMap(output->content,"crs","http://www.opengis.net/def/crs/OGC/1.3/CRS84"); + } + char* tmpStrs[2]={ + "lowerCorner", + "upperCorner" + }; + for(int i=0;i<2;i++) + if(json_object_object_get_ex(req,tmpStrs[i],&json_cinput)!=FALSE){ + if(output->content==NULL) + output->content=createMap(tmpStrs[i],json_object_get_string(json_cinput)); + else + addToMap(output->content,tmpStrs[i],json_object_get_string(json_cinput)); + } + if(json_object_object_get_ex(req,"transmissionMode",&json_cinput)!=FALSE){ + if(output->content==NULL) + output->content=createMap("transmissionMode",json_object_get_string(json_cinput)); + else + addToMap(output->content,"transmissionMode",json_object_get_string(json_cinput)); + } + } + + /** + * Parse inputs / outputs + * @param conf the maps containing the settings of the main.cfg file + * @param req json_object pointing to the input/output + * @param ioElements the elements extracted from the zcfg + * @param ioMaps the produced maps containing inputs (or outputs) + * @param ioType the char* set to inputs or outputs + */ + void parseJIO(maps* conf, json_object* req, elements* ioElements, maps** ioMaps,const char* ioType){ + json_object* json_io=NULL; + if(json_object_object_get_ex(req,ioType,&json_io)!=FALSE){ + json_object* json_current_io=NULL; + size_t len=json_object_array_length(json_io); + for(int i=0;iname); + addToMap(error,"message",tmpS); + setMapInMaps(conf,"lenv","status_code","400 Bad Request"); + printExceptionReportResponseJ(conf,error); + return; + }else{ + if(json_object_get_type(json_cinput)==json_type_string){ + parseJLiteral(conf,json_input,cio,cMaps); + }else if(json_object_get_type(json_cinput)==json_type_object){ + json_object* json_ccinput=NULL; + if(json_object_object_get_ex(json_cinput,"bbox",&json_ccinput)!=FALSE){ + parseJComplex(conf,json_input,cio,cMaps,json_object_get_string(cname)); + } + else{ + parseJBoundingBox(conf,json_input,cio,cMaps); + } + }else{ + if(strcmp(ioType,"input")==0){ + map* error=createMap("code","BadRequest"); + char tmpS1[1024]; + sprintf(tmpS1,_("Issue with input %s"),ioElements->name); + addToMap(error,"message",tmpS1); + setMapInMaps(conf,"lenv","status_code","400 Bad Request"); + printExceptionReportResponseJ(conf,error); + return; + } + } + } + } + }else{ + if(strcmp(ioType,"input")==0){ + map* error=createMap("code","BadRequest"); + char tmpS1[1024]; + sprintf(tmpS1,_("Missing input for %s"),ioElements->name); + addToMap(error,"message",tmpS1); + setMapInMaps(conf,"lenv","status_code","400 Bad Request"); + printExceptionReportResponseJ(conf,error); + return; + }else{ + // Outputs + if(json_object_object_get_ex(json_current_io,"transmissionMode",&json_cinput)!=FALSE){ + if(cMaps->content==NULL) + cMaps->content=createMap("transmissionMode",json_object_get_string(json_cinput)); + else + addToMap(cMaps->content,"transmissionMode",json_object_get_string(json_cinput)); + } + if(json_object_object_get_ex(json_current_io,"format",&json_cinput)!=FALSE){ + json_object_object_foreach(json_cinput, key, val) { + if(cMaps->content==NULL) + cMaps->content=createMap(key,json_object_get_string(val)); + else + addToMap(cMaps->content,key,json_object_get_string(val)); + } + } + } + } + } + addToMap(cMaps->content,"inRequest","true"); + if (ioMaps == NULL) + *ioMaps = dupMaps(&cMaps); + else { + + maps* testIath=getMaps(*ioMaps,cMaps->name); + if(testIath){ + + int cursor=2; + char name[20],cCursor[55]; + memset(name,'\0',20); + memset(cCursor,'\0',55); + + map *getValueMap = getMap(cMaps->content,"value"); + if (getValueMap){ + strcpy(name,"value"); + } + map *getXlink = getMap(cMaps->content,"xlink:href"); + if (getXlink){ + strcpy(name,"xlink:href"); + } + + map* isArray=getMap(testIath->content,"isArray"); + if(isArray){ + + map* le=getMap(testIath->content,"length"); + if (le){ + cursor = atoi(le->value); + cursor=cursor+1; + }else{ + cursor=2; + } + + free(le->value); + le->value=NULL; + + snprintf(cCursor,54,"%d",cursor); + le->value=zStrdup(cCursor); + + }else{ + map *addArray = createMap("isArray","true"); + addMapToMap(&testIath->content,addArray); + + map *addLength = createMap("length","2"); + addMapToMap(&testIath->content,addLength); + } + + if (strlen(name)!=0){ + memset(cCursor,'\0',55); + snprintf(cCursor,54,"%d",cursor-1); + + int newSize=(5+strlen(cCursor) + strlen(name)) +sizeof(char); + char* newValueC=(char*)malloc( newSize); + memset(newValueC,'\n',newSize); + + sprintf(newValueC,"%s_%s",name,cCursor); + map *addValue = createMap(newValueC, getValueMap?getValueMap->value:getXlink->value); + addMapToMap(&testIath->content,addValue); + + free(newValueC); + } + + }else{ + addMapsToMaps(ioMaps, cMaps); + } + + } + } + } + } + + + + /** + * Parse Json Request + * @param conf the maps containing the settings of the main.cfg file + * @param s the current service metadata + * @param req the JSON object of the request body + * @param inputs the produced maps + * @param outputs the produced maps + */ + void parseJRequest(maps* conf, service* s,json_object* req,maps** inputs,maps** outputs){ + elements* io=s->inputs; + + json_object* json_io=NULL; + int parsed=0; + char* tmpS="input"; + maps* in=*inputs; + parseJIO(conf,req,s->inputs,inputs,"inputs"); + + if(parsed==0){ + json_io=NULL; + if(json_object_object_get_ex(req,"outputs",&json_io)!=FALSE){ + parseJIO(conf,req,s->outputs,outputs,"outputs"); + } + } + } + + /** + * Print the jobs list + * + * @param conf the maps containing the settings of the main.cfg file + * @return the JSON object pointer to the jobs list + */ + json_object* printJobList(maps* conf){ + json_object* res=json_object_new_array(); + map* tmpPath=getMapFromMaps(conf,"main","tmpPath"); + map* oIdentifier=getMapFromMaps(conf,"lenv","oIdentifier"); + char* cpath=(char*)malloc( (strlen(tmpPath->value)+strlen(oIdentifier->value)+14+/*rdr add user path*/ + 1024)*sizeof(char)) ; + + +// + map *userMap = getMapFromMaps (conf, "eoepcaUser", "user"); + if (userMap && userMap->value && strlen(userMap->value)>0 ){ + sprintf(cpath,"%s/statusInfos/%s/%s",tmpPath->value,userMap->value,oIdentifier->value); + }else{ + sprintf(cpath,"%s/statusInfos/%s",tmpPath->value,oIdentifier->value); + } + fprintf(stderr,"-----------PATH1: %s ---------------\n",cpath); + + struct dirent *dp; + DIR *dirp = opendir (cpath); + if(dirp!=NULL){ + while ((dp = readdir (dirp)) != NULL){ + char* extn = strstr(dp->d_name, ".json"); + if(extn!=NULL){ + + fprintf(stderr,"-----------PATH1: FILE: %s ---------------\n",dp->d_name); + + json_object* cjob=json_object_new_object(); + char* tmpStr=zStrdup(dp->d_name); + tmpStr[strlen(dp->d_name)-5]=0; + json_object_object_add(cjob,"id",json_object_new_string(tmpStr)); + char *tmps1=(char*)malloc((strlen(cpath)+strlen(dp->d_name)+2)*sizeof(char)); + sprintf (tmps1, "%s/%s", cpath, dp->d_name); + + fprintf(stderr,"-----------PATH1: FILE: tmps1: %s ---------------\n",tmps1); + + FILE* cdat=fopen(tmps1,"rb"); + if(cdat!=NULL){ + zStatStruct f_status; + int s=zStat(tmps1, &f_status); + char* mystring=(char*)malloc((f_status.st_size+1)*sizeof(char)); + fread(mystring,1,f_status.st_size,cdat); + mystring[f_status.st_size]=0; + json_object *jobj = NULL; + int slen = 0; + enum json_tokener_error jerr; + struct json_tokener* tok=json_tokener_new(); + do { + slen = strlen(mystring); + jobj = json_tokener_parse_ex(tok, mystring, slen); + } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); + if (jerr != json_tokener_success) { + fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); + return res; + } + if (tok->char_offset < slen){ + return res; + } + json_object_object_add(cjob,"infos",jobj); + free(mystring); + fclose(cdat); + } + free(tmpStr); + json_object_array_add(res,cjob); + } + } + closedir (dirp); + } + return res; + } + + + /** + * Returns current UTC timestamp + * @param dest + * @return + */ + char *getUtcTimestamp(char *dest) + { + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm *tmp = gmtime(&tv.tv_sec); + char fmt[128]; + strftime(fmt, sizeof(fmt), "%Y-%m-%dT%H:%M:%S.%%06uZ", tmp); + sprintf(dest, fmt, tv.tv_usec); + return dest; + } + + /** + * Print the result of an execution + * + * @param conf the maps containing the settings of the main.cfg file + * @param s service pointer to metadata + * @param result outputs of the service + * @param res the status of executino SERVICE_FAILED/SERVICE_SUCCEEDED + * @return the JSON object pointer to the result + */ + json_object* printJResult(maps* conf,service* s,maps* result,int res){ + printHeaders(conf); + json_object* eres1=json_object_new_object(); + json_object* eres=json_object_new_array(); + maps* resu=result; + int itn=0; + while(resu!=NULL){ + json_object* res1=json_object_new_object(); + json_object_object_add(res1,"id",json_object_new_string(resu->name)); + + // UTC timestamp of the time of the job completion + // the value is temporary as it is not 100% OGC compliant + char dest[12]; + json_object_object_add(res1,"time",json_object_new_string(getUtcTimestamp(dest))); + + map* tmpMap=NULL; + if((tmpMap=getMap(resu->content,"value"))!=NULL || + (getMap(resu->content,"generated_file"))!=NULL){ + json_object* res2=json_object_new_object(); + map* tmpMap1=NULL; + if((tmpMap1=getMap(resu->content,"transmissionMode"))!=NULL) { + if(strcmp(tmpMap1->value,"value")==0) { + map* tmpMap2=getMap(resu->content,"mimeType"); + if(tmpMap2!=NULL && strstr(tmpMap2->value,"json")!=NULL){ + json_object *jobj = NULL; + int slen = 0; + enum json_tokener_error jerr; + struct json_tokener* tok=json_tokener_new(); + do { + slen = strlen(tmpMap->value); + jobj = json_tokener_parse_ex(tok, tmpMap->value, slen); + } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); + if (jerr != json_tokener_success) { + fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); + return eres1; + } + if (tok->char_offset < slen){ + return eres1; + } + json_object_object_add(res2,"inlineValue",jobj); + }else + json_object_object_add(res2,"inlineValue",json_object_new_string(tmpMap->value)); + } + else{ + // Create file for reference data if not existing + map *gfile=getMap(resu->content,"generated_file"); + char *file_name=NULL; + char *file_path=NULL; + char *file_url=NULL; + map *tmp1=getMapFromMaps(conf,"main","tmpPath"); + if(gfile!=NULL){ + gfile=getMap(resu->content,"expected_generated_file"); + if(gfile==NULL){ + gfile=getMap(resu->content,"generated_file"); + } + if(strstr(gfile->value,tmp1->value)!=NULL) + file_name=zStrdup(strstr(gfile->value,tmp1->value)+strlen(tmp1->value)); + }/*else*/ + { + // Create file for reference data + map *tmpUrl=getMapFromMaps(conf,"main","tmpUrl"); + map *usid=getMapFromMaps(conf,"lenv","usid"); + map *ext=getMap(resu->content,"extension"); + if(gfile==NULL){ + char file_ext[32]; + if( ext != NULL && ext->value != NULL) { + strncpy(file_ext, ext->value, 32); + } + else { + // Obtain default file extension (see mimetypes.h). + // If the MIME type is not recognized, txt is used as the default extension + map* mtype=getMap(resu->content,"mimeType"); + getFileExtension(mtype != NULL ? mtype->value : NULL, file_ext, 32); + } + if(file_name!=NULL) + free(file_name); + + file_name=(char*)malloc((strlen(s->name)+strlen(usid->value)+strlen(file_ext)+strlen(resu->name)+45)*sizeof(char)); + sprintf(file_name,"ZOO_DATA_%s_%s_%s_%d.%s",s->name,resu->name,usid->value,itn,file_ext); + + file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char)); + sprintf(file_path,"%s/%s",tmp1->value,file_name); + }else{ + file_path=(char*)malloc((strlen(gfile->value)+1)*sizeof(char)); + sprintf(file_path,"%s",gfile->value); + } + + + itn++; + + file_url=(char*)malloc((strlen(tmpUrl->value)+ + strlen(file_name)+2)*sizeof(char)); + sprintf(file_url,"%s/%s",tmpUrl->value,file_name); + + if(gfile==NULL){ + FILE *ofile=fopen(file_path,"wb"); + if(ofile==NULL){ + char tmpMsg[1024]; + sprintf(tmpMsg, + _("Unable to create the file \"%s\" for storing the %s final result."), + file_name,resu->name); + map* error=createMap("code","InternalError"); + addToMap(error,"message",tmpMsg); + printExceptionReportResponseJ(conf,error); + free(file_name); + free(file_path); + return NULL; + } + + map* toto=getMap(resu->content,"value"); + if(toto==NULL){ + char tmpMsg[1024]; + sprintf(tmpMsg, + _("No value found for the requested output %s."), + resu->name); + map* error=createMap("code","InternalError"); + addToMap(error,"message",tmpMsg); + printExceptionReportResponseJ(conf,error); + fclose(ofile); + free(file_name); + free(file_path); + return NULL; + } + map* size=getMap(resu->content,"size"); + if(size!=NULL && toto!=NULL) + fwrite(toto->value,1,(atoi(size->value))*sizeof(char),ofile); + else + if(toto!=NULL && toto->value!=NULL) + fwrite(toto->value,1, + strlen(toto->value)*sizeof(char),ofile); + fclose(ofile); + } + json_object_object_add(res2,"href", + json_object_new_string(file_url)); + free(file_url); + free(file_name); + free(file_path); + + } + + } + } + json_object_object_add(res1,"value",res2); + json_object_array_add(eres,res1); + } + resu=resu->next; + } + json_object_object_add(eres1,"outputs",eres); + const char* jsonStr = + json_object_to_json_string_ext(eres1,JSON_C_TO_STRING_PLAIN); + map *tmpPath = getMapFromMaps (conf, "main", "tmpPath"); + map *cIdentifier = getMapFromMaps (conf, "lenv", "oIdentifier"); + map *sessId = getMapFromMaps (conf, "lenv", "usid"); + char tmp[1024]; + sprintf(tmp,"%s/%s_%s.json", + tmpPath->value,cIdentifier->value,sessId->value); + FILE* foutput=fopen(tmp,"w+"); + + + fprintf(stderr,"/////////////////////%s//////////////////////// \n",tmp ); + + + if(foutput!=NULL){ + fclose(foutput); + char tmpUrl[1024]; + map* tmpPath1 = getMapFromMaps (conf, "main", "tmpUrl"); + + int wpLen=0; + char* wp=NULL; + map* eoUserMap=getMapFromMaps(conf,"eoepcaUser","user"); + if (eoUserMap && eoUserMap->value){ + wpLen=strlen(eoUserMap->value); + wp=(char*)malloc((10+wpLen)*sizeof(char)); + memset(wp,0,(10+wpLen)*sizeof(char)); + sprintf(wp,"/%s",eoUserMap->value); + } + + sprintf(tmpUrl,"%s%s/%s_%s.json", + (wpLen>0?wp:""), + tmpPath1->value, + cIdentifier->value,sessId->value); + setMapInMaps(conf,"headers","Location",tmpUrl); + + + + fprintf(stderr,"/////////////////////%s//////////////////////// \n",tmpUrl ); + + } + if(res==3){ + setMapInMaps(conf,"headers","Status","201 Created"); + } + else{ + setMapInMaps(conf,"headers","Status","500 Issue running your service"); + } + + return eres1; + } + + + /** + * Create the status links + * + * @param conf the maps containing the settings of the main.cfg file + * @param result an integer (>0 for adding the /result link) + * @param obj the JSON object pointer to add the links to + * @return 0 + */ + int createStatusLinks(maps* conf,int result,json_object* obj){ + json_object* res=json_object_new_array(); + map *tmpPath = getMapFromMaps (conf, "openapi", "rootUrl"); + map *cIdentifier = getMapFromMaps (conf, "lenv", "oIdentifier"); + map *sessId = getMapFromMaps (conf, "lenv", "usid"); + + int wpLen=0; + char* wp=NULL; + map* eoUserMap=getMapFromMaps(conf,"eoepcaUser","user"); + if (eoUserMap && eoUserMap->value){ + wpLen=strlen(eoUserMap->value); + wp=(char*)malloc((10+wpLen)*sizeof(char)); + memset(wp,0,(10+wpLen)*sizeof(char)); + sprintf(wp,"/%s",eoUserMap->value); + }else{ + fprintf(stderr,"///////////////////////////////////////////// \n" ); + fprintf(stderr,"workspace did not define\n"); + fprintf(stderr,"///////////////////////////////////////////// \n" ); + } + + char *Url0=(char*) malloc(wpLen*(strlen(tmpPath->value)+ + strlen(cIdentifier->value)+ + strlen(sessId->value)+18)*sizeof(char)); + + int needResult=-1; + char *message, *status; + sprintf(Url0,"%s%s/processes/%s/jobs/%s", + (wpLen>0?wp:""), + tmpPath->value, + cIdentifier->value, + sessId->value); + setMapInMaps(conf,"headers","Location",Url0); + json_object* val=json_object_new_object(); + json_object_object_add(val,"Title", + json_object_new_string(_("Status location"))); + json_object_object_add(val,"href",json_object_new_string(Url0)); + json_object_array_add(res,val); + if(result>0){ + fprintf(stderr, "Setting Result Location\n"); + free(Url0); + + fprintf(stderr, (wpLen>0?" workspace name length is greater than 0\n":"")); + fprintf(stderr, "workspace is %s", wp); + + Url0=(char*) malloc(wpLen*(strlen(tmpPath->value)+ + strlen(cIdentifier->value)+ + strlen(sessId->value)+25)*sizeof(char)); + + fprintf(stderr, "result location is %s%s/processes/%s/jobs/%s/result", + (wpLen>0?wp:""), + tmpPath->value, + cIdentifier->value, + sessId->value); + + sprintf(Url0,"%s%s/processes/%s/jobs/%s/result", + (wpLen>0?wp:""), + tmpPath->value, + cIdentifier->value, + sessId->value); + json_object* val1=json_object_new_object(); + json_object_object_add(val1,"Title", + json_object_new_string(_("Result location"))); + json_object_object_add(val1,"href",json_object_new_string(Url0)); + json_object_array_add(res,val1); + } + json_object_object_add(obj,"links",res); + free(Url0); + free(wp); + return 0; + } + + /** + * Get the status file path + * + * @param conf the maps containing the settings of the main.cfg file + * @return a char* containing the full status file path + */ + char* json_getStatusFilePath(maps* conf){ + + + map *tmpPath = getMapFromMaps (conf, "main", "tmpPath"); + map *cIdentifier = getMapFromMaps (conf, "lenv", "oIdentifier"); + map *sessId = getMapFromMaps (conf, "lenv", "usid"); + if(sessId!=NULL){ + sessId = getMapFromMaps (conf, "lenv", "gs_usid"); + if(sessId==NULL) + sessId = getMapFromMaps (conf, "lenv", "usid"); + }else + sessId = getMapFromMaps (conf, "lenv", "gs_usid"); + char *tmp1=(char*) malloc((strlen(tmpPath->value)+ + strlen(cIdentifier->value)+14)*sizeof(char) + /*rdr*/ (1024*sizeof(char)) ); + + + map *userMap = getMapFromMaps (conf, "eoepcaUser", "user"); + if (userMap && userMap->value && strlen(userMap->value)>0 ){ + sprintf(tmp1,"%s/statusInfos/%s/%s", + tmpPath->value,userMap->value, + cIdentifier->value); + fprintf(stderr,"--------------1--%s %s\n",tmp1,cIdentifier->value); + }else{ + sprintf(tmp1,"%s/statusInfos/%s", + tmpPath->value, + cIdentifier->value); + fprintf(stderr,"--------------2--%s %s\n",tmp1,cIdentifier->value); + + } + +// sprintf(tmp1,"%s/statusInfos/%s", +// tmpPath->value, +// cIdentifier->value); +// fprintf(stderr,"--------------2--%s %s\n",tmp1,cIdentifier->value); + + + if(mkdir(tmp1,0777) != 0 && errno != EEXIST){ + fprintf(stderr,"Issue creating directory %s\n",tmp1); + return NULL; + } + free(tmp1); + tmp1=(char*) malloc((strlen(tmpPath->value)+ + strlen(cIdentifier->value)+ + strlen(sessId->value)+20)*sizeof(char) + /*rdr*/ (1024*sizeof(char))); + int needResult=0; + char *message, *rstatus; + + + + if (userMap && userMap->value && strlen(userMap->value)>0 ){ + sprintf(tmp1,"%s/statusInfos/%s/%s/%s.json", + tmpPath->value,userMap->value, + cIdentifier->value, + sessId->value); + }else{ + sprintf(tmp1,"%s/statusInfos/%s/%s.json", + tmpPath->value, + cIdentifier->value, + sessId->value); + } + + return tmp1; + } + + /** + * Create the status file + * + * @param conf the maps containing the settings of the main.cfg file + * @param status an integer (SERVICE_ACCEPTED,SERVICE_STARTED...) + * @return an integer (0 in case of success, 1 in case of failure) + */ + int createStatusFile(maps* conf,int status){ + int needResult=0; + const char *message, *rstatus; + char* tmp1=json_getStatusFilePath(conf); + // Create statusInfo JSON object + // cf. https://github.com/opengeospatial/wps-rest-binding/blob/master/core/ + // openapi/schemas/statusInfo.yaml + json_object* res=json_object_new_object(); + json_object_object_add(res,"status",json_object_new_string("successful")); + switch(status){ + case SERVICE_ACCEPTED: + { + message=_("ZOO-Kernel accepted to run your service!"); + rstatus="accepted"; + break; + } + case SERVICE_STARTED: + { + message=_("ZOO-Kernel is currently running your service!"); + rstatus="running"; + break; + } + case SERVICE_PAUSED: + { + message=_("ZOO-Kernel pause your service!"); + rstatus="paused"; + break; + } + case SERVICE_SUCCEEDED: + { + message=_("ZOO-Kernel successfully ran your service!"); + rstatus="successful"; + needResult=1; + break; + } + default: + { + message=_("ZOO-Kernel failed to run your service!"); + rstatus="failed"; + break; + } + } + setMapInMaps(conf,"lenv","message",message); + setMapInMaps(conf,"lenv","status",rstatus); + + map* mess=getMapFromMaps(conf,"lenv","message"); + if(mess!=NULL) + json_object_object_add(res,"message",json_object_new_string(mess->value)); + + createStatusLinks(conf,needResult,res); + + FILE* foutput1=fopen(tmp1,"w+"); + if(foutput1!=NULL){ + const char* jsonStr1=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN); + fprintf(foutput1,"%s",jsonStr1); + fclose(foutput1); + }else{ + // Failure + setMapInMaps(conf,"lenv","message",_("Unable to store the statusInfo!")); + free(tmp1); + return 1; + } + free(tmp1); + return 0; + } + + /** + * Create the status file + * + * @param conf the maps containing the settings of the main.cfg file + * @return an integer (0 in case of success, 1 in case of failure) + */ + int json_getStatusFile(maps* conf){ + char* tmp1=json_getStatusFilePath(conf); + FILE* statusFile=fopen(tmp1,"rb"); + + map* tmpMap=getMapFromMaps(conf,"lenv","gs_usid"); + if(tmpMap!=NULL){ + char* tmpStr=_getStatus(conf,tmpMap->value); + if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){ + char *tmpStr1=zStrdup(tmpStr); + char *tmpStr0=zStrdup(strstr(tmpStr,"|")+1); + free(tmpStr); + tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0'; + setMapInMaps(conf,"lenv","PercentCompleted",tmpStr1); + setMapInMaps(conf,"lenv","gs_message",tmpStr0); + free(tmpStr0); + free(tmpStr1); + } + } + } + + /** + * Produce the JSON object for api info object + * + * @param conf the maps containing the settings of the main.cfg file + * @param res the JSON object for the api info + */ + void produceApiInfo(maps* conf,json_object* res,json_object* res5){ + json_object *res1=json_object_new_object(); + map* tmpMap=getMapFromMaps(conf,"provider","providerName"); + if(tmpMap!=NULL){ + json_object *res2=json_object_new_object(); + json_object_object_add(res2,"name",json_object_new_string(tmpMap->value)); + tmpMap=getMapFromMaps(conf,"provider","addressElectronicMailAddress"); + if(tmpMap!=NULL) + json_object_object_add(res2,"email",json_object_new_string(tmpMap->value)); + tmpMap=getMapFromMaps(conf,"provider","providerSite"); + if(tmpMap!=NULL) + json_object_object_add(res2,"url",json_object_new_string(tmpMap->value)); + json_object_object_add(res1,"contact",res2); + } + tmpMap=getMapFromMaps(conf,"identification","abstract"); + if(tmpMap!=NULL){ + json_object_object_add(res1,"description",json_object_new_string(tmpMap->value)); + json_object_object_add(res5,"description",json_object_new_string(tmpMap->value)); + tmpMap=getMapFromMaps(conf,"openapi","rootUrl"); + json_object_object_add(res5,"url",json_object_new_string(tmpMap->value)); + } + tmpMap=getMapFromMaps(conf,"identification","title"); + if(tmpMap!=NULL) + json_object_object_add(res1,"title",json_object_new_string(tmpMap->value)); + json_object_object_add(res1,"version",json_object_new_string(ZOO_VERSION)); + tmpMap=getMapFromMaps(conf,"identification","keywords"); + if(tmpMap!=NULL){ + char *saveptr; + char *tmps = strtok_r (tmpMap->value, ",", &saveptr); + json_object *res3=json_object_new_array(); + while (tmps != NULL){ + json_object_array_add(res3,json_object_new_string(tmps)); + tmps = strtok_r (NULL, ",", &saveptr); + } + json_object_object_add(res1,"x-keywords",res3); + } + maps* tmpMaps=getMaps(conf,"provider"); + if(tmpMaps!=NULL){ + json_object *res4=json_object_new_object(); + map* cItem=tmpMaps->content; + while(cItem!=NULL){ + json_object_object_add(res4,cItem->name,json_object_new_string(cItem->value)); + cItem=cItem->next; + } + json_object_object_add(res1,"x-ows-servicecontact",res4); + } + + json_object *res4=json_object_new_object(); + tmpMap=getMapFromMaps(conf,"main","license_name"); + if(tmpMap!=NULL){ + json_object_object_add(res4,"name",json_object_new_string(tmpMap->value)); + tmpMap=getMapFromMaps(conf,"main","license_url"); + if(tmpMap!=NULL){ + json_object_object_add(res4,"url",json_object_new_string(tmpMap->value)); + } + } + json_object_object_add(res1,"license",res4); + + json_object_object_add(res,"info",res1); + } + + /** + * Produce the JSON object for api parameter + * + * @param conf the maps containing the settings of the main.cfg file + * @param res the JSON object to populate with the parameters + */ + void produceApiParameters(maps* conf,json_object* res){ + json_object *res9=json_object_new_object(); + maps* tmpMaps1=getMaps(conf,"{id}"); + map* tmpMap2=getMapFromMaps(conf,"openapi","parameters"); + char *saveptr12; + char *tmps12 = strtok_r (tmpMap2->value, ",", &saveptr12); + while(tmps12!=NULL){ + char* tmpId=(char*) malloc((strlen(tmps12)+3)*sizeof(char)); + sprintf(tmpId,"{%s}",tmps12); + tmpMaps1=getMaps(conf,tmpId); + json_object *res8=json_object_new_object(); + if(tmpMaps1!=NULL){ + map* tmpMap=getMap(tmpMaps1->content,"title"); + if(tmpMap!=NULL) + json_object_object_add(res8,"x-internal-summary",json_object_new_string(tmpMap->value)); + tmpMap=getMap(tmpMaps1->content,"abstract"); + if(tmpMap!=NULL) + json_object_object_add(res8,"description",json_object_new_string(tmpMap->value)); + tmpMap=getMap(tmpMaps1->content,"example"); + if(tmpMap!=NULL) + json_object_object_add(res8,"example",json_object_new_string(tmpMap->value)); + tmpMap=getMap(tmpMaps1->content,"required"); + if(tmpMap!=NULL){ + if(strcmp(tmpMap->value,"true")==0) + json_object_object_add(res8,"required",json_object_new_boolean(TRUE)); + else + json_object_object_add(res8,"required",json_object_new_boolean(FALSE)); + } + else + json_object_object_add(res8,"required",json_object_new_boolean(FALSE)); + json_object_object_add(res8,"in",json_object_new_string("path")); + json_object_object_add(res8,"name",json_object_new_string(tmps12)); + json_object *res6=json_object_new_object(); + json_object *res7=json_object_new_object(); + tmpMap=getMap(tmpMaps1->content,"type"); + if(tmpMap!=NULL) + json_object_object_add(res6,"type",json_object_new_string(tmpMap->value)); + else + json_object_object_add(res6,"type",json_object_new_string("string")); + + json_object_object_add(res8,"schema",res6); + + } + + json_object_object_add(res9,tmps12,res8); + tmps12 = strtok_r (NULL, ",", &saveptr12); + } + tmpMap2=getMapFromMaps(conf,"openapi","header_parameters"); + char *saveptr13; + char *tmps13 = strtok_r (tmpMap2->value, ",", &saveptr13); + while(tmps13!=NULL){ + char* tmpId=zStrdup(tmps13); + maps *tmpMaps2=getMaps(conf,tmpId); + json_object *res8=json_object_new_object(); + if(tmpMaps2!=NULL){ + map* tmpMap=getMap(tmpMaps2->content,"title"); + if(tmpMap!=NULL) + json_object_object_add(res8,"x-internal-summary",json_object_new_string(tmpMap->value)); + tmpMap=getMap(tmpMaps2->content,"abstract"); + if(tmpMap!=NULL) + json_object_object_add(res8,"description",json_object_new_string(tmpMap->value)); + tmpMap=getMap(tmpMaps2->content,"example"); + if(tmpMap!=NULL) + json_object_object_add(res8,"example",json_object_new_string(tmpMap->value)); + tmpMap=getMap(tmpMaps2->content,"required"); + if(tmpMap!=NULL){ + if(strcmp(tmpMap->value,"true")==0) + json_object_object_add(res8,"required",json_object_new_boolean(TRUE)); + else + json_object_object_add(res8,"required",json_object_new_boolean(FALSE)); + } + else + json_object_object_add(res8,"required",json_object_new_boolean(FALSE)); + json_object_object_add(res8,"in",json_object_new_string("header")); + tmpMap=getMap(tmpMaps2->content,"name"); + if(tmpMap!=NULL) + json_object_object_add(res8,"name",json_object_new_string(tmpMap->value)); + json_object *res6=json_object_new_object(); + json_object *res7=json_object_new_object(); + tmpMap=getMap(tmpMaps2->content,"type"); + if(tmpMap!=NULL) + json_object_object_add(res6,"type",json_object_new_string(tmpMap->value)); + else + json_object_object_add(res6,"type",json_object_new_string("string")); + + { + tmpMap=getMap(tmpMaps2->content,"enum"); + if(tmpMap!=NULL){ + char *saveptr11; + char *tmps11 = strtok_r (tmpMap->value, ",", &saveptr11); + json_object *res71=json_object_new_array(); + while(tmps11!=NULL){ + json_object_array_add(res71,json_object_new_string(tmps11)); + tmps11 = strtok_r (NULL, ",", &saveptr11); + } + json_object_object_add(res6,"enum",res71); + } + } + + json_object_object_add(res8,"schema",res6); + + } + + json_object_object_add(res9,tmpId,res8); + tmps13 = strtok_r (NULL, ",", &saveptr13); + } + json_object_object_add(res,"parameters",res9); + } + + void produceApiComponents(maps*conf,json_object* res){ + json_object* res1=json_object_new_object(); + produceApiParameters(conf,res1); + json_object_object_add(res,"components",res1); + } + + /** + * Produce the JSON object for /api + * + * @param conf the maps containing the settings of the main.cfg file + * @param res the JSON object to populate + */ + void produceApi(maps* conf,json_object* res){ + json_object *res9=json_object_new_object(); + json_object *res10=json_object_new_object(); + maps* tmpMaps1=getMaps(conf,"{id}"); + + produceApiComponents(conf,res); + json_object *res4=json_object_new_object(); + setMapInMaps(conf,"headers","Content-Type","application/openapi+json; version=3.0;charset=UTF-8"); + + produceApiInfo(conf,res,res4); + map* tmpMap=getMapFromMaps(conf,"provider","providerName"); + + tmpMap=getMapFromMaps(conf,"openapi","version"); + if(tmpMap!=NULL) + json_object_object_add(res,"openapi",json_object_new_string(tmpMap->value)); + else + json_object_object_add(res,"openapi",json_object_new_string("3.0.2")); + + tmpMap=getMapFromMaps(conf,"openapi","paths"); + if(tmpMap!=NULL){ + json_object *res5=json_object_new_object(); + char *saveptr; + char *tmps = strtok_r (tmpMap->value, ",", &saveptr); + int cnt=0; + maps* tmpMaps; + json_object *paths=json_object_new_object(); + while (tmps != NULL){ + tmpMaps=getMaps(conf,tmps+1); + json_object *method=json_object_new_object(); + if(tmpMaps!=NULL){ + if(getMap(tmpMaps->content,"length")==NULL) + addToMap(tmpMaps->content,"length","1"); + map* len=getMap(tmpMaps->content,"length"); + + for(int i=0;ivalue);i++){ + json_object *methodc=json_object_new_object(); + map* cMap=getMapArray(tmpMaps->content,"method",i); + map* vMap=getMapArray(tmpMaps->content,"title",i); + if(vMap!=NULL) + json_object_object_add(methodc,"summary",json_object_new_string(vMap->value)); + vMap=getMapArray(tmpMaps->content,"abstract",i); + if(vMap!=NULL) + json_object_object_add(methodc,"description",json_object_new_string(vMap->value)); + vMap=getMapArray(tmpMaps->content,"tags",i); + if(vMap!=NULL){ + json_object *cc=json_object_new_array(); + json_object_array_add(cc,json_object_new_string(vMap->value)); + json_object_object_add(methodc,"tags",cc); + } + json_object *responses=json_object_new_object(); + json_object *cc3=json_object_new_object(); + vMap=getMapArray(tmpMaps->content,"schema",i); + if(vMap!=NULL){ + json_object *cc=json_object_new_object(); + json_object_object_add(cc,"$ref",json_object_new_string(vMap->value)); + json_object *cc0=json_object_new_object(); + json_object_object_add(cc0,"schema",cc); + json_object *cc1=json_object_new_object(); + map* tmpMap3=getMapFromMaps(conf,tmps,"type"); + if(tmpMap3!=NULL) + json_object_object_add(cc1,tmpMap3->value,cc0); + else + json_object_object_add(cc1,"application/json",cc0); + json_object *cc2=json_object_new_object(); + json_object_object_add(cc2,"content",cc1); + json_object_object_add(cc2,"description",json_object_new_string("successful operation")); + if(i==1) + json_object_object_add(cc3,"201",cc2); + else + json_object_object_add(cc3,"200",cc2); + }else{ + json_object *cc1=json_object_new_object(); + map* tmpMap3=getMapFromMaps(conf,tmps,"type"); + if(tmpMap3!=NULL) + json_object_object_add(cc1,tmpMap3->value,json_object_new_object()); + else + json_object_object_add(cc1,"application/json",json_object_new_object()); + json_object *cc2=json_object_new_object(); + json_object_object_add(cc2,"content",cc1); + json_object_object_add(cc2,"description",json_object_new_string("successful operation")); + if(i==1) + json_object_object_add(cc3,"201",cc2); + else + json_object_object_add(cc3,"200",cc2); + } + if(strstr(tmps,"{id}")!=NULL){ + vMap=getMapFromMaps(conf,"exception","schema"); + json_object *cc=json_object_new_object(); + json_object_object_add(cc,"$ref",json_object_new_string(vMap->value)); + json_object *cc01=json_object_new_array(); + json_object_array_add(cc01,cc); + + json_object *cc0=json_object_new_object(); + json_object_object_add(cc0,"schema",cc); + json_object *cc1=json_object_new_object(); + map* tmpMap3=getMapFromMaps(conf,"exception","type"); + if(tmpMap3!=NULL) + json_object_object_add(cc1,tmpMap3->value,cc0); + else + json_object_object_add(cc1,"application/json",cc0); + + json_object *cc2=json_object_new_object(); + json_object_object_add(cc2,"content",cc1); + if(strstr(tmps,"{jobID}")==NULL) + json_object_object_add(cc2,"description",json_object_new_string("The process with id {id} does not exist.")); + else + json_object_object_add(cc2,"description",json_object_new_string("The process with id {id} or job with id {jobID} does not exist.")); + json_object_object_add(cc3,"404",cc2); + json_object_object_add(cc3,"default",cc2); + } + json_object_object_add(methodc,"responses",cc3); + vMap=getMapArray(tmpMaps->content,"parameters",i); + if(vMap!=NULL){ + char *saveptr0; + char *tmps1 = strtok_r (vMap->value, ",", &saveptr0); + json_object *cc2=json_object_new_array(); + int cnt=0; + while(tmps1!=NULL){ + char* tmpStr=(char*)malloc((strlen(tmps1)+2)*sizeof(char)); + sprintf(tmpStr,"#%s",tmps1); + json_object *cc1=json_object_new_object(); + json_object_object_add(cc1,"$ref",json_object_new_string(tmpStr)); + json_object_array_add(cc2,cc1); + free(tmpStr); + cnt++; + tmps1 = strtok_r (NULL, ",", &saveptr0); + } + json_object_object_add(methodc,"parameters",cc2); + } + if(i==1){ + maps* tmpMaps1=getMaps(conf,"requestBody"); + if(tmpMaps1!=NULL){ + vMap=getMap(tmpMaps1->content,"schema"); + if(vMap!=NULL){ + json_object *cc=json_object_new_object(); + json_object_object_add(cc,"$ref",json_object_new_string(vMap->value)); + json_object *cc0=json_object_new_object(); + json_object_object_add(cc0,"schema",cc); + json_object *cc1=json_object_new_object(); + map* tmpMap3=getMap(tmpMaps->content,"type"); + if(tmpMap3!=NULL) + json_object_object_add(cc1,tmpMap3->value,cc0); + else + json_object_object_add(cc1,"application/json",cc0); + json_object *cc2=json_object_new_object(); + json_object_object_add(cc2,"content",cc1); + vMap=getMap(tmpMaps1->content,"abstract"); + if(vMap!=NULL) + json_object_object_add(cc2,"description",json_object_new_string(vMap->value)); + json_object_object_add(cc2,"required",json_object_new_boolean(true)); + json_object_object_add(methodc,"requestBody",cc2); + + } + } + } + map* mMap=getMapArray(tmpMaps->content,"method",i); + if(mMap!=NULL) + json_object_object_add(method,mMap->value,methodc); + else + json_object_object_add(method,"get",methodc); + + } + + tmpMap=getMapFromMaps(conf,"openapi","version"); + if(tmpMap!=NULL) + json_object_object_add(res,"openapi",json_object_new_string(tmpMap->value)); + else + json_object_object_add(res,"openapi",json_object_new_string("3.0.2")); + if(strstr(tmps,"/root")!=NULL) + json_object_object_add(paths,"/",method); + else + json_object_object_add(paths,tmps,method); + } + tmps = strtok_r (NULL, ",", &saveptr); + cnt++; + } + json_object_object_add(res,"paths",paths); + } + + tmpMap=getMapFromMaps(conf,"openapi","links"); + if(tmpMap!=NULL){ + + } + + json_object *res3=json_object_new_array(); + json_object_array_add(res3,res4); + json_object_object_add(res,"servers",res3); + } + + +#ifdef __cplusplus +} +#endif diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/zoo_service_loader.c b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/zoo_service_loader.c new file mode 100644 index 00000000..acde73da --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/patch/zooOld/zoo_service_loader.c @@ -0,0 +1,4064 @@ +/* + * Author : Gérald FENOY + * + * Copyright 2008-2013 GeoLabs SARL. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +extern "C" int yylex (); +extern "C" int crlex (); + +#ifdef META_DB +#include "ogrsf_frmts.h" +#if GDAL_VERSION_MAJOR >= 2 +#include +#endif +#endif + +#ifdef USE_OTB +#include "service_internal_otb.h" +#endif + +#ifdef USE_R +#include "service_internal_r.h" +#endif + +#ifdef USE_HPC +#include "service_internal_hpc.h" +#endif + +#ifdef USE_PYTHON +#include "service_internal_python.h" +#endif + +#include "cgic.h" + +#include +#include +#include +#include +#include + +#include "ulinet.h" + +#include +#include +#include + +#include "service.h" + +#include "service_internal.h" +#include "server_internal.h" +#include "response_print.h" +#include "request_parser.h" + + +#include +#include + + +#ifdef USE_JSON +#include "caching.h" +#endif +#include "sqlapi.h" + +#ifdef META_DB +#include "meta_sql.h" +#endif + +#ifdef USE_SAGA +#include "service_internal_saga.h" +#endif + +#ifdef USE_JAVA +#include "service_internal_java.h" +#endif + +#ifdef USE_PHP +#include "service_internal_php.h" +#endif + +#ifdef USE_JS +#include "service_internal_js.h" +#endif + +#ifdef USE_RUBY +#include "service_internal_ruby.h" +#endif + +#ifdef USE_PERL +#include "service_internal_perl.h" +#endif + +#ifdef USE_MONO +#include "service_internal_mono.h" +#endif + +#ifdef USE_CALLBACK +#include "service_callback.h" +#endif + +#ifdef USE_JSON +#include "service_json.h" +#include "json_tokener.h" +#endif + +#include +#include +#ifndef WIN32 +#include +#endif +#include +#ifndef WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#define pid_t int; +#endif +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +//rdr +//#ifndef WIN32 +#include +#include +#include +//#endif +//rdr + +#ifndef WIN32 +extern char **environ; +#endif + + +#ifdef WIN32 +extern "C" +{ + __declspec (dllexport) char *strcasestr (char const *a, char const *b) +#ifndef USE_MS + { + char *x = zStrdup (a); + char *y = zStrdup (b); + + x = _strlwr (x); + y = _strlwr (y); + char *pos = strstr (x, y); + char *ret = pos == NULL ? NULL : (char *) (a + (pos - x)); + free (x); + free (y); + return ret; + }; +#else + ; +#endif +} +#endif + +/** + * Translation function for zoo-kernel + */ +#define _(String) dgettext ("zoo-kernel",String) +/** + * Translation function for zoo-service + */ +#define __(String) dgettext ("zoo-service",String) + +#ifdef WIN32 +#ifndef PROGRAMNAME +#define PROGRAMNAME "zoo_loader.cgi" +#endif +#endif + + +/** + * Replace a char by another one in a string + * + * @param str the string to update + * @param toReplace the char to replace + * @param toReplaceBy the char that will be used + */ +void +translateChar (char *str, char toReplace, char toReplaceBy) +{ + int i = 0, len = strlen (str); + for (i = 0; i < len; i++) + { + if (str[i] == toReplace) + str[i] = toReplaceBy; + } +} + +/** + * Dump back the final file fbkp1 to fbkp + * + * @param m the conf maps containing the main.cfg settings + * @param fbkp the string corresponding to the name of the file + * @param fbkp1 the string corresponding to the name of the file + */ +int dumpBackFinalFile(maps* m,char* fbkp,char* fbkp1) +{ + FILE *f2 = fopen (fbkp1, "rb"); +#ifndef RELY_ON_DB + semid lid = getShmLockId (m, 1); + if (lid < 0) + return -1; + lockShm (lid); +#endif + FILE *f3 = fopen (fbkp, "wb+"); + free (fbkp); + fseek (f2, 0, SEEK_END); + long flen = ftell (f2); + fseek (f2, 0, SEEK_SET); + char *tmps1 = (char *) malloc ((flen + 1) * sizeof (char)); + fread (tmps1, flen, 1, f2); +#ifdef WIN32 + /* knut: I think this block can be dropped; pchr may be NULL if result is not in XML format + char *pchr=strrchr(tmps1,'>'); + flen=strlen(tmps1)-strlen(pchr)+1; + tmps1[flen]=0; + */ +#endif + fwrite (tmps1, 1, flen, f3); + fclose (f2); + fclose (f3); + free(tmps1); + return 1; +} + +char* replace_char(char* str, char find, char replace){ + char *current_pos = strchr(str,find); + while (current_pos){ + *current_pos = replace; + current_pos = strchr(current_pos,find); + } + return str; +} + +/** EOEPCA SPEC **/ + +//rdr +int mkpath(char *file_path, mode_t mode) { + // assert(file_path && *file_path); + if (file_path!=nullptr) + for (char *p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) { + *p = '\0'; + if (mkdir(file_path, mode) == -1) { + if (errno != EEXIST) { + *p = '/'; + return -1; + } + } + *p = '/'; + } + return 0; +} + + +//rdr +int +getUserWorkspacePath(maps* m,char* oldPatr,char* newPath,int maxSize){ + map *rdrMAP = getMapFromMaps (m, "eoepcaUser", "user"); + map *userWorkspace = getMapFromMaps (m, "eoepca", "userworkspace"); + memset(newPath,0,maxSize); + if (rdrMAP && rdrMAP->value && userWorkspace && userWorkspace->value){ + snprintf (newPath,maxSize, "%s/%s", userWorkspace->value,rdrMAP->value); + }else{ + if (oldPatr) + snprintf (newPath,maxSize, "%s", oldPatr); + } + return 0; +} + +//rdr +size_t calcDecodeLength(const char* b64input) { //Calculates the length of a decoded string + size_t len = strlen(b64input), + padding = 0; + if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are = + padding = 2; + else if (b64input[len-1] == '=') //last char is = + padding = 1; + + return (len*3)/4 - padding; +} +//rdr +int Base64Decode(char* b64message, unsigned char** buffer, size_t* length) { //Decodes a base64 encoded string + BIO *bio, *b64; + + int decodeLen = calcDecodeLength(b64message); + *buffer = (unsigned char*)malloc(decodeLen + 1); + (*buffer)[decodeLen] = '\0'; + + bio = BIO_new_mem_buf(b64message, -1); + b64 = BIO_new(BIO_f_base64()); + bio = BIO_push(b64, bio); + + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer + *length = BIO_read(bio, *buffer, strlen(b64message)); + // assert(*length == decodeLen); //length should equal decodeLen, else something went horribly wrong + BIO_free_all(bio); + + return (0); //success +} + +int exitFolder(const char* path){ + int ret=0; + DIR *dirp = opendir (path); + if (dirp != NULL){ + ret=1; + } + closedir (dirp); + return ret; +} + +//rdr +int createUserSpace(maps* conf,const char* User){ + int ret=0; + char* thePath=(char*)malloc(1024); + memset(thePath,'\0',1024); + getUserWorkspacePath(conf,NULL,thePath,1023); + + char* script=(char*)malloc(1024*3); + memset(script,'\0',1024*3); + + char* statusInfoPath=(char*)malloc(1024) ; + memset(statusInfoPath,'\0',1024); + + map *statusInfoPathMAP = getMapFromMaps (conf, "main", "tmpPath"); + if (statusInfoPathMAP && statusInfoPathMAP->value && strlen(statusInfoPathMAP->value)>0){ + sprintf(statusInfoPath,"%s/statusInfos/%s",statusInfoPathMAP->value,User); + }else{ + sprintf(statusInfoPath,"/var/www/_run/res/statusInfos/%s",User); + } + + + map *rdrMAP = getMapFromMaps (conf, "eoepca", "userSpaceScript"); + + if(rdrMAP && rdrMAP->value && strlen(rdrMAP->value)>0){ + sprintf(script,"%s \"%s\" \"%s\" \"%s\" 1>/dev/null",rdrMAP->value,thePath,statusInfoPath,User); + }else{ + sprintf(script,"/opt/t2scripts/prepareUserSpace.sh \"%s\" \"%s\" \"%s\" 1>/dev/null",thePath,statusInfoPath,User); + } + + fprintf(stderr,"creation script: %s \n",script); + + int y=system(script); +// if(!exitFolder(thePath)){ +// int a=zMkdir(thePath,0777); +// }else{ +// } +// + free(statusInfoPath); + free(thePath); + free(script); + + return y; +} + + +int removeService(maps* conf,char* service=NULL){ + + char* username=NULL; + char* anonymousUser=NULL; + char* userServicePath=NULL; + char* deleteScript=NULL; + char* JWT = NULL; + + if (conf && service){ + + dumpMaps(conf); + maps* eoepcaMap=getMaps(conf,"eoepca"); + + + maps* userMap=getMaps(conf,"eoepcaUser"); + if (userMap){ + map* theUser=getMap(userMap->content,"user"); + if (theUser){ + username=zStrdup(theUser->value); + } + } + + if (eoepcaMap){ + map* defaultUser=getMap(eoepcaMap->content,"defaultUser"); + if (defaultUser){ + anonymousUser=zStrdup(defaultUser->value); + } + + + map* userServicePathMap=getMap(eoepcaMap->content,"userworkspace"); + if (userServicePathMap){ + userServicePath=zStrdup(userServicePathMap->value); + } + + map* aa=getMap(userMap->content,"jwt"); + if (aa) + JWT = aa->value; + + + maps* pepMap=getMaps(conf,"pep"); + if (pepMap){ + map* usepep=getMap(pepMap->content,"usepep"); + map* pepresource=getMap(pepMap->content,"pepresource"); + map* pephost=getMap(pepMap->content,"pephost"); + map* onError=getMap(pepMap->content,"stopOnError"); + map* pathBase=getMap(pepMap->content,"pathBase"); + + int usePep= pepresource && pepresource->value && pephost && pephost->value && pathBase && pathBase->value ?1:0; + usePep = usePep && strcmp(anonymousUser,username)!=0; + + int stopOnError=0; + if (onError && onError->value && strcmp(onError->value,"true")==0 ){ + stopOnError=1; + } + + + if (usepep && usepep->value && strcmp(usepep->value,"true")==0 ){ + if (usePep){ + void *handle=NULL; + handle = dlopen(pepresource->value, RTLD_LAZY); + fprintf(stderr,"-->pepresource: %s \n", pepresource->value ); + if (handle) { + long (*pepRemoveFromZoo)(const char*,const char*,char* jwt,int ) = + (long (*)(const char* ,const char* /*base uri*/,char* jwt,int ))dlsym(handle, "pepRemoveFromZoo"); + + if(pepRemoveFromZoo){ + fprintf(stderr,"-->pep SEND REMOVE!!!\n"); + char* serviceToDelete = (char*)malloc(2048); + memset(serviceToDelete,0,2048); + snprintf(serviceToDelete,2047,pathBase->value,username,service); + fprintf(stderr,"jwt:%s\n user: %s\n service: %s\npath: %s\n",JWT,username,service,serviceToDelete); + + long a = pepRemoveFromZoo(serviceToDelete,pephost->value,JWT,stopOnError); + fprintf(stderr,"-->pep END REMOVE!!!\n"); + free(serviceToDelete); + if (a!=200 && stopOnError){ + memset(serviceToDelete,0,2048); + snprintf(serviceToDelete,2047,"PEP result: %l on service: %s",a,service); + errorException (conf, _("pepRemoveFromZoo"),serviceToDelete, NULL); + free(serviceToDelete); + serviceToDelete=NULL; + return a; + } + + }else{ + fprintf(stderr,"-->can't bind libs: %s on %s \n", pepresource->value,"pepRemoveFromZoo"); + } + }else{ + fprintf(stderr,"-->can't open libs: %s \n", pepresource->value ); + } + if(handle){ + dlclose(handle); + } + } + } + } + + map* deleteScriptMap=getMap(eoepcaMap->content,"removeServiceScript"); + if (deleteScriptMap){ + deleteScript=zStrdup(deleteScriptMap->value); + } + } + +// maps* userMap=getMaps(conf,"eoepcaUser"); +// if (userMap){ +// map* theUser=getMap(userMap->content,"user"); +// if (theUser){ +// username=zStrdup(theUser->value); +// } +// } + + if( strcmp(anonymousUser,username)!=0 && deleteScript!=NULL ) { + if( + deleteScript && strlen(deleteScript)>0 + && username && strlen(username)>0 + && userServicePath && strlen(userServicePath)>0 + ){ + + char* script=(char*)malloc(1024*3); + memset(script,'\0',1024*3); + sprintf(script,"%s '%s' '%s' '%s' 1>/dev/null",deleteScript,userServicePath,username ,service ); + + fprintf(stderr,"%s\n",script); + int y=system(script); + + free(script); + } + } + } + + free(username); username=NULL; + free(anonymousUser);anonymousUser=NULL; + free(userServicePath);userServicePath=NULL; + free(deleteScript);deleteScript=NULL; + + return 0; +} + +/** + * + * @param conf + * @param s + * @param req + * @return 0 async 1 sync + */ + +#ifdef USE_JSON +int parseJRequestMode(maps* conf, service* s,json_object* req){ + json_object* the_mode=NULL; + char* c_the_mode=NULL; + if(json_object_object_get_ex(req,"mode",&the_mode)!=FALSE) { + int uLen=json_object_get_string_len(the_mode) * sizeof(char); + if (uLen>0) { + return strcasecmp(json_object_get_string(the_mode),"sync")==0?1:0; + } + } + return 0; +} +#endif + +//rdr +int +addUserToMap(maps* conf){ + int ret=0; + int ei = 1; + int canContinue=false; + char **orig = environ; + char *s=*orig; + char* username=NULL; + char* JWT=NULL; + + char* anonymousUser=NULL; + + if (conf){ + maps* anonymousMap=getMaps(conf,"eoepca"); + if (anonymousMap){ + map* defaultUser=getMap(anonymousMap->content,"defaultUser"); + if (defaultUser){ + anonymousUser=zStrdup(defaultUser->value); + } + } + } + + if(orig!=NULL) + for (; s; ei++ ) { + if(strstr(s,"=")!=NULL && strlen(strstr(s,"="))>1){ + + if (strstr(s,"EOEPCA_WORKSPACE")!=NULL){ + char* baseU=strchr(s,'='); + if (strlen(baseU)>1){ + char* workspace= ++baseU; +// fprintf(stderr,"GNAGNERA >%s<\n",workspace); + + + username = zStrdup(workspace); + + maps *_tmpMaps = createMaps("eoepcaUser"); + if(_tmpMaps->content == NULL) + _tmpMaps->content = createMap ("user",workspace); + else + addToMap (_tmpMaps->content,"user",workspace); + + if( strcmp(anonymousUser,workspace)==0 ){ + // it is anonymous, can only reads + // rwx + map *theGrants = createMap("grant","1--"); + addMapToMap(&_tmpMaps->content,theGrants); + }else{ + // it is ok! + map *theGrants = createMap("grant","111"); + addMapToMap(&_tmpMaps->content,theGrants); + } + + if(conf){ + addMapsToMaps (&conf, _tmpMaps); + } + } + } + + + if(strstr(s,"HTTP_AUTHORIZATION")!=NULL && strlen(strstr(s,"="))>1 && strstr(s,"REDIRECT_HTTP_AUTHORIZATION")==NULL) { + char *baseU = strchr(s, '='); + if (baseU) { + char *baseS = strchr(++baseU, ' '); + if (baseS) { + *baseS = '\0'; + fprintf(stderr, "**** %s\n", baseU); + if (strcmp(baseU, "Bearer") == 0) { + canContinue = true; + } + *baseS = ' '; + if (canContinue) { + while (*(++baseS) == ' '); + fprintf(stderr, ">%s<\n", baseS); + JWT = zStrdup(baseS); + } + } + } + } + + if(false && strstr(s,"HTTP_AUTHORIZATION")!=NULL && strlen(strstr(s,"="))>1 && strstr(s,"REDIRECT_HTTP_AUTHORIZATION")==NULL){ + // fprintf(stderr,"--> %s=%s \n", tmpName1, tmpValue ); + char* baseU=strchr(s,'='); + if (baseU){ + char* baseS=strchr(++baseU,' '); + if (baseS){ + *baseS='\0'; + fprintf(stderr,"**** %s\n",baseU); + if (strcmp(baseU,"Bearer")==0){ + canContinue=true; + } + *baseS=' '; + if (canContinue){ + while (*(++baseS)==' '); + fprintf(stderr,">%s<\n",baseS); + + char* HEADER=baseS; + char* PAYLOAD=NULL; + char* VERIFY_SIGNATURE=NULL; + + char* tmpP=strchr(HEADER,'.'); + if (tmpP){ + *tmpP='\0'; + PAYLOAD=tmpP+1; + tmpP=strchr(PAYLOAD ,'.'); + if (tmpP){ + *tmpP='\0'; + VERIFY_SIGNATURE=tmpP+1; + int bufferLen=0; + + size_t nPAYLOAD=(strlen(PAYLOAD)+2)*sizeof (char); + char* cPAYLOAD=(char*)malloc(nPAYLOAD); + memset(cPAYLOAD,'\0',nPAYLOAD); + memcpy(cPAYLOAD,PAYLOAD,(strlen(PAYLOAD))*sizeof (char)); + *(cPAYLOAD+strlen(PAYLOAD)) = '='; + + unsigned char* buffer=NULL; + size_t theLen=0; + Base64Decode(cPAYLOAD,&buffer,&theLen); + + fprintf(stderr,"PAYLOAD %s\n",PAYLOAD); + fprintf(stderr,"PAYLOAD %s\n",cPAYLOAD); + fprintf(stderr,"buffer %s\n",(char*)buffer); + + struct json_object *jobj; + jobj = json_tokener_parse((char*)buffer/*(char *)buffer*/); + + if(jobj){ + fprintf(stderr,"jobj from str:\n---\n%s\n---\n", json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY)); + json_object* pct_claims=NULL; + if(json_object_object_get_ex(jobj,"pct_claims",&pct_claims)!=FALSE){ + + json_object* user_names=NULL; + if(json_object_object_get_ex(pct_claims,"user_name",&user_names)!=FALSE){ + int arraylen; + json_object *medi_array=NULL,*medi_array_obj=NULL; + arraylen = json_object_array_length(user_names); + if (arraylen>0){ + medi_array_obj=json_object_array_get_idx(user_names, 0); + + int uLen=json_object_get_string_len(medi_array_obj) * sizeof(char); + + if (uLen>0){ + username=(char*)malloc(uLen+1); + memset(username,'\0',uLen+1); + memcpy(username,json_object_get_string(medi_array_obj),uLen); + fprintf(stderr,">>>>%s<<<<<=====>>>>>\n",username); + + maps *_tmpMaps = createMaps("eoepcaUser"); + if(_tmpMaps->content == NULL) + _tmpMaps->content = createMap ("user",username); + else + addToMap (_tmpMaps->content,"user",username); + + if( strcmp(anonymousUser,username)==0 ){ + // it is anonymous, can only reads + // rwx + map *theGrants = createMap("grant","1--"); + addMapToMap(&_tmpMaps->content,theGrants); + }else{ + // it is ok! + map *theGrants = createMap("grant","111"); + addMapToMap(&_tmpMaps->content,theGrants); + } + + if(conf){ + addMapsToMaps (&conf, _tmpMaps); + } + + } + } + } + } + }else{ + fprintf(stderr,"can't convert the json string >%s< \n",(char*)buffer); + ret=1; + } + + if(jobj){ + json_object_put(jobj); + } + free(cPAYLOAD); + free(buffer); + } + } + } + } + } + } + } + s = *(orig+ei); + } + + maps* userMap=getMaps(conf,"eoepcaUser"); + if(!userMap && ret==0){ + maps *_tmpMaps = createMaps("eoepcaUser"); + _tmpMaps->content = createMap ("user", (anonymousUser?anonymousUser:"anonymous")); + map *theGrants = createMap("grant","1--"); + addMapToMap(&_tmpMaps->content,theGrants); + addMapsToMaps (&conf, _tmpMaps); + if(username){ + free(username); + } + username=zStrdup( anonymousUser?anonymousUser:"anonymous" ); + } + + if(userMap && ret==0) { + if (JWT){ + map *theYWT = createMap("jwt",zStrdup(JWT)); + addMapToMap(&userMap->content,theYWT); + } + } + + int sc=createUserSpace(conf,username); + + if(username){ + free(username); + } + + if(anonymousUser){ + free(anonymousUser); + } + + if (JWT){ + free(JWT); + } + + return ret; +} + +/** EOEPCA SPEC END **/ + + + +/** + * Recursivelly parse zcfg starting from the ZOO-Kernel cwd. + * Call the func function given in arguments after parsing the ZCFG file. + * + * @param m the conf maps containing the main.cfg settings + * @param r the registry containing profiles hierarchy + * @param n the root XML Node to add the sub-elements + * @param conf_dir the location of the main.cfg file (basically cwd) + * @param prefix the current prefix if any, or NULL + * @param saved_stdout the saved stdout identifier + * @param level the current level (number of sub-directories to reach the + * current path) + * @param func a pointer to a function having 4 parameters + * (registry*, maps*, xmlNodePtr and service*). + * @see inheritance, readServiceFile + */ +int +recursReaddirF ( maps * m, registry *r, void* doc1, void* n1, char *conf_dir_, + //( maps * m, registry *r, xmlDocPtr doc, xmlNodePtr n, char *conf_dir, + char *prefix, int saved_stdout, int level, + void (func) (registry *, maps *, void*, void*, service *) ) + //void (func) (registry *, maps *, xmlDocPtr, xmlNodePtr, service *) ) +{ + + // rdr + char conf_dir[1024]; + getUserWorkspacePath(m,conf_dir_,conf_dir,1024); + // fprintf(stderr,"2################%s##################\n",conf_dir); + // fprintf(stderr,"2################%s##################\n",conf_dir); + + + struct dirent *dp; + int scount = 0; + xmlDocPtr doc=(xmlDocPtr) doc1; + xmlNodePtr n=(xmlNodePtr) n1; + if (conf_dir == NULL) + return 1; + DIR *dirp = opendir (conf_dir); + if (dirp == NULL) + { + if (level > 0) + return 1; + else + return -1; + } + char tmp1[25]; + sprintf (tmp1, "sprefix_%d", level); + char levels[17]; + sprintf (levels, "%d", level); + setMapInMaps (m, "lenv", "level", levels); + while ((dp = readdir (dirp)) != NULL) + if ((dp->d_type == DT_DIR || dp->d_type == DT_LNK) && dp->d_name[0] != '.' + && strstr (dp->d_name, ".") == NULL) + { + + char *tmp = + (char *) malloc ((strlen (conf_dir) + strlen (dp->d_name) + 2) * + sizeof (char)); + sprintf (tmp, "%s/%s", conf_dir, dp->d_name); + + if (prefix != NULL) + { + prefix = NULL; + } + prefix = (char *) malloc ((strlen (dp->d_name) + 2) * sizeof (char)); + sprintf (prefix, "%s.", dp->d_name); + + //map* tmpMap=getMapFromMaps(m,"lenv",tmp1); + + int res; + if (prefix != NULL) + { + setMapInMaps (m, "lenv", tmp1, prefix); + char levels1[17]; + sprintf (levels1, "%d", level + 1); + setMapInMaps (m, "lenv", "level", levels1); + res = + recursReaddirF (m, r, doc, n, tmp, prefix, saved_stdout, level + 1, + func); + sprintf (levels1, "%d", level); + setMapInMaps (m, "lenv", "level", levels1); + free (prefix); + prefix = NULL; + } + else + res = -1; + free (tmp); + if (res < 0) + { + return res; + } + } + else + { + // map* tmpMap=getMapFromMaps(m,"lenv",tmp1); + fprintf(stderr,"rdr a5b %s \n",dp->d_name); + char* extn = strstr(dp->d_name, ".zcfg"); + if(dp->d_name[0] != '.' && extn != NULL && strlen(extn) == 5 && strlen(dp->d_name)>6) + { + int t; + char tmps1[1024]; + memset (tmps1, 0, 1024); + snprintf (tmps1, 1024, "%s/%s", conf_dir, dp->d_name); + + char *tmpsn = (char*)malloc((strlen(dp->d_name)-4)*sizeof(char));//zStrdup (dp->d_name); + memset (tmpsn, 0, strlen(dp->d_name)-4); + snprintf(tmpsn,strlen(dp->d_name)-4,"%s",dp->d_name); + + map* import = getMapFromMaps (m, IMPORTSERVICE, tmpsn); + if (import == NULL || import->value == NULL || zoo_path_compare(tmps1, import->value) != 0 ) { // service is not in [include] block + service *s1 = createService(); + if (s1 == NULL) + { + zDup2 (saved_stdout, fileno (stdout)); + errorException (m, _("Unable to allocate memory"), + "InternalError", NULL); + return -1; + } + #ifdef DEBUG + fprintf (stderr, "#################\n%s\n#################\n", + tmps1); + #endif + t = readServiceFile (m, tmps1, &s1, tmpsn); + free (tmpsn); + if (t < 0) + { + map *tmp00 = getMapFromMaps (m, "lenv", "message"); + char tmp01[1024]; + if (tmp00 != NULL) + sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"), + dp->d_name, tmp00->value); + else + sprintf (tmp01, _("Unable to parse the ZCFG file: %s."), + dp->d_name); + zDup2 (saved_stdout, fileno (stdout)); + errorException (m, tmp01, "InternalError", NULL); + return -1; + } + #ifdef DEBUG + dumpService (s1); + fflush (stdout); + fflush (stderr); + #endif + if(s1!=NULL) + inheritance(r,&s1); + func (r, m, doc, n, s1); + freeService (&s1); + free (s1); + scount++; + } + } + } + (void) closedir (dirp); + return 1; +} + +/** + * When th zcfg file is not found, print error message and cleanup memory + * @param zooRegistry the populated registry + * @param m the maps pointer to the content of main.cfg file + * @param zcfg the zcfg file name + * @param code the string determining the nature of the error + * @param locator the string determining which parameter the error refer to + * @param orig the service name + * @param corig the current service name (in case multiple services was parsed) + * @param funcError the function used to print the error back + */ +void exitAndCleanUp(registry* zooRegistry, maps* m, + const char* zcfg,const char* code,const char* locator, + char* orig,char* corig, + void (funcError) (maps*, map*)){ + map *tmp00 = getMapFromMaps (m, "lenv", "message"); + char tmp01[1024]; + if (tmp00 != NULL) + sprintf (tmp01, + _("Unable to parse the ZCFG file: %s (%s)"), + zcfg, tmp00->value); + else + sprintf (tmp01, + _("Unable to parse the ZCFG file: %s."), + zcfg); + map* errormap = createMap("text", tmp01); + addToMap(errormap,"code", code); + addToMap(errormap,"locator", locator); + funcError(m,errormap); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (orig); + if (corig != NULL) + free (corig); + //xmlFreeDoc (doc); + xmlCleanupParser (); + zooXmlCleanupNs (); + freeMap(&errormap); + free(errormap); +} + + +/** + * Search services from various possible sources + * + * @param zopRegistry the populated registry + * @param m the maps pointer to the content of main.cfg file + * @param r_inputs the service(s) name(s) + * @param func the function used to print the result back + * @param doc the xml document or NULL (for json) + * @param n the xmlNode of JSON object pointer to the current element + * @param conf_dir the directory where the main.cfg has been found + * @param request_inputs the map pointer to the request KVP if any + * @param funcError the function used to print the error back + * @return 0 in case of success, 1 otherwise + */ +int fetchServicesForDescription(registry* zooRegistry, maps* m, char* r_inputs, + void (func) (registry *, maps *, void*, void*, service *), + void* doc, void* n, char* conf_dir_, map* request_inputs, + void (funcError) (maps*, map*) ){ + + char conf_dir[1024]; + // rdr + getUserWorkspacePath(m,conf_dir_,conf_dir,1024); + + char *orig = zStrdup (r_inputs); + service* s1=NULL; + int saved_stdout = zDup (fileno (stdout)); + int t; + int scount = 0; + struct dirent *dp; + + zDup2 (fileno (stderr), fileno (stdout)); + if (strcasecmp ("all", orig) == 0) + { + maps* imports = getMaps(m, IMPORTSERVICE); + if (imports != NULL) { + map* zcfg = imports->content; + + while (zcfg != NULL) { + if (zcfg->value != NULL) { + service* svc = (service*) malloc(SERVICE_SIZE); + if (svc == NULL || readServiceFile(m, zcfg->value, &svc, zcfg->name) < 0) { + // pass over silently + zcfg = zcfg->next; + continue; + } + inheritance(zooRegistry, &svc); +#ifdef USE_HPC + addNestedOutputs(&svc); +#endif + + func(zooRegistry, m, doc, n, svc); + freeService(&svc); + free(svc); + } + zcfg = zcfg->next; + } + } + if (int res = + recursReaddirF (m, zooRegistry, doc, n, conf_dir, NULL, saved_stdout, 0, + func) < 0) + return res; +#ifdef META_DB + fetchServicesFromDb(zooRegistry,m,doc,n,func,0); + close_sql(m,0); +#endif + } + else + { + DIR *dirp = opendir (conf_dir); + char *saveptr; + char *tmps = strtok_r (orig, ",", &saveptr); + + char buff[256]; + char buff1[1024]; + while (tmps != NULL) + { + int hasVal = -1; + char *corig = zStrdup (tmps); + map* import = getMapFromMaps (m, IMPORTSERVICE, corig); + if (import != NULL && import->value != NULL) + { +#ifdef META_DB + service* s2=extractServiceFromDb(m,import->name,0); + if(s2==NULL){ +#endif + s1 = createService(); + t = readServiceFile (m, import->value, &s1, import->name); + + if (t < 0) // failure reading zcfg + { + zDup2 (saved_stdout, fileno (stdout)); + exitAndCleanUp(zooRegistry, m, + tmps,"InvalidParameterValue","identifier", + orig,corig, + funcError); + return 1; + } +#ifdef DEBUG + dumpService (s1); +#endif + inheritance(zooRegistry,&s1); +#ifdef USE_HPC + addNestedOutputs(&s1); +#endif + func (zooRegistry, m, doc, n, s1); + freeService (&s1); + free (s1); + s1 = NULL; + scount++; + hasVal = 1; +#ifdef META_DB + } +#endif + } + else if (strstr (corig, ".") != NULL) + { + parseIdentifier (m, conf_dir, corig, buff1); + map *tmpMap = getMapFromMaps (m, "lenv", "metapath"); + if (tmpMap != NULL) + addToMap (request_inputs, "metapath", tmpMap->value); + map *tmpMapI = getMapFromMaps (m, "lenv", "Identifier"); + /** + * No support for dot in service name stored in metadb!? + #ifdef META_DB + service* s2=extractServiceFromDb(m,tmpMapI->value,0); + if(s2==NULL){ + #endif + */ + s1 = createService(); + t = readServiceFile (m, buff1, &s1, tmpMapI->value); + if (t < 0) + { + zDup2 (saved_stdout, fileno (stdout)); + exitAndCleanUp(zooRegistry, m, + tmps,"InvalidParameterValue","identifier", + orig,corig, + funcError); + return 1; + } +#ifdef DEBUG + dumpService (s1); +#endif + inheritance(zooRegistry,&s1); +#ifdef USE_HPC + addNestedOutputs(&s1); +#endif + func (zooRegistry, m, doc, n, s1); + freeService (&s1); + free (s1); + s1 = NULL; + scount++; + hasVal = 1; + setMapInMaps (m, "lenv", "level", "0"); + } + else + { +#ifdef META_DB + _init_sql(m,"metadb"); + //FAILED CONNECTING DB + if(getMapFromMaps(m,"lenv","dbIssue")!=NULL){ + fprintf(stderr,"ERROR CONNECTING METADB"); + } + service* s2=extractServiceFromDb(m,corig,0); + if(s2!=NULL){ + inheritance(zooRegistry,&s2); +#ifdef USE_HPC + addNestedOutputs(&s2); +#endif + func (zooRegistry,m, doc, n, s2); + freeService (&s2); + free (s2); + s2 = NULL; + hasVal = 1; + }else /*TOTO*/{ +#endif + memset (buff, 0, 256); + fprintf(stderr,"rdr a6\n"); + snprintf (buff, 256, "%s.zcfg", corig); + memset (buff1, 0, 1024); +#ifdef DEBUG + printf ("\n#######%s\n########\n", buff); +#endif + while ((dp = readdir (dirp)) != NULL) + { + if (strcasecmp (dp->d_name, buff) == 0) + { + memset (buff1, 0, 1024); + snprintf (buff1, 1024, "%s/%s", conf_dir, + dp->d_name); + s1 = createService(); + if (s1 == NULL) + { + zDup2 (saved_stdout, fileno (stdout)); + map* errormap = createMap("text", _("Unable to allocate memory")); + addToMap(errormap,"code", "InternalError"); + addToMap(errormap,"locator", "NULL"); + funcError(m,errormap); + return -1; + } +#ifdef DEBUG_SERVICE_CONF + fprintf + (stderr,"#################\n(%s) %s\n#################\n", + r_inputs->value, buff1); +#endif + char *tmp0 = zStrdup (dp->d_name); + tmp0[strlen (tmp0) - 5] = 0; + t = readServiceFile (m, buff1, &s1, tmp0); + free (tmp0); + if (t < 0) + { + zDup2 (saved_stdout, fileno (stdout)); + exitAndCleanUp(zooRegistry, m, + buff,"InternalError","NULL", + orig,corig, + funcError); + return 1; + } +#ifdef DEBUG + dumpService (s1); +#endif + inheritance(zooRegistry,&s1); +#ifdef USE_HPC + addNestedOutputs(&s1); +#endif + func (zooRegistry,m, doc, n, s1); + freeService (&s1); + free (s1); + s1 = NULL; + scount++; + hasVal = 1; + } + } +#ifdef META_DB + } +#endif + } + if (hasVal < 0) + { + zDup2 (saved_stdout, fileno (stdout)); + exitAndCleanUp(zooRegistry, m, + buff,"InvalidParameterValue","Identifier", + orig,corig, + funcError); + return 1; + } + rewinddir (dirp); + tmps = strtok_r (NULL, ",", &saveptr); + if (corig != NULL) + free (corig); + } + } + fflush (stdout); + zDup2 (saved_stdout, fileno (stdout)); + free (orig); + return 0; +} + +/** + * Run every HTTP request to download inputs passed as reference + * + * @param conf the maps pointing to the main.cfg file content + * @param inputs the maps pointing to the inputs provided in the request + */ +int loadHttpRequests(maps* conf,maps* inputs){ + // Resolve reference + // TODO: add erro gesture + int eres; + maps* tmpMaps=getMaps(conf,"http_requests"); + if(tmpMaps!=NULL){ + map* lenMap=getMap(tmpMaps->content,"length"); + int len=0; + if(lenMap!=NULL){ + len=atoi(lenMap->value); + } + HINTERNET hInternet; + HINTERNET res; + if(len>0) + hInternet = InternetOpen ( +#ifndef WIN32 + (LPCTSTR) +#endif + "ZOO-Project WPS Client\0", + INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + for(int j=0;jcontent,"url",j); + map* tmpInput=getMapArray(tmpMaps->content,"input",j); + maps* currentMaps=getMaps(inputs,tmpInput->value); + loadRemoteFile(&conf,¤tMaps->content,&hInternet,tmpUrl->value); + addIntToMap(currentMaps->content,"Order",hInternet.nb); + addToMap(currentMaps->content,"Reference",tmpUrl->value); + } + if(len>0){ + map* error=NULL; + runHttpRequests(&conf,&inputs,&hInternet,&error); + InternetCloseHandle(&hInternet); + } + } + return 0; +} + +/** + * Returns current UTC timestamp + * @param dest + * @return + */ +char *getUtcTimestamp(char *dest) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm *tmp = gmtime(&tv.tv_sec); + char fmt[128]; + strftime(fmt, sizeof(fmt), "%Y-%m-%dT%H:%M:%S.%%06uZ", tmp); + sprintf(dest, fmt, tv.tv_usec); + return dest; +} + + +/** + * Initialize environment sections, load env, and populate lenv and renv. + * + * @param conf the maps pointing to the main.cfg file content + * @param request_inputs the map pointing to the request KVP + * @param cPath a string pointing to the cwd + * @param request a string pointing to the request key (xrequest or jrequest) + */ +void initAllEnvironment(maps* conf,map* request_inputs, + const char* cPath,const char* request){ + // Define each env variable in runing environment + maps *curs = getMaps (conf, "env"); + if (curs != NULL) { + map *mapcs = curs->content; + while (mapcs != NULLMAP) + { +#ifndef WIN32 + setenv (mapcs->name, mapcs->value, 1); +#ifdef DEBUG + fprintf (stderr, "[ZOO: setenv (%s=%s)]\n", mapcs->name, + mapcs->value); +#endif +#else + if (mapcs->value[strlen (mapcs->value) - 2] == '\r') + { +#ifdef DEBUG + fprintf (stderr, "[ZOO: Env var finish with \r]\n"); +#endif + mapcs->value[strlen (mapcs->value) - 1] = 0; + } +#ifdef DEBUG + if (SetEnvironmentVariable (mapcs->name, mapcs->value) == 0) + { + fflush (stderr); + fprintf (stderr, "setting variable... %s\n", "OK"); + } + else + { + fflush (stderr); + fprintf (stderr, "setting variable... %s\n", "OK"); + } +#else + SetEnvironmentVariable (mapcs->name, mapcs->value); +#endif + char *toto = + (char *) + malloc ((strlen (mapcs->name) + strlen (mapcs->value) + + 2) * sizeof (char)); + sprintf (toto, "%s=%s", mapcs->name, mapcs->value); + _putenv (toto); +#ifdef DEBUG + fflush (stderr); +#endif +#endif + +#ifdef DEBUG + fprintf (stderr, "[ZOO: setenv (%s=%s)]\n", mapcs->name, + mapcs->value); + fflush (stderr); +#endif + mapcs = mapcs->next; + } + } + + + + int eres = SERVICE_STARTED; + int cpid = zGetpid (); + + // Create a map containing a copy of the request map + maps *_tmpMaps = createMaps("request"); + addMapToMap(&_tmpMaps->content,request_inputs); + addMapsToMaps (&conf, _tmpMaps); + freeMaps (&_tmpMaps); + free (_tmpMaps); + /** + * Initialize the specific [lenv] section which contains runtime variables: + * + * - usid : it is an universally unique identifier + * - osid : it is an idenfitication number + * - sid : it is the process idenfitication number (OS) + * - uusid : it is an universally unique identifier + * - status : value between 0 and 100 to express the completude of + * the operations of the running service + * - message : is a string where you can store error messages, in case + * service is failing, or o provide details on the ongoing operation. + * - cwd : the current working directory or servicePath if defined + * - soap : is a boolean value, true if the request was contained in a SOAP + * Envelop + * - sessid : string storing the session identifier (only when cookie is + * used) + * - cgiSid : only defined on Window platforms (for being able to identify + * the created process) + * + */ + _tmpMaps = createMaps("lenv"); + char tmpBuff[100]; + struct ztimeval tp; + if (zGettimeofday (&tp, NULL) == 0) + sprintf (tmpBuff, "%i", (cpid + ((int) tp.tv_sec + (int) tp.tv_usec))); + else + sprintf (tmpBuff, "%i", (cpid + (int) time (NULL))); + _tmpMaps->content = createMap ("osid", tmpBuff); + sprintf (tmpBuff, "%i", cpid); + addToMap (_tmpMaps->content, "sid", tmpBuff); + char* tmpUuid=get_uuid(); + addToMap (_tmpMaps->content, "uusid", tmpUuid); + addToMap (_tmpMaps->content, "usid", tmpUuid); + free(tmpUuid); + addToMap (_tmpMaps->content, "status", "0"); + + // UTC timestamp of the time of the job start + char dest[12]; + addToMap (_tmpMaps->content, "started", getUtcTimestamp(dest)); + map* cwdMap0=getMapFromMaps(conf,"main","servicePath"); + if(cwdMap0!=NULL){ + addToMap (_tmpMaps->content, "cwd", cwdMap0->value); + addToMap (_tmpMaps->content, "rcwd", cPath); + } + else + addToMap (_tmpMaps->content, "cwd", cPath); + addToMap (_tmpMaps->content, "message", _("No message provided")); + map *ltmp = getMap (request_inputs, "soap"); + if (ltmp != NULL) + addToMap (_tmpMaps->content, "soap", ltmp->value); + else + addToMap (_tmpMaps->content, "soap", "false"); + + // Parse the session file and add it to the main maps + char* originalCookie=NULL; + if (cgiCookie != NULL && strlen (cgiCookie) > 0) + { + int hasValidCookie = -1; + char *tcook = originalCookie = zStrdup (cgiCookie); + map *testing = getMapFromMaps (conf, "main", "cookiePrefix"); + parseCookie(&conf,originalCookie); + map *sessId=getMapFromMaps(conf,"cookies", + (testing==NULL?"ID":testing->value)); + if (sessId!=NULL) + { + addToMap (_tmpMaps->content, "sessid", sessId->value); + char session_file_path[1024]; + map *tmpPath = getMapFromMaps (conf, "main", "sessPath"); + if (tmpPath == NULL) + tmpPath = getMapFromMaps (conf, "main", "tmpPath"); + char *tmp1 = strtok (tcook, ";"); + if (tmp1 != NULL) + sprintf (session_file_path, "%s/sess_%s.cfg", tmpPath->value, + sessId->value); + else + sprintf (session_file_path, "%s/sess_%s.cfg", tmpPath->value, + sessId->value); + free (tcook); + maps *tmpSess = (maps *) malloc (MAPS_SIZE); + tmpSess->child=NULL; + struct stat file_status; + int istat = stat (session_file_path, &file_status); + if (istat == 0 && file_status.st_size > 0) + { + int saved_stdout = zDup (fileno (stdout)); + zDup2 (fileno (stderr), fileno (stdout)); + conf_read (session_file_path, tmpSess); + addMapsToMaps (&conf, tmpSess); + freeMaps (&tmpSess); + fflush(stdout); + zDup2 (saved_stdout, fileno (stdout)); + zClose(saved_stdout); + } + free (tmpSess); + } + } + addMapsToMaps (&conf, _tmpMaps); + freeMaps (&_tmpMaps); + free (_tmpMaps); + maps* bmap=NULL; +#ifdef DEBUG + dumpMap (request_inputs); +#endif + int ei = 1; + + _tmpMaps = createMaps("renv"); + +#ifdef WIN32 + LPVOID orig = GetEnvironmentStrings(); + LPTSTR s = (LPTSTR) orig; + + while (*s != NULL) { + char* env = strdup(s); + char* delim = strchr(env,'='); + if (delim != NULL) { + char* val = delim+1; + *delim = '\0'; + if(_tmpMaps->content == NULL) { + _tmpMaps->content = createMap(env,val); + } + else { + addToMap(_tmpMaps->content,env,val); + } + } + s += strlen(s)+1; + } + FreeEnvironmentStrings((LPCH)orig); +#else + char **orig = environ; + char *s=*orig; + + if(orig!=NULL) + for (; s; ei++ ) { + if(strstr(s,"=")!=NULL && strlen(strstr(s,"="))>1){ + int len=strlen(s); + char* tmpName=zStrdup(s); + char* tmpValue=strstr(s,"=")+1; + char* tmpName1=(char*)malloc((1+(len-(strlen(tmpValue)+1)))*sizeof(char)); + snprintf(tmpName1,(len-strlen(tmpValue)),"%s",tmpName); + if(_tmpMaps->content == NULL) + _tmpMaps->content = createMap (tmpName1,tmpValue); + else + addToMap (_tmpMaps->content,tmpName1,tmpValue); + free(tmpName1); + free(tmpName); + } + s = *(orig+ei); + } +#endif + + if(_tmpMaps->content!=NULL && getMap(_tmpMaps->content,"HTTP_COOKIE")!=NULL){ + addToMap(_tmpMaps->content,"HTTP_COOKIE1",&cgiCookie[0]); + } + addMapsToMaps (&conf, _tmpMaps); + freeMaps (&_tmpMaps); + free (_tmpMaps); + map* postRequest=getMap(request_inputs,request); + if(postRequest!=NULL) + setMapInMaps (conf, "renv", request, postRequest->value); +#ifdef WIN32 + char *cgiSidL = NULL; + if (getenv ("CGISID") != NULL) + addToMap (request_inputs, "cgiSid", getenv ("CGISID")); + + char* usidp; + if ( (usidp = getenv("USID")) != NULL ) { + setMapInMaps (conf, "lenv", "usid", usidp); + } + + map *test1 = getMap (request_inputs, "cgiSid"); + if (test1 != NULL){ + cgiSid = zStrdup(test1->value); + addToMap (request_inputs, "storeExecuteResponse", "true"); + addToMap (request_inputs, "status", "true"); + setMapInMaps (conf, "lenv", "osid", test1->value); + status = getMap (request_inputs, "status"); + } + test1 = getMap (request_inputs, "usid"); + if (test1 != NULL){ + setMapInMaps (conf, "lenv", "usid", test1->value); + setMapInMaps (conf, "lenv", "uusid", test1->value); + } +#endif + +} + +/** + * Signal handling function which simply call exit(0). + * + * @param sig the signal number + */ +void +donothing (int sig) +{ +#ifdef DEBUG + fprintf (stderr, "Signal %d after the ZOO-Kernel returned result!\n", sig); +#endif + exit (0); +} + +/** + * Signal handling function which create an ExceptionReport node containing the + * information message corresponding to the signal number. + * + * @param sig the signal number + */ +void +sig_handler (int sig) +{ + + char tmp[100]; + const char *ssig; + switch (sig) + { + case SIGSEGV: + ssig = "SIGSEGV"; + break; + case SIGTERM: + ssig = "SIGTERM"; + break; + case SIGINT: + ssig = "SIGINT"; + break; + case SIGILL: + ssig = "SIGILL"; + break; + case SIGFPE: + ssig = "SIGFPE"; + break; + case SIGABRT: + ssig = "SIGABRT"; + break; + default: + ssig = "UNKNOWN"; + break; + } + sprintf (tmp, + _ + ("ZOO Kernel failed to process your request, receiving signal %d = %s "), + sig, ssig); + errorException (NULL, tmp, "InternalError", NULL); +#ifdef DEBUG + fprintf (stderr, "Not this time!\n"); +#endif + exit (0); +} + +#ifdef USE_JSON + /** + * Signal handling function which create an ExceptionReport node containing the + * information message corresponding to the signal number. + * + * @param sig the signal number + */ +void json_sig_handler (int sig){ + char tmp[100]; + const char *ssig; + switch (sig) + { + case SIGSEGV: + ssig = "SIGSEGV"; + break; + case SIGTERM: + ssig = "SIGTERM"; + break; + case SIGINT: + ssig = "SIGINT"; + break; + case SIGILL: + ssig = "SIGILL"; + break; + case SIGFPE: + ssig = "SIGFPE"; + break; + case SIGABRT: + ssig = "SIGABRT"; + break; + default: + ssig = "UNKNOWN"; + break; + } + sprintf (tmp, + _ + ("ZOO Kernel failed to process your request, receiving signal %d = %s "), + sig, ssig); + map* tmpMap=createMap("decode","suze"); + maps* tmpMaps=createMaps("lenv"); + setMapInMaps(tmpMaps,"lenv","message",tmp); + setMapInMaps(tmpMaps,"lenv","status","failed"); + printExceptionReportResponseJ(tmpMaps,tmpMap); + //errorException (NULL, tmp, "InternalError", NULL); +#ifdef DEBUG + fprintf (stderr, "Not this time!\n"); +#endif + exit (0); +} + +#endif + +/** + * Load a service provider and run the service function. + * + * @param myMap the conf maps containing the main.cfg settings + * @param s1 the service structure + * @param request_inputs map storing all the request parameters + * @param inputs the inputs maps + * @param ioutputs the outputs maps + * @param eres the result returned by the service execution + */ +void +loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs, + maps ** inputs, maps ** ioutputs, int *eres) +{ + char eoUserPath[1024]; + char tmps1[1024]; + char ntmp[1024]; + maps *m = *myMap; + maps *request_output_real_format = *ioutputs; + maps *request_input_real_format = *inputs; + /** + * Extract serviceType to know what kind of service should be loaded + */ + + /** EOEPCA SPEC **/ + memset(eoUserPath,'\0',1024); + map* eoUserMap=getMapFromMaps(m,"eoepcaUser","user"); + map* eoUserPathMap=getMapFromMaps(m,"eoepca","userworkspace"); + + if( eoUserMap && strlen(eoUserMap->value)>0 && eoUserPathMap && strlen(eoUserPathMap->value)>0){ + + sprintf(eoUserPath,"%s/%s",eoUserPathMap->value,eoUserMap->value); + + fprintf(stderr,"MAP ALL:--> %s***************0 \n",eoUserPath); + + } + /** EOEPCA SPEC END **/ + + + map *r_inputs = NULL; + map* cwdMap=getMapFromMaps(m,"main","servicePath"); + if(cwdMap!=NULL){ + sprintf(ntmp,"%s",cwdMap->value); + }else{ +#ifndef WIN32 + getcwd (ntmp, 1024); +#else + _getcwd (ntmp, 1024); +#endif + } + r_inputs = getMap (s1->content, "serviceType"); +#ifdef DEBUG + fprintf (stderr, "LOAD A %s SERVICE PROVIDER \n", r_inputs->value); + fflush (stderr); +#endif + + map* libp = getMapFromMaps(m, "main", "libPath"); + if (strlen (r_inputs->value) == 1 + && strncasecmp (r_inputs->value, "C", 1) == 0) + { + if (libp != NULL && libp->value != NULL) { + r_inputs = getMap (s1->content, "ServiceProvider"); + sprintf (tmps1, "%s/%s", libp->value, r_inputs->value); + } + else { + r_inputs = getMap (request_inputs, "metapath"); + if (r_inputs != NULL) + sprintf (tmps1, "%s/%s", ntmp, r_inputs->value); + else + sprintf (tmps1, "%s/", ntmp); + + /** EOEPCA SPEC **/ + char *altPath = zStrdup ( strlen(eoUserPath)>0?eoUserPath:tmps1); + r_inputs = getMap (s1->content, "ServiceProvider"); + sprintf (tmps1, "%s/%s", altPath, r_inputs->value); + fprintf(stderr,"--->%s \n",tmps1); + free (altPath); + /** EOEPCA SPEC END **/ + } +#ifdef DEBUG + fprintf (stderr, "Trying to load %s\n", tmps1); +#endif +#ifdef WIN32 + HINSTANCE so = + LoadLibraryEx (tmps1, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); +#else + void *so = dlopen (tmps1, RTLD_LAZY); +#endif +#ifdef WIN32 + char* errstr = getLastErrorMessage(); +#else + char *errstr; + errstr = dlerror (); +#endif +#ifdef DEBUG + fprintf (stderr, "%s loaded (%s) \n", tmps1, errstr); +#endif + if (so != NULL) + { +#ifdef DEBUG + fprintf (stderr, "Library loaded %s \n", errstr); + fprintf (stderr, "Service Shared Object = %s\n", r_inputs->value); +#endif + r_inputs = getMap (s1->content, "serviceType"); +#ifdef DEBUG + dumpMap (r_inputs); + fprintf (stderr, "%s\n", r_inputs->value); + fflush (stderr); +#endif + if (strncasecmp (r_inputs->value, "C-FORTRAN", 9) == 0) + { + r_inputs = getMap (request_inputs, "Identifier"); + char fname[1024]; + sprintf (fname, "%s_", r_inputs->value); +#ifdef DEBUG + fprintf (stderr, "Try to load function %s\n", fname); +#endif +#ifdef WIN32 + typedef int (CALLBACK * execute_t) (char ***, char ***, + char ***); + execute_t execute = (execute_t) GetProcAddress (so, fname); +#else + typedef int (*execute_t) (char ***, char ***, char ***); + + char* nS = zStrdup(fname); + replace_char(nS,'.','_'); + replace_char(nS,'-','_'); + fprintf(stderr,"service from %s to %s\n",fname,nS); + execute_t execute = (execute_t) dlsym (so, fname); + free(nS); +#endif +#ifdef DEBUG +#ifdef WIN32 + errstr = getLastErrorMessage(); +#else + errstr = dlerror (); +#endif + fprintf (stderr, "Function loaded %s\n", errstr); +#endif + + char main_conf[10][30][1024]; + char inputs[10][30][1024]; + char outputs[10][30][1024]; + for (int i = 0; i < 10; i++) + { + for (int j = 0; j < 30; j++) + { + memset (main_conf[i][j], 0, 1024); + memset (inputs[i][j], 0, 1024); + memset (outputs[i][j], 0, 1024); + } + } + mapsToCharXXX (m, (char ***) main_conf); + mapsToCharXXX (request_input_real_format, (char ***) inputs); + mapsToCharXXX (request_output_real_format, (char ***) outputs); + *eres = + execute ((char ***) &main_conf[0], (char ***) &inputs[0], + (char ***) &outputs[0]); +#ifdef DEBUG + fprintf (stderr, "Function run successfully \n"); +#endif + charxxxToMaps ((char ***) &outputs[0], + &request_output_real_format); + } + else + { +#ifdef DEBUG +#ifdef WIN32 + errstr = getLastErrorMessage(); + fprintf (stderr, "Function %s failed to load because of %s\n", + r_inputs->value, errstr); +#endif +#endif + r_inputs = getMapFromMaps (m, "lenv", "Identifier"); +#ifdef DEBUG + fprintf (stderr, "Try to load function %s\n", r_inputs->value); +#endif + typedef int (*execute_t) (maps **, maps **, maps **); +#ifdef WIN32 + execute_t execute = + (execute_t) GetProcAddress (so, r_inputs->value); +#else + char* nS = zStrdup(r_inputs->value); + replace_char(nS,'.','_'); + replace_char(nS,'-','_'); + fprintf(stderr,"service from %s to %s\n",r_inputs->value,nS); + execute_t execute = (execute_t) dlsym (so, nS); + free(nS); +#endif + + if (execute == NULL) + { +#ifdef WIN32 + errstr = getLastErrorMessage(); +#else + errstr = dlerror (); +#endif + char *tmpMsg = + (char *) malloc (2048 + strlen (r_inputs->value)); + sprintf (tmpMsg, + _ + ("Error occurred while running the %s function: %s"), + r_inputs->value, errstr); + errorException (m, tmpMsg, "InternalError", NULL); + free (tmpMsg); +#ifdef DEBUG + fprintf (stderr, "Function %s error %s\n", r_inputs->value, + errstr); +#endif + *eres = -1; + return; + } + +#ifdef DEBUG +#ifdef WIN32 + errstr = getLastErrorMessage(); +#else + errstr = dlerror (); +#endif + fprintf (stderr, "Function loaded %s\n", errstr); +#endif + +#ifdef DEBUG + fprintf (stderr, "Now run the function \n"); + fflush (stderr); +#endif + *eres = + execute (&m, &request_input_real_format, + &request_output_real_format); +#ifdef DEBUG + fprintf (stderr, "Function loaded and returned %d\n", eres); + fflush (stderr); +#endif + } +#ifdef WIN32 + *ioutputs = dupMaps (&request_output_real_format); + FreeLibrary (so); +#else + dlclose (so); +#endif + } + else + { + /** + * Unable to load the specified shared library + */ + char tmps[1024]; +#ifdef WIN32 + errstr = getLastErrorMessage(); +#else + errstr = dlerror (); +#endif + sprintf (tmps, _("Unable to load C Library %s"), errstr); + errorException(m,tmps,"InternalError",NULL); + *eres = -1; + } + } + else + +#ifdef USE_HPC + if (strncasecmp (r_inputs->value, "HPC", 3) == 0) + { + *eres = + zoo_hpc_support (&m, request_inputs, s1, + &request_input_real_format, + &request_output_real_format); + } + else +#endif + +#ifdef USE_SAGA + if (strncasecmp (r_inputs->value, "SAGA", 4) == 0) + { + *eres = + zoo_saga_support (&m, request_inputs, s1, + &request_input_real_format, + &request_output_real_format); + } + else +#endif + +#ifdef USE_OTB + if (strncasecmp (r_inputs->value, "OTB", 3) == 0) + { + *eres = + zoo_otb_support (&m, request_inputs, s1, + &request_input_real_format, + &request_output_real_format); + } + else +#endif +#ifdef USE_PYTHON + if (strncasecmp (r_inputs->value, "PYTHON", 6) == 0) + { + *eres = + zoo_python_support (&m, request_inputs, s1, + &request_input_real_format, + &request_output_real_format); + } + else +#endif + +#ifdef USE_R + if (strncasecmp (r_inputs->value, "R", 6) == 0) + { + *eres = + zoo_r_support (&m, request_inputs, s1, + &request_input_real_format, + &request_output_real_format); + } + else +#endif + +#ifdef USE_JAVA + if (strncasecmp (r_inputs->value, "JAVA", 4) == 0) + { + *eres = + zoo_java_support (&m, request_inputs, s1, &request_input_real_format, + &request_output_real_format); + } + else +#endif + +#ifdef USE_PHP + if (strncasecmp (r_inputs->value, "PHP", 3) == 0) + { + *eres = + zoo_php_support (&m, request_inputs, s1, &request_input_real_format, + &request_output_real_format); + } + else +#endif + + +#ifdef USE_PERL + if (strncasecmp (r_inputs->value, "PERL", 4) == 0) + { + *eres = + zoo_perl_support (&m, request_inputs, s1, &request_input_real_format, + &request_output_real_format); + } + else +#endif + +#ifdef USE_JS + if (strncasecmp (r_inputs->value, "JS", 2) == 0) + { + *eres = + zoo_js_support (&m, request_inputs, s1, &request_input_real_format, + &request_output_real_format); + } + else +#endif + +#ifdef USE_RUBY + if (strncasecmp (r_inputs->value, "Ruby", 4) == 0) + { + *eres = + zoo_ruby_support (&m, request_inputs, s1, &request_input_real_format, + &request_output_real_format); + } + else +#endif + +#ifdef USE_MONO + if (strncasecmp (r_inputs->value, "Mono", 4) == 0) + { + *eres = + zoo_mono_support (&m, request_inputs, s1, &request_input_real_format, + &request_output_real_format); + } + else +#endif + + { + char tmpv[1024]; + sprintf (tmpv, + _ + ("Programming Language (%s) set in ZCFG file is not currently supported by ZOO Kernel.\n"), + r_inputs->value); + errorException (m, tmpv, "InternalError", NULL); + *eres = -1; + } + *myMap = m; + *ioutputs = request_output_real_format; +} + + +#ifdef WIN32 +/** + * createProcess function: create a new process after setting some env variables + */ +void +createProcess (maps * m, map * request_inputs, service * s1, char *opts, + int cpid, maps * inputs, maps * outputs) +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory (&si, sizeof (si)); + si.cb = sizeof (si); + ZeroMemory (&pi, sizeof (pi)); + char *tmp = (char *) malloc ((1024 + cgiContentLength) * sizeof (char)); + char *tmpq = (char *) malloc ((1024 + cgiContentLength) * sizeof (char)); + map *req = getMap (request_inputs, "request"); + map *id = getMap (request_inputs, "identifier"); + map *di = getMap (request_inputs, "DataInputs"); + + // The required size for the dataInputsKVP and dataOutputsKVP buffers + // may exceed cgiContentLength, hence a 2 kb extension. However, a + // better solution would be to have getMapsAsKVP() determine the required + // buffer size before allocating memory. + char *dataInputsKVP = getMapsAsKVP (inputs, cgiContentLength + 2048, 0); + char *dataOutputsKVP = getMapsAsKVP (outputs, cgiContentLength + 2048, 1); +#ifdef DEBUG + fprintf (stderr, "DATAINPUTSKVP %s\n", dataInputsKVP); + fprintf (stderr, "DATAOUTPUTSKVP %s\n", dataOutputsKVP); +#endif + map *sid = getMapFromMaps (m, "lenv", "osid"); + map *usid = getMapFromMaps (m, "lenv", "usid"); + map *r_inputs = getMapFromMaps (m, "main", "tmpPath"); + map *r_inputs1 = getMap (request_inputs, "metapath"); + + int hasIn = -1; + if (r_inputs1 == NULL) + { + r_inputs1 = createMap ("metapath", ""); + hasIn = 1; + } + map *r_inputs2 = getMap (request_inputs, "ResponseDocument"); + if (r_inputs2 == NULL) + r_inputs2 = getMap (request_inputs, "RawDataOutput"); + map *tmpPath = getMapFromMaps (m, "lenv", "cwd"); + + map *tmpReq = getMap (request_inputs, "xrequest"); + + if(r_inputs2 != NULL && tmpReq != NULL) { + const char key[] = "rfile="; + char* kvp = (char*) malloc((FILENAME_MAX + strlen(key))*sizeof(char)); + char* filepath = kvp + strlen(key); + strncpy(kvp, key, strlen(key)); + addToCache(m, tmpReq->value, tmpReq->value, "text/xml", strlen(tmpReq->value), + filepath, FILENAME_MAX); + if (filepath == NULL) { + errorException( m, _("Unable to cache HTTP POST Execute request."), "InternalError", NULL); + return; + } + sprintf(tmp,"\"metapath=%s&%s&cgiSid=%s&usid=%s\"", + r_inputs1->value,kvp,sid->value,usid->value); + sprintf(tmpq,"metapath=%s&%s", + r_inputs1->value,kvp); + free(kvp); + } + else if (r_inputs2 != NULL) + { + sprintf (tmp, + "\"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&%s=%s&cgiSid=%s&usid=%s\"", + r_inputs1->value, req->value, id->value, dataInputsKVP, + r_inputs2->name, dataOutputsKVP, sid->value, usid->value); + sprintf (tmpq, + "metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&%s=%s", + r_inputs1->value, req->value, id->value, dataInputsKVP, + r_inputs2->name, dataOutputsKVP); + } + else + { + sprintf (tmp, + "\"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&cgiSid=%s&usid=%s\"", + r_inputs1->value, req->value, id->value, dataInputsKVP, + sid->value, usid->value); + sprintf (tmpq, + "metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s", + r_inputs1->value, req->value, id->value, dataInputsKVP, + sid->value); + } + + if (hasIn > 0) + { + freeMap (&r_inputs1); + free (r_inputs1); + } + char *tmp1 = zStrdup (tmp); + sprintf (tmp, "\"%s\" %s \"%s\"", PROGRAMNAME, tmp1, sid->value); + free (dataInputsKVP); + free (dataOutputsKVP); +#ifdef DEBUG + fprintf (stderr, "REQUEST IS : %s \n", tmp); +#endif + + usid = getMapFromMaps (m, "lenv", "usid"); + if (usid != NULL && usid->value != NULL) { + SetEnvironmentVariable("USID", TEXT (usid->value)); + } + SetEnvironmentVariable ("CGISID", TEXT (sid->value)); + SetEnvironmentVariable ("QUERY_STRING", TEXT (tmpq)); + // knut: Prevent REQUEST_METHOD=POST in background process call to cgic:main + // (process hangs when reading cgiIn): + SetEnvironmentVariable("REQUEST_METHOD", "GET"); + SetEnvironmentVariable("CONTENT_TYPE", "text/plain"); + + char clen[1000]; + sprintf (clen, "%d", strlen (tmpq)); + SetEnvironmentVariable ("CONTENT_LENGTH", TEXT (clen)); + + // ref. https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863%28v=vs.85%29.aspx + if (!CreateProcess (NULL, // No module name (use command line) + TEXT (tmp), // Command line + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + CREATE_NO_WINDOW, // Apache won't wait until the end + NULL, // Use parent's environment block + NULL, // Use parent's starting directory + &si, // Pointer to STARTUPINFO struct + &pi) // Pointer to PROCESS_INFORMATION struct + ) + { +#ifdef DEBUG + fprintf (stderr, "CreateProcess failed (%d).\n", GetLastError ()); +#endif + if (tmp != NULL) { + free(tmp); + } + if (tmpq != NULL) { + free(tmpq); + } + return; + } + else + { +#ifdef DEBUG + fprintf (stderr, "CreateProcess successful (%d).\n\n\n\n", + GetLastError ()); +#endif + } + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + + if (tmp != NULL) { + free(tmp); + } + if (tmpq != NULL) { + free(tmpq); + } + +#ifdef DEBUG + fprintf (stderr, "CreateProcess finished !\n"); +#endif +} +#endif + +/** + * Process the request. + * + * @param inputs the request parameters map + * @return 0 on sucess, other value on failure + * @see conf_read,recursReaddirF + */ +int +runRequest (map ** inputs) +{ + +#ifndef USE_GDB +#ifndef WIN32 + signal (SIGCHLD, SIG_IGN); +#endif + signal (SIGSEGV, sig_handler); + signal (SIGTERM, sig_handler); + signal (SIGINT, sig_handler); + signal (SIGILL, sig_handler); + signal (SIGFPE, sig_handler); + signal (SIGABRT, sig_handler); +#endif + + + map *r_inputs = NULL; + map *request_inputs = *inputs; +#ifdef IGNORE_METAPATH + addToMap(request_inputs, "metapath", ""); +#endif + maps *m = NULL; + char *REQUEST = NULL; + /** + * Parsing service specfic configuration file + */ + m = (maps *) malloc (MAPS_SIZE); + if (m == NULL) + { + return errorException (NULL, _("Unable to allocate memory"), + "InternalError", NULL); + } + m->child=NULL; + char ntmp[1024]; +#ifndef ETC_DIR +#ifndef WIN32 + getcwd (ntmp, 1024); +#else + _getcwd (ntmp, 1024); +#endif +#else + sprintf(ntmp,"%s",ETC_DIR); +#endif + r_inputs = getMapOrFill (&request_inputs, "metapath", ""); + + char conf_file[10240]; + snprintf (conf_file, 10240, "%s/%s/main.cfg", ntmp, r_inputs->value); + if (conf_read (conf_file, m) == 2) + { + errorException (NULL, _("Unable to load the main.cfg file."), + "InternalError", NULL); + free (m); + return 1; + } +#ifdef DEBUG + fprintf (stderr, "***** BEGIN MAPS\n"); + dumpMaps (m); + fprintf (stderr, "***** END MAPS\n"); +#endif + + /** EOEPCA SPEC **/ + //rdr + addUserToMap(m); + maps* userMap=getMaps(m,"eoepcaUser"); + /** EOEPCA SPEC END **/ + + // map *theServicePath = getMapFromMaps (m, "main", "servicePath"); + // if (theServicePath && theServicePath->value ){ + // int theLen=(strlen(theServicePath->value)+1024+1)*sizeof(char); + // char* tmpNewPath=(char*) malloc(theLen); + // memset(tmpNewPath,0,theLen); + // sprintf(tmpNewPath,"%s%s",theServicePath->value,"rdr" ); + // free(theServicePath->value); + // theServicePath->value=tmpNewPath; + // } + +// map* eoUserMap=getMapFromMaps(m,"eoepcaUser","user"); +// if (eoUserMap && eoUserMap->value){ +// fprintf(stderr,"eoUserMap->value=%s a8\n",eoUserMap->value); +// } + + + map *getPath = getMapFromMaps (m, "main", "gettextPath"); + if (getPath != NULL) + { + bindtextdomain ("zoo-kernel", getPath->value); + bindtextdomain ("zoo-services", getPath->value); + } + else + { + bindtextdomain ("zoo-kernel", LOCALEDIR); + bindtextdomain ("zoo-services", LOCALEDIR); + } + + /** + * Manage our own error log file (usefull to separate standard apache debug + * messages from the ZOO-Kernel ones but also for IIS users to avoid wrong + * headers messages returned by the CGI due to wrong redirection of stderr) + */ + FILE *fstde = NULL; + map *fstdem = getMapFromMaps (m, "main", "logPath"); + if (fstdem != NULL) + fstde = freopen (fstdem->value, "a+", stderr); + + /** + * Language gesture + */ + r_inputs = getMap (request_inputs, "language"); + if (r_inputs == NULL) + r_inputs = getMap (request_inputs, "AcceptLanguages"); + if (r_inputs == NULL) + r_inputs = getMapFromMaps (m, "main", "language"); + if (r_inputs != NULL) + { + if (isValidLang (m, r_inputs->value) < 0) + { + char tmp[1024]; + sprintf (tmp, + _ + ("The value %s is not supported for the parameter"), + r_inputs->value); + errorException (m, tmp, "InvalidParameterValue", "language"); + freeMaps (&m); + free (m); + free (REQUEST); + return 1; + + } + char *tmp = zStrdup (r_inputs->value); + setMapInMaps (m, "main", "language", tmp); +#ifdef DEB + char tmp2[12]; + sprintf (tmp2, "%s.utf-8", tmp); + translateChar (tmp2, '-', '_'); + setlocale (LC_ALL, tmp2); +#else + translateChar (tmp, '-', '_'); + setlocale (LC_ALL, tmp); +#endif +#ifndef WIN32 + setenv ("LC_ALL", tmp, 1); +#else + char tmp1[13]; + sprintf (tmp1, "LC_ALL=%s", tmp); + _putenv (tmp1); +#endif + free (tmp); + } + else + { + setlocale (LC_ALL, "en_US"); +#ifndef WIN32 + setenv ("LC_ALL", "en_US", 1); +#else + char tmp1[13]; + sprintf (tmp1, "LC_ALL=en_US"); + _putenv (tmp1); +#endif + setMapInMaps (m, "main", "language", "en-US"); + } + setlocale (LC_NUMERIC, "C"); +#ifndef WIN32 + setenv ("LC_NUMERIC", "C", 1); +#else + char tmp1[17]; + sprintf (tmp1, "LC_NUMERIC=C"); + _putenv (tmp1); +#endif + bind_textdomain_codeset ("zoo-kernel", "UTF-8"); + textdomain ("zoo-kernel"); + bind_textdomain_codeset ("zoo-services", "UTF-8"); + textdomain ("zoo-services"); + + map *lsoap = getMap (request_inputs, "soap"); + if (lsoap != NULL && strcasecmp (lsoap->value, "true") == 0) + setMapInMaps (m, "main", "isSoap", "true"); + else + setMapInMaps (m, "main", "isSoap", "false"); + + if(strlen(cgiServerName)>0) + { + char tmpUrl[1024]; + + if ( getenv("HTTPS") != NULL && strncmp(getenv("HTTPS"), "on", 2) == 0 ) { + // Knut: check if non-empty instead of "on"? + if ( strncmp(cgiServerPort, "443", 3) == 0 ) { + sprintf(tmpUrl, "https://%s%s", cgiServerName, cgiScriptName); + } + else { + sprintf(tmpUrl, "https://%s:%s%s", cgiServerName, cgiServerPort, cgiScriptName); + } + } + else { + if ( strncmp(cgiServerPort, "80", 2) == 0 ) { + sprintf(tmpUrl, "http://%s%s", cgiServerName, cgiScriptName); + } + else { + sprintf(tmpUrl, "http://%s:%s%s", cgiServerName, cgiServerPort, cgiScriptName); + } + } +#ifdef DEBUG + fprintf(stderr,"*** %s ***\n",tmpUrl); +#endif + if(getMapFromMaps(m,"main","proxied")==NULL) + setMapInMaps(m,"main","serverAddress",tmpUrl); + else + setMapInMaps(m,"lenv","serverAddress",tmpUrl); + } + + // CORS Support + if(strncasecmp(cgiRequestMethod,"OPTIONS",7)==0){ + map* cors=getMapFromMaps(m,"main","cors"); + if(cors!=NULL && strncasecmp(cors->value,"true",4)==0){ + char *encoding=getEncoding(m); + printHeaders(m); + printf("Content-Type: text/plain; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding); + printf(_("CORS is enabled.\r\n")); + freeMaps (&m); + free (m); + fflush (stdout); + return 3; + } + } + + // Populate the Registry + char conf_dir[1024*2]; + int t; + char tmps1[1024*2]; + r_inputs = NULL; + r_inputs = getMap (request_inputs, "metapath"); + map* cwdMap0=getMapFromMaps(m,"main","servicePath"); + if (r_inputs != NULL) + if(cwdMap0!=NULL) + snprintf (conf_dir, 1024, "%s/%s", cwdMap0->value, r_inputs->value); + else + snprintf (conf_dir, 1024, "%s/%s", ntmp, r_inputs->value); + else + if(cwdMap0!=NULL) + snprintf (conf_dir, 1024, "%s", cwdMap0->value); + else + snprintf (conf_dir, 1024, "%s", ntmp); + map* reg = getMapFromMaps (m, "main", "registry"); + registry* zooRegistry=NULL; + if(reg!=NULL){ +#ifndef WIN32 + int saved_stdout = zDup (fileno (stdout)); + zDup2 (fileno (stderr), fileno (stdout)); +#endif + if(createRegistry (m,&zooRegistry,reg->value)<0){ + map *message=getMapFromMaps(m,"lenv","message"); + map *type=getMapFromMaps(m,"lenv","type"); +#ifndef WIN32 + zDup2 (saved_stdout, fileno (stdout)); +#endif + errorException (m, message->value, + type->value, NULL); + return 0; + } +#ifndef WIN32 + zDup2 (saved_stdout, fileno (stdout)); + zClose(saved_stdout); +#endif + } + + setMapInMaps(m,"lenv","executionType","xml"); + if((strlen(cgiQueryString)>0 && cgiQueryString[0]=='/') && strstr(cgiAccept,"json")!=NULL){ + // + // OGC API - Processing starts here + // +#ifndef USE_JSON + errorException (m, _("OGC API - Processing is not supported by this ZOO-Kernel."), "InternalError", NULL); + return 1; +#else +#ifndef USE_GDB +#ifndef WIN32 + signal (SIGCHLD, SIG_IGN); +#endif + signal (SIGSEGV, json_sig_handler); + signal (SIGTERM, json_sig_handler); + signal (SIGINT, json_sig_handler); + signal (SIGILL, json_sig_handler); + signal (SIGFPE, json_sig_handler); + signal (SIGABRT, json_sig_handler); +#endif + r_inputs = getMapOrFill (&request_inputs, "metapath", ""); + char conf_file1[10240]; + maps* m1 = (maps *) malloc (MAPS_SIZE); + snprintf (conf_file1, 10240, "%s/%s/oas.cfg", ntmp, r_inputs->value); + if (conf_read (conf_file1, m1) == 2) + { + errorException (NULL, _("Unable to load the oas.cfg file."), + "InternalError", NULL); + free (m); + return 1; + } + addMapsToMaps(&m,m1); + setMapInMaps(m,"lenv","executionType","json"); + + json_object *res=json_object_new_object(); + setMapInMaps(m,"headers","Content-Type","application/json;charset=UTF-8"); + + + if((strcmp(cgiQueryString,"/processes")==0 || strcmp(cgiQueryString,"/processes/")==0) && + strcasecmp(cgiRequestMethod,"post")==0){ + cgiQueryString="/processes/DeployProcess/jobs"; + // TODO: store the request file, replacing the deployResult by undeployResult + } + +// if(( +// strcmp(cgiQueryString,"/processes")==0 || strcmp(cgiQueryString,"/processes/")==0) && +// strcasecmp(cgiRequestMethod,"delete")==0 +// ){ +// +// +// +// +// //cgiRequestMethod="post"; +// cgiQueryString="/processes/UndeployProcess/jobs"; +// } + + + /* - Root url */ + if(cgiContentLength==1){ + map* tmpMap=getMapFromMaps(m,"main","serverAddress"); + json_object *res1=json_object_new_array(); + const char* urls[4]={ + "/","/api","/conformance","/processes" + }; + map* tmpUrl=getMapFromMaps(m,"main","serverAddress"); + for(int kk=0;kk<4;kk++){ + maps* tmpMaps=getMaps(m,urls[kk]); + json_object *res2; + if(tmpMaps!=NULL){ + res2=mapToJson(tmpMaps->content); + char* tmpStr=(char*) malloc((strlen(tmpUrl->value)+strlen(urls[kk])+2)*sizeof(char)); + sprintf(tmpStr,"%s%s",tmpUrl->value,urls[kk]); + json_object_object_add(res2,"href",json_object_new_string(tmpStr)); + json_object_array_add(res1,res2); + } + } + json_object_object_add(res,"links",res1); + }else if(strcmp(cgiQueryString,"/conformance")==0){ + /* - /conformance url */ + map* rootUrl=getMapFromMaps(m,"conformTo","rootUrl"); + json_object *res1=json_object_new_array(); + map* length=getMapFromMaps(m,"conformTo","length"); + maps* tmpMaps=getMaps(m,"conformTo"); + for(int kk=0;kkvalue);kk++){ + map* tmpMap1=getMapArray(tmpMaps->content,"link",kk); + json_object *res2; + if(tmpMap1!=NULL){ + char* tmpStr=(char*) malloc((strlen(rootUrl->value)+strlen(tmpMap1->value)+1)*sizeof(char)); + sprintf(tmpStr,"%s%s",rootUrl->value,tmpMap1->value); + json_object_array_add(res1,json_object_new_string(tmpStr)); + } + } + json_object_object_add(res,"conformTo",res1); + }else if(strcmp(cgiQueryString,"/api")==0){ + /* - /api url */ + produceApi(m,res); + }else if( strstr(cgiQueryString,"/processes/") && strcasecmp(cgiRequestMethod,"delete")==0 ){ + + + fprintf(stderr,"%s\n",cgiQueryString); + char* p=strstr(cgiQueryString,"/processes/"); + if (strlen(cgiQueryString)>11/*/processes/*/){ + + char *orig = zStrdup (p+11); + if(orig[strlen(orig)-1]=='/') + orig[strlen(orig)-1]=0; + + char *theS=strchr(orig,'/'); + if (theS){ + *theS='\0'; + } + + fprintf(stderr,"%s\n",orig); + + + + int y=removeService(m,orig); + free (orig); + if (y){ + // errorException (conf, _("Unable to allocate memory"),"InternalError", NULL); + return 1; + } + + } + + }else if(strcmp(cgiQueryString,"/processes")==0 || strcmp(cgiQueryString,"/processes/")==0){ + /* - /processes */ + json_object *res3=json_object_new_array(); + int saved_stdout = zDup (fileno (stdout)); + zDup2 (fileno (stderr), fileno (stdout)); + + if (int res = + recursReaddirF (m, NULL, res3, NULL, ntmp, NULL, saved_stdout, 0, + printGetCapabilitiesForProcessJ) < 0) + { + } + zDup2 (saved_stdout, fileno (stdout)); + zClose(saved_stdout); + +// json_object_object_add(res,"processes",res3); //rdr + json_object_put(res);//rdr + res = res3;//rdr + }else{ + service* s1=NULL; + int t=0; + if(strstr(cgiQueryString,"/processes/")==NULL){ + map* error=createMap("code","BadRequest"); + addToMap(error,"message",_("The ressource is not available")); + //setMapInMaps(conf,"lenv","status_code","404 Bad Request"); + printExceptionReportResponseJ(m,error); + freeMaps (&m); + free (m); + free (REQUEST); + xmlCleanupParser (); + zooXmlCleanupNs (); + return 1; + } else + if(strstr(cgiQueryString,"/jobs")==NULL && strstr(cgiQueryString,"/jobs/")==NULL){ + /* - /processes/{id}/ */ + DIR *dirp = opendir (ntmp); + json_object *res3=json_object_new_object(); + char *orig = zStrdup (strstr(cgiQueryString,"/processes/")+11); + if(orig[strlen(orig)-1]=='/') + orig[strlen(orig)-1]=0; + json_object* res1=json_object_new_object(); + + int t=fetchServicesForDescription(NULL, m, orig, + printGetCapabilitiesForProcessJ, + NULL, (void*) res3, ntmp, + request_inputs, + printExceptionReportResponseJ); + if(t==1){ + /*map* error=createMap("code","BadRequest"); + addToMap(error,"message",_("Failed to acces the requested service")); + printExceptionReportResponseJ(m,error);*/ + return 1; + } + res=json_object_get(res3); + }else{ + char* queryString=zStrdup(cgiQueryString); + int len0=strlen(strstr(cgiQueryString,"/processes/")+11); + int len1=strlen(cgiQueryString)-strlen(strstr(cgiQueryString,"/job")); + char* cIdentifier=(char*)malloc((len1-10)*sizeof(char)); + int cnt=0; + for(int j=11;jvalue != NULL) { + strncpy(tmps1, import->value, 1024); + setMapInMaps (m, "lenv", "Identifier", cIdentifier); + setMapInMaps (m, "lenv", "oIdentifier", cIdentifier); + } + else { + //rdr....... + char newPath[1024]; + getUserWorkspacePath(m,ntmp,newPath,1024); + + if ( + strcmp(cIdentifier,"DeployProcess")==0 || + strcmp(cIdentifier,"UndeployProcess")==0 + ){ + memset(newPath,'\0',1024); + strcpy(newPath,ntmp); + } + + if (strcmp(ntmp, newPath )==0) { + snprintf (tmps1, 1024, "%s/%s.zcfg", ntmp, cIdentifier); + }else{ + // fprintf(stderr,"rdr a7 %s/%s.zcfg \n",newPath, cIdentifier); + snprintf (tmps1, 1024, "%s/%s.zcfg", newPath, cIdentifier); + } + //rdr....... + +#ifdef DEBUG + fprintf (stderr, "Trying to load %s\n", tmps1); +#endif + if (strstr (cIdentifier, ".") != NULL) + { + char *identifier = zStrdup (cIdentifier); + parseIdentifier (m, ntmp, identifier, tmps1); + map *tmpMap = getMapFromMaps (m, "lenv", "metapath"); + if (tmpMap != NULL) + addToMap (request_inputs, "metapath", tmpMap->value); + free (identifier); + } + else + { + setMapInMaps (m, "lenv", "oIdentifier", cIdentifier); + setMapInMaps (m, "lenv", "Identifier", cIdentifier); + } + } + + r_inputs = getMapFromMaps (m, "lenv", "Identifier"); + +#ifdef META_DB + int metadb_id=_init_sql(m,"metadb"); + //FAILED CONNECTING DB + if(getMapFromMaps(m,"lenv","dbIssue")!=NULL || metadb_id<0){ + fprintf(stderr,"ERROR CONNECTING METADB\n"); + } + if(metadb_id>=0) + s1=extractServiceFromDb(m,cIdentifier,0); + if(s1!=NULL){ + inheritance(zooRegistry,&s1); +#ifdef USE_HPC + addNestedOutputs(&s1); +#endif + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + }else /* Not found in MetaDB */{ +#endif + s1 = createService(); + if (s1 == NULL) + { + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + map* error=createMap("code","InternalError"); + addToMap(error,"message",_("Unable to allocate memory")); + //setMapInMaps(conf,"lenv","status_code","404 Bad Request"); + printExceptionReportResponseJ(m,error); + + return 1; /*errorException (m, _("Unable to allocate memory"), + "InternalError", NULL);*/ + } + + int saved_stdout = zDup (fileno (stdout)); + zDup2 (fileno (stderr), fileno (stdout)); + t = readServiceFile (m, tmps1, &s1, cIdentifier); + if(t>=0){ + inheritance(zooRegistry,&s1); +#ifdef USE_HPC + addNestedOutputs(&s1); +#endif + } + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + fflush (stdout); + zDup2 (saved_stdout, fileno (stdout)); + if (t < 0) + { + char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value)); + sprintf (tmpMsg, + _ + ("The value for seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."), + r_inputs->value); + map* error=createMap("code","NotFound");//EOEPCA-237 + addToMap(error,"message",tmpMsg); + //setMapInMaps(conf,"lenv","status_code","404 Bad Request"); + printExceptionReportResponseJ(m,error); + + //errorException (m, tmpMsg, "InvalidParameterValue", "identifier"); + free (tmpMsg); + free (s1); + freeMaps (&m); + free (m); + free (REQUEST); + free (SERVICE_URL); + return 0; + } + zClose (saved_stdout); + +#ifdef META_DB + } +#endif + if(strstr(cgiQueryString,"/jobs/")!=NULL && strlen(strstr(cgiQueryString,"/jobs/"))>6){ + /* - /jobs/{jobID} and /jobs/{jobID}/result urls */ + if(strstr(cgiQueryString,"/result")!=NULL && strlen(strstr(cgiQueryString,"/result"))>=7){ + fprintf(stderr,"For GetResult %s %d \n",__FILE__,__LINE__); + }else{ + char* tmpUrl=strstr(cgiQueryString,"/jobs/"); + if(tmpUrl!=NULL && strlen(tmpUrl)>6){ + char* jobId=zStrdup(strstr(cgiQueryString,"/jobs/")+6); + setMapInMaps(m,"lenv","gs_usid",jobId); + json_getStatusFile(m); + free(jobId); + return 1; + } + } + }else{ + /* - /jobs url */ + fprintf(stderr,"For Execute or Job list %s %d \n",__FILE__,__LINE__); + if(strcasecmp(cgiRequestMethod,"get")==0){ + /* - /jobs List (GET) */ + res=printJobList(m); + }else if(strcasecmp(cgiRequestMethod,"post")==0){ + /* - /jobs Execution (POST) */ + int eres = SERVICE_STARTED; + + initAllEnvironment(m,request_inputs,ntmp,"jrequest"); + map* req=getMapFromMaps(m,"renv","jrequest"); + json_object *jobj = NULL; + const char *mystring = NULL; + int slen = 0; + enum json_tokener_error jerr; + struct json_tokener* tok=json_tokener_new(); + do { + mystring = req->value; // get JSON string, e.g. read from file, etc... + slen = strlen(mystring); + jobj = json_tokener_parse_ex(tok, mystring, slen); + } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue); + if (jerr != json_tokener_success) { + fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); + return 1; + } + if (tok->char_offset < slen){ + return 1; + } + fprintf(stderr,"%s %d \n",__FILE__,__LINE__); + // Success, use jobj here. + maps* inputs_real_format=NULL, *outputs_real_format= NULL; + parseJRequest(m,s1,jobj,&inputs_real_format,&outputs_real_format); +#ifdef USE_JSON + int request_type = parseJRequestMode(m,s1,jobj); + switch(request_type){ + case 0: + fprintf(stderr,"REQUEST_TYPE: async\n"); + break; + case 1: + fprintf(stderr,"REQUEST_TYPE: sync\n"); + break; + } +#endif + map* preference=getMapFromMaps(m,"renv","HTTP_PREFER"); +#ifdef USE_JSON + if(request_type==0){//async +#else + if(preference!=NULL && strcasecmp(preference->value,"respond-async")==0){ +#endif + fprintf(stderr,"Asynchronous call!\n"); + char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog; + FILE *f0, *f1; + int pid; +#ifdef DEBUG + fprintf (stderr, "\nPID : %d\n", cpid); +#endif +#ifndef WIN32 + pid = fork (); +#else + if (cgiSid == NULL) + { + createProcess (m, request_inputs, s1, NULL, cpid, + request_input_real_format, + request_output_real_format); + pid = cpid; + } + else + { + pid = 0; + cpid = atoi (cgiSid); + updateStatus(m,0,_("Initializing")); + } +#endif + if (pid > 0) + { + // + // dady : + // set status to SERVICE_ACCEPTED + // +#ifdef DEBUG + fprintf (stderr, "father pid continue (origin %d) %d ...\n", cpid, + zGetpid ()); +#endif + eres = SERVICE_ACCEPTED; + createStatusFile(m,eres); + printHeaders(m); + printf("Status: 201 Created \r\n\r\n"); + return 1; + } + else if (pid == 0) + { + eres = SERVICE_STARTED; + // + // son : have to close the stdout, stdin and stderr to let the parent + // process answer to http client. + // + map* usid = getMapFromMaps (m, "lenv", "uusid"); + map* tmpm = getMapFromMaps (m, "lenv", "osid"); + int cpid = atoi (tmpm->value); + pid=cpid; + r_inputs = getMapFromMaps (m, "main", "tmpPath"); + setMapInMaps (m, "lenv", "async","true"); + map* r_inputs1 = createMap("ServiceName", s1->name); + // Create the filename for the result file (.res) + fbkpres = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value); + maps* bmap = createMaps("status"); + bmap->content=createMap("usid",usid->value); + addToMap(bmap->content,"sid",tmpm->value); + addIntToMap(bmap->content,"pid",zGetpid()); + + // Create PID file referencing the OS process identifier + fbkpid = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value); + setMapInMaps (m, "lenv", "file.pid", fbkpid); + + f0 = freopen (fbkpid, "w+",stdout); + printf("%d",zGetpid()); + fflush(stdout); + + // Create SID file referencing the semaphore name + fbkp = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value); + setMapInMaps (m, "lenv", "file.sid", fbkp); + FILE* f2 = freopen (fbkp, "w+",stdout); + printf("%s",tmpm->value); + fflush(f2); + free(fbkp); + + fbkp = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value, + usid->value); + setMapInMaps (m, "lenv", "file.responseInit", fbkp); + flog = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 13) * sizeof (char)); + sprintf (flog, "%s/%s_%s_error.log", r_inputs->value, + r_inputs1->value, usid->value); + setMapInMaps (m, "lenv", "file.log", flog); +#ifdef DEBUG + fprintf (stderr, "RUN IN BACKGROUND MODE \n"); + fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid, + zGetpid ()); + fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value); +#endif + freopen (flog, "w+", stderr); + fflush (stderr); + f0 = freopen (fbkp, "w+", stdout); + rewind (stdout); +#ifndef WIN32 + fclose (stdin); +#endif +#ifdef RELY_ON_DB + init_sql(m); + recordServiceStatus(m); +#endif +#ifdef USE_CALLBACK + invokeCallback(m,NULL,NULL,0,0); +#endif + fprintf(stderr,"%s %d\n",__FILE__,__LINE__); + fflush(stderr); + + createStatusFile(m,eres); + + + fbkp1 = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 15) * sizeof (char)); + sprintf (fbkp1, "%s/%s_final_%s.json", r_inputs->value, + r_inputs1->value, usid->value); + setMapInMaps (m, "lenv", "file.responseFinal", fbkp1); + + f1 = freopen (fbkp1, "w+", stdout); + + map* serviceTypeMap=getMap(s1->content,"serviceType"); + if(serviceTypeMap!=NULL) + setMapInMaps (m, "lenv", "serviceType", serviceTypeMap->value); + + char *flenv = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 12) * sizeof (char)); + sprintf (flenv, "%s/%s_lenv.cfg", r_inputs->value, usid->value); + maps* lenvMaps=getMaps(m,"lenv"); + dumpMapsToFile(lenvMaps,flenv,0); + free(flenv); + + map* testMap=getMapFromMaps(m,"main","memory"); + loadHttpRequests(m,inputs_real_format); + loadServiceAndRun (&m, s1, request_inputs, + &inputs_real_format, + &outputs_real_format, &eres); + createStatusFile(m,eres); + res=printJResult(m,s1,outputs_real_format,eres); + char tmpUrl0[1024]; + const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN); + printf(jsonStr); + printf("\n"); + return 1; + + } + }else{ + loadHttpRequests(m,inputs_real_format); + loadServiceAndRun (&m,s1,request_inputs,&inputs_real_format,&outputs_real_format,&eres); + res=printJResult(m,s1,outputs_real_format,eres); + createStatusFile(m,eres); + printHeaders(m); + + if (eres==SERVICE_SUCCEEDED){ + printf("Status: 201 Created \r\n\r\n"); + }else{ + printf("Status: 500 failed \r\n\r\n"); + } + + const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN); + printf(jsonStr); + printf("\n"); + return 1; + } + + + }//else error + + } + } + } + printHeaders(m); + printf("Status: 200 OK \r\n\r\n"); + const char* jsonStr=json_object_to_json_string_ext(res,JSON_C_TO_STRING_PLAIN); + printf(jsonStr); + printf("\n"); + return 1; +#endif + } + + // + // WPS 1.0.0 and 2.0.0 starts here + // + //Check for minimum inputs + map* version=getMap(request_inputs,"version"); + if(version==NULL) + version=getMapFromMaps(m,"main","version"); + setMapInMaps(m,"main","rversion",version->value); + int vid=getVersionId(version->value); + if(vid<0) + vid=0; + map* err=NULL; + const char **vvr=(const char**)requests[vid]; + checkValidValue(request_inputs,&err,"request",vvr,1); + const char *vvs[]={ + "WPS", + NULL + }; + if(err!=NULL){ + checkValidValue(request_inputs,&err,"service",(const char**)vvs,1); + printExceptionReportResponse (m, err); + freeMap(&err); + free(err); + if (count (request_inputs) == 1) + { + freeMap (&request_inputs); + free (request_inputs); + } + freeMaps (&m); + free (m); + return 1; + } + checkValidValue(request_inputs,&err,"service",(const char**)vvs,1); + + const char *vvv[]={ + "1.0.0", + "2.0.0", + NULL + }; + r_inputs = getMap (request_inputs, "Request"); + if(r_inputs!=NULL) + REQUEST = zStrdup (r_inputs->value); + int reqId=-1; + if (strncasecmp (REQUEST, "GetCapabilities", 15) != 0){ + checkValidValue(request_inputs,&err,"version",(const char**)vvv,1); + int j=0; + for(j=0;j=nbReqIdentifier && jvalue,schemas[1][0])!=NULL){ + addToMap(request_inputs,"version",schemas[1][0]); + setMapInMaps(m,"main","rversion",schemas[1][0]); + } + else{ + addToMap(request_inputs,"version",version1->value); + setMapInMaps(m,"main","rversion",version1->value); + } + version=getMap(request_inputs,"version"); + } + } + if(err!=NULL){ + printExceptionReportResponse (m, err); + freeMap(&err); + free(err); + if (count (request_inputs) == 1) + { + freeMap (&request_inputs); + free (request_inputs); + } + free(REQUEST); + freeMaps (&m); + free (m); + return 1; + } + + r_inputs = getMap (request_inputs, "serviceprovider"); + if (r_inputs == NULL) + { + addToMap (request_inputs, "serviceprovider", ""); + } + + maps *request_output_real_format = NULL; + map *tmpm = getMapFromMaps (m, "main", "serverAddress"); + if (tmpm != NULL) + SERVICE_URL = zStrdup (tmpm->value); + else + SERVICE_URL = zStrdup (DEFAULT_SERVICE_URL); + + + + service *s1; + int scount = 0; +#ifdef DEBUG + dumpMap (r_inputs); +#endif + + if (strncasecmp (REQUEST, "GetCapabilities", 15) == 0) + { +#ifdef DEBUG + dumpMap (r_inputs); +#endif + xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0"); + xmlNodePtr n=printGetCapabilitiesHeader(doc,m,(version!=NULL?version->value:"1.0.0")); + /** + * Here we need to close stdout to ensure that unsupported chars + * has been found in the zcfg and then printed on stdout + */ + int saved_stdout = zDup (fileno (stdout)); + zDup2 (fileno (stderr), fileno (stdout)); + + maps* imports = getMaps(m, IMPORTSERVICE); + if (imports != NULL) { + map* zcfg = imports->content; + + while (zcfg != NULL) { + if (zcfg->value != NULL) { + service* svc = (service*) malloc(SERVICE_SIZE); + if (svc == NULL || readServiceFile(m, zcfg->value, &svc, zcfg->name) < 0) { + // pass over silently + zcfg = zcfg->next; + continue; + } + inheritance(zooRegistry, &svc); + printGetCapabilitiesForProcess(zooRegistry, m, doc, n, svc); + freeService(&svc); + free(svc); + } + zcfg = zcfg->next; + } + } + + if (int res = + recursReaddirF (m, zooRegistry, doc, n, conf_dir, NULL, saved_stdout, 0, + printGetCapabilitiesForProcess) < 0) + { + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + fflush (stdout); + return res; + } + fflush (stdout); + zDup2 (saved_stdout, fileno (stdout)); +#ifdef META_DB + fetchServicesFromDb(zooRegistry,m,doc,n,printGetCapabilitiesForProcess,1); + close_sql(m,0); +#endif + printDocument (m, doc, zGetpid ()); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + fflush (stdout); + return 0; + } + else + { + r_inputs = getMap (request_inputs, "JobId"); + if(reqId>nbReqIdentifier){ + if (strncasecmp (REQUEST, "GetStatus", 9) == 0 || + strncasecmp (REQUEST, "GetResult", 9) == 0){ + runGetStatus(m,r_inputs->value,REQUEST); +#ifdef RELY_ON_DB + map* dsNb=getMapFromMaps(m,"lenv","ds_nb"); + if(dsNb!=NULL && atoi(dsNb->value)>1) + close_sql(m,1); + close_sql(m,0); +#endif + + freeMaps (&m); + free(m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + return 0; + } + else + if (strncasecmp (REQUEST, "Dismiss", strlen(REQUEST)) == 0){ + runDismiss(m,r_inputs->value); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + return 0; + + } + return 0; + } + if(reqId<=nbReqIdentifier){ + r_inputs = getMap (request_inputs, "Identifier"); + + struct dirent *dp; + DIR *dirp = opendir (conf_dir); + if (dirp == NULL) + { + errorException (m, _("The specified path does not exist."), + "InternalError", NULL); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + return 0; + } + if (strncasecmp (REQUEST, "DescribeProcess", 15) == 0) + { + /** + * Loop over Identifier list + */ + xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0"); + r_inputs = NULL; + r_inputs = getMap (request_inputs, "version"); +#ifdef DEBUG + fprintf(stderr," ** DEBUG %s %d \n",__FILE__,__LINE__); + fflush(stderr); +#endif + xmlNodePtr n = printWPSHeader(doc,m,"DescribeProcess", + root_nodes[vid][1],(version!=NULL?version->value:"1.0.0"),1); + + r_inputs = getMap (request_inputs, "Identifier"); + + fetchServicesForDescription(zooRegistry, m, r_inputs->value, + printDescribeProcessForProcess, + (void*) doc, (void*) n, conf_dir, + request_inputs,printExceptionReportResponse); + + printDocument (m, doc, zGetpid ()); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + fflush (stdout); +#ifdef META_DB + close_sql(m,0); + //end_sql(); +#endif + return 0; + } + else if (strncasecmp (REQUEST, "Execute", strlen (REQUEST)) != 0) + { + map* version=getMapFromMaps(m,"main","rversion"); + int vid=getVersionId(version->value); + int len = 0; + int j = 0; + for(j=0;j value was not recognized. Allowed values are %s.",tmpStr); + errorException (m,_(message),"InvalidParameterValue", "request"); +#ifdef DEBUG + fprintf (stderr, "No request found %s", REQUEST); +#endif + closedir (dirp); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + fflush (stdout); + return 0; + } + closedir (dirp); + } + } + + map *postRequest = NULL; + postRequest = getMap (request_inputs, "xrequest"); + + if(vid==1 && postRequest==NULL){ + errorException (m,_("Unable to run Execute request using the GET HTTP method"),"InvalidParameterValue", "request"); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + fflush (stdout); + return 0; + } + s1 = NULL; + + r_inputs = getMap (request_inputs, "Identifier"); + map* import = getMapFromMaps (m, IMPORTSERVICE, r_inputs->value); + if (import != NULL && import->value != NULL) { + strncpy(tmps1, import->value, 1024); + setMapInMaps (m, "lenv", "Identifier", r_inputs->value); + setMapInMaps (m, "lenv", "oIdentifier", r_inputs->value); + } + else { + + char conf_dir2[1024*2]; + memset(conf_dir2,0,1024*2); + + strcpy(conf_dir2,conf_dir); + getUserWorkspacePath(m,conf_dir,conf_dir2,1024); + strcpy(conf_dir,conf_dir2); + +// fprintf(stderr,"rdr a8--> conf_dir %s -- %s\n", conf_dir, r_inputs->value); +// fprintf(stderr,"rdr a8--> conf_dir2 %s -- %s\n", conf_dir2, r_inputs->value); + + snprintf (tmps1, 1024, "%s/%s.zcfg", conf_dir, r_inputs->value); + +#ifdef DEBUG + fprintf (stderr, "Trying to load %s\n", tmps1); +#endif + if (strstr (r_inputs->value, ".") != NULL) + { + char *identifier = zStrdup (r_inputs->value); + parseIdentifier (m, conf_dir, identifier, tmps1); + map *tmpMap = getMapFromMaps (m, "lenv", "metapath"); + if (tmpMap != NULL) + addToMap (request_inputs, "metapath", tmpMap->value); + free (identifier); + } + else + { + setMapInMaps (m, "lenv", "Identifier", r_inputs->value); + setMapInMaps (m, "lenv", "oIdentifier", r_inputs->value); + } + } + + r_inputs = getMapFromMaps (m, "lenv", "Identifier"); + +#ifdef META_DB + int metadb_id=_init_sql(m,"metadb"); + //FAILED CONNECTING DB + if(getMapFromMaps(m,"lenv","dbIssue")!=NULL || metadb_id<0){ + fprintf(stderr,"ERROR CONNECTING METADB\n"); + } + if(metadb_id>=0) + s1=extractServiceFromDb(m,r_inputs->value,0); + //close_sql(m,0); + if(s1!=NULL){ + inheritance(zooRegistry,&s1); +#ifdef USE_HPC + addNestedOutputs(&s1); +#endif + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + }else /* Not found in MetaDB */{ +#endif + s1 = createService(); + if (s1 == NULL) + { + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + free (REQUEST); + free (SERVICE_URL); + return errorException (m, _("Unable to allocate memory"), + "InternalError", NULL); + } + + int saved_stdout = zDup (fileno (stdout)); + zDup2 (fileno (stderr), fileno (stdout)); + t = readServiceFile (m, tmps1, &s1, r_inputs->value); + if(t>=0){ + inheritance(zooRegistry,&s1); +#ifdef USE_HPC + addNestedOutputs(&s1); +#endif + } + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + fflush (stdout); + zDup2 (saved_stdout, fileno (stdout)); + if (t < 0) + { + char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value)); + sprintf (tmpMsg, + _ + ("The value for seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."), + r_inputs->value); + errorException (m, tmpMsg, "InvalidParameterValue", "identifier"); + free (tmpMsg); + free (s1); + freeMaps (&m); + free (m); + free (REQUEST); + free (SERVICE_URL); + return 0; + } + zClose (saved_stdout); +#ifdef META_DB + } +#endif + +#ifdef DEBUG + dumpService (s1); +#endif + int j; + + + /** + * Create the input and output maps data structure + */ + int i = 0; + HINTERNET hInternet; + HINTERNET res; + hInternet = InternetOpen ( +#ifndef WIN32 + (LPCTSTR) +#endif + "ZooWPSClient\0", + INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + +#ifndef WIN32 + if (!CHECK_INET_HANDLE (hInternet)) + fprintf (stderr, "WARNING : hInternet handle failed to initialize"); +#endif + maps *request_input_real_format = NULL; + maps *tmpmaps = request_input_real_format; + + if(parseRequest(&m,&request_inputs,s1,&request_input_real_format,&request_output_real_format,&hInternet)<0){ + freeMaps (&m); + free (m); + free (REQUEST); + free (SERVICE_URL); + InternetCloseHandle (&hInternet); + freeService (&s1); + free (s1); + return 0; + } + //InternetCloseHandle (&hInternet); + + initAllEnvironment(m,request_inputs,ntmp,"xrequest"); + + +#ifdef DEBUG + dumpMap (request_inputs); +#endif + + map *status = getMap (request_inputs, "status"); + if(vid==0){ + // Need to check if we need to fork to load a status enabled + r_inputs = NULL; + map *store = getMap (request_inputs, "storeExecuteResponse"); + /** + * 05-007r7 WPS 1.0.0 page 57 : + * 'If status="true" and storeExecuteResponse is "false" then the service + * shall raise an exception.' + */ + if (status != NULL && strcmp (status->value, "true") == 0 && + store != NULL && strcmp (store->value, "false") == 0) + { + errorException (m, + _ + ("The status parameter cannot be set to true if storeExecuteResponse is set to false. Please modify your request parameters."), + "InvalidParameterValue", "storeExecuteResponse"); + freeService (&s1); + free (s1); + freeMaps (&m); + free (m); + + freeMaps (&request_input_real_format); + free (request_input_real_format); + + freeMaps (&request_output_real_format); + free (request_output_real_format); + + free (REQUEST); + free (SERVICE_URL); + return 1; + } + r_inputs = getMap (request_inputs, "storeExecuteResponse"); + }else{ + // Define status depending on the WPS 2.0.0 mode attribute + status = getMap (request_inputs, "mode"); + map* mode=getMap(s1->content,"mode"); + if(strcasecmp(status->value,"async")==0){ + if(mode!=NULL && strcasecmp(mode->value,"async")==0) + addToMap(request_inputs,"status","true"); + else{ + if(mode!=NULL){ + // see ref. http://docs.opengeospatial.org/is/14-065/14-065.html#61 + errorException (m,_("The process does not permit the desired execution mode."),"NoSuchMode", mode->value); + fflush (stdout); + freeMaps (&m); + free (m); + if(zooRegistry!=NULL){ + freeRegistry(&zooRegistry); + free(zooRegistry); + } + freeMaps (&request_input_real_format); + free (request_input_real_format); + freeMaps (&request_output_real_format); + free (request_output_real_format); + free (REQUEST); + free (SERVICE_URL); + return 0; + }else + addToMap(request_inputs,"status","true"); + } + } + else{ + if(strcasecmp(status->value,"auto")==0){ + if(mode!=NULL){ + if(strcasecmp(mode->value,"async")==0) + addToMap(request_inputs,"status","false"); + else + addToMap(request_inputs,"status","true"); + } + else + addToMap(request_inputs,"status","false"); + }else + addToMap(request_inputs,"status","false"); + } + status = getMap (request_inputs, "status"); + } + + int eres = SERVICE_STARTED; + int cpid = zGetpid (); + + maps* bmap=NULL; + char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog; + FILE *f0, *f1; + if (status != NULL) + if (strcasecmp (status->value, "false") == 0) + status = NULLMAP; + if (status == NULLMAP) + { + if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){ + freeService (&s1); + free (s1); + freeMaps (&m); + free (m); + free (REQUEST); + free (SERVICE_URL); + freeMaps (&request_input_real_format); + free (request_input_real_format); + freeMaps (&request_output_real_format); + free (request_output_real_format); + freeMaps (&tmpmaps); + free (tmpmaps); + return -1; + } + map* testMap=getMapFromMaps(m,"main","memory"); + if(testMap==NULL || strcasecmp(testMap->value,"load")!=0) + dumpMapsValuesToFiles(&m,&request_input_real_format); + loadServiceAndRun (&m, s1, request_inputs, &request_input_real_format, + &request_output_real_format, &eres); + +#ifdef META_DB + close_sql(m,0); +#endif + } + else + { + int pid; +#ifdef DEBUG + fprintf (stderr, "\nPID : %d\n", cpid); +#endif +#ifndef WIN32 + pid = fork (); +#else + if (cgiSid == NULL) + { + createProcess (m, request_inputs, s1, NULL, cpid, + request_input_real_format, + request_output_real_format); + pid = cpid; + } + else + { + pid = 0; + cpid = atoi (cgiSid); + updateStatus(m,0,_("Initializing")); + } +#endif + if (pid > 0) + { + // + // dady : + // set status to SERVICE_ACCEPTED + // +#ifdef DEBUG + fprintf (stderr, "father pid continue (origin %d) %d ...\n", cpid, + zGetpid ()); +#endif + eres = SERVICE_ACCEPTED; + } + else if (pid == 0) + { + eres = SERVICE_ACCEPTED; + // + // son : have to close the stdout, stdin and stderr to let the parent + // process answer to http client. + // + map* usid = getMapFromMaps (m, "lenv", "uusid"); + map* tmpm = getMapFromMaps (m, "lenv", "osid"); + int cpid = atoi (tmpm->value); + pid=cpid; + r_inputs = getMapFromMaps (m, "main", "tmpPath"); + setMapInMaps (m, "lenv", "async","true"); + map* r_inputs1 = createMap("ServiceName", s1->name); + + // Create the filename for the result file (.res) + fbkpres = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value); + bmap = createMaps("status"); + bmap->content=createMap("usid",usid->value); + addToMap(bmap->content,"sid",tmpm->value); + addIntToMap(bmap->content,"pid",zGetpid()); + + // Create PID file referencing the OS process identifier + fbkpid = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value); + setMapInMaps (m, "lenv", "file.pid", fbkpid); + + f0 = freopen (fbkpid, "w+",stdout); + printf("%d",zGetpid()); + fflush(stdout); + + // Create SID file referencing the semaphore name + fbkp = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value); + setMapInMaps (m, "lenv", "file.sid", fbkp); + FILE* f2 = freopen (fbkp, "w+",stdout); + printf("%s",tmpm->value); + fflush(f2); + free(fbkp); + + fbkp = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 7) * sizeof (char)); + sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value, + usid->value); + setMapInMaps (m, "lenv", "file.responseInit", fbkp); + flog = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 13) * sizeof (char)); + sprintf (flog, "%s/%s_%s_error.log", r_inputs->value, + r_inputs1->value, usid->value); + setMapInMaps (m, "lenv", "file.log", flog); +#ifdef DEBUG + fprintf (stderr, "RUN IN BACKGROUND MODE \n"); + fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid, + zGetpid ()); + fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value); +#endif + freopen (flog, "w+", stderr); + fflush (stderr); + f0 = freopen (fbkp, "w+", stdout); + rewind (stdout); +#ifndef WIN32 + fclose (stdin); +#endif +#ifdef RELY_ON_DB + init_sql(m); + recordServiceStatus(m); +#endif +#ifdef USE_CALLBACK + invokeCallback(m,NULL,NULL,0,0); +#endif + if(vid==0){ + // + // set status to SERVICE_STARTED and flush stdout to ensure full + // content was outputed (the file used to store the ResponseDocument). + // Then, rewind stdout to restart writing from the begining of the file. + // This way, the data will be updated at the end of the process run. + // + printProcessResponse (m, request_inputs, cpid, s1, r_inputs1->value, + SERVICE_STARTED, request_input_real_format, + request_output_real_format); + fflush (stdout); +#ifdef RELY_ON_DB + recordResponse(m,fbkp); +#endif + } + + fflush (stderr); + + fbkp1 = + (char *) + malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) + + strlen (usid->value) + 13) * sizeof (char)); + sprintf (fbkp1, "%s/%s_final_%s.xml", r_inputs->value, + r_inputs1->value, usid->value); + setMapInMaps (m, "lenv", "file.responseFinal", fbkp1); + + f1 = freopen (fbkp1, "w+", stdout); + + map* serviceTypeMap=getMap(s1->content,"serviceType"); + if(serviceTypeMap!=NULL) + setMapInMaps (m, "lenv", "serviceType", serviceTypeMap->value); + + char *flenv = + (char *) + malloc ((strlen (r_inputs->value) + + strlen (usid->value) + 12) * sizeof (char)); + sprintf (flenv, "%s/%s_lenv.cfg", r_inputs->value, usid->value); + maps* lenvMaps=getMaps(m,"lenv"); + dumpMapsToFile(lenvMaps,flenv,0); + free(flenv); + +#ifdef USE_CALLBACK + invokeCallback(m,request_input_real_format,NULL,1,0); +#endif + if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){ + freeService (&s1); + free (s1); + fflush (stdout); + fflush (stderr); + fclose (f0); + fclose (f1); + if(dumpBackFinalFile(m,fbkp,fbkp1)<0) + return -1; +#ifndef RELY_ON_DB + dumpMapsToFile(bmap,fbkpres,1); + removeShmLock (m, 1); +#else + recordResponse(m,fbkp1); +#ifdef USE_CALLBACK + invokeCallback(m,NULL,NULL,7,0); +#endif +#endif + zUnlink (fbkpid); + unhandleStatus (m); +#ifdef RELY_ON_DB +#ifdef META_DB + cleanupCallbackThreads(); + close_sql(m,1); +#endif + close_sql(m,0); +#endif + freeMaps (&m); + free (m); + free (REQUEST); + free (SERVICE_URL); + freeMaps (&request_input_real_format); + free (request_input_real_format); + freeMaps (&request_output_real_format); + free (request_output_real_format); + freeMaps (&tmpmaps); + free (tmpmaps); + return -1; + } + if(getMapFromMaps(m,"lenv","mapError")!=NULL){ + setMapInMaps(m,"lenv","message",_("Issue with geographic data")); +#ifdef USE_CALLBACK + invokeCallback(m,NULL,NULL,7,0); +#endif + eres=-1;//SERVICE_FAILED; + }else{ + map* testMap=getMapFromMaps(m,"main","memory"); + if(testMap==NULL || strcasecmp(testMap->value,"load")!=0) + dumpMapsValuesToFiles(&m,&request_input_real_format); + loadServiceAndRun (&m, s1, request_inputs, + &request_input_real_format, + &request_output_real_format, &eres); + } + } + else + { + /** + * error server don't accept the process need to output a valid + * error response here !!! + */ + eres = -1; + errorException (m, _("Unable to run the child process properly"), + "InternalError", NULL); + } + } + +#ifdef DEBUG + fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__); + dumpMaps (request_output_real_format); + fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__); +#endif + fflush(stdout); + rewind(stdout); + + //fprintf(stderr,"%s %d %d\n",__FILE__,__LINE__,eres); + if (eres != -1) + outputResponse (s1, request_input_real_format, + request_output_real_format, request_inputs, + cpid, m, eres); + fflush (stdout); + + /** + * Ensure that if error occurs when freeing memory, no signal will return + * an ExceptionReport document as the result was already returned to the + * client. + */ +#ifndef USE_GDB + signal (SIGSEGV, donothing); + signal (SIGTERM, donothing); + signal (SIGINT, donothing); + signal (SIGILL, donothing); + signal (SIGFPE, donothing); + signal (SIGABRT, donothing); +#endif + + if (((int) zGetpid ()) != cpid || cgiSid != NULL) + { + if (eres == SERVICE_SUCCEEDED) +#ifdef USE_CALLBACK + invokeCallback(m,NULL,request_output_real_format,5,1); +#endif + fflush(stderr); + fflush(stdout); + + fclose (stdout); + + fclose (f0); + fclose (f1); + + if(dumpBackFinalFile(m,fbkp,fbkp1)<0) + return -1; + zUnlink (fbkpid); + switch(eres){ + default: + case SERVICE_FAILED: + setMapInMaps(bmap,"status","status",wpsStatus[1]); + setMapInMaps(m,"lenv","fstate",wpsStatus[1]); + break; + case SERVICE_SUCCEEDED: + setMapInMaps(bmap,"status","status",wpsStatus[0]); + setMapInMaps(m,"lenv","fstate",wpsStatus[0]); + break; + } +#ifndef RELY_ON_DB + dumpMapsToFile(bmap,fbkpres,1); + removeShmLock (m, 1); +#else + recordResponse(m,fbkp1); + if (eres == SERVICE_SUCCEEDED) +#ifdef USE_CALLBACK + invokeCallback(m,NULL,request_output_real_format,6,0); +#endif +#endif + freeMaps(&bmap); + free(bmap); + zUnlink (fbkp1); + unhandleStatus (m); +#ifdef RELY_ON_DB +#ifdef META_DB + cleanupCallbackThreads(); + close_sql(m,1); +#endif + close_sql(m,0); + end_sql(); +#endif + free(fbkpid); + free(fbkpres); + free (fbkp1); + if(cgiSid!=NULL) + free(cgiSid); + InternetCloseHandle (&hInternet); + fprintf (stderr, "RUN IN BACKGROUND MODE %s %d \n",__FILE__,__LINE__); + fflush(stderr); + fclose (stderr); + zUnlink (flog); + free (flog); + } + else{ + //InternetCloseHandle (&hInternet); +#ifdef META_DB + close_sql(m,0); +#endif + } + + freeService (&s1); + free (s1); + freeMaps (&m); + free (m); + + freeMaps (&request_input_real_format); + free (request_input_real_format); + + freeMaps (&request_output_real_format); + free (request_output_real_format); + + free (REQUEST); + free (SERVICE_URL); +#ifdef DEBUG + fprintf (stderr, "Processed response \n"); + fflush (stdout); + fflush (stderr); +#endif + + if (((int) zGetpid ()) != cpid || cgiSid != NULL) + { + exit (0); + } + + return 0; +} diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess_ogcapi b/3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess_ogcapi new file mode 100644 index 00000000..2f72d4e6 --- /dev/null +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess_ogcapi @@ -0,0 +1,9 @@ +RewriteEngine On +SetEnvIf Request_URI "^\/?(\w+)\/ogc-api(.*)" SERVICES_NAMESPACE=$1 +RewriteRule ^\/?(\w+)\/ogc-api/(.*) /ogc-api/$2 [PT] +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule ^api.html$ /zoo-bin/zoo_loader.cgi?/api.html [L,QSA] +RewriteRule ^index.html$ /zoo-bin/zoo_loader.cgi?service=WPS&service=WPS&request=Execute&version=1.0.0&Identifier=display&RawDataOutput=Result&DataInputs=tmpl=@xlink:href=http://localhost/ogc-api/ [L,QSA] +RewriteRule ^(.*).html$ /zoo-bin/zoo_loader.cgi?service=WPS&service=WPS&request=Execute&version=1.0.0&Identifier=display&RawDataOutput=Result&DataInputs=tmpl=@xlink:href=http://localhost/ogc-api/$1 [L,QSA] +RewriteRule ^(.*)$ /zoo-bin/zoo_loader.cgi?/$1 [L,QSA] diff --git a/3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess_wps3 b/3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess_wps3 index 51829d99..e99338e4 100644 --- a/3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess_wps3 +++ b/3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess_wps3 @@ -1,3 +1,3 @@ Options +FollowSymLinks RewriteEngine On -RewriteRule (.*) /zoo-bin/zoo_loader.cgi?/$1 [PT] \ No newline at end of file +RewriteRule (.*) /zoo-bin/zoo_loader.cgi?/$1&%{QUERY_STRING} [PT] \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 1f694b1b..7b18bd3a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ SHELL ["/bin/bash", "-c"] RUN yum install -y epel-release && \ yum update -y && \ - yum install -y json-c json-c-devel zlib-devel libxml2 libxml2-devel bison openssl python-devel subversion libxslt-devel libcurl-devel gdal gdal-devel proj-devel libuuid-devel openssl-devel fcgi-devel wget unzip autoconf flex cmake3 && \ + yum install -y json-c json-c-devel zlib-devel libxml2 libxml2-devel bison openssl python-devel subversion libxslt-devel libcurl-devel gdal gdal-devel proj-devel libuuid-devel openssl-devel fcgi-devel wget unzip autoconf flex cmake3 valgrind && \ yum install -y bzip2 kernel-devel which && ln -s /opt/rh/devtoolset-7/enable /etc/profile.d/rhgccenable.sh && chmod +x /etc/profile.d/rhgccenable.sh && \ yum install -y git && \ yum install -y automake && \ @@ -29,8 +29,19 @@ WORKDIR /project RUN cp 3ty/proc-comm-zoo-1.2-alpha/assets/zoo-project.tar.gz /opt/zoo-project.tar.gz RUN cd /opt/ && tar -zxvf zoo-project.tar.gz && rm -f zoo-project.tar.gz ### Apply patches -RUN cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/response_print.c /opt/zoo-project/zoo-project/zoo-kernel/response_print.c && \ +RUN cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/Makefile.in /opt/zoo-project/zoo-project/zoo-kernel/Makefile.in && \ + cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/configure.ac /opt/zoo-project/zoo-project/zoo-kernel/configure.ac && \ + cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/ZOOMakefile.opts.in /opt/zoo-project/zoo-project/zoo-kernel/ZOOMakefile.opts.in && \ + cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/response_print.h /opt/zoo-project/zoo-project/zoo-kernel/response_print.h && \ + cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/response_print.c /opt/zoo-project/zoo-project/zoo-kernel/response_print.c && \ cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/zoo_service_loader.c /opt/zoo-project/zoo-project/zoo-kernel/zoo_service_loader.c && \ + cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service.h /opt/zoo-project/zoo-project/zoo-kernel/service.h && \ + cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service.c /opt/zoo-project/zoo-project/zoo-kernel/service.c && \ + cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/server_internal.h /opt/zoo-project/zoo-project/zoo-kernel/server_internal.h && \ + cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/server_internal.c /opt/zoo-project/zoo-project/zoo-kernel/server_internal.c && \ + cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_callback.h /opt/zoo-project/zoo-project/zoo-kernel/service_callback.h && \ + cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_callback.c /opt/zoo-project/zoo-project/zoo-kernel/service_callback.c && \ + cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_json.h /opt/zoo-project/zoo-project/zoo-kernel/service_json.h && \ cp 3ty/proc-comm-zoo-1.2-alpha/assets/patch/zoo/service_json.c /opt/zoo-project/zoo-project/zoo-kernel/service_json.c ### Make libcgi RUN cd /opt/zoo-project/thirds/cgic206 && make libcgic.a && make install @@ -46,7 +57,8 @@ RUN mkdir -p /opt/t2service /opt/watchjob /var/www/zoo-bin/ /var/www/data/ /etc/ RUN cd /opt/zoo-project/zoo-project/zoo-services/utils/status && make ### Copy it as a service RUN cd /opt/zoo-project/zoo-project/zoo-services/utils/status/cgi-env && cp longProcess.zcfg wps_status.zo GetStatus.zcfg /opt/t2service/ && \ - cp /opt/zoo-project/zoo-project/zoo-services/utils/status/cgi-env/updateStatus.xsl /var/www/data/updateStatus.xsl + cp /opt/zoo-project/zoo-project/zoo-services/utils/status/cgi-env/updateStatus.xsl /var/www/data/updateStatus.xsl && \ + sed "s:serviceType = C:serviceType = C\n mutable = false:g" -i /opt/t2service/GetStatus.zcfg ### Copy watchjob source RUN cp -r 3ty/proc-comm-zoo-1.2-alpha/src/* /opt/watchjob/ ### Make watchjob @@ -69,10 +81,12 @@ RUN yum install -y vim httpd \ && chown -R 48:48 /var/www/zoo-bin/ /var/www/zoo-bin/ /var/www/data/ /var/www/_run/res \ && echo '/usr/local/lib' > /etc/ld.so.conf.d/zoo.conf && ldconfig \ && mkdir -p /opt/t2build/includes /opt/t2service/ /opt/opt/t2service/t2scripts/ \ - && mkdir -p /var/www/zoo-bin/ /var/www/_run/zoo/ + && mkdir -p /var/www/zoo-bin/ /var/www/_run/zoo/ /var/www/html/ogc-api /var/www/cache \ + && chown -R 48:48 /var/www/cache ## Copy HTTP files COPY 3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess_html /var/www/html/.htaccess +COPY 3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess_ogcapi /var/www/html/ogc-api/.htaccess COPY 3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess_wps3 /var/www/_run/wps3/.htaccess COPY 3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess_watchjob /var/www/_run/watchjob/.htaccess COPY 3ty/proc-comm-zoo-1.2-alpha/assets/zoo/httpd/htaccess /var/www/_run/zoo/.htaccess @@ -103,6 +117,19 @@ RUN wget -qO- https://micromamba.snakepit.net/api/micromamba/linux-64/latest | t rm -fr /srv/conda/pkgs && \ rm -fr /tmp/* +RUN git clone https://github.com/swagger-api/swagger-ui.git && \ + mv swagger-ui /var/www/html/swagger-ui && \ + sed "s=https://petstore.swagger.io/v2/swagger.json=http://localhost:8080/ogc-api/api=g" -i /var/www/html/swagger-ui/dist/* && \ + mv /var/www/html/swagger-ui/dist /var/www/html/swagger-ui/oapip && \ + mkdir -p /var/www/html/examples/snuggs-0_3_0 +COPY test/sample_apps/snuggs/deployment-job.json /var/www/html/examples/deployment-job.json +COPY test/sample_apps/snuggs/job_order1.json /var/www/html/examples/snuggs-0_3_0/job_order1.json +COPY test/sample_apps/snuggs/job_order2.json /var/www/html/examples/snuggs-0_3_0/job_order2.json +COPY test/sample_apps/snuggs/job_order3.json /var/www/html/examples/snuggs-0_3_0/job_order3.json +COPY test/sample_apps/vegetation-index/deployment-job.json /var/www/html/examples/deployment-job1.json +COPY test/sample_apps/dNBR/app-deploy-body.json /var/www/html/examples/deployment-job2.json + + COPY assets/main.cfg /opt/t2service/main.cfg COPY assets/oas.cfg /opt/t2service/oas.cfg diff --git a/assets/main.cfg b/assets/main.cfg index dc5d98a8..4e66611d 100644 --- a/assets/main.cfg +++ b/assets/main.cfg @@ -82,4 +82,11 @@ libWorkflowExecutor=/opt/t2service/libworkflow_executor.so userworkspace=/opt/zooservices_user defaultUser=anonymous userSpaceScript=/opt/t2scripts/prepareUserSpace.sh -removeServiceScript=/opt/t2scripts/removeservice.sh \ No newline at end of file +removeServiceScript=/opt/t2scripts/removeservice.sh + +[fnRewrite] +length=2 +val=. +rep=_ +val_1=- +rep_1=_ \ No newline at end of file diff --git a/assets/oas.cfg b/assets/oas.cfg index de1aa8c7..8d1e18a2 100644 --- a/assets/oas.cfg +++ b/assets/oas.cfg @@ -1,17 +1,31 @@ [openapi] -rootUrl=/watchjob -links=/,/api,/conformance,/processes -paths=/root,/api,/conformance,/processes,/processes/{id},/processes/{id}/jobs,/processes/{id}/jobs/{jobID},/processes/{id}/jobs/{jobID}/result -parameters=id,jobID,resultID -header_parameters=oas-header1,oas-header2 -version=3.0.1 +use_content=false +rootUrl=http://localhost:8080/ogc-api/ +rootPath=wps3 +links=/,/api,/conformance,/processes,/jobs +paths=/root,/api,/conformance,/processes,/processes/{processID},/processes/snuggs-0_3_0/execution,/processes/{processID}/execution,/jobs,/jobs/{jobID},/jobs/{jobID}/results +parameters=processID,jobID,resultID +header_parameters=oas-header1,oas-header2,oas-header3,limitParam,skipParam,processIdParam,statusParam,minDurationParam,maxDurationParam,typeParam,datetimeParam +version=3.0.3 +license_name=OGC license +license_url=https://raw.githubusercontent.com/opengeospatial/ogcapi-processes/master/LICENSE +full_html_support=false +partial_html_support=false +wsUrl=ws://localhost:8888/ +publisherUrl=http://zookernel/cgi-bin/publish.py?jobid= +link_href=http://zoo-project.org/dl/link.json +tags=Home,API,Conformance,GetCapabilities,DeployProcess,ProcessDescription,UndeployProcess,ExecuteEndpoint,JobList,GetStatus,GetResult,Dismiss +examplesPath=/var/www/html/examples/ +examplesUrl=http://localhost:8888/examples/ +exceptionsUrl=http://www.opengis.net/def/exceptions/ogcapi-processes-1/1.0 [oas-header1] in=header name=Prefer type=string -required=false -enum=respond-async +required=true +enum=return=representation,return=minimal,respond-async;return=representation +enum1=,return=representation,return=minimal,respond-async;return=representation,respond-async;return=minimal [oas-header2] in=header @@ -20,6 +34,33 @@ type=string required=false enum=return=representation,return=minimal +[oas-header3] +in=header +name=Prefer +type=string +required=true +enum=respond-async;return=representation + +[limitParam] +name=limit +title=The limit parameter +abstract=The limit parameter indicates the number of elements to return in an array +in=query +type=integer +schema_minimum=1 +schema_maximum=10000 +schema_default=1000 +required=false + +[skipParam] +name=skip +title=The skip parameter +abstract=The skip parameter indicates the number of elements to skip before starting returning values in an array +in=query +type=integer +schema_minimum=0 +required=false + [/] rel=self type=application/json @@ -31,13 +72,24 @@ title=landing page of this API abstract=The landing page provides links to the API definition, the Conformance statements and the metadata about the processes offered by this service. tags=Home tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/root.yaml +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/LandingPage.yaml + +[/index.html] +rel=alternate +type=text/html [/api] -rel=service -type=application/openapi+json;version=3.0 +rel=service-desc +type=application/vnd.oai.openapi+json;version=3.0 title=the API definition +[/api.html] +rel=service-doc +type=text/html + +[api.html] +href=http://localhost:8080/swagger-ui/oapip/ + [api] method=get title=This document @@ -47,20 +99,24 @@ tags_description= schema= [/conformance] -rel=conformance +rel=http://www.opengis.net/def/rel/ogc/1.0/conformance type=application/json -title=WPS 2.0 REST/JSON Binding Extension conformance classes implemented by this server +title=OGC API - Processes conformance classes implemented by this server [conformance] method=get title=information about standards that this API conforms to -abstract==list all requirements classes specified in a standard (e.g., WPS REST/JSON Binding Core) that the server conforms to +abstract=list all requirements classes specified in a standard (e.g., WPS REST/JSON Binding Core) that the server conforms to tags=Conformance tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/req-classes.yaml +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ConformanceDeclaration.yaml + +[/conformance.html] +rel=alternate +type=text/html [/processes] -rel=processes +rel=http://www.opengis.net/def/rel/ogc/1.0/processes type=application/json title=The processes offered by this server @@ -71,111 +127,157 @@ title=retrieve available processes abstract=Information about the available processes tags=GetCapabilities tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/processCollection.yaml +parameters=/components/parameters/limitParam,/components/parameters/skipParam +schema=https://raw.githubusercontent.com/GeoLabs/ogcapi-processes/rel-1.0/core/openapi/responses/ProcessList.yaml method_1=post -title_1=install service -abstract_1=install service -tags_1=Install Endpoint +code_1=201 +title_1=deploy a new processes +abstract_1=Deploy a new processes +tags_1=DeployProcess tags_description_1= -schema_1=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/result.yaml +parameters_1= +schema_1=https://raw.githubusercontent.com/GeoLabs/ogcapi-processes/master/extensions/deploy_replace_undeploy/standard/openapi/responses/DeployProcess.yaml +examples_1=deployment-job.json,deployment-job1.json,deployment-job2.json, +examples_summary=Deploy snuggs-0_3_0 process +examples_summary_1=Deploy vegetation-index process +examples_summary_2=Deploy dNBR process + +[/processes.html] +rel=alternate +type=text/html -[processes/{id}] +[processes/{processID}] +prel=http://www.opengis.net/def/rel/iana/1.0/describedby +rel=self length=2 method=get title=retrieve a process description abstract=A process description. tags=ProcessDescription tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/process.yaml -parameters=/components/parameters/id - +schema=https://raw.githubusercontent.com/GeoLabs/ogcapi-processes/rel-1.0/core/openapi/responses/swagger/ProcessDescription.yaml +ecode=404 +parameters=/components/parameters/processID method_1=delete -title=Remove a process -abstract=Remove process. -tags=ProcessRemove +code_1=204 +title_1=undeploy a mutable process +abstract_1=Undeploy a mutable process. +tags_1=UndeployProcess +tags_description_1= +ecode_1=404 +parameters_1=/components/parameters/processID + +[processes/{processID}/execution] +rel=http://www.opengis.net/def/rel/ogc/1.0/execute +length=1 +method=post +title=execute a job +abstract=An execute endpoint. +tags=ExecuteEndpoint tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/process.yaml -parameters=/components/parameters/id +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteSync.yaml +parameters=/components/parameters/processID,/components/parameters/oas-header1 +ecode=400,404,500 +eschema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteAsync.yaml +[processes/snuggs-0_3_0/execution] +length=1 +method=post +pname=snuggs-0_3_0 +title=execute a job +abstract=An execute endpoint. +tags=ExecuteEndpoint +tags_description= +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteSync.yaml +parameters=/components/parameters/oas-header3 +ecode=400,404,500 +eschema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteAsync.yaml +examples=job_order1.json,job_order2.json,job_order3.json +examples_summary=Execute suggs-0_3_0 producing ndvi and nbr for a single image +examples_summary_1=Execute suggs-0_3_0 producing ndvi and nbr for another image +examples_summary_2=Execute suggs-0_3_0 producing ndvi and nbr for the two images -[/processes/{id}/jobs] -rel=canonical +[/jobs] +rel=http://www.opengis.net/def/rel/ogc/1.0/job-list type=application/json -title=Process Description +title=Job Management -[processes/{id}/jobs] -length=2 +[jobs] +length=1 method=get title=retrieve a list of jobs run abstract=A list of jobs run. tags=JobList tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/jobCollection.yaml -parameters=/components/parameters/id +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/JobList.yaml +parameters=/components/parameters/limitParam,/components/parameters/skipParam,/components/parameters/processIdParam,/components/parameters/statusParam,/components/parameters/minDurationParam,/components/parameters/maxDurationParam,/components/parameters/typeParam,/components/parameters/datetimeParam +ecode=404,500 method_1=post title_1=execute a job abstract_1=An execute endpoint. -tags_1=Execute Endpoint +tags_1=ExecuteEndpoint tags_description_1= -schema_1=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/result.yaml -parameters_1=/components/parameters/id,/components/parameters/oas-header1 +schema_1=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteSync.yaml +parameters_1= +ecode_1=400,404,500 +eschema_1=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ExecuteAsync.yaml +ep=,/components/parameters/oas-header1 [requestBody] abstract=Mandatory execute request in JSON format type=application/json -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/execute.yaml +schema=https://raw.githubusercontent.com/GeoLabs/ogcapi-processes/rel-1.0/core/openapi/schemas/execute.yaml -[/processes/{id}/jobs/{jobID}] +[/jobs.html] +rel=alternate +type=text/html + +[/jobs/{jobID}] rel=canonical type=application/json title=Status -[processes/{id}/jobs/{jobID}] +[jobs/{jobID}] +length=2 method=get title=The status of a job. abstract=The status of a job. tags=GetStatus tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/statusInfo.yaml -parameters=/components/parameters/id,/components/parameters/jobID +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/Status.yaml +parameters=/components/parameters/jobID +method_1=delete +title_1=Cancel a job +abstract_1=Cancel the job execution. +tags_1=Dismiss +tags_description_1=Cancel a job execution +schema_1=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/Status.yaml +parameters_1=/components/parameters/jobID +ecode_1=404,500 -[/processes/{id}/jobs/{jobID}/result] -rel=canonical +[/jobs/{jobID}/results] +rel=http://www.opengis.net/def/rel/ogc/1.0/results type=application/json title=Get Result -[processes/{id}/jobs/{jobID}/result] +[jobs/{jobID}/results] method=get title=The result of a job execution. abstract=The result of a job execution. tags=GetResult tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/result.yaml -parameters=/components/parameters/id,/components/parameters/jobID +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/Results.yaml +parameters=/components/parameters/jobID +ecode=404,500 ep=,/components/parameters/oas-header2 -[/processes/{id}/jobs/{jobID}/result/{resultID}] -rel=canonical -type=application/json -title=Get Result - -[processes/{id}/jobs/{jobID}/result/{resultID}] -method=get -title=The result of a job execution. -abstract=The result of a job execution. -tags=GetResult -tags_description= -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/valueType.yaml -parameters=/components/parameters/id,/components/parameters/jobID,/components/parameters/resultID,/components/parameters/oas-header2 - - -[{id}] +[{processID}] type=string title=The id of a process abstract=The id of a process in=path required=true -example=buffer +example=snuggs-0_3_0 [{jobID}] type=string @@ -191,6 +293,24 @@ abstract=The id of an output in=path required=true +[statusParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/status.yaml + +[processIdParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/processIdQueryParam.yaml + +[minDurationParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/minDuration.yaml + +[maxDurationParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/maxDuration.yaml + +[typeParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/type.yaml + +[datetimeParam] +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/parameters/datetime.yaml + [{f}] default=json enum=json @@ -199,14 +319,91 @@ abstract=The optional f parameter indicates the output format which the server s in=query required=false -[conformTo] -rootUrl=http://www.opengis.net/spec/WPS/2.0/req/service/binding/rest-json/ +[conformsTo] +rootUrl=http://www.opengis.net/spec/ogcapi-processes/1.0/req/ +extentionsLength=1 +extentionUrl=http://www.opengis.net/spec/ogcapi-processes-2/1.0/req/ link=core link_1=oas30 link_2=json -length=3 +link_3=job-list +link_4=dismiss +link_5=callback +link_6=ogc-process-description +link_7=html +link_8=deploy-replace-undeploy +extention_8=true +extid_8=0 +length=9 [exception] abstract=Exception type=application/json -schema=https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi/schemas/exception.yaml +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/NotFound.yaml +default_schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ServerError.yaml + +[responses] +length=5 +code=404 +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/NotFound.yaml +type=application/json +title=NotFound +code_1=500 +schema_1=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/ServerError.yaml +type_1=application/json +title_1=ServerError +code_2=400 +schema_2=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/InvalidParameter.yaml +type_2=appliction/json +title_2=InvalidParameter +code_3=405 +schema_3=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/NotAllowed.yaml +type_3=appliction/json +title_3=NotAllowed +code_4=406 +schema_4=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/responses/NotSupported.yaml +type_4=appliction/json +title_4=NotSupported + +[callbacks] +length=3 +state=jobSuccess +uri=successUri +schema=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/schemas/results.yaml +type=application/json +title=Results received successfully +state_1=jobInProgress +uri_1=inProgressUri +schema_1=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/schemas/statusInfo.yaml +type_1=application/json +title_1=Status received successfully +state_2=jobFailed +uri_2=failedUri +schema_2=http://schemas.opengis.net/ogcapi/processes/part1/1.0/openapi/schemas/exception.yaml +type_2=application/json +title_2=Exception received successfully + +[links_title] +self=View this document in JSON. +alternate=View the alternative version in HTML. +conformance=View the conformance classes that the link's context conforms to. +service-desc=View the service description. +service-doc=View service documentation. +processes=View the list of processes the API offers. +results=View the results of a process. +status=View the current status of a job execution. +execute=View the execution endpoint of a process. +job-list=View the list of job available on this server. + +[provider_alt] +addressDeliveryPoint=streetAddress +addressCity=addressLocality +addressAdministrativeArea=addressRegion +addressPostalCode=postalCode +addressCountry=addressCountry +addressElectronicMailAddress=email +phoneVoice=telephone +phoneFacsimile=faxNumber +hoursOfService=hoursAvailable +contactInstructions=contactOption + diff --git a/build.yml b/build.yml index 4d8ea085..f2a132c6 100644 --- a/build.yml +++ b/build.yml @@ -1,4 +1,2 @@ docker_image_name: eoepca/proc-ades -docker_image_version: 1.2.0 - - +docker_image_version: 2.0.0 diff --git a/charts/ades/files/main.cfg.tpl b/charts/ades/files/main.cfg.tpl index 9f6874f8..c9475db1 100644 --- a/charts/ades/files/main.cfg.tpl +++ b/charts/ades/files/main.cfg.tpl @@ -12,7 +12,7 @@ cacheDir=/var/www/cache lang=en-US,en-GB language=en-US msOgcVersion=1.0.0 -tmpUrl=/res +tmpUrl=http://localhost:8080/_run/res cors=false storeExecuteResponse=true servicePath=/zooservices/ @@ -83,4 +83,13 @@ libWorkflowExecutor=/opt/t2service/libworkflow_executor.so userworkspace=/opt/zooservices_user defaultUser=anonymous userSpaceScript=/opt/t2scripts/prepareUserSpace.sh -removeServiceScript=/opt/t2scripts/removeservice.sh \ No newline at end of file +removeServiceScript=/opt/t2scripts/removeservice.sh + + +[fnRewrite] +length=2 +val=. +rep=_ +val_1=- +rep_1=_ + diff --git a/src/deployundeploy/zoo/DeployProcess.zcfg b/src/deployundeploy/zoo/DeployProcess.zcfg index 610178cd..777cbe18 100644 --- a/src/deployundeploy/zoo/DeployProcess.zcfg +++ b/src/deployundeploy/zoo/DeployProcess.zcfg @@ -4,6 +4,7 @@ processVersion = 1.0.0 storeSupported = true statusSupported = true + mutable = false serviceType = C serviceProvider = libepcatransactional.zo diff --git a/src/deployundeploy/zoo/UndeployProcess.zcfg b/src/deployundeploy/zoo/UndeployProcess.zcfg index de8a4855..ab454b1e 100644 --- a/src/deployundeploy/zoo/UndeployProcess.zcfg +++ b/src/deployundeploy/zoo/UndeployProcess.zcfg @@ -4,6 +4,7 @@ processVersion = 1.0.0 storeSupported = true statusSupported = true + mutable = false serviceType = C serviceProvider = libepcatransactional.zo diff --git a/src/deployundeploy/zoo/deploy.cpp b/src/deployundeploy/zoo/deploy.cpp index 4a348a6c..da781b3b 100644 --- a/src/deployundeploy/zoo/deploy.cpp +++ b/src/deployundeploy/zoo/deploy.cpp @@ -450,7 +450,7 @@ int job(maps *&conf, maps *&inputs, maps *&outputs, Operation operation) { map *applicationPackageZooMapHref = getMapFromMaps(inputs, "applicationPackage", "xlink:href"); - map *applicationPackageZooMimeTypeMap = getMapFromMaps(inputs, "applicationPackage", "mimeType"); + map *applicationPackageZooMimeTypeMap = getMapFromMaps(inputs, "applicationPackage", "type"); if (applicationPackageZooMimeTypeMap){ theMimeType=applicationPackageZooMimeTypeMap->value; } @@ -662,11 +662,17 @@ int job(maps *&conf, maps *&inputs, maps *&outputs, Operation operation) { zooRef.append(".zo"); xml->startElement("status"); + + service_name_to_build=zoo->getIdentifier(); + replaceStr(service_name_to_build, ".", "_"); + setMapInMaps(conf,"lenv","deployedService",service_name_to_build.c_str()); + if (!fileExist(zooRef.c_str())) { - service_name_to_build=zoo->getIdentifier(); + /*service_name_to_build=zoo->getIdentifier(); replaceStr(service_name_to_build, ".", "_"); - replaceStr(service_name_to_build, "-", "_"); + replaceStr(service_name_to_build, "-", "_");*/ + replaceStr(service_name_to_build, "-", "_"); std::string COMPILE = ("make -C " + buildPath + " USERPATH=\"" +user->getPath() +"\" COMPILE=\"" + @@ -692,6 +698,7 @@ int job(maps *&conf, maps *&inputs, maps *&outputs, Operation operation) { xml->writeAttribute("mess", ""); xml->writeContent("ready"); + if (usepep){ resource->dump(); @@ -822,16 +829,24 @@ extern "C" { ZOO_DLL_EXPORT int DeployProcess(maps *&conf, maps *&inputs, maps *&outputs){ - dumpMaps(inputs); - dumpMaps(conf); + fprintf(stderr,"------- %s %d \n",__FILE__,__LINE__); + fflush(stderr); + dumpMaps(inputs); + fprintf(stderr,"------- %s %d \n",__FILE__,__LINE__); + fflush(stderr); + //dumpMaps(conf); return job(conf, inputs, outputs, Operation::DEPLOY); } ZOO_DLL_EXPORT int UndeployProcess(maps *&conf, maps *&inputs, maps *&outputs) { - dumpMaps(inputs); - dumpMaps(conf); + fprintf(stderr,"------- %s %d \n",__FILE__,__LINE__); + fflush(stderr); + dumpMaps(inputs); + fprintf(stderr,"------- %s %d \n",__FILE__,__LINE__); + fflush(stderr); + //dumpMaps(conf); return job(conf, inputs, outputs, Operation::UNDEPLOY); } -} \ No newline at end of file +} diff --git a/test/sample_apps/dNBR/app-deploy-body.json b/test/sample_apps/dNBR/app-deploy-body.json index 092f2f48..76062076 100644 --- a/test/sample_apps/dNBR/app-deploy-body.json +++ b/test/sample_apps/dNBR/app-deploy-body.json @@ -1,28 +1,8 @@ { - "inputs": [ - { - "id": "applicationPackage", - "input": { - "format": { - "mimeType": "application/cwl" - }, - "value": { - "href": "https://raw.githubusercontent.com/EOEPCA/proc-ades/develop/test/sample_apps/dNBR/dNBR.cwl#dnbr" - } - } + "inputs": { + "applicationPackage": { + "type":"application/cwl", + "href": "https://raw.githubusercontent.com/EOEPCA/proc-ades/develop/test/sample_apps/dNBR/dNBR.cwl#dnbr" + } } - ], - "outputs": [ - { - "format": { - "mimeType": "string", - "schema": "string", - "encoding": "string" - }, - "id": "deployResult", - "transmissionMode": "value" - } - ], - "mode": "auto", - "response": "raw" } diff --git a/test/sample_apps/dNBR/app-execute-body.json b/test/sample_apps/dNBR/app-execute-body.json index e88a55f9..1f4b6879 100644 --- a/test/sample_apps/dNBR/app-execute-body.json +++ b/test/sample_apps/dNBR/app-execute-body.json @@ -1,45 +1,14 @@ { - "inputs": [ - { - "id": "post_stac_item", - "input": { - "dataType": { - "name": "application/json" - }, - "value": "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/S2B_53HPA_20210723_0_L2A" - } + "inputs": { + "post_stac_item": [ + "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/S2B_53HPA_20210723_0_L2A", + "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/S2B_53HPA_20210703_0_L2A" + ], + "aoi": "136.659,-35.96,136.923,-35.791" }, - { - "id": "pre_stac_item", - "input": { - "dataType": { - "name": "application/json" - }, - "value": "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/S2B_53HPA_20210703_0_L2A" - } + "outputs": { + "wf_outputs":{ + "transmissionMode": "value" + } }, - - { - "id": "aoi", - "input": { - "dataType": { - "name": "string" - }, - "value": "136.659,-35.96,136.923,-35.791" - } - } - ], - "outputs": [ - { - "format": { - "mimeType": "string", - "schema": "string", - "encoding": "string" - }, - "id": "wf_outputs", - "transmissionMode": "value" - } - ], - "mode": "auto", - "response": "raw" -} \ No newline at end of file +} diff --git a/test/sample_apps/snuggs/deployment-job.json b/test/sample_apps/snuggs/deployment-job.json index 61e341e0..d665c850 100644 --- a/test/sample_apps/snuggs/deployment-job.json +++ b/test/sample_apps/snuggs/deployment-job.json @@ -1,28 +1,9 @@ { - "inputs": [ + "inputs": { - "id": "applicationPackage", - "input": { - "format": { - "mimeType": "application/cwl" - }, - "value": { - "href": "https://raw.githubusercontent.com/EOEPCA/app-snuggs/main/app-package.cwl" + "applicationPackage": { + "href": "https://raw.githubusercontent.com/EOEPCA/app-snuggs/main/app-package.cwl", + "type": "application/cwl" } - } } - ], - "outputs": [ - { - "format": { - "mimeType": "string", - "schema": "string", - "encoding": "string" - }, - "id": "deployResult", - "transmissionMode": "value" - } - ], - "mode": "auto", - "response": "raw" -} \ No newline at end of file +} diff --git a/test/sample_apps/snuggs/deployment-job.json.save b/test/sample_apps/snuggs/deployment-job.json.save new file mode 100644 index 00000000..61e341e0 --- /dev/null +++ b/test/sample_apps/snuggs/deployment-job.json.save @@ -0,0 +1,28 @@ +{ + "inputs": [ + { + "id": "applicationPackage", + "input": { + "format": { + "mimeType": "application/cwl" + }, + "value": { + "href": "https://raw.githubusercontent.com/EOEPCA/app-snuggs/main/app-package.cwl" + } + } + } + ], + "outputs": [ + { + "format": { + "mimeType": "string", + "schema": "string", + "encoding": "string" + }, + "id": "deployResult", + "transmissionMode": "value" + } + ], + "mode": "auto", + "response": "raw" +} \ No newline at end of file diff --git a/test/sample_apps/snuggs/deployment-job2.json b/test/sample_apps/snuggs/deployment-job2.json new file mode 100644 index 00000000..1c2fd188 --- /dev/null +++ b/test/sample_apps/snuggs/deployment-job2.json @@ -0,0 +1,22 @@ +{ + "inputs": + { + "applicationPackage": { + "href": "https://raw.githubusercontent.com/EOEPCA/app-snuggs/main/app-package.cwl", + "type": "application/cwl" + } + }, + "outputs": + { + "unDeployResult":{ + "format": { + "mimeType": "string", + "schema": "string", + "encoding": "string" + }, + "transmissionMode": "value" + } + }, + "mode": "auto", + "response": "raw" +} diff --git a/test/sample_apps/snuggs/job_order1.json b/test/sample_apps/snuggs/job_order1.json new file mode 100644 index 00000000..c958d9ee --- /dev/null +++ b/test/sample_apps/snuggs/job_order1.json @@ -0,0 +1,9 @@ +{ + "inputs": { + "input_reference": "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/S2B_36RTT_20191205_0_L2A", + "s_expression":[ + "nbr:(/ (- B05 B02) (+ B05 B02))", + "ndvi:(/ (- B05 B03) (+ B05 B03))" + ] + } +} diff --git a/test/sample_apps/snuggs/job_order2.json b/test/sample_apps/snuggs/job_order2.json new file mode 100644 index 00000000..e0b64ded --- /dev/null +++ b/test/sample_apps/snuggs/job_order2.json @@ -0,0 +1,9 @@ +{ + "inputs": { + "input_reference": "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/S2B_36RTT_20191215_0_L2A", + "s_expression":[ + "nbr:(/ (- B05 B02) (+ B05 B02))", + "ndvi:(/ (- B05 B03) (+ B05 B03))" + ] + } +} diff --git a/test/sample_apps/snuggs/job_order3.json b/test/sample_apps/snuggs/job_order3.json new file mode 100644 index 00000000..c1c21099 --- /dev/null +++ b/test/sample_apps/snuggs/job_order3.json @@ -0,0 +1,12 @@ +{ + "inputs": { + "input_reference": [ + "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/S2B_36RTT_20191205_0_L2A", + "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/S2B_36RTT_20191215_0_L2A" + ], + "s_expression":[ + "nbr:(/ (- B05 B02) (+ B05 B02))", + "ndvi:(/ (- B05 B03) (+ B05 B03))" + ] + } +} diff --git a/test/sample_apps/snuggs/job_order4.json b/test/sample_apps/snuggs/job_order4.json new file mode 100644 index 00000000..9838f4a7 --- /dev/null +++ b/test/sample_apps/snuggs/job_order4.json @@ -0,0 +1,10 @@ +{ + "inputs": { + "input_reference": + "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/S2B_36RTT_20191215_0_L2A", + "s_expression":[ + "nbr:(/ (- B05 B02) (+ B05 B02))", + "ndvi:(/ (- B05 B03) (+ B05 B03))" + ] + } +} diff --git a/test/sample_apps/snuggs/job_order5.json b/test/sample_apps/snuggs/job_order5.json new file mode 100644 index 00000000..1116ff0e --- /dev/null +++ b/test/sample_apps/snuggs/job_order5.json @@ -0,0 +1,13 @@ +{ + "inputs": { + "input_reference": [ + "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/S2B_36RTT_20191205_0_L2A", + "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/S2B_36RTT_20191215_0_L2A" + ], + "s_expression":[ + "nbr:(/ (- B05 B02) (+ B05 B02))", + "ndvi:(/ (- B05 B03) (+ B05 B03))", + "ndwi:(/ (- B06 B03) (+ B06 B03))" + ] + } +} diff --git a/test/sample_apps/vegetation-index/deployment-job.json b/test/sample_apps/vegetation-index/deployment-job.json index 94be13e0..f3653176 100644 --- a/test/sample_apps/vegetation-index/deployment-job.json +++ b/test/sample_apps/vegetation-index/deployment-job.json @@ -1,28 +1,8 @@ { - "inputs": [ - { - "id": "applicationPackage", - "input": { - "format": { - "mimeType": "application/xml" - }, - "value": { + "inputs": { + "applicationPackage": { + "type": "application/xml", "href": "https://catalog.terradue.com/eoepca-services/search?uid=application_vegetation_index" - } } - } - ], - "outputs": [ - { - "format": { - "mimeType": "string", - "schema": "string", - "encoding": "string" - }, - "id": "deployResult", - "transmissionMode": "value" - } - ], - "mode": "async", - "response": "raw" - } \ No newline at end of file + } +} diff --git a/test/sample_apps/vegetation-index/deployment-job.json.save b/test/sample_apps/vegetation-index/deployment-job.json.save new file mode 100644 index 00000000..75dd7f97 --- /dev/null +++ b/test/sample_apps/vegetation-index/deployment-job.json.save @@ -0,0 +1,28 @@ +{ + "inputs": [ + { + "id": "applicationPackage", + "input": { + "format": { + "mimeType": "application/xml" + }, + "value": { + "href": "https://catalog.terradue.com/eoepca-services/search?uid=application_vegetation_index" + } + } + } + ], + "outputs": [ + { + "format": { + "mimeType": "string", + "schema": "string", + "encoding": "string" + }, + "id": "deployResult", + "transmissionMode": "value" + } + ], + "mode": "async", + "response": "raw" + } diff --git a/test/sample_apps/vegetation-index/job_order.json b/test/sample_apps/vegetation-index/job_order.json index 65ad8efe..1478ca0e 100644 --- a/test/sample_apps/vegetation-index/job_order.json +++ b/test/sample_apps/vegetation-index/job_order.json @@ -1,35 +1,7 @@ { - "inputs": [ + "inputs": { - "id": "input_reference", - "input": { - "dataType": { - "name": "string" - }, - "value": "https://catalog.terradue.com/sentinel2/search?uid=S2A_MSIL2A_20191216T004701_N0213_R102_T53HPA_20191216T024808" - } - }, - { - "id": "aoi", - "input": { - "dataType": { - "name": "string" - }, - "value": "POLYGON((136.112726861895 -36.227897298303,137.333826362695 -36.2103069464338,137.305145407058 -35.2211228310596,136.099040812374 -35.2380875358202,136.112726861895 -36.227897298303))" - } - } - ], - "outputs": [ - { - "format": { - "mimeType": "string", - "schema": "string", - "encoding": "string" - }, - "id": "wf_output", - "transmissionMode": "value" + "input_reference": "https://catalog.terradue.com/sentinel2/search?uid=S2A_MSIL2A_20191216T004701_N0213_R102_T53HPA_20191216T024808", + "aoi": "POLYGON((136.112726861895 -36.227897298303,137.333826362695 -36.2103069464338,137.305145407058 -35.2211228310596,136.099040812374 -35.2380875358202,136.112726861895 -36.227897298303))" } - ], - "mode": "async", - "response": "raw" -} \ No newline at end of file +}