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