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