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
Line 
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
40 * @warning make sure to free resources returned by this function
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/**
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/**
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){
148    char* myRequest=getFilenameForRequest(conf,request);
149    char* md5str=getMd5(myRequest);
150    free(myRequest);
151    char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
152    sprintf(fname,"%s/%s.zca",tmp->value,md5str);
153    zooLock* lck=lockFile(conf,fname,'w');
154    if(lck!=NULL){
155#ifdef DEBUG
156      fprintf(stderr,"Cache list : %s\n",fname);
157      fflush(stderr);
158#endif
159      FILE* fo=fopen(fname,"w+");
160      if(fo==NULL){
161#ifdef DEBUG
162        fprintf (stderr, "Failed to open %s for writing: %s\n",fname, strerror(errno));
163#endif
164        filepath = NULL;
165        unlockFile(conf,lck);
166        return;
167      }
168      fwrite(content,sizeof(char),length,fo);
169      unlockFile(conf,lck);
170      fclose(fo);
171       
172      if (filepath != NULL) {
173        strncpy(filepath, fname, max_path);
174      }
175
176      sprintf(fname,"%s/%s.zcm",tmp->value,md5str);
177      fo=fopen(fname,"w+");
178#ifdef DEBUG
179      fprintf(stderr,"MIMETYPE: %s\n",mimeType);
180#endif
181      fwrite(mimeType,sizeof(char),strlen(mimeType),fo);
182      fclose(fo);
183
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    }
196  }
197  else {
198    filepath = NULL;
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
208 * @warning make sure to free resources returned by this function (if not NULL)
209 */
210char* isInCache(maps* conf,char* request){
211  map* tmpM=getMapFromMaps(conf,"main","cacheDir");
212  if(tmpM!=NULL){
213    char* myRequest=getFilenameForRequest(conf,request);
214    char* md5str=getMd5(myRequest);
215    free(myRequest);
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/**
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
240 * @param error the error map pointer
241 * @return 0 in case of success, -1 in case of failure
242 */
243int readCurrentInput(maps** m,maps** in,int* index,HINTERNET* hInternet,map** error){
244 
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];
265    char bname[8];
266    char hname[11];
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);
281      sprintf(bname,"body_%d",i);
282      sprintf(hname,"headers_%d",i);
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");
291      sprintf(bname,"body");
292      sprintf(hname,"headers");
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){
299
300      if(getMap(content->content,icname)==NULL){       
301        fcontent=(char*)malloc((hInternet->ihandle[*index].nDataLen+1)*sizeof(char));
302        if(fcontent == NULL){
303          errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
304          return -1;
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));
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        }
344       
345        char ltmp1[256];
346        sprintf(ltmp1,"%d",fsize);
347        map* tmp=getMapFromMaps(*m,"main","cacheDir");
348        char *request=NULL;
349        if(tmp!=NULL){
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);
357              free(tmpStr);
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{
366            char *myRequest=getFilenameForRequest(*m,tmp1->value);
367            md5str=getMd5(myRequest);
368            request=zStrdup(tmp1->value);
369            free(myRequest);
370          }
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);
378        addToCache(*m,request,fcontent,mimeType,fsize, NULL, 0);
379        free(fcontent);
380        free(mimeType);
381        free(request);
382        (*index)++;
383      }
384    }
385  }
386  if(shouldClean>0){
387    freeMap(&length);
388    free(length);
389  }
390  return 0;
391}
392
393/**
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
400 * @param error the error map pointer
401 * @return 0 on success, -1 on failure
402 */
403int runHttpRequests(maps** m,maps** inputs,HINTERNET* hInternet,map** error){
404  int hasAFailure=0;
405  if(hInternet!=NULL && hInternet->nb>0){
406    AddHeaderEntries(hInternet,*m);
407    processDownloads(hInternet);
408    maps* content=*inputs;
409    int index=0;
410    while(content!=NULL){
411      if(content->child!=NULL){
412        maps* cursor=content->child;
413        while(cursor!=NULL){
414          int red=readCurrentInput(m,&cursor,&index,hInternet,error);
415          if(red<0)
416            hasAFailure=red;
417          cursor=cursor->next;
418        }
419      }
420      else{
421        int red=readCurrentInput(m,&content,&index,hInternet,error);
422        if(red<0)
423          hasAFailure=red;
424      }
425      content=content->next;
426    }
427  }
428  return hasAFailure;
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){
443    oreq=createMaps("orequests");
444    oreq->content=createMap("value",url);
445    addMapsToMaps(m,oreq);
446    freeMaps(&oreq);
447    free(oreq);
448  }else{
449    setMapArray(oreq->content,"value",hInternet->nb,url);
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){
463  char* fcontent = NULL;
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){
478      zooLock* lck=lockFile(*m,cached,'r');
479      if(lck==NULL)
480        return -1;
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);
488      unlockFile(*m,lck);
489    }
490    cached[strlen(cached)-1]='m';
491    s=stat(cached, &f_status);
492    if(s==0){
493      zooLock* lck=lockFile(*m,cached,'r');
494      if(lck==NULL)
495        return -1;
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);
501      unlockFile(*m,lck);
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));
518  if(tmpMap->value==NULL || fcontent == NULL)
519    return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
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");
533      char *myRequest=getFilenameForRequest(*m,c->value);
534      char* md5str=getMd5(myRequest);
535      free(myRequest);
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);
540      free(md5str);
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