Index: trunk/zoo-project/zoo-kernel/request_parser.c
===================================================================
--- trunk/zoo-project/zoo-kernel/request_parser.c	(revision 870)
+++ trunk/zoo-project/zoo-kernel/request_parser.c	(revision 889)
@@ -628,5 +628,6 @@
 			  if (l == 4 )
 			    {
-			      if ((ltmp==NULL || strncmp (ltmp->value, "POST",4) != 0))
+			      if ((ltmp==NULL || strncasecmp (ltmp->value, "POST",4) != 0)) // 
+			      //if ((ltmp==NULL || strncmp (ltmp->value, "POST",4) != 0))
 				{
 				  if (loadRemoteFile
@@ -1168,4 +1169,5 @@
     }
   }
+  return 0;
 }
 
@@ -1468,5 +1470,6 @@
 
   xmlInitParser ();
-  xmlDocPtr doc = xmlReadMemory (post, cgiContentLength, "input_request.xml", NULL, XML_PARSE_RECOVER);
+  //xmlDocPtr doc = xmlReadMemory (post, cgiContentLength, "input_request.xml", NULL, XML_PARSE_RECOVER);
+  xmlDocPtr doc = xmlReadMemory (post, cgiContentLength, "input_request.xml", NULL, XML_PARSE_RECOVER | XML_PARSE_HUGE); // 
 
   /**
Index: trunk/zoo-project/zoo-kernel/response_print.c
===================================================================
--- trunk/zoo-project/zoo-kernel/response_print.c	(revision 870)
+++ trunk/zoo-project/zoo-kernel/response_print.c	(revision 889)
@@ -2611,8 +2611,9 @@
     map* tmpIV=getMap(request_inputs1,"RawDataOutput");
     if(tmpIV!=NULL){
-      tmpI=getMaps(request_outputs,tmpIV->value);
+      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){
@@ -2621,5 +2622,5 @@
       map *gfile=getMap(tmpI->content,"generated_file");
       if(gfile!=NULL){
-	gfile=getMap(tmpI->content,"expected_generated_file");
+	gfile=getMap(tmpI->content,"expected_generated_file");	
 	if(gfile==NULL){
 	  gfile=getMap(tmpI->content,"generated_file");
@@ -2627,5 +2628,5 @@
 	readGeneratedFile(m,tmpI->content,gfile->value);
       }
-      toto=getMap(tmpI->content,"value");
+      toto=getMap(tmpI->content,"value");	 
       if(toto==NULL){
 	char tmpMsg[1024];
@@ -2633,6 +2634,6 @@
 	errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput");
 	return;
-      }
-      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
+      }	  
+      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");	  	  
       if(fname!=NULL)
 	printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
Index: trunk/zoo-project/zoo-kernel/server_internal.c
===================================================================
--- trunk/zoo-project/zoo-kernel/server_internal.c	(revision 870)
+++ trunk/zoo-project/zoo-kernel/server_internal.c	(revision 889)
@@ -942,5 +942,5 @@
     (char *)
     malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
-  sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid);
+  sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid);  
   FILE* f0 = fopen (fbkpid, "r");
   if(f0!=NULL){
@@ -970,5 +970,5 @@
   }else{
     map* statusInfo=createMap("JobID",pid);
-    if(isRunning(conf,pid)>0){
+    if(isRunning(conf,pid)>0){		
       if(strncasecmp(req,"GetResult",strlen(req))==0){
 	errorException (conf, _("The result for the requested JobID has not yet been generated. "),
Index: trunk/zoo-project/zoo-kernel/service.c
===================================================================
--- trunk/zoo-project/zoo-kernel/service.c	(revision 870)
+++ trunk/zoo-project/zoo-kernel/service.c	(revision 889)
@@ -25,4 +25,8 @@
 #include "service.h"
 
+// knut: time utilities required for new log function (logMessage)
+#include <ctime>
+#include <chrono>
+#include <process.h>
 
 #if defined(_MSC_VER) && _MSC_VER < 1800
@@ -450,16 +454,18 @@
  */
 void addToMap(map* m,const char* n,const char* v){
-  if(hasKey(m,n)==false){
-    map* _cursor=m;
-    while(_cursor->next!=NULL){
-      _cursor=_cursor->next;
-    }
-    _cursor->next=createMap(n,v);
-  }
-  else{
-    map *tmp=getMap(m,n);
-    if(tmp->value!=NULL)
-      free(tmp->value);
-    tmp->value=zStrdup(v);
+  if (m != NULL) { // knut: add NULL-pointer check
+    if(hasKey(m,n)==false){
+      map* _cursor=m;
+      while(_cursor->next!=NULL){
+        _cursor=_cursor->next;
+      }
+      _cursor->next=createMap(n,v);
+    }
+    else{
+      map *tmp=getMap(m,n);
+      if(tmp->value!=NULL)
+        free(tmp->value);
+      tmp->value=zStrdup(v);
+    }
   }
 }
@@ -1597,4 +1603,113 @@
 }
 
