Line data Source code
1 : /******************************************************************************
2 : * File : PostGISRasterDriver.cpp
3 : * Project: PostGIS Raster driver
4 : * Purpose: Implements PostGIS Raster driver class methods
5 : * Author: Jorge Arevalo, jorge.arevalo@deimos-space.com
6 : *
7 : * Last changes: $Id$
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2010, Jorge Arevalo, jorge.arevalo@deimos-space.com
11 : * Copyright (c) 2013, Even Rouault
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ******************************************************************************/
31 :
32 : #include <stdexcept>
33 :
34 : #include "postgisrasterdrivercore.h"
35 :
36 : /************************************************************************/
37 : /* PostGISRasterDriverIdentify() */
38 : /************************************************************************/
39 :
40 48144 : int PostGISRasterDriverIdentify(GDALOpenInfo *poOpenInfo)
41 :
42 : {
43 48144 : if (poOpenInfo->pszFilename == nullptr || poOpenInfo->fpL != nullptr ||
44 45212 : !STARTS_WITH_CI(poOpenInfo->pszFilename, "PG:"))
45 : {
46 48140 : return FALSE;
47 : }
48 :
49 : // Will avoid a OGR PostgreSQL connection string to be recognized as a
50 : // PostgisRaster one and later fail (#6034)
51 4 : if (strstr(poOpenInfo->pszFilename, " schemas=") ||
52 4 : strstr(poOpenInfo->pszFilename, " SCHEMAS="))
53 : {
54 0 : return FALSE;
55 : }
56 :
57 4 : return TRUE;
58 : }
59 :
60 : /**************************************************************
61 : * \brief Replace the single quotes by " in the input string
62 : *
63 : * Needed before tokenize function
64 : *************************************************************/
65 2 : static char *ReplaceSingleQuotes(const char *pszInput, int nLength)
66 : {
67 : int i;
68 2 : char *pszOutput = nullptr;
69 :
70 2 : if (nLength == -1)
71 2 : nLength = static_cast<int>(strlen(pszInput));
72 :
73 2 : pszOutput = static_cast<char *>(CPLCalloc(nLength + 1, sizeof(char)));
74 :
75 106 : for (i = 0; i < nLength; i++)
76 : {
77 104 : if (pszInput[i] == '\'')
78 12 : pszOutput[i] = '"';
79 : else
80 92 : pszOutput[i] = pszInput[i];
81 : }
82 :
83 2 : return pszOutput;
84 : }
85 :
86 : /***********************************************************************
87 : * \brief Split connection string into user, password, host, database...
88 : *
89 : * The parameters separated by spaces are return as a list of strings.
90 : * The function accepts all the PostgreSQL recognized parameter keywords.
91 : *
92 : * The returned list must be freed with CSLDestroy when no longer needed
93 : **********************************************************************/
94 2 : char **PostGISRasterParseConnectionString(const char *pszConnectionString)
95 : {
96 :
97 : /* Escape string following SQL scheme */
98 : char *pszEscapedConnectionString =
99 2 : ReplaceSingleQuotes(pszConnectionString, -1);
100 :
101 : /* Avoid PG: part */
102 2 : char *pszStartPos = strstr(pszEscapedConnectionString, ":") + 1;
103 :
104 : /* Tokenize */
105 : char **papszParams =
106 2 : CSLTokenizeString2(pszStartPos, " ", CSLT_HONOURSTRINGS);
107 :
108 : /* Free */
109 2 : CPLFree(pszEscapedConnectionString);
110 :
111 2 : return papszParams;
112 : }
113 :
114 : /************************************************************************/
115 : /* PostGISRasterDriverGetSubdatasetInfo() */
116 : /************************************************************************/
117 :
118 : struct PostGISRasterDriverSubdatasetInfo : public GDALSubdatasetInfo
119 : {
120 : public:
121 0 : explicit PostGISRasterDriverSubdatasetInfo(const std::string &fileName)
122 0 : : GDALSubdatasetInfo(fileName)
123 : {
124 0 : }
125 :
126 : // GDALSubdatasetInfo interface
127 : private:
128 0 : void parseFileName() override
129 : {
130 0 : if (!STARTS_WITH_CI(m_fileName.c_str(), "PG:"))
131 : {
132 0 : return;
133 : }
134 :
135 : char **papszParams =
136 0 : PostGISRasterParseConnectionString(m_fileName.c_str());
137 :
138 0 : const int nTableIdx = CSLFindName(papszParams, "table");
139 0 : if (nTableIdx != -1)
140 : {
141 0 : size_t nTableStart = m_fileName.find("table=");
142 0 : bool bHasQuotes{false};
143 : try
144 : {
145 0 : bHasQuotes = m_fileName.at(nTableStart + 6) == '\'';
146 : }
147 0 : catch (const std::out_of_range &)
148 : {
149 : // ignore error
150 : }
151 :
152 0 : m_subdatasetComponent = papszParams[nTableIdx];
153 :
154 0 : if (bHasQuotes)
155 : {
156 0 : m_subdatasetComponent.insert(6, "'");
157 0 : m_subdatasetComponent.push_back('\'');
158 : }
159 :
160 0 : m_driverPrefixComponent = "PG";
161 :
162 0 : size_t nPathLength = m_subdatasetComponent.length();
163 0 : if (nTableStart != 0)
164 : {
165 0 : nPathLength++;
166 0 : nTableStart--;
167 : }
168 :
169 0 : m_pathComponent = m_fileName;
170 0 : m_pathComponent.erase(nTableStart, nPathLength);
171 0 : m_pathComponent.erase(0, 3);
172 : }
173 :
174 0 : CSLDestroy(papszParams);
175 : }
176 : };
177 :
178 : static GDALSubdatasetInfo *
179 994 : PostGISRasterDriverGetSubdatasetInfo(const char *pszFileName)
180 : {
181 994 : if (STARTS_WITH_CI(pszFileName, "PG:"))
182 : {
183 : std::unique_ptr<GDALSubdatasetInfo> info =
184 0 : std::make_unique<PostGISRasterDriverSubdatasetInfo>(pszFileName);
185 0 : if (!info->GetSubdatasetComponent().empty() &&
186 0 : !info->GetPathComponent().empty())
187 : {
188 0 : return info.release();
189 : }
190 : }
191 994 : return nullptr;
192 : }
193 :
194 : /************************************************************************/
195 : /* PostGISRasterDriverSetCommonMetadata() */
196 : /************************************************************************/
197 :
198 1226 : void PostGISRasterDriverSetCommonMetadata(GDALDriver *poDriver)
199 : {
200 1226 : poDriver->SetDescription(DRIVER_NAME);
201 1226 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
202 1226 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "PostGIS Raster driver");
203 1226 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
204 :
205 1226 : poDriver->pfnIdentify = PostGISRasterDriverIdentify;
206 1226 : poDriver->pfnGetSubdatasetInfoFunc = PostGISRasterDriverGetSubdatasetInfo;
207 :
208 1226 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
209 1226 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
210 1226 : }
211 :
212 : /************************************************************************/
213 : /* DeclareDeferredPostGISRasterPlugin() */
214 : /************************************************************************/
215 :
216 : #ifdef PLUGIN_FILENAME
217 1520 : void DeclareDeferredPostGISRasterPlugin()
218 : {
219 1520 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
220 : {
221 301 : return;
222 : }
223 1219 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
224 : #ifdef PLUGIN_INSTALLATION_MESSAGE
225 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
226 : PLUGIN_INSTALLATION_MESSAGE);
227 : #endif
228 1219 : PostGISRasterDriverSetCommonMetadata(poDriver);
229 1219 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
230 : }
231 : #endif
|