Index: trunk/zoo-project/zoo-kernel/service.c
===================================================================
--- trunk/zoo-project/zoo-kernel/service.c	(revision 889)
+++ trunk/zoo-project/zoo-kernel/service.c	(revision 917)
@@ -2,5 +2,5 @@
  * Author : Gérald FENOY
  *
- * Copyright (c) 2015 GeoLabs SARL
+ * Copyright (c) 2015-2019 GeoLabs SARL
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -28,5 +28,7 @@
 #include <ctime>
 #include <chrono>
+#ifdef WIN32
 #include <process.h>
+#endif
 
 #if defined(_MSC_VER) && _MSC_VER < 1800
@@ -102,6 +104,9 @@
     fprintf(stderr," * CONTENT [%s] \n",tmp->name);
     dumpMap(tmp->content);
-    fprintf(stderr," * CHILD [%s] \n",tmp->name);
-    dumpMaps(tmp->child);
+    if(tmp->child!=NULL){
+      fprintf(stderr," * CHILD [%s] \n",tmp->name);
+      dumpMaps(tmp->child);
+      fprintf(stderr," * /CHILD [%s] \n",tmp->name);
+    }
     tmp=tmp->next;
   }
@@ -125,7 +130,7 @@
     fflush(file);
     tmp=tmp->next;
-    cnt++;
     if(limit>=0 && cnt==limit)
       tmp=NULL;
+    cnt++;
   }
   fflush(file);
@@ -144,4 +149,16 @@
   fflush(file);
   fclose(file);
+}
+
+/**
+ * Create a new iotype*
+ *
+ * @return a pointer to the allocated iotype 
+ */
+iotype* createIoType(){
+  iotype* io=(iotype*)malloc(IOTYPE_SIZE);
+  io->content=NULL;
+  io->next=NULL;
+  return io;
 }
 
@@ -179,9 +196,25 @@
  * Count number of map in a map
  *
- * @param m the maps to count
+ * @param m the map to count
  * @return number of map in a map
  */
 int count(map* m){
   map* tmp=m;
+  int c=0;
+  while(tmp!=NULL){
+    c++;
+    tmp=tmp->next;
+  }
+  return c;
+}
+
+/**
+ * Count number of maps in a maps
+ *
+ * @param m the maps to count
+ * @return number of maps in a maps
+ */
+int maps_length(maps* m){
+  maps* tmp=m;
   int c=0;
   while(tmp!=NULL){
@@ -401,26 +434,49 @@
     if(tmp->metadata!=NULL)
       free(tmp->metadata);
+    freeMap(&tmp->additional_parameters);
+    if(tmp->additional_parameters!=NULL)
+      free(tmp->additional_parameters);
     if(tmp->format!=NULL)
       free(tmp->format);
+    freeElements(&tmp->child);
     if(tmp->child!=NULL){
-      freeElements(&tmp->child);
       free(tmp->child);
     }
-    freeIOType(&tmp->defaults);
-    if(tmp->defaults!=NULL)
+    if(tmp->defaults!=NULL){
+      freeIOType(&tmp->defaults);
       free(tmp->defaults);
-    freeIOType(&tmp->supported);
+    }
     if(tmp->supported!=NULL){
+      freeIOType(&tmp->supported);
       free(tmp->supported);
     }
-    freeElements(&tmp->next);
-    if(tmp->next!=NULL)
+    if(tmp->next!=NULL){
+      freeElements(&tmp->next);
       free(tmp->next);
-  }
+    }
+  }
+}
+
+
+/**
+ * Allocate memory for a service.
+ * Require to call free after calling this function.
+ *
+ * @return the service
+ */
+service* createService(){
+  service *s1 = (service *) malloc (SERVICE_SIZE);
+  s1->name=NULL;
+  s1->content=NULL;
+  s1->metadata=NULL;
+  s1->additional_parameters=NULL;
+  s1->inputs=NULL;
+  s1->outputs=NULL;
+  return s1;
 }
 
 /**
  * Free allocated memory of a service.
- * Require to call free on e after calling this function.
+ * Require to be invoked for every createService call.
  *
  * @param s the service to free
@@ -437,4 +493,7 @@
     if(tmp->metadata!=NULL)
       free(tmp->metadata);
+    freeMap(&tmp->additional_parameters);
+    if(tmp->additional_parameters!=NULL)
+      free(tmp->additional_parameters);
     freeElements(&tmp->inputs);
     if(tmp->inputs!=NULL)
@@ -454,19 +513,19 @@
  */
 void addToMap(map* m,const char* n,const char* 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);
