1 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
2 /* EXIFPROBE - TIFF/JPEG/EXIF image file probe */
3 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
4 /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved. */
5 /* */
6 /* See the file LICENSE.EXIFPROBE for terms of use. */
7 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
8
9 #ifndef lint
10 static char *ModuleId = "@(#) $Id: print.c,v 1.51 2005/07/24 17:16:59 alex Exp $";
11 #endif
12
13 /* This file contains the primary "print" routines for TIFF/EXIF */
14 /* data, file offsets, etc. */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <ctype.h>
19
20 #include "defs.h"
21 #include "datadefs.h"
22 #include "summary.h"
23 #include "misc.h"
24 #include "tags.h"
25 #include "extern.h"
26 #include "maker_extern.h"
27 #include "ciff_extern.h"
28 #include "jp2_extern.h"
29 #include "mrw_extern.h"
30
31 /* Print the "header" information from the beginning of a file which */
32 /* identifies the image type and/or image characteristics. Return 0 */
33 /* if all goes well, -1 if no header is passed or the header magic */
34 /* number is invlid. */
35
36 int
print_header(struct fileheader * header,unsigned long section_id)37 print_header(struct fileheader *header,unsigned long section_id)
38 {
39 int status = -1;
40 int chpr = 0;
41
42 if(header)
43 {
44 switch(header->probe_magic)
45 {
46 case JPEG_SOI:
47 if(Print_options & section_id)
48 chpr += printf("JPEG SOI %#06x",header->file_marker);
49 status = 0;
50 chpr = newline(chpr);
51 break;
52 case ORF1_MAGIC:
53 status = print_tiff_header(ORF1_MAGIC,header->file_marker,section_id);
54 /* no newline */
55 break;
56 case ORF2_MAGIC:
57 status = print_tiff_header(ORF2_MAGIC,header->file_marker,section_id);
58 /* no newline */
59 break;
60 case TIFF_MAGIC:
61 status = print_tiff_header(TIFF_MAGIC,header->file_marker,section_id);
62 /* no newline */
63 break;
64 case PROBE_CIFFMAGIC:
65 status = print_ciff_header(header,section_id);
66 chpr = newline(chpr);
67 break;
68 case PROBE_JP2MAGIC:
69 status = print_jp2_header(header,section_id);
70 chpr = newline(chpr);
71 break;
72 case PROBE_MRWMAGIC:
73 status = print_mrw_header(header,section_id);
74 chpr = newline(chpr);
75 break;
76 case PROBE_RAFMAGIC:
77 chpr = printf("FUJIFILMCCD-RAW ");
78 chpr = newline(chpr);
79 break;
80 default:
81 if(Print_options & section_id)
82 chpr += printf("UNKNOWN HEADER MAGIC %#06lx",header->probe_magic);
83 chpr = newline(chpr);
84 break;
85 }
86 }
87 else
88 fprintf(stderr,"%s: null fileheader to print_header()\n",Progname);
89 return(status);
90 }
91
92
93 /* Print TIFF header information if options permit. Return 0 if */
94 /* information is valid to print or does not need to be printed for */
95 /* the identified section id. Return -1 if the magic number or */
96 /* byteorder are invalid. */
97
98 int
print_tiff_header(unsigned short magic,unsigned short byteorder,unsigned long section_id)99 print_tiff_header(unsigned short magic,unsigned short byteorder,unsigned long section_id)
100 {
101 char *name = CNULL;
102 int status = -1;
103 int chpr = 0;
104
105 if(Print_options & section_id)
106 {
107 switch(magic)
108 {
109 case TIFF_MAGIC: name = "TIFF"; break;
110 case ORF1_MAGIC: name = "ORF1"; break;
111 case ORF2_MAGIC: name = "ORF2"; break;
112 default: break;
113 }
114
115 if(name)
116 {
117 chpr += printf("%s",name);
118 switch(byteorder)
119 {
120 case TIFF_INTEL:
121 case TIFF_MOTOROLA:
122 print_byteorder(byteorder,1);
123 print_magic((unsigned long)magic,2);
124 status = 0;
125 break;
126 default:
127 chpr += printf("INVALID %s BYTEORDER ",name);
128 print_byteorder(byteorder,1);
129 print_magic((unsigned long)magic,2);
130 break;
131 }
132 }
133 else
134 {
135 chpr += printf("INVALID TIFF IDENTIFIER, byteorder ");
136 print_byteorder(byteorder,1);
137 print_magic((unsigned long)magic,2);
138 }
139 }
140 else
141 status = 0;
142
143 setcharsprinted(chpr);
144 return(status);
145 }
146
147 /* Print the file type as indicated by the "header" information at */
148 /* the start of the file. */
149
150 int
print_filetype(unsigned long magic,unsigned short marker)151 print_filetype(unsigned long magic,unsigned short marker)
152 {
153 int status = -1;
154 int chpr = 0;
155
156 switch(magic)
157 {
158 case JPEG_SOI:
159 chpr += printf("JPEG");
160 status = 0;
161 break;
162 case ORF1_MAGIC:
163 chpr += printf("ORF1");
164 switch(marker)
165 {
166 case TIFF_INTEL:
167 chpr += printf(":II");
168 break;
169 case TIFF_MOTOROLA:
170 chpr += printf(":MM");
171 break;
172 default:
173 break;
174 }
175 status = 0;
176 break;
177 case ORF2_MAGIC:
178 chpr += printf("ORF2");
179 switch(marker)
180 {
181 case TIFF_INTEL:
182 chpr += printf(":II");
183 break;
184 case TIFF_MOTOROLA:
185 chpr += printf(":MM");
186 break;
187 default:
188 break;
189 }
190 status = 0;
191 break;
192 case TIFF_MAGIC:
193 chpr += printf("TIFF");
194 switch(marker)
195 {
196 case TIFF_INTEL:
197 chpr += printf(":II");
198 break;
199 case TIFF_MOTOROLA:
200 chpr += printf(":MM");
201 break;
202 default:
203 break;
204 }
205 status = 0;
206 break;
207 case PROBE_CIFFMAGIC:
208 chpr += printf("CIFF");
209 switch(marker)
210 {
211 case TIFF_INTEL:
212 chpr += printf(":II");
213 break;
214 case TIFF_MOTOROLA:
215 chpr += printf(":MM");
216 break;
217 default:
218 break;
219 }
220 status = 0;
221 break;
222 case PROBE_JP2MAGIC:
223 chpr += printf("JP2");
224 status = 0;
225 break;
226 case PROBE_MRWMAGIC:
227 chpr += printf("MRW");
228 status = 0;
229 break;
230 case PROBE_RAFMAGIC:
231 chpr += printf("RAF");
232 status = 0;
233 break;
234 case PROBE_X3FMAGIC:
235 chpr += printf("X3F");
236 status = 0;
237 break;
238 default:
239 chpr += printf("UNKNOWN");
240 break;
241 }
242 setcharsprinted(chpr);
243 return(status);
244 }
245
246 /* Print an address in the file (offset from beginning of file), in */
247 /* hex, decimal, or both, offset from left margin by 'indent' spaces. */
248 /* "Addresses" are usually prefixed by an "@", but may be prefixed by */
249 /* a string passed as argument (this is normally used to pass a '-' */
250 /* prefix to mark the end of a segment, or something to flag an */
251 /* out-of-order segment). */
252
253 /* If this routine is called with all PRINT_ADDRESS bits off, it */
254 /* produces only the indent. */
255
256 void
print_tag_address(unsigned long section_id,unsigned long address,int indent,char * prefix)257 print_tag_address(unsigned long section_id,unsigned long address,int indent,char *prefix)
258 {
259 int chpr = 0;
260
261 if(Print_options & section_id)
262 {
263 print_filename();
264 if(PRINT_INDENT_BEFORE_ADDRESS)
265 putindent(indent);
266 if(!prefix)
267 prefix = "@";
268 if(address == HERE)
269 {
270 /* special case; bland address field */
271 if(PRINT_BOTH_ADDRESS)
272 chpr += printf("%*s: ",(ADDRWIDTH * 2) + 3,prefix);
273 else if(PRINT_HEX_ADDRESS)
274 chpr += printf("%*s: ",ADDRWIDTH + 1,prefix);
275 else if(PRINT_DEC_ADDRESS)
276 chpr += printf("%*s: ",ADDRWIDTH,prefix);
277 }
278 else
279 {
280 if(PRINT_BOTH_ADDRESS)
281 chpr += printf("%s%#0*lx=%-*lu: ",prefix,ADDRWIDTH+1,address,ADDRWIDTH,address);
282 else if(PRINT_HEX_ADDRESS)
283 chpr += printf("%s%#0*lx: ",prefix,ADDRWIDTH+1,address);
284 else if(PRINT_DEC_ADDRESS)
285 chpr += printf("%s%-*lu: ",prefix,ADDRWIDTH,address);
286 }
287 if(PRINT_INDENT_AFTER_ADDRESS)
288 putindent(indent);
289 setcharsprinted(chpr);
290 }
291 }
292
293 /* Print the option-selected items in a TIFF IFD entry, including the */
294 /* tag number, tag name, tag type, and offset or value. If the */
295 /* "value" doesn't fit in 4 bytes, print_offset_value() will be */
296 /* called and may defer printing to be handled later (by the caller's */
297 /* second pass) or may print the offset, preceded by an '@' sign if */
298 /* appropriate. If the value does fit in the 4 bytes provided in the */
299 /* entry, print it according to its TIFF type, intercepting tags */
300 /* which require special handling of value. */
301
302 unsigned long
print_entry(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,int ifdtype,int ifdnum,int subifdnum,int indent)303 print_entry(FILE *inptr,unsigned short byteorder,struct ifd_entry *entry_ptr,
304 unsigned long fileoffset_base,struct image_summary *summary_entry,
305 char *parent_name,int ifdtype,int ifdnum,int subifdnum,int indent)
306 {
307 int value_is_offset = 0;
308 unsigned long endoffset = 0UL;
309 int chpr = 0;
310
311 value_is_offset = is_offset(entry_ptr);
312 if((PRINT_ENTRY))
313 {
314 print_taginfo(entry_ptr,parent_name,indent,ifdtype,ifdnum,subifdnum);
315 if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) ||
316 ferror(inptr) || feof(inptr))
317 {
318 clearerr(inptr);
319 printred("# INVALID ENTRY");
320 endoffset = ftell(inptr);
321 }
322 else if(entry_ptr->count == 0)
323 {
324 if(PRINT_VALUE)
325 chpr += printf(" EMPTY (value=%#lx)",entry_ptr->value);
326 endoffset = ftell(inptr);
327 }
328 else if(value_is_offset)
329 {
330 /* Offsets read from the file are printed relative to the */
331 /* beginning of the file (with fileoffset_base added) so */
332 /* that the values, printed later, will be easy to find. */
333 if(PRINT_BOTH_OFFSET)
334 chpr += printf("@%#lx=%lu",entry_ptr->value + fileoffset_base,
335 entry_ptr->value + fileoffset_base);
336 else if(PRINT_HEX_OFFSET)
337 chpr += printf("@%#lx",entry_ptr->value + fileoffset_base);
338 else if(PRINT_DEC_OFFSET)
339 chpr += printf("@%lu",entry_ptr->value + fileoffset_base);
340
341 if(fileoffset_base && (PRINT_ENTRY_RELOFFSET))
342 chpr += printf(" (%lu) ",entry_ptr->value);
343
344 /* Print "inline" in REPORT & LIST modes */
345 if(!(PRINT_VALUE_AT_OFFSET))
346 {
347 setcharsprinted(chpr);
348 chpr = 0;
349 endoffset = print_offset_value(inptr,byteorder,entry_ptr,
350 fileoffset_base,parent_name,
351 ifdtype,indent,0);
352 }
353 }
354 else if(PRINT_VALUE)
355 {
356 /* Intercept some EXIF values which print_value() would */
357 /* not handle properly, possibly because they are ascii */
358 /* items tagged as UNDEFINED. A few items given as LONG */
359 /* type are actually offsets, and are printed as such */
360 /* here, with fileoffset_base added. */
361 switch(entry_ptr->tag)
362 {
363 case EXIFTAG_ExifVersion:
364 case EXIFTAG_FlashPixVersion:
365 case INTEROPTAG_Version:
366 case INTEROPTAG_Index:
367 /* ASCII */
368 /* ###%%% show_string()? */
369 chpr += printf("%s\'%s\'",PREFIX,(char *)&entry_ptr->value);
370 break;
371 case EXIFTAG_ExifIFDPointer:
372 case EXIFTAG_GPSInfoIFDPointer:
373 case EXIFTAG_Interoperability:
374 case TIFFTAG_JPEGInterchangeFormat:
375 /* OFFSETS */
376 if(PRINT_BOTH_OFFSET)
377 {
378 chpr += printf("@%#lx=%lu",entry_ptr->value + fileoffset_base,
379 entry_ptr->value + fileoffset_base);
380 }
381 else if(PRINT_HEX_OFFSET)
382 chpr += printf("@%#lx",entry_ptr->value + fileoffset_base);
383 else if((PRINT_DEC_OFFSET) || is_a_long_offset(entry_ptr))
384 chpr += printf("@%lu",entry_ptr->value + fileoffset_base);
385
386 if(fileoffset_base && (PRINT_ENTRY_RELOFFSET))
387 chpr += printf(" (%lu)",entry_ptr->value);
388 break;
389 default:
390 /* VALUES */
391 if(entry_ptr->tag == TIFFTAG_StripOffsets)
392 print_value(entry_ptr,"@");
393 else
394 print_value(entry_ptr,PREFIX);
395 /* This one is worth flagging... */
396 if((entry_ptr->tag == TIFFTAG_StripOffsets) &&
397 (entry_ptr->value == 0))
398 {
399 printred(" (BAD START OFFSET)");
400 }
401 interpret_value(entry_ptr,summary_entry);
402 break;
403 }
404 }
405 chpr = newline(chpr);
406 }
407 return(endoffset);
408 }
409
410
411 /* Some items are marked as LONG, but are intended to be interpreted */
412 /* as offsets. */
413
414 int
is_a_long_offset(struct ifd_entry * entry_ptr)415 is_a_long_offset(struct ifd_entry *entry_ptr)
416 {
417 int is_an_offset = 0;
418
419 if(entry_ptr)
420 {
421 switch(entry_ptr->tag)
422 {
423 case EXIFTAG_ExifIFDPointer:
424 case EXIFTAG_GPSInfoIFDPointer:
425 case EXIFTAG_Interoperability:
426 case TIFFTAG_JPEGInterchangeFormat:
427 ++is_an_offset;
428 break;
429 default:
430 break;
431 }
432 }
433 return(is_an_offset);
434 }
435
436 /* Repeat the tag identifier for values printed at an offset. This is */
437 /* called only when printing offset values at the offset (rather than */
438 /* "inline"), and repeats only one of the identifiers (preferably */
439 /* tagname). */
440
441 void
print_tagid(struct ifd_entry * entry_ptr,int indent,int ifdtype)442 print_tagid(struct ifd_entry *entry_ptr,int indent,int ifdtype)
443 {
444 char *nameoftag;
445 int chpr = 0;
446
447 if(entry_ptr && (PRINT_ENTRY))
448 {
449 if(PRINT_TAGNAME || !(PRINT_TAGNO))
450 {
451 switch(ifdtype)
452 {
453 case GPS_IFD:
454 nameoftag = gps_tagname(entry_ptr->tag);
455 break;
456 case INTEROP_IFD:
457 nameoftag = interop_tagname(entry_ptr->tag);
458 break;
459 case EXIF_IFD:
460 case TIFF_IFD:
461 case TIFF_SUBIFD:
462 default:
463 nameoftag = tagname(entry_ptr->tag);
464 break;
465 }
466 chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,nameoftag);
467 }
468 else if(PRINT_HEX_TAGNO)
469 chpr += printf("<%#06x>",entry_ptr->tag & 0xffff);
470 else if(PRINT_DEC_TAGNO)
471 chpr += printf("<%5u>",entry_ptr->tag & 0xffff);
472 }
473 setcharsprinted(chpr);
474 }
475
476
477 /* Print the part of an IFD entry describing the entry tag, including */
478 /* it's tag number, name and type. Only the items enabled in */
479 /* "Print_options" are printed. */
480
481 /* When the LONGNAMES option bit is set prefix the tag name with a */
482 /* section identifier (parent_name). */
483
484 void
print_taginfo(struct ifd_entry * entry_ptr,char * parent_name,int indent,int ifdtype,int ifdnum,int subifdnum)485 print_taginfo(struct ifd_entry *entry_ptr,char *parent_name,
486 int indent,int ifdtype,int ifdnum,int subifdnum)
487 {
488 char *nameoftag;
489 char *nameof_value_type;
490 int tagwidth = TAGWIDTH;
491 int chpr = 0;
492
493 if(entry_ptr && (PRINT_ENTRY))
494 {
495 if(PRINT_BOTH_TAGNO)
496 chpr += printf("<%#06x=%5u> ",entry_ptr->tag & 0xffff,entry_ptr->tag & 0xffff);
497 else if(PRINT_DEC_TAGNO)
498 chpr += printf("<%5u> ",entry_ptr->tag & 0xffff);
499 else if(PRINT_HEX_TAGNO)
500 chpr += printf("<%#06x> ",entry_ptr->tag & 0xffff);
501 if((PRINT_TAGNAME))
502 {
503 switch(ifdtype)
504 {
505 case GPS_IFD:
506 nameoftag = gps_tagname(entry_ptr->tag);
507 break;
508 case INTEROP_IFD:
509 nameoftag = interop_tagname(entry_ptr->tag);
510 break;
511 case EXIF_IFD:
512 case TIFF_IFD:
513 case TIFF_SUBIFD:
514 nameoftag = tagname(entry_ptr->tag);
515 break;
516 default:
517 nameoftag = tagname(entry_ptr->tag);
518 break;
519 }
520 if((PRINT_LONGNAMES))
521 printf("%s.",parent_name);
522 chpr += printf("%-*.*s",tagwidth,tagwidth,nameoftag ? nameoftag : "NULL");
523 }
524 if(PRINT_TYPE)
525 {
526 nameof_value_type = value_type_name(entry_ptr->value_type);
527 chpr += printf(" [%-2u=%-9.9s %5lu] ",entry_ptr->value_type,
528 nameof_value_type,entry_ptr->count);
529 }
530 if(PRINT_VALUE)
531 chpr += printf(" = ");
532 }
533 setcharsprinted(chpr);
534 }
535
536 /* Print a "value" from an ifd structure entry, according to the TIFF */
537 /* type recorded in the entry. Print in hex or decimal (or both) */
538 /* according to the global Print_options variable. */
539
540 void
print_value(struct ifd_entry * entry_ptr,char * prefix)541 print_value(struct ifd_entry *entry_ptr,char *prefix)
542 {
543 unsigned long byte;
544 unsigned short ushort_val;
545 unsigned long i;
546 int chpr = 0;
547
548 if(entry_ptr && (PRINT_VALUE))
549 {
550 if(prefix)
551 chpr += printf("%s",prefix);
552 switch(entry_ptr->value_type)
553 {
554 case SBYTE:
555 byte = entry_ptr->value;
556 for(i = 0; i < entry_ptr->count; ++i)
557 {
558 if(PRINT_BOTH_VALUE)
559 chpr += printf("%#x=%d",(unsigned int)((char)byte & 0xff),
560 (int)((char)byte & 0xff));
561 else if(PRINT_HEX_VALUE)
562 chpr += printf("%#x",(unsigned int)((char)byte & 0xff));
563 else if(PRINT_DEC_VALUE)
564 chpr += printf("%d",(int)((char)byte & 0xff));
565 byte >>= 8;
566 }
567 break;
568 case SHORT:
569 ushort_val = entry_ptr->value ;
570 if(PRINT_BOTH_VALUE)
571 chpr += printf("%#x=%u",ushort_val,ushort_val);
572 else if(PRINT_HEX_VALUE)
573 chpr += printf("%#x",ushort_val);
574 else if(PRINT_DEC_VALUE)
575 chpr += printf("%u",ushort_val);
576 if(entry_ptr->count > 1)
577 {
578 (void)putchar(','); ++chpr;
579 ushort_val = (entry_ptr->value & 0xffff0000) >> 16;
580 if(PRINT_BOTH_VALUE)
581 chpr += printf("%#x=%u",ushort_val,ushort_val);
582 else if(PRINT_HEX_VALUE)
583 chpr += printf("%#x",ushort_val);
584 else if(PRINT_DEC_VALUE)
585 chpr += printf("%u",ushort_val);
586 }
587 break;
588 case SSHORT:
589 ushort_val = entry_ptr->value & 0xffff;
590 if(PRINT_BOTH_VALUE)
591 chpr += printf("%#x=%d",(unsigned int)ushort_val,
592 (int)ushort_val);
593 else if(PRINT_HEX_VALUE)
594 chpr += printf("%#x",(unsigned int)ushort_val);
595 else if(PRINT_DEC_VALUE)
596 chpr += printf("%d",(int)ushort_val);
597 if(entry_ptr->count > 1)
598 {
599 (void)putchar(',');
600 ushort_val = (entry_ptr->value & 0xffff0000) >> 16;
601 if(PRINT_BOTH_VALUE)
602 chpr += printf("%#x=%d",(unsigned int)ushort_val,
603 (int)ushort_val);
604 else if(PRINT_HEX_VALUE)
605 chpr += printf("%#x",(unsigned int)ushort_val);
606 else if(PRINT_DEC_VALUE)
607 chpr += printf("%d",(int)ushort_val);
608 }
609 break;
610 case LONG:
611 if(PRINT_BOTH_VALUE)
612 chpr += printf("0x%08lx=%lu",entry_ptr->value,
613 entry_ptr->value);
614 else if(PRINT_HEX_VALUE)
615 chpr += printf("0x%08lx",entry_ptr->value);
616 else if(PRINT_DEC_VALUE)
617 chpr += printf("%lu",entry_ptr->value);
618 break;
619 case SLONG:
620 if(PRINT_BOTH_VALUE)
621 chpr += printf("%#lx=%ld",(unsigned long)entry_ptr->value,
622 (long)entry_ptr->value);
623 else if(PRINT_HEX_VALUE)
624 chpr += printf("%#lx",(unsigned long)entry_ptr->value);
625 else if(PRINT_DEC_VALUE)
626 chpr += printf("%ld",(long)entry_ptr->value);
627 break;
628 case ASCII:
629 byte = entry_ptr->value;
630 if(entry_ptr->count <= 4)
631 {
632 chpr += printf("\'");
633 for(i = 0; i < entry_ptr->count; ++i)
634 {
635 if(isprint(byte & 0xff))
636 (void)putchar(byte & 0xff);
637 else
638 chpr += printf("\\%03ld",byte & 0xff);
639 byte >>= 8;
640 ++chpr;
641 }
642 chpr += printf("\'");
643 }
644 break;
645 case FLOAT:
646 chpr += printf("%g",(float)entry_ptr->value);
647 break;
648 case DOUBLE: /* double is not possible in a direct ifd entry */
649 chpr += printf("# DOUBLE TYPE IS INVALID HERE");
650 break;
651 case UNDEFINED: /* fall through; handle these as BYTE */
652 case BYTE:
653 default:
654 byte = entry_ptr->value;
655 for(i = 0; i < entry_ptr->count; ++i)
656 {
657 if(i)
658 (void)putchar(',');
659 if(PRINT_BOTH_VALUE)
660 chpr += printf("%#lx=%lu",byte & 0xff,byte & 0xff);
661 else if(PRINT_HEX_VALUE)
662 chpr += printf("%#lx",byte & 0xff);
663 else if(PRINT_DEC_VALUE)
664 chpr += printf("%lu",byte & 0xff);
665 byte >>= 8;
666 }
667 /* UNDEFINED stuff may be ascii */
668 byte = entry_ptr->value;
669 if((entry_ptr->value_type == UNDEFINED) &&
670 (entry_ptr->count == 4) &&
671 isprint(byte & 0xff))
672
673 {
674 chpr += printf(" = \'");
675 for(i = 0; i < entry_ptr->count; ++i)
676 {
677 if(isprint(byte & 0xff))
678 (void)putchar(byte & 0xff);
679 else
680 (void)putchar('.');
681 byte >>= 8;
682 ++chpr;
683 }
684 (void)putchar('\'');
685 ++chpr;
686 }
687 break;
688 }
689 }
690 setcharsprinted(chpr);
691 }
692
693 /* Goto the offset given by an IFD entry whose value couldn't be */
694 /* squeezed into the 4 bytes of the entry itself, and read the value */
695 /* found at that offset, printing according to the TIFF type found in */
696 /* the entry. UNDEFINED entry types must/may be special-cased, else */
697 /* their presence and size will be noted and the data skipped or */
698 /* hexdumped. */
699
700 /* Returns the file pointer offset at the end of processing, which */
701 /* may be 0 if the seek or read fails, or if the entry does not have */
702 /* offset data, or the data is outside the current IFD (e.g. */
703 /* JPEGTables). */
704
705 unsigned long
print_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,char * parent_name,int ifdtype,int indent,int at_offset)706 print_offset_value(FILE *inptr,unsigned short byteorder,
707 struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
708 char *parent_name,int ifdtype,int indent,
709 int at_offset)
710 {
711 unsigned long endoffset = 0L;
712 unsigned long value_offset,dumplength,total;
713 char *nameoftag,*data;
714 int chpr = 0;
715
716 if(inptr && entry_ptr)
717 {
718 value_offset = fileoffset_base + entry_ptr->value;
719 endoffset = value_offset +
720 (value_type_size(entry_ptr->value_type) * entry_ptr->count);
721
722 if(PRINT_VALUE)
723 {
724 if((at_offset && (PRINT_VALUE_AT_OFFSET)) ||
725 ((PRINT_OFFSET) && (entry_ptr->value_type != UNDEFINED)))
726 chpr += printf(" = ");
727 switch(entry_ptr->value_type)
728 {
729 case UNDEFINED:
730 if(!at_offset && (PRINT_VALUE))
731 {
732 if(!(PRINT_OFFSET))
733 chpr += printf("@%lu:%lu",value_offset,entry_ptr->count);
734 else
735 chpr += printf(":%lu", entry_ptr->count);
736 }
737 switch(entry_ptr->tag)
738 {
739 case EXIFTAG_CFAPattern:
740 if(!at_offset && (PRINT_VALUE))
741 chpr += printf(" = ");
742 nameoftag = tagname(entry_ptr->tag);
743 setcharsprinted(chpr);
744 chpr = 0;
745 print_cfapattern(inptr,entry_ptr->count,
746 byteorder,value_offset,
747 parent_name,nameoftag);
748 break;
749 case EXIFTAG_UserComment:
750 if(!at_offset && (PRINT_VALUE))
751 chpr += printf(" = ");
752 setcharsprinted(chpr);
753 chpr = 0;
754 print_user_comment(inptr,entry_ptr->count,
755 value_offset,byteorder);
756 break;
757 case TIFFTAG_META_0xc353:
758 /* This should probably be handled */
759 /* through the 'private IFD' mechanism, */
760 /* but do it here for now. */
761 if(!at_offset && (PRINT_VALUE))
762 chpr += printf(" = ");
763 /* The first 8 bytes should say "UNICODE" */
764 if((data = (char *)read_bytes(inptr,8UL,value_offset)) && (strncmp(data,"UNICODE",8) == 0))
765 {
766 if(!(LIST_MODE))
767 chpr += printf("UNICODE: ");
768 setcharsprinted(chpr);
769 chpr = 0;
770 print_unicode(inptr,entry_ptr->count - 8,HERE,byteorder);
771 }
772 else
773 {
774 chpr = newline(chpr);
775 dumplength = entry_ptr->count;
776 hexdump(inptr,value_offset,dumplength,dumplength,16,0,SUBINDENT);
777 }
778 break;
779 case TIFFTAG_PrintIM:
780 case EXIFTAG_MakerNote:
781 case TIFFTAG_JPEGTables:
782 break;
783 /* TIFFEP_CFAPATTERN is not quite the same as */
784 /* EXIF_CFAPattern: it will be handled in */
785 /* interpret.c */
786 case TIFFEPTAG_CFAPattern:
787 case TIFFEPTAG_SpatialFrequencyResponse:
788 case EXIFTAG_SpatialFrequencyResponse:
789 case EXIFTAG_SpectralSensitivity:
790 case EXIFTAG_OECF:
791 /* fall through, until some routines are */
792 /* written for these. */
793 default:
794 /* Could make a pseudo-tag for 'count' in */
795 /* LIST mode... */
796 if(at_offset)
797 {
798 if(Max_undefined == 0L)
799 chpr += printf(" (not dumped, use -U)");
800 else
801 {
802 /* Even in LIST mode */
803 if((Max_undefined == DUMPALL) ||
804 (Max_undefined > entry_ptr->count))
805 dumplength = entry_ptr->count;
806 else
807 dumplength = Max_undefined;
808 chpr = newline(1);
809 hexdump(inptr,value_offset,entry_ptr->count,
810 dumplength,12,indent,SUBINDENT);
811 }
812 }
813 /* make certain we're at the end */
814 fseek(inptr,(long)(value_offset + entry_ptr->count),0);
815 break;
816 }
817 if(!at_offset && (PRINT_VALUE))
818 chpr += printf(" # UNDEFINED");
819 break;
820 case BYTE:
821 if(entry_ptr->tag == DNGTAG_OriginalRawFileName)
822 print_ascii(inptr,entry_ptr->count,value_offset);
823 else
824 print_ubytes(inptr,entry_ptr->count,value_offset);
825 break;
826 case SBYTE:
827 print_sbytes(inptr,entry_ptr->count,value_offset);
828 break;
829 case ASCII:
830 print_ascii(inptr,entry_ptr->count,value_offset);
831 if(Debug & NOTE_DEBUG)
832 {
833 if(entry_ptr->tag == TIFFTAG_Make)
834 chpr += printf(" [%d]",maker_number(Make_name));
835 else if(entry_ptr->tag == TIFFTAG_Model)
836 chpr += printf(" [%d]",model_number(maker_number(Make_name),
837 Model_name,CNULL));
838 }
839 break;
840 case SHORT:
841 if(entry_ptr->tag == TIFFTAG_StripOffsets)
842 chpr += printf("@");
843 print_ushort(inptr,entry_ptr->count,byteorder,value_offset);
844 if(entry_ptr->tag == TIFFTAG_StripByteCounts)
845 {
846 total = sum_strip_bytecounts(inptr,byteorder,
847 entry_ptr->value + fileoffset_base,
848 entry_ptr->count,entry_ptr->value_type);
849 chpr += printf(" = %lu",total);
850 }
851 break;
852 case SSHORT:
853 print_sshort(inptr,entry_ptr->count,byteorder,value_offset);
854 break;
855 case LONG:
856 if(entry_ptr->tag == TIFFTAG_StripOffsets)
857 chpr += printf("@");
858 print_ulong(inptr,entry_ptr->count,byteorder,value_offset);
859 if(entry_ptr->tag == TIFFTAG_StripByteCounts)
860 {
861 total = sum_strip_bytecounts(inptr,byteorder,
862 entry_ptr->value + fileoffset_base,
863 entry_ptr->count,entry_ptr->value_type);
864 chpr += printf(" = %lu",total);
865 }
866 break;
867 case SLONG:
868 print_slong(inptr,entry_ptr->count,byteorder,value_offset);
869 break;
870 case RATIONAL:
871 print_urational(inptr,entry_ptr->count,byteorder,value_offset);
872 break;
873 case SRATIONAL:
874 print_srational(inptr,entry_ptr->count,byteorder,value_offset);
875 break;
876 case FLOAT:
877 print_float(inptr,entry_ptr->count,byteorder,value_offset);
878 break;
879 case DOUBLE:
880 print_double(inptr,entry_ptr->count,byteorder,value_offset);
881 break;
882 default:
883 chpr += printf(" INVALID TYPE %#x",entry_ptr->value_type);
884 break;
885 }
886 setcharsprinted(chpr);
887 chpr = 0;
888 interpret_offset_value(inptr,entry_ptr,byteorder,fileoffset_base);
889 chpr = newline(chpr);
890 }
891 }
892 else
893 {
894 chpr += printf(" invalid call to print_offset_value() ");
895 if(inptr == (FILE *)0)
896 chpr += printf(" - no input file pointer ");
897 if(entry_ptr == (struct ifd_entry *)0)
898 chpr += printf(" - null entry pointer");
899 chpr = newline(chpr);
900 }
901 return(endoffset);
902 }
903
904 /* Read 'count' unsigned bytes starting at 'offset' and print their */
905 /* values in hex. If there are a lot, just print the first few, an */
906 /* elipsis to admit that something is left out, then print the count */
907 /* and the last value and it's offset. */
908
909 void
print_ubytes(FILE * inptr,unsigned long count,unsigned long offset)910 print_ubytes(FILE *inptr,unsigned long count,unsigned long offset)
911 {
912 int i,j;
913 unsigned short byte;
914 int chpr = 0;
915
916 if(count)
917 {
918 byte = read_ubyte(inptr,offset);
919 if(feof(inptr) || ferror(inptr))
920 {
921 clearerr(inptr);
922 setcharsprinted(chpr);
923 return;
924 }
925 chpr += printf("%02x",(unsigned int)byte & 0xff);
926 }
927 if(PRINT_MULTIVAL_ALL)
928 {
929 for(i = 1; i < count; ++i,offset += 2L)
930 {
931 byte = read_ubyte(inptr,HERE);
932 if(feof(inptr) || ferror(inptr))
933 {
934 clearerr(inptr);
935 setcharsprinted(chpr);
936 return;
937 }
938 chpr += printf(",%02x",(unsigned int)byte & 0xff);
939 }
940 }
941 else
942 {
943 #define MAX 10UL
944 j = count > MAX + 2 ? MAX : count;
945 for(i = 1; i < j; ++i)
946 {
947 byte = read_ubyte(inptr,HERE);
948 if(feof(inptr) || ferror(inptr))
949 {
950 clearerr(inptr);
951 setcharsprinted(chpr);
952 return;
953 }
954 chpr += printf(",%02x",(unsigned int)byte & 0xff);
955 }
956 if((count > j) && (ferror(inptr) == 0))
957 {
958 chpr += printf(" ... ");
959 offset += (unsigned long)(count - 1);
960 byte = read_ubyte(inptr,offset);
961 if(feof(inptr) || ferror(inptr))
962 {
963 clearerr(inptr);
964 setcharsprinted(chpr);
965 return;
966 }
967 chpr += printf(",%02x (%lu)",(unsigned int)byte & 0xff,count);
968 if(PRINT_ADDRESS)
969 chpr += printf(" -> @%lu",offset);
970 }
971 #undef MAX
972 }
973 }
974
975 /* Read 'count' signed bytes starting at 'offset' and print their */
976 /* values in decimale. If there are a lot, just print the first few, */
977 /* an elipsis to admit that something is left out, then print the */
978 /* last value and it's offset. */
979
980 void
print_sbytes(FILE * inptr,unsigned long count,unsigned long offset)981 print_sbytes(FILE *inptr,unsigned long count,unsigned long offset)
982 {
983 int i,j;
984 short byte;
985 int chpr = 0;
986
987 if(count)
988 {
989 byte = read_ubyte(inptr,offset);
990 if(feof(inptr) || ferror(inptr))
991 {
992 clearerr(inptr);
993 setcharsprinted(chpr);
994 return;
995 }
996 chpr += printf("%d",byte);
997 }
998 if(PRINT_MULTIVAL_ALL)
999 {
1000 for(i = 1; i < count; ++i,offset += 2L)
1001 {
1002 byte = read_ubyte(inptr,HERE);
1003 if(feof(inptr) || ferror(inptr))
1004 {
1005 clearerr(inptr);
1006 setcharsprinted(chpr);
1007 return;
1008 }
1009 chpr += printf(",%d",byte);
1010 }
1011 }
1012 else
1013 {
1014 #define MAX 10UL
1015 j = count > MAX + 2 ? MAX : count;
1016 for(i = 1; i < j; ++i)
1017 {
1018 byte = read_ubyte(inptr,HERE);
1019 if(feof(inptr) || ferror(inptr))
1020 {
1021 clearerr(inptr);
1022 setcharsprinted(chpr);
1023 return;
1024 }
1025 chpr += printf(",%d",byte);
1026 }
1027 if((count > j) && (ferror(inptr) == 0))
1028 {
1029 chpr += printf(" ... ");
1030 offset += (unsigned long)(count - 1);
1031 byte = read_ubyte(inptr,offset);
1032 if(feof(inptr) || ferror(inptr))
1033 {
1034 clearerr(inptr);
1035 setcharsprinted(chpr);
1036 return;
1037 }
1038 chpr += printf(",%d (%lu)",byte,count);
1039 if(PRINT_ADDRESS)
1040 chpr += printf(" -> @%lu",offset);
1041 }
1042 #undef MAX
1043 }
1044 setcharsprinted(chpr);
1045 }
1046
1047 /* Read 'count' unsigned short integers starting at 'offset' and */
1048 /* print their values. If there are a lot, just print the first few, */
1049 /* an elipsis to admit that something is left out, then print the */
1050 /* last value and it's offset. */
1051 void
print_ushort(FILE * inptr,unsigned long count,unsigned short byteorder,unsigned long offset)1052 print_ushort(FILE *inptr,unsigned long count,unsigned short byteorder,
1053 unsigned long offset)
1054 {
1055 int i,j;
1056 unsigned short value;
1057 int chpr = 0;
1058
1059 if(count)
1060 {
1061 value = read_ushort(inptr,byteorder,offset);
1062 if(feof(inptr) || ferror(inptr))
1063 {
1064 clearerr(inptr);
1065 setcharsprinted(chpr);
1066 return;
1067 }
1068 if(PRINT_BOTH_VALUE)
1069 chpr += printf("%#x/%u",value,value);
1070 else if(PRINT_HEX_VALUE)
1071 chpr += printf("%#x",value);
1072 else if(PRINT_DEC_VALUE)
1073 chpr += printf("%u",value);
1074 }
1075 if(PRINT_MULTIVAL_ALL)
1076 {
1077 for(i = 1; i < count; ++i,offset += 2L)
1078 {
1079 value = read_ushort(inptr,byteorder,HERE);
1080 if(feof(inptr) || ferror(inptr))
1081 {
1082 clearerr(inptr);
1083 setcharsprinted(chpr);
1084 return;
1085 }
1086 if(PRINT_BOTH_VALUE)
1087 chpr += printf(",%#x/%u",value,value);
1088 else if(PRINT_HEX_VALUE)
1089 chpr += printf(",%#x",value);
1090 else if(PRINT_DEC_VALUE)
1091 chpr += printf(",%u",value);
1092 }
1093 }
1094 else
1095 {
1096 #define MAX 5UL
1097 j = count > MAX + 2 ? MAX : count;
1098 for(i = 1; i < j; ++i,offset += 2L)
1099 {
1100 value = read_ushort(inptr,byteorder,HERE);
1101 if(feof(inptr) || ferror(inptr))
1102 {
1103 clearerr(inptr);
1104 setcharsprinted(chpr);
1105 return;
1106 }
1107 if(PRINT_BOTH_VALUE)
1108 chpr += printf(",%#x/%u",value,value);
1109 else if(PRINT_HEX_VALUE)
1110 chpr += printf(",%#x",value);
1111 else if(PRINT_DEC_VALUE)
1112 chpr += printf(",%u",value);
1113 }
1114 if((count > j) && (ferror(inptr) == 0))
1115 {
1116 chpr += printf(" ... ");
1117 offset += (unsigned long)(count - j) * 2L;
1118 value = read_ushort(inptr,byteorder,offset);
1119 if(feof(inptr) || ferror(inptr))
1120 {
1121 clearerr(inptr);
1122 setcharsprinted(chpr);
1123 return;
1124 }
1125 if(PRINT_BOTH_VALUE)
1126 chpr += printf(",%#x/%u (%lu)",value,value,count);
1127 else if(PRINT_HEX_VALUE)
1128 chpr += printf(",%#x (%lu)",value,count);
1129 else if(PRINT_DEC_VALUE)
1130 chpr += printf(",%u (%lu)",value,count);
1131 if(PRINT_ADDRESS)
1132 chpr += printf(" -> @%lu",offset);
1133 }
1134 #undef MAX
1135 }
1136 setcharsprinted(chpr);
1137 }
1138
1139 /* Read 'count' signed short integers starting at 'offset' and print */
1140 /* their values. If there are a lot, just print the first 5, an */
1141 /* elipsis to admit that something is left out, then print the last */
1142 /* value and it's offset. */
1143
1144 void
print_sshort(FILE * inptr,unsigned long count,unsigned short byteorder,unsigned long offset)1145 print_sshort(FILE *inptr,unsigned long count,unsigned short byteorder,
1146 unsigned long offset)
1147 {
1148 int i,j;
1149 short value;
1150 int chpr = 0;
1151
1152 if(count)
1153 {
1154 value = (short)read_ushort(inptr,byteorder,offset);
1155 if(feof(inptr) || ferror(inptr))
1156 {
1157 clearerr(inptr);
1158 setcharsprinted(chpr);
1159 return;
1160 }
1161 chpr += printf("%d",value);
1162 }
1163 if(PRINT_MULTIVAL_ALL)
1164 {
1165 for(i = 1; i < count; ++i,offset += 2L)
1166 {
1167 value = (short)read_ushort(inptr,byteorder,HERE);
1168 if(feof(inptr) || ferror(inptr))
1169 {
1170 clearerr(inptr);
1171 setcharsprinted(chpr);
1172 return;
1173 }
1174 chpr += printf(",%d",value);
1175 }
1176 }
1177 else
1178 {
1179 #define MAX 5UL
1180 j = count > MAX + 2 ? MAX : count;
1181 for(i = 1; i < j; ++i,offset += 2L)
1182 {
1183 value = (short)read_ushort(inptr,byteorder,HERE);
1184 if(feof(inptr) || ferror(inptr))
1185 {
1186 clearerr(inptr);
1187 setcharsprinted(chpr);
1188 return;
1189 }
1190 chpr += printf(",%d",value);
1191 }
1192 if(count > j)
1193 {
1194 chpr += printf(" ... ");
1195 offset += (unsigned long)(count - j) * 2L;
1196 value = (short)read_ushort(inptr,byteorder,offset);
1197 if(feof(inptr) || ferror(inptr))
1198 {
1199 clearerr(inptr);
1200 setcharsprinted(chpr);
1201 return;
1202 }
1203 chpr += printf(",%d (%lu)",value,count);
1204 if(PRINT_ADDRESS)
1205 chpr += printf(" -> @%lu",offset);
1206 }
1207 #undef MAX
1208 }
1209 setcharsprinted(chpr);
1210 }
1211
1212 /* Read 'count' unsigned long integers starting at 'offset' and print */
1213 /* their values. If there are a lot, just print the first 3, an */
1214 /* elipsis to admit that something is left out, then print the last */
1215 /* value and it's offset. */
1216
1217 void
print_ulong(FILE * inptr,unsigned long count,unsigned short byteorder,unsigned long offset)1218 print_ulong(FILE *inptr,unsigned long count,unsigned short byteorder,
1219 unsigned long offset)
1220 {
1221 int i,j;
1222 unsigned long value;
1223 int chpr = 0;
1224
1225 if(count)
1226 {
1227 value = read_ulong(inptr,byteorder,offset);
1228 if(feof(inptr) || ferror(inptr))
1229 {
1230 clearerr(inptr);
1231 setcharsprinted(chpr);
1232 return;
1233 }
1234 if(PRINT_BOTH_VALUE)
1235 chpr += printf("%#lx/%lu",value,value);
1236 else if(PRINT_HEX_VALUE)
1237 chpr += printf("%#lx",value);
1238 else if(PRINT_DEC_VALUE)
1239 chpr += printf("%lu",value);
1240 }
1241 if(PRINT_MULTIVAL_ALL)
1242 {
1243 for(i = 1; i < count; ++i,offset += 4L)
1244 {
1245 value = read_ulong(inptr,byteorder,HERE);
1246 if(feof(inptr) || ferror(inptr))
1247 {
1248 clearerr(inptr);
1249 setcharsprinted(chpr);
1250 return;
1251 }
1252 if(PRINT_BOTH_VALUE)
1253 chpr += printf(",%#lx/%lu",value,value);
1254 else if(PRINT_HEX_VALUE)
1255 chpr += printf(",%#lx",value);
1256 else if(PRINT_DEC_VALUE)
1257 chpr += printf(",%lu",value);
1258 }
1259 }
1260 else
1261 {
1262 #define MAX 3UL
1263 j = count > MAX + 2 ? MAX : count;
1264 for(i = 1; i < j; ++i,offset += 4L)
1265 {
1266 value = read_ulong(inptr,byteorder,HERE);
1267 if(feof(inptr) || ferror(inptr))
1268 {
1269 clearerr(inptr);
1270 setcharsprinted(chpr);
1271 return;
1272 }
1273 if(PRINT_BOTH_VALUE)
1274 chpr += printf(",%#lx/%lu",value,value);
1275 else if(PRINT_HEX_VALUE)
1276 chpr += printf(",%#lx",value);
1277 else if(PRINT_DEC_VALUE)
1278 chpr += printf(",%lu",value);
1279 }
1280 if(count > j)
1281 {
1282 chpr += printf(" ... ");
1283 offset += (unsigned long)(count - j) * 4L;
1284 value = read_ulong(inptr,byteorder,offset);
1285 if(feof(inptr) || ferror(inptr))
1286 {
1287 clearerr(inptr);
1288 setcharsprinted(chpr);
1289 return;
1290 }
1291 if(PRINT_BOTH_VALUE)
1292 chpr += printf(",%#lx/%lu (%lu)",value,value,count);
1293 else if(PRINT_HEX_VALUE)
1294 chpr += printf(",%#lx (%lu)",value,count);
1295 else if(PRINT_DEC_VALUE)
1296 chpr += printf(",%lu (%lu)",value,count);
1297 if(PRINT_ADDRESS)
1298 chpr += printf(" -> @%lu",offset);
1299 }
1300 #undef MAX
1301 }
1302 setcharsprinted(chpr);
1303 }
1304
1305 /* Read 'count' signed long integers starting at 'offset' and print */
1306 /* their values. If there are a lot, just print the first 3, an */
1307 /* elipsis to admit that something is left out, then print the last */
1308 /* value and it's offset. */
1309
1310 void
print_slong(FILE * inptr,unsigned long count,unsigned short byteorder,unsigned long offset)1311 print_slong(FILE *inptr,unsigned long count,unsigned short byteorder,
1312 unsigned long offset)
1313 {
1314 int i,j;
1315 long value;
1316 int chpr = 0;
1317
1318 if(count)
1319 {
1320 value = (long)read_ulong(inptr,byteorder,offset);
1321 if(feof(inptr) || ferror(inptr))
1322 {
1323 clearerr(inptr);
1324 setcharsprinted(chpr);
1325 return;
1326 }
1327 chpr += printf("%ld",value);
1328 }
1329 if(PRINT_MULTIVAL_ALL)
1330 {
1331 for(i = 1; i < count; ++i,offset += 4L)
1332 {
1333 value = (long)read_ulong(inptr,byteorder,HERE);
1334 if(feof(inptr) || ferror(inptr))
1335 {
1336 clearerr(inptr);
1337 setcharsprinted(chpr);
1338 return;
1339 }
1340 chpr += printf(",%ld",value);
1341 }
1342 }
1343 else
1344 {
1345 #define MAX 3UL
1346 j = count > MAX + 2 ? MAX : count;
1347 for(i = 1; i < j; ++i)
1348 {
1349 value = (long)read_ulong(inptr,byteorder,HERE);
1350 if(feof(inptr) || ferror(inptr))
1351 {
1352 clearerr(inptr);
1353 setcharsprinted(chpr);
1354 return;
1355 }
1356 chpr += printf(",%ld",value);
1357 }
1358 if(count > j)
1359 {
1360 chpr += printf(" ... ");
1361 offset += (unsigned long)(count - j) * 4L;
1362 value = (long)read_ulong(inptr,byteorder,offset);
1363 if(feof(inptr) || ferror(inptr))
1364 {
1365 clearerr(inptr);
1366 setcharsprinted(chpr);
1367 return;
1368 }
1369 chpr += printf(",%ld (%lu)",value,count);
1370 if(PRINT_ADDRESS)
1371 chpr += printf(" -> @%lu",offset);
1372 }
1373 #undef MAX
1374 }
1375 setcharsprinted(chpr);
1376 }
1377
1378 /* Read 'count' unsigned rational values starting at 'offset' and */
1379 /* print their values. If there are a lot, just print the first 3, an */
1380 /* elipsis to admit that something is left out, then print the last */
1381 /* value and it's offset. */
1382
1383 void
print_urational(FILE * inptr,unsigned long count,unsigned short byteorder,unsigned long offset)1384 print_urational(FILE *inptr,unsigned long count,unsigned short byteorder,
1385 unsigned long offset)
1386 {
1387 int i,j;
1388 unsigned long num,denom;
1389 int chpr = 0;
1390
1391 if(count)
1392 {
1393 num = read_ulong(inptr,byteorder,offset);
1394 if(feof(inptr) || ferror(inptr))
1395 {
1396 clearerr(inptr);
1397 setcharsprinted(chpr);
1398 return;
1399 }
1400 denom = read_ulong(inptr,byteorder,HERE);
1401 if(feof(inptr) || ferror(inptr))
1402 {
1403 clearerr(inptr);
1404 setcharsprinted(chpr);
1405 return;
1406 }
1407 if(PRINT_RAW_VALUES)
1408 chpr += printf("%lu/%lu = ",num,denom);
1409 if(num == 0UL)
1410 chpr += printf("0");
1411 else
1412 chpr += printf("%g",(double)((double)num/(double)denom));
1413 }
1414 if(PRINT_MULTIVAL_ALL)
1415 {
1416 for(i = 1; i < count; ++i)
1417 {
1418 num = read_ulong(inptr,byteorder,HERE);
1419 if(feof(inptr) || ferror(inptr))
1420 {
1421 clearerr(inptr);
1422 setcharsprinted(chpr);
1423 return;
1424 }
1425 denom = read_ulong(inptr,byteorder,HERE);
1426 if(feof(inptr) || ferror(inptr))
1427 {
1428 clearerr(inptr);
1429 setcharsprinted(chpr);
1430 return;
1431 }
1432 if(PRINT_RAW_VALUES)
1433 chpr += printf("%lu/%lu = ",num,denom);
1434 if(num == 0UL)
1435 chpr += printf(",0");
1436 else
1437 chpr += printf(",%g",(double)((double)num/(double)denom));
1438 }
1439 }
1440 else
1441 {
1442 #define MAX 3UL
1443 j = count > MAX + 2 ? MAX : count;
1444 for(i = 1; i < j; ++i)
1445 {
1446 num = read_ulong(inptr,byteorder,HERE);
1447 if(feof(inptr) || ferror(inptr))
1448 {
1449 clearerr(inptr);
1450 setcharsprinted(chpr);
1451 return;
1452 }
1453 denom = read_ulong(inptr,byteorder,HERE);
1454 if(feof(inptr) || ferror(inptr))
1455 {
1456 clearerr(inptr);
1457 setcharsprinted(chpr);
1458 return;
1459 }
1460 if(PRINT_RAW_VALUES)
1461 chpr += printf("%lu/%lu = ",num,denom);
1462 if(num == 0UL)
1463 chpr += printf(",0");
1464 else
1465 chpr += printf(",%g",(double)((double)num/(double)denom));
1466 }
1467 if(count > j)
1468 {
1469 chpr += printf(" ... ");
1470 offset += (unsigned long)(count - j) * 8UL;
1471 fseek(inptr,offset,0);
1472 num = read_ulong(inptr,byteorder,HERE);
1473 if(feof(inptr) || ferror(inptr))
1474 {
1475 clearerr(inptr);
1476 setcharsprinted(chpr);
1477 return;
1478 }
1479 denom = read_ulong(inptr,byteorder,HERE);
1480 if(feof(inptr) || ferror(inptr))
1481 {
1482 clearerr(inptr);
1483 setcharsprinted(chpr);
1484 return;
1485 }
1486 if(PRINT_RAW_VALUES)
1487 chpr += printf("%lu/%lu = ",num,denom);
1488 else
1489 if(num == 0UL)
1490 chpr += printf(",0 (%lu)",count);
1491 else
1492 chpr += printf(",%g (%lu)",(double)((double)num/(double)denom),count);
1493 if(PRINT_ADDRESS)
1494 chpr += printf(" -> @%lu",offset);
1495 }
1496 #undef MAX
1497 }
1498 setcharsprinted(chpr);
1499 }
1500
1501 void
print_srational(FILE * inptr,unsigned long count,unsigned short byteorder,unsigned long offset)1502 print_srational(FILE *inptr,unsigned long count,unsigned short byteorder,
1503 unsigned long offset)
1504 {
1505 int i,j;
1506 long num,denom;
1507 int chpr = 0;
1508
1509 if(count)
1510 {
1511 num = (long)read_ulong(inptr,byteorder,offset);
1512 if(feof(inptr) || ferror(inptr))
1513 {
1514 clearerr(inptr);
1515 setcharsprinted(chpr);
1516 return;
1517 }
1518 denom = (long)read_ulong(inptr,byteorder,HERE);
1519 if(feof(inptr) || ferror(inptr))
1520 {
1521 clearerr(inptr);
1522 setcharsprinted(chpr);
1523 return;
1524 }
1525 if(PRINT_RAW_VALUES)
1526 chpr += printf("%ld/%ld = ",num,denom);
1527 if(num == 0UL)
1528 chpr += printf("0");
1529 else
1530 chpr += printf("%g",(double)((double)num/(double)denom));
1531 }
1532 if(PRINT_MULTIVAL_ALL)
1533 {
1534 for(i = 1; i < count; ++i)
1535 {
1536 num = (long)read_ulong(inptr,byteorder,HERE);
1537 if(feof(inptr) || ferror(inptr))
1538 {
1539 clearerr(inptr);
1540 setcharsprinted(chpr);
1541 return;
1542 }
1543 denom = (long)read_ulong(inptr,byteorder,HERE);
1544 if(feof(inptr) || ferror(inptr))
1545 {
1546 clearerr(inptr);
1547 setcharsprinted(chpr);
1548 return;
1549 }
1550 if(PRINT_RAW_VALUES)
1551 chpr += printf("%ld/%ld = ",num,denom);
1552 if(num == 0UL)
1553 chpr += printf(",0");
1554 else
1555 chpr += printf(",%g",(double)((double)num/(double)denom));
1556 }
1557 }
1558 else
1559 {
1560 #define MAX 3UL
1561 j = count > MAX + 2 ? MAX : count;
1562 for(i = 1; i < j; ++i)
1563 {
1564 num = (long)read_ulong(inptr,byteorder,HERE);
1565 if(feof(inptr) || ferror(inptr))
1566 {
1567 clearerr(inptr);
1568 setcharsprinted(chpr);
1569 return;
1570 }
1571 denom = (long)read_ulong(inptr,byteorder,HERE);
1572 if(feof(inptr) || ferror(inptr))
1573 {
1574 clearerr(inptr);
1575 setcharsprinted(chpr);
1576 return;
1577 }
1578 if(PRINT_RAW_VALUES)
1579 chpr += printf("%ld/%ld = ",num,denom);
1580 if(num == 0UL)
1581 chpr += printf(",0");
1582 else
1583 chpr += printf(",%g",(double)((double)num/(double)denom));
1584 }
1585 if(count > j)
1586 {
1587 chpr += printf(" ... ");
1588 offset += (unsigned long)(count - j) * 8UL;
1589 fseek(inptr,offset,0);
1590 num = (long)read_ulong(inptr,byteorder,HERE);
1591 if(feof(inptr) || ferror(inptr))
1592 {
1593 clearerr(inptr);
1594 setcharsprinted(chpr);
1595 return;
1596 }
1597 denom = (long)read_ulong(inptr,byteorder,HERE);
1598 if(feof(inptr) || ferror(inptr))
1599 {
1600 clearerr(inptr);
1601 setcharsprinted(chpr);
1602 return;
1603 }
1604 if(PRINT_RAW_VALUES)
1605 chpr += printf("%ld/%ld = ",num,denom);
1606 if(num == 0UL)
1607 chpr += printf(",0 (%lu)",count);
1608 else
1609 chpr += printf(",%g (%lu)",(double)((double)num/(double)denom),count);
1610 if(PRINT_ADDRESS)
1611 chpr += printf(" -> @%lu",offset);
1612 }
1613 #undef MAX
1614 }
1615 setcharsprinted(chpr);
1616 }
1617
1618 void
print_float(FILE * inptr,unsigned long count,unsigned short byteorder,unsigned long offset)1619 print_float(FILE *inptr,unsigned long count,unsigned short byteorder,
1620 unsigned long offset)
1621 {
1622 int i,j;
1623 double data;
1624 int chpr = 0;
1625
1626 if(count)
1627 {
1628 data = read_float(inptr,byteorder,offset);
1629 if(feof(inptr) || ferror(inptr))
1630 {
1631 clearerr(inptr);
1632 setcharsprinted(chpr);
1633 return;
1634 }
1635 chpr += printf("%g",data);
1636 }
1637 if(PRINT_MULTIVAL_ALL)
1638 {
1639 for(i = 1; i < count; ++i)
1640 {
1641 data = read_float(inptr,byteorder,HERE);
1642 if(feof(inptr) || ferror(inptr))
1643 {
1644 clearerr(inptr);
1645 setcharsprinted(chpr);
1646 return;
1647 }
1648 chpr += printf(",%g",data);
1649 }
1650 }
1651 else
1652 {
1653 #define MAX 3L
1654 j = count > MAX + 2 ? MAX : count;
1655 for(i = 1; i < j; ++i)
1656 {
1657 data = read_float(inptr,byteorder,HERE);
1658 if(feof(inptr) || ferror(inptr))
1659 {
1660 clearerr(inptr);
1661 setcharsprinted(chpr);
1662 return;
1663 }
1664 chpr += printf(",%g",data);
1665 }
1666 if(count > j)
1667 {
1668 chpr += printf(" ... ");
1669 offset += (unsigned long)(count - j) * 4L;
1670 data = read_float(inptr,byteorder,offset);
1671 chpr += printf(",%g (%lu)",data,count);
1672 if(PRINT_ADDRESS)
1673 chpr += printf(" -> @%lu",offset);
1674 }
1675 #undef MAX
1676 }
1677 setcharsprinted(chpr);
1678 }
1679
1680
1681 void
print_double(FILE * inptr,unsigned long count,unsigned short byteorder,unsigned long offset)1682 print_double(FILE *inptr,unsigned long count,unsigned short byteorder,
1683 unsigned long offset)
1684 {
1685 int i,j;
1686 double data;
1687 int chpr = 0;
1688
1689 if(count)
1690 {
1691 data = read_double(inptr,byteorder,offset);
1692 if(feof(inptr) || ferror(inptr))
1693 {
1694 clearerr(inptr);
1695 setcharsprinted(chpr);
1696 return;
1697 }
1698 chpr += printf("%g",data);
1699 }
1700 if(PRINT_MULTIVAL_ALL)
1701 {
1702 for(i = 1; i < count; ++i)
1703 {
1704 data = read_double(inptr,byteorder,HERE);
1705 if(feof(inptr) || ferror(inptr))
1706 {
1707 clearerr(inptr);
1708 setcharsprinted(chpr);
1709 return;
1710 }
1711 chpr += printf(",%g",data);
1712 }
1713 }
1714 else
1715 {
1716 #define MAX 3L
1717 j = count > MAX + 2 ? MAX : count;
1718 for(i = 1; i < j; ++i)
1719 {
1720 data = read_double(inptr,byteorder,HERE);
1721 chpr += printf(",%g",data);
1722 }
1723 if(count > j)
1724 {
1725 chpr += printf(" ... ");
1726 offset += (unsigned long)(count - j) * 8UL;
1727 data = read_double(inptr,byteorder,offset);
1728 if(feof(inptr) || ferror(inptr))
1729 {
1730 clearerr(inptr);
1731 setcharsprinted(chpr);
1732 return;
1733 }
1734 chpr += printf(",%g (%lu)",data,count);
1735 if(PRINT_ADDRESS)
1736 chpr += printf(" -> @%lu",offset);
1737 }
1738 #undef MAX
1739 }
1740 setcharsprinted(chpr);
1741 }
1742
1743 /* Print up to 'count' bytes read from the image file, starting at */
1744 /* 'offset', as an ascii string, expanding nulls and unprintable */
1745 /* characters. */
1746
1747 /* If PRINT_ASCII_IGNORE_LENGTH is set in Print_options, quit */
1748 /* printing (but not reading) if a null byte is encountered. */
1749
1750 int
print_ascii(FILE * inptr,unsigned long count,unsigned long offset)1751 print_ascii(FILE *inptr,unsigned long count,unsigned long offset)
1752 {
1753 int remaining;
1754 int nread;
1755 int ch,lastch;
1756 int chpr = 0;
1757 int indent = 0;
1758
1759 remaining = count;
1760 nread = 0;
1761 if((offset != HERE) && (fseek(inptr,offset,0) == -1))
1762 {
1763 chpr += printf(" seek failed to offset %lu to print ascii",offset);
1764 chpr = newline(chpr);
1765 }
1766 else
1767 {
1768 indent = charsprinted();
1769 lastch = 'A';
1770 (void)putchar('\'');
1771 chpr++;
1772 while((remaining > 0) && !feof(inptr))
1773 {
1774 ch = fgetc(inptr);
1775 ++nread;
1776 --remaining;
1777 if(ch && isprint(ch))
1778 {
1779 if(isdigit(ch) && (lastch == '\0'))
1780 chpr += printf("00");
1781 (void)putchar(ch);
1782 chpr++;
1783 }
1784 else if(ch == '\0')
1785 {
1786 if((PRINT_ASCII_IGNORE_LENGTH))
1787 {
1788 /* read it but don't print any more */
1789 while((remaining-- > 0) && !feof(inptr))
1790 {
1791 ch = fgetc(inptr);
1792 ++nread;
1793 }
1794 break;
1795 }
1796 chpr += printf("\\0");
1797 }
1798 else if((ch == '\n') && !(LIST_MODE))
1799 {
1800 chpr = newline(chpr);
1801 putindent(indent);
1802 }
1803 else if((ch == '\011') && !(LIST_MODE))
1804 {
1805 putchar(ch);
1806 ++ch;
1807 }
1808 else
1809 chpr += printf("\\%03o",(unsigned int)(ch & 0xff));
1810 lastch = ch;
1811 }
1812 (void)putchar('\'');
1813 chpr++;
1814 if(ferror(inptr))
1815 clearerr(inptr);
1816 }
1817 setcharsprinted(chpr);
1818 return(nread);
1819 }
1820
1821 /* Write 16 bit 'unicode' data. The data is read as unsigned short */
1822 /* characters and normally printed via putchar() (unsigned char). If */
1823 /* the user specifically requests PRINT_UNICODE, blast out both */
1824 /* bytes. */
1825 /* Any checks for UNICODE should be done by the caller. */
1826
1827 int
print_unicode(FILE * inptr,unsigned long count,unsigned long offset,unsigned short byteorder)1828 print_unicode(FILE *inptr,unsigned long count,unsigned long offset,unsigned short byteorder)
1829 {
1830 int remaining;
1831 int nread;
1832 int ch;
1833 int chpr = 0;
1834
1835 nread = 0;
1836 if((offset != HERE) && (fseek(inptr,offset,0) == -1))
1837 {
1838 chpr += printf(" seek failed to offset %lu to print unicode",offset);
1839 chpr = newline(chpr);
1840 }
1841
1842 remaining = count / 2;
1843 putchar('\''); ++chpr;
1844 while((remaining > 0) && !feof(inptr))
1845 {
1846 if(ch == 0)
1847 chpr += printf("\\0");
1848 else
1849 ch = read_ushort(inptr,byteorder,HERE);
1850 ++nread;
1851 ++chpr;
1852 --remaining;
1853 /* Write both bytes iff requested by user */
1854 if((PRINT_UNICODE))
1855 (void)fwrite((char *)&ch,2,1,stdout);
1856 else
1857 putchar(ch);
1858 }
1859 putchar('\''); ++chpr;
1860 if(ferror(inptr))
1861 clearerr(inptr);
1862
1863 setcharsprinted(chpr);
1864 return(nread);
1865 }
1866
1867 /* Print an ascii string, expanding nulls and unprintable characters. */
1868 /* Print up to a null byte, or up to 'maxchars', whichever occurs */
1869 /* first. */
1870
1871 /* ###%%% IGNORE_LENGTH? */
1872 int
show_string(char * string,int maxchars,int noquotes)1873 show_string(char *string,int maxchars,int noquotes)
1874 {
1875 int lastch;
1876 int chpr = 0;
1877 int indent = 0;
1878 int printed = 0;
1879 char *ch;
1880
1881 if(string)
1882 {
1883 indent = charsprinted();
1884 lastch = 'A';
1885 if(!noquotes)
1886 {
1887 (void)putchar('\'');
1888 chpr++;
1889 }
1890 ch = string;
1891 while(printed < maxchars)
1892 {
1893 if(*ch == '\0')
1894 {
1895 printf("\\0");
1896 break;
1897 }
1898 else if(isprint(*ch))
1899 {
1900 if(isdigit(*ch) && (lastch == '\0'))
1901 chpr += printf("00");
1902 (void)putchar(*ch);
1903 chpr++;
1904 }
1905 else if(*ch == '\n')
1906 {
1907 chpr = newline(chpr);
1908 putindent(indent);
1909 }
1910 else if(*ch == '\011')
1911 {
1912 putchar(*ch);
1913 ++ch;
1914 }
1915 else
1916 chpr += printf("\\%03o",(unsigned int)(*ch & 0xff));
1917 lastch = *ch;
1918 ++printed;
1919 ++ch;
1920 }
1921 if(!noquotes)
1922 {
1923 (void)putchar('\'');
1924 chpr++;
1925 }
1926 }
1927 setcharsprinted(chpr);
1928 return(printed);
1929 }
1930
1931
1932 /* Print the UserComment field from an EXIF segment, which is */
1933 /* expected at 'offset' in the file and should be 'count' bytes long. */
1934 /* The field begins with an 8 byte "character code", followed by */
1935 /* 'count - 8' bytes of actual comment. The length is printed as */
1936 /* "%d+8" to give the user the usable length of the comment, but */
1937 /* remind that the 8 bytes is there. An "undefined" field is printed */
1938 /* as ascii, but checked to see if it is filled with nulls or spaces. */
1939 /* Non-ascii comment types are simply hexdumped. */
1940
1941 void
print_user_comment(FILE * inptr,unsigned long count,unsigned long offset,unsigned short byteorder)1942 print_user_comment(FILE *inptr,unsigned long count,unsigned long offset,
1943 unsigned short byteorder)
1944 {
1945 char *data;
1946 int i;
1947 int chpr = 0;
1948
1949 /* The first 8 bytes identify the character code */
1950
1951 if(PRINT_ENTRY)
1952 {
1953 if(PRINT_SECTION)
1954 chpr += printf("length %lu+8: (CC=",count - 8);
1955 if((offset != HERE) && (fseek(inptr,offset,0) == -1))
1956 {
1957 chpr += printf("seek failed to offset %lu to process user comment)",offset);
1958 chpr = newline(chpr);
1959 }
1960 else if((data = (char *)read_bytes(inptr,8UL,HERE)))
1961 {
1962 if(offset == HERE)
1963 offset = ftell(inptr); /* need to return after check */
1964 if((data[0] == 0) || (strncmp(data,"ASCII",5) == 0))
1965 {
1966 if(PRINT_SECTION)
1967 {
1968 if(data[0] == 0)
1969 chpr += printf("undefined");
1970 else
1971 {
1972 for(i = 0; i < 8; ++i)
1973 {
1974 if(data[i] && isascii(data[i]))
1975 {
1976 (void)putchar(data[i]);
1977 chpr++;
1978 }
1979 }
1980 }
1981 (void)putchar(')');
1982 chpr++;
1983 chpr += printf(" = ");
1984 }
1985 i = 8;
1986 if(PRINT_SECTION)
1987 {
1988 /* check for all nulls */
1989 for( ; i < count; ++i)
1990 {
1991 if(fgetc(inptr) != '\0')
1992 break;
1993 }
1994 }
1995 if(i == count)
1996 chpr += printf(" (%lu nulls)",count - 8);
1997 else
1998 {
1999 /* check for all spaces */
2000 if(fseek(inptr,offset + 8,0))
2001 {
2002 chpr += printf(" re-seek to comment offset %lu failed ",offset + 8);
2003 chpr = newline(chpr);
2004 why(stdout);
2005 }
2006 else
2007 {
2008 i = 8;
2009 for( ; i < count; ++i)
2010 {
2011 if(fgetc(inptr) != ' ')
2012 break;
2013 }
2014 if(i >= count)
2015 chpr += printf("(%d spaces)",i - 8);
2016 else
2017 {
2018 if(fseek(inptr,offset + i,0))
2019 {
2020 chpr += printf(" re-seek to comment offset %lu failed ",offset + 8);
2021 why(stdout);
2022 }
2023 else
2024 {
2025 chpr++;
2026 /* note that the above loop strips leading spaces */
2027 if((i > 20) && (PRINT_SECTION))
2028 chpr += printf("(%d spaces)",i - 8);
2029 print_ascii(inptr,count - i,offset + i);
2030 }
2031 }
2032 }
2033 }
2034 if((LIST_MODE))
2035 {
2036 chpr += printf(" # CC='");
2037 if(data[0])
2038 {
2039 for(i = 0; i < 8; ++i)
2040 {
2041 if(data[i] && isascii(data[i]))
2042 {
2043 (void)putchar(data[i]);
2044 chpr++;
2045 }
2046 }
2047 putchar('\''); ++chpr;
2048 }
2049 else
2050 chpr += printf("undefined'");
2051 }
2052 }
2053 else if(strncmp(data,"UNICODE",5) == 0)
2054 {
2055 if((PRINT_SECTION))
2056 {
2057 for(i = 0; i < 8; ++i)
2058 {
2059 if(data[i] && isascii(data[i]))
2060 {
2061 (void)putchar(data[i]);
2062 chpr++;
2063 }
2064 }
2065 }
2066 print_unicode(inptr,count - 8,HERE,byteorder);
2067 if((LIST_MODE))
2068 {
2069 chpr += printf(" # CC='");
2070 if(data[0])
2071 {
2072 for(i = 0; i < 8; ++i)
2073 {
2074 if(data[i] && isascii(data[i]))
2075 {
2076 (void)putchar(data[i]);
2077 chpr++;
2078 }
2079 }
2080 putchar('\''); ++chpr;
2081 }
2082 else
2083 chpr += printf("undefined'");
2084 }
2085 }
2086 else
2087 {
2088 chpr = newline(chpr);
2089 hexdump(inptr,offset,count,count,16,0,SUBINDENT);
2090 chpr = newline(chpr);
2091 }
2092 }
2093 setcharsprinted(chpr);
2094 }
2095 }
2096
2097 #define COLORSTACKSIZE 16
2098 static int colorstack[COLORSTACKSIZE];
2099 static int colorstack_index = -1;
2100
2101 void
pushcolor(int color)2102 pushcolor(int color)
2103 {
2104 if(USE_COLOR)
2105 {
2106 if(colorstack_index < 0)
2107 {
2108 colorstack_index = 0;
2109 colorstack[0] = END_COLOR;
2110 }
2111 else if(colorstack_index >= COLORSTACKSIZE)
2112 colorstack_index = 0;
2113
2114 printf("\033[%dm",color);
2115 colorstack[++colorstack_index] = color;
2116 }
2117 }
2118
2119 void
popcolor()2120 popcolor()
2121 {
2122 if(USE_COLOR)
2123 {
2124 if(colorstack_index > 0)
2125 colorstack[colorstack_index--] = END_COLOR;
2126 printf("\033[0m");
2127 if(colorstack_index >= 0)
2128 printf("\033[%dm",colorstack[colorstack_index]);
2129 }
2130 }
2131
2132 void
printred(char * msg)2133 printred(char *msg)
2134 {
2135 int chpr = 0;
2136
2137 PUSHCOLOR(RED);
2138 chpr = printf("%s",msg);
2139 POPCOLOR();
2140 setcharsprinted(chpr);
2141 }
2142
2143 /* Print the Color Filter Array pattern in a human-readable form. */
2144 /* The array pattern is printed on a single line, as simply as */
2145 /* possible. This could be annoying for arrays larger than 2x2. */
2146
2147 /* This prints the color characters... */
2148 void
putcolorchar(unsigned short color)2149 putcolorchar(unsigned short color)
2150 {
2151 switch(color & 0xff)
2152 {
2153 case 0: putchar('R'); break;
2154 case 1: putchar('G'); break;
2155 case 2: putchar('B'); break;
2156 case 3: putchar('C'); break;
2157 case 4: putchar('M'); break;
2158 case 5: putchar('Y'); break;
2159 case 6: putchar('W'); break;
2160 default: putchar('?'); break;
2161 }
2162 setcharsprinted(1);
2163 }
2164
2165 /* ...and this does the grunt work. */
2166
2167 void
print_cfapattern(FILE * inptr,unsigned long count,unsigned short byteorder,unsigned long offset,char * parent_name,char * nameoftag)2168 print_cfapattern(FILE *inptr,unsigned long count,unsigned short byteorder,
2169 unsigned long offset,char *parent_name,char *nameoftag)
2170 {
2171 unsigned short horiz_repeat;
2172 unsigned short hr = 0;
2173 unsigned short vert_repeat;
2174 unsigned short vr = 0;
2175 unsigned short color;
2176 unsigned long cfaoffset,hoffset;
2177 int h,v,show;
2178 int chpr = 0;
2179 int curindent = 0;
2180
2181 #define MAX_REPEAT 8
2182 #define MAX_COLOR 6
2183 if((PRINT_SECTION))
2184 chpr += printf("length %lu: ",count);
2185 if(offset == HERE)
2186 cfaoffset = ftell(inptr);
2187 else
2188 cfaoffset = offset;
2189 horiz_repeat = read_ushort(inptr,byteorder,cfaoffset);
2190 vert_repeat = read_ushort(inptr,byteorder,HERE);
2191
2192 if((horiz_repeat == 0) || (vert_repeat == 0) ||
2193 (horiz_repeat > MAX_REPEAT) || (vert_repeat > MAX_REPEAT))
2194 {
2195 /* This section checks for possible byteorder reversal in the */
2196 /* repeat counts. */
2197 if(byteorder == TIFF_INTEL)
2198 {
2199 hr = read_ushort(inptr,TIFF_MOTOROLA,cfaoffset);
2200 vr = read_ushort(inptr,TIFF_MOTOROLA,HERE);
2201 }
2202 else
2203 {
2204 hr = read_ushort(inptr,TIFF_INTEL,HERE);
2205 vr = read_ushort(inptr,TIFF_INTEL,HERE);
2206 }
2207 if(PRINT_SECTION)
2208 {
2209 curindent = charsprinted() + chpr;
2210 chpr += printf("H=%#x/%u, V=%#x/%u ",horiz_repeat,vert_repeat,
2211 horiz_repeat,vert_repeat);
2212 PUSHCOLOR(RED);
2213 chpr += printf(" (INVALID or BYTE SWAPPED!)*");
2214 POPCOLOR();
2215 chpr = newline(chpr);
2216 }
2217 else
2218 {
2219 PUSHCOLOR(RED);
2220 chpr += printf("%ux%u",horiz_repeat,vert_repeat);
2221 chpr += printf(" # WARNING: repeat counts INVALID or BYTE SWAPPED");
2222 POPCOLOR();
2223 }
2224 if((hr > 0) && (vr > 0) &&
2225 ((hr < MAX_REPEAT) || (vr < MAX_REPEAT)))
2226 {
2227 horiz_repeat = hr;
2228 vert_repeat = vr;
2229 if(PRINT_SECTION)
2230 {
2231 print_tag_address(ENTRY|APP_ENTRY,HERE,0,"*");
2232 curindent -= charsprinted();
2233 putindent(curindent);
2234 }
2235 else if(PRINT_TAGINFO)
2236 {
2237 chpr = newline(chpr);
2238 print_tag_address(ENTRY|APP_ENTRY,HERE,MEDIUMINDENT,"*");
2239 if((PRINT_LONGNAMES))
2240 chpr += printf("%s.",parent_name);
2241 chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,nameoftag);
2242 if((PRINT_VALUE))
2243 chpr += printf(" = ");
2244 }
2245 }
2246 }
2247 if(PRINT_SECTION)
2248 {
2249 chpr += printf("H=%#x/%u, V=%#x/%u ",horiz_repeat,vert_repeat,
2250 horiz_repeat,vert_repeat);
2251 /* Some sanity checks */
2252 if((horiz_repeat == 0) || (vert_repeat == 0) ||
2253 (horiz_repeat > MAX_REPEAT) || (vert_repeat > MAX_REPEAT))
2254 {
2255 PUSHCOLOR(RED);
2256 chpr += printf(" INVALID REPEAT COUNT");
2257 POPCOLOR();
2258 }
2259 else
2260 {
2261 chpr += printf(" = ");
2262 hoffset = ftell(inptr);
2263 for(v = 0; v < vert_repeat; ++v)
2264 {
2265 putchar('[');
2266 ++chpr;
2267 /* show 2 repetitions */
2268 for(show = 0; show < 2; ++show)
2269 {
2270 for(h = 0; h < horiz_repeat; ++h)
2271 {
2272 color = read_ubyte(inptr,hoffset+h);
2273 if(ferror(inptr))
2274 break;
2275 if(color <= MAX_COLOR)
2276 {
2277 putcolorchar(color & 0xff);
2278 putchar(',');
2279 ++chpr;
2280 }
2281 else
2282 {
2283 putchar('?');
2284 ++chpr;
2285 setcharsprinted(chpr);
2286 return;
2287 }
2288 }
2289 }
2290 chpr += printf(" ...],");
2291 hoffset = ftell(inptr);
2292 }
2293 chpr += printf(" ...");
2294 if(hr)
2295 printred(" (BYTE SWAPPED) ");
2296 }
2297 }
2298 else
2299 {
2300 chpr += printf("%dx%d",horiz_repeat,vert_repeat);
2301 if((horiz_repeat == 0) || (vert_repeat == 0) ||
2302 (horiz_repeat > MAX_REPEAT) || (vert_repeat > MAX_REPEAT))
2303 {
2304 PUSHCOLOR(RED);
2305 chpr += printf("# INVALID REPEAT COUNT");
2306 POPCOLOR();
2307 }
2308 else
2309 {
2310 print_startvalue();
2311 hoffset = ftell(inptr);
2312 for(v = 0; v < vert_repeat; ++v)
2313 {
2314 for(h = 0; h < horiz_repeat; ++h)
2315 {
2316 color = read_ubyte(inptr,hoffset+h);
2317 if(ferror(inptr))
2318 break;
2319 if(color < MAX_COLOR)
2320 {
2321 putcolorchar(color & 0xff);
2322 if((h + 1) < horiz_repeat)
2323 putchar(',');
2324 ++chpr;
2325 }
2326 else
2327 {
2328 putchar('?');
2329 ++chpr;
2330 setcharsprinted(chpr);
2331 return;
2332 }
2333 }
2334 hoffset = ftell(inptr);
2335 if((v + 1) < vert_repeat)
2336 putchar(':');
2337 }
2338 print_endvalue();
2339 if(hr)
2340 printred(" # BYTE SWAPPED");
2341 }
2342 }
2343 if(ferror(inptr))
2344 clearerr(inptr);
2345 setcharsprinted(chpr);
2346 }
2347
2348 /* Dump a bunch of bytes in traditional hex/ascii format. The offset */
2349 /* and size of the chunk to dump are passed, with a separate argument */
2350 /* for the number of bytes to print, which is constrained to be <= */
2351 /* the size. The per-line width of the output is also passed */
2352 /* (sometimes this program uses 16, sometimes 12 if the chunk might */
2353 /* be in IFD format). */
2354
2355 /* This function checks to assure that the buffer in read_bytes() is */
2356 /* not overrun (read_bytes() can't report truncation) and loops on */
2357 /* the data if necessary. */
2358
2359 /* If the length of data to be printed is less than the actual size, */
2360 /* the last line is annotated with "ect..." to indicate that there is */
2361 /* more. On the other hand, if 'max_to_print' expires before the last */
2362 /* line is full, both fields are padded with spaces. */
2363
2364 /* NOTE: this routine never prints a final newline (intentionally) */
2365
2366 void
hexdump(FILE * inptr,unsigned long offset,unsigned long size,unsigned long max_to_print,int width,int indent,int subindent)2367 hexdump(FILE *inptr,unsigned long offset,unsigned long size,
2368 unsigned long max_to_print,int width,int indent,
2369 int subindent)
2370 {
2371 char *data,*next;
2372 int bytes = 0;
2373 int printed = 0;
2374 int etc = 0;
2375 unsigned long remaining,readlength;
2376 int i;
2377 int chpr = 0;
2378
2379 if(inptr)
2380 {
2381 if((size > 0L) && (max_to_print > 0L))
2382 {
2383 if(size > MAXBUFLEN)
2384 readlength = MAXBUFLEN;
2385 else
2386 readlength = size;
2387
2388 /* Always read in multiples of "width" if doing multiple */
2389 /* reads. */
2390 if(size > readlength)
2391 readlength = (readlength / width) * width;
2392 if(size < max_to_print)
2393 max_to_print = size;
2394
2395 if((offset != HERE) && (fseek(inptr,offset,0) == -1))
2396 {
2397 chpr += printf(" seek failed to offset %lu to print hex/ascii dump",offset);
2398 chpr = newline(chpr);
2399 why(stdout);
2400 return;
2401 }
2402 while((printed < max_to_print) && (data = (char *)read_bytes(inptr,readlength,HERE)))
2403 {
2404 if(feof(inptr) || ferror(inptr))
2405 {
2406 clearerr(inptr);
2407 setcharsprinted(chpr);
2408 break;
2409 }
2410 if(max_to_print < readlength)
2411 {
2412 readlength = max_to_print;
2413 ++etc;
2414 }
2415
2416 bytes = 0;
2417 while(bytes < readlength)
2418 {
2419 next = data;
2420 remaining = readlength - bytes;
2421
2422 /* start address of each line */
2423 print_tag_address(ENTRY|APP_ENTRY,offset + printed,
2424 indent + SUBINDENT," ");
2425 extraindent(subindent);
2426
2427 /* This is the hex part */
2428 for(i = 0; i < width; ++i)
2429 {
2430 if(i && ((i % 4) == 0))
2431 putchar(' ');
2432 if(i < remaining)
2433 chpr += printf("%02x ",(unsigned int)(*data++ & 0xff));
2434 else
2435 chpr += printf(" ");
2436 }
2437
2438 /* Now do it again for the ascii side */
2439 chpr += printf(" |");
2440 remaining = readlength - bytes;
2441 for(i = 0; i < width; ++i,++next,++bytes,++printed)
2442 {
2443 if(i >= remaining) /* pad at the end */
2444 putchar(' ');
2445 else if(isprint(*next))
2446 putchar(*next);
2447 else
2448 putchar('.'); /* can't win 'em all */
2449 ++chpr;
2450 }
2451 if(printed < max_to_print)
2452 chpr += printf("|\n"); /* every line except the last */
2453 else
2454 chpr += printf("|");
2455 }
2456 if((max_to_print - printed) < readlength)
2457 readlength = max_to_print - printed;
2458 }
2459 if(etc) /* didn't print the whole chunk... */
2460 chpr += printf(" etc...");
2461 }
2462 }
2463 else
2464 printred(" INTERNAL ERROR: no input file to hexdump()\n");
2465 setcharsprinted(chpr);
2466 }
2467
2468 /* indent the following text by printing 'indent' spaces */
2469 void
putindent(int spaces)2470 putindent(int spaces)
2471 {
2472 int spaces_left;
2473
2474 if(spaces > MAXINDENT)
2475 spaces = MAXINDENT;
2476 spaces_left = spaces;
2477 while(spaces_left-- > 0)
2478 (void)putchar(' ');
2479 setcharsprinted(spaces);
2480 }
2481
2482 /* conditionally indent the following text */
2483
2484 void
extraindent(int spaces)2485 extraindent(int spaces)
2486 {
2487 if(PRINT_INDENT)
2488 putindent(spaces);
2489 }
2490
2491 #define START_VALUE " = \'"
2492 void
print_startvalue()2493 print_startvalue()
2494 {
2495 printf("%s",START_VALUE);
2496 setcharsprinted(sizeof(START_VALUE));
2497 }
2498
2499 #define END_VALUE "\'"
2500 void
print_endvalue()2501 print_endvalue()
2502 {
2503 printf("%s",END_VALUE);
2504 setcharsprinted(sizeof(END_VALUE));
2505 }
2506
2507 /* Print the TIFF byteorder. If verbose, print as "(hex=ascii)", */
2508 /* otherwise just print the 2 bytes as a string, with octal escapes */
2509 /* for unprintable bytes. */
2510
2511 void
print_byteorder(unsigned short byteorder,int verbose)2512 print_byteorder(unsigned short byteorder,int verbose)
2513 {
2514 int chpr = 0;
2515
2516 if(verbose == 1)
2517 chpr += printf("(");
2518 else if(verbose == 2)
2519 chpr += printf("\'");
2520 (void)show_string((char *)&byteorder,2,1);
2521
2522 /* Check for a legitimate TIFF byteorder */
2523 if(verbose == 1)
2524 {
2525 switch(byteorder)
2526 {
2527 case TIFF_INTEL:
2528 case TIFF_MOTOROLA:
2529 chpr += printf("=%#06x)",byteorder);
2530 break;
2531 default:
2532 chpr +=printf("=%#06x=unknown)",byteorder);
2533 break;
2534 }
2535 }
2536 else if(verbose == 2)
2537 chpr += printf("\'");
2538 setcharsprinted(chpr);
2539 }
2540
2541 /* Print a "magic number". The 'size' argument should be 2 for */
2542 /* unsigned short magic numbers, 4 for unsigned long. */
2543
2544 void
print_magic(unsigned long magic,int size)2545 print_magic(unsigned long magic,int size)
2546 {
2547 int chpr = 0;
2548
2549 chpr += printf(" magic=%#06lx=",magic);
2550 show_string((char *)&magic,size,0);
2551 setcharsprinted(chpr);
2552 }
2553
2554 /* Check and clear the status recorded by jpeg_status() from */
2555 /* process_jpeg_segments() and report anomalies. Output is preceded */
2556 /* by shell comment markers and normally appears at the end of a */
2557 /* line. */
2558
2559 void
print_jpeg_status()2560 print_jpeg_status()
2561 {
2562 int status = 0;
2563
2564 /* get and clear the status */
2565 status = jpeg_status(status);
2566
2567 if((PRINT_SEGMENT))
2568 {
2569 if(status == JPEG_NO_SOI)
2570 printred(" ### (JPEG_SOI NOT FOUND)");
2571 if(status == JPEG_HAD_ERROR)
2572 printred(" ### (INVALID JPEG MARKER)");
2573 else if(status == JPEG_NO_EOI)
2574 printred(" ### (JPEG_EOI NOT FOUND)");
2575 else if(status == JPEG_EARLY_EOI)
2576 printred(" (JPEG_EOI FOUND EARLY)");
2577 }
2578 }
2579
2580 void
display_end_of_ifd(unsigned long max_ifd_offset,int ifdtype,int ifdnum,int subifdnum,int indent,char * ifdname,char * prefix)2581 display_end_of_ifd(unsigned long max_ifd_offset,int ifdtype,int ifdnum,int subifdnum,
2582 int indent,char *ifdname,char *prefix)
2583 {
2584 int chpr = 0;
2585 print_tag_address(SECTION,max_ifd_offset - 1,indent,prefix);
2586 switch(ifdtype)
2587 {
2588 case TIFF_IFD:
2589 if(PRINT_SECTION)
2590 chpr += printf("</IFD %d>",ifdnum);
2591 break;
2592 case TIFF_SUBIFD:
2593 if(PRINT_SECTION)
2594 chpr += printf("</SubIFD %d of IFD %d>",subifdnum,ifdnum);
2595 break;
2596 case INTEROP_IFD:
2597 if(PRINT_SECTION)
2598 chpr += printf("</Interoperability SubIFD>");
2599 break;
2600 case GPS_IFD:
2601 if(PRINT_SECTION)
2602 chpr += printf("</GPS SubIFD>");
2603 break;
2604 case EXIF_IFD:
2605 if(PRINT_SECTION)
2606 chpr += printf("</EXIF IFD>");
2607 break;
2608 case MAKER_SUBIFD:
2609 if(PRINT_SECTION)
2610 chpr += printf("</%s>",ifdname);
2611 break;
2612 default:
2613 if(PRINT_SECTION)
2614 chpr += printf("</UNKNOWN IFD TYPE %d>",ifdtype);
2615 break;
2616 }
2617 chpr = newline(chpr);
2618 }
2619
2620
2621
2622 /* Provide a short hex/ascii dump of interesting sections. The */
2623 /* default dumplength can be increased via the -U option. This allows */
2624 /* examination of the tables and CFA sections. */
2625
2626 void
dumpsection(FILE * inptr,unsigned long offset,unsigned long length,int indent)2627 dumpsection(FILE *inptr,unsigned long offset,unsigned long length,int indent)
2628 {
2629 unsigned long dumplength;
2630
2631 if(inptr)
2632 {
2633 if(Max_imgdump > 0L)
2634 dumplength = Max_imgdump;
2635 else
2636 dumplength = DEF_DUMPLENGTH;
2637 if(dumplength > length)
2638 dumplength = length;
2639 if(dumplength)
2640 {
2641 hexdump(inptr,offset,length,dumplength,16,indent,0);
2642 (void)newline(1);
2643 }
2644 }
2645 }
2646
2647 /* ================= PRIVATE IFDs ==================== */
2648
2649 /* process_private_ifd() reads an ifd section which is defined */
2650 /* "privately" (e.g. by a camera maker for use in makernotes) and for */
2651 /* which tag numbers are thus defined without reference to the TIFF */
2652 /* spec. Any interpretation of tag numbers, values, etc. must be */
2653 /* switched through routines which recognize the make of the camera */
2654 /* or other device which produced the file, and might potentially */
2655 /* need to recognize a "note version" as well. */
2656
2657 /* The routine currently assumes a single IFD (no IFD chaining), */
2658 /* which may be be short-sighted considering the inventive nature of */
2659 /* camera producers. Please stand by... */
2660
2661 /* There is a mild assumption that these IFDs will be contained in */
2662 /* makernotes, since the TIFF, JPEG and Exif specs do not provide for */
2663 /* such things outside the maker blob. */
2664
2665 unsigned long
process_private_ifd(FILE * inptr,unsigned short byteorder,unsigned long subifd_offset,unsigned long fileoffset_base,unsigned long max_offset,unsigned short subifd_ident,struct image_summary * summary_entry,char * parent_name,char * prefix,int make,int model,int indent)2666 process_private_ifd(FILE *inptr,unsigned short byteorder,
2667 unsigned long subifd_offset,unsigned long fileoffset_base,
2668 unsigned long max_offset,unsigned short subifd_ident,
2669 struct image_summary *summary_entry,char *parent_name,
2670 char *prefix,int make,int model,int indent)
2671 {
2672 struct ifd_entry *entry_ptr;
2673 unsigned long max_value_offset = 0L;
2674 unsigned long next_ifd_offset,current_offset,max_subifd_offset;
2675 unsigned long start_entry_offset,entry_offset,value_offset;
2676 int entry_num,num_entries,value_is_offset,use_second_pass;
2677 int chpr = 0;
2678
2679 if(inptr == (FILE *)0)
2680 {
2681 fprintf(stderr,"%s: no open file pointer to read makernote %s subifd\n",
2682 Progname,parent_name);
2683 return(0L);
2684 }
2685 if(summary_entry)
2686 summary_entry->filesubformat |= FILESUBFMT_MNSUBIFD;
2687
2688 /* If the section appears to be beyond the end of the parent ifd, */
2689 /* mark the start address to call attention. */
2690 if(max_offset && ((subifd_offset + fileoffset_base) > max_offset))
2691 prefix = "+";
2692
2693 max_subifd_offset = max_offset;
2694 print_tag_address(SECTION,subifd_offset + fileoffset_base,indent,prefix);
2695 if(PRINT_SECTION)
2696 chpr += printf("<%s SubIFD> (in MakerNote)",parent_name);
2697
2698 num_entries = read_ushort(inptr,byteorder,subifd_offset + fileoffset_base);
2699 if(ferror(inptr) || feof(inptr))
2700 goto blewit;
2701 current_offset = entry_offset = start_entry_offset = ftell(inptr);
2702 if(PRINT_SECTION)
2703 {
2704 chpr += printf(" %d entries ",num_entries);
2705 chpr += printf("starting at file offset %#lx=%lu",
2706 current_offset,current_offset);
2707 chpr = newline(chpr);
2708 }
2709 use_second_pass = value_is_offset = 0;
2710
2711 /* The direct entries */
2712 for(entry_num = 0; entry_num < num_entries; ++entry_num)
2713 {
2714 entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset);
2715 if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) ||
2716 ferror(inptr) || feof(inptr))
2717 {
2718 int invalid_entry = 0;
2719 unsigned long limit_offset = 0L;
2720
2721 print_tag_address(ENTRY,entry_offset,indent,prefix);
2722 chpr += printf(" INVALID MAKERNOTE SUBIFD ENTRY (%lu)",entry_ptr->value);
2723 chpr = newline(chpr);
2724 clearerr(inptr);
2725 current_offset = ftell(inptr);
2726 if(max_offset > 0)
2727 limit_offset = max_offset;
2728 else
2729 {
2730 if(fseek(inptr,0L,2) != -1)
2731 {
2732 limit_offset = ftell(inptr);
2733 fseek(inptr,0L,current_offset);
2734 }
2735 }
2736 /* If there's an error on input, or we can't check */
2737 /* for absurd num_entries, give up. */
2738 if(!ferror(inptr) && (limit_offset > 0))
2739 {
2740 /* If the number of entries would read past the */
2741 /* size of the IFD, or past EOF, give up */
2742 if((entry_offset + (12 * num_entries)) < limit_offset)
2743 {
2744 /* Limit the number of consecutive failures. */
2745 /* An apparently valid entry resets the count */
2746 /* to 0. */
2747 if(invalid_entry++ < MAX_INVALID_ENTRIES)
2748 {
2749 entry_offset = current_offset;
2750 continue;
2751 }
2752 }
2753 }
2754 chpr = newline(chpr);
2755 goto blewit;
2756 }
2757 current_offset = ftell(inptr);
2758
2759 print_tag_address(ENTRY,entry_offset,indent,prefix);
2760 value_offset = print_private_entry(inptr,byteorder,entry_ptr,fileoffset_base,
2761 subifd_ident,summary_entry,parent_name,
2762 prefix,make,model,SUBINDENT);
2763 if(value_offset == 0UL)
2764 value_offset = current_offset;
2765 if(value_offset > max_value_offset)
2766 max_value_offset = value_offset;
2767 if((PRINT_VALUE_AT_OFFSET) && (is_offset(entry_ptr)))
2768 ++use_second_pass;
2769 entry_offset = current_offset;
2770 }
2771
2772 next_ifd_offset = read_ulong(inptr,byteorder,current_offset);
2773
2774 /* offsets found in the next pass should be within the bounds of */
2775 /* the parent ifd. The following helps to detect chunks that are */
2776 /* written "out of place". */
2777
2778 /* There should be no next_ifd_offset (it should be 0) */
2779 /* ###%%% prepare for chains? */
2780 if(next_ifd_offset > 0L)
2781 {
2782 /* ###%%% report unwillingness to handle chained IFDs */
2783 if((PRINT_ADDRESS) && (PRINT_VALUE) && (PRINT_VALUE_AT_OFFSET))
2784 {
2785 print_tag_address(ENTRY,current_offset,indent,prefix);
2786 extraindent(SUBINDENT);
2787 chpr += printf("**** next IFD offset %lu ",next_ifd_offset);
2788 next_ifd_offset += fileoffset_base;
2789 if(next_ifd_offset < ftell(inptr))
2790 {
2791 printred("BAD NEXT IFD OFFSET");
2792 next_ifd_offset = 0L;
2793 }
2794 else
2795 chpr += printf("(+ %lu = %#lx/%lu)",fileoffset_base,
2796 next_ifd_offset,next_ifd_offset);
2797 chpr = newline(chpr);
2798 }
2799 else
2800 next_ifd_offset += fileoffset_base;
2801 /* This should never happen */
2802 max_subifd_offset = next_ifd_offset;
2803 }
2804 else
2805 {
2806 if((PRINT_ADDRESS) && (PRINT_VALUE) && (PRINT_VALUE_AT_OFFSET))
2807 {
2808 print_tag_address(ENTRY,current_offset,indent,prefix);
2809 extraindent(SUBINDENT);
2810 chpr += printf("**** next IFD offset 0");
2811 chpr = newline(chpr);
2812 }
2813 }
2814
2815 if(ferror(inptr) || feof(inptr))
2816 {
2817 chpr += printf(" READ NEXT IFD OFFSET FAILED ");
2818 chpr = newline(chpr);
2819 why(stdout);
2820 clearerr(inptr); /* keep going... */
2821 }
2822 else
2823 current_offset = ftell(inptr);
2824
2825 value_offset = current_offset;
2826
2827 /* Second pass, to evaluate entries which are stored indirectly. */
2828 /* This occurs when the value requires more than 4 bytes, AND for */
2829 /* certain LONG values which are intended to be used as offsets */
2830 if(use_second_pass)
2831 {
2832 if((PRINT_VALUE) && (PRINT_ADDRESS) && (PRINT_VALUE_AT_OFFSET))
2833 {
2834 print_tag_address(ENTRY,value_offset,indent,prefix);
2835 extraindent(SUBINDENT);
2836 chpr += printf("============= VALUES, %s IFD ============",parent_name);
2837 chpr = newline(chpr);
2838 }
2839
2840 entry_offset = start_entry_offset;
2841 for(entry_num = 0; entry_num < num_entries; ++entry_num)
2842 {
2843 entry_ptr = read_ifd_entry(inptr,byteorder,entry_offset);
2844 if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) ||
2845 ferror(inptr) || feof(inptr))
2846 {
2847 /* If the first pass made it through invalid entries, */
2848 /* this pass should just ignore them and quietly */
2849 /* continue. */
2850 clearerr(inptr);
2851 entry_offset = current_offset = ftell(inptr);
2852 continue;
2853 }
2854 current_offset = entry_offset = ftell(inptr);
2855 if(is_offset(entry_ptr) ||
2856 private_value_is_offset(make,subifd_ident,entry_ptr->tag))
2857 {
2858 value_offset = print_offset_pe_value(inptr,byteorder,
2859 entry_ptr,fileoffset_base,
2860 subifd_ident,summary_entry,
2861 parent_name,prefix,indent,
2862 make,model,1);
2863 }
2864 if(value_offset > max_value_offset)
2865 max_value_offset = value_offset;
2866 }
2867 }
2868 else if(current_offset > max_value_offset)
2869 max_value_offset = current_offset;
2870
2871 if(max_offset && (max_value_offset > max_offset))
2872 {
2873 max_value_offset = max_offset;
2874 print_tag_address(SECTION,max_value_offset - 1,indent,">");
2875 }
2876 else
2877 print_tag_address(SECTION,max_value_offset - 1,indent,"-");
2878 if(PRINT_SECTION)
2879 {
2880 chpr += printf("</%s SubIFD> (in MakerNote)",parent_name);
2881 chpr = newline(chpr);
2882 }
2883
2884 return(max_value_offset);
2885 blewit:
2886 clearerr(inptr);
2887 current_offset = ftell(inptr);
2888 print_tag_address(SECTION,current_offset - 1,indent,"-");
2889 if(PRINT_SECTION)
2890 {
2891 chpr += printf("</EXIF IFD>");
2892 chpr = newline(chpr);
2893 }
2894 return(0L);
2895 }
2896
2897 unsigned long
print_private_entry(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,unsigned short subifd_ident,struct image_summary * summary_entry,char * parent_name,char * prefix,int make,int model,int indent)2898 print_private_entry(FILE *inptr,unsigned short byteorder,struct ifd_entry *entry_ptr,
2899 unsigned long fileoffset_base, unsigned short subifd_ident,
2900 struct image_summary *summary_entry, char *parent_name,
2901 char *prefix,int make,int model,int indent)
2902 {
2903 int value_is_offset = 0;
2904 unsigned long endoffset = 0UL;
2905 int chpr = 0;
2906
2907 if((PRINT_ENTRY))
2908 {
2909 value_is_offset = is_offset(entry_ptr);
2910 if(value_is_offset == 0)
2911 value_is_offset = private_value_is_offset(make,subifd_ident,entry_ptr->tag);
2912 print_private_taginfo(entry_ptr,subifd_ident,parent_name,make,indent);
2913 if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE) ||
2914 ferror(inptr) || feof(inptr))
2915 {
2916 clearerr(inptr);
2917 printred("# INVALID ENTRY");
2918 endoffset = ftell(inptr);
2919 }
2920 else if(entry_ptr->count == 0)
2921 {
2922 if(PRINT_VALUE)
2923 chpr += printf(" EMPTY (value=%#lx)",entry_ptr->value);
2924 endoffset = ftell(inptr);
2925 }
2926 else if(value_is_offset)
2927 {
2928 if(value_is_offset > 0)
2929 {
2930 /* Offsets read from the file are printed relative to the */
2931 /* beginning of the file (with fileoffset_base added) so */
2932 /* that the values, printed later, will be easy to find. */
2933 if(PRINT_BOTH_OFFSET)
2934 chpr += printf("@%#lx=%lu",entry_ptr->value + fileoffset_base,
2935 entry_ptr->value + fileoffset_base);
2936 else if(PRINT_HEX_OFFSET)
2937 chpr += printf("@%#lx",entry_ptr->value + fileoffset_base);
2938 else if(PRINT_DEC_OFFSET)
2939 chpr += printf("@%lu",entry_ptr->value + fileoffset_base);
2940
2941 if(fileoffset_base && (PRINT_ENTRY_RELOFFSET))
2942 chpr += printf(" (%lu) ",entry_ptr->value);
2943 }
2944 else if((value_is_offset < 0) && (PRINT_VALUE))
2945 {
2946 print_value(entry_ptr,PREFIX);
2947 interpret_pe_value(entry_ptr,subifd_ident,make,prefix);
2948 }
2949
2950 /* Print "inline" in REPORT & LIST modes */
2951 if(!(PRINT_VALUE_AT_OFFSET))
2952 {
2953 setcharsprinted(chpr);
2954 chpr = 0;
2955 endoffset = print_offset_pe_value(inptr,byteorder,
2956 entry_ptr,fileoffset_base,
2957 subifd_ident,summary_entry,
2958 parent_name,"@",indent + MEDIUMINDENT,
2959 make,model,0);
2960 }
2961 }
2962 else if(PRINT_VALUE)
2963 {
2964 print_value(entry_ptr,PREFIX);
2965 interpret_pe_value(entry_ptr,subifd_ident,make,prefix);
2966 }
2967 chpr = newline(chpr);
2968 }
2969 return(endoffset);
2970 }
2971
2972 int
private_value_is_offset(int make,unsigned short subifd_ident,unsigned short tag)2973 private_value_is_offset(int make,unsigned short subifd_ident,unsigned short tag)
2974 {
2975 int is_offset = 0;
2976
2977 switch(make)
2978 {
2979 case MAKER_OLYMPUS:
2980 is_offset = olympus_private_value_is_offset(subifd_ident,tag);
2981 break;
2982 default:
2983 break;
2984 }
2985 return(is_offset);
2986 }
2987
2988 void
print_private_taginfo(struct ifd_entry * entry_ptr,unsigned short subifd_ident,char * parent_name,int make,int indent)2989 print_private_taginfo(struct ifd_entry *entry_ptr,unsigned short subifd_ident,
2990 char *parent_name,int make,int indent)
2991 {
2992 char *nameoftag = CNULL;
2993 char *nameof_value_type = CNULL;
2994 int tagwidth = TAGWIDTH;
2995 int chpr = 0;
2996
2997 if(entry_ptr && (PRINT_ENTRY))
2998 {
2999 extraindent(indent);
3000 if(PRINT_BOTH_TAGNO)
3001 chpr += printf("<%#06x=%5u> ",entry_ptr->tag & 0xffff,entry_ptr->tag & 0xffff);
3002 else if(PRINT_DEC_TAGNO)
3003 chpr += printf("<%5u> ",entry_ptr->tag & 0xffff);
3004 else if(PRINT_HEX_TAGNO)
3005 chpr += printf("<%#06x> ",entry_ptr->tag & 0xffff);
3006 if((PRINT_TAGNAME))
3007 {
3008 nameoftag = private_tagname(make,entry_ptr->tag,subifd_ident);
3009 if((PRINT_LONGNAMES))
3010 chpr += printf("%s.",parent_name);
3011 chpr += printf("%-*.*s",tagwidth,tagwidth,nameoftag ? nameoftag : "NULL");
3012 }
3013 if(PRINT_TYPE)
3014 {
3015 nameof_value_type = value_type_name(entry_ptr->value_type);
3016 chpr += printf(" [%-2u=%-9.9s %5lu] ",entry_ptr->value_type,
3017 nameof_value_type,entry_ptr->count);
3018 }
3019 if(PRINT_VALUE)
3020 chpr += printf(" = ");
3021 }
3022 setcharsprinted(chpr);
3023 }
3024
3025 void
print_private_tagid(struct ifd_entry * entry_ptr,unsigned short subifd_ident,int make,int indent)3026 print_private_tagid(struct ifd_entry *entry_ptr,unsigned short subifd_ident,
3027 int make,int indent)
3028 {
3029 char *nameoftag;
3030 int chpr = 0;
3031
3032 if(entry_ptr && (PRINT_ENTRY))
3033 {
3034 extraindent(indent);
3035 if(PRINT_TAGNAME || !(PRINT_TAGNO))
3036 {
3037 nameoftag = private_tagname(make,entry_ptr->tag,subifd_ident);
3038 chpr += printf("%-*.*s",TAGWIDTH,TAGWIDTH,nameoftag);
3039 }
3040 else if(PRINT_HEX_TAGNO)
3041 chpr += printf("<%#06x>",entry_ptr->tag & 0xffff);
3042 else if(PRINT_DEC_TAGNO)
3043 chpr += printf("<%5u>",entry_ptr->tag & 0xffff);
3044 /* ###%%% should be done just befor value is printed, not */
3045 /* here */
3046 if(PRINT_VALUE)
3047 chpr += printf(" = ");
3048 }
3049 setcharsprinted(chpr);
3050 }
3051
3052 char *
private_tagname(int make,unsigned short tag,unsigned short subifd_ident)3053 private_tagname(int make,unsigned short tag,unsigned short subifd_ident)
3054 {
3055 static char unknown_buf[16];
3056 char *tagname = CNULL;
3057
3058 switch(make)
3059 {
3060 case MAKER_OLYMPUS:
3061 tagname = olympus_private_tagname(tag,subifd_ident);
3062 break;
3063 default:
3064 break;
3065 }
3066 if(tagname == CNULL)
3067 {
3068 unknown_buf[0] = '\0';
3069 if(snprintf(unknown_buf,11,"TAG_%#06x",(int)tag) > 11)
3070 {
3071 printf(" bad tag %#x not converted\n",tag);
3072 why(stdout);
3073 tagname = "<BADTAG>";
3074 }
3075 else
3076 tagname = unknown_buf;
3077 }
3078 return(tagname);
3079 }
3080
3081 /* Interpret private entry values */
3082
3083 void
interpret_pe_value(struct ifd_entry * entry_ptr,unsigned short subifd_ident,int make,char * prefix)3084 interpret_pe_value(struct ifd_entry *entry_ptr,unsigned short subifd_ident,
3085 int make,char *prefix)
3086 {
3087 if(entry_ptr)
3088 {
3089 switch(make)
3090 {
3091 case MAKER_OLYMPUS:
3092 olympus_interpret_pe_value(entry_ptr,subifd_ident,prefix);
3093 break;
3094 default:
3095 break;
3096 }
3097 }
3098 }
3099
3100 unsigned long
print_offset_pe_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,unsigned short subifd_ident,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)3101 print_offset_pe_value(FILE *inptr,unsigned short byteorder,struct ifd_entry *entry_ptr,
3102 unsigned long fileoffset_base,unsigned short subifd_ident,
3103 struct image_summary *summary_entry,char *parent_name,char*prefix,
3104 int indent,int make,int model,int at_offset)
3105 {
3106 unsigned long endoffset = 0L;
3107
3108 if(inptr && entry_ptr)
3109 {
3110 endoffset = fileoffset_base + entry_ptr->value +
3111 (value_type_size(entry_ptr->value_type) * entry_ptr->count);
3112
3113 switch(make)
3114 {
3115 case MAKER_OLYMPUS:
3116 olympus_offset_pe_value(inptr,byteorder,entry_ptr,fileoffset_base,
3117 subifd_ident,summary_entry,
3118 parent_name,prefix,indent,
3119 make,model,at_offset);
3120 break;
3121 default:
3122 print_private_offset_value(inptr,byteorder,entry_ptr,
3123 fileoffset_base,subifd_ident,
3124 parent_name,prefix,indent,
3125 make,model,at_offset);
3126 break;
3127 }
3128 }
3129 else
3130 {
3131 printred(" invalid call to print_offset_pe_makervalue ");
3132 if(inptr == (FILE *)0)
3133 printred(" no input file pointer ");
3134 if(entry_ptr == (struct ifd_entry *)0)
3135 printred(" null entry pointer");
3136 }
3137 if(ferror(inptr) || feof(inptr))
3138 clearerr(inptr);
3139 (void)newline(0);
3140 return(endoffset);
3141 }
3142
3143 void
print_private_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,unsigned short subifd_ident,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)3144 print_private_offset_value(FILE *inptr,unsigned short byteorder,
3145 struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
3146 unsigned short subifd_ident,char *parent_name, char *prefix,
3147 int indent,int make,int model,int at_offset)
3148 {
3149 unsigned long value_offset;
3150 unsigned long dumplength;
3151 int chpr = 0;
3152
3153 if((value_type_size(entry_ptr->value_type) * entry_ptr->count) > 4)
3154 {
3155 value_offset = fileoffset_base + entry_ptr->value;
3156 if(PRINT_VALUE)
3157 {
3158 if(at_offset)
3159 {
3160 print_tag_address(ENTRY,value_offset,indent,prefix);
3161 print_private_tagid(entry_ptr,subifd_ident,make,SUBINDENT);
3162 }
3163 else
3164 {
3165 if((PRINT_OFFSET) && (entry_ptr->value_type != UNDEFINED))
3166 chpr += printf(" = ");
3167 }
3168 switch(entry_ptr->value_type)
3169 {
3170 case UNDEFINED:
3171 /* Could make a pseudo-tag for 'count' in LIST */
3172 /* mode... */
3173 if((PRINT_SECTION))
3174 chpr += printf("length %-9lu # UNDEFINED",entry_ptr->count);
3175 else
3176 {
3177 if(!(PRINT_OFFSET))
3178 chpr += printf("@%lu",value_offset);
3179 chpr += printf(":%lu # UNDEFINED",entry_ptr->count);
3180 }
3181 if(Max_undefined == 0)
3182 {
3183 if((PRINT_SECTION))
3184 printred(" (not dumped, use -U)");
3185 }
3186 else
3187 {
3188 /* Even in LIST mode */
3189 if((Max_undefined == DUMPALL)
3190 || (Max_undefined > entry_ptr->count))
3191 dumplength = entry_ptr->count;
3192 else
3193 dumplength = Max_undefined;
3194 chpr = newline(1);
3195 hexdump(inptr,entry_ptr->value + fileoffset_base,
3196 entry_ptr->count,dumplength,12,
3197 indent,SUBINDENT);
3198 }
3199 /* make certain we're at the end */
3200 fseek(inptr,(long)(entry_ptr->value + fileoffset_base + entry_ptr->count),0);
3201 break;
3202 case ASCII:
3203 print_ascii(inptr,entry_ptr->count,value_offset);
3204 break;
3205 case BYTE:
3206 print_ubytes(inptr,entry_ptr->count,value_offset);
3207 break;
3208 case SBYTE:
3209 print_sbytes(inptr,entry_ptr->count,value_offset);
3210 break;
3211 case SHORT:
3212 print_ushort(inptr,entry_ptr->count,byteorder,value_offset);
3213 break;
3214 case SSHORT:
3215 print_sshort(inptr,entry_ptr->count,byteorder,value_offset);
3216 break;
3217 case LONG:
3218 print_ulong(inptr,entry_ptr->count,byteorder,value_offset);
3219 break;
3220 case SLONG:
3221 print_slong(inptr,entry_ptr->count,byteorder,value_offset);
3222 break;
3223 case RATIONAL:
3224 print_urational(inptr,entry_ptr->count,byteorder,value_offset);
3225 break;
3226 case SRATIONAL:
3227 print_srational(inptr,entry_ptr->count,byteorder,value_offset);
3228 break;
3229 case FLOAT:
3230 print_float(inptr,entry_ptr->count,byteorder,value_offset);
3231 break;
3232 case DOUBLE:
3233 print_double(inptr,entry_ptr->count,byteorder,value_offset);
3234 break;
3235 default:
3236 chpr = printf(" INVALID TYPE %#x",entry_ptr->value_type);
3237 break;
3238 }
3239 }
3240 }
3241 if(ferror(inptr) || feof(inptr))
3242 clearerr(inptr);
3243 setcharsprinted(chpr);
3244 }
3245
3246 /* ================= END PRIVATE IFDS ================== */
3247