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

Last change on this file since 839 was 839, checked in by djay, 7 years ago

Update the source code for HPC support. Automatically adding nested outputs for the HPC support (should this be available for every support?). Add capability to store the metadata in the Collection DataBase?. Addition of the zcfg2sql to import any existing ZCFG file into the Collection DB. Add the support to invoke a callback (for history purpose) in case a [callback] section contains at least one parameter defined (url). Add support to convert maps and map to JSON (for callback use only by now). Fix some memory leaks (some are still there).

  • Property svn:keywords set to Id
File size: 13.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 * Cache a file for a given request.
67 * For each cached file, the are two files stored, a .zca and a .zcm containing
68 * the downloaded content and the mimeType respectively.
69 *
70 * @param conf the maps containing the settings of the main.cfg file
71 * @param request the url used too fetch the content
72 * @param content the downloaded content
73 * @param mimeType the content mimeType
74 * @param length the content size
75 * @param filepath a buffer for storing the path of the cached file; may be NULL
76 * @param max_path the size of the allocated filepath buffer 
77 */
78void addToCache(maps* conf,char* request,char* content,char* mimeType,int length, 
79                char* filepath, size_t max_path){
80  map* tmp=getMapFromMaps(conf,"main","cacheDir");
81  if(tmp!=NULL){
82    char* md5str=getMd5(request);
83    char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
84    sprintf(fname,"%s/%s.zca",tmp->value,md5str);
85#ifdef DEBUG
86    fprintf(stderr,"Cache list : %s\n",fname);
87    fflush(stderr);
88#endif
89    FILE* fo=fopen(fname,"w+");
90    if(fo==NULL){
91#ifdef DEBUG
92      fprintf (stderr, "Failed to open %s for writing: %s\n",fname, strerror(errno));
93#endif
94      filepath = NULL; 
95      return;
96    }
97    fwrite(content,sizeof(char),length,fo);
98    fclose(fo);
99       
100        if (filepath != NULL) {
101                strncpy(filepath, fname, max_path);
102        }       
103
104    sprintf(fname,"%s/%s.zcm",tmp->value,md5str);
105    fo=fopen(fname,"w+");
106#ifdef DEBUG
107    fprintf(stderr,"MIMETYPE: %s\n",mimeType);
108#endif
109    fwrite(mimeType,sizeof(char),strlen(mimeType),fo);
110    fclose(fo);
111
112    free(md5str);
113    free(fname);
114  }
115  else {
116          filepath = NULL;
117  }       
118}
119
120/**
121 * Verify if a url is available in the cache
122 *
123 * @param conf the maps containing the settings of the main.cfg file
124 * @param request the url
125 * @return the full name of the cached file if any, NULL in other case
126 * @warning make sure to free resources returned by this function (if not NULL)
127 */
128char* isInCache(maps* conf,char* request){
129  map* tmpM=getMapFromMaps(conf,"main","cacheDir");
130  if(tmpM!=NULL){
131    char* md5str=getMd5(request);
132#ifdef DEBUG
133    fprintf(stderr,"MD5STR : (%s)\n\n",md5str);
134#endif
135    char* fname=(char*)malloc(sizeof(char)*(strlen(tmpM->value)+strlen(md5str)+6));
136    sprintf(fname,"%s/%s.zca",tmpM->value,md5str);
137    struct stat f_status;
138    int s=stat(fname, &f_status);
139    if(s==0 && f_status.st_size>0){
140      free(md5str);
141      return fname;
142    }
143    free(md5str);
144    free(fname);
145  }
146  return NULL;
147}
148
149/**
150 * Read the downloaded file for a specific input
151 *
152 * @param m the maps containing the settings of the main.cfg file
153 * @param in the input
154 * @param index the input index
155 * @param hInternet the internet connection
156 * @param error the error map pointer
157 * @return 0 in case of success, -1 in case of failure
158 */
159int readCurrentInput(maps** m,maps** in,int* index,HINTERNET* hInternet,map** error){
160 
161  map* tmp1;
162  char sindex[5];
163  maps* content=*in;
164  map* length=getMap(content->content,"length");
165  int shouldClean=-1;
166  if(length==NULL){
167    length=createMap("length","1");
168    shouldClean=1;
169  }
170  for(int i=0;i<atoi(length->value);i++){
171    char* fcontent;
172    char *mimeType=NULL;
173    int fsize=0;
174    char cname[15];
175    char vname[11];
176    char vname1[11];
177    char sname[9];
178    char mname[15];
179    char icname[14];
180    char xname[16];
181    char bname[8];
182    char hname[11];
183    char oname[12];
184    if(*index>0)
185      sprintf(vname1,"value_%d",*index);
186    else
187      sprintf(vname1,"value");
188   
189    if(i>0){
190      tmp1=getMap(content->content,cname);
191      sprintf(cname,"cache_file_%d",i);
192      sprintf(vname,"value_%d",i);
193      sprintf(sname,"size_%d",i);
194      sprintf(mname,"mimeType_%d",i);
195      sprintf(icname,"isCached_%d",i);
196      sprintf(xname,"Reference_%d",i);
197      sprintf(bname,"body_%d",i);
198      sprintf(hname,"headers_%d",i);
199      sprintf(oname,"Order_%d",i);
200    }else{
201      sprintf(cname,"cache_file");
202      sprintf(vname,"value");
203      sprintf(sname,"size");
204      sprintf(mname,"mimeType");
205      sprintf(icname,"isCached");
206      sprintf(xname,"Reference");
207      sprintf(bname,"body");
208      sprintf(hname,"headers",i);
209      sprintf(oname,"Order");
210    }
211   
212    map* tmap=getMap(content->content,oname);
213    sprintf(sindex,"%d",*index+1);
214    if((tmp1=getMap(content->content,xname))!=NULL && tmap!=NULL && strcasecmp(tmap->value,sindex)==0){
215
216      if(getMap(content->content,icname)==NULL){       
217        fcontent=(char*)malloc((hInternet->ihandle[*index].nDataLen+1)*sizeof(char));
218        if(fcontent == NULL){
219          errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
220          return -1;
221        }
222        size_t dwRead;
223        InternetReadFile(hInternet->ihandle[*index], 
224                         (LPVOID)fcontent, 
225                         hInternet->ihandle[*index].nDataLen, 
226                         &dwRead);
227        fcontent[hInternet->ihandle[*index].nDataLen]=0;
228        fsize=hInternet->ihandle[*index].nDataLen;
229        if(hInternet->ihandle[*index].mimeType==NULL)
230          mimeType=zStrdup("none");
231        else
232          mimeType=zStrdup(hInternet->ihandle[*index].mimeType);             
233       
234        map* tmpMap=getMapOrFill(&(*in)->content,vname,"");
235        free(tmpMap->value);
236        tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
237        if(tmpMap->value==NULL){
238          return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
239        }
240        memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
241        if(hInternet->ihandle[*index].code!=200){
242          char *error_rep_str=_("Unable to download the file for the input <%s>, response code was : %d.");
243          char *error_msg=(char*)malloc((strlen(error_rep_str)+strlen(content->name)+4)*sizeof(char));
244          sprintf(error_msg,error_rep_str,content->name,hInternet->ihandle[*index].code);
245          if(*error==NULL){
246            *error=createMap("text",error_msg);
247            addToMap(*error,"locator",content->name);
248            addToMap(*error,"code","InvalidParameterValue");
249          }else{
250            int nb=1;
251            map* tmpMap=getMap(*error,"length");
252            if(tmpMap!=NULL)
253              nb=atoi(tmpMap->value);
254            setMapArray(*error,"text",nb,error_msg);
255            setMapArray(*error,"locator",nb,content->name);
256            setMapArray(*error,"code",nb,"InvalidParameterValue");
257          }
258          return -1;
259        }
260       
261        char ltmp1[256];
262        sprintf(ltmp1,"%d",fsize);
263        map* tmp=getMapFromMaps(*m,"main","cacheDir");
264        char *request=NULL;
265        if(tmp!=NULL){
266          map* tmp2;
267          char* md5str=NULL;
268          if((tmp2=getMap(content->content,bname))!=NULL){
269            char *tmpStr=(char*)malloc((strlen(tmp1->value)+strlen(tmp2->value)+1)*sizeof(char));
270            sprintf(tmpStr,"%s%s",tmp1->value,tmp2->value);
271            if((tmp2=getMap(content->content,"headers"))!=NULL){
272              char *tmpStr2=zStrdup(tmpStr);
273              free(tmpStr);
274              tmpStr=(char*)malloc((strlen(tmpStr2)+strlen(tmp2->value)+1)*sizeof(char));
275              sprintf(tmpStr,"%s%s",tmpStr2,tmp2->value);
276              free(tmpStr2);
277            }
278            md5str=getMd5(tmpStr);
279            request=zStrdup(tmpStr);
280            free(tmpStr);
281          }else{
282            md5str=getMd5(tmp1->value);
283            request=zStrdup(tmp1->value);
284          }
285          char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
286          sprintf(fname,"%s/%s.zca",tmp->value,md5str);
287          addToMap((*in)->content,cname,fname);
288          free(fname);
289        }
290        addToMap((*in)->content,sname,ltmp1);
291        addToMap((*in)->content,mname,mimeType);
292        addToCache(*m,request,fcontent,mimeType,fsize, NULL, 0);
293        free(fcontent);
294        free(mimeType);
295        free(request);
296        (*index)++;
297      }
298    }
299  }
300  if(shouldClean>0){
301    freeMap(&length);
302    free(length);
303  }
304  return 0;
305}
306
307/**
308 * Effectively run all the HTTP requests in the queue
309 *
310 * @param m the maps containing the settings of the main.cfg file
311 * @param inputs the maps containing the inputs (defined in the requests+added
312 *  per default based on the zcfg file)
313 * @param hInternet the HINTERNET pointer
314 * @param error the error map pointer
315 * @return 0 on success, -1 on failure
316 */
317int runHttpRequests(maps** m,maps** inputs,HINTERNET* hInternet,map** error){
318  int hasAFailure=0;
319  if(hInternet!=NULL && hInternet->nb>0){
320    AddHeaderEntries(hInternet,*m);
321    processDownloads(hInternet);
322    maps* content=*inputs;
323    int index=0;
324    while(content!=NULL){
325      if(content->child!=NULL){
326        maps* cursor=content->child;
327        while(cursor!=NULL){
328          int red=readCurrentInput(m,&cursor,&index,hInternet,error);
329          if(red<0)
330            hasAFailure=red;
331          cursor=cursor->next;
332        }
333      }
334      else{
335        int red=readCurrentInput(m,&content,&index,hInternet,error);
336        if(red<0)
337          hasAFailure=red;
338      }
339      content=content->next;
340    }
341  }
342  return hasAFailure;
343}
344
345/**
346 * Add a request in the download queue
347 *
348 * @param m the maps containing the settings of the main.cfg file
349 * @param url the url to add to the queue
350 */
351void addRequestToQueue(maps** m,HINTERNET* hInternet,const char* url,bool req){
352  hInternet->waitingRequests[hInternet->nb]=strdup(url);
353  if(req)
354    InternetOpenUrl(hInternet,hInternet->waitingRequests[hInternet->nb],NULL,0,INTERNET_FLAG_NO_CACHE_WRITE,0);
355  maps *oreq=getMaps(*m,"orequests");
356  if(oreq==NULL){
357    oreq=createMaps("orequests");
358    oreq->content=createMap("value",url);
359    addMapsToMaps(m,oreq);
360    freeMaps(&oreq);
361    free(oreq);
362  }else{
363    setMapArray(oreq->content,"value",hInternet->nb,url);
364  }
365}
366
367/**
368 * Try to load file from cache or download a remote file if not in cache
369 *
370 * @param m the maps containing the settings of the main.cfg file
371 * @param content the map to update
372 * @param hInternet the HINTERNET pointer
373 * @param url the url to fetch
374 * @return 0
375 */
376int loadRemoteFile(maps** m,map** content,HINTERNET* hInternet,char *url){
377  char* fcontent = NULL;
378  char* cached=isInCache(*m,url);
379  char *mimeType=NULL;
380  int fsize=0;
381
382  map* t=getMap(*content,"xlink:href");
383  if(t==NULL){
384    t=getMap((*content),"href");
385    addToMap(*content,"xlink:href",url);
386  }
387
388  if(cached!=NULL){
389
390    struct stat f_status;
391    int s=stat(cached, &f_status);
392    if(s==0){
393      fcontent=(char*)malloc(sizeof(char)*(f_status.st_size+1));
394      FILE* f=fopen(cached,"rb");
395      fread(fcontent,f_status.st_size,1,f);
396      fsize=f_status.st_size;
397      fcontent[fsize]=0;
398      fclose(f);
399      addToMap(*content,"cache_file",cached);
400    }
401    cached[strlen(cached)-1]='m';
402    s=stat(cached, &f_status);
403    if(s==0){
404      mimeType=(char*)malloc(sizeof(char)*(f_status.st_size+1));
405      FILE* f=fopen(cached,"rb");
406      fread(mimeType,f_status.st_size,1,f);
407      mimeType[f_status.st_size]=0;
408      fclose(f);
409    }
410
411  }else{   
412    addRequestToQueue(m,hInternet,url,true);
413    return 0;
414  }
415  if(fsize==0){
416    return errorException(*m, _("Unable to download the file."), "InternalError",NULL);
417  }
418  if(mimeType!=NULL){
419    addToMap(*content,"fmimeType",mimeType);
420  }
421
422  map* tmpMap=getMapOrFill(content,"value","");
423   
424  free(tmpMap->value);
425  tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
426  if(tmpMap->value==NULL || fcontent == NULL)
427    return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
428  memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
429
430  char ltmp1[256];
431  sprintf(ltmp1,"%d",fsize);
432  addToMap(*content,"size",ltmp1);
433  if(cached==NULL){
434    addToCache(*m,url,fcontent,mimeType,fsize, NULL, 0);
435  }
436  else{
437    addToMap(*content,"isCached","true");
438    map* tmp=getMapFromMaps(*m,"main","cacheDir");
439    if(tmp!=NULL){
440      map *c=getMap((*content),"xlink:href");
441      char* md5str=getMd5(c->value);
442      char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
443      sprintf(fname,"%s/%s.zca",tmp->value,md5str);
444      addToMap(*content,"cache_file",fname);
445      free(fname);
446      free(md5str);
447    }
448  }
449  free(fcontent);
450  free(mimeType);
451  free(cached);
452  return 0;
453}
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