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 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include <cstring>
14 : #include "cpl_conv.h"
15 : #include "cpl_string.h"
16 : #include "cpl_error.h"
17 : #include "cpl_spawn.h"
18 :
19 : #include "ogr_gpsbabel.h"
20 :
21 : /************************************************************************/
22 : /* OGRGPSBabelWriteDataSource() */
23 : /************************************************************************/
24 :
25 1 : OGRGPSBabelWriteDataSource::OGRGPSBabelWriteDataSource()
26 1 : : pszGPSBabelDriverName(nullptr), pszFilename(nullptr), poGPXDS(nullptr)
27 : {
28 1 : }
29 :
30 : /************************************************************************/
31 : /* ~OGRGPSBabelWriteDataSource() */
32 : /************************************************************************/
33 :
34 2 : OGRGPSBabelWriteDataSource::~OGRGPSBabelWriteDataSource()
35 :
36 : {
37 1 : if (poGPXDS)
38 1 : GDALClose(poGPXDS);
39 :
40 1 : Convert();
41 :
42 1 : CPLFree(pszGPSBabelDriverName);
43 1 : CPLFree(pszFilename);
44 2 : }
45 :
46 : /************************************************************************/
47 : /* Convert() */
48 : /************************************************************************/
49 :
50 1 : bool OGRGPSBabelWriteDataSource::Convert()
51 : {
52 1 : int nRet = -1;
53 2 : if (!osTmpFileName.empty() && pszFilename != nullptr &&
54 1 : pszGPSBabelDriverName != nullptr)
55 : {
56 1 : if (OGRGPSBabelDataSource::IsSpecialFile(pszFilename))
57 : {
58 : /* Special file : don't try to open it */
59 0 : VSILFILE *tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
60 0 : if (tmpfp)
61 : {
62 0 : const char *const argv[] = {"gpsbabel",
63 : "-i",
64 : "gpx",
65 : "-f",
66 : "-",
67 : "-o",
68 0 : pszGPSBabelDriverName,
69 : "-F",
70 0 : pszFilename,
71 0 : nullptr};
72 0 : nRet = CPLSpawn(argv, tmpfp, nullptr, TRUE);
73 :
74 0 : VSIFCloseL(tmpfp);
75 0 : tmpfp = nullptr;
76 : }
77 : }
78 : else
79 : {
80 1 : VSILFILE *fp = VSIFOpenL(pszFilename, "wb");
81 1 : if (fp == nullptr)
82 : {
83 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot open file %s",
84 : pszFilename);
85 : }
86 : else
87 : {
88 1 : VSILFILE *tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
89 1 : if (tmpfp)
90 : {
91 1 : const char *const argv[] = {"gpsbabel",
92 : "-i",
93 : "gpx",
94 : "-f",
95 : "-",
96 : "-o",
97 1 : pszGPSBabelDriverName,
98 : "-F",
99 : "-",
100 1 : nullptr};
101 1 : nRet = CPLSpawn(argv, tmpfp, fp, TRUE);
102 :
103 1 : VSIFCloseL(tmpfp);
104 1 : tmpfp = nullptr;
105 : }
106 :
107 1 : VSIFCloseL(fp);
108 1 : fp = nullptr;
109 : }
110 : }
111 :
112 1 : VSIUnlink(osTmpFileName.c_str());
113 1 : osTmpFileName = "";
114 : }
115 :
116 1 : return nRet == 0;
117 : }
118 :
119 : /************************************************************************/
120 : /* Create() */
121 : /************************************************************************/
122 :
123 1 : int OGRGPSBabelWriteDataSource::Create(const char *pszNameIn,
124 : char **papszOptions)
125 : {
126 : GDALDriver *poGPXDriver =
127 1 : OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("GPX");
128 1 : if (poGPXDriver == nullptr)
129 : {
130 0 : CPLError(CE_Failure, CPLE_AppDefined,
131 : "GPX driver is necessary for GPSBabel write support");
132 0 : return FALSE;
133 : }
134 :
135 1 : if (!STARTS_WITH_CI(pszNameIn, "GPSBABEL:"))
136 : {
137 : const char *pszOptionGPSBabelDriverName =
138 0 : CSLFetchNameValue(papszOptions, "GPSBABEL_DRIVER");
139 0 : if (pszOptionGPSBabelDriverName != nullptr)
140 0 : pszGPSBabelDriverName = CPLStrdup(pszOptionGPSBabelDriverName);
141 : else
142 : {
143 0 : CPLError(CE_Failure, CPLE_AppDefined,
144 : "GPSBABEL_DRIVER dataset creation option expected");
145 0 : return FALSE;
146 : }
147 :
148 0 : pszFilename = CPLStrdup(pszNameIn);
149 : }
150 : else
151 : {
152 1 : const char *pszSep = strchr(pszNameIn + 9, ':');
153 1 : if (pszSep == nullptr)
154 : {
155 0 : CPLError(CE_Failure, CPLE_AppDefined,
156 : "Wrong syntax. Expected GPSBabel:driver_name[,options]*:"
157 : "file_name");
158 0 : return FALSE;
159 : }
160 :
161 1 : pszGPSBabelDriverName = CPLStrdup(pszNameIn + 9);
162 1 : *(strchr(pszGPSBabelDriverName, ':')) = '\0';
163 :
164 1 : pszFilename = CPLStrdup(pszSep + 1);
165 : }
166 :
167 : /* A bit of validation to avoid command line injection */
168 1 : if (!OGRGPSBabelDataSource::IsValidDriverName(pszGPSBabelDriverName))
169 0 : return FALSE;
170 :
171 : const char *pszOptionUseTempFile =
172 1 : CSLFetchNameValue(papszOptions, "USE_TEMPFILE");
173 1 : if (pszOptionUseTempFile == nullptr)
174 1 : pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", nullptr);
175 1 : if (pszOptionUseTempFile && CPLTestBool(pszOptionUseTempFile))
176 0 : osTmpFileName = CPLGenerateTempFilename(nullptr);
177 : else
178 1 : osTmpFileName = VSIMemGenerateHiddenFilename("gpsbabel");
179 :
180 1 : poGPXDS = poGPXDriver->Create(osTmpFileName.c_str(), 0, 0, 0, GDT_Unknown,
181 : papszOptions);
182 1 : if (poGPXDS == nullptr)
183 0 : return FALSE;
184 :
185 1 : return TRUE;
186 : }
187 :
188 : /************************************************************************/
189 : /* ICreateLayer() */
190 : /************************************************************************/
191 :
192 1 : OGRLayer *OGRGPSBabelWriteDataSource::ICreateLayer(
193 : const char *pszLayerName, const OGRGeomFieldDefn *poGeomFieldDefn,
194 : CSLConstList papszOptions)
195 : {
196 1 : if (poGPXDS)
197 1 : return poGPXDS->CreateLayer(pszLayerName, poGeomFieldDefn,
198 1 : papszOptions);
199 0 : return nullptr;
200 : }
201 :
202 : /************************************************************************/
203 : /* TestCapability() */
204 : /************************************************************************/
205 :
206 0 : int OGRGPSBabelWriteDataSource::TestCapability(const char *pszCap)
207 :
208 : {
209 0 : if (EQUAL(pszCap, ODsCCreateLayer))
210 0 : return TRUE;
211 :
212 0 : return FALSE;
213 : }
214 :
215 : /************************************************************************/
216 : /* GetLayer() */
217 : /************************************************************************/
218 :
219 0 : OGRLayer *OGRGPSBabelWriteDataSource::GetLayer(int iLayer)
220 :
221 : {
222 0 : if (poGPXDS)
223 0 : return poGPXDS->GetLayer(iLayer);
224 :
225 0 : return nullptr;
226 : }
227 :
228 : /************************************************************************/
229 : /* GetLayerCount() */
230 : /************************************************************************/
231 :
232 0 : int OGRGPSBabelWriteDataSource::GetLayerCount()
233 :
234 : {
235 0 : if (poGPXDS)
236 0 : return poGPXDS->GetLayerCount();
237 :
238 0 : return 0;
239 : }
|