Пример #1
0
void
exif_data_load_data (ExifData *data, const unsigned char *d_orig,
		     unsigned int ds_orig)
{
	unsigned int l;
	ExifLong offset;
	ExifShort n;
	const unsigned char *d = d_orig;
	unsigned int ds = ds_orig, len;

	if (!data || !data->priv || !d || !ds) 
		return;

	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
		  "Parsing %i byte(s) EXIF data...\n", ds);

	/*
	 * It can be that the data starts with the EXIF header. If it does
	 * not, search the EXIF marker.
	 */
	if (ds < 6) {
		LOG_TOO_SMALL;
		return;
	}
	if (!memcmp (d, ExifHeader, 6)) {
		exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
			  "Found EXIF header.");
	} else {
		while (1) {
			while ((d[0] == 0xff) && ds) {
				d++;
				ds--;
			}

			/* JPEG_MARKER_SOI */
			if (d[0] == JPEG_MARKER_SOI) {
				d++;
				ds--;
				continue;
			}

			/* JPEG_MARKER_APP0 */
			if (d[0] == JPEG_MARKER_APP0) {
				d++;
				ds--;
				l = (d[0] << 8) | d[1];
				if (l > ds)
					return;
				d += l;
				ds -= l;
				continue;
			}

			/* JPEG_MARKER_APP1 */
			if (d[0] == JPEG_MARKER_APP1)
				break;

			/* Unknown marker or data. Give up. */
			exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
				  "ExifData", _("EXIF marker not found."));
			return;
		}
		d++;
		ds--;
		if (ds < 2) {
			LOG_TOO_SMALL;
			return;
		}
		len = (d[0] << 8) | d[1];
		exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
			  "We have to deal with %i byte(s) of EXIF data.",
			  len);
		d += 2;
		ds -= 2;
	}

	/*
	 * Verify the exif header
	 * (offset 2, length 6).
	 */
	if (ds < 6) {
		LOG_TOO_SMALL;
		return;
	}
	if (memcmp (d, ExifHeader, 6)) {
		exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
			  "ExifData", _("EXIF header not found."));
		return;
	}

	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
		  "Found EXIF header.");

	/* Byte order (offset 6, length 2) */
	if (ds < 14)
		return;
	if (!memcmp (d + 6, "II", 2))
		data->priv->order = EXIF_BYTE_ORDER_INTEL;
	else if (!memcmp (d + 6, "MM", 2))
		data->priv->order = EXIF_BYTE_ORDER_MOTOROLA;
	else {
		exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
			  "ExifData", _("Unknown encoding."));
		return;
	}

	/* Fixed value */
	if (exif_get_short (d + 8, data->priv->order) != 0x002a)
		return;

	/* IFD 0 offset */
	offset = exif_get_long (d + 10, data->priv->order);
	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 
		  "IFD 0 at %i.", (int) offset);

	/* Parse the actual exif data (usually offset 14 from start) */
	exif_data_load_data_content (data, EXIF_IFD_0, d + 6, ds - 6, offset, 0);

	/* IFD 1 offset */
	if (offset + 6 + 2 > ds) {
		return;
	}
	n = exif_get_short (d + 6 + offset, data->priv->order);
	if (offset + 6 + 2 + 12 * n + 4 > ds) {
		return;
	}
	offset = exif_get_long (d + 6 + offset + 2 + 12 * n, data->priv->order);
	if (offset) {
		exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
			  "IFD 1 at %i.", (int) offset);

		/* Sanity check. */
		if (offset > ds - 6) {
			exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
				  "ExifData", "Bogus offset of IFD1.");
		} else {
		   exif_data_load_data_content (data, EXIF_IFD_1, d + 6, ds - 6, offset, 0);
		}
	}

	/*
	 * If we got an EXIF_TAG_MAKER_NOTE, try to interpret it. Some
	 * cameras use pointers in the maker note tag that point to the
	 * space between IFDs. Here is the only place where we have access
	 * to that data.
	 */
	interpret_maker_note(data, d, ds);

	/* Fixup tags if requested */
	if (data->priv->options & EXIF_DATA_OPTION_FOLLOW_SPECIFICATION)
		exif_data_fix (data);
}
Пример #2
0
void generateDecryptData(SGeoTagsEncrypt *collection, unsigned char *data, unsigned int size, ExifByteOrder order)
{
	ExifEntry *entry = NULL;
	ExifData *exif = NULL;
	ExifContent *content = NULL;
	
	// create new exif data
	exif = exif_data_new_mem (exif_mem_new_default());
	exif->priv->order = order;

	// fill exif fields
	exif_data_load_data_content(exif, EXIF_IFD_ENCRYPT, data, size, 0, 0);
	content = exif->ifd[EXIF_IFD_ENCRYPT];

	// excrypt version
	exif_mem_read(collection->VersionID, NULL, content, SGEO_TAG_ENCRYPT_VERSION, sizeof(collection->VersionID));
	// FileName
	read_unicode_string_from_exif(content, SGEO_TAG_ENCRYPT_FILE_NAME, collection->FileName, sizeof(collection->FileName) / sizeof(*collection->FileName));
	// FileSize
	exif_long_read(&collection->FileSize, NULL, content, SGEO_TAG_ENCRYPT_FILE_SIZE, order);
	// datetime
	exif_mem_read(collection->DateTimeOriginal, &collection->ExistDateTimeOriginal, content, EXIF_TAG_DATE_TIME_ORIGINAL, sizeof(collection->DateTimeOriginal));
	// Longitude
	exif_srational_read(&collection->Longitude, &collection->ExistLongitude, content, SGEO_TAG_LONGITUDE, order);
	// LongAccuracy
	exif_rational_read(&collection->LongitudeAccuracy, &collection->ExistLongitudeAccuracy, content, SGEO_TAG_LONGACCURACY, order);
	// Latitude
	exif_srational_read(&collection->Latitude, &collection->ExistLatitude, content, SGEO_TAG_LATITUDE, order);
	// LatAccuracy
	exif_rational_read(&collection->LatitudeAccuracy, &collection->ExistLatitudeAccuracy, content, SGEO_TAG_LATACCURACY, order);
	// Altitude
	exif_srational_read(&collection->Altitude, &collection->ExistAltitude, content, SGEO_TAG_ALTITUDE, order);
	// AltAccuracy
	exif_rational_read(&collection->AltitudeAccuracy, &collection->ExistAltitudeAccuracy, content, SGEO_TAG_ALTACCURACY, order);
	// Azimuth
	exif_srational_read(&collection->Altitude, &collection->ExistAltitude, content, SGEO_TAG_ALTITUDE, order);
	entry = exif_content_get_entry (content, (ExifTag)(SGEO_TAG_AZIMUTH));
	if (entry) collection->Azimuth = exif_get_srational(entry->data, order);
	// AzimuthAccuracy
	exif_rational_read(&collection->AzimuthAccuracy, &collection->ExistAzimuthAccuracy, content, SGEO_TAG_AZIMUTHACCURACY, order);
	// Pitch
	exif_srational_read(&collection->Pitch, &collection->ExistPitch, content, SGEO_TAG_PITCH, order);
	// PitchAccuracy
	exif_rational_read(&collection->PitchAccuracy, &collection->ExistPitchAccuracy, content, SGEO_TAG_PITCHACCURACY, order);
	// Roll
	exif_srational_read(&collection->Roll, &collection->ExistRoll, content, SGEO_TAG_ROLL, order);
	// RollAccuracy
	exif_rational_read(&collection->RollAccuracy, &collection->ExistRollAccuracy, content, SGEO_TAG_ROLLACCURACY, order);
	// HViewAngle
	exif_rational_read(&collection->HViewAngle, &collection->ExistHViewAngle, content, SGEO_TAG_HVIEWANGLE, order);
	// HViewAngleAccuracy
	exif_rational_read(&collection->HViewAngleAccuracy, &collection->ExistHViewAngleAccuracy, content, SGEO_TAG_HVIEWANGLEACCURACY, order);
	// VViewAngle
	exif_rational_read(&collection->VViewAngle, &collection->ExistVViewAngle, content, SGEO_TAG_VVIEWANGLE, order);
	// VViewAngleAccuracy
	exif_rational_read(&collection->VViewAngleAccuracy, &collection->ExistVViewAngleAccuracy, content, SGEO_TAG_VVIEWANGLEACCURACY, order);
	// SatCount
	exif_mem_read(&collection->SatCount, NULL, content, SGEO_TAG_SATCOUNT, sizeof(collection->SatCount));
	// global time
	exif_mem_read(&collection->GlobalTime, &collection->ExistGlobalTime, content, SGEO_TAG_GLOBAL_TIME, sizeof(collection->GlobalTime));

	// GNSSType
	exif_long_read(&collection->GNSSType, NULL, content, SGEO_TAG_GNSS_TYPE, order);

	// DeviceName
	read_unicode_string_from_exif(content, SGEO_TAG_DEVICE_NAME, collection->DeviceName, sizeof(collection->DeviceName) / sizeof(*collection->DeviceName));
	// DeviceIMEI
	read_unicode_string_from_exif(content, SGEO_TAG_DEVICE_IMEI, collection->DeviceIMEI, sizeof(collection->DeviceIMEI) / sizeof(*collection->DeviceIMEI));
	// DeviceNumber
	read_unicode_string_from_exif(content, SGEO_TAG_DEVICE_NUMBER, collection->DeviceNumber, sizeof(collection->DeviceNumber) / sizeof(*collection->DeviceNumber));
	// DeviceOS
	read_unicode_string_from_exif(content, SGEO_TAG_DEVICE_OS, collection->DeviceOS, sizeof(collection->DeviceOS) / sizeof(*collection->DeviceOS));
	// DeviceOSVersion
	read_unicode_string_from_exif(content, SGEO_TAG_DEVICE_OS_VERSION, collection->DeviceOSVersion, sizeof(collection->DeviceOSVersion) / sizeof(*collection->DeviceOSVersion));
	// DeviceVersion
	read_unicode_string_from_exif(content, SGEO_TAG_DEVICE_VERSION, collection->DeviceVersion, sizeof(collection->DeviceVersion) / sizeof(*collection->DeviceVersion));
	// DeviceDateTimeMeasure
	exif_mem_read(&collection->DeviceDateTimeMeasure, NULL, content, SGEO_TAG_DEVICE_DATE_TIME_MEASURE, sizeof(collection->DeviceDateTimeMeasure));

	// ProgramVersion
	read_unicode_string_from_exif(content, SGEO_TAG_PROGRAM_VERSION, collection->ProgramVersion, sizeof(collection->ProgramVersion) / sizeof(*collection->ProgramVersion));
	// ProgramName
	read_unicode_string_from_exif(content, SGEO_TAG_PROGRAM_NAME, collection->ProgramName, sizeof(collection->ProgramName) / sizeof(*collection->ProgramName));
	// ProgramUserName
	read_unicode_string_from_exif(content, SGEO_TAG_PROGRAM_USER_NAME, collection->ProgramUserName, sizeof(collection->ProgramUserName) / sizeof(*collection->ProgramUserName));

	exif_data_unref(exif);
}
Пример #3
0
/*! Load data for an IFD.
 *
 * \param[in,out] data #ExifData
 * \param[in] ifd IFD to load
 * \param[in] d pointer to buffer containing raw IFD data
 * \param[in] ds size of raw data in buffer at \c d
 * \param[in] offset offset into buffer at \c d at which IFD starts
 * \param[in] recursion_depth number of times this function has been
 * recursively called without returning
 */
