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