Changeset 392


Ignore:
Timestamp:
Feb 11, 2013, 1:52:15 PM (12 years ago)
Author:
djay
Message:

Add support for Python-3.3.0. Fix issue with cache handling. Fix issue with Cookie identifier detection.

Location:
trunk/zoo-project
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/zoo-project/HISTORY.txt

    r383 r392  
    1616  * Add support for sending headers through JS ZOO-api
    1717  * Add support for multi-valued inputs in JS ZOO-api
     18  * Fixing issue about invalid status document #73
     19  * Add Python-3.3.0 support
    1820
    1921Version 1.2.0-rc3
  • trunk/zoo-project/zoo-kernel/nmake.opt

    r384 r392  
    3434TPATH=$(ZOOK_DIR)\..\..\..\tools
    3535LIBINTL_CPATH=$(ZOOK_DIR)\..\..\..\
    36 PYTHON_CPATH=$(ZOOK_DIR)\..\..\..\Python-2.7.3
     36PYTHON_CPATH=$(PY_DIR)
    3737
    3838CFLAGS=$(CFLAGS1) /nologo /MD /W3 /EHsc /Ox /D_CRT_SECURE_NO_WARNINGS /DWIN32 $(CJFLAGS) -I$(ZOOK_DIR) -I./ $(JAVA_CFLAGS) $(MS_CFLAGS) -I$(TROOT)\..\..\thirds\dirent-win32 -I$(INTL_DIR) -I$(CURL_DIR)\include -I$(XML2_DIR)\include -I$(GDAL_DIR)\port $(JS_CFLAGS) -I$(GDAL_DIR)\ogr -I$(GDAL_DIR)\gcore -I$(GD_DIR) -I$(ICONV_DIR) -I$(TROOT)\..\..\thirds\include -I$(TROOT)\..\..\thirds\cgic206 -I$(PYTHON_CPATH)\include -I$(SSL_DIR)/inc32 -I$(FCGI_DIR)\include $(PY_CFLAGS) -DLINUX_FREE_ISSUE #-DDEBUG #-DDEBUG_SERVICE_CONF
  • trunk/zoo-project/zoo-kernel/service_internal.c

    r387 r392  
    22 * Author : Gérald FENOY
    33 *
    4  * Copyright (c) 2009-2012 GeoLabs SARL
     4 * Copyright (c) 2009-2013 GeoLabs SARL
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a copy
     
    25182518    fprintf(stderr,"MD5STR : (%s)\n\n",md5str);
    25192519#endif
    2520     char* fname=(char*)malloc(sizeof(char)*(strlen(tmpM->value)+50));
     2520    char* fname=(char*)malloc(sizeof(char)*(strlen(tmpM->value)+strlen(md5str)+6));
    25212521    sprintf(fname,"%s/%s.zca",tmpM->value,md5str);
    25222522    struct stat f_status;
     
    25482548      fcontent=(char*)malloc(sizeof(char)*(f_status.st_size+1));
    25492549      FILE* f=fopen(cached,"rb");
    2550       fread(fcontent,sizeof(char),f_status.st_size,f);
     2550      int len=fread(fcontent,f_status.st_size,1,f);
    25512551      fsize=f_status.st_size;
    2552       hasF=1;
     2552      fcontent[fsize]=0;
    25532553    }
    25542554  }else{
     
    25582558      return errorException(m, _("Unable to allocate memory."), "InternalError");
    25592559    }
    2560     hasF=1;
    25612560    size_t dwRead;
    25622561    InternetReadFile(res, (LPVOID)fcontent, res.nDataLen, &dwRead);
     
    25742573  if(tmpMap->value==NULL)
    25752574    fprintf(stderr,"Unable to allocate memory!\n");
    2576   memcpy(tmpMap->value,fcontent,(fsize)*sizeof(char));
     2575  //snprintf(tmpMap->value,(fsize+1)*sizeof(char),fcontent);
     2576  memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
    25772577 
    25782578  char ltmp1[256];
     
    25822582    addToCache(m,url,fcontent,fsize);
    25832583  else{
    2584     if(hasF)
    2585       free(fcontent);
    25862584    free(cached);
    25872585  }
  • trunk/zoo-project/zoo-kernel/service_internal.h

    r376 r392  
    22 * Author : Gérald FENOY
    33 *
    4  * Copyright (c) 2009-2011 GeoLabs SARL
     4 * Copyright (c) 2009-2013 GeoLabs SARL
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a copy
     
    5959#include <openssl/buffer.h>
    6060
    61 #include "cgic.h"
    6261#include "ulinet.h"
    6362
     
    135134  char* isInCache(maps*,char*);
    136135  int loadRemoteFile(maps*,map*,HINTERNET,char*);
    137  
     136
    138137#ifdef __cplusplus
    139138}
  • trunk/zoo-project/zoo-kernel/service_internal_python.c

    r376 r392  
    22 * Author : Gérald FENOY
    33 *
    4  * Copyright (c) 2009-2012 GeoLabs SARL
     4 * Copyright (c) 2009-2013 GeoLabs SARL
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a copy
     
    2525#include "service_internal_python.h"
    2626
     27struct module_state {
     28    PyObject *error;
     29};
     30
     31#if PY_MAJOR_VERSION >= 3
     32#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
     33#else
     34#define GETSTATE(m) (&_state)
     35static struct module_state _state;
     36#endif
     37
    2738static PyObject* ZooError;
    2839
     
    3344};
    3445
     46#if PY_MAJOR_VERSION >= 3
     47
     48static int myextension_traverse(PyObject *m, visitproc visit, void *arg) {
     49  Py_VISIT(GETSTATE(m)->error);
     50  return 0;
     51}
     52
     53static int myextension_clear(PyObject *m) {
     54  Py_CLEAR(GETSTATE(m)->error);
     55  return 0;
     56}
     57
     58static struct PyModuleDef moduledef = {
     59  PyModuleDef_HEAD_INIT,
     60  "zoo",
     61  NULL,
     62  sizeof(struct module_state),
     63  zooMethods,
     64  NULL,
     65  myextension_traverse,
     66  myextension_clear,
     67  NULL
     68};
     69#endif
     70
    3571PyMODINIT_FUNC init_zoo(){
    3672  PyObject *tmp,*d;
    37   PyObject* module = Py_InitModule("zoo", zooMethods);
    38   if (module == NULL)
     73  PyObject *module =
     74#if PY_MAJOR_VERSION >= 3
     75    PyModule_Create(&moduledef);
     76#else
     77    Py_InitModule("zoo", zooMethods);
     78#endif
     79  if (module == NULL){
     80#if PY_MAJOR_VERSION >= 3
     81    return NULL;
     82#else
    3983    return;
    40  
     84#endif
     85  }
     86
     87  struct module_state *st = GETSTATE(module);
     88
    4189  d = PyModule_GetDict(module);
     90#if PY_MAJOR_VERSION >= 3
     91  tmp = PyLong_FromLong(3);
     92#else
    4293  tmp = PyInt_FromLong(3);
     94#endif
    4395  PyDict_SetItemString(d, "SERVICE_SUCCEEDED", tmp);
    4496  Py_DECREF(tmp);
    4597
     98#if PY_MAJOR_VERSION >= 3
     99  tmp = PyLong_FromLong(4);
     100#else
    46101  tmp = PyInt_FromLong(4);
     102#endif
    47103  PyDict_SetItemString(d, "SERVICE_FAILED", tmp);
    48104  Py_DECREF(tmp);
     
    51107  Py_INCREF(ZooError);
    52108  PyModule_AddObject(module, "error", ZooError);
     109#if PY_MAJOR_VERSION >= 3
     110  return module;
     111#endif
    53112}
    54113
     
    57116  maps* inputs=*real_inputs;
    58117  maps* outputs=*real_outputs;
    59   char ntmp[1024];
    60   getcwd(ntmp,1024);
     118  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
     119  char *ntmp=tmp0->value;
    61120  map* tmp=NULL;
    62121  tmp=getMapFromMaps(*main_conf,"env","PYTHONPATH");
     
    78137  tmp=NULL;
    79138  tmp=getMap(request,"metapath");
    80   char *pythonpath=(char*)malloc((1+strlen(python_path)+2048)*sizeof(char));
    81   if(tmp!=NULL && strcmp(tmp->value,"")!=0)
     139  char *pythonpath;//=(char*)malloc((1+strlen(python_path)+2048)*sizeof(char));
     140  if(tmp!=NULL && strcmp(tmp->value,"")!=0){
     141    pythonpath=(char*)malloc((4+strlen(python_path)+strlen(ntmp)+strlen(tmp->value))*sizeof(char));
    82142#ifdef WIN32
    83143    sprintf(pythonpath,"%s/%s/;%s",ntmp,tmp->value,python_path);
    84144#else
    85   sprintf(pythonpath,"%s/%s/:%s",ntmp,tmp->value,python_path);
    86 #endif
    87   else
     145    sprintf(pythonpath,"%s/%s/:%s",ntmp,tmp->value,python_path);
     146#endif
     147  }
     148  else{
     149    pythonpath=(char*)malloc((2+strlen(python_path)+strlen(ntmp))*sizeof(char));
    88150#ifdef WIN32
    89151    sprintf(pythonpath,"%s;%s",ntmp,python_path);
    90152#else
    91   sprintf(pythonpath,"%s:%s",ntmp,python_path);
    92 #endif
     153    sprintf(pythonpath,"%s:%s",ntmp,python_path);
     154#endif
     155  }
    93156#ifdef DEBUG
    94157    fprintf(stderr,"PYTHONPATH=%s\n",pythonpath);
     
    106169
    107170  PyThreadState *mainstate;
     171#if PY_MAJOR_VERSION >= 3
     172  PyImport_AppendInittab("zoo", init_zoo);
     173#else
    108174  PyEval_InitThreads();
     175#endif
    109176  Py_Initialize();
     177#if PY_MAJOR_VERSION >= 3
     178  PyEval_InitThreads();
     179  PyImport_ImportModule("zoo");
     180#else
    110181  init_zoo();
     182#endif
    111183  mainstate = PyThreadState_Swap(NULL);
    112184  PyEval_ReleaseLock();
     
    116188  tmp=getMap(s->content,"serviceProvider");
    117189  if(tmp!=NULL)
    118     pName = PyString_FromString(tmp->value);
     190    pName =
     191#if PY_MAJOR_VERSION >= 3
     192      PyUnicode_FromString(tmp->value);
     193#else
     194      PyString_FromString(tmp->value);
     195#endif
    119196  else{
    120197    map* err=createMap("text","Unable to parse serviceProvider please check your zcfg file.");
     
    145222      pValue = PyObject_CallObject(pFunc, pArgs);
    146223      if (pValue != NULL) {
     224#if PY_MAJOR_VERSION >= 3
     225        res=PyLong_AsLong(pValue);
     226#else
    147227        res=PyInt_AsLong(pValue);
     228#endif
    148229        freeMaps(real_outputs);
    149230        free(*real_outputs);
     
    153234        *real_outputs=mapsFromPyDict(arg3);
    154235#ifdef DEBUG
     236#if PY_MAJOR_VERSION >= 3
     237        fprintf(stderr,"Result of call: %i\n", PyLong_AsLong(pValue));
     238#else
    155239        fprintf(stderr,"Result of call: %i\n", PyInt_AsLong(pValue));
     240#endif
    156241        dumpMaps(inputs);
    157242        dumpMaps(*real_outputs);
     
    162247        PyObject *trace=PyObject_Str(pvalue);
    163248        char pbt[10240];
     249#if PY_MAJOR_VERSION >= 3
     250        if(PyUnicode_Check(trace))
     251          sprintf(pbt,"TRACE : %s",_PyUnicode_AsString(trace));
     252#else
    164253        if(PyString_Check(trace))
    165254          sprintf(pbt,"TRACE : %s",PyString_AsString(trace));
     255#endif
    166256        else
    167257          fprintf(stderr,"EMPTY TRACE ?");
    168258        trace=NULL;
    169259        trace=PyObject_Str(ptype);
     260#if PY_MAJOR_VERSION >= 3
     261        if(PyUnicode_Check(trace)){
     262#else
    170263        if(PyString_Check(trace)){
     264#endif
    171265          char *tpbt=strdup(pbt);
     266#if PY_MAJOR_VERSION >= 3
     267          sprintf(pbt,"%s\n%s\0",tpbt,_PyUnicode_AsString(trace));
     268#else
    172269          sprintf(pbt,"%s\n%s\0",tpbt,PyString_AsString(trace));
     270#endif
    173271          free(tpbt);
    174272        }
     
    177275       
    178276        char *tpbt=strdup(pbt);
     277#if PY_MAJOR_VERSION >= 3
     278        pName = PyUnicode_FromString("traceback");
     279#else
    179280        pName = PyString_FromString("traceback");
     281#endif
    180282        pModule = PyImport_Import(pName);
    181283        pArgs = PyTuple_New(1);
     
    185287        trace=NULL;
    186288        trace=PyObject_Str(pValue);
     289#if PY_MAJOR_VERSION >= 3
     290        if(PyUnicode_Check(trace))
     291          sprintf(pbt,"%s\nUnable to run your python process properly. Please check the following messages : %s",tpbt,_PyUnicode_AsString(trace));
     292#else
    187293        if(PyString_Check(trace))
    188294          sprintf(pbt,"%s\nUnable to run your python process properly. Please check the following messages : %s",tpbt,PyString_AsString(trace));
     295#endif
    189296        else
    190297          sprintf(pbt,"%s \n Unable to run your python process properly. Unable to provide any futher informations. %s",tpbt);
     
    214321    //exit(-1);
    215322  }
     323#if PY_MAJOR_VERSION < 3
    216324  PyGILState_Release(gstate);
    217325  PyEval_AcquireLock();
     326#endif
    218327  PyThreadState_Swap(mainstate);
    219328  Py_Finalize();
     
    226335  while(tmp!=NULL){
    227336    PyObject* value=(PyObject*)PyDict_FromMap(tmp->content);
    228     PyObject* name=PyString_FromString(tmp->name);
     337    PyObject* name=
     338#if PY_MAJOR_VERSION >= 3
     339      PyUnicode_FromString(tmp->name);
     340#else
     341      PyString_FromString(tmp->name);
     342#endif
    229343    if(PyDict_SetItem(res,name,value)<0){
    230344      fprintf(stderr,"Unable to set map value ...");
     
    245359  map* tmap=getMapType(tmp);
    246360  while(tmp!=NULL){
    247     PyObject* name=PyString_FromString(tmp->name);
     361    PyObject* name=
     362#if PY_MAJOR_VERSION >= 3
     363      PyUnicode_FromString(tmp->name);
     364#else
     365      PyString_FromString(tmp->name);
     366#endif
    248367    if(strcasecmp(tmp->name,"value")==0) {
    249368      if(isArray!=NULL){
     
    264383            PyObject* lsvalue;
    265384            if(sMap==NULL){
     385#if PY_MAJOR_VERSION >= 3
     386              lvalue=PyUnicode_FromString(vMap->value);
     387#else
    266388              lvalue=PyString_FromString(vMap->value);
     389#endif
    267390              lsvalue=Py_None;
    268391            }
    269392            else{
     393#if PY_MAJOR_VERSION >= 3
     394              lvalue=PyUnicode_FromStringAndSize(vMap->value,atoi(sMap->value));
     395              lsvalue=PyUnicode_FromString(sMap->value);
     396#else
    270397              lvalue=PyString_FromStringAndSize(vMap->value,atoi(sMap->value));
    271398              lsvalue=PyString_FromString(sMap->value);
     399#endif
    272400              hasSize=1;
    273401            }
     
    286414          PyObject* lmvalue;
    287415          if(mMap!=NULL){
     416#if PY_MAJOR_VERSION >= 3
     417            lmvalue=PyUnicode_FromString(mMap->value);
     418#else
    288419            lmvalue=PyString_FromString(mMap->value);
     420#endif
    289421          }else
    290422            lmvalue=Py_None;
     
    301433          return NULL;
    302434        }
     435#if PY_MAJOR_VERSION >= 3
     436        if(PyDict_SetItem(res,PyUnicode_FromString(tmap->name),mvalue)<0){
     437#else
    303438        if(PyDict_SetItem(res,PyString_FromString(tmap->name),mvalue)<0){
     439#endif
    304440          fprintf(stderr,"Unable to set key value pair...");
    305441          return NULL;
    306442        }
    307443        if(hasSize>0)
     444#if PY_MAJOR_VERSION >= 3
     445          if(PyDict_SetItem(res,PyUnicode_FromString("size"),svalue)<0){
     446#else
    308447          if(PyDict_SetItem(res,PyString_FromString("size"),svalue)<0){
     448#endif
    309449            fprintf(stderr,"Unable to set key value pair...");
    310450            return NULL;
     
    312452      }
    313453      else if(size!=NULL){
    314         PyObject* value=PyString_FromStringAndSize(tmp->value,atoi(size->value));
     454        PyObject* value=
     455#if PY_MAJOR_VERSION >= 3
     456          PyUnicode_FromStringAndSize(tmp->value,atoi(size->value));
     457#else
     458          PyString_FromStringAndSize(tmp->value,atoi(size->value));
     459#endif
    315460        if(PyDict_SetItem(res,name,value)<0){
    316461          fprintf(stderr,"Unable to set key value pair...");
     
    319464      }
    320465      else{
    321         PyObject* value=PyString_FromString(tmp->value);
     466        PyObject* value=
     467#if PY_MAJOR_VERSION >= 3
     468          PyUnicode_FromString(tmp->value);
     469#else
     470          PyString_FromString(tmp->value);
     471#endif
    322472        if(PyDict_SetItem(res,name,value)<0){
    323473          fprintf(stderr,"Unable to set key value pair...");
     
    328478    else{
    329479      if(PyDict_GetItem(res,name)==NULL){
    330         PyObject* value=PyString_FromString(tmp->value);
     480        PyObject* value=
     481#if PY_MAJOR_VERSION >= 3
     482          PyUnicode_FromString(tmp->value);
     483#else
     484          PyString_FromString(tmp->value);
     485#endif
    331486        if(PyDict_SetItem(res,name,value)<0){
    332487          fprintf(stderr,"Unable to set key value pair...");
     
    358513#endif
    359514    cursor=(maps*)malloc(MAPS_SIZE);
     515#if PY_MAJOR_VERSION >= 3
     516    cursor->name=_PyUnicode_AsString(key);
     517#else
    360518    cursor->name=PyString_AsString(key);
     519#endif
    361520    cursor->content=mapFromPyDict((PyDictObject*)value);
    362521#ifdef DEBUG
     
    391550            PyString_AsString(key),PyString_AsString(value));
    392551#endif
     552#if PY_MAJOR_VERSION >= 3
     553    if(strcmp(_PyUnicode_AsString(key),"value")==0){
     554#else
    393555    if(strcmp(PyString_AsString(key),"value")==0){
     556#endif
    394557      char *buffer=NULL;
    395558      Py_ssize_t size;
     559#if PY_MAJOR_VERSION >= 3
     560      buffer=_PyUnicode_AsStringAndSize(value,&size);
     561#else
    396562      PyString_AsStringAndSize(value,&buffer,&size);
     563#endif
    397564      if(res!=NULL){
     565#if PY_MAJOR_VERSION >= 3
     566        addToMap(res,_PyUnicode_AsString(key),"");
     567#else
    398568        addToMap(res,PyString_AsString(key),"");
     569#endif
    399570      }else{
     571#if PY_MAJOR_VERSION >= 3
     572        res=createMap(_PyUnicode_AsString(key),"");
     573#else
    400574        res=createMap(PyString_AsString(key),"");
     575#endif
    401576      }
    402577      map* tmpR=getMap(res,"value");
     
    409584      addToMap(res,"size",sin);
    410585    }else{
    411       if(res!=NULL)
     586      if(res!=NULL){
     587#if PY_MAJOR_VERSION >= 3
     588        addToMap(res,_PyUnicode_AsString(key),_PyUnicode_AsString(value));
     589#else
    412590        addToMap(res,PyString_AsString(key),PyString_AsString(value));
    413       else
    414         res=createMap(PyString_AsString(key),PyString_AsString(value));
     591#endif
     592      }
     593      else{
     594        res=
     595#if PY_MAJOR_VERSION >= 3
     596          createMap(_PyUnicode_AsString(key),_PyUnicode_AsString(value));
     597#else
     598          createMap(PyString_AsString(key),PyString_AsString(value));
     599#endif
     600      }
    415601    }
    416602  }
     
    428614    return NULL;
    429615  }
     616#if PY_MAJOR_VERSION >= 3
     617  return PyUnicode_FromString(_ss(str));
     618#else
    430619  return PyString_FromString(_ss(str));
     620#endif
    431621}
    432622
     
    456646    PyObject* lenv = PyMapping_GetItemString(confdict, "lenv");
    457647    if (lenv && PyMapping_Check(lenv)){
    458       PyObject* valobj = PyString_FromString(status);
     648      PyObject* valobj =
     649#if PY_MAJOR_VERSION >= 3
     650        PyUnicode_FromString(status);
     651#else
     652        PyString_FromString(status);
     653#endif
    459654      PyMapping_SetItemString(lenv, "status", valobj);
    460655      Py_DECREF(valobj);
  • trunk/zoo-project/zoo-kernel/zoo_service_loader.c

    r391 r392  
    22 * Author : Gérald FENOY
    33 *
    4  *  Copyright 2008-2012 GeoLabs SARL. All rights reserved.
     4 *  Copyright 2008-2013 GeoLabs SARL. All rights reserved.
    55 *
    66 * Permission is hereby granted, free of charge, to any person obtaining a copy
     
    272272#endif
    273273#endif
    274 
    275274    if( so != NULL ) {
    276275#ifdef DEBUG
     
    378377      char* errstr = dlerror();
    379378#endif
    380       sprintf(tmps,_("C Library can't be loaded %s \n"),errstr);
     379      sprintf(tmps,_("C Library can't be loaded %s"),errstr);
    381380      map* tmps1=createMap("text",tmps);
    382381      printExceptionReportResponse(m,tmps1);
     
    18961895  }
    18971896 
    1898   //if(CHECK_INET_HANDLE(hInternet))
     1897
     1898  //  if(CHECK_INET_HANDLE(hInternet))
    18991899  InternetCloseHandle(hInternet);
    19001900
     
    20392039      ;
    20402040#endif
    2041           char* toto=(char*)malloc((strlen(mapcs->name)+strlen(mapcs->value)+2)*sizeof(char));
     2041      char* toto=(char*)malloc((strlen(mapcs->name)+strlen(mapcs->value)+2)*sizeof(char));
    20422042      sprintf(toto,"%s=%s",mapcs->name,mapcs->value);
    2043           putenv(toto);
     2043      putenv(toto);
    20442044#ifdef DEBUG
    20452045      fflush(stderr);
     
    21112111      token=strtok_r(cgiCookie,";",&saveptr);
    21122112      while(token!=NULL){
    2113         if(strcasestr(token,"ID")!=NULL){
     2113        if(strcasestr(token,"ID=")!=NULL){
    21142114          if(tcook!=NULL)
    21152115            free(tcook);
     
    21202120      }
    21212121    }else{
    2122       if(strstr(cgiCookie,"=")!=NULL && strcasestr(cgiCookie,"ID")!=NULL){
     2122      if(strstr(cgiCookie,"=")!=NULL && strcasestr(cgiCookie,"ID=")!=NULL){
    21232123        tcook=strdup(cgiCookie);
    21242124        hasValidCookie=1;
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