1 : /******************************************************************************
2 : * $Id: ogrgpsbabelwritedatasource.cpp 25598 2013-02-05 22:24:35Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRGPSBabelWriteDataSource class.
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2010, Even Rouault
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 <string.h>
31 : #include "ogr_gpsbabel.h"
32 : #include "cpl_conv.h"
33 : #include "cpl_string.h"
34 : #include "cpl_error.h"
35 : #include "cpl_spawn.h"
36 :
37 : CPL_CVSID("$Id: ogrgpsbabelwritedatasource.cpp 25598 2013-02-05 22:24:35Z rouault $");
38 :
39 : /************************************************************************/
40 : /* OGRGPSBabelWriteDataSource() */
41 : /************************************************************************/
42 :
43 1 : OGRGPSBabelWriteDataSource::OGRGPSBabelWriteDataSource()
44 :
45 : {
46 1 : pszName = NULL;
47 1 : pszGPSBabelDriverName = NULL;
48 1 : pszFilename = NULL;
49 1 : poGPXDS = NULL;
50 1 : }
51 :
52 : /************************************************************************/
53 : /* ~OGRGPSBabelWriteDataSource() */
54 : /************************************************************************/
55 :
56 1 : OGRGPSBabelWriteDataSource::~OGRGPSBabelWriteDataSource()
57 :
58 : {
59 1 : if (poGPXDS)
60 1 : OGRDataSource::DestroyDataSource(poGPXDS);
61 :
62 1 : Convert();
63 :
64 1 : CPLFree(pszName);
65 1 : CPLFree(pszGPSBabelDriverName);
66 1 : CPLFree(pszFilename);
67 1 : }
68 :
69 : /************************************************************************/
70 : /* Convert() */
71 : /************************************************************************/
72 :
73 1 : int OGRGPSBabelWriteDataSource::Convert()
74 : {
75 1 : int nRet = -1;
76 1 : if (osTmpFileName.size() > 0 && pszFilename != NULL && pszGPSBabelDriverName != NULL)
77 : {
78 1 : if (OGRGPSBabelDataSource::IsSpecialFile(pszFilename))
79 : {
80 : /* Special file : don't try to open it */
81 : const char* const argv[] = { "gpsbabel", "-i", "gpx", "-f", "-",
82 0 : "-o", pszGPSBabelDriverName, "-F", pszFilename, NULL };
83 0 : VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
84 0 : if (tmpfp)
85 : {
86 0 : nRet = CPLSpawn(argv, tmpfp, NULL, TRUE);
87 :
88 0 : VSIFCloseL(tmpfp);
89 0 : tmpfp = NULL;
90 : }
91 : }
92 : else
93 : {
94 1 : VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
95 1 : if (fp == NULL)
96 : {
97 : CPLError(CE_Failure, CPLE_AppDefined,
98 0 : "Cannot open file %s", pszFilename);
99 : }
100 : else
101 : {
102 : const char* const argv[] = { "gpsbabel", "-i", "gpx", "-f", "-",
103 1 : "-o", pszGPSBabelDriverName, "-F", "-", NULL };
104 1 : VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
105 1 : if (tmpfp)
106 : {
107 1 : nRet = CPLSpawn(argv, tmpfp, fp, TRUE);
108 :
109 1 : VSIFCloseL(tmpfp);
110 1 : tmpfp = NULL;
111 : }
112 :
113 1 : VSIFCloseL(fp);
114 1 : fp = NULL;
115 : }
116 : }
117 :
118 1 : VSIUnlink(osTmpFileName.c_str());
119 1 : osTmpFileName = "";
120 : }
121 :
122 1 : return nRet == 0;
123 : }
124 :
125 : /************************************************************************/
126 : /* Create() */
127 : /************************************************************************/
128 :
129 1 : int OGRGPSBabelWriteDataSource::Create( const char * pszName,
130 : char **papszOptions )
131 : {
132 1 : OGRSFDriver* poGPXDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("GPX");
133 1 : if (poGPXDriver == NULL)
134 : {
135 0 : CPLError(CE_Failure, CPLE_AppDefined, "GPX driver is necessary for GPSBabel write support");
136 0 : return FALSE;
137 : }
138 :
139 1 : if (!EQUALN(pszName, "GPSBABEL:", 9))
140 : {
141 : const char* pszOptionGPSBabelDriverName =
142 0 : CSLFetchNameValue(papszOptions, "GPSBABEL_DRIVER");
143 0 : if (pszOptionGPSBabelDriverName != NULL)
144 0 : pszGPSBabelDriverName = CPLStrdup(pszOptionGPSBabelDriverName);
145 : else
146 : {
147 0 : CPLError(CE_Failure, CPLE_AppDefined, "GPSBABEL_DRIVER dataset creation option expected");
148 0 : return FALSE;
149 : }
150 :
151 0 : pszFilename = CPLStrdup(pszName);
152 : }
153 : else
154 : {
155 1 : const char* pszSep = strchr(pszName + 9, ':');
156 1 : if (pszSep == NULL)
157 : {
158 : CPLError(CE_Failure, CPLE_AppDefined,
159 0 : "Wrong syntax. Expected GPSBabel:driver_name[,options]*:file_name");
160 0 : return FALSE;
161 : }
162 :
163 1 : pszGPSBabelDriverName = CPLStrdup(pszName + 9);
164 1 : *(strchr(pszGPSBabelDriverName, ':')) = '\0';
165 :
166 1 : pszFilename = CPLStrdup(pszSep+1);
167 : }
168 :
169 : /* A bit of validation to avoid command line injection */
170 1 : if (!OGRGPSBabelDataSource::IsValidDriverName(pszGPSBabelDriverName))
171 0 : return FALSE;
172 :
173 1 : const char* pszOptionUseTempFile = CSLFetchNameValue(papszOptions, "USE_TEMPFILE");
174 1 : if (pszOptionUseTempFile == NULL)
175 1 : pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", NULL);
176 1 : if (pszOptionUseTempFile && CSLTestBoolean(pszOptionUseTempFile))
177 0 : osTmpFileName = CPLGenerateTempFilename(NULL);
178 : else
179 1 : osTmpFileName.Printf("/vsimem/ogrgpsbabeldatasource_%p", this);
180 :
181 1 : poGPXDS = poGPXDriver->CreateDataSource(osTmpFileName.c_str(), papszOptions);
182 1 : if (poGPXDS == NULL)
183 0 : return FALSE;
184 :
185 1 : this->pszName = CPLStrdup(pszName);
186 :
187 1 : return TRUE;
188 : }
189 :
190 : /************************************************************************/
191 : /* CreateLayer() */
192 : /************************************************************************/
193 :
194 1 : OGRLayer * OGRGPSBabelWriteDataSource::CreateLayer( const char * pszLayerName,
195 : OGRSpatialReference *poSRS,
196 : OGRwkbGeometryType eType,
197 : char ** papszOptions )
198 : {
199 1 : if (poGPXDS)
200 1 : return poGPXDS->CreateLayer(pszLayerName, poSRS, eType, papszOptions);
201 0 : return NULL;
202 : }
203 :
204 :
205 : /************************************************************************/
206 : /* TestCapability() */
207 : /************************************************************************/
208 :
209 0 : int OGRGPSBabelWriteDataSource::TestCapability( const char * pszCap )
210 :
211 : {
212 0 : if( EQUAL(pszCap,ODsCCreateLayer) )
213 0 : return TRUE;
214 0 : return FALSE;
215 : }
216 :
217 : /************************************************************************/
218 : /* GetLayer() */
219 : /************************************************************************/
220 :
221 0 : OGRLayer *OGRGPSBabelWriteDataSource::GetLayer( int iLayer )
222 :
223 : {
224 0 : if (poGPXDS)
225 0 : return poGPXDS->GetLayer(iLayer);
226 0 : return NULL;
227 : }
228 :
229 : /************************************************************************/
230 : /* GetLayerCount() */
231 : /************************************************************************/
232 :
233 0 : int OGRGPSBabelWriteDataSource::GetLayerCount()
234 :
235 : {
236 0 : if (poGPXDS)
237 0 : return poGPXDS->GetLayerCount();
238 0 : return 0;
239 : }
|