Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package jhead for openSUSE:Factory checked in at 2021-01-27 18:58:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/jhead (Old) and /work/SRC/openSUSE:Factory/.jhead.new.28504 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "jhead" Wed Jan 27 18:58:40 2021 rev:26 rq:867250 version:3.04 Changes: -------- --- /work/SRC/openSUSE:Factory/jhead/jhead.changes 2018-10-25 09:11:35.286316887 +0200 +++ /work/SRC/openSUSE:Factory/.jhead.new.28504/jhead.changes 2021-01-27 18:59:22.236538828 +0100 @@ -1,0 +2,20 @@ +Fri Jan 22 03:28:11 UTC 2021 - Wang Jun <[email protected]> + +- Update to version 3.04 + * Apply a whole bunch of patches from Debian. + * Spell check and fuzz test stuff from Debian, nothing useful to + human users. + * Add option to set exif date from date from another file. + * Bug fixes relating to fuzz testing. + * Fix bug where thumbnail replacement DID NOT WORK. + * Fix bug when no orientation tag is present + * Fix bug of not clearing exif information when processing images + with an without exif data in one invocation. + * Remove some unnecessary warnings with some types of GPS data + * Remove multiple copies of the same type of section when deleting + section types + * Modify the patch CVE-2018-17088.patch because source code changed +- Remove these patches because of including upstream code + * CVE-2018-6612.patch, CVE-2016-3822.patch, CVE-2018-16554.patch + +------------------------------------------------------------------- Old: ---- CVE-2016-3822.patch CVE-2018-16554.patch CVE-2018-6612.patch jhead-3.00.tar.gz New: ---- jhead-3.04.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ jhead.spec ++++++ --- /var/tmp/diff_new_pack.tCSPS4/_old 2021-01-27 18:59:22.932539905 +0100 +++ /var/tmp/diff_new_pack.tCSPS4/_new 2021-01-27 18:59:22.936539912 +0100 @@ -1,7 +1,7 @@ # # spec file for package jhead # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,21 +17,16 @@ Name: jhead -Version: 3.00 +Version: 3.04 Release: 0 Summary: Tool to Manipulate the Nonimage Part of EXIF Compliant JPEG Files License: SUSE-Public-Domain Group: Productivity/Graphics/Other -Url: http://www.sentex.net/~mwandel/jhead/ +URL: http://www.sentex.net/~mwandel/jhead/ Source0: http://www.sentex.net/~mwandel/jhead/jhead-%{version}.tar.gz Source1: %{name}.changes -Patch0: CVE-2018-6612.patch -# PATCH-FIX-SECURITY CVE-2016-3822.patch CVE-2016-3822 boo1108480 [email protected] -- Integer overflow fix from Debian (31_CVE-2016-3822.patch). -Patch1: CVE-2016-3822.patch # PATCH-FIX-SECURITY CVE-2018-17088.patch CVE-2018-17088 boo1108672 [email protected] -- Integer overflow fix. -Patch2: CVE-2018-17088.patch -# PATCH-FIX-SECURITY CVE-2018-16554.patch CVE-2018-16554 boo1108480 [email protected] -- Buffer overflow fix. -Patch3: CVE-2018-16554.patch +Patch0: CVE-2018-17088.patch Requires: %{_bindir}/jpegtran Requires: %{_bindir}/mogrify BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -47,9 +42,7 @@ %prep %setup -q %patch0 -p1 -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 + modified="$(sed -n '/^----/n;s/ - .*$//;p;q' "%{SOURCE1}")" DATE="\"$(date -d "${modified}" "+%%b %%e %%Y")\"" TIME="\"$(date -d "${modified}" "+%%R")\"" ++++++ CVE-2018-17088.patch ++++++ --- /var/tmp/diff_new_pack.tCSPS4/_old 2021-01-27 18:59:22.952539936 +0100 +++ /var/tmp/diff_new_pack.tCSPS4/_new 2021-01-27 18:59:22.952539936 +0100 @@ -1,28 +1,6 @@ -Index: jhead-3.00/gpsinfo.c -=================================================================== ---- jhead-3.00.orig/gpsinfo.c -+++ jhead-3.00/gpsinfo.c -@@ -6,6 +6,7 @@ - #include "jhead.h" - - #define MAX_GPS_TAG 0x1e -+#include <stdint.h> - - - #define TAG_GPS_LAT_REF 1 -@@ -101,7 +102,7 @@ void ProcessGpsInfo(unsigned char * DirS - unsigned OffsetVal; - OffsetVal = Get32u(DirEntry+8); - // If its bigger than 4 bytes, the dir entry contains an offset. -- if (OffsetVal+ByteCount > ExifLength){ -+ if (OffsetVal > UINT32_MAX - ByteCount || OffsetVal+ByteCount > ExifLength){ - // Bogus pointer offset and / or bytecount value - ErrNonfatal("Illegal value pointer for Exif gps tag %04x", Tag,0); - continue; -Index: jhead-3.00/makernote.c -=================================================================== ---- jhead-3.00.orig/makernote.c -+++ jhead-3.00/makernote.c +diff -auNr jhead-3.04/makernote.c jhead-3.04-new/makernote.c +--- jhead-3.04/makernote.c 2019-11-22 22:27:34.000000000 +0800 ++++ jhead-3.04-new/makernote.c 2021-01-22 11:15:07.425323997 +0800 @@ -5,6 +5,7 @@ #include "jhead.h" @@ -31,7 +9,7 @@ //-------------------------------------------------------------------------- // Process exif format directory, as used by Cannon maker note -@@ -64,7 +65,7 @@ static void ProcessCanonMakerNoteDir(uns +@@ -64,7 +65,7 @@ unsigned OffsetVal; OffsetVal = Get32u(DirEntry+8); // If its bigger than 4 bytes, the dir entry contains an offset. ++++++ jhead-3.00.tar.gz -> jhead-3.04.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jhead-3.00/changes.txt new/jhead-3.04/changes.txt --- old/jhead-3.00/changes.txt 2015-02-02 23:24:06.000000000 +0100 +++ new/jhead-3.04/changes.txt 2019-11-22 15:27:34.000000000 +0100 @@ -409,4 +409,36 @@ Sep 28 2014: Add ability to reset invalid rotation tag (from Moultrie game cameras) --------Released version 3.0 -- Feb 2 2015 -------- \ No newline at end of file +-------Released version 3.0 -- Feb 2 2015 -------- +Ma4 5 2015: +Add option to set exif date from date from another file. + +Jul 28 2015: +Remove some unnecessary warnings with some types of GPS data + +Aug 4 2015: +Remove multiple copies of the same type of section when deleting section types + +Aug 11 2011: +Bug fixes relating to fuzz testing. + +Aug 1 2017: +Fix bug when no orientation tag is present + +Aug 12 2018: +Fix bug of not clearing exif information when processing images with an without +exif data in one invocation. + +-------Released version 3.02 -- Dec 11 2018 -------- + +Dec 21 2018: +Fix bug where thumbnail replacement DID NOT WORK. +(broke while fixing compiler warnings for 3.02 release) + +-------Released version 3.03 -- Dec 31 2018 -------- + +Nov 20 2019: +Apply a whole bunch of patches from Debian. +Spell check and fuzz test stuff from Debian, nothing useful to human users. + +-------Released version 3.04 -- Nov 22 2019 -------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jhead-3.00/exif.c new/jhead-3.04/exif.c --- old/jhead-3.00/exif.c 2015-02-02 23:24:06.000000000 +0100 +++ new/jhead-3.04/exif.c 2019-11-22 15:27:34.000000000 +0100 @@ -455,13 +455,13 @@ // Process one of the nested EXIF directories. //-------------------------------------------------------------------------- static void ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, - unsigned ExifLength, int NestingLevel) + int ExifLength, int NestingLevel) { int de; int a; int NumDirEntries; - unsigned ThumbnailOffset = 0; - unsigned ThumbnailSize = 0; + int ThumbnailOffset = 0; + int ThumbnailSize = 0; char IndentString[25]; if (NestingLevel > 4){ @@ -524,10 +524,10 @@ ByteCount = Components * BytesPerFormat[Format]; if (ByteCount > 4){ - unsigned OffsetVal; + int OffsetVal; OffsetVal = Get32u(DirEntry+8); // If its bigger than 4 bytes, the dir entry contains an offset. - if (OffsetVal+ByteCount > ExifLength){ + if (OffsetVal+ByteCount > ExifLength || OffsetVal < 0 || OffsetVal > 65536){ // Bogus pointer offset and / or bytecount value ErrNonfatal("Illegal value pointer for tag %04x in Exif", Tag,0); continue; @@ -915,7 +915,7 @@ // there's also a potential link to another directory at the end of each // directory. this has got to be the result of a committee! unsigned char * SubdirStart; - unsigned Offset; + int Offset; if (DIR_ENTRY_ADDR(DirStart, NumDirEntries) + 4 <= OffsetBase+ExifLength){ Offset = Get32u(DirStart+2+12*NumDirEntries); @@ -931,7 +931,7 @@ ErrNonfatal("Illegal subdirectory link in Exif header",0,0); } }else{ - if (SubdirStart <= OffsetBase+ExifLength){ + if (SubdirStart+2 <= OffsetBase+ExifLength){ if (ShowTags) printf("%s Continued directory ",IndentString); ProcessExifDir(SubdirStart, OffsetBase, ExifLength, NestingLevel+1); } @@ -972,19 +972,26 @@ } } +void Clear_EXIF () +{ + FocalplaneXRes = 0; + FocalplaneUnits = 0; + ExifImageWidth = 0; + NumOrientations = 0; + MotorolaOrder = 0; + OrientationPtr[0] = OrientationPtr[1] = NULL; + OrientationNumFormat[0] = OrientationNumFormat[1] = 0; +} //-------------------------------------------------------------------------- // Process a EXIF marker // Describes all the drivel that most digital cameras include... //-------------------------------------------------------------------------- -void process_EXIF (unsigned char * ExifSection, unsigned int length) +void process_EXIF (unsigned char * ExifSection, int length) { - unsigned int FirstOffset; - - FocalplaneXRes = 0; - FocalplaneUnits = 0; - ExifImageWidth = 0; - NumOrientations = 0; + int FirstOffset; + + Clear_EXIF(); if (ShowTags){ printf("Exif header %u bytes long\n",length); @@ -1017,9 +1024,9 @@ return; } - FirstOffset = Get32u(ExifSection+12); + FirstOffset = (int)Get32u(ExifSection+12); if (FirstOffset < 8 || FirstOffset > 16){ - if (FirstOffset < 16 || FirstOffset > length-16){ + if (FirstOffset < 16 || FirstOffset > length-16 || length < 16){ ErrNonfatal("invalid offset for first Exif IFD value",0,0); return; } @@ -1036,7 +1043,7 @@ ImageInfo.ThumbnailAtEnd = ImageInfo.ThumbnailOffset >= ImageInfo.LargestExifOffset ? TRUE : FALSE; if (DumpExifMap){ - unsigned a,b; + int a,b; printf("Map: %05d- End of exif\n",length-8); for (a=0;a<length-8;a+= 10){ printf("Map: %05d ",a); @@ -1204,6 +1211,7 @@ //-------------------------------------------------------------------------- // Cler the rotation tag in the exif header to 1. +// Returns NULL if no orietnation tag exists. //-------------------------------------------------------------------------- const char * ClearOrientation(void) { @@ -1240,7 +1248,7 @@ if (ImageInfo.Orientation >= 1 && ImageInfo.Orientation <= 8){ return OrientTab[ImageInfo.Orientation]; }else{ - return NULL; + return ""; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jhead-3.00/gpsinfo.c new/jhead-3.04/gpsinfo.c --- old/jhead-3.00/gpsinfo.c 2015-02-02 23:24:06.000000000 +0100 +++ new/jhead-3.04/gpsinfo.c 2019-11-22 15:27:34.000000000 +0100 @@ -101,7 +101,8 @@ unsigned OffsetVal; OffsetVal = Get32u(DirEntry+8); // If its bigger than 4 bytes, the dir entry contains an offset. - if (OffsetVal+ByteCount > ExifLength){ + if (OffsetVal > 0x1000000 || OffsetVal+ByteCount > ExifLength){ + // Max exif in jpeg is 64k, so any offset bigger than that is bogus. // Bogus pointer offset and / or bytecount value ErrNonfatal("Illegal value pointer for Exif gps tag %04x", Tag,0); continue; @@ -147,7 +148,7 @@ Values[a] = ConvertAnyFormat(ValuePtr+a*ComponentSize, Format); } - sprintf(TempString, FmtString, Values[0], Values[1], Values[2]); + snprintf(TempString, sizeof(TempString), FmtString, Values[0], Values[1], Values[2]); if (Tag == TAG_GPS_LAT){ strncpy(ImageInfo.GpsLat+2, TempString, 29); @@ -161,8 +162,8 @@ break; case TAG_GPS_ALT: - sprintf(ImageInfo.GpsAlt + 1, "%.2fm", - ConvertAnyFormat(ValuePtr, Format)); + snprintf(ImageInfo.GpsAlt+1, sizeof(ImageInfo.GpsAlt)-1, + "%.2fm", ConvertAnyFormat(ValuePtr, Format)); break; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jhead-3.00/iptc.c new/jhead-3.04/iptc.c --- old/jhead-3.00/iptc.c 2015-02-02 23:24:06.000000000 +0100 +++ new/jhead-3.04/iptc.c 2019-11-22 15:27:34.000000000 +0100 @@ -126,6 +126,7 @@ type = *pos++; length = (*pos << 8) + (*(pos+1)); + if (length < 1) goto corrupt; pos += 2; // Skip tag length if (pos+length > maxpos) goto corrupt; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jhead-3.00/jhead.1 new/jhead-3.04/jhead.1 --- old/jhead-3.00/jhead.1 2015-02-02 23:24:06.000000000 +0100 +++ new/jhead-3.04/jhead.1 2019-11-22 15:27:34.000000000 +0100 @@ -1,4 +1,4 @@ -.TH JHEAD 1 "2 Feb 2015" "jhead 3.00" +.TH JHEAD 1 "22 Nov 2019" "jhead 3.04" .SH NAME jhead \- Digicam JPEG Exif header manipulation tool .SH SYNOPSIS @@ -105,7 +105,6 @@ .TP .BI \-\^cl \ string Replace comment with specified string from command line -.IR file .SH DATE / TIME MANIPULATION OPTIONS @@ -121,16 +120,10 @@ This option causes files to be renamed and/ or mmoved using the date information from the Exif header "DateTimeOriginal" field. If the file is not an Exif file, or the DateTimeOriginal does not contain a valid -value, the file date is used. Renaming is by default restricted to -files whose names consist largely of digits. This effectively restricts -renaming to files that have not already been manually renamed, as the -default sequential names from digital cameras consist largely of digits. -Use the -.B \-n -option to force renaming of all files. If the new name contains a '/', +value, the file date is used. If the new name contains a '/', this will be interpreted as a new path, and the file will be moved accordingly. - + If the .I format_string is omitted, the file will be renamed to MMDD-HHMMSS. Note that this diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jhead-3.00/jhead.c new/jhead-3.04/jhead.c --- old/jhead-3.00/jhead.c 2015-02-02 23:24:06.000000000 +0100 +++ new/jhead-3.04/jhead.c 2019-11-22 15:27:34.000000000 +0100 @@ -2,12 +2,12 @@ // Program to pull the information out of various types of EXIF digital // camera files and show it in a reasonably consistent way // -// Version 3.00 +// Version 3.04 // // Compiling under Windows: // Make sure you have Microsoft's compiler on the path, then run make.bat // -// Dec 1999 - Feb 2015 +// Dec 1999 - Nov 2019 // // by Matthias Wandel www.sentex.net/~mwandel //-------------------------------------------------------------------------- @@ -19,7 +19,7 @@ #include <sys/stat.h> -#define JHEAD_VERSION "3.00" +#define JHEAD_VERSION "3.04" // This #define turns on features that are too very specific to // how I organize my photos. Best to ignore everything inside #ifdef MATTHIAS @@ -59,6 +59,7 @@ static int TrimExifTrailingZeroes = FALSE; static char * ApplyCommand = NULL; // Apply this command to all images. static char * FilterModel = NULL; +static int FilterQuality = 0; static int ExifOnly = FALSE; static int PortraitOnly = FALSE; static time_t ExifTimeAdjust = 0; // Timezone adjust @@ -84,7 +85,7 @@ // put it into the Jpegs processed. static int EditComment = FALSE; // Invoke an editor for editing the comment -static int SupressNonFatalErrors = FALSE; // Wether or not to pint warnings on recoverable errors +static int SuppressNonFatalErrors = FALSE; // Wether or not to pint warnings on recoverable errors static char * CommentSavefileName = NULL; // Save comment to this file. static char * CommentInsertfileName = NULL; // Insert comment from this file. @@ -123,7 +124,7 @@ //-------------------------------------------------------------------------- void ErrNonfatal(const char * msg, int a1, int a2) { - if (SupressNonFatalErrors) return; + if (SuppressNonFatalErrors) return; fprintf(stderr,"\nNonfatal Error : "); if (CurrentFile) fprintf(stderr,"'%s' ",CurrentFile); @@ -370,11 +371,11 @@ strcpy(TempName+a, "XXXXXX"); // Note: Compiler will warn about mkstemp. but I need a filename, not a file. - // I could just then get the fiel name from what mkstemp made, and pass that + // I could just then get the file name from what mkstemp made, and pass that // to the executable, but that would make for the exact same vulnerability // as mktemp - that is, that between getting the random name, and making the file // some other program could snatch that exact same name! - // also, not all pltforms support mkstemp. + // also, not all platforms support mkstemp. mktemp(TempName); @@ -457,6 +458,12 @@ return TRUE; } } + if (FilterQuality > 0){ + //Filter by above threshold quality + if (ImageInfo.QualityGuess < FilterQuality){ + return TRUE; + } + } if (ExifOnly){ // Filtering by EXIF only. Skip all files that have no Exif. @@ -670,7 +677,7 @@ NameExtra[0] = 0; } - sprintf(NewName, "%s%s.jpg", NewBaseName, NameExtra); + snprintf(NewName, sizeof(NewName), "%s%s.jpg", NewBaseName, NameExtra); if (!strcmp(FileName, NewName)) break; // Skip if its already this name. @@ -711,11 +718,12 @@ if (ImageInfo.Orientation != 1){ const char * Argument; Argument = ClearOrientation(); + if (Argument == NULL) return FALSE; // orientation tag in image, nothing changed. if (!ZeroRotateTagOnly){ char RotateCommand[PATH_MAX*2+50]; - if (Argument == NULL){ - ErrNonfatal("Unknown orientation tag",0,0); + if (strlen(Argument) == 0){ + // Unknown orientation, but still modified. return TRUE; // Image is still modified. } sprintf(RotateCommand, "jpegtran -trim -%s -outfile &o &i", Argument); @@ -765,7 +773,7 @@ return FALSE; } - sprintf(ThumbnailGenCommand, "mogrify -thumbnail %dx%d \"%s\"", + sprintf(ThumbnailGenCommand, "mogrify -thumbnail %dx%d -quality 80 \"%s\"", RegenThumbnail, RegenThumbnail, FileName); if (system(ThumbnailGenCommand) == 0){ @@ -805,6 +813,7 @@ FilesMatched = 1; ResetJpgfile(); + Clear_EXIF(); // Start with an empty image information structure. memset(&ImageInfo, 0, sizeof(ImageInfo)); @@ -1250,7 +1259,7 @@ static void Usage (void) { printf("Jhead is a program for manipulating settings and thumbnails in Exif jpeg headers\n" - "used by most Digital Cameras. v"JHEAD_VERSION" Matthias Wandel, Jan 30 2013.\n" + "used by most Digital Cameras. v"JHEAD_VERSION" Matthias Wandel, Nov 22 2019.\n" "http://www.sentex.net/~mwandel/jhead\n" "\n"); @@ -1295,8 +1304,7 @@ " '%%i' will include a sequence number, starting from 1. You can\n" " You can specify '%%03i' for example to get leading zeros.\n" " This feature is useful for ordering files from multiple digicams to\n" - " sequence of taking. Only renames files whose names are mostly\n" - " numerical (as assigned by digicam)\n" + " sequence of taking.\n" " The '.jpg' is automatically added to the end of the name. If the\n" " destination name already exists, a letter or digit is added to \n" " the end of the name to make it unique.\n" @@ -1322,6 +1330,7 @@ " and time in the format yyyy:mm:dd/hh:mm:ss\n" " -ts<time> Set the Exif internal time to <time>. <time> is in the format\n" " yyyy:mm:dd-hh:mm:ss\n" + " -tf file Set the exif time to the modicfation time from another file\n" " -ds<date> Set the Exif internal date. <date> is in the format YYYY:MM:DD\n" " or YYYY:MM or YYYY\n" @@ -1342,6 +1351,7 @@ "\nROTATION TAG MANIPULATION:\n" " -autorot Invoke jpegtran to rotate images according to Exif orientation tag\n" + " anc clear Exif orientation tag\n" " Note: Windows users must get jpegtran for this to work\n" " -norot Zero out the rotation tag. This to avoid some browsers from\n" " rotating the image again after you rotated it but neglected to\n" @@ -1353,7 +1363,7 @@ " -q Quiet (no messages on success, like Unix)\n" " -V Show jhead version\n" " -exifmap Dump header bytes, annotate. Pipe thru sort for better viewing\n" - " -se Supress error messages relating to corrupt exif header structure\n" + " -se Suppress error messages relating to corrupt exif header structure\n" " -c concise output\n" " -nofinfo Don't show file info (name/size/date)\n" @@ -1363,6 +1373,7 @@ " camera model description\n" " -exonly Skip all files that don't have an exif header (skip all jpegs that\n" " were not created by digicam)\n" + " -quality x Only work on images with JPEG quality factor x or higher\n" " -cmd command\n" " Apply 'command' to every file, then re-insert exif and command\n" " sections into the image. &i will be substituted for the input file\n" @@ -1500,12 +1511,12 @@ }else if (!strcmp(arg,"-q")){ Quiet = TRUE; }else if (!strcmp(arg,"-V")){ - printf("Jhead version: "JHEAD_VERSION" Compiled: "__DATE__"\n"); + printf("Jhead version: "JHEAD_VERSION"\n"); exit(0); }else if (!strcmp(arg,"-exifmap")){ DumpExifMap = TRUE; }else if (!strcmp(arg,"-se")){ - SupressNonFatalErrors = TRUE; + SuppressNonFatalErrors = TRUE; }else if (!strcmp(arg,"-c")){ ShowConcise = TRUE; }else if (!strcmp(arg,"-nofinfo")){ @@ -1589,13 +1600,13 @@ if (pOldDate){ OldDate = ParseCmdDate(pOldDate+1); }else{ - ErrFatal("Must specifiy second date for -da option"); + ErrFatal("Must specify second date for -da option"); } if (ExifTimeAdjust) ErrFatal("Can only use one of -da or -ta options at once"); ExifTimeAdjust = NewDate-OldDate; DoModify |= MODIFY_JPEG; }else if (!memcmp(arg,"-dsft",5)){ - // Set file time to date/time in exif + // Set exif time to the timestamp of the file. FileTimeToExif = TRUE; DoModify |= MODIFY_JPEG; }else if (!memcmp(arg,"-ds",3)){ @@ -1640,11 +1651,26 @@ if ((int)ExifTimeSet == -1) ErrFatal("Time specified is out of range"); DoModify |= MODIFY_JPEG; + + }else if (!memcmp(arg,"-tf",3)){ + // Set the exif time to the modification time from another file. + struct stat stat_buf; + if (stat(argv[++argn], &stat_buf) == 0){ + ExifTimeSet = stat_buf.st_mtime; + }else{ + ErrFatal("Could not read file"); + } + DoModify |= MODIFY_JPEG; // File matching and selection }else if (!strcmp(arg,"-model")){ if (argn+1 >= argc) Usage(); // No extra argument. FilterModel = argv[++argn]; + }else if (!strcmp(arg,"-quality")){ + if (argn+1 >= argc) Usage(); // No extra argument. + if (sscanf(argv[++argn], "%d", &FilterQuality) != 1){ + Usage(); + } }else if (!strcmp(arg,"-exonly")){ ExifOnly = 1; }else if (!strcmp(arg,"-orp")){ @@ -1688,7 +1714,7 @@ if (ThumbSaveName != NULL && strcmp(ThumbSaveName, "&i") == 0){ printf("Error: By specifying \"&i\" for the thumbail name, your original file\n" - " will be overwitten. If this is what you really want,\n" + " will be overwritten. If this is what you really want,\n" " specify -st \"./&i\" to override this check\n"); exit(0); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jhead-3.00/jhead.h new/jhead-3.04/jhead.h --- old/jhead-3.00/jhead.h 2015-02-02 23:24:06.000000000 +0100 +++ new/jhead-3.04/jhead.h 2019-11-22 15:27:34.000000000 +0100 @@ -24,6 +24,11 @@ #define chmod _chmod #define access _access #define mktemp _mktemp + + #if _MSC_VER && _MSC_VER <= 1500 + // The 2007 vintage compiler I use on windows doesn't have snprintf + #define snprintf(dest, len, format,...) sprintf (dest, format, __VA_ARGS__) + #endif #else #include <utime.h> #include <sys/types.h> @@ -117,9 +122,9 @@ char Comments[MAX_COMMENT_SIZE]; int CommentWidthchars; // If nonzero, widechar comment, indicates number of chars. - unsigned ThumbnailOffset; // Exif offset to thumbnail - unsigned ThumbnailSize; // Size of thumbnail. - unsigned LargestExifOffset; // Last exif data referenced (to check if thumbnail is at end) + int ThumbnailOffset; // Exif offset to thumbnail + int ThumbnailSize; // Size of thumbnail. + int LargestExifOffset; // Last exif data referenced (to check if thumbnail is at end) char ThumbnailAtEnd; // Exif header ends with the thumbnail // (we can only modify the thumbnail if its at the end) @@ -137,8 +142,9 @@ }ImageInfo_t; - +#ifndef EXIT_FAILURE #define EXIT_FAILURE 1 +#endif #define EXIT_SUCCESS 0 // jpgfile.c functions @@ -157,7 +163,8 @@ // Prototypes for exif.c functions. int Exif2tm(struct tm * timeptr, char * ExifTime); -void process_EXIF (unsigned char * CharBuf, unsigned int length); +void Clear_EXIF(); +void process_EXIF (unsigned char * CharBuf, int length); void ShowImageInfo(int ShowFileInfo); void ShowConciseImageInfo(void); const char * ClearOrientation(void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jhead-3.00/jpgfile.c new/jhead-3.04/jpgfile.c --- old/jhead-3.00/jpgfile.c 2015-02-02 23:24:06.000000000 +0100 +++ new/jhead-3.04/jpgfile.c 2019-11-22 15:27:34.000000000 +0100 @@ -248,13 +248,13 @@ // marker instead, althogh ACDsee will write images with both markers. // this program will re-create this marker on absence of exif marker. // hence no need to keep the copy from the file. - if (memcmp(Data+2, "JFIF\0",5)){ - fprintf(stderr,"Header missing JFIF marker\n"); - } if (itemlen < 16){ fprintf(stderr,"Jfif header too short\n"); goto ignore; } + if (memcmp(Data+2, "JFIF\0",5)){ + fprintf(stderr,"Header missing JFIF marker\n"); + } ImageInfo.JfifHeader.Present = TRUE; ImageInfo.JfifHeader.ResolutionUnits = Data[9]; @@ -289,7 +289,7 @@ }else if (memcmp(Data+2, "http:", 5) == 0){ Sections[SectionsRead-1].Type = M_XMP; // Change tag for internal purposes. if (ShowTags){ - printf("Image cotains XMP section, %d bytes long\n", itemlen); + printf("Image contains XMP section, %d bytes long\n", itemlen); if (ShowTags){ ShowXmp(Sections[SectionsRead-1]); } @@ -304,7 +304,7 @@ case M_IPTC: if (ReadMode & READ_METADATA){ if (ShowTags){ - printf("Image cotains IPTC section, %d bytes long\n", itemlen); + printf("Image contains IPTC section, %d bytes long\n", itemlen); } // Note: We just store the IPTC section. Its relatively straightforward // and we don't act on any part of it, so just display it at parse time. @@ -326,6 +326,10 @@ case M_SOF13: case M_SOF14: case M_SOF15: + if (itemlen < 8){ + fprintf(stderr,"Section too short\n"); + break; + } process_SOFn(Data, marker); break; default: @@ -454,6 +458,7 @@ ThumbnailFile = fopen(ThumbFileName,"rb"); if (ThumbnailFile == NULL){ + noread: ErrFatal("Could not read thumbnail file"); return FALSE; } @@ -484,7 +489,9 @@ ThumbnailPointer = ExifSection->Data+ImageInfo.ThumbnailOffset+8; if (ThumbnailFile){ - fread(ThumbnailPointer, ThumbLen, 1, ThumbnailFile); + if (fread(ThumbnailPointer, 1, ThumbLen, ThumbnailFile) != ThumbLen){ + goto noread; + } fclose(ThumbnailFile); } @@ -649,6 +656,7 @@ int RemoveSectionType(int SectionType) { int a; + int retval = FALSE; for (a=0;a<SectionsRead-1;a++){ if (Sections[a].Type == SectionType){ // Free up this section @@ -656,10 +664,11 @@ // Move succeding sections back by one to close space in array. memmove(Sections+a, Sections+a+1, sizeof(Section_t) * (SectionsRead-a)); SectionsRead -= 1; - return TRUE; + a -= 1; + retval = TRUE; } } - return FALSE; + return retval; } //-------------------------------------------------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jhead-3.00/jpgqguess.c new/jhead-3.04/jpgqguess.c --- old/jhead-3.00/jpgqguess.c 2015-02-02 23:24:06.000000000 +0100 +++ new/jhead-3.04/jpgqguess.c 2019-11-22 15:27:34.000000000 +0100 @@ -8,9 +8,6 @@ //-------------------------------------------------------------------------- #include "jhead.h" - - - // for the DQT marker -- start -- // Sample quantization tables from JPEG spec --- only needed for // guesstimate of quality factor. Note these are in zigzag order. @@ -78,7 +75,7 @@ // multiple of the standard's sample table, so the file was NOT // generated by cjpeg and the quality estimate is dubious. //-------------------------------------------------------------------------- - void process_DQT (const uchar * Data, int length) +void process_DQT (const uchar * Data, int length) { int a; int c; @@ -87,7 +84,7 @@ int *reftable = NULL; double cumsf = 0.0, cumsf2 = 0.0; int allones = 1; - + a=2; // first two bytes is length while (a<length) { @@ -101,6 +98,10 @@ } // Read in the table, compute statistics relative to reference table + if (a+64 > length) { + ErrNonfatal("DQT section too short",0,0); + return; + } for (coefindex = 0; coefindex < 64; coefindex++) { unsigned int val; if (c>>4) { @@ -150,10 +151,9 @@ if (ShowTags){ printf("Approximate quality factor for qtable %d: %.0f (scale %.2f, var %.2f)\n", tableindex, qual, cumsf, var); - } else { - if (tableindex == 0){ - ImageInfo.QualityGuess = (int)(qual+0.5); - } + } + if (tableindex == 0){ + ImageInfo.QualityGuess = (int)(qual+0.5); } } } @@ -172,7 +172,6 @@ int a, i; int c, c2; unsigned char huff[16]; - if (ShowTags>1){ printf("DHT (length %d bytes)\n", length); } @@ -184,6 +183,11 @@ if (ShowTags>1){ printf(" table %d\n", c); } + if (a+16 > length){ + tooshort: + ErrFatal("Huff table too short"); + } + for (i=0; i<16; i++) { huff[i]=(unsigned char) Data[a++]; } @@ -191,6 +195,9 @@ if (ShowTags>2){ printf(" bits %2d (codes=%3u) ", i+1, (unsigned int) huff[i]); } + if (a+huff[i] > length){ + goto tooshort; + } while (huff[i]--) { c2 = Data[a++]; if (ShowTags>2){ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jhead-3.00/makefile new/jhead-3.04/makefile --- old/jhead-3.00/makefile 2015-02-02 23:24:06.000000000 +0100 +++ new/jhead-3.04/makefile 2019-11-22 15:27:34.000000000 +0100 @@ -3,7 +3,9 @@ #-------------------------------- OBJ=. SRC=. -CFLAGS:= $(CFLAGS) -O3 -Wall +CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS) +CFLAGS:=$(shell dpkg-buildflags --get CFLAGS) +LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS) all: jhead @@ -11,13 +13,13 @@ $(OBJ)/exif.o $(OBJ)/iptc.o $(OBJ)/gpsinfo.o $(OBJ)/makernote.o $(OBJ)/%.o:$(SRC)/%.c - ${CC} $(CFLAGS) -c $< -o $@ + ${CC} $(CFLAGS) $(CPPFLAGS) -c $< -o $@ jhead: $(objs) jhead.h - ${CC} -o jhead $(objs) -lm + ${CC} $(LDFLAGS) -o jhead $(objs) -lm clean: rm -f $(objs) jhead install: - cp jhead ${DESTDIR}/usr/local/bin/ + cp jhead ${DESTDIR}/usr/bin/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jhead-3.00/usage.html new/jhead-3.04/usage.html --- old/jhead-3.00/usage.html 2015-02-02 23:24:06.000000000 +0100 +++ new/jhead-3.04/usage.html 2019-11-22 15:27:34.000000000 +0100 @@ -8,7 +8,7 @@ or Mac OS-X won't do anything for you - you have to <b>use it from the Command prompt</b> -<h3>Jhead v3.00 program Features</h3> +<h3>Jhead v3.03 program Features</h3> <ul> <li>Extracting camera settings from Exif image files <li>Able to set and/or adjust the Exif time field @@ -126,7 +126,7 @@ of an event. By renaming them to a scheme according to date, they will automatically appear in order of taking when viewed with some sort of viewer like Xnview or AcdSee, and sorted by name. Or you could use the -ft option and view the images sorted by date. - Typically, one of the carera's date will be set not quite right, in which case you may have + Typically, one of the camera's date will be set not quite right, in which case you may have to use the -ta or -da options on those files first. <p> <b>Some of the more useful arguments for strftime are:</b> @@ -169,9 +169,9 @@ <p> Examples:<br> Adjust time one hour forward (you would use this after you forgot to set daylight savings - time on the digicam)<br> + time on the camera)<br> <ul>jhead -ta+1:00 *.jpg</ul> - Adjust time back by 23 seconds (you would use this to get the timestamps from two digicams + Adjust time back by 23 seconds (you would use this to get the timestamps from two cameras in sync after you found that they didn't quite align) <ul>jhead -ta-0:00:23 *.jpg</ul> Adjust time forward by 2 days and 1 hour (49 hours) @@ -203,6 +203,10 @@ This option changes all the date fields in the Exif header. Time must be specified as:<br> <font face=courier>     yyyy:mm:dd-hh:mm:ss</font><p> + +<tr valign=top><td><b>-tf <filename> +<td>Sets the date stored in the Exif header to the modification time from a file. + This option changes all the date fields in the Exif header. <tr valign=top><td><b>-ds<date-time> <td>Sets the date stored in the Exif header to what is specified on the command line. @@ -251,7 +255,7 @@ This only works if the Exif header already contains an Exif header a thumbnail. <tr valign=top><td><b>-rgt[size] -<td>Regnerate Exif thumbnail. +<td>Regenerate Exif thumbnail. 'size' specifies maximum height or width of thumbnail. I added this option because I had a lot of images that I had rotated with various tools that don't update the Exif header. But newer image browsers such as XnView make use of the Exif thumbnail, @@ -264,7 +268,7 @@ This option relies on 'mogrify' program (from ImageMagick) to regenerate the thumbnail. Linux users often already have this tool pre-installed. Windows users have to go and download it. - This option only works if the image already contains a thumbail. + This option only works if the image already contains a thumbnail. </table> <h3>Rotation tag manipulation</h3> @@ -307,12 +311,12 @@ its crashed. <tr valign=top><td><b>-q -<td>Makes the progran not spit out messages on success - more like the "Silence is golden" Unix way. its crashed. +<td>Makes the program not spit out messages on success - more like the "Silence is golden" Unix way. its crashed. <tr valign=top><td><b>-V <td>Print version info and compilation date. -<tr valign=top><td><b>-Exifmap +<tr valign=top><td><b>-exifmap <td>Show a map of the bytes in the Exif header. Useful when analyzing strange Exif headers, not of much use to non software developers. @@ -330,7 +334,7 @@ <h3>File matching and selection</h3> <table cellpadding=5> -<tr valign=top><td><b>-model +<tr valign=top><td><b>-model <model> <td>Restricts processing of files to those whose camera model, as indicated by the Exif image information, contains the substring specified in the argument after '-model'. For example, the following command will list only images that are from an S100 camera: @@ -338,7 +342,11 @@ jhead -model S100 *.jpg<p> <p> I use this option to restrict my JPEG re-compressing to those images that came from my - Cannon S100 digicam, (see the -cmd option). + Cannon S100 camera, (see the -cmd option). + +<tr valign=top><td><b>-quality <nn> +<td>Restricts processing of files to those whose estimated quality factor is equal to + or higher than the specified number nn. <tr valign=top> <td><b>-exonly @@ -347,18 +355,18 @@ preserve the Exif header when saving pictures. <tr valign=top><td><b>-cmd<command> -<td>Executes the specified command on each Jepg file to be processed.<p> +<td>Executes the specified command on each Jpeg file to be processed.<p> The Exif section of each file is read before running the command, and re-inserted after the command finishes. <p> - This is useful for using jhead's file globbing capability for processing a whole + This is useful for using Jhead's file globbing capability for processing a whole directory tree of files. <p> - It's also useful for restoring the exif header after operatiosn that wipe out + It's also useful for restoring the exif header after operations that wipe out the Exif metadata. Most programs today however will keep the Exif metadata intact, so this is less important than it used to be. -<tr valign=top><td><b>-orp -orl +<tr valign=top><td><b>-orp, -orl <td>Operate only on images with portrait (-orp) or landscape (-orl) aspect ratio.<br> Please note that this is solely based on jpeg width and height values. Some browsers may auto rotate the image on displaying it based on the Exif orientation tag, so that images shot @@ -374,7 +382,7 @@ <h3>Bugs and Shortcomings</h3> <ul> - After jhead runs a program to rotate or resize an image, the image dimensions and thumbnail + After Jhead runs a program to rotate or resize an image, the image dimensions and thumbnail in the Exif header are not adjusted. <p> Modifying of Exif header data is very limited, as Jhead internally only has a read only @@ -383,7 +391,7 @@ <p> Most Canon digital SLR cameras fail to adjust the effective sensor resolution when shooting at less - than full resolution, causing jhead to incorrectly miscalculate the sensor width and 35mm equivalent + than full resolution, causing Jhead to incorrectly miscalculate the sensor width and 35mm equivalent focal length. The same can result from resizing photos with Photoshop, which will manipulate parts of the Exif header. This is often reported as a bug in Jhead, but Jhead can't do much about incorrect data. @@ -449,19 +457,22 @@ <ul> You can use these programs to write and extract COM markers from JPEG images respectively. Although I always use my jhead program for this feature, the wrjpgcom and rdjpgcom programs are extremely simple and very -suitable for use with perl or shell scripts to process lots of images. These programs are part of most +suitable for use with shell scripts to process lots of images. These programs are part of most Linux distributions as part of the libjpg package (along with jpegtran) </ul> <p><br> -You may also want to try other exif manipulation tools, suhc as -<b><a href="http://www.sno.phy.queensu.ca/~phil/exiftool/">Exiftool</a></b> -<b><a href="http://libexif.sourceforge.net/">libexif</a></b> or -<b><a href="http://www.exiv2.org">exifv2</a></b>. These tools are more -capable than jhead, but also more complex, larger, and slower. +If you are looking for a feature that Jhead doesn't have, try +<a href="http://www.sno.phy.queensu.ca/~phil/exiftool/"><b>Exiftool</b></a>. +Exiftool is actively maintained and has a LOT of features. A downside of Exiftool is that +it's much bigger and slower. +<p> +For those who need a programming interface, there are: +<b><a href="https://libexif.github.io/">libexif</a></b> and +<b><a href="http://www.exiv2.org">exifv2</a></b>. <p> Jhead homeage: <a href="http://www.sentex.net/~mwandel/jhead">http://www.sentex.net/~mwandel/jhead</a><br> -Last Updated: Feb 2 2015<p> +Last Updated: Dec 31 2018<p>