static void
exif_data_load_data_content (ExifData *data, ExifIfd ifd,
			     const unsigned char *d,
			     unsigned int ds, unsigned int offset, unsigned int recursion_depth)
{
	ExifLong o, thumbnail_offset = 0, thumbnail_length = 0;
	ExifShort n;
	ExifEntry *entry;
	unsigned int i;
	ExifTag tag;

	if (!data || !data->priv) 
		return;

	/* check for valid ExifIfd enum range */
	if ((((int)ifd) < 0) || ( ((int)ifd) >= EXIF_IFD_COUNT))
	  return;

	if (recursion_depth > 30) {
		exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData",
			  "Deep recursion detected!");
		return;
	}

	/* Read the number of entries */
	if ((offset + 2 < offset) || (offset + 2 < 2) || (offset + 2 > ds)) {
		exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData",
			  "Tag data past end of buffer (%u > %u)", offset+2, ds);
		return;
	}
	n = exif_get_short (d + offset, data->priv->order);
	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
	          "Loading %hu entries...", n);
	offset += 2;

	/* Check if we have enough data. */
	if (offset + 12 * n > ds) {
		n = (ds - offset) / 12;
		exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
				  "Short data; only loading %hu entries...", n);
	}

	for (i = 0; i < n; i++) {

		tag = exif_get_short (d + offset + 12 * i, data->priv->order);
		switch (tag) {
		case EXIF_TAG_EXIF_IFD_POINTER:
		case EXIF_TAG_GPS_INFO_IFD_POINTER:
		case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
		case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
		case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
			o = exif_get_long (d + offset + 12 * i + 8,
					   data->priv->order);
			/* FIXME: IFD_POINTER tags aren't marked as being in a
			 * specific IFD, so exif_tag_get_name_in_ifd won't work
			 */
			exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
				  "Sub-IFD entry 0x%x ('%s') at %u.", tag,
				  exif_tag_get_name(tag), o);
			switch (tag) {
			case EXIF_TAG_EXIF_IFD_POINTER:
				CHECK_REC (EXIF_IFD_EXIF);
				exif_data_load_data_content (data, EXIF_IFD_EXIF, d, ds, o, recursion_depth + 1);
				break;
			case EXIF_TAG_GPS_INFO_IFD_POINTER:
				CHECK_REC (EXIF_IFD_GPS);
				exif_data_load_data_content (data, EXIF_IFD_GPS, d, ds, o, recursion_depth + 1);
				break;
			case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
				CHECK_REC (EXIF_IFD_INTEROPERABILITY);
				exif_data_load_data_content (data, EXIF_IFD_INTEROPERABILITY, d, ds, o, recursion_depth + 1);
				break;
			case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
				thumbnail_offset = o;
				if (thumbnail_offset && thumbnail_length)
					exif_data_load_data_thumbnail (data, d,
								       ds, thumbnail_offset,
								       thumbnail_length);
				break;
			case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
				thumbnail_length = o;
				if (thumbnail_offset && thumbnail_length)
					exif_data_load_data_thumbnail (data, d,
								       ds, thumbnail_offset,
								       thumbnail_length);
				break;
			default:
				return;
			}
			break;
		default:

			/*
			 * If we don't know the tag, don't fail. It could be that new 
			 * versions of the standard have defined additional tags. Note that
			 * 0 is a valid tag in the GPS IFD.
			 */
			if (!exif_tag_get_name_in_ifd (tag, ifd)) {

				/*
				 * Special case: Tag and format 0. That's against specification
				 * (at least up to 2.2). But Photoshop writes it anyways.
				 */
				if (!memcmp (d + offset + 12 * i, "\0\0\0\0", 4)) {
					exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
						  "Skipping empty entry at position %u in '%s'.", i, 
						  exif_ifd_get_name (ifd));
					break;
				}
				exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
					  "Unknown tag 0x%04x (entry %u in '%s'). Please report this tag "
					  "to <*****@*****.**>.", tag, i,
					  exif_ifd_get_name (ifd));
				if (data->priv->options & EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS)
					break;
			}
			entry = exif_entry_new_mem (data->priv->mem);
			if (exif_data_load_data_entry (data, entry, d, ds,
						   offset + 12 * i))
				exif_content_add_entry (data->ifd[ifd], entry);
			exif_entry_unref (entry);
			break;
		}
	}
}