Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements OGRGPSBabelWriteDataSource class.
5 : * Author: Even Rouault, <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include <cstring>
30 : #include "cpl_conv.h"
31 : #include "cpl_string.h"
32 : #include "cpl_error.h"
33 : #include "cpl_spawn.h"
34 :
35 : #include "ogr_gpsbabel.h"
36 :
37 : /************************************************************************/
38 : /* OGRGPSBabelWriteDataSource() */
39 : /************************************************************************/
40 :
41 1 : OGRGPSBabelWriteDataSource::OGRGPSBabelWriteDataSource()
42 : : pszName(nullptr), pszGPSBabelDriverName(nullptr), pszFilename(nullptr),
43 1 : poGPXDS(nullptr)
44 : {
45 1 : }
46 :
47 : /************************************************************************/
48 : /* ~OGRGPSBabelWriteDataSource() */
49 : /************************************************************************/
50 :
51 2 : OGRGPSBabelWriteDataSource::~OGRGPSBabelWriteDataSource()
52 :
53 : {
54 1 : if (poGPXDS)
55 1 : GDALClose(poGPXDS);
56 :
57 1 : Convert();
58 :
59 1 : CPLFree(pszName);
60 1 : CPLFree(pszGPSBabelDriverName);
61 1 : CPLFree(pszFilename);
62 2 : }
63 :
64 : /************************************************************************/
65 : /* Convert() */
66 : /************************************************************************/
67 :
68 1 : bool OGRGPSBabelWriteDataSource::Convert()
69 : {
70 1 : int nRet = -1;
71 2 : if (!osTmpFileName.empty() && pszFilename != nullptr &&
72 1 : pszGPSBabelDriverName != nullptr)
73 : {
74 1 : if (OGRGPSBabelDataSource::IsSpecialFile(pszFilename))
75 : {
76 : /* Special file : don't try to open it */
77 0 : VSILFILE *tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
78 0 : if (tmpfp)
79 : {
80 0 : const char *const argv[] = {"gpsbabel",
81 : "-i",
82 : "gpx",
83 : "-f",
84 : "-",
85 : "-o",
86 0 : pszGPSBabelDriverName,
87 : "-F",
88 0 : pszFilename,
89 0 : nullptr};
90 0 : nRet = CPLSpawn(argv, tmpfp, nullptr, TRUE);
91 :
92 0 : VSIFCloseL(tmpfp);
93 0 : tmpfp = nullptr;
94 : }
95 : }
96 : else
97 : {
98 1 : VSILFILE *fp = VSIFOpenL(pszFilename, "wb");
99 1 : if (fp == nullptr)
100 : {
101 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot open file %s",
102 : pszFilename);
103 : }
104 : else
105 : {
106 1 : VSILFILE *tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
107 1 : if (tmpfp)
108 : {
109 1 : const char *const argv[] = {"gpsbabel",
110 : "-i",
111 : "gpx",
112 : "-f",
113 : "-",
114 : "-o",
115 1 : pszGPSBabelDriverName,
116 : "-F",
117 : "-",
118 1 : nullptr};
119 1 : nRet = CPLSpawn(argv, tmpfp, fp, TRUE);
120 :
121 1 : VSIFCloseL(tmpfp);
122 1 : tmpfp = nullptr;
123 : }
124 :
125 1 : VSIFCloseL(fp);
126 1 : fp = nullptr;
127 : }
128 : }
129 :
130 1 : VSIUnlink(osTmpFileName.c_str());
131 1 : osTmpFileName = "";
132 : }
133 :
134 1 : return nRet == 0;
135 : }
136 :
137 : /************************************************************************/
138 : /* Create() */
139 : /************************************************************************/
140 :
141 1 : int OGRGPSBabelWriteDataSource::Create(const char *pszNameIn,
142 : char **papszOptions)
143 : {
144 : GDALDriver *poGPXDriver =
145 1 : OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("GPX");
146 1 : if (poGPXDriver == nullptr)
147 : {
148 0 : CPLError(CE_Failure, CPLE_AppDefined,
149 : "GPX driver is necessary for GPSBabel write support");
150 0 : return FALSE;
151 : }
152 :
153 1 : if (!STARTS_WITH_CI(pszNameIn, "GPSBABEL:"))
154 : {
155 : const char *pszOptionGPSBabelDriverName =
156 0 : CSLFetchNameValue(papszOptions, "GPSBABEL_DRIVER");
157 0 : if (pszOptionGPSBabelDriverName != nullptr)
158 0 : pszGPSBabelDriverName = CPLStrdup(pszOptionGPSBabelDriverName);
159 : else
160 : {
161 0 : CPLError(CE_Failure, CPLE_AppDefined,
162 : "GPSBABEL_DRIVER dataset creation option expected");
163 0 : return FALSE;
164 : }
165 :
166 0 : pszFilename = CPLStrdup(pszNameIn);
167 : }
168 : else
169 : {
170 1 : const char *pszSep = strchr(pszNameIn + 9, ':');
171 1 : if (pszSep == nullptr)
172 : {
173 0 : CPLError(CE_Failure, CPLE_AppDefined,
174 : "Wrong syntax. Expected GPSBabel:driver_name[,options]*:"
175 : "file_name");
176 0 : return FALSE;
177 : }
178 :
179 1 : pszGPSBabelDriverName = CPLStrdup(pszNameIn + 9);
180 1 : *(strchr(pszGPSBabelDriverName, ':')) = '\0';
181 :
182 1 : pszFilename = CPLStrdup(pszSep + 1);
183 : }
184 :
185 : /* A bit of validation to avoid command line injection */
186 1 : if (!OGRGPSBabelDataSource::IsValidDriverName(pszGPSBabelDriverName))
187 0 : return FALSE;
188 :
189 : const char *pszOptionUseTempFile =
190 1 : CSLFetchNameValue(papszOptions, "USE_TEMPFILE");
191 1 : if (pszOptionUseTempFile == nullptr)
192 1 : pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", nullptr);
193 1 : if (pszOptionUseTempFile && CPLTestBool(pszOptionUseTempFile))
194 0 : osTmpFileName = CPLGenerateTempFilename(nullptr);
195 : else
196 1 : osTmpFileName.Printf("/vsimem/ogrgpsbabeldatasource_%p", this);
197 :
198 1 : poGPXDS = poGPXDriver->Create(osTmpFileName.c_str(), 0, 0, 0, GDT_Unknown,
199 : papszOptions);
200 1 : if (poGPXDS == nullptr)
201 0 : return FALSE;
202 :
203 1 : pszName = CPLStrdup(pszNameIn);
204 :
205 1 : return TRUE;
206 : }
207 :
208 : /************************************************************************/
209 : /* ICreateLayer() */
210 : /************************************************************************/
211 :
212 1 : OGRLayer *OGRGPSBabelWriteDataSource::ICreateLayer(
213 : const char *pszLayerName, const OGRGeomFieldDefn *poGeomFieldDefn,
214 : CSLConstList papszOptions)
215 : {
216 1 : if (poGPXDS)
217 1 : return poGPXDS->CreateLayer(pszLayerName, poGeomFieldDefn,
218 1 : papszOptions);
219 0 : return nullptr;
220 : }
221 :
222 : /************************************************************************/
223 : /* TestCapability() */
224 : /************************************************************************/
225 :
226 0 : int OGRGPSBabelWriteDataSource::TestCapability(const char *pszCap)
227 :
228 : {
229 0 : if (EQUAL(pszCap, ODsCCreateLayer))
230 0 : return TRUE;
231 :
232 0 : return FALSE;
233 : }
234 :
235 : /************************************************************************/
236 : /* GetLayer() */
237 : /************************************************************************/
238 :
239 0 : OGRLayer *OGRGPSBabelWriteDataSource::GetLayer(int iLayer)
240 :
241 : {
242 0 : if (poGPXDS)
243 0 : return poGPXDS->GetLayer(iLayer);
244 :
245 0 : return nullptr;
246 : }
247 :
248 : /************************************************************************/
249 : /* GetLayerCount() */
250 : /************************************************************************/
251 :
252 0 : int OGRGPSBabelWriteDataSource::GetLayerCount()
253 :
254 : {
255 0 : if (poGPXDS)
256 0 : return poGPXDS->GetLayerCount();
257 :
258 0 : return 0;
259 : }
|