+/**
+ * Verify that a map has a value
+ *
+ * @param map 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* map ) {
+    return ( map != NULL && map->value != NULL && strlen(map->value) > 0 && strcmp(map->value, "NULL") != 0 );
+}
+
+/**
+ * Verify that a particular map value exists in a maps 
+ * data structure, and obtain that value
+ *
+ * @param source pointer to maps structure
+ * @param node name of maps node to search
+ * @param key name of map node to find
+ * @param address to the map* if it exists, otherwise NULL
+ * @return true if map has a value or false if value is missing/NULL
+ */
+bool hasvalue( maps* source, const char* node, const char* key, map** kvp ) {
+    *kvp = getMapFromMaps(source, node, key);
+    return ( *kvp != NULL && (*kvp)->value != NULL && 
+             strlen((*kvp)->value) > 0 && strcmp((*kvp)->value, "NULL") != 0 );
+}
+
+/*
+ * Set error message in configuration maps
+ *
+ * @param conf reference to configuration maps
+ * @param service name of service 
+ * @param exc WPSException code
+ * @param message exception text (default: exception text in WPS specification)
+ */
+void setErrorMessage( maps*& conf, const char* service, WPSException exc, const char* message ) {
+  
+  if (message == NULL) {
+    message = WPSExceptionText[exc];
+  } 
+
+	size_t len = strlen( service ) + strlen(": ") + strlen( message ) + strlen(": ") + strlen(WPSExceptionCode[exc]) + 16;
+	char* msg = (char*) malloc( len * sizeof(char) );
+
+	if (msg != NULL) {
+		snprintf( msg, len*sizeof(char), "\n%s: %s: %s\n", service, message, WPSExceptionCode[exc] );
+		setMapInMaps( conf, "lenv", "message", msg );
+		free( msg );
+	}	
+}
+
+void logMessage(const char* source, const char* function, int line, const char* file, const char* message) { //, const char* source, const char* function, int line) {
+  
+  size_t msglen = 512;
+  const char empty[] = "";
+  
+  FILE* log;
+  
+  // 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* str = asctime(tm);
+  str[strlen(str)-1] = '\0'; // remove newline
+  
+  sys_t = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
+  //proc_t = (unsigned long long)(1.0e9*t/CLOCKS_PER_SEC);
+  proc_t = t;
+  
+  if ( message != NULL ) {
+     msglen += strlen(message);
+  }  
+  else {
+    message = empty;
+  }
+  //getLastErrorMessage(); // cgiScriptName  
+  char* text = (char*) malloc( sizeof(char)*msglen );
+  
+  snprintf( text, msglen, "pid: %d %s line %d %s() %s systime: %lld ns ticks: %lld %s\n", 
+    _getpid(), source, line, function, str, sys_t, proc_t, message ); // __FILE__ __LINE__ __func__ //
+  
+  if ( file != NULL && (log = fopen( file, "a+" )) != NULL ) {
+    fputs( text, log );
+    fclose( log );
+  }
+  else {
+    #ifdef MSG_LOG_FILE
+    if ( (log = fopen( MSG_LOG_FILE, "a+" )) != NULL ) {
+      fputs( text, log );
+      fclose( log );
+    }      
+    #endif
+  }
+  
+  if ( text != NULL ) free( text );
+}
+
+// knut:
+// Example:
+// zooLog;
+// zooLogMsg(NULL, getLastErrorMessage()); 
+// zooLogMsg(log.txt, getLastErrorMessage()); 
+
 #ifdef WIN32
 #ifndef USE_MS
