source: branches/prototype-v0/zoo-project/zoo-kernel/caching.c @ 854

Last change on this file since 854 was 854, checked in by djay, 6 years ago

HPC support update. Add inputs for create options in Gdal_Dem.

  • Property svn:keywords set to Id
File size: 16.4 KB
RevLine 
[642]1/*
2 * Author : Gérald Fenoy
3 *
4 *  Copyright 2008-2015 GeoLabs SARL. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#include "caching.h"
26#include "service.h"
27#include "service_internal.h"
28#include "response_print.h"
29#include <openssl/md5.h>
30#include <openssl/hmac.h>
31#include <openssl/evp.h>
32#include <openssl/bio.h>
33#include <openssl/buffer.h>
34
35/**
36 * Compute md5
37 *
38 * @param url the char*
39 * @return a char* representing the md5 of the url
[781]40 * @warning make sure to free resources returned by this function
[642]41 */
42char* getMd5(char* url){
43  EVP_MD_CTX md5ctx;
44  char* fresult=(char*)malloc((EVP_MAX_MD_SIZE+1)*sizeof(char));
45  unsigned char result[EVP_MAX_MD_SIZE];
46  unsigned int len;
47  EVP_DigestInit(&md5ctx, EVP_md5());
48  EVP_DigestUpdate(&md5ctx, url, strlen(url));
49  EVP_DigestFinal_ex(&md5ctx,result,&len);
50  EVP_MD_CTX_cleanup(&md5ctx);
51  int i;
52  for(i = 0; i < len; i++){
53    if(i>0){
54      char *tmp=strdup(fresult);
55      sprintf(fresult,"%s%02x", tmp,result[i]);
56      free(tmp);
57    }
58    else
59      sprintf(fresult,"%02x",result[i]);
60  }
61  return fresult;
62}
63
64
65/**
[854]66 * Create a URL by appending every request header listed in the security
67 * section.This imply that the URL will contain any authentication
68 * informations that should be fowarded to the server from which de input
69 * was download.
70 * @param conf the main configuration maps
71 * @param request the URL to transform.
72 * @return a char* that contain the original URL plus potential header (only for
73 * hosts that are not shared).
74 * @warning Be sure to free the memory returned by this function.
75 */
76char* getFilenameForRequest(maps* conf, const char* request){
77  map* passThrough=getMapFromMaps(conf,"security","attributes");
78  map* targetHosts=getMapFromMaps(conf,"security","hosts");
79  char* passedHeader[10];
80  int cnt=0;
81  char *res=zStrdup(request);
82  char *toAppend=NULL;
83  if(passThrough!=NULL && targetHosts!=NULL){
84    char *tmp=zStrdup(passThrough->value);
85    char *token, *saveptr;
86    token = strtok_r (tmp, ",", &saveptr);
87    int i;
88    if((strstr(targetHosts->value,"*")!=NULL || isProtectedHost(targetHosts->value,request)==1) && strncasecmp(getProvenance(conf,request),"SHARED",6)!=0){
89      while (token != NULL){
90        int length=strlen(token)+6;
91        char* tmp1=(char*)malloc(length*sizeof(char));
92        map* tmpMap;
93        snprintf(tmp1,6,"HTTP_");
94        int j;
95        for(j=0;token[j]!='\0';j++){
96          if(token[j]!='-')
97            tmp1[5+j]=toupper(token[j]);
98          else
99            tmp1[5+j]='_';
100          tmp1[5+j+1]='\0';
101        }
102        tmpMap = getMapFromMaps(conf,"renv",tmp1);
103        if(tmpMap!=NULL){
104          if(toAppend==NULL){
105            toAppend=(char*)malloc((strlen(tmpMap->value)+1)*sizeof(char));
106            sprintf(toAppend,"%s",tmpMap->value);
107          }else{
108            char *tmp3=zStrdup(toAppend);
109            toAppend=(char*)realloc(toAppend,(strlen(tmpMap->value)+strlen(tmp3)+2)*sizeof(char));
110            sprintf(toAppend,"%s,%s",tmp3,tmpMap->value);
111            free(tmp3);
112          }
113        }
114        free(tmp1);
115        cnt+=1;
116        token = strtok_r (NULL, ",", &saveptr);
117      }
118    }
119    free(tmp);
120  }
121  if(toAppend!=NULL){
122    char *tmp3=zStrdup(res);
123    res=(char*)realloc(res,(strlen(tmp3)+strlen(toAppend)+1)*sizeof(char));
124    sprintf(res,"%s%s",tmp3,toAppend);
125    free(tmp3);
126    free(toAppend);
127  }
128  return res;
129}
130
131/**
[642]132 * Cache a file for a given request.
133 * For each cached file, the are two files stored, a .zca and a .zcm containing
134 * the downloaded content and the mimeType respectively.
135 *
136 * @param conf the maps containing the settings of the main.cfg file
137 * @param request the url used too fetch the content
138 * @param content the downloaded content
139 * @param mimeType the content mimeType
140 * @param length the content size
141 * @param filepath a buffer for storing the path of the cached file; may be NULL
142 * @param max_path the size of the allocated filepath buffer 
143 */
144void addToCache(maps* conf,char* request,char* content,char* mimeType,int length, 
145                char* filepath, size_t max_path){
146  map* tmp=getMapFromMaps(conf,"main","cacheDir");
147  if(tmp!=NULL){
[854]148    char* myRequest=getFilenameForRequest(conf,request);
149    char* md5str=getMd5(myRequest);
150    free(myRequest);
[642]151    char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
152    sprintf(fname,"%s/%s.zca",tmp->value,md5str);
[854]153    zooLock* lck=lockFile(conf,fname,'w');
154    if(lck!=NULL){
[642]155#ifdef DEBUG
[854]156      fprintf(stderr,"Cache list : %s\n",fname);
157      fflush(stderr);
[642]158#endif
[854]159      FILE* fo=fopen(fname,"w+");
160      if(fo==NULL){
[642]161#ifdef DEBUG
[854]162        fprintf (stderr, "Failed to open %s for writing: %s\n",fname, strerror(errno));
[642]163#endif
[854]164        filepath = NULL;
165        unlockFile(conf,lck);
166        return;
167      }
168      fwrite(content,sizeof(char),length,fo);
169      unlockFile(conf,lck);
170      fclose(fo);
[642]171       
[854]172      if (filepath != NULL) {
173        strncpy(filepath, fname, max_path);
174      }
[642]175
[854]176      sprintf(fname,"%s/%s.zcm",tmp->value,md5str);
177      fo=fopen(fname,"w+");
[642]178#ifdef DEBUG
[854]179      fprintf(stderr,"MIMETYPE: %s\n",mimeType);
[642]180#endif
[854]181      fwrite(mimeType,sizeof(char),strlen(mimeType),fo);
182      fclose(fo);
[642]183
[854]184      sprintf(fname,"%s/%s.zcp",tmp->value,md5str);
185      fo=fopen(fname,"w+");
186      char* origin=getProvenance(conf,request);
187#ifdef DEBUG
188      fprintf(stderr,"ORIGIN: %s\n",mimeType);
189#endif
190      fwrite(origin,sizeof(char),strlen(origin),fo);
191      fclose(fo);
192
193      free(md5str);
194      free(fname);
195    }
[642]196  }
197  else {
[854]198    filepath = NULL;
[642]199  }       
200}
201
202/**
203 * Verify if a url is available in the cache
204 *
205 * @param conf the maps containing the settings of the main.cfg file
206 * @param request the url
207 * @return the full name of the cached file if any, NULL in other case
[781]208 * @warning make sure to free resources returned by this function (if not NULL)
[642]209 */
210char* isInCache(maps* conf,char* request){
211  map* tmpM=getMapFromMaps(conf,"main","cacheDir");
212  if(tmpM!=NULL){
[854]213    char* myRequest=getFilenameForRequest(conf,request);
214    char* md5str=getMd5(myRequest);
215    free(myRequest);
[642]216#ifdef DEBUG
217    fprintf(stderr,"MD5STR : (%s)\n\n",md5str);
218#endif
219    char* fname=(char*)malloc(sizeof(char)*(strlen(tmpM->value)+strlen(md5str)+6));
220    sprintf(fname,"%s/%s.zca",tmpM->value,md5str);
221    struct stat f_status;
222    int s=stat(fname, &f_status);
223    if(s==0 && f_status.st_size>0){
224      free(md5str);
225      return fname;
226    }
227    free(md5str);
228    free(fname);
229  }
230  return NULL;
231}
232
233/**
[790]234 * Read the downloaded file for a specific input
235 *
236 * @param m the maps containing the settings of the main.cfg file
237 * @param in the input
238 * @param index the input index
239 * @param hInternet the internet connection
[797]240 * @param error the error map pointer
241 * @return 0 in case of success, -1 in case of failure
[790]242 */
[797]243int readCurrentInput(maps** m,maps** in,int* index,HINTERNET* hInternet,map** error){
[839]244 
[790]245  map* tmp1;
246  char sindex[5];
247  maps* content=*in;
248  map* length=getMap(content->content,"length");
249  int shouldClean=-1;
250  if(length==NULL){
251    length=createMap("length","1");
252    shouldClean=1;
253  }
254  for(int i=0;i<atoi(length->value);i++){
255    char* fcontent;
256    char *mimeType=NULL;
257    int fsize=0;
258    char cname[15];
259    char vname[11];
260    char vname1[11];
261    char sname[9];
262    char mname[15];
263    char icname[14];
264    char xname[16];
[822]265    char bname[8];
266    char hname[11];
[790]267    char oname[12];
268    if(*index>0)
269      sprintf(vname1,"value_%d",*index);
270    else
271      sprintf(vname1,"value");
272   
273    if(i>0){
274      tmp1=getMap(content->content,cname);
275      sprintf(cname,"cache_file_%d",i);
276      sprintf(vname,"value_%d",i);
277      sprintf(sname,"size_%d",i);
278      sprintf(mname,"mimeType_%d",i);
279      sprintf(icname,"isCached_%d",i);
280      sprintf(xname,"Reference_%d",i);
[822]281      sprintf(bname,"body_%d",i);
282      sprintf(hname,"headers_%d",i);
[790]283      sprintf(oname,"Order_%d",i);
284    }else{
285      sprintf(cname,"cache_file");
286      sprintf(vname,"value");
287      sprintf(sname,"size");
288      sprintf(mname,"mimeType");
289      sprintf(icname,"isCached");
290      sprintf(xname,"Reference");
[822]291      sprintf(bname,"body");
[854]292      sprintf(hname,"headers");
[790]293      sprintf(oname,"Order");
294    }
295   
296    map* tmap=getMap(content->content,oname);
297    sprintf(sindex,"%d",*index+1);
298    if((tmp1=getMap(content->content,xname))!=NULL && tmap!=NULL && strcasecmp(tmap->value,sindex)==0){
[839]299
300      if(getMap(content->content,icname)==NULL){       
[790]301        fcontent=(char*)malloc((hInternet->ihandle[*index].nDataLen+1)*sizeof(char));
302        if(fcontent == NULL){
[797]303          errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
304          return -1;
[790]305        }
306        size_t dwRead;
307        InternetReadFile(hInternet->ihandle[*index], 
308                         (LPVOID)fcontent, 
309                         hInternet->ihandle[*index].nDataLen, 
310                         &dwRead);
311        fcontent[hInternet->ihandle[*index].nDataLen]=0;
312        fsize=hInternet->ihandle[*index].nDataLen;
313        if(hInternet->ihandle[*index].mimeType==NULL)
314          mimeType=zStrdup("none");
315        else
316          mimeType=zStrdup(hInternet->ihandle[*index].mimeType);             
317       
318        map* tmpMap=getMapOrFill(&(*in)->content,vname,"");
319        free(tmpMap->value);
320        tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
321        if(tmpMap->value==NULL){
322          return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
323        }
324        memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
[797]325        if(hInternet->ihandle[*index].code!=200){
326          char *error_rep_str=_("Unable to download the file for the input <%s>, response code was : %d.");
327          char *error_msg=(char*)malloc((strlen(error_rep_str)+strlen(content->name)+4)*sizeof(char));
328          sprintf(error_msg,error_rep_str,content->name,hInternet->ihandle[*index].code);
329          if(*error==NULL){
330            *error=createMap("text",error_msg);
331            addToMap(*error,"locator",content->name);
332            addToMap(*error,"code","InvalidParameterValue");
333          }else{
334            int nb=1;
335            map* tmpMap=getMap(*error,"length");
336            if(tmpMap!=NULL)
337              nb=atoi(tmpMap->value);
338            setMapArray(*error,"text",nb,error_msg);
339            setMapArray(*error,"locator",nb,content->name);
340            setMapArray(*error,"code",nb,"InvalidParameterValue");
341          }
342          return -1;
343        }
[790]344       
345        char ltmp1[256];
346        sprintf(ltmp1,"%d",fsize);
347        map* tmp=getMapFromMaps(*m,"main","cacheDir");
[822]348        char *request=NULL;
[790]349        if(tmp!=NULL){
[822]350          map* tmp2;
351          char* md5str=NULL;
352          if((tmp2=getMap(content->content,bname))!=NULL){
353            char *tmpStr=(char*)malloc((strlen(tmp1->value)+strlen(tmp2->value)+1)*sizeof(char));
354            sprintf(tmpStr,"%s%s",tmp1->value,tmp2->value);
355            if((tmp2=getMap(content->content,"headers"))!=NULL){
356              char *tmpStr2=zStrdup(tmpStr);
[839]357              free(tmpStr);
[822]358              tmpStr=(char*)malloc((strlen(tmpStr2)+strlen(tmp2->value)+1)*sizeof(char));
359              sprintf(tmpStr,"%s%s",tmpStr2,tmp2->value);
360              free(tmpStr2);
361            }
362            md5str=getMd5(tmpStr);
363            request=zStrdup(tmpStr);
364            free(tmpStr);
365          }else{
[854]366            char *myRequest=getFilenameForRequest(*m,tmp1->value);
367            md5str=getMd5(myRequest);
[822]368            request=zStrdup(tmp1->value);
[854]369            free(myRequest);
[822]370          }
[790]371          char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
372          sprintf(fname,"%s/%s.zca",tmp->value,md5str);
373          addToMap((*in)->content,cname,fname);
374          free(fname);
375        }
376        addToMap((*in)->content,sname,ltmp1);
377        addToMap((*in)->content,mname,mimeType);
[822]378        addToCache(*m,request,fcontent,mimeType,fsize, NULL, 0);
[790]379        free(fcontent);
380        free(mimeType);
[822]381        free(request);
[839]382        (*index)++;
[790]383      }
384    }
385  }
386  if(shouldClean>0){
387    freeMap(&length);
388    free(length);
389  }
390  return 0;
391}
392
393/**
[642]394 * Effectively run all the HTTP requests in the queue
395 *
396 * @param m the maps containing the settings of the main.cfg file
397 * @param inputs the maps containing the inputs (defined in the requests+added
398 *  per default based on the zcfg file)
399 * @param hInternet the HINTERNET pointer
[797]400 * @param error the error map pointer
401 * @return 0 on success, -1 on failure
[642]402 */
[797]403int runHttpRequests(maps** m,maps** inputs,HINTERNET* hInternet,map** error){
404  int hasAFailure=0;
[790]405  if(hInternet!=NULL && hInternet->nb>0){
[817]406    AddHeaderEntries(hInternet,*m);
[642]407    processDownloads(hInternet);
408    maps* content=*inputs;
409    int index=0;
410    while(content!=NULL){
[790]411      if(content->child!=NULL){
412        maps* cursor=content->child;
413        while(cursor!=NULL){
[797]414          int red=readCurrentInput(m,&cursor,&index,hInternet,error);
415          if(red<0)
416            hasAFailure=red;
[790]417          cursor=cursor->next;
[642]418        }
419      }
[797]420      else{
421        int red=readCurrentInput(m,&content,&index,hInternet,error);
422        if(red<0)
423          hasAFailure=red;
424      }
[642]425      content=content->next;
[797]426    }
[642]427  }
[797]428  return hasAFailure;
[642]429}
430
431/**
432 * Add a request in the download queue
433 *
434 * @param m the maps containing the settings of the main.cfg file
435 * @param url the url to add to the queue
436 */
437void addRequestToQueue(maps** m,HINTERNET* hInternet,const char* url,bool req){
438  hInternet->waitingRequests[hInternet->nb]=strdup(url);
439  if(req)
440    InternetOpenUrl(hInternet,hInternet->waitingRequests[hInternet->nb],NULL,0,INTERNET_FLAG_NO_CACHE_WRITE,0);
441  maps *oreq=getMaps(*m,"orequests");
442  if(oreq==NULL){
[790]443    oreq=createMaps("orequests");
[642]444    oreq->content=createMap("value",url);
445    addMapsToMaps(m,oreq);
446    freeMaps(&oreq);
447    free(oreq);
448  }else{
[839]449    setMapArray(oreq->content,"value",hInternet->nb,url);
[642]450  }
451}
452
453/**
454 * Try to load file from cache or download a remote file if not in cache
455 *
456 * @param m the maps containing the settings of the main.cfg file
457 * @param content the map to update
458 * @param hInternet the HINTERNET pointer
459 * @param url the url to fetch
460 * @return 0
461 */
462int loadRemoteFile(maps** m,map** content,HINTERNET* hInternet,char *url){
[738]463  char* fcontent = NULL;
[642]464  char* cached=isInCache(*m,url);
465  char *mimeType=NULL;
466  int fsize=0;
467
468  map* t=getMap(*content,"xlink:href");
469  if(t==NULL){
470    t=getMap((*content),"href");
471    addToMap(*content,"xlink:href",url);
472  }
473
474  if(cached!=NULL){
475    struct stat f_status;
476    int s=stat(cached, &f_status);
477    if(s==0){
[854]478      zooLock* lck=lockFile(*m,cached,'r');
479      if(lck==NULL)
480        return -1;
[642]481      fcontent=(char*)malloc(sizeof(char)*(f_status.st_size+1));
482      FILE* f=fopen(cached,"rb");
483      fread(fcontent,f_status.st_size,1,f);
484      fsize=f_status.st_size;
485      fcontent[fsize]=0;
486      fclose(f);
487      addToMap(*content,"cache_file",cached);
[854]488      unlockFile(*m,lck);
[642]489    }
490    cached[strlen(cached)-1]='m';
491    s=stat(cached, &f_status);
492    if(s==0){
[854]493      zooLock* lck=lockFile(*m,cached,'r');
494      if(lck==NULL)
495        return -1;
[642]496      mimeType=(char*)malloc(sizeof(char)*(f_status.st_size+1));
497      FILE* f=fopen(cached,"rb");
498      fread(mimeType,f_status.st_size,1,f);
499      mimeType[f_status.st_size]=0;
500      fclose(f);
[854]501      unlockFile(*m,lck);
[642]502    }
503  }else{   
504    addRequestToQueue(m,hInternet,url,true);
505    return 0;
506  }
507  if(fsize==0){
508    return errorException(*m, _("Unable to download the file."), "InternalError",NULL);
509  }
510  if(mimeType!=NULL){
511    addToMap(*content,"fmimeType",mimeType);
512  }
513
514  map* tmpMap=getMapOrFill(content,"value","");
515   
516  free(tmpMap->value);
517  tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
[738]518  if(tmpMap->value==NULL || fcontent == NULL)
[725]519    return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
[642]520  memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
521
522  char ltmp1[256];
523  sprintf(ltmp1,"%d",fsize);
524  addToMap(*content,"size",ltmp1);
525  if(cached==NULL){
526    addToCache(*m,url,fcontent,mimeType,fsize, NULL, 0);
527  }
528  else{
529    addToMap(*content,"isCached","true");
530    map* tmp=getMapFromMaps(*m,"main","cacheDir");
531    if(tmp!=NULL){
532      map *c=getMap((*content),"xlink:href");
[854]533      char *myRequest=getFilenameForRequest(*m,c->value);
534      char* md5str=getMd5(myRequest);
535      free(myRequest);
[642]536      char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
537      sprintf(fname,"%s/%s.zca",tmp->value,md5str);
538      addToMap(*content,"cache_file",fname);
539      free(fname);
[839]540      free(md5str);
[642]541    }
542  }
543  free(fcontent);
544  free(mimeType);
545  free(cached);
546  return 0;
547}
Note: See TracBrowser for help on using the repository browser.

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png