1 : /******************************************************************************
2 : * $Id: rpftocfile.cpp 20996 2010-10-28 18:38:15Z rouault $
3 : *
4 : * Project: RPF A.TOC read Library
5 : * Purpose: Module responsible for opening a RPF TOC file, populating RPFToc
6 : * structure
7 : * Author: Even Rouault, even.rouault at mines-paris.org
8 : *
9 : **********************************************************************
10 : * Copyright (c) 2007, Even Rouault
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : /* Portions of code are placed under the following copyright : */
32 : /*
33 : ******************************************************************************
34 : * Copyright (C) 1995 Logiciels et Applications Scientifiques (L.A.S.) Inc
35 : * Permission to use, copy, modify and distribute this software and
36 : * its documentation for any purpose and without fee is hereby granted,
37 : * provided that the above copyright notice appear in all copies, that
38 : * both the copyright notice and this permission notice appear in
39 : * supporting documentation, and that the name of L.A.S. Inc not be used
40 : * in advertising or publicity pertaining to distribution of the software
41 : * without specific, written prior permission. L.A.S. Inc. makes no
42 : * representations about the suitability of this software for any purpose.
43 : * It is provided "as is" without express or implied warranty.
44 : ******************************************************************************
45 : */
46 :
47 : #include "rpftoclib.h"
48 : #include "cpl_vsi.h"
49 : #include "cpl_conv.h"
50 : #include "cpl_string.h"
51 :
52 : CPL_CVSID("$Id: rpftocfile.cpp 20996 2010-10-28 18:38:15Z rouault $");
53 :
54 : /************************************************************************/
55 : /* RPFTOCTrim() */
56 : /************************************************************************/
57 :
58 80 : static void RPFTOCTrim(char* str)
59 : {
60 80 : char* c = str;
61 : int i;
62 80 : if (str == NULL || *str == 0)
63 0 : return;
64 :
65 160 : while(*c == ' ')
66 : {
67 0 : c++;
68 : }
69 80 : if (c != str)
70 : {
71 0 : memmove(str, c, strlen(c)+1);
72 : }
73 :
74 80 : i = strlen(str) - 1;
75 192 : while (i >= 0 && str[i] == ' ')
76 : {
77 32 : str[i] = 0;
78 32 : i--;
79 : }
80 : }
81 :
82 : /************************************************************************/
83 : /* RPFTOCRead() */
84 : /************************************************************************/
85 :
86 :
87 0 : RPFToc* RPFTOCRead(const char* pszFilename, NITFFile* psFile)
88 : {
89 : int nTRESize;
90 : const char* pachTRE = NITFFindTRE( psFile->pachTRE, psFile->nTREBytes,
91 0 : "RPFHDR", &nTRESize );
92 0 : if (pachTRE == NULL)
93 : {
94 : CPLError( CE_Failure, CPLE_NotSupported,
95 0 : "Invalid TOC file. Can't find RPFHDR." );
96 0 : return NULL;
97 : }
98 :
99 0 : if (nTRESize != 48)
100 : {
101 : CPLError( CE_Failure, CPLE_NotSupported,
102 0 : "RPFHDR TRE wrong size." );
103 0 : return NULL;
104 : }
105 :
106 0 : return RPFTOCReadFromBuffer(pszFilename, psFile->fp, pachTRE);
107 : }
108 :
109 :
110 : /* This function is directly inspired by function parse_toc coming from ogdi/driver/rpf/utils.c */
111 :
112 16 : RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char* tocHeader)
113 : {
114 : int i, j;
115 : unsigned int locationSectionPhysicalLocation;
116 :
117 : int nSections;
118 16 : unsigned int boundaryRectangleSectionSubHeaderPhysIndex = 0;
119 16 : unsigned int boundaryRectangleTablePhysIndex = 0;
120 16 : unsigned int frameFileIndexSectionSubHeaderPhysIndex = 0;
121 16 : unsigned int frameFileIndexSubsectionPhysIndex = 0;
122 :
123 : unsigned int boundaryRectangleTableOffset;
124 : unsigned short boundaryRectangleCount;
125 :
126 : unsigned int frameIndexTableOffset;
127 : unsigned int nFrameFileIndexRecords;
128 : unsigned short nFrameFilePathnameRecords;
129 : unsigned short frameFileIndexRecordLength;
130 :
131 16 : int newBoundaryId = 0;
132 :
133 : RPFToc* toc;
134 :
135 16 : tocHeader += 1; /* skip endian */
136 16 : tocHeader += 2; /* skip header length */
137 16 : tocHeader += 12; /* skip file name : this should be A.TOC (padded) */
138 16 : tocHeader += 1; /* skip new */
139 16 : tocHeader += 15; /* skip standard_num */
140 16 : tocHeader += 8; /* skip standard_date */
141 16 : tocHeader += 1; /* skip classification */
142 16 : tocHeader += 2; /* skip country */
143 16 : tocHeader += 2; /* skip release */
144 :
145 16 : memcpy(&locationSectionPhysicalLocation, tocHeader, sizeof(unsigned int));
146 16 : CPL_MSBPTR32(&locationSectionPhysicalLocation);
147 :
148 16 : if( VSIFSeekL( fp, locationSectionPhysicalLocation, SEEK_SET ) != 0)
149 : {
150 : CPLError( CE_Failure, CPLE_NotSupported,
151 : "Invalid TOC file. Unable to seek to locationSectionPhysicalLocation at offset %d.",
152 0 : locationSectionPhysicalLocation );
153 0 : return NULL;
154 : }
155 :
156 16 : NITFLocation* pasLocations = NITFReadRPFLocationTable(fp, &nSections);
157 :
158 80 : for (i = 0; i < nSections; i++)
159 : {
160 64 : if (pasLocations[i].nLocId == LID_BoundaryRectangleSectionSubheader)
161 : {
162 16 : boundaryRectangleSectionSubHeaderPhysIndex = pasLocations[i].nLocOffset;
163 : }
164 48 : else if (pasLocations[i].nLocId == LID_BoundaryRectangleTable)
165 : {
166 16 : boundaryRectangleTablePhysIndex = pasLocations[i].nLocOffset;
167 : }
168 32 : else if (pasLocations[i].nLocId == LID_FrameFileIndexSectionSubHeader)
169 : {
170 16 : frameFileIndexSectionSubHeaderPhysIndex = pasLocations[i].nLocOffset;
171 : }
172 16 : else if (pasLocations[i].nLocId == LID_FrameFileIndexSubsection)
173 : {
174 16 : frameFileIndexSubsectionPhysIndex = pasLocations[i].nLocOffset;
175 : }
176 : }
177 :
178 16 : CPLFree(pasLocations);
179 :
180 16 : if (boundaryRectangleSectionSubHeaderPhysIndex == 0)
181 : {
182 : CPLError( CE_Failure, CPLE_NotSupported,
183 0 : "Invalid TOC file. Can't find LID_BoundaryRectangleSectionSubheader." );
184 0 : return NULL;
185 : }
186 16 : if (boundaryRectangleTablePhysIndex == 0)
187 : {
188 : CPLError( CE_Failure, CPLE_NotSupported,
189 0 : "Invalid TOC file. Can't find LID_BoundaryRectangleTable." );
190 0 : return NULL;
191 : }
192 16 : if (frameFileIndexSectionSubHeaderPhysIndex == 0)
193 : {
194 : CPLError( CE_Failure, CPLE_NotSupported,
195 0 : "Invalid TOC file. Can't find LID_FrameFileIndexSectionSubHeader." );
196 0 : return NULL;
197 : }
198 16 : if (frameFileIndexSubsectionPhysIndex == 0)
199 : {
200 : CPLError( CE_Failure, CPLE_NotSupported,
201 0 : "Invalid TOC file. Can't find LID_FrameFileIndexSubsection." );
202 0 : return NULL;
203 : }
204 :
205 16 : if( VSIFSeekL( fp, boundaryRectangleSectionSubHeaderPhysIndex, SEEK_SET ) != 0)
206 : {
207 : CPLError( CE_Failure, CPLE_NotSupported,
208 : "Invalid TOC file. Unable to seek to boundaryRectangleSectionSubHeaderPhysIndex at offset %d.",
209 0 : boundaryRectangleSectionSubHeaderPhysIndex );
210 0 : return NULL;
211 : }
212 :
213 16 : VSIFReadL( &boundaryRectangleTableOffset, 1, sizeof(boundaryRectangleTableOffset), fp);
214 16 : CPL_MSBPTR32( &boundaryRectangleTableOffset );
215 :
216 16 : VSIFReadL( &boundaryRectangleCount, 1, sizeof(boundaryRectangleCount), fp);
217 16 : CPL_MSBPTR16( &boundaryRectangleCount );
218 :
219 16 : if( VSIFSeekL( fp, boundaryRectangleTablePhysIndex, SEEK_SET ) != 0)
220 : {
221 : CPLError( CE_Failure, CPLE_NotSupported,
222 : "Invalid TOC file. Unable to seek to boundaryRectangleTablePhysIndex at offset %d.",
223 0 : boundaryRectangleTablePhysIndex );
224 0 : return NULL;
225 : }
226 :
227 16 : toc = (RPFToc*)CPLMalloc(sizeof(RPFToc));
228 16 : toc->nEntries = boundaryRectangleCount;
229 16 : toc->entries = (RPFTocEntry*)CPLMalloc(boundaryRectangleCount * sizeof(RPFTocEntry));
230 16 : memset(toc->entries, 0, boundaryRectangleCount * sizeof(RPFTocEntry));
231 :
232 32 : for(i=0;i<toc->nEntries;i++)
233 : {
234 16 : toc->entries[i].isOverviewOrLegend = 0;
235 :
236 16 : VSIFReadL( toc->entries[i].type, 1, 5, fp);
237 16 : toc->entries[i].type[5] = 0;
238 16 : RPFTOCTrim(toc->entries[i].type);
239 :
240 16 : VSIFReadL( toc->entries[i].compression, 1, 5, fp);
241 16 : toc->entries[i].compression[5] = 0;
242 16 : RPFTOCTrim(toc->entries[i].compression);
243 :
244 16 : VSIFReadL( toc->entries[i].scale, 1, 12, fp);
245 16 : toc->entries[i].scale[12] = 0;
246 16 : RPFTOCTrim(toc->entries[i].scale);
247 32 : if (toc->entries[i].scale[0] == '1' &&
248 16 : toc->entries[i].scale[1] == ':')
249 : {
250 16 : memmove(toc->entries[i].scale,
251 16 : toc->entries[i].scale+2,
252 48 : strlen(toc->entries[i].scale+2)+1);
253 : }
254 :
255 16 : VSIFReadL( toc->entries[i].zone, 1, 1, fp);
256 16 : toc->entries[i].zone[1] = 0;
257 16 : RPFTOCTrim(toc->entries[i].zone);
258 :
259 16 : VSIFReadL( toc->entries[i].producer, 1, 5, fp);
260 16 : toc->entries[i].producer[5] = 0;
261 16 : RPFTOCTrim(toc->entries[i].producer);
262 :
263 16 : VSIFReadL( &toc->entries[i].nwLat, 1, sizeof(double), fp);
264 16 : CPL_MSBPTR64( &toc->entries[i].nwLat);
265 :
266 16 : VSIFReadL( &toc->entries[i].nwLong, 1, sizeof(double), fp);
267 16 : CPL_MSBPTR64( &toc->entries[i].nwLong);
268 :
269 16 : VSIFReadL( &toc->entries[i].swLat, 1, sizeof(double), fp);
270 16 : CPL_MSBPTR64( &toc->entries[i].swLat);
271 :
272 16 : VSIFReadL( &toc->entries[i].swLong, 1, sizeof(double), fp);
273 16 : CPL_MSBPTR64( &toc->entries[i].swLong);
274 :
275 16 : VSIFReadL( &toc->entries[i].neLat, 1, sizeof(double), fp);
276 16 : CPL_MSBPTR64( &toc->entries[i].neLat);
277 :
278 16 : VSIFReadL( &toc->entries[i].neLong, 1, sizeof(double), fp);
279 16 : CPL_MSBPTR64( &toc->entries[i].neLong);
280 :
281 16 : VSIFReadL( &toc->entries[i].seLat, 1, sizeof(double), fp);
282 16 : CPL_MSBPTR64( &toc->entries[i].seLat);
283 :
284 16 : VSIFReadL( &toc->entries[i].seLong, 1, sizeof(double), fp);
285 16 : CPL_MSBPTR64( &toc->entries[i].seLong);
286 :
287 16 : VSIFReadL( &toc->entries[i].vertResolution, 1, sizeof(double), fp);
288 16 : CPL_MSBPTR64( &toc->entries[i].vertResolution);
289 :
290 16 : VSIFReadL( &toc->entries[i].horizResolution, 1, sizeof(double), fp);
291 16 : CPL_MSBPTR64( &toc->entries[i].horizResolution);
292 :
293 16 : VSIFReadL( &toc->entries[i].vertInterval, 1, sizeof(double), fp);
294 16 : CPL_MSBPTR64( &toc->entries[i].vertInterval);
295 :
296 16 : VSIFReadL( &toc->entries[i].horizInterval, 1, sizeof(double), fp);
297 16 : CPL_MSBPTR64( &toc->entries[i].horizInterval);
298 :
299 16 : VSIFReadL( &toc->entries[i].nVertFrames, 1, sizeof(int), fp);
300 16 : CPL_MSBPTR32( &toc->entries[i].nVertFrames );
301 :
302 16 : VSIFReadL( &toc->entries[i].nHorizFrames, 1, sizeof(int), fp);
303 16 : CPL_MSBPTR32( &toc->entries[i].nHorizFrames );
304 :
305 16 : toc->entries[i].frameEntries = (RPFTocFrameEntry*)
306 16 : VSIMalloc3(toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames, sizeof(RPFTocFrameEntry));
307 16 : if (toc->entries[i].frameEntries == NULL)
308 : {
309 : CPLError( CE_Failure, CPLE_OutOfMemory,
310 0 : "RPFTOCReadFromBuffer : Out of memory. Probably due to corrupted TOC file.");
311 0 : RPFTOCFree(toc);
312 0 : return NULL;
313 : }
314 16 : memset(toc->entries[i].frameEntries, 0,
315 32 : toc->entries[i].nVertFrames * toc->entries[i].nHorizFrames * sizeof(RPFTocFrameEntry));
316 :
317 : CPLDebug("RPFTOC", "[%d] type=%s, compression=%s, scale=%s, zone=%s, producer=%s, nVertFrames=%d, nHorizFrames=%d",
318 48 : i, toc->entries[i].type, toc->entries[i].compression, toc->entries[i].scale,
319 64 : toc->entries[i].zone, toc->entries[i].producer, toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames);
320 : }
321 :
322 16 : if( VSIFSeekL( fp, frameFileIndexSectionSubHeaderPhysIndex, SEEK_SET ) != 0)
323 : {
324 : CPLError( CE_Failure, CPLE_NotSupported,
325 : "Invalid TOC file. Unable to seek to frameFileIndexSectionSubHeaderPhysIndex at offset %d.",
326 0 : frameFileIndexSectionSubHeaderPhysIndex );
327 0 : RPFTOCFree(toc);
328 0 : return NULL;
329 : }
330 :
331 : /* Skip 1 byte security classification */
332 16 : VSIFSeekL( fp, 1, SEEK_CUR );
333 :
334 16 : VSIFReadL( &frameIndexTableOffset, 1, sizeof(frameIndexTableOffset), fp);
335 16 : CPL_MSBPTR32( &frameIndexTableOffset );
336 :
337 16 : VSIFReadL( &nFrameFileIndexRecords, 1, sizeof(nFrameFileIndexRecords), fp);
338 16 : CPL_MSBPTR32( &nFrameFileIndexRecords );
339 :
340 16 : VSIFReadL( &nFrameFilePathnameRecords, 1, sizeof(nFrameFilePathnameRecords), fp);
341 16 : CPL_MSBPTR16( &nFrameFilePathnameRecords );
342 :
343 16 : VSIFReadL( &frameFileIndexRecordLength, 1, sizeof(frameFileIndexRecordLength), fp);
344 16 : CPL_MSBPTR16( &frameFileIndexRecordLength );
345 :
346 32 : for (i=0;i<(int)nFrameFileIndexRecords;i++)
347 : {
348 : RPFTocEntry* entry;
349 : RPFTocFrameEntry* frameEntry;
350 : unsigned short boundaryId, frameRow, frameCol;
351 : unsigned int offsetFrameFilePathName;
352 : unsigned short pathLength;
353 :
354 16 : if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i, SEEK_SET ) != 0)
355 : {
356 : CPLError( CE_Failure, CPLE_NotSupported,
357 : "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex(%d) at offset %d.",
358 0 : i, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i);
359 0 : RPFTOCFree(toc);
360 0 : return NULL;
361 : }
362 :
363 16 : VSIFReadL( &boundaryId, 1, sizeof(boundaryId), fp);
364 16 : CPL_MSBPTR16( &boundaryId );
365 :
366 16 : if (i == 0 && boundaryId == 0)
367 16 : newBoundaryId = 1;
368 16 : if (newBoundaryId == 0)
369 0 : boundaryId--;
370 :
371 16 : if (boundaryId >= toc->nEntries)
372 : {
373 : CPLError( CE_Failure, CPLE_NotSupported,
374 : "Invalid TOC file. Bad boundary id (%d) for frame file index %d.",
375 0 : boundaryId, i);
376 0 : RPFTOCFree(toc);
377 0 : return NULL;
378 : }
379 :
380 16 : entry = &toc->entries[boundaryId];
381 16 : entry->boundaryId = boundaryId;
382 :
383 16 : VSIFReadL( &frameRow, 1, sizeof(frameRow), fp);
384 16 : CPL_MSBPTR16( &frameRow );
385 :
386 16 : VSIFReadL( &frameCol, 1, sizeof(frameCol), fp);
387 16 : CPL_MSBPTR16( &frameCol );
388 :
389 :
390 16 : if (newBoundaryId == 0)
391 : {
392 0 : frameRow--;
393 0 : frameCol--;
394 : }
395 : else
396 : {
397 : /* Trick so that frames are numbered north to south */
398 16 : frameRow = (unsigned short)((entry->nVertFrames-1) - frameRow);
399 : }
400 :
401 16 : if (frameRow >= entry->nVertFrames)
402 : {
403 : CPLError( CE_Failure, CPLE_NotSupported,
404 : "Invalid TOC file. Bad row num (%d) for frame file index %d.",
405 0 : frameRow, i);
406 0 : RPFTOCFree(toc);
407 0 : return NULL;
408 : }
409 :
410 16 : if (frameCol >= entry->nHorizFrames)
411 : {
412 : CPLError( CE_Failure, CPLE_NotSupported,
413 : "Invalid TOC file. Bad col num (%d) for frame file index %d.",
414 0 : frameCol, i);
415 0 : RPFTOCFree(toc);
416 0 : return NULL;
417 : }
418 :
419 16 : frameEntry = &entry->frameEntries[frameRow * entry->nHorizFrames + frameCol ];
420 16 : frameEntry->frameRow = frameRow;
421 16 : frameEntry->frameCol = frameCol;
422 :
423 16 : if (frameEntry->exists)
424 : {
425 : CPLError( CE_Warning, CPLE_AppDefined,
426 : "Frame entry(%d,%d) for frame file index %d was already found.",
427 0 : frameRow, frameCol, i);
428 0 : CPLFree(frameEntry->directory);
429 0 : frameEntry->directory = NULL;
430 0 : CPLFree(frameEntry->fullFilePath);
431 0 : frameEntry->fullFilePath = NULL;
432 0 : frameEntry->exists = 0;
433 : }
434 :
435 16 : VSIFReadL( &offsetFrameFilePathName, 1, sizeof(offsetFrameFilePathName), fp);
436 16 : CPL_MSBPTR32( &offsetFrameFilePathName );
437 :
438 :
439 16 : VSIFReadL( frameEntry->filename, 1, 12, fp);
440 16 : frameEntry->filename[12] = '\0';
441 :
442 : /* Check if the filename is an overview or legend */
443 208 : for (j=0;j<12;j++)
444 : {
445 768 : if (strcmp(&(frameEntry->filename[j]),".OVR") == 0 ||
446 192 : strcmp(&(frameEntry->filename[j]),".ovr") == 0 ||
447 192 : strcmp(&(frameEntry->filename[j]),".LGD") == 0 ||
448 192 : strcmp(&(frameEntry->filename[j]),".lgd") == 0)
449 : {
450 0 : entry->isOverviewOrLegend = TRUE;
451 0 : break;
452 : }
453 : }
454 :
455 : /* Extract series code */
456 16 : if (entry->seriesAbbreviation == NULL)
457 : {
458 16 : const NITFSeries* series = NITFGetSeriesInfo(frameEntry->filename);
459 16 : if (series)
460 : {
461 16 : entry->seriesAbbreviation = series->abbreviation;
462 16 : entry->seriesName = series->name;
463 : }
464 : }
465 :
466 : /* Get file geo reference */
467 16 : VSIFReadL( frameEntry->georef, 1, 6, fp);
468 16 : frameEntry->georef[6] = '\0';
469 :
470 : /* Go to start of pathname record */
471 : /* New path_off offset from start of frame file index section of TOC?? */
472 : /* Add pathoffset wrt frame file index table subsection (loc[3]) */
473 16 : if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName, SEEK_SET ) != 0)
474 : {
475 : CPLError( CE_Failure, CPLE_NotSupported,
476 : "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName(%d) at offset %d.",
477 0 : i, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName);
478 0 : RPFTOCFree(toc);
479 0 : return NULL;
480 : }
481 :
482 16 : VSIFReadL( &pathLength, 1, sizeof(pathLength), fp);
483 16 : CPL_MSBPTR16( &pathLength );
484 :
485 : /* if nFrameFileIndexRecords == 65535 and pathLength == 65535 for each record,
486 : this leads to 4 GB allocation... Protect against this case */
487 16 : if (pathLength > 256)
488 : {
489 : CPLError( CE_Failure, CPLE_NotSupported,
490 0 : "Path length is big : %d. Probably corrupted TOC file.", (int)pathLength);
491 0 : RPFTOCFree(toc);
492 0 : return NULL;
493 : }
494 :
495 16 : frameEntry->directory = (char *)CPLMalloc(pathLength+1);
496 16 : VSIFReadL( frameEntry->directory, 1, pathLength, fp);
497 16 : frameEntry->directory[pathLength] = 0;
498 16 : if (pathLength > 0 && frameEntry->directory[pathLength-1] == '/')
499 16 : frameEntry->directory[pathLength-1] = 0;
500 :
501 16 : if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == '/')
502 0 : memmove(frameEntry->directory, frameEntry->directory+2, strlen(frameEntry->directory+2)+1);
503 :
504 : {
505 16 : char* baseDir = CPLStrdup(CPLGetDirname(pszFilename));
506 : VSIStatBufL sStatBuf;
507 : char* subdir;
508 16 : if (CPLIsFilenameRelative(frameEntry->directory) == FALSE)
509 0 : subdir = CPLStrdup(frameEntry->directory);
510 32 : else if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == 0)
511 16 : subdir = CPLStrdup(baseDir);
512 : else
513 0 : subdir = CPLStrdup(CPLFormFilename(baseDir, frameEntry->directory, NULL));
514 : #if !defined(_WIN32) && !defined(_WIN32_CE)
515 16 : if( VSIStatL( subdir, &sStatBuf ) != 0 && subdir[strlen(baseDir)] != 0)
516 : {
517 0 : char* c = subdir + strlen(baseDir)+1;
518 0 : while(*c)
519 : {
520 0 : if (*c >= 'A' && *c <= 'Z')
521 0 : *c += 'a' - 'A';
522 0 : c++;
523 : }
524 : }
525 : #endif
526 : frameEntry->fullFilePath = CPLStrdup(CPLFormFilename(
527 : subdir,
528 16 : frameEntry->filename, NULL));
529 16 : if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 )
530 : {
531 : #if !defined(_WIN32) && !defined(_WIN32_CE)
532 0 : char* c = frameEntry->fullFilePath + strlen(subdir)+1;
533 0 : while(*c)
534 : {
535 0 : if (*c >= 'A' && *c <= 'Z')
536 0 : *c += 'a' - 'A';
537 0 : c++;
538 : }
539 0 : if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 )
540 : #endif
541 : {
542 0 : frameEntry->fileExists = 0;
543 : CPLError( CE_Warning, CPLE_AppDefined,
544 0 : "File %s does not exist.", frameEntry->fullFilePath );
545 : }
546 : #if !defined(_WIN32) && !defined(_WIN32_CE)
547 : else
548 : {
549 0 : frameEntry->fileExists = 1;
550 : }
551 : #endif
552 : }
553 : else
554 : {
555 16 : frameEntry->fileExists = 1;
556 : }
557 16 : CPLFree(subdir);
558 16 : CPLFree(baseDir);
559 : }
560 :
561 16 : CPLDebug("RPFTOC", "Entry %d : %s,%s (%d, %d)", boundaryId, frameEntry->directory, frameEntry->filename, frameRow, frameCol);
562 :
563 16 : frameEntry->exists = 1;
564 : }
565 :
566 16 : return toc;
567 : }
568 :
569 : /************************************************************************/
570 : /* RPFTOCFree() */
571 : /************************************************************************/
572 :
573 16 : void RPFTOCFree(RPFToc* toc)
574 : {
575 : int i, j;
576 16 : if (!toc) return;
577 :
578 32 : for(i=0;i<toc->nEntries;i++)
579 : {
580 32 : for(j=0;j<(int)(toc->entries[i].nVertFrames * toc->entries[i].nHorizFrames); j++)
581 : {
582 16 : CPLFree(toc->entries[i].frameEntries[j].fullFilePath);
583 16 : CPLFree(toc->entries[i].frameEntries[j].directory);
584 : }
585 16 : CPLFree(toc->entries[i].frameEntries);
586 : }
587 :
588 16 : CPLFree(toc->entries);
589 16 : CPLFree(toc);
590 : }
|