Index: trunk/zoo-project/zoo-kernel/caching.c
===================================================================
--- trunk/zoo-project/zoo-kernel/caching.c	(revision 837)
+++ trunk/zoo-project/zoo-kernel/caching.c	(revision 917)
@@ -23,14 +23,14 @@
  */
 
+#include <openssl/md5.h>
+#include <openssl/evp.h>
 #include "caching.h"
 #include "service.h"
 #include "service_internal.h"
 #include "response_print.h"
-#include <openssl/md5.h>
-#include <openssl/hmac.h>
-#include <openssl/evp.h>
-#include <openssl/bio.h>
-#include <openssl/buffer.h>
-
+#ifdef MS_FORCE_LOCAL_FILE_USE
+#include "ogr_api.h"
+#include "mapserver.h"
+#endif
 /**
  * Compute md5
@@ -41,16 +41,16 @@
  */
 char* getMd5(char* url){
-  EVP_MD_CTX md5ctx;
+  EVP_MD_CTX *md5ctx=EVP_MD_CTX_create();
   char* fresult=(char*)malloc((EVP_MAX_MD_SIZE+1)*sizeof(char));
   unsigned char result[EVP_MAX_MD_SIZE];
   unsigned int len;
-  EVP_DigestInit(&md5ctx, EVP_md5());
-  EVP_DigestUpdate(&md5ctx, url, strlen(url));
-  EVP_DigestFinal_ex(&md5ctx,result,&len);
-  EVP_MD_CTX_cleanup(&md5ctx);
+  EVP_DigestInit(md5ctx, EVP_md5());
+  EVP_DigestUpdate(md5ctx, url, strlen(url));
+  EVP_DigestFinal_ex(md5ctx,result,&len);
+  EVP_MD_CTX_destroy(md5ctx);
   int i;
   for(i = 0; i < len; i++){
     if(i>0){
-      char *tmp=strdup(fresult);
+      char *tmp=zStrdup(fresult);
       sprintf(fresult,"%s%02x", tmp,result[i]);
       free(tmp);
@@ -62,4 +62,125 @@
 }
 
+/**
+ * Compute md5 of a file
+ * 
+ * @param file the char* 
+ * @return a char* representing the md5 of the url
+ * @warning make sure to free resources returned by this function
+ */
+char* getMd5f(char* file){
+  EVP_MD_CTX *md5ctx=EVP_MD_CTX_create();
+  char* fresult=(char*)malloc((EVP_MAX_MD_SIZE+1)*sizeof(char));
+  unsigned char result[EVP_MAX_MD_SIZE];
+  unsigned int len;
+  int bytes;
+  int dlen=65536;
+  unsigned char data[65537];
+  FILE *inFile = fopen (file, "rb");
+  EVP_DigestInit(md5ctx, EVP_md5());
+  while ((bytes = fread (data, sizeof(unsigned char), dlen, inFile)) != 0)
+    EVP_DigestUpdate(md5ctx, data, bytes);
+  EVP_DigestFinal_ex(md5ctx,result,&len);
+  EVP_MD_CTX_destroy(md5ctx);
+  int i;
+  for(i = 0; i < len; i++){
+    if(i>0){
+      char *tmp=zStrdup(fresult);
+      sprintf(fresult,"%s%02x", tmp,result[i]);
+      free(tmp);
+    }
+    else
+      sprintf(fresult,"%02x",result[i]);
+  }
+  fclose (inFile);
+  return fresult;
+}
+
+
+
+/**
+ * Create a URL by appending every request header listed in the security 
+ * section.This imply that the URL will contain any authentication 
+ * informations that should be fowarded to the server from which de input
+ * was download.
+ * @param conf the main configuration maps
+ * @param request the URL to transform.
+ * @return a char* that contain the original URL plus potential header (only for
+ * hosts that are not shared).
+ * @warning Be sure to free the memory returned by this function.
+ */
+char* getFilenameForRequest(maps* conf, const char* request){
+  map* passThrough=getMapFromMaps(conf,"security","attributes");
+  map* targetHosts=getMapFromMaps(conf,"security","hosts");
+  char* passedHeader[10];
+  int cnt=0;
+  char *res=zStrdup(request);
+  char *toAppend=NULL;
+  if(passThrough!=NULL && targetHosts!=NULL){
+    char *tmp=zStrdup(passThrough->value);
+    char *token, *saveptr;
+    token = strtok_r (tmp, ",", &saveptr);
+    int i;
+    if((strstr(targetHosts->value,"*")!=NULL || isProtectedHost(targetHosts->value,request)==1) && strncasecmp(getProvenance(conf,request),"SHARED",6)!=0){
+      while (token != NULL){
+	int length=strlen(token)+6;
+	char* tmp1=(char*)malloc(length*sizeof(char));
+	map* tmpMap;
+	snprintf(tmp1,6,"HTTP_");
+	int j;
+	for(j=0;token[j]!='\0';j++){
+	  if(token[j]!='-')
+	    tmp1[5+j]=toupper(token[j]);
+	  else
+	    tmp1[5+j]='_';
+	  tmp1[5+j+1]='\0';
+	}
+	tmpMap = getMapFromMaps(conf,"renv",tmp1);
+	if(tmpMap!=NULL){
+	  if(toAppend==NULL){
+	    toAppend=(char*)malloc((strlen(tmpMap->value)+1)*sizeof(char));
+	    sprintf(toAppend,"%s",tmpMap->value);
+	  }else{
+	    char *tmp3=zStrdup(toAppend);
+	    toAppend=(char*)realloc(toAppend,(strlen(tmpMap->value)+strlen(tmp3)+2)*sizeof(char));
+	    sprintf(toAppend,"%s,%s",tmp3,tmpMap->value);
+	    free(tmp3);
+	  }
+	}
+	free(tmp1);
+	cnt+=1;
+	token = strtok_r (NULL, ",", &saveptr);
+      }
+    }
+    free(tmp);
+  }
+  if(toAppend!=NULL){
+    char *tmp3=zStrdup(res);
+    res=(char*)realloc(res,(strlen(tmp3)+strlen(toAppend)+1)*sizeof(char));
+    sprintf(res,"%s%s",tmp3,toAppend);
+    free(tmp3);
+    free(toAppend);
+  }
+  return res;
+}
+
+/**
+ * Store MD5 of the content of a file
+ * @file char* the full path of the file
+ */
+int storeMd5(char* file){
+  char* storage=zStrdup(file);
+  char* md5fstr=getMd5f(file);
+  storage[strlen(storage)-2]='m';
+  storage[strlen(storage)-1]='d';
+  FILE* fo=fopen(storage,"w+");
+  if(fo==NULL)
+    return 1;
+  fwrite(md5fstr,sizeof(char),strlen(md5fstr),fo);
+  free(md5fstr);
+  free(storage);
+  fclose(fo);
+  return 0;
+}
 
 /**
@@ -76,43 +197,153 @@
  * @param max_path the size of the allocated filepath buffer  
  */
+void cacheFile(maps* conf,char* request,char* mimeType,int length,char* filename){
+  map* tmp=getMapFromMaps(conf,"main","cacheDir");
+  char contentr[4096];
+  int cred=0;
+  if(tmp!=NULL){
+    char* myRequest=getFilenameForRequest(conf,request);
+    char* md5str=getMd5(myRequest);
+    free(myRequest);
+    char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
+    // Store md5
+    char* md5fstr=getMd5f(filename);
+    sprintf(fname,"%s/%s.zmd",tmp->value,md5str);
+    FILE* fo=fopen(fname,"w+");
+#ifdef DEBUG
+    fprintf(stderr,"filename: %s\n",filename);
+    fprintf(stderr,"MD5: %s\n",md5fstr);
+#endif
+    fwrite(md5fstr,sizeof(char),strlen(md5fstr),fo);
+    free(md5fstr);
+    fclose(fo);
+    
+    sprintf(fname,"%s/%s.zca",tmp->value,md5str);
+    zooLock* lck=lockFile(conf,fname,'w');
+    if(lck!=NULL){
+#ifdef DEBUG
+      fprintf(stderr,"Cache list : %s\n",fname);
+      fflush(stderr);
+#endif
+      FILE* fi=fopen(filename,"rb");
+      sprintf(fname,"%s/%s.zca",tmp->value,md5str);
+      fo=fopen(fname,"w+");
+      if(fo==NULL){
+#ifdef DEBUG
+	fprintf (stderr, "Failed to open %s for writing: %s\n",fname, strerror(errno));
+#endif
+	unlockFile(conf,lck);
+	return;
+      }
+      if(fi==NULL){
+#ifdef DEBUG
+	fprintf (stderr, "Failed to open %s for reading: %s\n",filename, strerror(errno));
+#endif
+	unlockFile(conf,lck);
+	return;
+      }
+      memset(contentr,0,4096);
+      while((cred=fread(contentr,sizeof(char),4096,fi))>0){
+	fwrite(contentr,sizeof(char),cred,fo);
+	fflush(fo);
+	memset(contentr,0,4096);
+      }
+      unlockFile(conf,lck);
+      fclose(fo);
+      fclose(fi);
+
+      // Store mimeType
+      sprintf(fname,"%s/%s.zcm",tmp->value,md5str);
+      fo=fopen(fname,"w+");
+#ifdef DEBUG
+      fprintf(stderr,"MIMETYPE: %s\n",mimeType);
+#endif
+      fwrite(mimeType,sizeof(char),strlen(mimeType),fo);
+      fclose(fo);
+
+      // Store provenance
+      sprintf(fname,"%s/%s.zcp",tmp->value,md5str);
+      fo=fopen(fname,"w+");
+      char* origin=getProvenance(conf,request);
+#ifdef DEBUG
+      fprintf(stderr,"ORIGIN: %s\n",mimeType);
+#endif
+      fwrite(origin,sizeof(char),strlen(origin),fo);
+      fclose(fo);
+
+      free(md5str);
+
+    }
+    free(fname);
+  }
+}
+
+/**
+ * Cache a file for a given request.
+ * For each cached file, the are two files stored, a .zca and a .zcm containing
+ * the downloaded content and the mimeType respectively. 
+ *
+ * @param conf the maps containing the settings of the main.cfg file
+ * @param request the url used too fetch the content
+ * @param content the downloaded content
+ * @param mimeType the content mimeType 
+ * @param length the content size
+ * @param filepath a buffer for storing the path of the cached file; may be NULL
+ * @param max_path the size of the allocated filepath buffer  
+ */
 void addToCache(maps* conf,char* request,char* content,char* mimeType,int length, 
                 char* filepath, size_t max_path){
   map* tmp=getMapFromMaps(conf,"main","cacheDir");
   if(tmp!=NULL){
-    char* md5str=getMd5(request);
+    char* myRequest=getFilenameForRequest(conf,request);
+    char* md5str=getMd5(myRequest);
+    free(myRequest);
     char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
     sprintf(fname,"%s/%s.zca",tmp->value,md5str);
-#ifdef DEBUG
-    fprintf(stderr,"Cache list : %s\n",fname);
-    fflush(stderr);
-#endif
-    FILE* fo=fopen(fname,"w+");
-    if(fo==NULL){
-#ifdef DEBUG
-      fprintf (stderr, "Failed to open %s for writing: %s\n",fname, strerror(errno));
-#endif
-      filepath = NULL;	
-      return;
-    }
-    fwrite(content,sizeof(char),length,fo);
-    fclose(fo);
+    zooLock* lck=lockFile(conf,fname,'w');
+    if(lck!=NULL){
+#ifdef DEBUG
+      fprintf(stderr,"Cache list : %s\n",fname);
+      fflush(stderr);
+#endif
+      FILE* fo=fopen(fname,"w+");
+      if(fo==NULL){
+#ifdef DEBUG
+	fprintf (stderr, "Failed to open %s for writing: %s\n",fname, strerror(errno));
+#endif
+	filepath = NULL;
+	unlockFile(conf,lck);
+	return;
+      }
+      fwrite(content,sizeof(char),length,fo);
+      unlockFile(conf,lck);
+      fclose(fo);
 	
-	if (filepath != NULL) {
-		strncpy(filepath, fname, max_path);
-	}	
-
-    sprintf(fname,"%s/%s.zcm",tmp->value,md5str);
-    fo=fopen(fname,"w+");
-#ifdef DEBUG
-    fprintf(stderr,"MIMETYPE: %s\n",mimeType);
-#endif
-    fwrite(mimeType,sizeof(char),strlen(mimeType),fo);
-    fclose(fo);
-
-    free(md5str);
-    free(fname);
+      if (filepath != NULL) {
+	strncpy(filepath, fname, max_path);
+      }
+
+      sprintf(fname,"%s/%s.zcm",tmp->value,md5str);
+      fo=fopen(fname,"w+");
+#ifdef DEBUG
+      fprintf(stderr,"MIMETYPE: %s\n",mimeType);
+#endif
+      fwrite(mimeType,sizeof(char),strlen(mimeType),fo);
+      fclose(fo);
+
+      sprintf(fname,"%s/%s.zcp",tmp->value,md5str);
+      fo=fopen(fname,"w+");
+      char* origin=getProvenance(conf,request);
+#ifdef DEBUG
+      fprintf(stderr,"ORIGIN: %s\n",mimeType);
+#endif
+      fwrite(origin,sizeof(char),strlen(origin),fo);
+      fclose(fo);
+
+      free(md5str);
+      free(fname);
+    }
   }
   else {
-	  filepath = NULL;
+    filepath = NULL;
   }	  
 }
@@ -127,7 +358,56 @@
  */
 char* isInCache(maps* conf,char* request){
+  map* tmpUrl=getMapFromMaps(conf,"main","tmpUrl");
   map* tmpM=getMapFromMaps(conf,"main","cacheDir");
-  if(tmpM!=NULL){
-    char* md5str=getMd5(request);
+  if(tmpM==NULL)
+    tmpM=getMapFromMaps(conf,"main","tmpPath");
+  if(strstr(request,tmpUrl->value)!=NULL){
+    map* tmpPath=getMapFromMaps(conf,"main","tmpPath");
+    char* tmpStr=strstr(request,tmpUrl->value);
+    char* tmpStr1=zStrdup(tmpStr+strlen(tmpUrl->value));
+    char* res=(char*) malloc((strlen(tmpPath->value)+strlen(tmpStr1)+2)*sizeof(char));
+    sprintf(res,"%s/%s",tmpPath->value,tmpStr1);
+    free(tmpStr1);
+    return res;
+  }
+#ifdef MS_FORCE_LOCAL_FILE_USE
+  map* msUrl=getMapFromMaps(conf,"main","mapserverAddress");
+  if(msUrl!=NULL && strstr(request,msUrl->value)!=NULL){
+    char *tmpStr=strstr(request,"?");
+    char *cursor=zStrdup(tmpStr+1);
+    char *token, *saveptr;
+    token = strtok_r (cursor, "&", &saveptr);
+    while(token!=NULL){
+      char *token1, *saveptr1;
+      token1 = strtok_r (token, "=", &saveptr1);
+      char *name=NULL;
+      while(token1!=NULL){
+	if(name==NULL)
+	  name=zStrdup(token1);
+	else
+	  if(strcasecmp(name,"map")==0){
+	    mapObj *myMap=msLoadMap(token1,NULL);
+	    char * res=zStrdup(myMap->layers[0]->data);
+	    free(name);
+	    free(cursor);
+	    msFreeMap(myMap);
+	    return res;
+	  }
+	token1 = strtok_r (NULL, "=", &saveptr1);
+      }
+      token = strtok_r (NULL, "&", &saveptr);
+    }
+    free(cursor);
+  }
+#endif  
+  if(strncasecmp(request,"file://",7)==0){
+    char* tmpStr=zStrdup(request+7);
+    fprintf(stderr,"**** %s %d %s \n",__FILE__,__LINE__,tmpStr);
+    return tmpStr;
+  }
+  else{
+    char* myRequest=getFilenameForRequest(conf,request);
+    char* md5str=getMd5(myRequest);
+    free(myRequest);
 #ifdef DEBUG
     fprintf(stderr,"MD5STR : (%s)\n\n",md5str);
@@ -135,6 +415,6 @@
     char* fname=(char*)malloc(sizeof(char)*(strlen(tmpM->value)+strlen(md5str)+6));
     sprintf(fname,"%s/%s.zca",tmpM->value,md5str);
-    struct stat f_status;
-    int s=stat(fname, &f_status);
+    zStatStruct f_status;
+    int s=zStat(fname, &f_status);
     if(s==0 && f_status.st_size>0){
       free(md5str);
@@ -158,9 +438,11 @@
  */
 int readCurrentInput(maps** m,maps** in,int* index,HINTERNET* hInternet,map** error){
+  
+  int shouldClean=-1;
   map* tmp1;
   char sindex[5];
   maps* content=*in;
   map* length=getMap(content->content,"length");
-  int shouldClean=-1;
+  map* memUse=getMapFromMaps(*m,"main","memory");
   if(length==NULL){
     length=createMap("length","1");
@@ -171,4 +453,5 @@
     char *mimeType=NULL;
     int fsize=0;
+    char oriname[12];
     char cname[15];
     char vname[11];
@@ -178,5 +461,8 @@
     char icname[14];
     char xname[16];
+    char bname[8];
+    char hname[11];
     char oname[12];
+    char ufile[12];    
     if(*index>0)
       sprintf(vname1,"value_%d",*index);
@@ -185,6 +471,7 @@
     
     if(i>0){
+      sprintf(cname,"cache_file_%d",i);
       tmp1=getMap(content->content,cname);
-      sprintf(cname,"cache_file_%d",i);
+      sprintf(oriname,"origin_%d",i);
       sprintf(vname,"value_%d",i);
       sprintf(sname,"size_%d",i);
@@ -192,7 +479,11 @@
       sprintf(icname,"isCached_%d",i);
       sprintf(xname,"Reference_%d",i);
+      sprintf(bname,"body_%d",i);
+      sprintf(hname,"headers_%d",i);
       sprintf(oname,"Order_%d",i);
+      sprintf(ufile,"use_file_%d",i);
     }else{
       sprintf(cname,"cache_file");
+      sprintf(oriname,"origin");
       sprintf(vname,"value");
       sprintf(sname,"size");
@@ -200,5 +491,8 @@
       sprintf(icname,"isCached");
       sprintf(xname,"Reference");
+      sprintf(bname,"body");
+      sprintf(hname,"headers");
       sprintf(oname,"Order");
+      sprintf(ufile,"use_file");
     }
     
@@ -206,17 +500,19 @@
     sprintf(sindex,"%d",*index+1);
     if((tmp1=getMap(content->content,xname))!=NULL && tmap!=NULL && strcasecmp(tmap->value,sindex)==0){
-      
-      if(getMap(content->content,icname)==NULL){
-	fcontent=(char*)malloc((hInternet->ihandle[*index].nDataLen+1)*sizeof(char));
-	if(fcontent == NULL){
-	  errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
-	  return -1;
+
+      if(getMap(content->content,icname)==NULL) {
+	if(memUse==NULL || strcasecmp(memUse->value,"load")==0){
+	  fcontent=(char*)malloc((hInternet->ihandle[*index].nDataLen+1)*sizeof(char));
+	  if(fcontent == NULL){
+	    errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
+	    return -1;
+	  }
+	  size_t dwRead;
+	  InternetReadFile(hInternet->ihandle[*index], 
+			   (LPVOID)fcontent, 
+			   hInternet->ihandle[*index].nDataLen, 
+			   &dwRead);
+	  fcontent[hInternet->ihandle[*index].nDataLen]=0;
 	}
-	size_t dwRead;
-	InternetReadFile(hInternet->ihandle[*index], 
-			 (LPVOID)fcontent, 
-			 hInternet->ihandle[*index].nDataLen, 
-			 &dwRead);
-	fcontent[hInternet->ihandle[*index].nDataLen]=0;
 	fsize=hInternet->ihandle[*index].nDataLen;
 	if(hInternet->ihandle[*index].mimeType==NULL)
@@ -226,10 +522,13 @@
 	
 	map* tmpMap=getMapOrFill(&(*in)->content,vname,"");
-	free(tmpMap->value);
-	tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
-	if(tmpMap->value==NULL){
-	  return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
-	}
-	memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
+	if(memUse==NULL || strcasecmp(memUse->value,"load")==0){
+	  free(tmpMap->value);
+	  tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
+	  if(tmpMap->value==NULL){
+	    return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
+	  }
+	  memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
+	}else
+	  addToMap((*in)->content,ufile,"true");
 	if(hInternet->ihandle[*index].code!=200){
 	  const char *error_rep_str=_("Unable to download the file for the input <%s>, response code was : %d.");
@@ -255,6 +554,27 @@
 	sprintf(ltmp1,"%d",fsize);
 	map* tmp=getMapFromMaps(*m,"main","cacheDir");
+	char *request=NULL;
 	if(tmp!=NULL){
-	  char* md5str=getMd5(tmp1->value);
+	  map* tmp2;
+	  char* md5str=NULL;
+	  if((tmp2=getMap(content->content,bname))!=NULL){
+	    char *tmpStr=(char*)malloc((strlen(tmp1->value)+strlen(tmp2->value)+1)*sizeof(char));
+	    sprintf(tmpStr,"%s%s",tmp1->value,tmp2->value);
+	    if((tmp2=getMap(content->content,"headers"))!=NULL){
+	      char *tmpStr2=zStrdup(tmpStr);
+	      free(tmpStr);
+	      tmpStr=(char*)malloc((strlen(tmpStr2)+strlen(tmp2->value)+1)*sizeof(char));
+	      sprintf(tmpStr,"%s%s",tmpStr2,tmp2->value);
+	      free(tmpStr2);
+	    }
+	    md5str=getMd5(tmpStr);
+	    request=zStrdup(tmpStr);
+	    free(tmpStr);
+	  }else{
+	    char *myRequest=getFilenameForRequest(*m,tmp1->value);
+	    md5str=getMd5(myRequest);
+	    request=zStrdup(tmp1->value);
+	    free(myRequest);
+	  }
 	  char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
 	  sprintf(fname,"%s/%s.zca",tmp->value,md5str);
@@ -264,9 +584,16 @@
 	addToMap((*in)->content,sname,ltmp1);
 	addToMap((*in)->content,mname,mimeType);
-	addToCache(*m,tmp1->value,fcontent,mimeType,fsize, NULL, 0);
-	free(fcontent);
+	char* origin=getProvenance(*m,request);
+	addToMap((*in)->content,oriname,origin);
+	if(memUse==NULL || strcasecmp(memUse->value,"load")==0){
+	  addToCache(*m,request,fcontent,mimeType,fsize, NULL, 0);
+	  free(fcontent);
+	}else{
+	  addToMap((*in)->content,ufile,"true");
+	  cacheFile(*m,request,mimeType,fsize,hInternet->ihandle[*index].filename);
+	}
 	free(mimeType);
-	*index++;
-	
+	free(request);
+	(*index)++;
       }
     }
@@ -324,7 +651,7 @@
  */
 void addRequestToQueue(maps** m,HINTERNET* hInternet,const char* url,bool req){
-  hInternet->waitingRequests[hInternet->nb]=strdup(url);
+  hInternet->waitingRequests[hInternet->nb]=zStrdup(url);
   if(req)
-    InternetOpenUrl(hInternet,hInternet->waitingRequests[hInternet->nb],NULL,0,INTERNET_FLAG_NO_CACHE_WRITE,0);
+    InternetOpenUrl(hInternet,hInternet->waitingRequests[hInternet->nb],NULL,0,INTERNET_FLAG_NO_CACHE_WRITE,0,*m);
   maps *oreq=getMaps(*m,"orequests");
   if(oreq==NULL){
@@ -335,5 +662,5 @@
     free(oreq);
   }else{
-    setMapArray(oreq->content,"value",hInternet->nb-1,url);
+    setMapArray(oreq->content,"value",hInternet->nb,url);
   }
 }
@@ -352,5 +679,7 @@
   char* cached=isInCache(*m,url);
   char *mimeType=NULL;
-  int fsize=0;
+  char *origin=NULL;
+  long long fsize=0;
+  map* memUse=getMapFromMaps(*m,"main","memory");
 
   map* t=getMap(*content,"xlink:href");
@@ -361,19 +690,29 @@
 
   if(cached!=NULL){
-
-    struct stat f_status;
-    int s=stat(cached, &f_status);
+    zStatStruct f_status;
+    int s=zStat(cached, &f_status);
     if(s==0){
-      fcontent=(char*)malloc(sizeof(char)*(f_status.st_size+1));
-      FILE* f=fopen(cached,"rb");
-      fread(fcontent,f_status.st_size,1,f);
+      zooLock* lck=lockFile(*m,cached,'r');
+      if(lck==NULL)
+	return -1;
       fsize=f_status.st_size;
-      fcontent[fsize]=0;
-      fclose(f);
+      if(memUse==NULL || strcasecmp(memUse->value,"load")==0){
+	fcontent=(char*)malloc(sizeof(char)*(f_status.st_size+1));
+	FILE* f=fopen(cached,"rb");
+	if(f!=NULL){
+	  fread(fcontent,f_status.st_size,1,f);
+	  fcontent[fsize]=0;
+	  fclose(f);
+	}
+      }
       addToMap(*content,"cache_file",cached);
+      unlockFile(*m,lck);
     }
     cached[strlen(cached)-1]='m';
-    s=stat(cached, &f_status);
+    s=zStat(cached, &f_status);
     if(s==0){
+      zooLock* lck=lockFile(*m,cached,'r');
+      if(lck==NULL)
+	return -1;
       mimeType=(char*)malloc(sizeof(char)*(f_status.st_size+1));
       FILE* f=fopen(cached,"rb");
@@ -381,6 +720,19 @@
       mimeType[f_status.st_size]=0;
       fclose(f);
-    }
-
+      unlockFile(*m,lck);
+    }
+    cached[strlen(cached)-1]='p';
+    s=zStat(cached, &f_status);
+    if(s==0){
+      zooLock* lck=lockFile(*m,cached,'r');
+      if(lck==NULL)
+	return -1;
+      origin=(char*)malloc(sizeof(char)*(f_status.st_size+1));
+      FILE* f=fopen(cached,"rb");
+      fread(origin,f_status.st_size,1,f);
+      mimeType[f_status.st_size]=0;
+      fclose(f);
+      unlockFile(*m,lck);
+    }
   }else{    
     addRequestToQueue(m,hInternet,url,true);
@@ -393,34 +745,50 @@
     addToMap(*content,"fmimeType",mimeType);
   }
+  if(origin!=NULL){
+    addToMap(*content,"origin",origin);
+  }
 
   map* tmpMap=getMapOrFill(content,"value","");
-    
-  free(tmpMap->value);
-  tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
-  if(tmpMap->value==NULL || fcontent == NULL)
-    return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
-  memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
-
+  if(memUse==NULL || strcasecmp(memUse->value,"load")==0){
+    free(tmpMap->value);
+    tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
+    if(tmpMap->value==NULL || fcontent == NULL)
+      return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
+    memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
+  }
+  
   char ltmp1[256];
-  sprintf(ltmp1,"%d",fsize);
+  sprintf(ltmp1,"%ld",fsize);
   addToMap(*content,"size",ltmp1);
   if(cached==NULL){
-    addToCache(*m,url,fcontent,mimeType,fsize, NULL, 0);
+    if(memUse==NULL || strcasecmp(memUse->value,"load")==0)
+      addToCache(*m,url,fcontent,mimeType,fsize, NULL, 0);
+    else
+      cacheFile(*m,url,mimeType,fsize,hInternet->ihandle[hInternet->nb-1].filename);
   }
   else{
     addToMap(*content,"isCached","true");
     map* tmp=getMapFromMaps(*m,"main","cacheDir");
-    if(tmp!=NULL){
+    map* tmp1=getMap((*content),"cache_file");
+    if(tmp!=NULL && tmp1==NULL){
       map *c=getMap((*content),"xlink:href");
-      char* md5str=getMd5(c->value);
-      char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
-      sprintf(fname,"%s/%s.zca",tmp->value,md5str);
-      addToMap(*content,"cache_file",fname);
-      free(fname);
-    }
-  }
-  free(fcontent);
-  free(mimeType);
-  free(cached);
+      if(strncasecmp(c->value,"file://",7)!=0){
+	char *myRequest=getFilenameForRequest(*m,c->value);
+	char* md5str=getMd5(myRequest);
+	free(myRequest);
+	char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
+	sprintf(fname,"%s/%s.zca",tmp->value,md5str);
+	addToMap(*content,"cache_file",fname);
+	free(fname);
+	free(md5str);
+      }
+    }
+  }
+  if(fcontent!=NULL)
+    free(fcontent);
+  if(mimeType!=NULL)
+    free(mimeType);
+  if(cached!=NULL)
+    free(cached);
   return 0;
 }