-    }
-  }
+    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);
+        }
+    }
 }
 
@@ -506,4 +565,7 @@
  */
 map* addToMapWithSize(map* m,const char* n,const char* v,int size){
+  char sin[128];
+  char sname[10]="size";
+  map *tmp;
   if(hasKey(m,n)==false){
     map* _cursor=m;
@@ -514,8 +576,7 @@
     }
   }
-  char sname[10]="size";
   if(strlen(n)>5)
     sprintf(sname,"size_%s",n+6);
-  map *tmp=getMap(m,n);
+  tmp=getMap(m,n);
   if(tmp->value!=NULL)
     free(tmp->value);
@@ -524,5 +585,4 @@
     memmove(tmp->value,v,size*sizeof(char));
   tmp->value[size]=0;
-  char sin[128];
   sprintf(sin,"%d",size);
   addToMap(m,sname,sin);
@@ -545,12 +605,8 @@
     }
     else{
-#ifdef DEBUG
-      fprintf(stderr,"_CURSOR\n");
-      dumpMap(_cursor);
-#endif
-      while(_cursor->next!=NULL)
-	_cursor=_cursor->next;
       map* tmp1=getMap(*mo,tmp->name);
       if(tmp1==NULL){
+	while(_cursor->next!=NULL)
+	  _cursor=_cursor->next;
 	_cursor->next=createMap(tmp->name,tmp->value);
       }
@@ -561,8 +617,4 @@
     _cursor=*mo;
     tmp=tmp->next;
-#ifdef DEBUG
-    fprintf(stderr,"MO\n");
-    dumpMap(*mo);
-#endif
   }
 }
@@ -678,4 +730,5 @@
   map* size=getMap(in,"size");
   map *lout=*out;
