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