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

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

Add the capability to publish heatmap or any templated mapfile using the epecific msInclude and msLayer keys for an output. For MapServer? published output, define 4096 as the default maxsize and use pixel width or height for raster files. use the correct MapServer? imagemode depending on GDALGetRasterDataType (MS_IMAGEMODE_BYTE for GDT_Byte, MS_IMAGEMODE_INT16 for GDT_Int16 and MS_IMAGEMODE_FLOAT32 for GDT_Float32). Create a text file (.maps) listing every mapfiles created for a MapServer? published output (or inputs) using saveMapNames function. Fixes in ulinet, use uuid for naming temporary files. Add dialect input to the ogr2ogr service. Use the .maps file for removing a file from the DeleteData? service

  • 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      sprintf(cname,"cache_file_%d",i);
275      tmp1=getMap(content->content,cname);
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  free(tmpMap->value);
516  tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
517  if(tmpMap->value==NULL || fcontent == NULL)
518    return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
519  memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
520
521  char ltmp1[256];
522  sprintf(ltmp1,"%d",fsize);
523  addToMap(*content,"size",ltmp1);
524  if(cached==NULL){
525    addToCache(*m,url,fcontent,mimeType,fsize, NULL, 0);
526  }
527  else{
528    addToMap(*content,"isCached","true");
529    map* tmp=getMapFromMaps(*m,"main","cacheDir");
530    if(tmp!=NULL){
531      map *c=getMap((*content),"xlink:href");
532      char *myRequest=getFilenameForRequest(*m,c->value);
533      char* md5str=getMd5(myRequest);
534      free(myRequest);
535      char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
536      sprintf(fname,"%s/%s.zca",tmp->value,md5str);
537      addToMap(*content,"cache_file",fname);
538      free(fname);
539      free(md5str);
540    }
541  }
542  free(fcontent);
543  free(mimeType);
544  free(cached);
545  return 0;
546}
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