+  map *tmpVin,*tmpVout;
   if(size!=NULL && pos>0){
     char tmp[11];
@@ -683,6 +736,6 @@
     size=getMap(in,tmp);
     sprintf(tmp,"value_%d",pos);
-    map* tmpVin=getMap(in,tmp);
-    map* tmpVout=getMap(lout,tmp);
+    tmpVin=getMap(in,tmp);
+    tmpVout=getMap(lout,tmp);
     free(tmpVout->value);
     tmpVout->value=(char*)malloc((atoi(size->value)+1)*sizeof(char));
@@ -691,6 +744,6 @@
   }else{
     if(size!=NULL){
-      map* tmpVin=getMap(in,"value");
-      map* tmpVout=getMap(lout,"value");
+      tmpVin=getMap(in,"value");
+      tmpVout=getMap(lout,"value");
       free(tmpVout->value);
       tmpVout->value=(char*)malloc((atoi(size->value)+1)*sizeof(char));
@@ -712,4 +765,11 @@
   map* size=getMap(in,"size");
   map* length=getMap(in,"length");
+  map* toload=getMap(in,"to_load");
+  if(toload!=NULL && strcasecmp(toload->value,"false")==0){
+#ifdef DEBUG
+    fprintf(stderr,"NO LOAD %s %d \n",__FILE__,__LINE__);
+#endif
+    return ;
+  }
   if(length!=NULL){
     int len=atoi(length->value);
@@ -734,11 +794,11 @@
   maps* res=NULL;
   if(_cursor!=NULL){
+    map* mc=_cursor->content;
+    maps* mcs=_cursor->child;
     res=createMaps(_cursor->name);
-    map* mc=_cursor->content;
     if(mc!=NULL){
       addMapToMap(&res->content,mc);
       loadMapBinaries(&res->content,mc);
     }
-    maps* mcs=_cursor->child;
     if(mcs!=NULL){
       res->child=dupMaps(&mcs);
@@ -764,7 +824,7 @@
     }
     else{
+      maps* tmp1=getMaps(*mo,tmp->name);
       while(_cursor->next!=NULL)
 	_cursor=_cursor->next;
-      maps* tmp1=getMaps(*mo,tmp->name);
       if(tmp1==NULL){
 	_cursor->next=dupMaps(&tmp);
@@ -797,4 +857,5 @@
 map* getMapArray(map* m,const char* key,int index){
   char tmp[1024];
+  map* tmpMap;
   if(index>0)
     sprintf(tmp,"%s_%d",key,index);
@@ -804,5 +865,5 @@
   fprintf(stderr,"** KEY %s\n",tmp);
 #endif
-  map* tmpMap=getMap(m,tmp);
+  tmpMap=getMap(m,tmp);
 #ifdef DEBUG
   if(tmpMap!=NULL)
@@ -823,7 +884,8 @@
 void setMapArray(map* m,const char* key,int index,const char* value){
   char tmp[1024];
+  map* tmpSize;
   if(index>0){
+    map* len=getMap(m,"length");
     sprintf(tmp,"%s_%d",key,index);
-    map* len=getMap(m,"length");
     if((len!=NULL && atoi(len->value)<index+1) || len==NULL){
       char tmp0[5];
@@ -832,12 +894,14 @@
     }
   }
-  else
+  else{
     sprintf(tmp,"%s",key);
-  map* tmpSize=getMapArray(m,"size",index);
+    addToMap(m,"length","1");
+  }
+  tmpSize=getMapArray(m,"size",index);
   if(tmpSize!=NULL && strncasecmp(key,"value",5)==0){
+    map* ptr=getMapOrFill(&m,tmp,(char *)"");
 #ifdef DEBUG
     fprintf(stderr,"%s\n",tmpSize->value);
 #endif
-    map* ptr=getMapOrFill(&m,tmp,(char *)"");
     free(ptr->value);
     ptr->value=(char*)malloc((atoi(tmpSize->value)+1)*sizeof(char));
@@ -846,4 +910,18 @@
   else
     addToMap(m,tmp,value);
+}
+
+/**
+ * Add a key and an integer value to an existing map array.
+ *
+ * @param m the map to add the KVP
+ * @param n the key to add
+ * @param index the index of the MapArray 
+ * @param v the corresponding value to add
+ */
+void addIntToMapArray(map* m,const char* n,int index,const int v){
+  char svalue[10];
+  sprintf(svalue,"%d",v);
+  setMapArray(m,n,index,svalue);
 }
 
@@ -881,15 +959,6 @@
   maps* tmp=mi;    
   maps* _cursor=getMaps(*mo,tmp->name);
-
-  if(_cursor==NULL)
-    return -1;
-
-  map* tmpLength=getMap(_cursor->content,"length");
   char tmpLen[10];
   int len=1;
-  if(tmpLength!=NULL){
-    len=atoi(tmpLength->value);
-  }
-
   char *tmpV[14]={
     (char*)"size",
@@ -906,9 +975,19 @@
     (char*)"isCached",
     (char*)"LowerCorner",
-    (char*)"UpperCorner"    
+    (char*)"UpperCorner"
   };
+  int i=0;
+  map* tmpLength;
+  
+  if(_cursor==NULL)
+    return -1;
+
+  tmpLength=getMap(_cursor->content,"length");
+  if(tmpLength!=NULL){
+    len=atoi(tmpLength->value);
+  }
+
   sprintf(tmpLen,"%d",len+1);
   addToMap(_cursor->content,"length",tmpLen);
-  int i=0;
   for(i=0;i<14;i++){
     map* tmpVI=getMap(tmp->content,tmpV[i]);
@@ -967,4 +1046,5 @@
   res->content=NULL;
   res->metadata=NULL;
+  res->additional_parameters=NULL;  
   res->format=NULL;
   res->defaults=NULL;
@@ -981,9 +1061,10 @@
  * @return a pointer to the allocated elements
  */
-elements* createElements(char* name){
+elements* createElements(const char* name){
   elements* res=(elements*)malloc(ELEMENTS_SIZE);
   res->name=zStrdup(name);
   res->content=NULL;
   res->metadata=NULL;
+  res->additional_parameters=NULL;
   res->format=NULL;
   res->defaults=NULL;
@@ -1020,4 +1101,6 @@
   elements* tmp=e;
   while(tmp!=NULL){
+    iotype* tmpio=tmp->defaults;
+    int ioc=0;
     fprintf(stderr,"ELEMENT [%s]\n",tmp->name);
     fprintf(stderr," > CONTENT [%s]\n",tmp->name);
@@ -1025,7 +1108,7 @@
     fprintf(stderr," > METADATA [%s]\n",tmp->name);
     dumpMap(tmp->metadata);
+    fprintf(stderr," > ADDITIONAL PARAMETERS [%s]\n",tmp->name);
+    dumpMap(tmp->additional_parameters);
     fprintf(stderr," > FORMAT [%s]\n",tmp->format);
-    iotype* tmpio=tmp->defaults;
-    int ioc=0;
     while(tmpio!=NULL){
       fprintf(stderr," > DEFAULTS [%s] (%i)\n",tmp->name,ioc);
@@ -1060,8 +1143,10 @@
   int i;
   while(tmp!=NULL){
+    map* mcurs=tmp->content;
+    int ioc=0;
+    iotype* tmpio;
     for(i=0;i<2+(4*level);i++)
       fprintf(stderr," ");
     fprintf(stderr,"%s:\n",tmp->name);
-    map* mcurs=tmp->content;
     while(mcurs!=NULL){
       for(i=0;i<4+(4*level);i++)
@@ -1091,6 +1176,5 @@
 	dumpElementsAsYAML(tmp->child,level+1);
     }
-    iotype* tmpio=tmp->defaults;
-    int ioc=0;
+    tmpio=tmp->defaults;
     while(tmpio!=NULL){
       for(i=0;i<6+(4*level);i++)
@@ -1142,5 +1226,5 @@
   elements* cursor=e;
   elements* tmp=NULL;
-  if(cursor!=NULL){
+  if(cursor!=NULL && cursor->name!=NULL){
 #ifdef DEBUG
     fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
@@ -1149,17 +1233,19 @@
 #endif
     tmp=(elements*)malloc(ELEMENTS_SIZE);
-    tmp->name=zStrdup(e->name);
+    tmp->name=zStrdup(cursor->name);
     tmp->content=NULL;
-    addMapToMap(&tmp->content,e->content);
+    addMapToMap(&tmp->content,cursor->content);
     tmp->metadata=NULL;
-    addMapToMap(&tmp->metadata,e->metadata);
-    if(e->format!=NULL)
-      tmp->format=zStrdup(e->format);
+    addMapToMap(&tmp->metadata,cursor->metadata);
+    tmp->additional_parameters=NULL;
+    addMapToMap(&tmp->additional_parameters,cursor->additional_parameters);
+    if(cursor->format!=NULL)
+      tmp->format=zStrdup(cursor->format);
     else
       tmp->format=NULL;
-    if(e->defaults!=NULL){
+    if(cursor->defaults!=NULL){
       tmp->defaults=(iotype*)malloc(IOTYPE_SIZE);
       tmp->defaults->content=NULL;
-      addMapToMap(&tmp->defaults->content,e->defaults->content);
+      addMapToMap(&tmp->defaults->content,cursor->defaults->content);
       tmp->defaults->next=NULL;
 #ifdef DEBUG
@@ -1169,11 +1255,11 @@
     }else
       tmp->defaults=NULL;
-    if(e->supported!=NULL){
+    if(cursor->supported!=NULL && cursor->supported->content!=NULL){
+      iotype *tmp2=cursor->supported->next;
       tmp->supported=(iotype*)malloc(IOTYPE_SIZE);
       tmp->supported->content=NULL;
-      addMapToMap(&tmp->supported->content,e->supported->content);
+      addMapToMap(&tmp->supported->content,cursor->supported->content);
       tmp->supported->next=NULL;
-      iotype *tmp2=e->supported->next;
-      while(tmp2!=NULL){
+            while(tmp2!=NULL){
 	addMapToIoType(&tmp->supported,tmp2->content);
 #ifdef DEBUG
@@ -1190,5 +1276,8 @@
     else
       tmp->child=NULL;
-    tmp->next=dupElements(cursor->next);
+    if(cursor->next!=NULL)
+      tmp->next=dupElements(cursor->next);
+    else
+      tmp->next=NULL;
   }
   return tmp;
@@ -1205,5 +1294,5 @@
   elements* tmp=e;
   if(*m==NULL){
-    *m=dupElements(tmp);
+    (*m)=dupElements(tmp);
   }else{
     addToElements(&(*m)->next,tmp);
@@ -1237,6 +1326,10 @@
     fprintf(stderr,"CONTENT MAP\n");
     dumpMap(s->content);
-    fprintf(stderr,"CONTENT METADATA\n");
+    if(s->metadata!=NULL)
+      fprintf(stderr,"CONTENT METADATA\n");
     dumpMap(s->metadata);
+    if(s->additional_parameters!=NULL)
+      fprintf(stderr,"CONTENT AdditionalParameters\n");
+    dumpMap(s->additional_parameters);
   }
   if(s->inputs!=NULL){
@@ -1296,4 +1389,6 @@
   res->metadata=NULL;
   addMapToMap(&res->metadata,s->metadata);
+  res->additional_parameters=NULL;
+  addMapToMap(&res->additional_parameters,s->additional_parameters);
   res->inputs=dupElements(s->inputs);
   res->outputs=dupElements(s->outputs);
@@ -1309,6 +1404,6 @@
   registry* p=r;
   while(p!=NULL){
+    services* s=p->content;
     fprintf(stderr,"%s \n",p->name);
-    services* s=p->content;
     s=p->content;
     while(s!=NULL){
@@ -1509,11 +1604,12 @@
  */
 void inheritance(registry *r,service** s){
+  service* ls=*s;
+  map *profile,*level;
   if(r==NULL)
     return;
-  service* ls=*s;
-  if(ls->content==NULL)
+  if(ls==NULL || ls->content==NULL)
     return;
-  map* profile=getMap(ls->content,"extend");
-  map* level=getMap(ls->content,"level");
+  profile=getMap(ls->content,"extend");
+  level=getMap(ls->content,"level");
   if(profile!=NULL&&level!=NULL){
     service* s1;
@@ -1550,4 +1646,5 @@
   memset(tmp,0,1024*10*10);
   while(tm!=NULL){
+    map* tc=tm->content;
     if(i>=10)
       break;
@@ -1556,5 +1653,4 @@
     strcpy(tmp[i][j],tm->name);
     j++;
-    map* tc=tm->content;
     while(tc!=NULL){
       if(j>=30)
@@ -1609,10 +1705,10 @@
  * @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 
+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
  *
@@ -1620,11 +1716,13 @@
  * @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
+ * @param kvp 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 );
+ *
+ * @note The map assigned to kvp is owned by the source maps
+ */
+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);
 }
 
@@ -1633,75 +1731,75 @@
  *
  * @param conf reference to configuration maps
- * @param service name of service 
+ * @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) );
+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 );
-	}	
+		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 );
+
+	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 );
+	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",
+		zGetpid(), 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);
 }
 
@@ -1710,23 +1808,3 @@
 // zooLog;
 // zooLogMsg(NULL, getLastErrorMessage()); 
-// zooLogMsg(log.txt, getLastErrorMessage()); 
-
-#ifdef WIN32
-#ifndef USE_MS
-char *strcasestr (char const *a, char const *b)
-  {
-    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
+// zooLogMsg("log.txt", getLastErrorMessage()); 
