Ignore:
Timestamp:
Jun 27, 2014, 1:14:39 AM (10 years ago)
Author:
djay
Message:

Remove memory leaks from ZOO-Kernel. Fix issue #99.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/zoo-project/zoo-kernel/service_internal.c

    r485 r490  
    181181
    182182void unhandleStatus(maps *conf){
    183   int shmid,i;
     183  int shmid;
    184184  key_t key;
    185185  void *shm;
    186186  struct shmid_ds shmids;
    187   char *s,*s1;
    188187  map *tmpMap=getMapFromMaps(conf,"lenv","sid");
    189188  if(tmpMap!=NULL){
     
    207206
    208207int _updateStatus(maps *conf){
    209   int shmid,i;
     208  int shmid;
    210209  key_t key;
    211210  char *shm,*s,*s1;
     
    247246
    248247char* getStatus(int pid){
    249   int shmid,i;
     248  int shmid;
    250249  key_t key;
    251250  void *shm;
    252   char *s;
    253251  key=pid;
    254252  if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
     
    265263    }
    266264  }
    267   return "-1";
     265  return (char*)"-1";
    268266}
    269267
     
    277275  jsval *argv = JS_ARGV(cx,argv1);
    278276  JS_MaybeGC(cx);
    279   char *sid;
    280277  int istatus=0;
    281278  char *status=NULL;
    282279  maps *conf;
    283   int i=0;
    284280  if(argc>2){
    285281#ifdef JS_DEBUG
     
    385381#endif
    386382  int currId=-1;
    387   int currNode=-1;
    388383  if(nbNs==0){
    389384    nbNs++;
     
    419414  nbNs=0;
    420415}
     416
     417
     418int zooXmlAddDoc(const char* value){
     419  int currId=0;
     420  nbDocs++;
     421  currId=nbDocs-1;
     422  iDocs[currId]=xmlParseMemory(value,strlen(value));
     423  return currId;
     424}
     425
     426void zooXmlCleanupDocs(){
     427  int j;
     428  for(j=nbDocs-1;j>=0;j--){
     429    xmlFreeDoc(iDocs[j]);
     430  }
     431  nbDocs=0;
     432}
     433
    421434
    422435xmlNodePtr soapEnvelope(maps* conf,xmlNodePtr n){
     
    447460
    448461  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
    449   xmlNodePtr n,nc,nc1,nc2,nc3,nc4,nc5,nc6,pseudor;
    450   xmlChar *xmlbuff;
    451   int buffersize;
     462  xmlNodePtr n,nc,nc1,nc2,nc3,nc4,nc5,nc6;
    452463  /**
    453464   * Create the document and its temporary root.
     
    486497  if(tmp4!=NULL){
    487498    map* tmp2=tmp4->content;
    488     char *orderedFields[5];
     499    const char *orderedFields[5];
    489500    orderedFields[0]="Title";
    490501    orderedFields[1]="Abstract";
     
    555566  if(tmp4!=NULL){
    556567    map* tmp2=tmp4->content;
    557     char *tmpAddress[6];
     568    const char *tmpAddress[6];
    558569    tmpAddress[0]="addressDeliveryPoint";
    559570    tmpAddress[1]="addressCity";
     
    562573    tmpAddress[4]="addressCountry";
    563574    tmpAddress[5]="addressElectronicMailAddress";
    564     char *tmpPhone[2];
     575    const char *tmpPhone[2];
    565576    tmpPhone[0]="phoneVoice";
    566577    tmpPhone[1]="phoneFacsimile";
    567     char *orderedFields[12];
     578    const char *orderedFields[12];
    568579    orderedFields[0]="providerName";
    569580    orderedFields[1]="providerSite";
     
    608619                  for(j=0;j<2;j++)
    609620                    if(strcasecmp(tmp2->name,tmpPhone[j])==0){
    610                       char *toto=NULL;
    611                       char *toto1=tmp2->name;
    612                       toto=strstr(toto1,"Phone");
    613                       nc1 = xmlNewNode(ns_ows, BAD_CAST toto1+5);
     621                      char *tmp4=tmp2->name;
     622                      nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+5);
    614623                      xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
    615624                      xmlAddChild(nc5,nc1);
     
    621630                    for(j=0;j<6;j++)
    622631                      if(strcasecmp(tmp2->name,tmpAddress[j])==0){
    623                         char *toto=NULL;
    624                         char *toto1=tmp2->name;
    625                         toto=strstr(toto1,"Address");
    626                         nc1 = xmlNewNode(ns_ows, BAD_CAST toto1+7);
     632                        char *tmp4=tmp2->name;
     633                        nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+7);
    627634                        xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
    628635                        xmlAddChild(nc6,nc1);
     
    799806void printGetCapabilitiesForProcess(maps* m,xmlNodePtr nc,service* serv){
    800807  xmlNsPtr ns,ns_ows,ns_xlink;
    801   xmlNodePtr nr,n,nc1,nc2,nc3,nc4,nc5,nc6,pseudor;
     808  xmlNodePtr n=NULL,nc1,nc2;
    802809  /**
    803810   * Initialize or get existing namspaces
     
    810817  ns_xlink=usedNs[xlinkId];
    811818
    812   int cursor=0;
    813819  map* tmp1;
    814820  if(serv->content!=NULL){
     
    833839xmlNodePtr printDescribeProcessHeader(xmlDocPtr doc,const char* service,maps* m){
    834840
    835   xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
    836   xmlNodePtr n,nr;
    837   xmlChar *xmlbuff;
    838   int buffersize;
     841  xmlNsPtr ns,ns_xsi;
     842  xmlNodePtr n;
    839843
    840844  int wpsId=zooXmlAddNs(NULL,"http://schemas.opengis.net/wps/1.0.0","wps");
    841845  ns=usedNs[wpsId];
    842846  n = xmlNewNode(ns, BAD_CAST "ProcessDescriptions");
    843   int owsId=zooXmlAddNs(n,"http://www.opengis.net/ows/1.1","ows");
    844   ns_ows=usedNs[owsId];
     847  zooXmlAddNs(n,"http://www.opengis.net/ows/1.1","ows");
    845848  xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
    846849  zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
     
    860863
    861864void printDescribeProcessForProcess(maps* m,xmlNodePtr nc,service* serv){
    862   xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
    863   xmlNodePtr nr,n,nc1,nc2,nc3,nc4,nc5,nc6,pseudor;
    864 
    865   char tmp[256];
     865  xmlNsPtr ns,ns_ows,ns_xlink;
     866  xmlNodePtr n,nc1;
     867
    866868  n=nc;
    867869 
     
    874876
    875877  nc = xmlNewNode(NULL, BAD_CAST "ProcessDescription");
    876   char *tmp4[3];
     878  const char *tmp4[3];
    877879  tmp4[0]="processVersion";
    878880  tmp4[1]="storeSupported";
     
    916918    nc1 = xmlNewNode(NULL, BAD_CAST "DataInputs");
    917919    elements* e=serv->inputs;
    918     printFullDescription(e,"Input",ns_ows,nc1);
     920    printFullDescription(1,e,"Input",ns_ows,nc1);
    919921    xmlAddChild(nc,nc1);
    920922  }
     
    922924  nc1 = xmlNewNode(NULL, BAD_CAST "ProcessOutputs");
    923925  elements* e=serv->outputs;
    924   printFullDescription(e,"Output",ns_ows,nc1);
     926  printFullDescription(0,e,"Output",ns_ows,nc1);
    925927  xmlAddChild(nc,nc1);
    926928
     
    929931}
    930932
    931 void printFullDescription(elements *elem,const char* type,xmlNsPtr ns_ows,xmlNodePtr nc1){
    932   char *orderedFields[13];
     933void printFullDescription(int in,elements *elem,const char* type,xmlNsPtr ns_ows,xmlNodePtr nc1){
     934  const char *orderedFields[13];
    933935  orderedFields[0]="mimeType";
    934936  orderedFields[1]="encoding";
     
    10011003    iotype* _tmp=e->defaults;
    10021004    int datatype=0;
    1003     bool hasDefault=false;
    10041005    bool hasUOM=false;
    10051006    bool hasUOM1=false;
     
    10791080             * RangeClosure: Table 47 OGC Web Services Common Standard
    10801081             */
    1081             char *tmp="closed";
     1082            const char *tmp="closed";
    10821083            if(orig[0]=='[' && orig[strlen(orig)-1]=='[')
    10831084              tmp="closed-open";
     
    11461147            tmp0=getMap(tmp1,"rangeClosure");
    11471148            if(tmp0!=NULL){
    1148               char *tmp="closed";
     1149              const char *tmp="closed";
    11491150              if(strcasecmp(tmp0->value,"co")==0)
    11501151                tmp="closed-open";
     
    11901191   
    11911192     
    1192     int avcnt=0;
    1193     int dcnt=0;
    11941193    int oI=0;
    11951194    for(oI=0;oI<13;oI++)
     
    12471246
    12481247      map* metadata=e->metadata;
    1249       xmlNodePtr n;
     1248      xmlNodePtr n=NULL;
    12501249      int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
    12511250      xmlNsPtr ns_xlink=usedNs[xlinkId];
     
    13531352    }
    13541353
    1355     if(datatype==1 &&
     1354    if(in>0 && datatype==1 &&
    13561355       getMap(_tmp->content,"AllowedValues")==NULL &&
    13571356       getMap(_tmp->content,"range")==NULL &&
     
    13891388
    13901389void printProcessResponse(maps* m,map* request, int pid,service* serv,const char* service,int status,maps* inputs,maps* outputs){
    1391   xmlNsPtr ns,ns1,ns_ows,ns_xlink,ns_xsi;
    1392   xmlNodePtr nr,n,nc,nc1,nc2,nc3,pseudor;
     1390  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
     1391  xmlNodePtr nr,n,nc,nc1=NULL,nc3;
    13931392  xmlDocPtr doc;
    1394   xmlChar *xmlbuff;
    1395   int buffersize;
    13961393  time_t time1; 
    13971394  time(&time1);
     
    15741571  if(lineage!=NULL && strcasecmp(lineage->value,"true")==0){
    15751572    nc = xmlNewNode(ns, BAD_CAST "DataInputs");
    1576     int i;
    15771573    maps* mcursor=inputs;
    15781574    elements* scursor=NULL;
     
    17271723
    17281724void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,map* m,const char* type){
    1729   xmlNodePtr nc1,nc2,nc3;
     1725  xmlNodePtr nc1;
    17301726  nc1=xmlNewNode(ns_wps, BAD_CAST type);
    17311727  map *tmp=NULL; 
     
    17741770  xmlAddChild(nc1,nc2);
    17751771  xmlAddChild(nc,nc1);
    1776   // Extract Title required to be first element in the ZCFG file !
    1777   bool isTitle=TRUE;
    17781772  if(e!=NULL)
    17791773    tmp=getMap(e->content,"Title");
     
    18361830         strcasecmp(tmp->name,"schema")==0 ||
    18371831         strcasecmp(tmp->name,"datatype")==0 ||
    1838          strcasecmp(tmp->name,"uom")==0)
     1832         strcasecmp(tmp->name,"uom")==0){
    18391833#ifdef USE_MS
    18401834        if(testMap==NULL || (testMap!=NULL && strncasecmp(testMap->value,"text/xml",8)==0)){
    18411835#endif
    1842         xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
     1836          xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
    18431837#ifdef USE_MS
    18441838        }
    1845       else
    1846         if(strcasecmp(tmp->name,"mimeType")==0)
    1847           if(testMap!=NULL)
    1848             xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST testMap->value);
    1849           else
    1850             xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
    1851 #endif
     1839        else
     1840          if(strcasecmp(tmp->name,"mimeType")==0){
     1841            if(testMap!=NULL)
     1842              xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST testMap->value);
     1843            else
     1844              xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
     1845          }
     1846#endif
     1847      }
    18521848      tmp=tmp->next;
    18531849      xmlAddChild(nc2,nc3);
     
    18971893      if((tmp1!=NULL && strncmp(tmp1->value,"base64",6)==0)
    18981894         || (tmp2!=NULL && (strncmp(tmp2->value,"image/",6)==0 ||
    1899                             (strncmp(tmp2->value,"application/",12)==0) &&
    1900                             strncmp(tmp2->value,"application/json",16)!=0&&
    1901                             strncmp(tmp2->value,"application/x-javascript",24)!=0&&
    1902                             strncmp(tmp2->value,"application/vnd.google-earth.kml",32)!=0)
     1895                            (strncmp(tmp2->value,"application/",12)==0 &&
     1896                             strncmp(tmp2->value,"application/json",16)!=0&&
     1897                             strncmp(tmp2->value,"application/x-javascript",24)!=0&&
     1898                             strncmp(tmp2->value,"application/vnd.google-earth.kml",32)!=0))
    19031899             )) {
    19041900        map* rs=getMap(m->content,"size");
     
    19061902        if(rs==NULL){
    19071903          char tmp1[1024];
    1908           sprintf(tmp1,"%d",strlen(tmp3->value));
     1904          sprintf(tmp1,"%u",strlen(tmp3->value));
    19091905          rs=createMap("size",tmp1);
    19101906          isSized=false;
     
    19241920          if(strncmp(tmp2->value,"text/xml",8)==0 ||
    19251921             strncmp(tmp2->value,"application/vnd.google-earth.kml",32)==0){
    1926             xmlDocPtr doc =
    1927               xmlParseMemory(tmp3->value,strlen(tmp3->value));
     1922            int li=zooXmlAddDoc(tmp3->value);
     1923            xmlDocPtr doc = iDocs[li];
    19281924            xmlNodePtr ir = xmlDocGetRootElement(doc);
    19291925            xmlAddChild(nc3,ir);
     
    19591955         strcasecmp(tmp->name,"schema")==0 ||
    19601956         strcasecmp(tmp->name,"datatype")==0 ||
    1961          strcasecmp(tmp->name,"uom")==0)
     1957         strcasecmp(tmp->name,"uom")==0){
    19621958#ifdef USE_MS
    19631959        if(testMap!=NULL  && strncasecmp(testMap->value,"text/xml",8)!=0){
     
    19671963        else
    19681964#endif
    1969         xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
     1965          xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
     1966      }
    19701967      tmp=tmp->next;
    19711968      xmlAddChild(nc2,nc3);
     
    19831980  xmlAddChild(root,nc2);
    19841981  map* tmp=amap;
    1985   char *tmp2[2];
     1982  const char *tmp2[2];
    19861983  tmp2[0]="Title";
    19871984  tmp2[1]="Abstract";
     
    20042001    }
    20052002    else
    2006       return "UTF-8";
     2003      return (char*)"UTF-8";
    20072004  }
    20082005  else
    2009     return "UTF-8"; 
     2006    return (char*)"UTF-8"; 
    20102007}
    20112008
     
    20172014    }
    20182015    else
    2019       return "1.0.0";
     2016      return (char*)"1.0.0";
    20202017  }
    20212018  else
    2022     return "1.0.0";
     2019    return (char*)"1.0.0";
    20232020}
    20242021
     
    20352032  maps* tmpMap=getMaps(m,"main");
    20362033  char *encoding=getEncoding(tmpMap);
    2037   char *exceptionCode;
     2034  const char *exceptionCode;
    20382035 
    20392036  map* tmp=getMap(s,"code");
     
    20872084xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){
    20882085 
    2089   int buffersize;
    2090   xmlChar *xmlbuff;
    2091   xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
    2092   xmlNodePtr n,nc,nc1,nc2;
    2093 
    2094   maps* tmpMap=getMaps(m,"main");
     2086  xmlNsPtr ns,ns_xsi;
     2087  xmlNodePtr n,nc,nc1;
    20952088
    20962089  int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows");
     
    21012094  n = xmlNewNode(ns, BAD_CAST "ExceptionReport");
    21022095  if(use_ns==1){
    2103     ns_ows=xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",NULL);
     2096    xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",NULL);
    21042097    int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
    21052098    ns_xsi=usedNs[xsiId];
     
    21262119  tmp=getMap(s,"text");
    21272120  nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
    2128   nc2=NULL;
    21292121  if(tmp!=NULL){
    21302122    xmlNodeSetContent(nc1, BAD_CAST tmp->value);
     
    21542146  if(tmpSess!=NULL){
    21552147    map *_tmp=getMapFromMaps(m,"lenv","cookie");
    2156     char* sessId;
     2148    char* sessId=NULL;
    21572149    if(_tmp!=NULL){
    21582150      printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value);
     
    24932485      if(type==0){
    24942486        map* tmpMapMinO=getMap(tmpInputs->content,"minOccurs");
    2495         if(tmpMapMinO!=NULL)
     2487        if(tmpMapMinO!=NULL){
    24962488          if(atoi(tmpMapMinO->value)>=1){
    24972489            freeMaps(&tmpMaps2);
     
    25052497              addToMap(tmpMaps2->content,"minOccurs",tmpMapMinO->value);
    25062498          }
     2499        }
    25072500        map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
    2508         if(tmpMaxO!=NULL)
     2501        if(tmpMaxO!=NULL){
    25092502          if(tmpMaps2->content==NULL)
    25102503            tmpMaps2->content=createMap("maxOccurs",tmpMaxO->value);
    25112504          else
    25122505            addToMap(tmpMaps2->content,"maxOccurs",tmpMaxO->value);
     2506        }
    25132507        map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");
    2514         if(tmpMaxMB!=NULL)
     2508        if(tmpMaxMB!=NULL){
    25152509          if(tmpMaps2->content==NULL)
    25162510            tmpMaps2->content=createMap("maximumMegabytes",tmpMaxMB->value);
    25172511          else
    25182512            addToMap(tmpMaps2->content,"maximumMegabytes",tmpMaxMB->value);
     2513        }
    25192514      }
    25202515
     
    25722567        }
    25732568        map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");
    2574         if(tmpMaxMB!=NULL)
     2569        if(tmpMaxMB!=NULL){
    25752570          if(tmpMaps->content==NULL)
    25762571            tmpMaps->content=createMap("maximumMegabytes",tmpMaxMB->value);
    25772572          else
    25782573            addToMap(tmpMaps->content,"maximumMegabytes",tmpMaxMB->value);
     2574        }
    25792575        /**
    25802576         * Parsing BoundingBoxData, fill the following map and then add it to
     
    27462742void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
    27472743
    2748   xmlNodePtr bb,lw,uc;
     2744  xmlNodePtr lw=NULL,uc=NULL;
    27492745
    27502746  map* tmp=getMap(boundingbox,"value");
     
    28762872    fprintf(stderr,"MIMETYPE: %s\n",mimeType);
    28772873#endif
    2878     fwrite(mimeType,sizeof(char),strlen(mimeType),fo);
     2874    fwrite(mimeType,1,strlen(mimeType),fo);
    28792875    fclose(fo);
    28802876
     
    29142910  char* cached=isInCache(*m,url);
    29152911  char *mimeType=NULL;
    2916   int fsize;
    2917   int hasF=-1;
     2912  int fsize=0;
    29182913  if(cached!=NULL){
    29192914    struct stat f_status;
     
    29222917      fcontent=(char*)malloc(sizeof(char)*(f_status.st_size+1));
    29232918      FILE* f=fopen(cached,"rb");
    2924       int len=fread(fcontent,f_status.st_size,1,f);
     2919      fread(fcontent,f_status.st_size,1,f);
    29252920      fsize=f_status.st_size;
    29262921      fcontent[fsize]=0;
     
    29322927      mimeType=(char*)malloc(sizeof(char)*(f_status.st_size+1));
    29332928      FILE* f=fopen(cached,"rb");
    2934       int len=fread(mimeType,f_status.st_size,1,f);
     2929      fread(mimeType,f_status.st_size,1,f);
    29352930      mimeType[f_status.st_size]=0;
    29362931      fclose(f);
     
    29702965  if(cached==NULL)
    29712966    addToCache(*m,url,fcontent,mimeType,fsize);
    2972   else{
    2973     free(fcontent);
    2974     free(mimeType);
    2975     free(cached);
    2976   }
     2967  free(fcontent);
     2968  free(mimeType);
     2969  free(cached);
    29772970  return 0;
    29782971}
     
    29922985}
    29932986
     2987
    29942988char *readVSIFile(maps* conf,const char* dataSource){
    29952989    VSILFILE * fichier=VSIFOpenL(dataSource,"rb");
     
    30042998    }
    30052999    char *res1=(char *)malloc(file_status.st_size*sizeof(char));
    3006     VSIFReadL(res1,1,(file_status.st_size)*sizeof(char),fichier);
     3000    VSIFReadL(res1,1,file_status.st_size*sizeof(char),fichier);
     3001    res1[file_status.st_size-1]=0;
    30073002    VSIFCloseL(fichier);
    30083003    VSIUnlink(dataSource);
     
    30653060}
    30663061
    3067 
    30683062int updateStatus( maps* conf, const int percentCompleted, const char* message ){
    30693063  char tmp[4];
     
    30983092    tmp->value=(char*) malloc((numberOfBytes+1)*sizeof(char));
    30993093    memcpy(tmp->value,data,numberOfBytes);
    3100     sprintf(size,"%d",numberOfBytes);
     3094    sprintf(size,"%lu",numberOfBytes);
    31013095    setMapInMaps(outputs,parameterName,"size",size);
    31023096  }
Note: See TracChangeset for help on using the changeset viewer.

Search

Context Navigation

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