Index: trunk/zoo-project/zoo-kernel/service.h
===================================================================
--- trunk/zoo-project/zoo-kernel/service.h	(revision 870)
+++ trunk/zoo-project/zoo-kernel/service.h	(revision 889)
@@ -40,4 +40,18 @@
 #endif
 
+// knut: add bool if necessary
+#ifndef __cplusplus
+  #ifndef WIN32
+    #include <stdbool.h>
+  #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 strncasecmp _strnicmp
@@ -47,4 +61,5 @@
 #define snprintf _snprintf
 #endif
+/* knut: see new definition of bool above
 #if defined(_MSC_VER) && _MSC_VER < 1800
 #define false 0
@@ -52,4 +67,5 @@
 #define bool int
 #endif
+*/
 #define zStrdup _strdup
 #define zMkdir _mkdir
@@ -124,5 +140,5 @@
 #ifndef WIN32
 #include <ctype.h>
-#include <stdbool.h>
+//#include <stdbool.h> // knut: see new definition of bool above
 #endif
 
@@ -274,4 +290,90 @@
     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
+  }; 
+  
+  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"    
+  };      
+
+  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*);
@@ -340,4 +442,13 @@
   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);
+  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);  
+  #define zooLogMsg(file,message) logMessage(__FILE__, __func__, __LINE__, (file), (message)) 
+  #define zooLog logMessage(__FILE__, __func__, __LINE__)  
+  
 #ifdef __cplusplus
 }
Index: trunk/zoo-project/zoo-kernel/service_internal.c
===================================================================
--- trunk/zoo-project/zoo-kernel/service_internal.c	(revision 870)
+++ trunk/zoo-project/zoo-kernel/service_internal.c	(revision 889)
@@ -243,5 +243,5 @@
  * @param conf the map containing the setting of the main.cfg file
  */
