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_maker.c,v 1.29 2005/07/24 17:27:09 alex Exp $";
11 #endif
12 
13 #include <stdio.h>
14 #include <string.h>
15 
16 #include "defs.h"
17 #include "summary.h"
18 #include "maker.h"
19 #include "datadefs.h"
20 #include "maker_datadefs.h"
21 #include "misc.h"
22 #include "tags.h"
23 #include "maker_extern.h"
24 #include "extern.h"
25 
26 extern struct camera_name Camera_make[];
27 
28 #ifndef STRCASESTR
29 #define STRCASESTR fake_strcasestr
30 extern char *fake_strcasestr(char *,char *);
31 #endif
32 
33 /* Print an IFD entry presumed to be from a MakerNote.                */
34 
35 /* This differs from print_entry() in that it dispatches              */
36 /* maker_tagname() to get tag names specific to a specific make and   */
37 /* (possibly) model, and calls print_makervalue() to intercept any    */
38 /* tags which may require special treatment due to maker oddities.    */
39 /* The maker-specific routines dispatched by print_makervalue() will  */
40 /* also handle interpretation of the tag values if known.             */
41 
42 unsigned long
print_makerentry(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,int indent,int make,int model)43 print_makerentry(FILE *inptr,unsigned short byteorder,
44                     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
45                     struct image_summary *summary_entry,char *parent_name,
46                     int indent,int make,int model)
47 {
48     int value_is_offset = 0;
49     unsigned long endoffset = 0UL;
50     int chpr = 0;
51 
52     value_is_offset = is_offset(entry_ptr);
53     if(value_is_offset == 0)
54         value_is_offset = maker_value_is_offset(entry_ptr,make,model);
55     else
56         value_is_offset += maker_value_is_offset(entry_ptr,make,model);
57 
58     if(PRINT_ENTRY)
59         print_makertaginfo(entry_ptr,parent_name,indent,make,model);
60     if((entry_ptr->value_type == 0) || (entry_ptr->value_type > DOUBLE))
61     {
62         if(PRINT_ENTRY)
63             chpr = printf("# INVALID MAKERNOTE ENTRY (%#lx)",entry_ptr->value);
64         endoffset = ftell(inptr);
65     }
66     else if(entry_ptr->count == 0)
67     {
68         if(PRINT_VALUE)
69             chpr = printf("EMPTY (%lu)",entry_ptr->value);
70         endoffset = ftell(inptr);
71     }
72     else if(value_is_offset)
73     {
74         if(value_is_offset > 0)
75         {
76             if(PRINT_BOTH_OFFSET)
77                 chpr += printf("@%#lx=%lu",entry_ptr->value + fileoffset_base,
78                         entry_ptr->value + fileoffset_base);
79             else if(PRINT_HEX_OFFSET)
80                 chpr += printf("@%#lx",entry_ptr->value + fileoffset_base);
81             else if(PRINT_DEC_OFFSET)
82                 chpr += printf("@%lu",entry_ptr->value + fileoffset_base);
83 
84             if(fileoffset_base && (PRINT_ENTRY_RELOFFSET))
85                 chpr += printf(" (%lu)",entry_ptr->value);
86         }
87         else if((value_is_offset < 0) && (PRINT_VALUE))
88             print_makervalue(entry_ptr,make,model,PREFIX);
89 
90         /* Print "inline" in REPORT & LIST modes                      */
91         if(!(PRINT_VALUE_AT_OFFSET))
92         {
93             setcharsprinted(chpr);
94             chpr = 0;
95             endoffset = print_offset_makervalue(inptr,byteorder,
96                                         entry_ptr,fileoffset_base,
97                                         summary_entry,parent_name,
98                                         "@",indent + SUBINDENT,
99                                         make,model,0);
100         }
101     }
102     else if(PRINT_VALUE)
103         print_makervalue(entry_ptr,make,model,PREFIX);
104     chpr = newline(chpr);
105     return(endoffset);
106 }
107 
108 /* Repeat the tag identifier for values printed at an offset. This is */
109 /* called only from the "*makervalue-at_offset()" routines when       */
110 /* printing offset values at the offset (rather than "inline"), and   */
111 /* repeats only one of the identifiers (preferably tagname) followed  */
112 /* by the value separator (if values are printed at all). If no tag   */
113 /* identifier is enabled in Print_options, the tag name will be       */
114 /* printed, as in the entry line printed by print_makertaginfo().     */
115 
116 /* The caller will normally pass the 'sep' argument as ' = ' if an    */
117 /* actual value is to follow, or ': ' if a description (e.g. length   */
118 /* of UNDEFINED segment which is not expanded).                       */
119 
120 void
print_makertagid(struct ifd_entry * entry_ptr,int width,char * sep,int make,int model)121 print_makertagid(struct ifd_entry *entry_ptr,int width, char *sep,
122                                                 int make,int model)
123 {
124     char *nameoftag;
125     int chpr = 0;
126 
127     if(entry_ptr)
128     {
129         if((PRINT_TAGNAME))
130         {
131             nameoftag = maker_tagname(entry_ptr->tag,make,model);
132             chpr = printf("%-*.*s",width,width,nameoftag);
133         }
134         else if(PRINT_HEX_TAGNO)
135             chpr = printf("<%#06x>",entry_ptr->tag & 0xffff);
136         else if(PRINT_DEC_TAGNO)
137             chpr = printf("<%5u>",entry_ptr->tag & 0xffff);
138         if(PRINT_VALUE)
139             chpr += printf("%s",sep ? sep : " = ");
140     }
141     setcharsprinted(chpr);
142 }
143 
144 /* Print the part of a MakerNote entry describing the entry tag,      */
145 /* including it's tag number, name and type. Only the items enabled   */
146 /* in "Print_options" are printed.                                    */
147 
148 /* In LIST mode prefix the tag name with a section identifier, so     */
149 /* that the resulting names may be recognized by patterns or regular  */
150 /* expressions applied to the output (e.g. 'egrep') in                */
151 /* post-processing.                                                   */
152 
153 void
print_makertaginfo(struct ifd_entry * entry_ptr,char * parent_name,int indent,int make,int model)154 print_makertaginfo(struct ifd_entry *entry_ptr,char *parent_name,
155                                         int indent,int make,int model)
156 {
157     char *nameoftag;
158     char *nameof_value_type;
159     int chpr = 0;
160 
161     if(entry_ptr)
162     {
163         if(PRINT_BOTH_TAGNO)
164             chpr = printf("<%#06X=%5u> ",entry_ptr->tag & 0xffff,entry_ptr->tag & 0xffff);
165         else if(PRINT_HEX_TAGNO)
166             chpr = printf("<%#06X> ",entry_ptr->tag & 0xffff);
167         else  if(PRINT_DEC_TAGNO)
168             chpr = printf("<%5u> ",entry_ptr->tag & 0xffff);
169         if((PRINT_TAGNAME))
170         {
171             nameoftag = maker_tagname(entry_ptr->tag,make,model);
172             if((PRINT_LONGNAMES))
173                 chpr += printf("%s.",parent_name);
174             chpr += printf("%-*.*s",MAKERTAGWIDTH,MAKERTAGWIDTH,nameoftag);
175         }
176         if(PRINT_TYPE)
177         {
178             nameof_value_type = value_type_name(entry_ptr->value_type);
179             chpr += printf(" [%2u=%-9.9s %5lu] ",entry_ptr->value_type,
180                     nameof_value_type,entry_ptr->count);
181         }
182         if(Debug & NOTE_DEBUG)
183         {
184             chpr += printf(" %d:%d,%d ",model,getnoteversion(),getnotetagset());
185         }
186         if(PRINT_VALUE)
187             chpr += printf(" = ");
188     }
189     setcharsprinted(chpr);
190 }
191 
192 /* Dispatch maker-specific routines to print (and possibly interpret) */
193 /* non-offset values in MakerNote IFDs. If the make is not known, the */
194 /* normal print_value() routine will be called, and the               */
195 /* maker-specific routines are free to do the same if the tag doesn't */
196 /* need special handling (such as a 4 byte UNDEFINED which should be  */
197 /* printed as ascii). The maker-specific routines can also call       */
198 /* routines to interpret the value (e.g "On", "Off", etc.) according  */
199 /* to the requirements of the make and model.                         */
200 
201 void
print_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)202 print_makervalue(struct ifd_entry *entry_ptr,int make,int model,char *prefix)
203 {
204     if(entry_ptr)
205     {
206         switch(make)
207         {
208             case MAKER_AGFA:
209                 print_agfa_makervalue(entry_ptr,make,model,PREFIX);
210                 break;
211             case MAKER_ASAHI:   /* Asahi is Pentax                    */
212             case MAKER_PENTAX:  /* Pentax is Asahi                    */
213                 print_asahi_makervalue(entry_ptr,make,model,PREFIX);
214                 break;
215             case MAKER_CANON:
216                 print_canon_makervalue(entry_ptr,make,model,PREFIX);
217                 break;
218             case MAKER_CASIO:
219                 print_casio_makervalue(entry_ptr,make,model,PREFIX);
220                 break;
221             case MAKER_EPSON:
222                 print_epson_makervalue(entry_ptr,make,model,PREFIX);
223                 break;
224             case MAKER_FUJIFILM:
225                 print_fujifilm_makervalue(entry_ptr,make,model,PREFIX);
226                 break;
227             case MAKER_HP:
228                 print_value(entry_ptr,PREFIX);
229                 break;
230             case MAKER_KODAK:
231                 print_value(entry_ptr,PREFIX);
232                 break;
233             case MAKER_KONICA:
234                 print_konica_makervalue(entry_ptr,make,model,PREFIX);
235                 break;
236             case MAKER_KYOCERA:
237                 print_kyocera_makervalue(entry_ptr,make,model,PREFIX);
238                 break;
239             case MAKER_LEICA:
240                 print_leica_makervalue(entry_ptr,make,model,PREFIX);
241                 break;
242             case MAKER_MINOLTA:
243                 print_minolta_makervalue(entry_ptr,make,model,PREFIX);
244                 break;
245             case MAKER_NIKON:
246                 print_nikon_makervalue(entry_ptr,make,model,PREFIX);
247                 break;
248             case MAKER_OLYMPUS:
249                 print_olympus_makervalue(entry_ptr,make,model,PREFIX);
250                 break;
251             case MAKER_PANASONIC:
252                 print_panasonic_makervalue(entry_ptr,make,model,PREFIX);
253                 break;
254             case MAKER_RICOH:
255                 print_value(entry_ptr,PREFIX);
256                 break;
257             case MAKER_SANYO:
258                 print_sanyo_makervalue(entry_ptr,make,model,PREFIX);
259                 break;
260             case MAKER_SIGMA:
261                 print_sigma_makervalue(entry_ptr,make,model,PREFIX);
262                 break;
263             case MAKER_SONY:
264                 print_sony_makervalue(entry_ptr,make,model,PREFIX);
265                 break;
266             case MAKER_TOSHIBA:
267                 print_toshiba_makervalue(entry_ptr,make,model,PREFIX);
268                 break;
269             case MAKER_TRAVELER:
270                 print_value(entry_ptr,PREFIX);
271                 break;
272             default: /* No maker_specific print routine available     */
273                 print_value(entry_ptr,PREFIX); /* use default`        */
274                 break;
275         }
276     }
277 }
278 
279 /* Print values found at offsets in a MakerNote entry by dispatching  */
280 /* maker-specific routines which know how to interpret UNDEFINED      */
281 /* values for that maker. These routines may also intercept "defined" */
282 /* values which are handled strangely, such as a "long" value which   */
283 /* is really an offset, or a 4-byte UNDEFINED value which is really   */
284 /* an offset to an UNDEFINED blob. If a maker-specific routine is     */
285 /* called, it must handle all values for that maker (possibly by      */
286 /* calling the generic routine). The generic and maker-specific       */
287 /* routines are all 'void' functions, which should assure that the    */
288 /* file pointer is moved past the subject data. This routine          */
289 /* clears any IO errors (or EOF) and returns the calculated file      */
290 /* offset of the end of the section.                                  */
291 
292 unsigned long
print_offset_makervalue(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)293 print_offset_makervalue(FILE *inptr,unsigned short byteorder,
294     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
295     struct image_summary *summary_entry,char *parent_name,char*prefix,
296     int indent,int make,int model,int at_offset)
297 {
298     unsigned long endoffset = 0L;
299 
300     if(inptr && entry_ptr)
301     {
302         if((value_type_size(entry_ptr->value_type) * entry_ptr->count) <= 4UL)
303             endoffset = 0;
304         else
305             endoffset = fileoffset_base + entry_ptr->value +
306                 (value_type_size(entry_ptr->value_type) * entry_ptr->count);
307 
308         switch(make)
309         {
310             case MAKER_AGFA:
311                 print_agfa_offset_makervalue(inptr,byteorder,entry_ptr,
312                                             fileoffset_base,summary_entry,
313 											parent_name,prefix,indent,make,
314 											model,at_offset);
315                 break;
316             case MAKER_ASAHI:   /* Pentax                             */
317             case MAKER_PENTAX:  /* Pentax                             */
318                 print_asahi_offset_makervalue(inptr,byteorder,entry_ptr,
319                                             fileoffset_base,summary_entry,
320 											parent_name,prefix,indent,make,
321 											model,at_offset);
322                 break;
323             case MAKER_CANON:
324                 print_canon_offset_makervalue(inptr,byteorder,entry_ptr,
325                                             fileoffset_base,summary_entry,
326                                             parent_name,prefix,indent,make,
327                                             model,at_offset);
328                 break;
329             case MAKER_CASIO:
330                 print_casio_offset_makervalue(inptr,byteorder,entry_ptr,
331                                             fileoffset_base,summary_entry,
332 											parent_name,prefix,indent,make,
333 											model,at_offset);
334                 break;
335             case MAKER_EPSON:
336                 print_epson_offset_makervalue(inptr,byteorder,entry_ptr,
337                                             fileoffset_base,summary_entry,
338 											parent_name,prefix,indent,make,
339 											model,at_offset);
340                 break;
341             case MAKER_FUJIFILM:
342                 print_fujifilm_offset_makervalue(inptr,byteorder,entry_ptr,
343                                             fileoffset_base,summary_entry,
344                                             parent_name,prefix,indent,
345                                             make,model,at_offset);
346                 break;
347             case MAKER_HP:
348                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
349                                             fileoffset_base,parent_name,prefix,indent,
350                                             make,model,at_offset);
351                 break;
352             case MAKER_KODAK:
353                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
354                                             fileoffset_base,parent_name,prefix,indent,
355                                             make,model,at_offset);
356                 break;
357             case MAKER_KYOCERA:
358                 print_kyocera_offset_makervalue(inptr,byteorder,entry_ptr,
359                                             fileoffset_base,summary_entry,
360                                             parent_name,prefix,indent,
361                                             make,model,at_offset);
362                 break;
363             case MAKER_KONICA:
364                 print_konica_offset_makervalue(inptr,byteorder,entry_ptr,
365                                             fileoffset_base,summary_entry,
366                                             parent_name,prefix,indent,
367                                             make,model,at_offset);
368                 break;
369             case MAKER_LEICA:
370                 print_leica_offset_makervalue(inptr,byteorder,entry_ptr,
371                                             fileoffset_base,summary_entry,
372                                             parent_name,prefix,indent,
373                                             make,model,at_offset);
374                 break;
375             case MAKER_MINOLTA:
376                 print_minolta_offset_makervalue(inptr,byteorder,entry_ptr,
377                                             fileoffset_base,summary_entry,
378 											parent_name,prefix,indent,make,
379 											model,at_offset);
380                 break;
381             case MAKER_NIKON:
382                 print_nikon_offset_makervalue(inptr,byteorder,entry_ptr,
383                                             fileoffset_base,summary_entry,
384 											parent_name,prefix,indent,make,
385 											model,at_offset);
386                 break;
387             case MAKER_OLYMPUS:
388                 print_olympus_offset_makervalue(inptr,byteorder,entry_ptr,
389                                             fileoffset_base,summary_entry,
390 											parent_name,prefix,indent,make,
391 											model,at_offset);
392                 break;
393             case MAKER_PANASONIC:
394                 print_panasonic_offset_makervalue(inptr,byteorder,entry_ptr,
395                                             fileoffset_base,summary_entry,
396                                             parent_name,prefix,indent,
397                                             make,model,at_offset);
398                 break;
399             case MAKER_RICOH:
400                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
401                                             fileoffset_base,parent_name,prefix,indent,
402                                             make,model,at_offset);
403                 break;
404             case MAKER_SANYO:
405                 print_sanyo_offset_makervalue(inptr,byteorder,entry_ptr,
406                                             fileoffset_base,summary_entry,
407 											parent_name,prefix,indent,make,
408 											model,at_offset);
409                 break;
410             case MAKER_SIGMA:
411                 print_sigma_offset_makervalue(inptr,byteorder,entry_ptr,
412                                             fileoffset_base,summary_entry,
413                                             parent_name,prefix,indent,
414                                             make,model,at_offset);
415                 break;
416             case MAKER_SONY:
417                 print_sony_offset_makervalue(inptr,byteorder,entry_ptr,
418                                             fileoffset_base,summary_entry,
419                                             parent_name,prefix,indent,
420                                             make,model,at_offset);
421                 break;
422             case MAKER_TOSHIBA:
423                 print_toshiba_offset_makervalue(inptr,byteorder,entry_ptr,
424                                             fileoffset_base,summary_entry,
425                                             parent_name,prefix,indent,
426                                             make,model,at_offset);
427                 break;
428             case MAKER_TRAVELER:
429                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
430                                             fileoffset_base,parent_name,prefix,indent,
431                                             make,model,at_offset);
432                 break;
433             default:
434                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
435                                             fileoffset_base,parent_name,prefix,indent,
436                                             make,model,at_offset);
437                 break;
438         }
439     }
440     else
441     {
442         printred(" invalid call to print_offset_makervalue ");
443         if(inptr == (FILE *)0)
444             printred(" no input file pointer ");
445         if(entry_ptr == (struct ifd_entry *)0)
446             printred(" null entry pointer");
447     }
448     if(ferror(inptr) || feof(inptr))
449         clearerr(inptr);
450     (void)newline(0);
451     if(ftell(inptr) > endoffset)
452         endoffset = ftell(inptr);
453     return(endoffset);
454 }
455 
456 /* Print the value found at an offset in a generic MakerNote, if no   */
457 /* maker-specific routine wants to deal with it. Similar to           */
458 /* print_offset_value(). The routine is expected to read or skip all  */
459 /* data associated with the entry.                                    */
460 
461 void
print_generic_offset_makervalue(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)462 print_generic_offset_makervalue(FILE *inptr,unsigned short byteorder,
463     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,char *parent_name,
464     char *prefix,int indent,int make,int model,int at_offset)
465 {
466     unsigned long value_offset;
467     unsigned long dumplength;
468     int chpr = 0;
469 
470     if((value_type_size(entry_ptr->value_type) * entry_ptr->count) > 4)
471     {
472         value_offset = fileoffset_base + entry_ptr->value;
473         if(PRINT_VALUE)
474         {
475             if(at_offset)
476             {
477                 print_tag_address(ENTRY,value_offset,indent,prefix);
478                 if(entry_ptr->value_type == UNDEFINED)
479                     print_makertagid(entry_ptr,MAKERTAGWIDTH," : ",make,model);
480                 else
481                     print_makertagid(entry_ptr,MAKERTAGWIDTH," = ",make,model);
482             }
483             else
484             {
485                 if((PRINT_OFFSET) && (entry_ptr->value_type != UNDEFINED))
486                     chpr += printf(" = ");
487             }
488             switch(entry_ptr->value_type)
489             {
490                 case UNDEFINED:
491                     /* Could make a pseudo-tag for 'count' in LIST    */
492                     /* mode...                                        */
493                     if((PRINT_SECTION) && at_offset && (PRINT_VALUE_AT_OFFSET))
494                         chpr += printf("length %-9lu # UNDEFINED",entry_ptr->count);
495                     else
496                     {
497                         if(!(PRINT_OFFSET))
498                             chpr += printf("@%lu",value_offset);
499                         chpr += printf(":%-9lu # UNDEFINED",entry_ptr->count);
500                     }
501                     if(Max_undefined == 0)
502                     {
503                         if((PRINT_SECTION))
504                             printred(" (not dumped, use -U)");
505                     }
506                     else
507                     {
508                         /* Even in LIST and REPORT modes              */
509                         if((Max_undefined == DUMPALL)
510                             || (Max_undefined > entry_ptr->count))
511                                 dumplength = entry_ptr->count;
512                         else
513                             dumplength = Max_undefined;
514                         chpr = newline(1);
515                         hexdump(inptr,entry_ptr->value + fileoffset_base,
516                                     entry_ptr->count,dumplength,12,
517                                     indent,SUBINDENT);
518                     }
519                     /* make certain we're at the end                  */
520                     fseek(inptr,entry_ptr->value + fileoffset_base + entry_ptr->count,0);
521                     break;
522                 case ASCII:
523                     print_ascii(inptr,entry_ptr->count,value_offset);
524                     break;
525                 case BYTE:
526                     print_ubytes(inptr,entry_ptr->count,value_offset);
527                     break;
528                 case SBYTE:
529                     print_sbytes(inptr,entry_ptr->count,value_offset);
530                     break;
531                 case SHORT:
532                     print_ushort(inptr,entry_ptr->count,byteorder,value_offset);
533                     break;
534                 case SSHORT:
535                     print_sshort(inptr,entry_ptr->count,byteorder,value_offset);
536                     break;
537                 case LONG:
538                     print_ulong(inptr,entry_ptr->count,byteorder,value_offset);
539                     break;
540                 case SLONG:
541                     print_slong(inptr,entry_ptr->count,byteorder,value_offset);
542                     break;
543                 case RATIONAL:
544                     print_urational(inptr,entry_ptr->count,byteorder,value_offset);
545                     break;
546                 case SRATIONAL:
547                     print_srational(inptr,entry_ptr->count,byteorder,value_offset);
548                     break;
549                 case FLOAT:
550                     print_float(inptr,entry_ptr->count,byteorder,value_offset);
551                     break;
552                 case DOUBLE:
553                     print_double(inptr,entry_ptr->count,byteorder,value_offset);
554                     break;
555                 default:
556                     chpr = printf(" INVALID TYPE %#x",entry_ptr->value_type);
557                     break;
558             }
559         }
560     }
561     if(ferror(inptr) || feof(inptr))
562         clearerr(inptr);
563     setcharsprinted(chpr);
564 }
565 
566 
567 void
print_scheme(FILE * inptr,struct maker_scheme * maker_scheme)568 print_scheme(FILE *inptr,struct maker_scheme *maker_scheme)
569 {
570     int chpr = 0;
571 
572     PUSHCOLOR(HI_BLACK);
573     chpr = newline(1);
574     chpr += printf("MakerNote Scheme:");
575     chpr += printf(" (at offset %lu, length %lu)",maker_scheme->note_fileoffset,
576                 maker_scheme->note_length);
577     chpr = newline(chpr);
578     chpr += printf("\tScheme Type = ");
579     switch(maker_scheme->scheme_type)
580     {
581         case PLAIN_IFD_SCHEME:
582             chpr += printf("\"Plain IFD\" (%#lx) at offset %lu",maker_scheme->scheme_type,
583                         maker_scheme->note_fileoffset);
584             chpr = newline(chpr);
585             break;
586         case HAS_ID_SCHEME:
587             chpr += printf("\"ID\" (%#lx)\n",maker_scheme->scheme_type);
588             chpr += printf("\tID = \"%s\";",maker_scheme->id[0] ? maker_scheme->id : "(NONE)");
589             chpr += printf(" length = %d, at offset %lu\n",maker_scheme->id_length,
590                         maker_scheme->note_fileoffset);
591             chpr += printf("\tIFD is offset %d from start of section",maker_scheme->ifd_offset);
592             chpr = newline(chpr);
593             break;
594         case HAS_ID_PLUS_TIFFHDR_SCHEME:
595             chpr += printf("\"ID plus TIFF header\" (%#lx)\n",maker_scheme->scheme_type);
596             chpr += printf("\tID = \"%s\";",maker_scheme->id[0] ? maker_scheme->id : "(NONE)");
597             chpr += printf("\tlength = %d, at offset %lu\n",maker_scheme->id_length,
598                         maker_scheme->note_fileoffset);
599             chpr += printf("\tTIFF header is offset %d from start of section\n",maker_scheme->tiffhdr_offset);
600             chpr += printf("\tIFD is offset %d from start of TIFF header",maker_scheme->ifd_offset);
601             chpr = newline(chpr);
602             break;
603         case UNKNOWN_SCHEME:
604         default:
605             chpr += printf("\"UNKNOWN\" (%#lx)\n",maker_scheme->scheme_type);
606             chpr += printf("\tID = \"%s\";",maker_scheme->id[0] ? maker_scheme->id : "(NONE)");
607             chpr += printf(" length = %d, at offset %lu",maker_scheme->id_length,
608                         maker_scheme->note_fileoffset);
609             chpr = newline(chpr);
610             break;
611     }
612     if(maker_scheme->note_byteorder &&
613             (maker_scheme->note_byteorder != maker_scheme->tiff_byteorder))
614         PUSHCOLOR(HI_RED);
615 
616     chpr += printf("\tNote byteorder = ");
617     print_byteorder(maker_scheme->note_byteorder,2);
618     if(maker_scheme->note_byteorder &&
619             (maker_scheme->note_byteorder != maker_scheme->tiff_byteorder))
620     {
621         chpr += printf(" != ");
622         POPCOLOR();
623     }
624     else
625     {
626         chpr = newline(chpr);
627         chpr += printf("\t");
628     }
629     chpr += printf("Tiff byteorder = ");
630     print_byteorder(maker_scheme->tiff_byteorder,2);
631     chpr += newline(chpr);
632     switch(maker_scheme->offsets_relative_to)
633     {
634         case START_OF_TIFFHEADER:
635                     chpr += printf("\tOffsets relative to TIFF header at offset %lu",
636                                 maker_scheme->fileoffset_base);
637                     chpr = newline(chpr);
638                     break;
639         case START_OF_NOTE:
640                     PUSHCOLOR(HI_RED);
641                     chpr += printf("\tOffsets relative to start of MakerNote");
642                     POPCOLOR();
643                     chpr += printf(" at offset %lu",maker_scheme->note_fileoffset);
644                     chpr += newline(1);
645                     break;
646         case START_OF_ENTRY:
647                     PUSHCOLOR(HI_RED);
648                     chpr += printf("\tOffsets relative to start of entry");
649                     POPCOLOR();
650                     chpr += newline(1);
651                     break;
652         default: chpr += printf("(UNKNOWN)\n");
653                     break;
654     }
655     chpr += printf("\tNumber of entries = %d",maker_scheme->num_entries);
656     chpr = newline(chpr);
657     if((maker_scheme->scheme_type != UNKNOWN_SCHEME) && maker_scheme->no_nextifd_offset)
658     {
659         putchar('\t'); ++chpr;
660         PUSHCOLOR(HI_RED);
661         chpr += printf("No next IFD offset");
662         POPCOLOR();
663         chpr += newline(1);
664     }
665     if(Make_name)
666     {
667         putchar('\t'); ++chpr;
668         chpr += printf("Make = \"%s\"",Make_name);
669         chpr += printf("  (maker id = %d)",maker_scheme->make);
670         chpr = newline(1);
671     }
672     if(Model_name)
673     {
674         putchar('\t'); ++chpr;
675         chpr += printf("Model = \"%s\"",Model_name);
676         chpr += printf("  (model id = %d)",maker_scheme->model);
677         chpr = newline(1);
678     }
679     if(Software_name)
680     {
681         putchar('\t'); ++chpr;
682         chpr += printf("Software = \"%s\"",Software_name);
683         chpr = newline(1);
684     }
685     putchar('\t'); ++chpr;
686     chpr += printf("Note version = %d (tagset = %d)",maker_scheme->note_version,maker_scheme->tagset);
687 
688     POPCOLOR();
689     chpr = newline(chpr);
690     chpr = newline(1);
691 }
692 
693 /* Print a list of camera makes known to the program. If a global     */
694 /* matching pattern has been set for names (by option) , limit the    */
695 /* output to camera names for which a case-insensitive substring      */
696 /* match occurs, otherwise list all makes. For each make printed,     */
697 /* print the list of recognized models. The Make and Model names (in  */
698 /* the camera_names.h and "maker"_datadefs.h files) are. or should    */
699 /* be, the "official" names used by the maker in the Make and Model   */
700 /* entries of and TIFF IFD or CIFF Make/Model entry.                  */
701 
702 void
print_camera_makes()703 print_camera_makes()
704 {
705     struct camera_name *maker_id;
706     char *pattern,*model_pattern;
707     int chpr = 0;
708 
709     chpr = newline(0);
710     chpr += printf("Camera Makes:");
711     chpr = newline(chpr);
712 
713     if(Camera_name_pattern)
714     {
715         pattern = Camera_name_pattern;
716         if((model_pattern = strchr(pattern,'+')))
717             *model_pattern++ = '\0';
718         else
719             model_pattern = NULL;
720 
721         /* 'Camera_make' is a global parameter                        */
722         for(maker_id = Camera_make; maker_id && maker_id->name; ++maker_id)
723         {
724             if(pattern)
725             {
726                 if(*pattern == '-')
727                 {
728                     chpr += printf("\t%-32.32s [%d]",maker_id->name,maker_id->id);
729                     chpr = newline(chpr);
730                 }
731                 else
732                 {
733                     if((*pattern) && !STRCASESTR(maker_id->name,pattern))
734                         continue;
735                     chpr += printf("\t%-32.32s [%d]",maker_id->name,maker_id->id);
736                     chpr = newline(chpr);
737                     if(model_pattern)
738                     {
739                         if(*model_pattern)
740                             print_camera_models(maker_id->model,model_pattern);
741                         else
742                             print_camera_models(maker_id->model,NULL);
743                     }
744                 }
745             }
746         }
747     }
748 }
749 
750 /* Print the list of recognized models for given device make. If a    */
751 /* non-null pattern is passed as argument, limit the output to models */
752 /* for which a case-insensitive substring match to the pattern occurs */
753 /* in the name, otherwise print all names.                            */
754 
755 void
print_camera_models(struct camera_id * model_names,char * pattern)756 print_camera_models(struct camera_id *model_names,char *pattern)
757 {
758     struct camera_id *maker_id;
759     int chpr = 0;
760 
761     chpr = newline(0);
762     for(maker_id = model_names ; maker_id && maker_id->name; ++maker_id)
763     {
764         if(pattern)
765         {
766             if(STRCASESTR(maker_id->name,pattern))
767             {
768                 chpr += printf("\t\t%-32.32s ",maker_id->name);
769                 chpr += printf("\t[%2d,%d]",maker_id->id,
770                                 maker_id->noteversion);
771                 chpr = newline(chpr);
772             }
773         }
774         else
775         {
776             chpr += printf("\t\t%-32.32s ",maker_id->name);
777             chpr += printf("\t[%2d,%d]",maker_id->id,
778                                 maker_id->noteversion);
779             chpr = newline(chpr);
780         }
781     }
782 }
783 
784 char *
fake_strcasestr(char * string,char * pattern)785 fake_strcasestr(char *string,char *pattern)
786 {
787     char *match = CNULL;
788     int plen,slen;
789 
790     if(string && pattern)
791     {
792         plen = strlen(pattern);
793         if(plen == 0)
794             match = string;
795         else
796         {
797             slen = strlen(string);
798             while(plen <= slen)
799             {
800                 if(strncasecmp(string,pattern,plen) == 0)
801                 {
802                     match = string;
803                     break;
804                 }
805                 ++string;
806                 --slen;
807             }
808         }
809     }
810     return(match);
811 }
812