1 /******************************************************************************
2  *
3  * Project:  OpenGIS Simple Features Reference Implementation
4  * Purpose:  Implements Personal Geodatabase driver.
5  * Author:   Even Rouault, <even dot rouault at spatialys.com>
6  *
7  ******************************************************************************
8  * Copyright (c) 2011-2012, Even Rouault <even dot rouault at spatialys.com>
9  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  ****************************************************************************/
29 
30 #include "ogr_geomedia.h"
31 #include "cpl_conv.h"
32 
33 CPL_CVSID("$Id: ogrgeomediadriver.cpp 2dc350b1c738a002da1ec5c4cbe3e42fec4069dc 2021-03-04 16:15:13 +0100 Even Rouault $")
34 
35 /************************************************************************/
36 /*                          ~OGRODBCDriver()                            */
37 /************************************************************************/
38 
~OGRGeomediaDriver()39 OGRGeomediaDriver::~OGRGeomediaDriver()
40 
41 {
42 }
43 
44 /************************************************************************/
45 /*                              GetName()                               */
46 /************************************************************************/
47 
GetName()48 const char *OGRGeomediaDriver::GetName()
49 
50 {
51     return "Geomedia";
52 }
53 
54 /************************************************************************/
55 /*                                Open()                                */
56 /************************************************************************/
57 
Open(const char * pszFilename,int bUpdate)58 OGRDataSource *OGRGeomediaDriver::Open( const char * pszFilename,
59                                     int bUpdate )
60 
61 {
62     if( STARTS_WITH_CI(pszFilename, "WALK:") )
63         return nullptr;
64 
65     if( STARTS_WITH_CI(pszFilename, "PGEO:") )
66         return nullptr;
67 
68     if( !STARTS_WITH_CI(pszFilename, "GEOMEDIA:")
69         && !EQUAL(CPLGetExtension(pszFilename),"mdb") )
70         return nullptr;
71 
72     /* Disabling the attempt to guess if a MDB file is a Geomedia database */
73     /* or not. See similar fix in PGeo driver for rationale. */
74 #if 0
75     if( !STARTS_WITH_CI(pszFilename, "GEOMEDIA:") &&
76         EQUAL(CPLGetExtension(pszFilename),"mdb") )
77     {
78         VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
79         if (!fp)
80             return NULL;
81         GByte* pabyHeader = (GByte*) CPLMalloc(100000);
82         VSIFReadL(pabyHeader, 100000, 1, fp);
83         VSIFCloseL(fp);
84 
85         /* Look for GAliasTable table */
86         const GByte pabyNeedle[] = { 'G', 0, 'A', 0, 'l', 0, 'i', 0, 'a', 0, 's', 0, 'T', 0, 'a', 0, 'b', 0, 'l', 0, 'e'};
87         int bFound = FALSE;
88         for(int i=0;i<100000 - (int)sizeof(pabyNeedle);i++)
89         {
90             if (memcmp(pabyHeader + i, pabyNeedle, sizeof(pabyNeedle)) == 0)
91             {
92                 bFound = TRUE;
93                 break;
94             }
95         }
96         CPLFree(pabyHeader);
97         if (!bFound)
98             return NULL;
99     }
100 #endif
101 
102 #ifndef WIN32
103     // Try to register MDB Tools driver
104     //
105     // ODBCINST.INI NOTE:
106     // This operation requires write access to odbcinst.ini file
107     // located in directory pointed by ODBCINISYS variable.
108     // Usually, it points to /etc, so non-root users can overwrite this
109     // setting ODBCINISYS with location they have write access to, e.g.:
110     // $ export ODBCINISYS=$HOME/etc
111     // $ touch $ODBCINISYS/odbcinst.ini
112     //
113     // See: http://www.unixodbc.org/internals.html
114     //
115     if ( !InstallMdbDriver() )
116     {
117         CPLError( CE_Warning, CPLE_AppDefined,
118                   "Unable to install MDB driver for ODBC, MDB access may not supported.\n" );
119     }
120     else
121         CPLDebug( "Geomedia", "MDB Tools driver installed successfully!");
122 
123 #endif /* ndef WIN32 */
124 
125     // Open data source
126     OGRGeomediaDataSource *poDS = new OGRGeomediaDataSource();
127 
128     if( !poDS->Open( pszFilename, bUpdate, TRUE ) )
129     {
130         delete poDS;
131         return nullptr;
132     }
133 
134     if( !GDALIsDriverDeprecatedForGDAL35StillEnabled("GEOMEDIA") )
135     {
136         delete poDS;
137         return nullptr;
138     }
139 
140     return poDS;
141 }
142 
143 /************************************************************************/
144 /*                           TestCapability()                           */
145 /************************************************************************/
146 
TestCapability(CPL_UNUSED const char * pszCap)147 int OGRGeomediaDriver::TestCapability( CPL_UNUSED const char * pszCap )
148 {
149     return FALSE;
150 }
151 
152 /************************************************************************/
153 /*                           RegisterOGRODBC()                          */
154 /************************************************************************/
155 
RegisterOGRGeomedia()156 void RegisterOGRGeomedia()
157 
158 {
159     OGRSFDriver* poDriver = new OGRGeomediaDriver;
160     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Geomedia .mdb" );
161     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mdb" );
162     poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drivers/vector/geomedia.html" );
163     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
164 }
165