1 : /******************************************************************************
2 : * $Id: rpftocfile.cpp 17617 2009-09-07 19:14:46Z 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 17617 2009-09-07 19:14:46Z rouault $");
53 :
54 : /************************************************************************/
55 : /* RPFTOCTrim() */
56 : /************************************************************************/
57 :
58 40 : static void RPFTOCTrim(char* str)
59 : {
60 40 : char* c = str;
61 : int i;
62 40 : if (str == NULL || *str == 0)
63 0 : return;
64 :
65 80 : while(*c == ' ')
66 : {
67 0 : c++;
68 : }
69 40 : if (c != str)
70 : {
71 0 : memmove(str, c, strlen(c)+1);
72 : }
73 :
74 40 : i = strlen(str) - 1;
75 96 : while (i >= 0 && str[i] == ' ')
76 : {
77 16 : str[i] = 0;
78 16 : i--;
79 : }
80 : }
81 :
82 : /************************************************************************/
83 : /* RPFTOCRead() */
84 : /************************************************************************/
85 :
86 :
87 0 : RPFToc* RPFTOCRead(const char* pszFilename, NITFFile* psFile)
88 : {
89 : int TRESize;
90 : const char* pachTRE = NITFFindTRE( psFile->pachTRE, psFile->nTREBytes,
91 0 : "RPFHDR", &TRESize );
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 (TRESize < 48)
100 : {
101 : CPLError( CE_Failure, CPLE_NotSupported,
102 0 : "Not enough bytes in RPFHDR." );
103 0 : return NULL;
104 : }
105 :
106 0 : int nRemainingBytes = psFile->nTREBytes - (pachTRE - psFile->pachTRE);
107 0 : if (nRemainingBytes < 48)
108 : {
109 : CPLError(CE_Failure, CPLE_AppDefined,
110 0 : "Cannot read RPFHDR TRE. Not enough bytes");
111 0 : return NULL;
112 : }
113 :
114 0 : return RPFTOCReadFromBuffer(pszFilename, psFile->fp, pachTRE);
115 : }
116 :
117 :
118 : /* This function is directly inspired by function parse_toc coming from ogdi/driver/rpf/utils.c */
119 :
120 8 : RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, FILE* fp, const char* tocHeader)
121 : {
122 : int i, j;
123 : unsigned int locationSectionPhysicalLocation;
124 :
125 : unsigned short nSections;
126 8 : unsigned int boundaryRectangleSectionSubHeaderPhysIndex = 0, boundaryRectangleSectionSubHeaderLength = 0;
127 8 : unsigned int boundaryRectangleTablePhysIndex = 0, boundaryRectangleTableLength = 0;
128 8 : unsigned int frameFileIndexSectionSubHeaderPhysIndex = 0, frameFileIndexSectionSubHeaderLength = 0;
129 8 : unsigned int frameFileIndexSubsectionPhysIndex = 0, frameFileIndexSubsectionLength = 0;
130 :
131 : unsigned int boundaryRectangleTableOffset;
132 : unsigned short boundaryRectangleCount;
133 :
134 : unsigned int frameIndexTableOffset;
135 : unsigned int nFrameFileIndexRecords;
136 : unsigned short nFrameFilePathnameRecords;
137 : unsigned short frameFileIndexRecordLength;
138 :
139 8 : int newBoundaryId = 0;
140 :
141 : RPFToc* toc;
142 :
143 8 : tocHeader += 1; /* skip endian */
144 8 : tocHeader += 2; /* skip header length */
145 8 : tocHeader += 12; /* skip file name : this should be A.TOC (padded) */
146 8 : tocHeader += 1; /* skip new */
147 8 : tocHeader += 15; /* skip standard_num */
148 8 : tocHeader += 8; /* skip standard_date */
149 8 : tocHeader += 1; /* skip classification */
150 8 : tocHeader += 2; /* skip country */
151 8 : tocHeader += 2; /* skip release */
152 :
153 8 : memcpy(&locationSectionPhysicalLocation, tocHeader, sizeof(unsigned int));
154 8 : CPL_MSBPTR32(&locationSectionPhysicalLocation);
155 :
156 8 : if( VSIFSeekL( fp, locationSectionPhysicalLocation, SEEK_SET ) != 0)
157 : {
158 : CPLError( CE_Failure, CPLE_NotSupported,
159 : "Invalid TOC file. Unable to seek to locationSectionPhysicalLocation at offset %d.",
160 0 : locationSectionPhysicalLocation );
161 0 : return NULL;
162 : }
163 :
164 : /* Skip location section length (4) and component location table offset (2)*/
165 8 : VSIFSeekL( fp, 4 + 2, SEEK_CUR);
166 :
167 : /* How many sections: # of section location records */
168 8 : VSIFReadL( &nSections, 1, sizeof(nSections), fp);
169 8 : CPL_MSBPTR16( &nSections );
170 :
171 : /* Skip location record length(2) + component aggregate length(4) */
172 8 : VSIFSeekL( fp, 2 + 4, SEEK_CUR);
173 :
174 40 : for (i = 0; i < nSections; i++)
175 : {
176 : unsigned short id;
177 : unsigned int sectionLength, physIndex;
178 32 : VSIFReadL( &id, 1, sizeof(id), fp);
179 32 : CPL_MSBPTR16( &id );
180 :
181 32 : VSIFReadL( §ionLength, 1, sizeof(sectionLength), fp);
182 32 : CPL_MSBPTR32( §ionLength );
183 :
184 32 : VSIFReadL( &physIndex, 1, sizeof(physIndex), fp);
185 32 : CPL_MSBPTR32( &physIndex );
186 :
187 32 : if (id == LID_BoundaryRectangleSectionSubheader)
188 : {
189 8 : boundaryRectangleSectionSubHeaderPhysIndex = physIndex;
190 8 : boundaryRectangleSectionSubHeaderLength = sectionLength;
191 : }
192 24 : else if (id == LID_BoundaryRectangleTable)
193 : {
194 8 : boundaryRectangleTablePhysIndex = physIndex;
195 8 : boundaryRectangleTableLength = sectionLength;
196 : }
197 16 : else if (id == LID_FrameFileIndexSectionSubHeader)
198 : {
199 8 : frameFileIndexSectionSubHeaderPhysIndex = physIndex;
200 8 : frameFileIndexSectionSubHeaderLength = sectionLength;
201 : }
202 8 : else if (id == LID_FrameFileIndexSubsection)
203 : {
204 8 : frameFileIndexSubsectionPhysIndex = physIndex;
205 8 : frameFileIndexSubsectionLength = sectionLength;
206 : }
207 : }
208 :
209 8 : if (boundaryRectangleSectionSubHeaderPhysIndex == 0)
210 : {
211 : CPLError( CE_Failure, CPLE_NotSupported,
212 0 : "Invalid TOC file. Can't find LID_BoundaryRectangleSectionSubheader." );
213 0 : return NULL;
214 : }
215 8 : if (boundaryRectangleTablePhysIndex == 0)
216 : {
217 : CPLError( CE_Failure, CPLE_NotSupported,
218 0 : "Invalid TOC file. Can't find LID_BoundaryRectangleTable." );
219 0 : return NULL;
220 : }
221 8 : if (frameFileIndexSectionSubHeaderPhysIndex == 0)
222 : {
223 : CPLError( CE_Failure, CPLE_NotSupported,
224 0 : "Invalid TOC file. Can't find LID_FrameFileIndexSectionSubHeader." );
225 0 : return NULL;
226 : }
227 8 : if (frameFileIndexSubsectionPhysIndex == 0)
228 : {
229 : CPLError( CE_Failure, CPLE_NotSupported,
230 0 : "Invalid TOC file. Can't find LID_FrameFileIndexSubsection." );
231 0 : return NULL;
232 : }
233 :
234 8 : if( VSIFSeekL( fp, boundaryRectangleSectionSubHeaderPhysIndex, SEEK_SET ) != 0)
235 : {
236 : CPLError( CE_Failure, CPLE_NotSupported,
237 : "Invalid TOC file. Unable to seek to boundaryRectangleSectionSubHeaderPhysIndex at offset %d.",
238 0 : boundaryRectangleSectionSubHeaderPhysIndex );
239 0 : return NULL;
240 : }
241 :
242 8 : VSIFReadL( &boundaryRectangleTableOffset, 1, sizeof(boundaryRectangleTableOffset), fp);
243 8 : CPL_MSBPTR32( &boundaryRectangleTableOffset );
244 :
245 8 : VSIFReadL( &boundaryRectangleCount, 1, sizeof(boundaryRectangleCount), fp);
246 8 : CPL_MSBPTR16( &boundaryRectangleCount );
247 :
248 8 : if( VSIFSeekL( fp, boundaryRectangleTablePhysIndex, SEEK_SET ) != 0)
249 : {
250 : CPLError( CE_Failure, CPLE_NotSupported,
251 : "Invalid TOC file. Unable to seek to boundaryRectangleTablePhysIndex at offset %d.",
252 0 : boundaryRectangleTablePhysIndex );
253 0 : return NULL;
254 : }
255 :
256 8 : toc = (RPFToc*)CPLMalloc(sizeof(RPFToc));
257 8 : toc->nEntries = boundaryRectangleCount;
258 8 : toc->entries = (RPFTocEntry*)CPLMalloc(boundaryRectangleCount * sizeof(RPFTocEntry));
259 8 : memset(toc->entries, 0, boundaryRectangleCount * sizeof(RPFTocEntry));
260 :
261 16 : for(i=0;i<toc->nEntries;i++)
262 : {
263 8 : toc->entries[i].isOverviewOrLegend = 0;
264 :
265 8 : VSIFReadL( toc->entries[i].type, 1, 5, fp);
266 8 : toc->entries[i].type[5] = 0;
267 8 : RPFTOCTrim(toc->entries[i].type);
268 :
269 8 : VSIFReadL( toc->entries[i].compression, 1, 5, fp);
270 8 : toc->entries[i].compression[5] = 0;
271 8 : RPFTOCTrim(toc->entries[i].compression);
272 :
273 8 : VSIFReadL( toc->entries[i].scale, 1, 12, fp);
274 8 : toc->entries[i].scale[12] = 0;
275 8 : RPFTOCTrim(toc->entries[i].scale);
276 16 : if (toc->entries[i].scale[0] == '1' &&
277 8 : toc->entries[i].scale[1] == ':')
278 : {
279 8 : memmove(toc->entries[i].scale,
280 8 : toc->entries[i].scale+2,
281 24 : strlen(toc->entries[i].scale+2)+1);
282 : }
283 :
284 8 : VSIFReadL( toc->entries[i].zone, 1, 1, fp);
285 8 : toc->entries[i].zone[1] = 0;
286 8 : RPFTOCTrim(toc->entries[i].zone);
287 :
288 8 : VSIFReadL( toc->entries[i].producer, 1, 5, fp);
289 8 : toc->entries[i].producer[5] = 0;
290 8 : RPFTOCTrim(toc->entries[i].producer);
291 :
292 8 : VSIFReadL( &toc->entries[i].nwLat, 1, sizeof(double), fp);
293 8 : CPL_MSBPTR64( &toc->entries[i].nwLat);
294 :
295 8 : VSIFReadL( &toc->entries[i].nwLong, 1, sizeof(double), fp);
296 8 : CPL_MSBPTR64( &toc->entries[i].nwLong);
297 :
298 8 : VSIFReadL( &toc->entries[i].swLat, 1, sizeof(double), fp);
299 8 : CPL_MSBPTR64( &toc->entries[i].swLat);
300 :
301 8 : VSIFReadL( &toc->entries[i].swLong, 1, sizeof(double), fp);
302 8 : CPL_MSBPTR64( &toc->entries[i].swLong);
303 :
304 8 : VSIFReadL( &toc->entries[i].neLat, 1, sizeof(double), fp);
305 8 : CPL_MSBPTR64( &toc->entries[i].neLat);
306 :
307 8 : VSIFReadL( &toc->entries[i].neLong, 1, sizeof(double), fp);
308 8 : CPL_MSBPTR64( &toc->entries[i].neLong);
309 :
310 8 : VSIFReadL( &toc->entries[i].seLat, 1, sizeof(double), fp);
311 8 : CPL_MSBPTR64( &toc->entries[i].seLat);
312 :
313 8 : VSIFReadL( &toc->entries[i].seLong, 1, sizeof(double), fp);
314 8 : CPL_MSBPTR64( &toc->entries[i].seLong);
315 :
316 8 : VSIFReadL( &toc->entries[i].vertResolution, 1, sizeof(double), fp);
317 8 : CPL_MSBPTR64( &toc->entries[i].vertResolution);
318 :
319 8 : VSIFReadL( &toc->entries[i].horizResolution, 1, sizeof(double), fp);
320 8 : CPL_MSBPTR64( &toc->entries[i].horizResolution);
321 :
322 8 : VSIFReadL( &toc->entries[i].vertInterval, 1, sizeof(double), fp);
323 8 : CPL_MSBPTR64( &toc->entries[i].vertInterval);
324 :
325 8 : VSIFReadL( &toc->entries[i].horizInterval, 1, sizeof(double), fp);
326 8 : CPL_MSBPTR64( &toc->entries[i].horizInterval);
327 :
328 8 : VSIFReadL( &toc->entries[i].nVertFrames, 1, sizeof(int), fp);
329 8 : CPL_MSBPTR32( &toc->entries[i].nVertFrames );
330 :
331 8 : VSIFReadL( &toc->entries[i].nHorizFrames, 1, sizeof(int), fp);
332 8 : CPL_MSBPTR32( &toc->entries[i].nHorizFrames );
333 :
334 8 : toc->entries[i].frameEntries = (RPFTocFrameEntry*)
335 8 : VSIMalloc3(toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames, sizeof(RPFTocFrameEntry));
336 8 : if (toc->entries[i].frameEntries == NULL)
337 : {
338 : CPLError( CE_Failure, CPLE_OutOfMemory,
339 0 : "RPFTOCReadFromBuffer : Out of memory. Probably due to corrupted TOC file.");
340 0 : RPFTOCFree(toc);
341 0 : return NULL;
342 : }
343 8 : memset(toc->entries[i].frameEntries, 0,
344 16 : toc->entries[i].nVertFrames * toc->entries[i].nHorizFrames * sizeof(RPFTocFrameEntry));
345 :
346 : CPLDebug("RPFTOC", "[%d] type=%s, compression=%s, scale=%s, zone=%s, producer=%s, nVertFrames=%d, nHorizFrames=%d",
347 24 : i, toc->entries[i].type, toc->entries[i].compression, toc->entries[i].scale,
348 32 : toc->entries[i].zone, toc->entries[i].producer, toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames);
349 : }
350 :
351 8 : if( VSIFSeekL( fp, frameFileIndexSectionSubHeaderPhysIndex, SEEK_SET ) != 0)
352 : {
353 : CPLError( CE_Failure, CPLE_NotSupported,
354 : "Invalid TOC file. Unable to seek to frameFileIndexSectionSubHeaderPhysIndex at offset %d.",
355 0 : frameFileIndexSectionSubHeaderPhysIndex );
356 0 : RPFTOCFree(toc);
357 0 : return NULL;
358 : }
359 :
360 : /* Skip 1 byte security classification */
361 8 : VSIFSeekL( fp, 1, SEEK_CUR );
362 :
363 8 : VSIFReadL( &frameIndexTableOffset, 1, sizeof(frameIndexTableOffset), fp);
364 8 : CPL_MSBPTR32( &frameIndexTableOffset );
365 :
366 8 : VSIFReadL( &nFrameFileIndexRecords, 1, sizeof(nFrameFileIndexRecords), fp);
367 8 : CPL_MSBPTR32( &nFrameFileIndexRecords );
368 :
369 8 : VSIFReadL( &nFrameFilePathnameRecords, 1, sizeof(nFrameFilePathnameRecords), fp);
370 8 : CPL_MSBPTR16( &nFrameFilePathnameRecords );
371 :
372 8 : VSIFReadL( &frameFileIndexRecordLength, 1, sizeof(frameFileIndexRecordLength), fp);
373 8 : CPL_MSBPTR16( &frameFileIndexRecordLength );
374 :
375 16 : for (i=0;i<(int)nFrameFileIndexRecords;i++)
376 : {
377 : RPFTocEntry* entry;
378 : RPFTocFrameEntry* frameEntry;
379 : unsigned short boundaryId, frameRow, frameCol;
380 : unsigned int offsetFrameFilePathName;
381 : unsigned short pathLength;
382 :
383 8 : if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i, SEEK_SET ) != 0)
384 : {
385 : CPLError( CE_Failure, CPLE_NotSupported,
386 : "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex(%d) at offset %d.",
387 0 : i, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i);
388 0 : RPFTOCFree(toc);
389 0 : return NULL;
390 : }
391 :
392 8 : VSIFReadL( &boundaryId, 1, sizeof(boundaryId), fp);
393 8 : CPL_MSBPTR16( &boundaryId );
394 :
395 8 : if (i == 0 && boundaryId == 0)
396 8 : newBoundaryId = 1;
397 8 : if (newBoundaryId == 0)
398 0 : boundaryId--;
399 :
400 8 : if (boundaryId >= toc->nEntries)
401 : {
402 : CPLError( CE_Failure, CPLE_NotSupported,
403 : "Invalid TOC file. Bad boundary id (%d) for frame file index %d.",
404 0 : boundaryId, i);
405 0 : RPFTOCFree(toc);
406 0 : return NULL;
407 : }
408 :
409 8 : entry = &toc->entries[boundaryId];
410 8 : entry->boundaryId = boundaryId;
411 :
412 8 : VSIFReadL( &frameRow, 1, sizeof(frameRow), fp);
413 8 : CPL_MSBPTR16( &frameRow );
414 :
415 8 : VSIFReadL( &frameCol, 1, sizeof(frameCol), fp);
416 8 : CPL_MSBPTR16( &frameCol );
417 :
418 :
419 8 : if (newBoundaryId == 0)
420 : {
421 0 : frameRow--;
422 0 : frameCol--;
423 : }
424 : else
425 : {
426 : /* Trick so that frames are numbered north to south */
427 8 : frameRow = (unsigned short)((entry->nVertFrames-1) - frameRow);
428 : }
429 :
430 8 : if (frameRow >= entry->nVertFrames)
431 : {
432 : CPLError( CE_Failure, CPLE_NotSupported,
433 : "Invalid TOC file. Bad row num (%d) for frame file index %d.",
434 0 : frameRow, i);
435 0 : RPFTOCFree(toc);
436 0 : return NULL;
437 : }
438 :
439 8 : if (frameCol >= entry->nHorizFrames)
440 : {
441 : CPLError( CE_Failure, CPLE_NotSupported,
442 : "Invalid TOC file. Bad col num (%d) for frame file index %d.",
443 0 : frameCol, i);
444 0 : RPFTOCFree(toc);
445 0 : return NULL;
446 : }
447 :
448 8 : frameEntry = &entry->frameEntries[frameRow * entry->nHorizFrames + frameCol ];
449 8 : frameEntry->frameRow = frameRow;
450 8 : frameEntry->frameCol = frameCol;
451 :
452 8 : if (frameEntry->exists)
453 : {
454 : CPLError( CE_Failure, CPLE_NotSupported,
455 : "Invalid TOC file. Frame entry(%d,%d) for frame file index %d is a duplicate.",
456 0 : frameRow, frameCol, i);
457 0 : RPFTOCFree(toc);
458 0 : return NULL;
459 : }
460 :
461 8 : VSIFReadL( &offsetFrameFilePathName, 1, sizeof(offsetFrameFilePathName), fp);
462 8 : CPL_MSBPTR32( &offsetFrameFilePathName );
463 :
464 :
465 8 : VSIFReadL( frameEntry->filename, 1, 12, fp);
466 8 : frameEntry->filename[12] = '\0';
467 :
468 : /* Check if the filename is an overview or legend */
469 104 : for (j=0;j<12;j++)
470 : {
471 384 : if (strcmp(&(frameEntry->filename[j]),".OVR") == 0 ||
472 96 : strcmp(&(frameEntry->filename[j]),".ovr") == 0 ||
473 96 : strcmp(&(frameEntry->filename[j]),".LGD") == 0 ||
474 96 : strcmp(&(frameEntry->filename[j]),".lgd") == 0)
475 : {
476 0 : entry->isOverviewOrLegend = TRUE;
477 0 : break;
478 : }
479 : }
480 :
481 : /* Extract series code */
482 8 : if (entry->seriesAbbreviation == NULL)
483 : {
484 8 : const NITFSeries* series = NITFGetSeriesInfo(frameEntry->filename);
485 8 : if (series)
486 : {
487 8 : entry->seriesAbbreviation = series->abbreviation;
488 8 : entry->seriesName = series->name;
489 : }
490 : }
491 :
492 : /* Get file geo reference */
493 8 : VSIFReadL( frameEntry->georef, 1, 6, fp);
494 8 : frameEntry->georef[6] = '\0';
495 :
496 : /* Go to start of pathname record */
497 : /* New path_off offset from start of frame file index section of TOC?? */
498 : /* Add pathoffset wrt frame file index table subsection (loc[3]) */
499 8 : if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName, SEEK_SET ) != 0)
500 : {
501 : CPLError( CE_Failure, CPLE_NotSupported,
502 : "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName(%d) at offset %d.",
503 0 : i, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName);
504 0 : RPFTOCFree(toc);
505 0 : return NULL;
506 : }
507 :
508 8 : VSIFReadL( &pathLength, 1, sizeof(pathLength), fp);
509 8 : CPL_MSBPTR16( &pathLength );
510 :
511 : /* if nFrameFileIndexRecords == 65535 and pathLength == 65535 for each record,
512 : this leads to 4 GB allocation... Protect against this case */
513 8 : if (pathLength > 256)
514 : {
515 : CPLError( CE_Failure, CPLE_NotSupported,
516 0 : "Path length is big : %d. Probably corrupted TOC file.", (int)pathLength);
517 0 : RPFTOCFree(toc);
518 0 : return NULL;
519 : }
520 :
521 8 : frameEntry->directory = (char *)CPLMalloc(pathLength+1);
522 8 : VSIFReadL( frameEntry->directory, 1, pathLength, fp);
523 8 : frameEntry->directory[pathLength] = 0;
524 8 : if (pathLength > 0 && frameEntry->directory[pathLength-1] == '/')
525 8 : frameEntry->directory[pathLength-1] = 0;
526 :
527 8 : if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == '/')
528 0 : memmove(frameEntry->directory, frameEntry->directory+2, strlen(frameEntry->directory+2)+1);
529 :
530 : {
531 8 : char* baseDir = CPLStrdup(CPLGetDirname(pszFilename));
532 : VSIStatBufL sStatBuf;
533 : char* subdir;
534 8 : if (CPLIsFilenameRelative(frameEntry->directory) == FALSE)
535 0 : subdir = CPLStrdup(frameEntry->directory);
536 16 : else if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == 0)
537 8 : subdir = CPLStrdup(baseDir);
538 : else
539 0 : subdir = CPLStrdup(CPLFormFilename(baseDir, frameEntry->directory, NULL));
540 : #if !defined(_WIN32) && !defined(_WIN32_CE)
541 8 : if( VSIStatL( subdir, &sStatBuf ) != 0 && subdir[strlen(baseDir)] != 0)
542 : {
543 0 : char* c = subdir + strlen(baseDir)+1;
544 0 : while(*c)
545 : {
546 0 : if (*c >= 'A' && *c <= 'Z')
547 0 : *c += 'a' - 'A';
548 0 : c++;
549 : }
550 : }
551 : #endif
552 : frameEntry->fullFilePath = CPLStrdup(CPLFormFilename(
553 : subdir,
554 8 : frameEntry->filename, NULL));
555 8 : if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 )
556 : {
557 : #if !defined(_WIN32) && !defined(_WIN32_CE)
558 0 : char* c = frameEntry->fullFilePath + strlen(subdir)+1;
559 0 : while(*c)
560 : {
561 0 : if (*c >= 'A' && *c <= 'Z')
562 0 : *c += 'a' - 'A';
563 0 : c++;
564 : }
565 0 : if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 )
566 : #endif
567 : {
568 0 : frameEntry->fileExists = 0;
569 : CPLError( CE_Warning, CPLE_AppDefined,
570 0 : "File %s does not exist.", frameEntry->fullFilePath );
571 : }
572 : #if !defined(_WIN32) && !defined(_WIN32_CE)
573 : else
574 : {
575 0 : frameEntry->fileExists = 1;
576 : }
577 : #endif
578 : }
579 : else
580 : {
581 8 : frameEntry->fileExists = 1;
582 : }
583 8 : CPLFree(subdir);
584 8 : CPLFree(baseDir);
585 : }
586 :
587 8 : CPLDebug("RPFTOC", "Entry %d : %s,%s (%d, %d)", boundaryId, frameEntry->directory, frameEntry->filename, frameRow, frameCol);
588 :
589 8 : frameEntry->exists = 1;
590 : }
591 :
592 8 : return toc;
593 : }
594 :
595 : /************************************************************************/
596 : /* RPFTOCFree() */
597 : /************************************************************************/
598 :
599 8 : void RPFTOCFree(RPFToc* toc)
600 : {
601 : int i, j;
602 8 : if (!toc) return;
603 :
604 16 : for(i=0;i<toc->nEntries;i++)
605 : {
606 16 : for(j=0;j<(int)(toc->entries[i].nVertFrames * toc->entries[i].nHorizFrames); j++)
607 : {
608 8 : CPLFree(toc->entries[i].frameEntries[j].fullFilePath);
609 8 : CPLFree(toc->entries[i].frameEntries[j].directory);
610 : }
611 8 : CPLFree(toc->entries[i].frameEntries);
612 : }
613 :
614 8 : CPLFree(toc->entries);
615 8 : CPLFree(toc);
616 : }
|