-void unhandleStatus(maps *conf){
+void unhandleStatus(maps *conf){	
   map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
   map* usid = getMapFromMaps (conf, "lenv", "usid");
Index: trunk/zoo-project/zoo-kernel/service_internal_ms.h
===================================================================
--- trunk/zoo-project/zoo-kernel/service_internal_ms.h	(revision 870)
+++ trunk/zoo-project/zoo-kernel/service_internal_ms.h	(revision 889)
@@ -38,4 +38,5 @@
 #endif
 
+
 #include <mapserver.h>
 
Index: trunk/zoo-project/zoo-kernel/ulinet.c
===================================================================
--- trunk/zoo-project/zoo-kernel/ulinet.c	(revision 870)
+++ trunk/zoo-project/zoo-kernel/ulinet.c	(revision 889)
@@ -91,5 +91,5 @@
 	;
 #endif
-    tmp=strtok(buffer,";");
+    tmp=strtok((char*) buffer,";"); // knut: added cast to char*
     cnt=0;
     psInternet=(_HINTERNET *)data;
@@ -247,6 +247,12 @@
   char *token, *saveptr;
   int cnt;
-  char* host;  
-  token = strtok_r (url, "//", &saveptr);
+  char* host; 
+  
+  // knut: make a copy of url since strtok family modifies first argument and cannot be used on constant strings  
+  char* urlcpy = (char*) malloc(sizeof(char)*(strlen(url)+1)); 
+  urlcpy = strncpy(urlcpy, url, strlen(url)+1); // since count > strlen(url), a null character is properly appended
+ 
+  //token = strtok_r (url, "//", &saveptr);
+  token = strtok_r (urlcpy, "//", &saveptr);   // knut
   cnt=0;
   while(token!=NULL && cnt<=1){
@@ -257,4 +263,5 @@
     if(cnt==1 && strstr(protectedHosts,token)!=NULL){
       fprintf(stderr,"%s %d %s \n",__FILE__,__LINE__,strstr(protectedHosts,token));
+      free(urlcpy); 
       return 1;
     }
@@ -262,4 +269,5 @@
     cnt+=1;
   }
+  free(urlcpy);
   return 0;
 }
Index: trunk/zoo-project/zoo-kernel/ulinet.h
===================================================================
--- trunk/zoo-project/zoo-kernel/ulinet.h	(revision 870)
+++ trunk/zoo-project/zoo-kernel/ulinet.h	(revision 889)
@@ -44,4 +44,5 @@
 #include "jsapi.h"
 #endif
+/* knut: see new definition of bool in service.h
 #ifndef bool
 #define bool int
@@ -51,4 +52,5 @@
 #define false 0
 #endif
+*/
 
 #define MAX_REQ 50
@@ -151,7 +153,9 @@
   typedef size_t* LPDWORD;
 #endif
+/* knut: see new definition of bool in service.h
 #ifndef bool
 #define bool int
 #endif
+*/
 
 #  define CHECK_INET_HANDLE(h) (h.handle != 0)
Index: trunk/zoo-project/zoo-kernel/zoo_service_loader.c
===================================================================
--- trunk/zoo-project/zoo-kernel/zoo_service_loader.c	(revision 870)
+++ trunk/zoo-project/zoo-kernel/zoo_service_loader.c	(revision 889)
@@ -159,19 +159,22 @@
   lockShm (lid);
 #endif
-  FILE *f3 = fopen (fbkp, "wb+");
-  free (fbkp);
+  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);
+  fread (tmps1, flen, 1, f2);  
 #ifdef WIN32
-  char *pchr=strrchr(tmps1,'>');
-  flen=strlen(tmps1)-strlen(pchr)+1;
-  tmps1[flen]=0;
-#endif
+  /* 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);
+  free(tmps1);
   fclose (f2);
-  fclose (f3);
+  fclose (f3);  
   return 1;
 }
@@ -2218,5 +2221,5 @@
 	  addToMap(bmap->content,"sid",tmpm->value);
 	  addIntToMap(bmap->content,"pid",getpid());
-	  
+	  	  
 	  // Create PID file referencing the OS process identifier
           fbkpid =
@@ -2309,5 +2312,5 @@
 	    if(dumpBackFinalFile(m,fbkp,fbkp1)<0)
 	      return -1;
-	    unlink (fbkpid);
+	    unlink (fbkpid);		
 	    unhandleStatus (m);
 	    freeMaps (&m);
@@ -2364,7 +2367,6 @@
   signal (SIGABRT, donothing);
 #endif
-
   if (((int) getpid ()) != cpid || cgiSid != NULL)
-    {
+    {	  
       fclose (stdout);
       fclose (stderr);
@@ -2372,8 +2374,9 @@
       fclose (f0);
       fclose (f1);
-
-      if(dumpBackFinalFile(m,fbkp,fbkp1)<0)
-	return -1;
-      unlink (fbkpid);
+	 
+	  if (dumpBackFinalFile(m, fbkp, fbkp1) < 0)
+		  return -1;
+	
+      unlink (fbkpid);	  
       switch(eres){
       default:
@@ -2387,5 +2390,5 @@
 	break;
       }      
-#ifndef RELY_ON_DB
+#ifndef RELY_ON_DB	  
       dumpMapsToFile(bmap,fbkpres,1);
       removeShmLock (m, 1);
