Obsolete old migrations and exif code (#13382)
* Obsoleted and deleted internal migrations + Enabled breaking changes checks agains v11.0.0-rc1 * Obsoleted and deleted internal exif stuff * Added CompatibilitySuppressions.xml * Change GenerateCompatibilitySuppressionFile
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -107,3 +107,4 @@ preserve.belle
|
||||
/src/Umbraco.Web.UI/appsettings-schema.*.json
|
||||
/tests/Umbraco.Tests.Integration/appsettings-schema.json
|
||||
/tests/Umbraco.Tests.Integration/appsettings-schema.*.json
|
||||
/src/Umbraco.Cms/appsettings-schema.json
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
|
||||
<!-- Package Validation -->
|
||||
<PropertyGroup>
|
||||
<GenerateCompatibilitySuppressionFile>false</GenerateCompatibilitySuppressionFile>
|
||||
<EnablePackageValidation>true</EnablePackageValidation>
|
||||
<!-- TODO: Change to 11.0.0 and remove all CompatibilitySuppressions.xml files when final version shipped -->
|
||||
<PackageValidationBaselineVersion>10.2.1</PackageValidationBaselineVersion>
|
||||
<PackageValidationBaselineVersion>11.0.0-rc1</PackageValidationBaselineVersion>
|
||||
<EnableStrictModeForCompatibleFrameworksInPackage>true</EnableStrictModeForCompatibleFrameworksInPackage>
|
||||
<EnableStrictModeForCompatibleTfms>true</EnableStrictModeForCompatibleTfms>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<Suppression>
|
||||
<DiagnosticId>PKV006</DiagnosticId>
|
||||
<Target>net6.0</Target>
|
||||
</Suppression>
|
||||
</Suppressions>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<Suppression>
|
||||
<DiagnosticId>PKV006</DiagnosticId>
|
||||
<Target>net6.0</Target>
|
||||
</Suppression>
|
||||
</Suppressions>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<Suppression>
|
||||
<DiagnosticId>PKV006</DiagnosticId>
|
||||
<Target>net6.0</Target>
|
||||
</Suppression>
|
||||
</Suppressions>
|
||||
@@ -1,7 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<Suppression>
|
||||
<DiagnosticId>PKV006</DiagnosticId>
|
||||
<Target>net6.0</Target>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Umbraco.Cms.Core.Deploy.IDataTypeConfigurationConnector.FromArtifact(Umbraco.Cms.Core.Models.IDataType,System.String,Umbraco.Cms.Core.Deploy.IContextCache)</Target>
|
||||
<Left>lib/net7.0/Umbraco.Core.dll</Left>
|
||||
<Right>lib/net7.0/Umbraco.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Umbraco.Cms.Core.Deploy.IDataTypeConfigurationConnector.ToArtifact(Umbraco.Cms.Core.Models.IDataType,System.Collections.Generic.ICollection{Umbraco.Cms.Core.Deploy.ArtifactDependency},Umbraco.Cms.Core.Deploy.IContextCache)</Target>
|
||||
<Left>lib/net7.0/Umbraco.Core.dll</Left>
|
||||
<Right>lib/net7.0/Umbraco.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Umbraco.Cms.Core.Deploy.IServiceConnector.GetArtifact(System.Object,Umbraco.Cms.Core.Deploy.IContextCache)</Target>
|
||||
<Left>lib/net7.0/Umbraco.Core.dll</Left>
|
||||
<Right>lib/net7.0/Umbraco.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Umbraco.Cms.Core.Deploy.IServiceConnector.GetArtifact(Umbraco.Cms.Core.Udi,Umbraco.Cms.Core.Deploy.IContextCache)</Target>
|
||||
<Left>lib/net7.0/Umbraco.Core.dll</Left>
|
||||
<Right>lib/net7.0/Umbraco.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Umbraco.Cms.Core.Deploy.IValueConnector.FromArtifact(System.String,Umbraco.Cms.Core.Models.IPropertyType,System.Object,Umbraco.Cms.Core.Deploy.IContextCache)</Target>
|
||||
<Left>lib/net7.0/Umbraco.Core.dll</Left>
|
||||
<Right>lib/net7.0/Umbraco.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Umbraco.Cms.Core.Deploy.IValueConnector.ToArtifact(System.Object,Umbraco.Cms.Core.Models.IPropertyType,System.Collections.Generic.ICollection{Umbraco.Cms.Core.Deploy.ArtifactDependency},Umbraco.Cms.Core.Deploy.IContextCache)</Target>
|
||||
<Left>lib/net7.0/Umbraco.Core.dll</Left>
|
||||
<Right>lib/net7.0/Umbraco.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
</Suppressions>
|
||||
@@ -1,346 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// An endian-aware converter for converting between base data types
|
||||
/// and an array of bytes.
|
||||
/// </summary>
|
||||
internal class BitConverterEx
|
||||
{
|
||||
#region Public Enums
|
||||
|
||||
/// <summary>
|
||||
/// Represents the byte order.
|
||||
/// </summary>
|
||||
public enum ByteOrder
|
||||
{
|
||||
LittleEndian = 1,
|
||||
BigEndian = 2,
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Member Variables
|
||||
|
||||
private readonly ByteOrder mFrom;
|
||||
private readonly ByteOrder mTo;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public BitConverterEx(ByteOrder from, ByteOrder to)
|
||||
{
|
||||
mFrom = from;
|
||||
mTo = to;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the byte order in which data is stored in this platform.
|
||||
/// </summary>
|
||||
public static ByteOrder SystemByteOrder =>
|
||||
BitConverter.IsLittleEndian ? ByteOrder.LittleEndian : ByteOrder.BigEndian;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Predefined Values
|
||||
|
||||
/// <summary>
|
||||
/// Returns a bit converter that converts between little-endian and system byte-order.
|
||||
/// </summary>
|
||||
public static BitConverterEx LittleEndian => new BitConverterEx(ByteOrder.LittleEndian, SystemByteOrder);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a bit converter that converts between big-endian and system byte-order.
|
||||
/// </summary>
|
||||
public static BitConverterEx BigEndian => new BitConverterEx(ByteOrder.BigEndian, SystemByteOrder);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a bit converter that does not do any byte-order conversion.
|
||||
/// </summary>
|
||||
public static BitConverterEx SystemEndian => new BitConverterEx(SystemByteOrder, SystemByteOrder);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a Unicode character.
|
||||
/// </summary>
|
||||
public static char ToChar(byte[] value, long startIndex, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = CheckData(value, startIndex, 2, from, to);
|
||||
return BitConverter.ToChar(data, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 16-bit unsigned integer.
|
||||
/// </summary>
|
||||
public static ushort ToUInt16(byte[] value, long startIndex, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = CheckData(value, startIndex, 2, from, to);
|
||||
return BitConverter.ToUInt16(data, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 32-bit unsigned integer.
|
||||
/// </summary>
|
||||
public static uint ToUInt32(byte[] value, long startIndex, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = CheckData(value, startIndex, 4, from, to);
|
||||
return BitConverter.ToUInt32(data, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 64-bit unsigned integer.
|
||||
/// </summary>
|
||||
public static ulong ToUInt64(byte[] value, long startIndex, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = CheckData(value, startIndex, 8, from, to);
|
||||
return BitConverter.ToUInt64(data, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 16-bit signed integer.
|
||||
/// </summary>
|
||||
public static short ToInt16(byte[] value, long startIndex, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = CheckData(value, startIndex, 2, from, to);
|
||||
return BitConverter.ToInt16(data, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 32-bit signed integer.
|
||||
/// </summary>
|
||||
public static int ToInt32(byte[] value, long startIndex, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = CheckData(value, startIndex, 4, from, to);
|
||||
return BitConverter.ToInt32(data, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 64-bit signed integer.
|
||||
/// </summary>
|
||||
public static long ToInt64(byte[] value, long startIndex, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = CheckData(value, startIndex, 8, from, to);
|
||||
return BitConverter.ToInt64(data, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a single precision floating number.
|
||||
/// </summary>
|
||||
public static float ToSingle(byte[] value, long startIndex, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = CheckData(value, startIndex, 4, from, to);
|
||||
return BitConverter.ToSingle(data, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a double precision floating number.
|
||||
/// </summary>
|
||||
public static double ToDouble(byte[] value, long startIndex, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = CheckData(value, startIndex, 8, from, to);
|
||||
return BitConverter.ToDouble(data, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 16-bit unsigned integer to an array of bytes.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(ushort value, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = BitConverter.GetBytes(value);
|
||||
data = CheckData(data, from, to);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 32-bit unsigned integer to an array of bytes.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(uint value, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = BitConverter.GetBytes(value);
|
||||
data = CheckData(data, from, to);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 64-bit unsigned integer to an array of bytes.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(ulong value, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = BitConverter.GetBytes(value);
|
||||
data = CheckData(data, from, to);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 16-bit signed integer to an array of bytes.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(short value, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = BitConverter.GetBytes(value);
|
||||
data = CheckData(data, from, to);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 32-bit signed integer to an array of bytes.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(int value, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = BitConverter.GetBytes(value);
|
||||
data = CheckData(data, from, to);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 64-bit signed integer to an array of bytes.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(long value, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = BitConverter.GetBytes(value);
|
||||
data = CheckData(data, from, to);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given single precision floating-point number to an array of bytes.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(float value, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = BitConverter.GetBytes(value);
|
||||
data = CheckData(data, from, to);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given double precision floating-point number to an array of bytes.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(double value, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = BitConverter.GetBytes(value);
|
||||
data = CheckData(data, from, to);
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 16-bit unsigned integer.
|
||||
/// </summary>
|
||||
public char ToChar(byte[] value, long startIndex) => ToChar(value, startIndex, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 16-bit unsigned integer.
|
||||
/// </summary>
|
||||
public ushort ToUInt16(byte[] value, long startIndex) => ToUInt16(value, startIndex, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 32-bit unsigned integer.
|
||||
/// </summary>
|
||||
public uint ToUInt32(byte[] value, long startIndex) => ToUInt32(value, startIndex, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 64-bit unsigned integer.
|
||||
/// </summary>
|
||||
public ulong ToUInt64(byte[] value, long startIndex) => ToUInt64(value, startIndex, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 16-bit signed integer.
|
||||
/// </summary>
|
||||
public short ToInt16(byte[] value, long startIndex) => ToInt16(value, startIndex, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 32-bit signed integer.
|
||||
/// </summary>
|
||||
public int ToInt32(byte[] value, long startIndex) => ToInt32(value, startIndex, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a 64-bit signed integer.
|
||||
/// </summary>
|
||||
public long ToInt64(byte[] value, long startIndex) => ToInt64(value, startIndex, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a single precision floating number.
|
||||
/// </summary>
|
||||
public float ToSingle(byte[] value, long startIndex) => ToSingle(value, startIndex, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of bytes to a double precision floating number.
|
||||
/// </summary>
|
||||
public double ToDouble(byte[] value, long startIndex) => ToDouble(value, startIndex, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 16-bit unsigned integer to an array of bytes.
|
||||
/// </summary>
|
||||
public byte[] GetBytes(ushort value) => GetBytes(value, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 32-bit unsigned integer to an array of bytes.
|
||||
/// </summary>
|
||||
public byte[] GetBytes(uint value) => GetBytes(value, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 64-bit unsigned integer to an array of bytes.
|
||||
/// </summary>
|
||||
public byte[] GetBytes(ulong value) => GetBytes(value, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 16-bit signed integer to an array of bytes.
|
||||
/// </summary>
|
||||
public byte[] GetBytes(short value) => GetBytes(value, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 32-bit signed integer to an array of bytes.
|
||||
/// </summary>
|
||||
public byte[] GetBytes(int value) => GetBytes(value, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given 64-bit signed integer to an array of bytes.
|
||||
/// </summary>
|
||||
public byte[] GetBytes(long value) => GetBytes(value, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given single precision floating-point number to an array of bytes.
|
||||
/// </summary>
|
||||
public byte[] GetBytes(float value) => GetBytes(value, mFrom, mTo);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given double precision floating-point number to an array of bytes.
|
||||
/// </summary>
|
||||
public byte[] GetBytes(double value) => GetBytes(value, mFrom, mTo);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Reverse the array of bytes as needed.
|
||||
/// </summary>
|
||||
private static byte[] CheckData(byte[] value, long startIndex, long length, ByteOrder from, ByteOrder to)
|
||||
{
|
||||
var data = new byte[length];
|
||||
Array.Copy(value, startIndex, data, 0, length);
|
||||
if (from != to)
|
||||
{
|
||||
Array.Reverse(data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reverse the array of bytes as needed.
|
||||
/// </summary>
|
||||
private static byte[] CheckData(byte[] value, ByteOrder from, ByteOrder to) =>
|
||||
CheckData(value, 0, value.Length, from, to);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,392 +0,0 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Converts between exif data types and array of bytes.
|
||||
/// </summary>
|
||||
internal class ExifBitConverter : BitConverterEx
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public ExifBitConverter(ByteOrder from, ByteOrder to)
|
||||
: base(from, to)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns an ASCII string converted from the given byte array.
|
||||
/// </summary>
|
||||
public static string ToAscii(byte[] data, bool endatfirstnull, Encoding encoding)
|
||||
{
|
||||
var len = data.Length;
|
||||
if (endatfirstnull)
|
||||
{
|
||||
len = Array.IndexOf(data, (byte)0);
|
||||
if (len == -1)
|
||||
{
|
||||
len = data.Length;
|
||||
}
|
||||
}
|
||||
|
||||
return encoding.GetString(data, 0, len);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an ASCII string converted from the given byte array.
|
||||
/// </summary>
|
||||
public static string ToAscii(byte[] data, Encoding encoding) => ToAscii(data, true, encoding);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string converted from the given byte array.
|
||||
/// from the numeric value of each byte.
|
||||
/// </summary>
|
||||
public static string ToString(byte[] data)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var b in data)
|
||||
{
|
||||
sb.Append(b);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a DateTime object converted from the given byte array.
|
||||
/// </summary>
|
||||
public static DateTime ToDateTime(byte[] data, bool hastime)
|
||||
{
|
||||
var str = ToAscii(data, Encoding.ASCII);
|
||||
var parts = str.Split(':', ' ');
|
||||
try
|
||||
{
|
||||
if (hastime && parts.Length == 6)
|
||||
{
|
||||
// yyyy:MM:dd HH:mm:ss
|
||||
// This is the expected format though some cameras
|
||||
// can use single digits. See Issue 21.
|
||||
return new DateTime(
|
||||
int.Parse(parts[0], CultureInfo.InvariantCulture),
|
||||
int.Parse(parts[1], CultureInfo.InvariantCulture),
|
||||
int.Parse(parts[2], CultureInfo.InvariantCulture),
|
||||
int.Parse(parts[3], CultureInfo.InvariantCulture),
|
||||
int.Parse(parts[4], CultureInfo.InvariantCulture),
|
||||
int.Parse(parts[5], CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
if (!hastime && parts.Length == 3)
|
||||
{
|
||||
// yyyy:MM:dd
|
||||
return new DateTime(
|
||||
int.Parse(parts[0], CultureInfo.InvariantCulture),
|
||||
int.Parse(parts[1], CultureInfo.InvariantCulture),
|
||||
int.Parse(parts[2], CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a DateTime object converted from the given byte array.
|
||||
/// </summary>
|
||||
public static DateTime ToDateTime(byte[] data) => ToDateTime(data, true);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an unsigned rational number converted from the first
|
||||
/// eight bytes of the given byte array. The first four bytes are
|
||||
/// assumed to be the numerator and the next four bytes are the
|
||||
/// denominator.
|
||||
/// Numbers are converted from the given byte-order to platform byte-order.
|
||||
/// </summary>
|
||||
public static MathEx.UFraction32 ToURational(byte[] data, ByteOrder frombyteorder)
|
||||
{
|
||||
var num = new byte[4];
|
||||
var den = new byte[4];
|
||||
Array.Copy(data, 0, num, 0, 4);
|
||||
Array.Copy(data, 4, den, 0, 4);
|
||||
return new MathEx.UFraction32(
|
||||
ToUInt32(num, 0, frombyteorder, SystemByteOrder),
|
||||
ToUInt32(den, 0, frombyteorder, SystemByteOrder));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a signed rational number converted from the first
|
||||
/// eight bytes of the given byte array. The first four bytes are
|
||||
/// assumed to be the numerator and the next four bytes are the
|
||||
/// denominator.
|
||||
/// Numbers are converted from the given byte-order to platform byte-order.
|
||||
/// </summary>
|
||||
public static MathEx.Fraction32 ToSRational(byte[] data, ByteOrder frombyteorder)
|
||||
{
|
||||
var num = new byte[4];
|
||||
var den = new byte[4];
|
||||
Array.Copy(data, 0, num, 0, 4);
|
||||
Array.Copy(data, 4, den, 0, 4);
|
||||
return new MathEx.Fraction32(
|
||||
ToInt32(num, 0, frombyteorder, SystemByteOrder),
|
||||
ToInt32(den, 0, frombyteorder, SystemByteOrder));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of 16-bit unsigned integers converted from
|
||||
/// the given byte array.
|
||||
/// Numbers are converted from the given byte-order to platform byte-order.
|
||||
/// </summary>
|
||||
public static ushort[] ToUShortArray(byte[] data, int count, ByteOrder frombyteorder)
|
||||
{
|
||||
var numbers = new ushort[count];
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
var num = new byte[2];
|
||||
Array.Copy(data, i * 2, num, 0, 2);
|
||||
numbers[i] = ToUInt16(num, 0, frombyteorder, SystemByteOrder);
|
||||
}
|
||||
|
||||
return numbers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of 32-bit unsigned integers converted from
|
||||
/// the given byte array.
|
||||
/// Numbers are converted from the given byte-order to platform byte-order.
|
||||
/// </summary>
|
||||
public static uint[] ToUIntArray(byte[] data, int count, ByteOrder frombyteorder)
|
||||
{
|
||||
var numbers = new uint[count];
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
var num = new byte[4];
|
||||
Array.Copy(data, i * 4, num, 0, 4);
|
||||
numbers[i] = ToUInt32(num, 0, frombyteorder, SystemByteOrder);
|
||||
}
|
||||
|
||||
return numbers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of 32-bit signed integers converted from
|
||||
/// the given byte array.
|
||||
/// Numbers are converted from the given byte-order to platform byte-order.
|
||||
/// </summary>
|
||||
public static int[] ToSIntArray(byte[] data, int count, ByteOrder byteorder)
|
||||
{
|
||||
var numbers = new int[count];
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
var num = new byte[4];
|
||||
Array.Copy(data, i * 4, num, 0, 4);
|
||||
numbers[i] = ToInt32(num, 0, byteorder, SystemByteOrder);
|
||||
}
|
||||
|
||||
return numbers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of unsigned rational numbers converted from
|
||||
/// the given byte array.
|
||||
/// Numbers are converted from the given byte-order to platform byte-order.
|
||||
/// </summary>
|
||||
public static MathEx.UFraction32[] ToURationalArray(byte[] data, int count, ByteOrder frombyteorder)
|
||||
{
|
||||
var numbers = new MathEx.UFraction32[count];
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
var num = new byte[4];
|
||||
var den = new byte[4];
|
||||
Array.Copy(data, i * 8, num, 0, 4);
|
||||
Array.Copy(data, (i * 8) + 4, den, 0, 4);
|
||||
numbers[i].Set(
|
||||
ToUInt32(num, 0, frombyteorder, SystemByteOrder),
|
||||
ToUInt32(den, 0, frombyteorder, SystemByteOrder));
|
||||
}
|
||||
|
||||
return numbers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of signed rational numbers converted from
|
||||
/// the given byte array.
|
||||
/// Numbers are converted from the given byte-order to platform byte-order.
|
||||
/// </summary>
|
||||
public static MathEx.Fraction32[] ToSRationalArray(byte[] data, int count, ByteOrder frombyteorder)
|
||||
{
|
||||
var numbers = new MathEx.Fraction32[count];
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
var num = new byte[4];
|
||||
var den = new byte[4];
|
||||
Array.Copy(data, i * 8, num, 0, 4);
|
||||
Array.Copy(data, (i * 8) + 4, den, 0, 4);
|
||||
numbers[i].Set(
|
||||
ToInt32(num, 0, frombyteorder, SystemByteOrder),
|
||||
ToInt32(den, 0, frombyteorder, SystemByteOrder));
|
||||
}
|
||||
|
||||
return numbers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given ascii string to an array of bytes optionally adding a null terminator.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(string value, bool addnull, Encoding encoding)
|
||||
{
|
||||
if (addnull)
|
||||
{
|
||||
value += '\0';
|
||||
}
|
||||
|
||||
return encoding.GetBytes(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given ascii string to an array of bytes without adding a null terminator.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(string value, Encoding encoding) => GetBytes(value, false, encoding);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given datetime to an array of bytes with a null terminator.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(DateTime value, bool hastime)
|
||||
{
|
||||
var str = string.Empty;
|
||||
if (hastime)
|
||||
{
|
||||
str = value.ToString("yyyy:MM:dd HH:mm:ss", CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
str = value.ToString("yyyy:MM:dd", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
return GetBytes(str, true, Encoding.ASCII);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given unsigned rational number to an array of bytes.
|
||||
/// Numbers are converted from the platform byte-order to the given byte-order.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(MathEx.UFraction32 value, ByteOrder tobyteorder)
|
||||
{
|
||||
var num = GetBytes(value.Numerator, SystemByteOrder, tobyteorder);
|
||||
var den = GetBytes(value.Denominator, SystemByteOrder, tobyteorder);
|
||||
var data = new byte[8];
|
||||
Array.Copy(num, 0, data, 0, 4);
|
||||
Array.Copy(den, 0, data, 4, 4);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given signed rational number to an array of bytes.
|
||||
/// Numbers are converted from the platform byte-order to the given byte-order.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(MathEx.Fraction32 value, ByteOrder tobyteorder)
|
||||
{
|
||||
var num = GetBytes(value.Numerator, SystemByteOrder, tobyteorder);
|
||||
var den = GetBytes(value.Denominator, SystemByteOrder, tobyteorder);
|
||||
var data = new byte[8];
|
||||
Array.Copy(num, 0, data, 0, 4);
|
||||
Array.Copy(den, 0, data, 4, 4);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of 16-bit unsigned integers to an array of bytes.
|
||||
/// Numbers are converted from the platform byte-order to the given byte-order.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(ushort[] value, ByteOrder tobyteorder)
|
||||
{
|
||||
var data = new byte[2 * value.Length];
|
||||
for (var i = 0; i < value.Length; i++)
|
||||
{
|
||||
var num = GetBytes(value[i], SystemByteOrder, tobyteorder);
|
||||
Array.Copy(num, 0, data, i * 2, 2);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of 32-bit unsigned integers to an array of bytes.
|
||||
/// Numbers are converted from the platform byte-order to the given byte-order.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(uint[] value, ByteOrder tobyteorder)
|
||||
{
|
||||
var data = new byte[4 * value.Length];
|
||||
for (var i = 0; i < value.Length; i++)
|
||||
{
|
||||
var num = GetBytes(value[i], SystemByteOrder, tobyteorder);
|
||||
Array.Copy(num, 0, data, i * 4, 4);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of 32-bit signed integers to an array of bytes.
|
||||
/// Numbers are converted from the platform byte-order to the given byte-order.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(int[] value, ByteOrder tobyteorder)
|
||||
{
|
||||
var data = new byte[4 * value.Length];
|
||||
for (var i = 0; i < value.Length; i++)
|
||||
{
|
||||
var num = GetBytes(value[i], SystemByteOrder, tobyteorder);
|
||||
Array.Copy(num, 0, data, i * 4, 4);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of unsigned rationals to an array of bytes.
|
||||
/// Numbers are converted from the platform byte-order to the given byte-order.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(MathEx.UFraction32[] value, ByteOrder tobyteorder)
|
||||
{
|
||||
var data = new byte[8 * value.Length];
|
||||
for (var i = 0; i < value.Length; i++)
|
||||
{
|
||||
var num = GetBytes(value[i].Numerator, SystemByteOrder, tobyteorder);
|
||||
var den = GetBytes(value[i].Denominator, SystemByteOrder, tobyteorder);
|
||||
Array.Copy(num, 0, data, i * 8, 4);
|
||||
Array.Copy(den, 0, data, (i * 8) + 4, 4);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given array of signed rationals to an array of bytes.
|
||||
/// Numbers are converted from the platform byte-order to the given byte-order.
|
||||
/// </summary>
|
||||
public static byte[] GetBytes(MathEx.Fraction32[] value, ByteOrder tobyteorder)
|
||||
{
|
||||
var data = new byte[8 * value.Length];
|
||||
for (var i = 0; i < value.Length; i++)
|
||||
{
|
||||
var num = GetBytes(value[i].Numerator, SystemByteOrder, tobyteorder);
|
||||
var den = GetBytes(value[i].Denominator, SystemByteOrder, tobyteorder);
|
||||
Array.Copy(num, 0, data, i * 8, 4);
|
||||
Array.Copy(den, 0, data, (i * 8) + 4, 4);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,297 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
internal enum Compression : ushort
|
||||
{
|
||||
Uncompressed = 1,
|
||||
CCITT1D = 2,
|
||||
Group3Fax = 3,
|
||||
Group4Fax = 4,
|
||||
LZW = 5,
|
||||
JPEG = 6,
|
||||
PackBits = 32773,
|
||||
}
|
||||
|
||||
internal enum PhotometricInterpretation : ushort
|
||||
{
|
||||
WhiteIsZero = 0,
|
||||
BlackIsZero = 1,
|
||||
RGB = 2,
|
||||
RGBPalette = 3,
|
||||
TransparencyMask = 4,
|
||||
CMYK = 5,
|
||||
YCbCr = 6,
|
||||
CIELab = 8,
|
||||
}
|
||||
|
||||
internal enum Orientation : ushort
|
||||
{
|
||||
Normal = 1,
|
||||
MirroredVertically = 2,
|
||||
Rotated180 = 3,
|
||||
MirroredHorizontally = 4,
|
||||
RotatedLeftAndMirroredVertically = 5,
|
||||
RotatedRight = 6,
|
||||
RotatedLeft = 7,
|
||||
RotatedRightAndMirroredVertically = 8,
|
||||
}
|
||||
|
||||
internal enum PlanarConfiguration : ushort
|
||||
{
|
||||
ChunkyFormat = 1,
|
||||
PlanarFormat = 2,
|
||||
}
|
||||
|
||||
internal enum YCbCrPositioning : ushort
|
||||
{
|
||||
Centered = 1,
|
||||
CoSited = 2,
|
||||
}
|
||||
|
||||
internal enum ResolutionUnit : ushort
|
||||
{
|
||||
Inches = 2,
|
||||
Centimeters = 3,
|
||||
}
|
||||
|
||||
internal enum ColorSpace : ushort
|
||||
{
|
||||
SRGB = 1,
|
||||
Uncalibrated = 0xfff,
|
||||
}
|
||||
|
||||
internal enum ExposureProgram : ushort
|
||||
{
|
||||
NotDefined = 0,
|
||||
Manual = 1,
|
||||
Normal = 2,
|
||||
AperturePriority = 3,
|
||||
ShutterPriority = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Biased toward depth of field.
|
||||
/// </summary>
|
||||
Creative = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Biased toward fast shutter speed.
|
||||
/// </summary>
|
||||
Action = 6,
|
||||
|
||||
/// <summary>
|
||||
/// For closeup photos with the background out of focus.
|
||||
/// </summary>
|
||||
Portrait = 7,
|
||||
|
||||
/// <summary>
|
||||
/// For landscape photos with the background in focus.
|
||||
/// </summary>
|
||||
Landscape = 8,
|
||||
}
|
||||
|
||||
internal enum MeteringMode : ushort
|
||||
{
|
||||
Unknown = 0,
|
||||
Average = 1,
|
||||
CenterWeightedAverage = 2,
|
||||
Spot = 3,
|
||||
MultiSpot = 4,
|
||||
Pattern = 5,
|
||||
Partial = 6,
|
||||
Other = 255,
|
||||
}
|
||||
|
||||
internal enum LightSource : ushort
|
||||
{
|
||||
Unknown = 0,
|
||||
Daylight = 1,
|
||||
Fluorescent = 2,
|
||||
Tungsten = 3,
|
||||
Flash = 4,
|
||||
FineWeather = 9,
|
||||
CloudyWeather = 10,
|
||||
Shade = 11,
|
||||
|
||||
/// <summary>
|
||||
/// D 5700 – 7100K
|
||||
/// </summary>
|
||||
DaylightFluorescent = 12,
|
||||
|
||||
/// <summary>
|
||||
/// N 4600 – 5400K
|
||||
/// </summary>
|
||||
DayWhiteFluorescent = 13,
|
||||
|
||||
/// <summary>
|
||||
/// W 3900 – 4500K
|
||||
/// </summary>
|
||||
CoolWhiteFluorescent = 14,
|
||||
|
||||
/// <summary>
|
||||
/// WW 3200 – 3700K
|
||||
/// </summary>
|
||||
WhiteFluorescent = 15,
|
||||
StandardLightA = 17,
|
||||
StandardLightB = 18,
|
||||
StandardLightC = 19,
|
||||
D55 = 20,
|
||||
D65 = 21,
|
||||
D75 = 22,
|
||||
D50 = 23,
|
||||
ISOStudioTungsten = 24,
|
||||
OtherLightSource = 255,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum Flash : ushort
|
||||
{
|
||||
FlashDidNotFire = 0,
|
||||
StrobeReturnLightNotDetected = 4,
|
||||
StrobeReturnLightDetected = 2,
|
||||
FlashFired = 1,
|
||||
CompulsoryFlashMode = 8,
|
||||
AutoMode = 16,
|
||||
NoFlashFunction = 32,
|
||||
RedEyeReductionMode = 64,
|
||||
}
|
||||
|
||||
internal enum SensingMethod : ushort
|
||||
{
|
||||
NotDefined = 1,
|
||||
OneChipColorAreaSensor = 2,
|
||||
TwoChipColorAreaSensor = 3,
|
||||
ThreeChipColorAreaSensor = 4,
|
||||
ColorSequentialAreaSensor = 5,
|
||||
TriLinearSensor = 7,
|
||||
ColorSequentialLinearSensor = 8,
|
||||
}
|
||||
|
||||
internal enum FileSource : byte // UNDEFINED
|
||||
{
|
||||
DSC = 3,
|
||||
}
|
||||
|
||||
internal enum SceneType : byte // UNDEFINED
|
||||
{
|
||||
DirectlyPhotographedImage = 1,
|
||||
}
|
||||
|
||||
internal enum CustomRendered : ushort
|
||||
{
|
||||
NormalProcess = 0,
|
||||
CustomProcess = 1,
|
||||
}
|
||||
|
||||
internal enum ExposureMode : ushort
|
||||
{
|
||||
Auto = 0,
|
||||
Manual = 1,
|
||||
AutoBracket = 2,
|
||||
}
|
||||
|
||||
internal enum WhiteBalance : ushort
|
||||
{
|
||||
Auto = 0,
|
||||
Manual = 1,
|
||||
}
|
||||
|
||||
internal enum SceneCaptureType : ushort
|
||||
{
|
||||
Standard = 0,
|
||||
Landscape = 1,
|
||||
Portrait = 2,
|
||||
NightScene = 3,
|
||||
}
|
||||
|
||||
internal enum GainControl : ushort
|
||||
{
|
||||
None = 0,
|
||||
LowGainUp = 1,
|
||||
HighGainUp = 2,
|
||||
LowGainDown = 3,
|
||||
HighGainDown = 4,
|
||||
}
|
||||
|
||||
internal enum Contrast : ushort
|
||||
{
|
||||
Normal = 0,
|
||||
Soft = 1,
|
||||
Hard = 2,
|
||||
}
|
||||
|
||||
internal enum Saturation : ushort
|
||||
{
|
||||
Normal = 0,
|
||||
Low = 1,
|
||||
High = 2,
|
||||
}
|
||||
|
||||
internal enum Sharpness : ushort
|
||||
{
|
||||
Normal = 0,
|
||||
Soft = 1,
|
||||
Hard = 2,
|
||||
}
|
||||
|
||||
internal enum SubjectDistanceRange : ushort
|
||||
{
|
||||
Unknown = 0,
|
||||
Macro = 1,
|
||||
CloseView = 2,
|
||||
DistantView = 3,
|
||||
}
|
||||
|
||||
internal enum GPSLatitudeRef : byte // ASCII
|
||||
{
|
||||
North = 78, // 'N'
|
||||
South = 83, // 'S'
|
||||
}
|
||||
|
||||
internal enum GPSLongitudeRef : byte // ASCII
|
||||
{
|
||||
West = 87, // 'W'
|
||||
East = 69, // 'E'
|
||||
}
|
||||
|
||||
internal enum GPSAltitudeRef : byte
|
||||
{
|
||||
AboveSeaLevel = 0,
|
||||
BelowSeaLevel = 1,
|
||||
}
|
||||
|
||||
internal enum GPSStatus : byte // ASCII
|
||||
{
|
||||
MeasurementInProgress = 65, // 'A'
|
||||
MeasurementInteroperability = 86, // 'V'
|
||||
}
|
||||
|
||||
internal enum GPSMeasureMode : byte // ASCII
|
||||
{
|
||||
TwoDimensional = 50, // '2'
|
||||
ThreeDimensional = 51, // '3'
|
||||
}
|
||||
|
||||
internal enum GPSSpeedRef : byte // ASCII
|
||||
{
|
||||
KilometersPerHour = 75, // 'K'
|
||||
MilesPerHour = 77, // 'M'
|
||||
Knots = 78, // 'N'
|
||||
}
|
||||
|
||||
internal enum GPSDirectionRef : byte // ASCII
|
||||
{
|
||||
TrueDirection = 84, // 'T'
|
||||
MagneticDirection = 77, // 'M'
|
||||
}
|
||||
|
||||
internal enum GPSDistanceRef : byte // ASCII
|
||||
{
|
||||
Kilometers = 75, // 'K'
|
||||
Miles = 77, // 'M'
|
||||
Knots = 78, // 'N'
|
||||
}
|
||||
|
||||
internal enum GPSDifferential : ushort
|
||||
{
|
||||
MeasurementWithoutDifferentialCorrection = 0,
|
||||
DifferentialCorrectionApplied = 1,
|
||||
}
|
||||
@@ -7,6 +7,7 @@ namespace Umbraco.Cms.Core.Media.Exif;
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Exception" />
|
||||
[Serializable]
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class NotValidExifFileException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,487 +0,0 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an enumerated value.
|
||||
/// </summary>
|
||||
internal class ExifEnumProperty<T> : ExifProperty
|
||||
where T : notnull
|
||||
{
|
||||
protected bool mIsBitField;
|
||||
protected T mValue;
|
||||
|
||||
public ExifEnumProperty(ExifTag tag, T value, bool isbitfield)
|
||||
: base(tag)
|
||||
{
|
||||
mValue = value;
|
||||
mIsBitField = isbitfield;
|
||||
}
|
||||
|
||||
public ExifEnumProperty(ExifTag tag, T value)
|
||||
: this(tag, value, false)
|
||||
{
|
||||
}
|
||||
|
||||
public new T Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (T)value;
|
||||
}
|
||||
|
||||
public bool IsBitField => mIsBitField;
|
||||
|
||||
public override ExifInterOperability Interoperability
|
||||
{
|
||||
get
|
||||
{
|
||||
var tagid = ExifTagFactory.GetTagID(mTag);
|
||||
|
||||
Type type = typeof(T);
|
||||
Type basetype = Enum.GetUnderlyingType(type);
|
||||
|
||||
if (type == typeof(FileSource) || type == typeof(SceneType))
|
||||
{
|
||||
// UNDEFINED
|
||||
return new ExifInterOperability(tagid, 7, 1, new[] { (byte)(object)mValue });
|
||||
}
|
||||
|
||||
if (type == typeof(GPSLatitudeRef) || type == typeof(GPSLongitudeRef) ||
|
||||
type == typeof(GPSStatus) || type == typeof(GPSMeasureMode) ||
|
||||
type == typeof(GPSSpeedRef) || type == typeof(GPSDirectionRef) ||
|
||||
type == typeof(GPSDistanceRef))
|
||||
{
|
||||
// ASCII
|
||||
return new ExifInterOperability(tagid, 2, 2, new byte[] { (byte)(object)mValue, 0 });
|
||||
}
|
||||
|
||||
if (basetype == typeof(byte))
|
||||
{
|
||||
// BYTE
|
||||
return new ExifInterOperability(tagid, 1, 1, new[] { (byte)(object)mValue });
|
||||
}
|
||||
|
||||
if (basetype == typeof(ushort))
|
||||
{
|
||||
// SHORT
|
||||
return new ExifInterOperability(
|
||||
tagid,
|
||||
3,
|
||||
1,
|
||||
BitConverterEx.GetBytes((ushort)(object)mValue, BitConverterEx.SystemByteOrder, BitConverterEx.SystemByteOrder));
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(
|
||||
$"An invalid enum type ({basetype.FullName}) was provided for type {type.FullName}");
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator T(ExifEnumProperty<T> obj) => obj.mValue;
|
||||
|
||||
public override string? ToString() => mValue.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an ASCII string. (EXIF Specification: UNDEFINED) Used for the UserComment field.
|
||||
/// </summary>
|
||||
internal class ExifEncodedString : ExifProperty
|
||||
{
|
||||
protected string mValue;
|
||||
|
||||
public ExifEncodedString(ExifTag tag, string value, Encoding encoding)
|
||||
: base(tag)
|
||||
{
|
||||
mValue = value;
|
||||
Encoding = encoding;
|
||||
}
|
||||
|
||||
public new string Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (string)value;
|
||||
}
|
||||
|
||||
public Encoding Encoding { get; set; }
|
||||
|
||||
public override ExifInterOperability Interoperability
|
||||
{
|
||||
get
|
||||
{
|
||||
var enc = string.Empty;
|
||||
if (Encoding == null)
|
||||
{
|
||||
enc = "\0\0\0\0\0\0\0\0";
|
||||
}
|
||||
else if (Encoding.EncodingName == "US-ASCII")
|
||||
{
|
||||
enc = "ASCII\0\0\0";
|
||||
}
|
||||
else if (Encoding.EncodingName == "Japanese (JIS 0208-1990 and 0212-1990)")
|
||||
{
|
||||
enc = "JIS\0\0\0\0\0";
|
||||
}
|
||||
else if (Encoding.EncodingName == "Unicode")
|
||||
{
|
||||
enc = "Unicode\0";
|
||||
}
|
||||
else
|
||||
{
|
||||
enc = "\0\0\0\0\0\0\0\0";
|
||||
}
|
||||
|
||||
var benc = Encoding.ASCII.GetBytes(enc);
|
||||
var bstr = Encoding == null ? Encoding.ASCII.GetBytes(mValue) : Encoding.GetBytes(mValue);
|
||||
var data = new byte[benc.Length + bstr.Length];
|
||||
Array.Copy(benc, 0, data, 0, benc.Length);
|
||||
Array.Copy(bstr, 0, data, benc.Length, bstr.Length);
|
||||
|
||||
return new ExifInterOperability(ExifTagFactory.GetTagID(mTag), 7, (uint)data.Length, data);
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator string(ExifEncodedString obj) => obj.mValue;
|
||||
|
||||
public override string ToString() => mValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an ASCII string formatted as DateTime. (EXIF Specification: ASCII) Used for the date time fields.
|
||||
/// </summary>
|
||||
internal class ExifDateTime : ExifProperty
|
||||
{
|
||||
protected DateTime mValue;
|
||||
|
||||
public ExifDateTime(ExifTag tag, DateTime value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new DateTime Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (DateTime)value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new(ExifTagFactory.GetTagID(mTag), 2, 20, ExifBitConverter.GetBytes(mValue, true));
|
||||
|
||||
public static implicit operator DateTime(ExifDateTime obj) => obj.mValue;
|
||||
|
||||
public override string ToString() => mValue.ToString("yyyy.MM.dd HH:mm:ss");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the exif version as a 4 byte ASCII string. (EXIF Specification: UNDEFINED)
|
||||
/// Used for the ExifVersion, FlashpixVersion, InteroperabilityVersion and GPSVersionID fields.
|
||||
/// </summary>
|
||||
internal class ExifVersion : ExifProperty
|
||||
{
|
||||
protected string mValue;
|
||||
|
||||
public ExifVersion(ExifTag tag, string value)
|
||||
: base(tag)
|
||||
{
|
||||
if (value.Length > 4)
|
||||
{
|
||||
mValue = value[..4];
|
||||
}
|
||||
else if (value.Length < 4)
|
||||
{
|
||||
mValue = value + new string(' ', 4 - value.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
public new string Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value[..4];
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (string)value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability
|
||||
{
|
||||
get
|
||||
{
|
||||
if (mTag == ExifTag.ExifVersion || mTag == ExifTag.FlashpixVersion ||
|
||||
mTag == ExifTag.InteroperabilityVersion)
|
||||
{
|
||||
return new ExifInterOperability(ExifTagFactory.GetTagID(mTag), 7, 4, Encoding.ASCII.GetBytes(mValue));
|
||||
}
|
||||
|
||||
var data = new byte[4];
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
data[i] = byte.Parse(mValue[0].ToString());
|
||||
}
|
||||
|
||||
return new ExifInterOperability(ExifTagFactory.GetTagID(mTag), 7, 4, data);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => mValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the location and area of the subject (EXIF Specification: 2xSHORT)
|
||||
/// The coordinate values, width, and height are expressed in relation to the
|
||||
/// upper left as origin, prior to rotation processing as per the Rotation tag.
|
||||
/// </summary>
|
||||
internal class ExifPointSubjectArea : ExifUShortArray
|
||||
{
|
||||
public ExifPointSubjectArea(ExifTag tag, ushort[] value)
|
||||
: base(tag, value)
|
||||
{
|
||||
}
|
||||
|
||||
public ExifPointSubjectArea(ExifTag tag, ushort x, ushort y)
|
||||
: base(tag, new[] { x, y })
|
||||
{
|
||||
}
|
||||
|
||||
public ushort X
|
||||
{
|
||||
get => mValue[0];
|
||||
set => mValue[0] = value;
|
||||
}
|
||||
|
||||
protected new ushort[] Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
public ushort Y
|
||||
{
|
||||
get => mValue[1];
|
||||
set => mValue[1] = value;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendFormat("({0:d}, {1:d})", mValue[0], mValue[1]);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the location and area of the subject (EXIF Specification: 3xSHORT)
|
||||
/// The coordinate values, width, and height are expressed in relation to the
|
||||
/// upper left as origin, prior to rotation processing as per the Rotation tag.
|
||||
/// </summary>
|
||||
internal class ExifCircularSubjectArea : ExifPointSubjectArea
|
||||
{
|
||||
public ExifCircularSubjectArea(ExifTag tag, ushort[] value)
|
||||
: base(tag, value)
|
||||
{
|
||||
}
|
||||
|
||||
public ExifCircularSubjectArea(ExifTag tag, ushort x, ushort y, ushort d)
|
||||
: base(tag, new[] { x, y, d })
|
||||
{
|
||||
}
|
||||
|
||||
public ushort Diamater
|
||||
{
|
||||
get => mValue[2];
|
||||
set => mValue[2] = value;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendFormat("({0:d}, {1:d}) {2:d}", mValue[0], mValue[1], mValue[2]);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the location and area of the subject (EXIF Specification: 4xSHORT)
|
||||
/// The coordinate values, width, and height are expressed in relation to the
|
||||
/// upper left as origin, prior to rotation processing as per the Rotation tag.
|
||||
/// </summary>
|
||||
internal class ExifRectangularSubjectArea : ExifPointSubjectArea
|
||||
{
|
||||
public ExifRectangularSubjectArea(ExifTag tag, ushort[] value)
|
||||
: base(tag, value)
|
||||
{
|
||||
}
|
||||
|
||||
public ExifRectangularSubjectArea(ExifTag tag, ushort x, ushort y, ushort w, ushort h)
|
||||
: base(tag, new[] { x, y, w, h })
|
||||
{
|
||||
}
|
||||
|
||||
public ushort Width
|
||||
{
|
||||
get => mValue[2];
|
||||
set => mValue[2] = value;
|
||||
}
|
||||
|
||||
public ushort Height
|
||||
{
|
||||
get => mValue[3];
|
||||
set => mValue[3] = value;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendFormat("({0:d}, {1:d}) ({2:d} x {3:d})", mValue[0], mValue[1], mValue[2], mValue[3]);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents GPS latitudes and longitudes (EXIF Specification: 3xRATIONAL)
|
||||
/// </summary>
|
||||
internal class GPSLatitudeLongitude : ExifURationalArray
|
||||
{
|
||||
public GPSLatitudeLongitude(ExifTag tag, MathEx.UFraction32[] value)
|
||||
: base(tag, value)
|
||||
{
|
||||
}
|
||||
|
||||
public GPSLatitudeLongitude(ExifTag tag, float d, float m, float s)
|
||||
: base(tag, new[] { new(d), new MathEx.UFraction32(m), new MathEx.UFraction32(s) })
|
||||
{
|
||||
}
|
||||
|
||||
public MathEx.UFraction32 Degrees
|
||||
{
|
||||
get => mValue[0];
|
||||
set => mValue[0] = value;
|
||||
}
|
||||
|
||||
protected new MathEx.UFraction32[] Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
public MathEx.UFraction32 Minutes
|
||||
{
|
||||
get => mValue[1];
|
||||
set => mValue[1] = value;
|
||||
}
|
||||
|
||||
public MathEx.UFraction32 Seconds
|
||||
{
|
||||
get => mValue[2];
|
||||
set => mValue[2] = value;
|
||||
}
|
||||
|
||||
public static explicit operator float(GPSLatitudeLongitude obj) => obj.ToFloat();
|
||||
|
||||
public float ToFloat() => (float)Degrees + ((float)Minutes / 60.0f) + ((float)Seconds / 3600.0f);
|
||||
|
||||
public override string ToString() =>
|
||||
string.Format("{0:F2}°{1:F2}'{2:F2}\"", (float)Degrees, (float)Minutes, (float)Seconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a GPS time stamp as UTC (EXIF Specification: 3xRATIONAL)
|
||||
/// </summary>
|
||||
internal class GPSTimeStamp : ExifURationalArray
|
||||
{
|
||||
public GPSTimeStamp(ExifTag tag, MathEx.UFraction32[] value)
|
||||
: base(tag, value)
|
||||
{
|
||||
}
|
||||
|
||||
public GPSTimeStamp(ExifTag tag, float h, float m, float s)
|
||||
: base(tag, new[] { new(h), new MathEx.UFraction32(m), new MathEx.UFraction32(s) })
|
||||
{
|
||||
}
|
||||
|
||||
public MathEx.UFraction32 Hour
|
||||
{
|
||||
get => mValue[0];
|
||||
set => mValue[0] = value;
|
||||
}
|
||||
|
||||
protected new MathEx.UFraction32[] Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
public MathEx.UFraction32 Minute
|
||||
{
|
||||
get => mValue[1];
|
||||
set => mValue[1] = value;
|
||||
}
|
||||
|
||||
public MathEx.UFraction32 Second
|
||||
{
|
||||
get => mValue[2];
|
||||
set => mValue[2] = value;
|
||||
}
|
||||
|
||||
public override string ToString() =>
|
||||
string.Format("{0:F2}:{1:F2}:{2:F2}\"", (float)Hour, (float)Minute, (float)Second);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an ASCII string. (EXIF Specification: BYTE)
|
||||
/// Used by Windows XP.
|
||||
/// </summary>
|
||||
internal class WindowsByteString : ExifProperty
|
||||
{
|
||||
protected string mValue;
|
||||
|
||||
public WindowsByteString(ExifTag tag, string value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new string Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (string)value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability
|
||||
{
|
||||
get
|
||||
{
|
||||
var data = Encoding.Unicode.GetBytes(mValue);
|
||||
return new ExifInterOperability(ExifTagFactory.GetTagID(mTag), 1, (uint)data.Length, data);
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator string(WindowsByteString obj) => obj.mValue;
|
||||
|
||||
public override string ToString() => mValue;
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a custom type descriptor for an ExifFile instance.
|
||||
/// </summary>
|
||||
internal sealed class ExifFileTypeDescriptionProvider : TypeDescriptionProvider
|
||||
{
|
||||
public ExifFileTypeDescriptionProvider()
|
||||
: this(TypeDescriptor.GetProvider(typeof(ImageFile)))
|
||||
{
|
||||
}
|
||||
|
||||
public ExifFileTypeDescriptionProvider(TypeDescriptionProvider parent)
|
||||
: base(parent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a custom type descriptor for the given type and object.
|
||||
/// </summary>
|
||||
/// <param name="objectType">The type of object for which to retrieve the type descriptor.</param>
|
||||
/// <param name="instance">
|
||||
/// An instance of the type. Can be null if no instance was passed to the
|
||||
/// <see cref="T:System.ComponentModel.TypeDescriptor" />.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// An <see cref="T:System.ComponentModel.ICustomTypeDescriptor" /> that can provide metadata for the type.
|
||||
/// </returns>
|
||||
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object? instance) =>
|
||||
new ExifFileTypeDescriptor(base.GetTypeDescriptor(objectType, instance), instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expands ExifProperty objects contained in an ExifFile as separate properties.
|
||||
/// </summary>
|
||||
internal sealed class ExifFileTypeDescriptor : CustomTypeDescriptor
|
||||
{
|
||||
private readonly ImageFile? owner;
|
||||
|
||||
public ExifFileTypeDescriptor(ICustomTypeDescriptor? parent, object? instance)
|
||||
: base(parent) =>
|
||||
owner = (ImageFile?)instance;
|
||||
|
||||
public override PropertyDescriptorCollection GetProperties(Attribute[]? attributes) => GetProperties();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a collection of property descriptors for the object represented by this type descriptor.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection" /> containing the property descriptions for the
|
||||
/// object represented by this type descriptor. The default is
|
||||
/// <see cref="F:System.ComponentModel.PropertyDescriptorCollection.Empty" />.
|
||||
/// </returns>
|
||||
public override PropertyDescriptorCollection GetProperties()
|
||||
{
|
||||
// Enumerate the original set of properties and create our new set with it
|
||||
var properties = new List<PropertyDescriptor>();
|
||||
|
||||
if (owner is not null)
|
||||
{
|
||||
foreach (ExifProperty prop in owner.Properties)
|
||||
{
|
||||
var pd = new ExifPropertyDescriptor(prop);
|
||||
properties.Add(pd);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally return the list
|
||||
return new PropertyDescriptorCollection(properties.ToArray(), true);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ExifPropertyDescriptor : PropertyDescriptor
|
||||
{
|
||||
private readonly ExifProperty linkedProperty;
|
||||
private readonly object originalValue;
|
||||
|
||||
public ExifPropertyDescriptor(ExifProperty property)
|
||||
: base(property.Name, new Attribute[] { new BrowsableAttribute(true) })
|
||||
{
|
||||
linkedProperty = property;
|
||||
originalValue = property.Value;
|
||||
}
|
||||
|
||||
public override Type ComponentType => typeof(JPEGFile);
|
||||
|
||||
public override bool IsReadOnly => false;
|
||||
|
||||
public override Type PropertyType => linkedProperty.Value.GetType();
|
||||
|
||||
public override bool CanResetValue(object component) => true;
|
||||
|
||||
public override object GetValue(object? component) => linkedProperty.Value;
|
||||
|
||||
public override void ResetValue(object component) => linkedProperty.Value = originalValue;
|
||||
|
||||
public override void SetValue(object? component, object? value)
|
||||
{
|
||||
if (value is not null)
|
||||
{
|
||||
linkedProperty.Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldSerializeValue(object component) => false;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents interoperability data for an exif tag in the platform byte order.
|
||||
/// </summary>
|
||||
internal struct ExifInterOperability
|
||||
{
|
||||
public ExifInterOperability(ushort tagid, ushort typeid, uint count, byte[] data)
|
||||
{
|
||||
TagID = tagid;
|
||||
TypeID = typeid;
|
||||
Count = count;
|
||||
Data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tag ID defined in the Exif standard.
|
||||
/// </summary>
|
||||
public ushort TagID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type code defined in the Exif standard.
|
||||
/// <list type="bullet">
|
||||
/// <item>1 = BYTE (byte)</item>
|
||||
/// <item>2 = ASCII (byte array)</item>
|
||||
/// <item>3 = SHORT (ushort)</item>
|
||||
/// <item>4 = LONG (uint)</item>
|
||||
/// <item>5 = RATIONAL (2 x uint: numerator, denominator)</item>
|
||||
/// <item>6 = BYTE (sbyte)</item>
|
||||
/// <item>7 = UNDEFINED (byte array)</item>
|
||||
/// <item>8 = SSHORT (short)</item>
|
||||
/// <item>9 = SLONG (int)</item>
|
||||
/// <item>10 = SRATIONAL (2 x int: numerator, denominator)</item>
|
||||
/// <item>11 = FLOAT (float)</item>
|
||||
/// <item>12 = DOUBLE (double)</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public ushort TypeID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the byte count or number of components.
|
||||
/// </summary>
|
||||
public uint Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the field value as an array of bytes.
|
||||
/// </summary>
|
||||
public byte[] Data { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the string representation of this instance.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString() => string.Format("Tag: {0}, Type: {1}, Count: {2}, Data Length: {3}", TagID, TypeID, Count, Data.Length);
|
||||
}
|
||||
@@ -1,672 +0,0 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the abstract base class for an Exif property.
|
||||
/// </summary>
|
||||
internal abstract class ExifProperty
|
||||
{
|
||||
protected IFD mIFD;
|
||||
protected string? mName;
|
||||
protected ExifTag mTag;
|
||||
|
||||
public ExifProperty(ExifTag tag)
|
||||
{
|
||||
mTag = tag;
|
||||
mIFD = ExifTagFactory.GetTagIFD(tag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Exif tag associated with this property.
|
||||
/// </summary>
|
||||
public ExifTag Tag => mTag;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the IFD section containing this property.
|
||||
/// </summary>
|
||||
public IFD IFD => mIFD;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of this property.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(mName))
|
||||
{
|
||||
return ExifTagFactory.GetTagName(mTag);
|
||||
}
|
||||
|
||||
return mName;
|
||||
}
|
||||
set => mName = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of this property.
|
||||
/// </summary>
|
||||
public object Value
|
||||
{
|
||||
get => _Value;
|
||||
set => _Value = value;
|
||||
}
|
||||
|
||||
protected abstract object _Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets interoperability data for this property.
|
||||
/// </summary>
|
||||
public abstract ExifInterOperability Interoperability { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an 8-bit unsigned integer. (EXIF Specification: BYTE)
|
||||
/// </summary>
|
||||
internal class ExifByte : ExifProperty
|
||||
{
|
||||
protected byte mValue;
|
||||
|
||||
public ExifByte(ExifTag tag, byte value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new byte Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = Convert.ToByte(value);
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(ExifTagFactory.GetTagID(mTag), 1, 1, new[] { mValue });
|
||||
|
||||
public static implicit operator byte(ExifByte obj) => obj.mValue;
|
||||
|
||||
public override string ToString() => mValue.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an array of 8-bit unsigned integers. (EXIF Specification: BYTE with count > 1)
|
||||
/// </summary>
|
||||
internal class ExifByteArray : ExifProperty
|
||||
{
|
||||
protected byte[] mValue;
|
||||
|
||||
public ExifByteArray(ExifTag tag, byte[] value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new byte[] Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (byte[])value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(ExifTagFactory.GetTagID(mTag), 1, (uint)mValue.Length, mValue);
|
||||
|
||||
public static implicit operator byte[](ExifByteArray obj) => obj.mValue;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append('[');
|
||||
foreach (var b in mValue)
|
||||
{
|
||||
sb.Append(b);
|
||||
sb.Append(' ');
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an ASCII string. (EXIF Specification: ASCII)
|
||||
/// </summary>
|
||||
internal class ExifAscii : ExifProperty
|
||||
{
|
||||
protected string mValue;
|
||||
|
||||
public ExifAscii(ExifTag tag, string value, Encoding encoding)
|
||||
: base(tag)
|
||||
{
|
||||
mValue = value;
|
||||
Encoding = encoding;
|
||||
}
|
||||
|
||||
public new string Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (string)value;
|
||||
}
|
||||
|
||||
public Encoding Encoding { get; }
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(
|
||||
ExifTagFactory.GetTagID(mTag),
|
||||
2,
|
||||
(uint)mValue.Length + 1,
|
||||
ExifBitConverter.GetBytes(mValue, true, Encoding));
|
||||
|
||||
public static implicit operator string(ExifAscii obj) => obj.mValue;
|
||||
|
||||
public override string ToString() => mValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 16-bit unsigned integer. (EXIF Specification: SHORT)
|
||||
/// </summary>
|
||||
internal class ExifUShort : ExifProperty
|
||||
{
|
||||
protected ushort mValue;
|
||||
|
||||
public ExifUShort(ExifTag tag, ushort value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new ushort Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = Convert.ToUInt16(value);
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(
|
||||
ExifTagFactory.GetTagID(mTag),
|
||||
3,
|
||||
1,
|
||||
BitConverterEx.GetBytes(mValue, BitConverterEx.SystemByteOrder, BitConverterEx.SystemByteOrder));
|
||||
|
||||
public static implicit operator ushort(ExifUShort obj) => obj.mValue;
|
||||
|
||||
public override string ToString() => mValue.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an array of 16-bit unsigned integers.
|
||||
/// (EXIF Specification: SHORT with count > 1)
|
||||
/// </summary>
|
||||
internal class ExifUShortArray : ExifProperty
|
||||
{
|
||||
protected ushort[] mValue;
|
||||
|
||||
public ExifUShortArray(ExifTag tag, ushort[] value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new ushort[] Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (ushort[])value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(
|
||||
ExifTagFactory.GetTagID(mTag),
|
||||
3,
|
||||
(uint)mValue.Length,
|
||||
ExifBitConverter.GetBytes(mValue, BitConverterEx.SystemByteOrder));
|
||||
|
||||
public static implicit operator ushort[](ExifUShortArray obj) => obj.mValue;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append('[');
|
||||
foreach (var b in mValue)
|
||||
{
|
||||
sb.Append(b);
|
||||
sb.Append(' ');
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 32-bit unsigned integer. (EXIF Specification: LONG)
|
||||
/// </summary>
|
||||
internal class ExifUInt : ExifProperty
|
||||
{
|
||||
protected uint mValue;
|
||||
|
||||
public ExifUInt(ExifTag tag, uint value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new uint Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = Convert.ToUInt32(value);
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(
|
||||
ExifTagFactory.GetTagID(mTag),
|
||||
4,
|
||||
1,
|
||||
BitConverterEx.GetBytes(mValue, BitConverterEx.SystemByteOrder, BitConverterEx.SystemByteOrder));
|
||||
|
||||
public static implicit operator uint(ExifUInt obj) => obj.mValue;
|
||||
|
||||
public override string ToString() => mValue.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an array of 16-bit unsigned integers.
|
||||
/// (EXIF Specification: LONG with count > 1)
|
||||
/// </summary>
|
||||
internal class ExifUIntArray : ExifProperty
|
||||
{
|
||||
protected uint[] mValue;
|
||||
|
||||
public ExifUIntArray(ExifTag tag, uint[] value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new uint[] Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (uint[])value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability => new ExifInterOperability(ExifTagFactory.GetTagID(mTag), 3, (uint)mValue.Length, ExifBitConverter.GetBytes(mValue, BitConverterEx.SystemByteOrder));
|
||||
|
||||
public static implicit operator uint[](ExifUIntArray obj) => obj.mValue;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append('[');
|
||||
foreach (var b in mValue)
|
||||
{
|
||||
sb.Append(b);
|
||||
sb.Append(' ');
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a rational number defined with a 32-bit unsigned numerator
|
||||
/// and denominator. (EXIF Specification: RATIONAL)
|
||||
/// </summary>
|
||||
internal class ExifURational : ExifProperty
|
||||
{
|
||||
protected MathEx.UFraction32 mValue;
|
||||
|
||||
public ExifURational(ExifTag tag, uint numerator, uint denominator)
|
||||
: base(tag) =>
|
||||
mValue = new MathEx.UFraction32(numerator, denominator);
|
||||
|
||||
public ExifURational(ExifTag tag, MathEx.UFraction32 value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new MathEx.UFraction32 Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (MathEx.UFraction32)value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(
|
||||
ExifTagFactory.GetTagID(mTag),
|
||||
5,
|
||||
1,
|
||||
ExifBitConverter.GetBytes(mValue, BitConverterEx.SystemByteOrder));
|
||||
|
||||
public static explicit operator float(ExifURational obj) => (float)obj.mValue;
|
||||
|
||||
public override string ToString() => mValue.ToString();
|
||||
|
||||
public float ToFloat() => (float)mValue;
|
||||
|
||||
public uint[] ToArray() => new[] { mValue.Numerator, mValue.Denominator };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an array of unsigned rational numbers.
|
||||
/// (EXIF Specification: RATIONAL with count > 1)
|
||||
/// </summary>
|
||||
internal class ExifURationalArray : ExifProperty
|
||||
{
|
||||
protected MathEx.UFraction32[] mValue;
|
||||
|
||||
public ExifURationalArray(ExifTag tag, MathEx.UFraction32[] value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new MathEx.UFraction32[] Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (MathEx.UFraction32[])value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(
|
||||
ExifTagFactory.GetTagID(mTag),
|
||||
5,
|
||||
(uint)mValue.Length,
|
||||
ExifBitConverter.GetBytes(mValue, BitConverterEx.SystemByteOrder));
|
||||
|
||||
public static explicit operator float[](ExifURationalArray obj)
|
||||
{
|
||||
var result = new float[obj.mValue.Length];
|
||||
for (var i = 0; i < obj.mValue.Length; i++)
|
||||
{
|
||||
result[i] = (float)obj.mValue[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append('[');
|
||||
foreach (MathEx.UFraction32 b in mValue)
|
||||
{
|
||||
sb.Append(b.ToString());
|
||||
sb.Append(' ');
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a byte array that can take any value. (EXIF Specification: UNDEFINED)
|
||||
/// </summary>
|
||||
internal class ExifUndefined : ExifProperty
|
||||
{
|
||||
protected byte[] mValue;
|
||||
|
||||
public ExifUndefined(ExifTag tag, byte[] value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new byte[] Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (byte[])value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(ExifTagFactory.GetTagID(mTag), 7, (uint)mValue.Length, mValue);
|
||||
|
||||
public static implicit operator byte[](ExifUndefined obj) => obj.mValue;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append('[');
|
||||
foreach (var b in mValue)
|
||||
{
|
||||
sb.Append(b);
|
||||
sb.Append(' ');
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 32-bit signed integer. (EXIF Specification: SLONG)
|
||||
/// </summary>
|
||||
internal class ExifSInt : ExifProperty
|
||||
{
|
||||
protected int mValue;
|
||||
|
||||
public ExifSInt(ExifTag tag, int value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new int Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = Convert.ToInt32(value);
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(
|
||||
ExifTagFactory.GetTagID(mTag),
|
||||
9,
|
||||
1,
|
||||
BitConverterEx.GetBytes(mValue, BitConverterEx.SystemByteOrder, BitConverterEx.SystemByteOrder));
|
||||
|
||||
public static implicit operator int(ExifSInt obj) => obj.mValue;
|
||||
|
||||
public override string ToString() => mValue.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an array of 32-bit signed integers.
|
||||
/// (EXIF Specification: SLONG with count > 1)
|
||||
/// </summary>
|
||||
internal class ExifSIntArray : ExifProperty
|
||||
{
|
||||
protected int[] mValue;
|
||||
|
||||
public ExifSIntArray(ExifTag tag, int[] value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new int[] Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (int[])value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(
|
||||
ExifTagFactory.GetTagID(mTag),
|
||||
9,
|
||||
(uint)mValue.Length,
|
||||
ExifBitConverter.GetBytes(mValue, BitConverterEx.SystemByteOrder));
|
||||
|
||||
public static implicit operator int[](ExifSIntArray obj) => obj.mValue;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append('[');
|
||||
foreach (var b in mValue)
|
||||
{
|
||||
sb.Append(b);
|
||||
sb.Append(' ');
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a rational number defined with a 32-bit signed numerator
|
||||
/// and denominator. (EXIF Specification: SRATIONAL)
|
||||
/// </summary>
|
||||
internal class ExifSRational : ExifProperty
|
||||
{
|
||||
protected MathEx.Fraction32 mValue;
|
||||
|
||||
public ExifSRational(ExifTag tag, int numerator, int denominator)
|
||||
: base(tag) =>
|
||||
mValue = new MathEx.Fraction32(numerator, denominator);
|
||||
|
||||
public ExifSRational(ExifTag tag, MathEx.Fraction32 value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new MathEx.Fraction32 Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (MathEx.Fraction32)value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(
|
||||
ExifTagFactory.GetTagID(mTag),
|
||||
10,
|
||||
1,
|
||||
ExifBitConverter.GetBytes(mValue, BitConverterEx.SystemByteOrder));
|
||||
|
||||
public static explicit operator float(ExifSRational obj) => (float)obj.mValue;
|
||||
|
||||
public override string ToString() => mValue.ToString();
|
||||
|
||||
public float ToFloat() => (float)mValue;
|
||||
|
||||
public int[] ToArray() => new[] { mValue.Numerator, mValue.Denominator };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an array of signed rational numbers.
|
||||
/// (EXIF Specification: SRATIONAL with count > 1)
|
||||
/// </summary>
|
||||
internal class ExifSRationalArray : ExifProperty
|
||||
{
|
||||
protected MathEx.Fraction32[] mValue;
|
||||
|
||||
public ExifSRationalArray(ExifTag tag, MathEx.Fraction32[] value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new MathEx.Fraction32[] Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (MathEx.Fraction32[])value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability =>
|
||||
new ExifInterOperability(
|
||||
ExifTagFactory.GetTagID(mTag),
|
||||
10,
|
||||
(uint)mValue.Length,
|
||||
ExifBitConverter.GetBytes(mValue, BitConverterEx.SystemByteOrder));
|
||||
|
||||
public static explicit operator float[](ExifSRationalArray obj)
|
||||
{
|
||||
var result = new float[obj.mValue.Length];
|
||||
for (var i = 0; i < obj.mValue.Length; i++)
|
||||
{
|
||||
result[i] = (float)obj.mValue[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append('[');
|
||||
foreach (MathEx.Fraction32 b in mValue)
|
||||
{
|
||||
sb.Append(b.ToString());
|
||||
sb.Append(' ');
|
||||
}
|
||||
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
@@ -1,493 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a collection of <see cref="ExifProperty" /> objects.
|
||||
/// </summary>
|
||||
internal class ExifPropertyCollection : IDictionary<ExifTag, ExifProperty>
|
||||
{
|
||||
#region Constructor
|
||||
|
||||
internal ExifPropertyCollection(ImageFile parentFile)
|
||||
{
|
||||
parent = parentFile;
|
||||
items = new Dictionary<ExifTag, ExifProperty>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Member Variables
|
||||
|
||||
private readonly ImageFile parent;
|
||||
private readonly Dictionary<ExifTag, ExifProperty> items;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of elements contained in the collection.
|
||||
/// </summary>
|
||||
public int Count => items.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection containing the keys in this collection.
|
||||
/// </summary>
|
||||
public ICollection<ExifTag> Keys => items.Keys;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection containing the values in this collection.
|
||||
/// </summary>
|
||||
public ICollection<ExifProperty> Values => items.Values;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
public ExifProperty this[ExifTag key]
|
||||
{
|
||||
get => items[key];
|
||||
set
|
||||
{
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
items.Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ExifProperty Collection Setters
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The tag to set.</param>
|
||||
/// <param name="value">The value of tag.</param>
|
||||
public void Set(ExifTag key, byte value)
|
||||
{
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
items.Add(key, new ExifByte(key, value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The tag to set.</param>
|
||||
/// <param name="value">The value of tag.</param>
|
||||
public void Set(ExifTag key, string value)
|
||||
{
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
if (key == ExifTag.WindowsTitle || key == ExifTag.WindowsComment || key == ExifTag.WindowsAuthor ||
|
||||
key == ExifTag.WindowsKeywords || key == ExifTag.WindowsSubject)
|
||||
{
|
||||
items.Add(key, new WindowsByteString(key, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(key, new ExifAscii(key, value, parent.Encoding));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The tag to set.</param>
|
||||
/// <param name="value">The value of tag.</param>
|
||||
public void Set(ExifTag key, ushort value)
|
||||
{
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
items.Add(key, new ExifUShort(key, value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The tag to set.</param>
|
||||
/// <param name="value">The value of tag.</param>
|
||||
public void Set(ExifTag key, int value)
|
||||
{
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
items.Add(key, new ExifSInt(key, value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The tag to set.</param>
|
||||
/// <param name="value">The value of tag.</param>
|
||||
public void Set(ExifTag key, uint value)
|
||||
{
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
items.Add(key, new ExifUInt(key, value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The tag to set.</param>
|
||||
/// <param name="value">The value of tag.</param>
|
||||
public void Set(ExifTag key, float value)
|
||||
{
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
items.Add(key, new ExifURational(key, new MathEx.UFraction32(value)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The tag to set.</param>
|
||||
/// <param name="value">The value of tag.</param>
|
||||
public void Set(ExifTag key, double value)
|
||||
{
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
items.Add(key, new ExifURational(key, new MathEx.UFraction32(value)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The tag to set.</param>
|
||||
/// <param name="value">The value of tag.</param>
|
||||
public void Set(ExifTag key, object value)
|
||||
{
|
||||
Type type = value.GetType();
|
||||
if (type.IsEnum)
|
||||
{
|
||||
Type etype = typeof(ExifEnumProperty<>).MakeGenericType(type);
|
||||
var prop = Activator.CreateInstance(etype, key, value);
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
if (prop is ExifProperty exifProperty)
|
||||
{
|
||||
items.Add(key, exifProperty);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("No exif property exists for this tag.", "value");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The tag to set.</param>
|
||||
/// <param name="value">The value of tag.</param>
|
||||
/// <param name="encoding">String encoding.</param>
|
||||
public void Set(ExifTag key, string value, Encoding encoding)
|
||||
{
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
items.Add(key, new ExifEncodedString(key, value, encoding));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The tag to set.</param>
|
||||
/// <param name="value">The value of tag.</param>
|
||||
public void Set(ExifTag key, DateTime value)
|
||||
{
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
items.Add(key, new ExifDateTime(key, value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ExifProperty" /> with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The tag to set.</param>
|
||||
/// <param name="d">Angular degrees (or clock hours for a timestamp).</param>
|
||||
/// <param name="m">Angular minutes (or clock minutes for a timestamp).</param>
|
||||
/// <param name="s">Angular seconds (or clock seconds for a timestamp).</param>
|
||||
public void Set(ExifTag key, float d, float m, float s)
|
||||
{
|
||||
if (items.ContainsKey(key))
|
||||
{
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
items.Add(key, new ExifURationalArray(key, new[] { new(d), new MathEx.UFraction32(m), new MathEx.UFraction32(s) }));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified item to the collection.
|
||||
/// </summary>
|
||||
/// <param name="item">The <see cref="ExifProperty" /> to add to the collection.</param>
|
||||
public void Add(ExifProperty item)
|
||||
{
|
||||
ExifProperty? oldItem = null;
|
||||
if (items.TryGetValue(item.Tag, out oldItem))
|
||||
{
|
||||
items[item.Tag] = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(item.Tag, item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all items from the collection.
|
||||
/// </summary>
|
||||
public void Clear() => items.Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the collection contains an element with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to locate in the collection.</param>
|
||||
/// <returns>
|
||||
/// true if the collection contains an element with the key; otherwise, false.
|
||||
/// </returns>
|
||||
/// <exception cref="T:System.ArgumentNullException">
|
||||
/// <paramref name="key" /> is null.
|
||||
/// </exception>
|
||||
public bool ContainsKey(ExifTag key) => items.ContainsKey(key);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the element with the specified key from the collection.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the element to remove.</param>
|
||||
/// <returns>
|
||||
/// true if the element is successfully removed; otherwise, false. This method also returns false if
|
||||
/// <paramref name="key" /> was not found in the original collection.
|
||||
/// </returns>
|
||||
/// <exception cref="T:System.ArgumentNullException">
|
||||
/// <paramref name="key" /> is null.
|
||||
/// </exception>
|
||||
public bool Remove(ExifTag key) => items.Remove(key);
|
||||
|
||||
/// <summary>
|
||||
/// Removes all items with the given IFD from the collection.
|
||||
/// </summary>
|
||||
/// <param name="ifd">The IFD section to remove.</param>
|
||||
public void Remove(IFD ifd)
|
||||
{
|
||||
var toRemove = new List<ExifTag>();
|
||||
foreach (KeyValuePair<ExifTag, ExifProperty> item in items)
|
||||
{
|
||||
if (item.Value.IFD == ifd)
|
||||
{
|
||||
toRemove.Add(item.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ExifTag tag in toRemove)
|
||||
{
|
||||
items.Remove(tag);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value associated with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key whose value to get.</param>
|
||||
/// <param name="value">
|
||||
/// When this method returns, the value associated with the specified key, if the key is found;
|
||||
/// otherwise, the default value for the type of the <paramref name="value" /> parameter. This parameter is passed
|
||||
/// uninitialized.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// true if the collection contains an element with the specified key; otherwise, false.
|
||||
/// </returns>
|
||||
/// <exception cref="T:System.ArgumentNullException">
|
||||
/// <paramref name="key" /> is null.
|
||||
/// </exception>
|
||||
public bool TryGetValue(ExifTag key, [MaybeNullWhen(false)] out ExifProperty value) =>
|
||||
items.TryGetValue(key, out value);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through a collection.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
|
||||
/// </returns>
|
||||
public IEnumerator<ExifProperty> GetEnumerator() => Values.GetEnumerator();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Hidden Interface
|
||||
|
||||
/// <summary>
|
||||
/// Adds an element with the provided key and value to the <see cref="T:System.Collections.Generic.IDictionary`2" />.
|
||||
/// </summary>
|
||||
/// <param name="key">The object to use as the key of the element to add.</param>
|
||||
/// <param name="value">The object to use as the value of the element to add.</param>
|
||||
/// <exception cref="T:System.ArgumentNullException">
|
||||
/// <paramref name="key" /> is null.
|
||||
/// </exception>
|
||||
/// <exception cref="T:System.ArgumentException">
|
||||
/// An element with the same key already exists in the
|
||||
/// <see cref="T:System.Collections.Generic.IDictionary`2" />.
|
||||
/// </exception>
|
||||
/// <exception cref="T:System.NotSupportedException">
|
||||
/// The <see cref="T:System.Collections.Generic.IDictionary`2" /> is
|
||||
/// read-only.
|
||||
/// </exception>
|
||||
void IDictionary<ExifTag, ExifProperty>.Add(ExifTag key, ExifProperty value) => Add(value);
|
||||
|
||||
/// <summary>
|
||||
/// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1" />.
|
||||
/// </summary>
|
||||
/// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
|
||||
/// <exception cref="T:System.NotSupportedException">
|
||||
/// The <see cref="T:System.Collections.Generic.ICollection`1" /> is
|
||||
/// read-only.
|
||||
/// </exception>
|
||||
void ICollection<KeyValuePair<ExifTag, ExifProperty>>.Add(KeyValuePair<ExifTag, ExifProperty> item) =>
|
||||
Add(item.Value);
|
||||
|
||||
bool ICollection<KeyValuePair<ExifTag, ExifProperty>>.Contains(KeyValuePair<ExifTag, ExifProperty> item) =>
|
||||
throw new NotSupportedException();
|
||||
|
||||
/// <summary>
|
||||
/// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1" /> to an
|
||||
/// <see cref="T:System.Array" />, starting at a particular <see cref="T:System.Array" /> index.
|
||||
/// </summary>
|
||||
/// <param name="array">
|
||||
/// The one-dimensional <see cref="T:System.Array" /> that is the destination of the elements copied
|
||||
/// from <see cref="T:System.Collections.Generic.ICollection`1" />. The <see cref="T:System.Array" /> must have
|
||||
/// zero-based indexing.
|
||||
/// </param>
|
||||
/// <param name="arrayIndex">The zero-based index in <paramref name="array" /> at which copying begins.</param>
|
||||
/// <exception cref="T:System.ArgumentNullException">
|
||||
/// <paramref name="array" /> is null.
|
||||
/// </exception>
|
||||
/// <exception cref="T:System.ArgumentOutOfRangeException">
|
||||
/// <paramref name="arrayIndex" /> is less than 0.
|
||||
/// </exception>
|
||||
/// <exception cref="T:System.ArgumentException">
|
||||
/// <paramref name="array" /> is multidimensional.-or-<paramref name="arrayIndex" /> is equal to or greater than the
|
||||
/// length of <paramref name="array" />.-or-The number of elements in the source
|
||||
/// <see cref="T:System.Collections.Generic.ICollection`1" /> is greater than the available space from
|
||||
/// <paramref name="arrayIndex" /> to the end of the destination <paramref name="array" />.-or-Type
|
||||
/// <paramref name="T" /> cannot be cast automatically to the type of the destination <paramref name="array" />.
|
||||
/// </exception>
|
||||
void ICollection<KeyValuePair<ExifTag, ExifProperty>>.CopyTo(KeyValuePair<ExifTag, ExifProperty>[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
throw new ArgumentNullException("array");
|
||||
}
|
||||
|
||||
if (arrayIndex < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("arrayIndex");
|
||||
}
|
||||
|
||||
if (array.Rank > 1)
|
||||
{
|
||||
throw new ArgumentException("Destination array is multidimensional.", "array");
|
||||
}
|
||||
|
||||
if (arrayIndex >= array.Length)
|
||||
{
|
||||
throw new ArgumentException("arrayIndex is equal to or greater than the length of destination array", "array");
|
||||
}
|
||||
|
||||
if (arrayIndex + items.Count > array.Length)
|
||||
{
|
||||
throw new ArgumentException("There is not enough space in destination array.", "array");
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
foreach (KeyValuePair<ExifTag, ExifProperty> item in items)
|
||||
{
|
||||
if (i >= arrayIndex)
|
||||
{
|
||||
array[i] = item;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.
|
||||
/// </summary>
|
||||
/// <returns>true if the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only; otherwise, false.</returns>
|
||||
bool ICollection<KeyValuePair<ExifTag, ExifProperty>>.IsReadOnly => false;
|
||||
|
||||
/// <summary>
|
||||
/// Removes the first occurrence of a specific object from the
|
||||
/// <see cref="T:System.Collections.Generic.ICollection`1" />.
|
||||
/// </summary>
|
||||
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
|
||||
/// <returns>
|
||||
/// true if <paramref name="item" /> was successfully removed from the
|
||||
/// <see cref="T:System.Collections.Generic.ICollection`1" />; otherwise, false. This method also returns false if
|
||||
/// <paramref name="item" /> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1" />.
|
||||
/// </returns>
|
||||
/// <exception cref="T:System.NotSupportedException">
|
||||
/// The <see cref="T:System.Collections.Generic.ICollection`1" /> is
|
||||
/// read-only.
|
||||
/// </exception>
|
||||
bool ICollection<KeyValuePair<ExifTag, ExifProperty>>.Remove(KeyValuePair<ExifTag, ExifProperty> item) =>
|
||||
throw new NotSupportedException();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through a collection.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
|
||||
/// </returns>
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates through the collection.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.
|
||||
/// </returns>
|
||||
IEnumerator<KeyValuePair<ExifTag, ExifProperty>> IEnumerable<KeyValuePair<ExifTag, ExifProperty>>.GetEnumerator() =>
|
||||
items.GetEnumerator();
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,598 +0,0 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Creates exif properties from interoperability parameters.
|
||||
/// </summary>
|
||||
internal static class ExifPropertyFactory
|
||||
{
|
||||
#region Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates an ExifProperty from the given interoperability parameters.
|
||||
/// </summary>
|
||||
/// <param name="tag">The tag id of the exif property.</param>
|
||||
/// <param name="type">The type id of the exif property.</param>
|
||||
/// <param name="count">Byte or component count.</param>
|
||||
/// <param name="value">Field data as an array of bytes.</param>
|
||||
/// <param name="byteOrder">Byte order of value.</param>
|
||||
/// <param name="ifd">IFD section containing this property.</param>
|
||||
/// <param name="encoding">The encoding to be used for text metadata when the source encoding is unknown.</param>
|
||||
/// <returns>an ExifProperty initialized from the interoperability parameters.</returns>
|
||||
public static ExifProperty Get(ushort tag, ushort type, uint count, byte[] value, BitConverterEx.ByteOrder byteOrder, IFD ifd, Encoding encoding)
|
||||
{
|
||||
var conv = new BitConverterEx(byteOrder, BitConverterEx.SystemByteOrder);
|
||||
|
||||
// Find the exif tag corresponding to given tag id
|
||||
ExifTag etag = ExifTagFactory.GetExifTag(ifd, tag);
|
||||
|
||||
if (ifd == IFD.Zeroth)
|
||||
{
|
||||
// Compression
|
||||
if (tag == 0x103)
|
||||
{
|
||||
return new ExifEnumProperty<Compression>(ExifTag.Compression, (Compression)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// PhotometricInterpretation
|
||||
if (tag == 0x106)
|
||||
{
|
||||
return new ExifEnumProperty<PhotometricInterpretation>(
|
||||
ExifTag.PhotometricInterpretation,
|
||||
(PhotometricInterpretation)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// Orientation
|
||||
if (tag == 0x112)
|
||||
{
|
||||
return new ExifEnumProperty<Orientation>(ExifTag.Orientation, (Orientation)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// PlanarConfiguration
|
||||
if (tag == 0x11c)
|
||||
{
|
||||
return new ExifEnumProperty<PlanarConfiguration>(
|
||||
ExifTag.PlanarConfiguration,
|
||||
(PlanarConfiguration)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// YCbCrPositioning
|
||||
if (tag == 0x213)
|
||||
{
|
||||
return new ExifEnumProperty<YCbCrPositioning>(
|
||||
ExifTag.YCbCrPositioning,
|
||||
(YCbCrPositioning)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// ResolutionUnit
|
||||
if (tag == 0x128)
|
||||
{
|
||||
return new ExifEnumProperty<ResolutionUnit>(
|
||||
ExifTag.ResolutionUnit,
|
||||
(ResolutionUnit)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// DateTime
|
||||
if (tag == 0x132)
|
||||
{
|
||||
return new ExifDateTime(ExifTag.DateTime, ExifBitConverter.ToDateTime(value));
|
||||
}
|
||||
|
||||
if (tag == 0x9c9b || tag == 0x9c9c || // Windows tags
|
||||
tag == 0x9c9d || tag == 0x9c9e || tag == 0x9c9f)
|
||||
{
|
||||
return new WindowsByteString(
|
||||
etag,
|
||||
Encoding.Unicode.GetString(value).TrimEnd(Constants.CharArrays.NullTerminator));
|
||||
}
|
||||
}
|
||||
else if (ifd == IFD.EXIF)
|
||||
{
|
||||
// ExifVersion
|
||||
if (tag == 0x9000)
|
||||
{
|
||||
return new ExifVersion(ExifTag.ExifVersion, ExifBitConverter.ToAscii(value, Encoding.ASCII));
|
||||
}
|
||||
|
||||
// FlashpixVersion
|
||||
if (tag == 0xa000)
|
||||
{
|
||||
return new ExifVersion(ExifTag.FlashpixVersion, ExifBitConverter.ToAscii(value, Encoding.ASCII));
|
||||
}
|
||||
|
||||
// ColorSpace
|
||||
if (tag == 0xa001)
|
||||
{
|
||||
return new ExifEnumProperty<ColorSpace>(ExifTag.ColorSpace, (ColorSpace)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// UserComment
|
||||
if (tag == 0x9286)
|
||||
{
|
||||
// Default to ASCII
|
||||
Encoding enc = Encoding.ASCII;
|
||||
bool hasenc;
|
||||
if (value.Length < 8)
|
||||
{
|
||||
hasenc = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasenc = true;
|
||||
var encstr = enc.GetString(value, 0, 8);
|
||||
if (string.Compare(encstr, "ASCII\0\0\0", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
enc = Encoding.ASCII;
|
||||
}
|
||||
else if (string.Compare(encstr, "JIS\0\0\0\0\0", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
enc = Encoding.GetEncoding("Japanese (JIS 0208-1990 and 0212-1990)");
|
||||
}
|
||||
else if (string.Compare(encstr, "Unicode\0", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
enc = Encoding.Unicode;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasenc = false;
|
||||
}
|
||||
}
|
||||
|
||||
var val = (hasenc ? enc.GetString(value, 8, value.Length - 8) : enc.GetString(value)).Trim(
|
||||
Constants.CharArrays.NullTerminator);
|
||||
|
||||
return new ExifEncodedString(ExifTag.UserComment, val, enc);
|
||||
}
|
||||
|
||||
// DateTimeOriginal
|
||||
if (tag == 0x9003)
|
||||
{
|
||||
return new ExifDateTime(ExifTag.DateTimeOriginal, ExifBitConverter.ToDateTime(value));
|
||||
}
|
||||
|
||||
// DateTimeDigitized
|
||||
if (tag == 0x9004)
|
||||
{
|
||||
return new ExifDateTime(ExifTag.DateTimeDigitized, ExifBitConverter.ToDateTime(value));
|
||||
}
|
||||
|
||||
// ExposureProgram
|
||||
if (tag == 0x8822)
|
||||
{
|
||||
return new ExifEnumProperty<ExposureProgram>(
|
||||
ExifTag.ExposureProgram,
|
||||
(ExposureProgram)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// MeteringMode
|
||||
if (tag == 0x9207)
|
||||
{
|
||||
return new ExifEnumProperty<MeteringMode>(ExifTag.MeteringMode, (MeteringMode)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// LightSource
|
||||
if (tag == 0x9208)
|
||||
{
|
||||
return new ExifEnumProperty<LightSource>(ExifTag.LightSource, (LightSource)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// Flash
|
||||
if (tag == 0x9209)
|
||||
{
|
||||
return new ExifEnumProperty<Flash>(ExifTag.Flash, (Flash)conv.ToUInt16(value, 0), true);
|
||||
}
|
||||
|
||||
// SubjectArea
|
||||
if (tag == 0x9214)
|
||||
{
|
||||
if (count == 3)
|
||||
{
|
||||
return new ExifCircularSubjectArea(
|
||||
ExifTag.SubjectArea,
|
||||
ExifBitConverter.ToUShortArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
if (count == 4)
|
||||
{
|
||||
return new ExifRectangularSubjectArea(
|
||||
ExifTag.SubjectArea,
|
||||
ExifBitConverter.ToUShortArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
return new ExifPointSubjectArea(
|
||||
ExifTag.SubjectArea,
|
||||
ExifBitConverter.ToUShortArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
// FocalPlaneResolutionUnit
|
||||
if (tag == 0xa210)
|
||||
{
|
||||
return new ExifEnumProperty<ResolutionUnit>(
|
||||
ExifTag.FocalPlaneResolutionUnit,
|
||||
(ResolutionUnit)conv.ToUInt16(value, 0),
|
||||
true);
|
||||
}
|
||||
|
||||
// SubjectLocation
|
||||
if (tag == 0xa214)
|
||||
{
|
||||
return new ExifPointSubjectArea(
|
||||
ExifTag.SubjectLocation,
|
||||
ExifBitConverter.ToUShortArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
// SensingMethod
|
||||
if (tag == 0xa217)
|
||||
{
|
||||
return new ExifEnumProperty<SensingMethod>(
|
||||
ExifTag.SensingMethod,
|
||||
(SensingMethod)conv.ToUInt16(value, 0),
|
||||
true);
|
||||
}
|
||||
|
||||
// FileSource
|
||||
if (tag == 0xa300)
|
||||
{
|
||||
return new ExifEnumProperty<FileSource>(ExifTag.FileSource, (FileSource)conv.ToUInt16(value, 0), true);
|
||||
}
|
||||
|
||||
// SceneType
|
||||
if (tag == 0xa301)
|
||||
{
|
||||
return new ExifEnumProperty<SceneType>(ExifTag.SceneType, (SceneType)conv.ToUInt16(value, 0), true);
|
||||
}
|
||||
|
||||
// CustomRendered
|
||||
if (tag == 0xa401)
|
||||
{
|
||||
return new ExifEnumProperty<CustomRendered>(
|
||||
ExifTag.CustomRendered,
|
||||
(CustomRendered)conv.ToUInt16(value, 0),
|
||||
true);
|
||||
}
|
||||
|
||||
// ExposureMode
|
||||
if (tag == 0xa402)
|
||||
{
|
||||
return new ExifEnumProperty<ExposureMode>(ExifTag.ExposureMode, (ExposureMode)conv.ToUInt16(value, 0), true);
|
||||
}
|
||||
|
||||
// WhiteBalance
|
||||
if (tag == 0xa403)
|
||||
{
|
||||
return new ExifEnumProperty<WhiteBalance>(ExifTag.WhiteBalance, (WhiteBalance)conv.ToUInt16(value, 0), true);
|
||||
}
|
||||
|
||||
// SceneCaptureType
|
||||
if (tag == 0xa406)
|
||||
{
|
||||
return new ExifEnumProperty<SceneCaptureType>(
|
||||
ExifTag.SceneCaptureType,
|
||||
(SceneCaptureType)conv.ToUInt16(value, 0),
|
||||
true);
|
||||
}
|
||||
|
||||
// GainControl
|
||||
if (tag == 0xa407)
|
||||
{
|
||||
return new ExifEnumProperty<GainControl>(ExifTag.GainControl, (GainControl)conv.ToUInt16(value, 0), true);
|
||||
}
|
||||
|
||||
// Contrast
|
||||
if (tag == 0xa408)
|
||||
{
|
||||
return new ExifEnumProperty<Contrast>(ExifTag.Contrast, (Contrast)conv.ToUInt16(value, 0), true);
|
||||
}
|
||||
|
||||
// Saturation
|
||||
if (tag == 0xa409)
|
||||
{
|
||||
return new ExifEnumProperty<Saturation>(ExifTag.Saturation, (Saturation)conv.ToUInt16(value, 0), true);
|
||||
}
|
||||
|
||||
// Sharpness
|
||||
if (tag == 0xa40a)
|
||||
{
|
||||
return new ExifEnumProperty<Sharpness>(ExifTag.Sharpness, (Sharpness)conv.ToUInt16(value, 0), true);
|
||||
}
|
||||
|
||||
// SubjectDistanceRange
|
||||
if (tag == 0xa40c)
|
||||
{
|
||||
return new ExifEnumProperty<SubjectDistanceRange>(
|
||||
ExifTag.SubjectDistanceRange,
|
||||
(SubjectDistanceRange)conv.ToUInt16(value, 0),
|
||||
true);
|
||||
}
|
||||
}
|
||||
else if (ifd == IFD.GPS)
|
||||
{
|
||||
// GPSVersionID
|
||||
if (tag == 0)
|
||||
{
|
||||
return new ExifVersion(ExifTag.GPSVersionID, ExifBitConverter.ToString(value));
|
||||
}
|
||||
|
||||
// GPSLatitudeRef
|
||||
if (tag == 1)
|
||||
{
|
||||
return new ExifEnumProperty<GPSLatitudeRef>(ExifTag.GPSLatitudeRef, (GPSLatitudeRef)value[0]);
|
||||
}
|
||||
|
||||
// GPSLatitude
|
||||
if (tag == 2)
|
||||
{
|
||||
return new GPSLatitudeLongitude(
|
||||
ExifTag.GPSLatitude,
|
||||
ExifBitConverter.ToURationalArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
// GPSLongitudeRef
|
||||
if (tag == 3)
|
||||
{
|
||||
return new ExifEnumProperty<GPSLongitudeRef>(ExifTag.GPSLongitudeRef, (GPSLongitudeRef)value[0]);
|
||||
}
|
||||
|
||||
// GPSLongitude
|
||||
if (tag == 4)
|
||||
{
|
||||
return new GPSLatitudeLongitude(
|
||||
ExifTag.GPSLongitude,
|
||||
ExifBitConverter.ToURationalArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
// GPSAltitudeRef
|
||||
if (tag == 5)
|
||||
{
|
||||
return new ExifEnumProperty<GPSAltitudeRef>(ExifTag.GPSAltitudeRef, (GPSAltitudeRef)value[0]);
|
||||
}
|
||||
|
||||
// GPSTimeStamp
|
||||
if (tag == 7)
|
||||
{
|
||||
return new GPSTimeStamp(
|
||||
ExifTag.GPSTimeStamp,
|
||||
ExifBitConverter.ToURationalArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
// GPSStatus
|
||||
if (tag == 9)
|
||||
{
|
||||
return new ExifEnumProperty<GPSStatus>(ExifTag.GPSStatus, (GPSStatus)value[0]);
|
||||
}
|
||||
|
||||
// GPSMeasureMode
|
||||
if (tag == 10)
|
||||
{
|
||||
return new ExifEnumProperty<GPSMeasureMode>(ExifTag.GPSMeasureMode, (GPSMeasureMode)value[0]);
|
||||
}
|
||||
|
||||
// GPSSpeedRef
|
||||
if (tag == 12)
|
||||
{
|
||||
return new ExifEnumProperty<GPSSpeedRef>(ExifTag.GPSSpeedRef, (GPSSpeedRef)value[0]);
|
||||
}
|
||||
|
||||
// GPSTrackRef
|
||||
if (tag == 14)
|
||||
{
|
||||
return new ExifEnumProperty<GPSDirectionRef>(ExifTag.GPSTrackRef, (GPSDirectionRef)value[0]);
|
||||
}
|
||||
|
||||
// GPSImgDirectionRef
|
||||
if (tag == 16)
|
||||
{
|
||||
return new ExifEnumProperty<GPSDirectionRef>(ExifTag.GPSImgDirectionRef, (GPSDirectionRef)value[0]);
|
||||
}
|
||||
|
||||
// GPSDestLatitudeRef
|
||||
if (tag == 19)
|
||||
{
|
||||
return new ExifEnumProperty<GPSLatitudeRef>(ExifTag.GPSDestLatitudeRef, (GPSLatitudeRef)value[0]);
|
||||
}
|
||||
|
||||
// GPSDestLatitude
|
||||
if (tag == 20)
|
||||
{
|
||||
return new GPSLatitudeLongitude(
|
||||
ExifTag.GPSDestLatitude,
|
||||
ExifBitConverter.ToURationalArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
// GPSDestLongitudeRef
|
||||
if (tag == 21)
|
||||
{
|
||||
return new ExifEnumProperty<GPSLongitudeRef>(ExifTag.GPSDestLongitudeRef, (GPSLongitudeRef)value[0]);
|
||||
}
|
||||
|
||||
// GPSDestLongitude
|
||||
if (tag == 22)
|
||||
{
|
||||
return new GPSLatitudeLongitude(
|
||||
ExifTag.GPSDestLongitude,
|
||||
ExifBitConverter.ToURationalArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
// GPSDestBearingRef
|
||||
if (tag == 23)
|
||||
{
|
||||
return new ExifEnumProperty<GPSDirectionRef>(ExifTag.GPSDestBearingRef, (GPSDirectionRef)value[0]);
|
||||
}
|
||||
|
||||
// GPSDestDistanceRef
|
||||
if (tag == 25)
|
||||
{
|
||||
return new ExifEnumProperty<GPSDistanceRef>(ExifTag.GPSDestDistanceRef, (GPSDistanceRef)value[0]);
|
||||
}
|
||||
|
||||
// GPSDate
|
||||
if (tag == 29)
|
||||
{
|
||||
return new ExifDateTime(ExifTag.GPSDateStamp, ExifBitConverter.ToDateTime(value, false));
|
||||
}
|
||||
|
||||
// GPSDifferential
|
||||
if (tag == 30)
|
||||
{
|
||||
return new ExifEnumProperty<GPSDifferential>(
|
||||
ExifTag.GPSDifferential,
|
||||
(GPSDifferential)conv.ToUInt16(value, 0));
|
||||
}
|
||||
}
|
||||
else if (ifd == IFD.Interop)
|
||||
{
|
||||
// InteroperabilityIndex
|
||||
if (tag == 1)
|
||||
{
|
||||
return new ExifAscii(ExifTag.InteroperabilityIndex, ExifBitConverter.ToAscii(value, Encoding.ASCII), Encoding.ASCII);
|
||||
}
|
||||
|
||||
// InteroperabilityVersion
|
||||
if (tag == 2)
|
||||
{
|
||||
return new ExifVersion(
|
||||
ExifTag.InteroperabilityVersion,
|
||||
ExifBitConverter.ToAscii(value, Encoding.ASCII));
|
||||
}
|
||||
}
|
||||
else if (ifd == IFD.First)
|
||||
{
|
||||
// Compression
|
||||
if (tag == 0x103)
|
||||
{
|
||||
return new ExifEnumProperty<Compression>(
|
||||
ExifTag.ThumbnailCompression,
|
||||
(Compression)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// PhotometricInterpretation
|
||||
if (tag == 0x106)
|
||||
{
|
||||
return new ExifEnumProperty<PhotometricInterpretation>(
|
||||
ExifTag.ThumbnailPhotometricInterpretation,
|
||||
(PhotometricInterpretation)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// Orientation
|
||||
if (tag == 0x112)
|
||||
{
|
||||
return new ExifEnumProperty<Orientation>(
|
||||
ExifTag.ThumbnailOrientation,
|
||||
(Orientation)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// PlanarConfiguration
|
||||
if (tag == 0x11c)
|
||||
{
|
||||
return new ExifEnumProperty<PlanarConfiguration>(
|
||||
ExifTag.ThumbnailPlanarConfiguration,
|
||||
(PlanarConfiguration)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// YCbCrPositioning
|
||||
if (tag == 0x213)
|
||||
{
|
||||
return new ExifEnumProperty<YCbCrPositioning>(
|
||||
ExifTag.ThumbnailYCbCrPositioning,
|
||||
(YCbCrPositioning)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// ResolutionUnit
|
||||
if (tag == 0x128)
|
||||
{
|
||||
return new ExifEnumProperty<ResolutionUnit>(
|
||||
ExifTag.ThumbnailResolutionUnit,
|
||||
(ResolutionUnit)conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
// DateTime
|
||||
if (tag == 0x132)
|
||||
{
|
||||
return new ExifDateTime(ExifTag.ThumbnailDateTime, ExifBitConverter.ToDateTime(value));
|
||||
}
|
||||
}
|
||||
|
||||
// 1 = BYTE An 8-bit unsigned integer.
|
||||
if (type == 1)
|
||||
{
|
||||
if (count == 1)
|
||||
{
|
||||
return new ExifByte(etag, value[0]);
|
||||
}
|
||||
|
||||
return new ExifByteArray(etag, value);
|
||||
}
|
||||
|
||||
// 2 = ASCII An 8-bit byte containing one 7-bit ASCII code.
|
||||
if (type == 2)
|
||||
{
|
||||
return new ExifAscii(etag, ExifBitConverter.ToAscii(value, encoding), encoding);
|
||||
}
|
||||
|
||||
// 3 = SHORT A 16-bit (2-byte) unsigned integer.
|
||||
if (type == 3)
|
||||
{
|
||||
if (count == 1)
|
||||
{
|
||||
return new ExifUShort(etag, conv.ToUInt16(value, 0));
|
||||
}
|
||||
|
||||
return new ExifUShortArray(etag, ExifBitConverter.ToUShortArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
// 4 = LONG A 32-bit (4-byte) unsigned integer.
|
||||
if (type == 4)
|
||||
{
|
||||
if (count == 1)
|
||||
{
|
||||
return new ExifUInt(etag, conv.ToUInt32(value, 0));
|
||||
}
|
||||
|
||||
return new ExifUIntArray(etag, ExifBitConverter.ToUIntArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
// 5 = RATIONAL Two LONGs. The first LONG is the numerator and the second LONG expresses the denominator.
|
||||
if (type == 5)
|
||||
{
|
||||
if (count == 1)
|
||||
{
|
||||
return new ExifURational(etag, ExifBitConverter.ToURational(value, byteOrder));
|
||||
}
|
||||
|
||||
return new ExifURationalArray(etag, ExifBitConverter.ToURationalArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
// 7 = UNDEFINED An 8-bit byte that can take any value depending on the field definition.
|
||||
if (type == 7)
|
||||
{
|
||||
return new ExifUndefined(etag, value);
|
||||
}
|
||||
|
||||
// 9 = SLONG A 32-bit (4-byte) signed integer (2's complement notation).
|
||||
if (type == 9)
|
||||
{
|
||||
if (count == 1)
|
||||
{
|
||||
return new ExifSInt(etag, conv.ToInt32(value, 0));
|
||||
}
|
||||
|
||||
return new ExifSIntArray(etag, ExifBitConverter.ToSIntArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
// 10 = SRATIONAL Two SLONGs. The first SLONG is the numerator and the second SLONG is the denominator.
|
||||
if (type == 10)
|
||||
{
|
||||
if (count == 1)
|
||||
{
|
||||
return new ExifSRational(etag, ExifBitConverter.ToSRational(value, byteOrder));
|
||||
}
|
||||
|
||||
return new ExifSRationalArray(etag, ExifBitConverter.ToSRationalArray(value, (int)count, byteOrder));
|
||||
}
|
||||
|
||||
throw new ArgumentException("Unknown property type.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,310 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the tags associated with exif fields.
|
||||
/// </summary>
|
||||
internal enum ExifTag
|
||||
{
|
||||
// ****************************
|
||||
// Zeroth IFD
|
||||
// ****************************
|
||||
NewSubfileType = IFD.Zeroth + 254,
|
||||
SubfileType = IFD.Zeroth + 255,
|
||||
ImageWidth = IFD.Zeroth + 256,
|
||||
ImageLength = IFD.Zeroth + 257,
|
||||
BitsPerSample = IFD.Zeroth + 258,
|
||||
Compression = IFD.Zeroth + 259,
|
||||
PhotometricInterpretation = IFD.Zeroth + 262,
|
||||
Threshholding = IFD.Zeroth + 263,
|
||||
CellWidth = IFD.Zeroth + 264,
|
||||
CellLength = IFD.Zeroth + 265,
|
||||
FillOrder = IFD.Zeroth + 266,
|
||||
DocumentName = IFD.Zeroth + 269,
|
||||
ImageDescription = IFD.Zeroth + 270,
|
||||
Make = IFD.Zeroth + 271,
|
||||
Model = IFD.Zeroth + 272,
|
||||
StripOffsets = IFD.Zeroth + 273,
|
||||
Orientation = IFD.Zeroth + 274,
|
||||
SamplesPerPixel = IFD.Zeroth + 277,
|
||||
RowsPerStrip = IFD.Zeroth + 278,
|
||||
StripByteCounts = IFD.Zeroth + 279,
|
||||
MinSampleValue = IFD.Zeroth + 280,
|
||||
MaxSampleValue = IFD.Zeroth + 281,
|
||||
XResolution = IFD.Zeroth + 282,
|
||||
YResolution = IFD.Zeroth + 283,
|
||||
PlanarConfiguration = IFD.Zeroth + 284,
|
||||
PageName = IFD.Zeroth + 285,
|
||||
XPosition = IFD.Zeroth + 286,
|
||||
YPosition = IFD.Zeroth + 287,
|
||||
FreeOffsets = IFD.Zeroth + 288,
|
||||
FreeByteCounts = IFD.Zeroth + 289,
|
||||
GrayResponseUnit = IFD.Zeroth + 290,
|
||||
GrayResponseCurve = IFD.Zeroth + 291,
|
||||
T4Options = IFD.Zeroth + 292,
|
||||
T6Options = IFD.Zeroth + 293,
|
||||
ResolutionUnit = IFD.Zeroth + 296,
|
||||
PageNumber = IFD.Zeroth + 297,
|
||||
TransferFunction = IFD.Zeroth + 301,
|
||||
Software = IFD.Zeroth + 305,
|
||||
DateTime = IFD.Zeroth + 306,
|
||||
Artist = IFD.Zeroth + 315,
|
||||
HostComputer = IFD.Zeroth + 316,
|
||||
Predictor = IFD.Zeroth + 317,
|
||||
WhitePoint = IFD.Zeroth + 318,
|
||||
PrimaryChromaticities = IFD.Zeroth + 319,
|
||||
ColorMap = IFD.Zeroth + 320,
|
||||
HalftoneHints = IFD.Zeroth + 321,
|
||||
TileWidth = IFD.Zeroth + 322,
|
||||
TileLength = IFD.Zeroth + 323,
|
||||
TileOffsets = IFD.Zeroth + 324,
|
||||
TileByteCounts = IFD.Zeroth + 325,
|
||||
InkSet = IFD.Zeroth + 332,
|
||||
InkNames = IFD.Zeroth + 333,
|
||||
NumberOfInks = IFD.Zeroth + 334,
|
||||
DotRange = IFD.Zeroth + 336,
|
||||
TargetPrinter = IFD.Zeroth + 337,
|
||||
ExtraSamples = IFD.Zeroth + 338,
|
||||
SampleFormat = IFD.Zeroth + 339,
|
||||
SMinSampleValue = IFD.Zeroth + 340,
|
||||
SMaxSampleValue = IFD.Zeroth + 341,
|
||||
TransferRange = IFD.Zeroth + 342,
|
||||
JPEGProc = IFD.Zeroth + 512,
|
||||
JPEGInterchangeFormat = IFD.Zeroth + 513,
|
||||
JPEGInterchangeFormatLength = IFD.Zeroth + 514,
|
||||
JPEGRestartInterval = IFD.Zeroth + 515,
|
||||
JPEGLosslessPredictors = IFD.Zeroth + 517,
|
||||
JPEGPointTransforms = IFD.Zeroth + 518,
|
||||
JPEGQTables = IFD.Zeroth + 519,
|
||||
JPEGDCTables = IFD.Zeroth + 520,
|
||||
JPEGACTables = IFD.Zeroth + 521,
|
||||
YCbCrCoefficients = IFD.Zeroth + 529,
|
||||
YCbCrSubSampling = IFD.Zeroth + 530,
|
||||
YCbCrPositioning = IFD.Zeroth + 531,
|
||||
ReferenceBlackWhite = IFD.Zeroth + 532,
|
||||
Copyright = IFD.Zeroth + 33432,
|
||||
|
||||
// Pointers to other IFDs
|
||||
EXIFIFDPointer = IFD.Zeroth + 34665,
|
||||
GPSIFDPointer = IFD.Zeroth + 34853,
|
||||
|
||||
// Windows Tags
|
||||
WindowsTitle = IFD.Zeroth + 0x9c9b,
|
||||
WindowsComment = IFD.Zeroth + 0x9c9c,
|
||||
WindowsAuthor = IFD.Zeroth + 0x9c9d,
|
||||
WindowsKeywords = IFD.Zeroth + 0x9c9e,
|
||||
WindowsSubject = IFD.Zeroth + 0x9c9f,
|
||||
|
||||
// Rating
|
||||
Rating = IFD.Zeroth + 0x4746,
|
||||
RatingPercent = IFD.Zeroth + 0x4749,
|
||||
|
||||
// Microsoft specifying padding and offset tags
|
||||
ZerothIFDPadding = IFD.Zeroth + 0xea1c,
|
||||
|
||||
// ****************************
|
||||
// EXIF Tags
|
||||
// ****************************
|
||||
ExifVersion = IFD.EXIF + 36864,
|
||||
FlashpixVersion = IFD.EXIF + 40960,
|
||||
ColorSpace = IFD.EXIF + 40961,
|
||||
ComponentsConfiguration = IFD.EXIF + 37121,
|
||||
CompressedBitsPerPixel = IFD.EXIF + 37122,
|
||||
PixelXDimension = IFD.EXIF + 40962,
|
||||
PixelYDimension = IFD.EXIF + 40963,
|
||||
MakerNote = IFD.EXIF + 37500,
|
||||
UserComment = IFD.EXIF + 37510,
|
||||
RelatedSoundFile = IFD.EXIF + 40964,
|
||||
DateTimeOriginal = IFD.EXIF + 36867,
|
||||
DateTimeDigitized = IFD.EXIF + 36868,
|
||||
SubSecTime = IFD.EXIF + 37520,
|
||||
SubSecTimeOriginal = IFD.EXIF + 37521,
|
||||
SubSecTimeDigitized = IFD.EXIF + 37522,
|
||||
ExposureTime = IFD.EXIF + 33434,
|
||||
FNumber = IFD.EXIF + 33437,
|
||||
ExposureProgram = IFD.EXIF + 34850,
|
||||
SpectralSensitivity = IFD.EXIF + 34852,
|
||||
ISOSpeedRatings = IFD.EXIF + 34855,
|
||||
OECF = IFD.EXIF + 34856,
|
||||
ShutterSpeedValue = IFD.EXIF + 37377,
|
||||
ApertureValue = IFD.EXIF + 37378,
|
||||
BrightnessValue = IFD.EXIF + 37379,
|
||||
ExposureBiasValue = IFD.EXIF + 37380,
|
||||
MaxApertureValue = IFD.EXIF + 37381,
|
||||
SubjectDistance = IFD.EXIF + 37382,
|
||||
MeteringMode = IFD.EXIF + 37383,
|
||||
LightSource = IFD.EXIF + 37384,
|
||||
Flash = IFD.EXIF + 37385,
|
||||
FocalLength = IFD.EXIF + 37386,
|
||||
SubjectArea = IFD.EXIF + 37396,
|
||||
FlashEnergy = IFD.EXIF + 41483,
|
||||
SpatialFrequencyResponse = IFD.EXIF + 41484,
|
||||
FocalPlaneXResolution = IFD.EXIF + 41486,
|
||||
FocalPlaneYResolution = IFD.EXIF + 41487,
|
||||
FocalPlaneResolutionUnit = IFD.EXIF + 41488,
|
||||
SubjectLocation = IFD.EXIF + 41492,
|
||||
ExposureIndex = IFD.EXIF + 41493,
|
||||
SensingMethod = IFD.EXIF + 41495,
|
||||
FileSource = IFD.EXIF + 41728,
|
||||
SceneType = IFD.EXIF + 41729,
|
||||
CFAPattern = IFD.EXIF + 41730,
|
||||
CustomRendered = IFD.EXIF + 41985,
|
||||
ExposureMode = IFD.EXIF + 41986,
|
||||
WhiteBalance = IFD.EXIF + 41987,
|
||||
DigitalZoomRatio = IFD.EXIF + 41988,
|
||||
FocalLengthIn35mmFilm = IFD.EXIF + 41989,
|
||||
SceneCaptureType = IFD.EXIF + 41990,
|
||||
GainControl = IFD.EXIF + 41991,
|
||||
Contrast = IFD.EXIF + 41992,
|
||||
Saturation = IFD.EXIF + 41993,
|
||||
Sharpness = IFD.EXIF + 41994,
|
||||
DeviceSettingDescription = IFD.EXIF + 41995,
|
||||
SubjectDistanceRange = IFD.EXIF + 41996,
|
||||
ImageUniqueID = IFD.EXIF + 42016,
|
||||
InteroperabilityIFDPointer = IFD.EXIF + 40965,
|
||||
|
||||
// Microsoft specifying padding and offset tags
|
||||
ExifIFDPadding = IFD.EXIF + 0xea1c,
|
||||
OffsetSchema = IFD.EXIF + 0xea1d,
|
||||
|
||||
// ****************************
|
||||
// GPS Tags
|
||||
// ****************************
|
||||
GPSVersionID = IFD.GPS + 0,
|
||||
GPSLatitudeRef = IFD.GPS + 1,
|
||||
GPSLatitude = IFD.GPS + 2,
|
||||
GPSLongitudeRef = IFD.GPS + 3,
|
||||
GPSLongitude = IFD.GPS + 4,
|
||||
GPSAltitudeRef = IFD.GPS + 5,
|
||||
GPSAltitude = IFD.GPS + 6,
|
||||
GPSTimeStamp = IFD.GPS + 7,
|
||||
GPSSatellites = IFD.GPS + 8,
|
||||
GPSStatus = IFD.GPS + 9,
|
||||
GPSMeasureMode = IFD.GPS + 10,
|
||||
GPSDOP = IFD.GPS + 11,
|
||||
GPSSpeedRef = IFD.GPS + 12,
|
||||
GPSSpeed = IFD.GPS + 13,
|
||||
GPSTrackRef = IFD.GPS + 14,
|
||||
GPSTrack = IFD.GPS + 15,
|
||||
GPSImgDirectionRef = IFD.GPS + 16,
|
||||
GPSImgDirection = IFD.GPS + 17,
|
||||
GPSMapDatum = IFD.GPS + 18,
|
||||
GPSDestLatitudeRef = IFD.GPS + 19,
|
||||
GPSDestLatitude = IFD.GPS + 20,
|
||||
GPSDestLongitudeRef = IFD.GPS + 21,
|
||||
GPSDestLongitude = IFD.GPS + 22,
|
||||
GPSDestBearingRef = IFD.GPS + 23,
|
||||
GPSDestBearing = IFD.GPS + 24,
|
||||
GPSDestDistanceRef = IFD.GPS + 25,
|
||||
GPSDestDistance = IFD.GPS + 26,
|
||||
GPSProcessingMethod = IFD.GPS + 27,
|
||||
GPSAreaInformation = IFD.GPS + 28,
|
||||
GPSDateStamp = IFD.GPS + 29,
|
||||
GPSDifferential = IFD.GPS + 30,
|
||||
|
||||
// ****************************
|
||||
// InterOp Tags
|
||||
// ****************************
|
||||
InteroperabilityIndex = IFD.Interop + 1,
|
||||
InteroperabilityVersion = IFD.Interop + 2,
|
||||
RelatedImageWidth = IFD.Interop + 0x1001,
|
||||
RelatedImageHeight = IFD.Interop + 0x1002,
|
||||
|
||||
// ****************************
|
||||
// First IFD TIFF Tags
|
||||
// ****************************
|
||||
ThumbnailImageWidth = IFD.First + 256,
|
||||
ThumbnailImageLength = IFD.First + 257,
|
||||
ThumbnailBitsPerSample = IFD.First + 258,
|
||||
ThumbnailCompression = IFD.First + 259,
|
||||
ThumbnailPhotometricInterpretation = IFD.First + 262,
|
||||
ThumbnailOrientation = IFD.First + 274,
|
||||
ThumbnailSamplesPerPixel = IFD.First + 277,
|
||||
ThumbnailPlanarConfiguration = IFD.First + 284,
|
||||
ThumbnailYCbCrSubSampling = IFD.First + 530,
|
||||
ThumbnailYCbCrPositioning = IFD.First + 531,
|
||||
ThumbnailXResolution = IFD.First + 282,
|
||||
ThumbnailYResolution = IFD.First + 283,
|
||||
ThumbnailResolutionUnit = IFD.First + 296,
|
||||
ThumbnailStripOffsets = IFD.First + 273,
|
||||
ThumbnailRowsPerStrip = IFD.First + 278,
|
||||
ThumbnailStripByteCounts = IFD.First + 279,
|
||||
ThumbnailJPEGInterchangeFormat = IFD.First + 513,
|
||||
ThumbnailJPEGInterchangeFormatLength = IFD.First + 514,
|
||||
ThumbnailTransferFunction = IFD.First + 301,
|
||||
ThumbnailWhitePoint = IFD.First + 318,
|
||||
ThumbnailPrimaryChromaticities = IFD.First + 319,
|
||||
ThumbnailYCbCrCoefficients = IFD.First + 529,
|
||||
ThumbnailReferenceBlackWhite = IFD.First + 532,
|
||||
ThumbnailDateTime = IFD.First + 306,
|
||||
ThumbnailImageDescription = IFD.First + 270,
|
||||
ThumbnailMake = IFD.First + 271,
|
||||
ThumbnailModel = IFD.First + 272,
|
||||
ThumbnailSoftware = IFD.First + 305,
|
||||
ThumbnailArtist = IFD.First + 315,
|
||||
ThumbnailCopyright = IFD.First + 33432,
|
||||
|
||||
// ****************************
|
||||
// JFIF Tags
|
||||
// ****************************
|
||||
|
||||
/// <summary>
|
||||
/// Represents the JFIF version.
|
||||
/// </summary>
|
||||
JFIFVersion = IFD.JFIF + 1,
|
||||
|
||||
/// <summary>
|
||||
/// Represents units for X and Y densities.
|
||||
/// </summary>
|
||||
JFIFUnits = IFD.JFIF + 101,
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal pixel density.
|
||||
/// </summary>
|
||||
XDensity = IFD.JFIF + 102,
|
||||
|
||||
/// <summary>
|
||||
/// Vertical pixel density
|
||||
/// </summary>
|
||||
YDensity = IFD.JFIF + 103,
|
||||
|
||||
/// <summary>
|
||||
/// Thumbnail horizontal pixel count.
|
||||
/// </summary>
|
||||
JFIFXThumbnail = IFD.JFIF + 201,
|
||||
|
||||
/// <summary>
|
||||
/// Thumbnail vertical pixel count.
|
||||
/// </summary>
|
||||
JFIFYThumbnail = IFD.JFIF + 202,
|
||||
|
||||
/// <summary>
|
||||
/// JFIF JPEG thumbnail.
|
||||
/// </summary>
|
||||
JFIFThumbnail = IFD.JFIF + 203,
|
||||
|
||||
/// <summary>
|
||||
/// Code which identifies the JFIF extension.
|
||||
/// </summary>
|
||||
JFXXExtensionCode = IFD.JFXX + 1,
|
||||
|
||||
/// <summary>
|
||||
/// Thumbnail horizontal pixel count.
|
||||
/// </summary>
|
||||
JFXXXThumbnail = IFD.JFXX + 101,
|
||||
|
||||
/// <summary>
|
||||
/// Thumbnail vertical pixel count.
|
||||
/// </summary>
|
||||
JFXXYThumbnail = IFD.JFXX + 102,
|
||||
|
||||
/// <summary>
|
||||
/// The 256-Color RGB palette.
|
||||
/// </summary>
|
||||
JFXXPalette = IFD.JFXX + 201,
|
||||
|
||||
/// <summary>
|
||||
/// JFIF thumbnail. The thumbnail will be either a JPEG,
|
||||
/// a 256 color palette bitmap, or a 24-bit RGB bitmap.
|
||||
/// </summary>
|
||||
JFXXThumbnail = IFD.JFXX + 202,
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
internal static class ExifTagFactory
|
||||
{
|
||||
#region Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns the ExifTag corresponding to the given tag id.
|
||||
/// </summary>
|
||||
public static ExifTag GetExifTag(IFD ifd, ushort tagid) => (ExifTag)(ifd + tagid);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the tag id corresponding to the given ExifTag.
|
||||
/// </summary>
|
||||
public static ushort GetTagID(ExifTag exiftag)
|
||||
{
|
||||
IFD ifd = GetTagIFD(exiftag);
|
||||
return (ushort)((int)exiftag - (int)ifd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the IFD section containing the given tag.
|
||||
/// </summary>
|
||||
public static IFD GetTagIFD(ExifTag tag) => (IFD)((int)tag / 100000 * 100000);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the string representation for the given exif tag.
|
||||
/// </summary>
|
||||
public static string GetTagName(ExifTag tag)
|
||||
{
|
||||
var name = Enum.GetName(typeof(ExifTag), tag);
|
||||
if (name == null)
|
||||
{
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the string representation for the given tag id.
|
||||
/// </summary>
|
||||
public static string GetTagName(IFD ifd, ushort tagid) => GetTagName(GetExifTag(ifd, tagid));
|
||||
|
||||
/// <summary>
|
||||
/// Returns the string representation for the given exif tag including
|
||||
/// IFD section and tag id.
|
||||
/// </summary>
|
||||
public static string GetTagLongName(ExifTag tag)
|
||||
{
|
||||
var ifdname = Enum.GetName(typeof(IFD), GetTagIFD(tag));
|
||||
var name = Enum.GetName(typeof(ExifTag), tag);
|
||||
if (name == null)
|
||||
{
|
||||
name = "Unknown";
|
||||
}
|
||||
|
||||
var tagidname = GetTagID(tag).ToString();
|
||||
return ifdname + ": " + name + " (" + tagidname + ")";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the IFD section containing tags.
|
||||
/// </summary>
|
||||
internal enum IFD
|
||||
{
|
||||
Unknown = 0,
|
||||
Zeroth = 100000,
|
||||
EXIF = 200000,
|
||||
GPS = 300000,
|
||||
Interop = 400000,
|
||||
First = 500000,
|
||||
MakerNote = 600000,
|
||||
JFIF = 700000,
|
||||
JFXX = 800000,
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using Umbraco.Cms.Core.Media.TypeDetector;
|
||||
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the base class for image files.
|
||||
/// </summary>
|
||||
[TypeDescriptionProvider(typeof(ExifFileTypeDescriptionProvider))]
|
||||
internal abstract class ImageFile
|
||||
{
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ImageFile" /> class.
|
||||
/// </summary>
|
||||
protected ImageFile()
|
||||
{
|
||||
Format = ImageFileFormat.Unknown;
|
||||
Properties = new ExifPropertyCollection(this);
|
||||
Encoding = Encoding.Default;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Returns the format of the <see cref="ImageFile" />.
|
||||
/// </summary>
|
||||
public ImageFileFormat Format { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of Exif properties contained in the <see cref="ImageFile" />.
|
||||
/// </summary>
|
||||
public ExifPropertyCollection Properties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the embedded thumbnail image.
|
||||
/// </summary>
|
||||
public ImageFile? Thumbnail { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Exif property with the given key.
|
||||
/// </summary>
|
||||
/// <param name="key">The Exif tag associated with the Exif property.</param>
|
||||
public ExifProperty this[ExifTag key]
|
||||
{
|
||||
get => Properties[key];
|
||||
set => Properties[key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the encoding used for text metadata when the source encoding is unknown.
|
||||
/// </summary>
|
||||
public Encoding Encoding { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <summary>
|
||||
/// Saves the <see cref="ImageFile" /> to the specified file.
|
||||
/// </summary>
|
||||
/// <param name="filename">A string that contains the name of the file.</param>
|
||||
public virtual void Save(string filename)
|
||||
{
|
||||
using (var stream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
Save(stream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the <see cref="ImageFile" /> to the specified stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">A <see cref="Sytem.IO.Stream" /> to save image data to.</param>
|
||||
public abstract void Save(Stream stream);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Static Methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="ImageFile" /> from the specified file.
|
||||
/// </summary>
|
||||
/// <param name="filename">A string that contains the name of the file.</param>
|
||||
/// <returns>The <see cref="ImageFile" /> created from the file.</returns>
|
||||
public static ImageFile? FromFile(string filename) => FromFile(filename, Encoding.Default);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="ImageFile" /> from the specified file.
|
||||
/// </summary>
|
||||
/// <param name="filename">A string that contains the name of the file.</param>
|
||||
/// <param name="encoding">The encoding to be used for text metadata when the source encoding is unknown.</param>
|
||||
/// <returns>The <see cref="ImageFile" /> created from the file.</returns>
|
||||
public static ImageFile? FromFile(string filename, Encoding encoding)
|
||||
{
|
||||
using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return FromStream(stream, encoding);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="ImageFile" /> from the specified data stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">A <see cref="Sytem.IO.Stream" /> that contains image data.</param>
|
||||
/// <returns>The <see cref="ImageFile" /> created from the file.</returns>
|
||||
public static ImageFile? FromStream(Stream stream) => FromStream(stream, Encoding.Default);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="ImageFile" /> from the specified data stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">A <see cref="Sytem.IO.Stream" /> that contains image data.</param>
|
||||
/// <param name="encoding">The encoding to be used for text metadata when the source encoding is unknown.</param>
|
||||
/// <returns>The <see cref="ImageFile" /> created from the file.</returns>
|
||||
public static ImageFile? FromStream(Stream stream, Encoding encoding)
|
||||
{
|
||||
// JPEG
|
||||
if (JpegDetector.IsOfType(stream))
|
||||
{
|
||||
return new JPEGFile(stream, encoding);
|
||||
}
|
||||
|
||||
// TIFF
|
||||
if (TIFFDetector.IsOfType(stream))
|
||||
{
|
||||
return new TIFFFile(stream, encoding);
|
||||
}
|
||||
|
||||
// SVG
|
||||
if (SvgDetector.IsOfType(stream))
|
||||
{
|
||||
return new SvgFile(stream);
|
||||
}
|
||||
|
||||
// We don't know
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an image file directory.
|
||||
/// </summary>
|
||||
internal class ImageFileDirectory
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ImageFileDirectory" /> class.
|
||||
/// </summary>
|
||||
public ImageFileDirectory()
|
||||
{
|
||||
Fields = new List<ImageFileDirectoryEntry>();
|
||||
Strips = new List<TIFFStrip>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The fields contained in this IFD.
|
||||
/// </summary>
|
||||
public List<ImageFileDirectoryEntry> Fields { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Offset to the next IFD.
|
||||
/// </summary>
|
||||
public uint NextIFDOffset { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Compressed image data.
|
||||
/// </summary>
|
||||
public List<TIFFStrip> Strips { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="ImageFileDirectory" /> initialized from the given byte data.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <param name="offset">The offset into <paramref name="data" />.</param>
|
||||
/// <param name="byteOrder">The byte order of <paramref name="data" />.</param>
|
||||
/// <returns>A <see cref="ImageFileDirectory" /> initialized from the given byte data.</returns>
|
||||
public static ImageFileDirectory FromBytes(byte[] data, uint offset, BitConverterEx.ByteOrder byteOrder)
|
||||
{
|
||||
var ifd = new ImageFileDirectory();
|
||||
var conv = new BitConverterEx(byteOrder, BitConverterEx.SystemByteOrder);
|
||||
|
||||
var stripOffsets = new List<uint>();
|
||||
var stripLengths = new List<uint>();
|
||||
|
||||
// Count
|
||||
var fieldcount = conv.ToUInt16(data, offset);
|
||||
|
||||
// Read fields
|
||||
for (uint i = 0; i < fieldcount; i++)
|
||||
{
|
||||
var fieldoffset = offset + 2 + (12 * i);
|
||||
var field = ImageFileDirectoryEntry.FromBytes(data, fieldoffset, byteOrder);
|
||||
ifd.Fields.Add(field);
|
||||
|
||||
// Read strip offsets
|
||||
if (field.Tag == 273)
|
||||
{
|
||||
var baselen = field.Data.Length / (int)field.Count;
|
||||
for (uint j = 0; j < field.Count; j++)
|
||||
{
|
||||
var val = new byte[baselen];
|
||||
Array.Copy(field.Data, j * baselen, val, 0, baselen);
|
||||
var stripOffset = field.Type == 3 ? BitConverter.ToUInt16(val, 0) : BitConverter.ToUInt32(val, 0);
|
||||
stripOffsets.Add(stripOffset);
|
||||
}
|
||||
}
|
||||
|
||||
// Read strip lengths
|
||||
if (field.Tag == 279)
|
||||
{
|
||||
var baselen = field.Data.Length / (int)field.Count;
|
||||
for (uint j = 0; j < field.Count; j++)
|
||||
{
|
||||
var val = new byte[baselen];
|
||||
Array.Copy(field.Data, j * baselen, val, 0, baselen);
|
||||
var stripLength = field.Type == 3 ? BitConverter.ToUInt16(val, 0) : BitConverter.ToUInt32(val, 0);
|
||||
stripLengths.Add(stripLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save strips
|
||||
if (stripOffsets.Count != stripLengths.Count)
|
||||
{
|
||||
throw new NotValidTIFFileException();
|
||||
}
|
||||
|
||||
for (var i = 0; i < stripOffsets.Count; i++)
|
||||
{
|
||||
ifd.Strips.Add(new TIFFStrip(data, stripOffsets[i], stripLengths[i]));
|
||||
}
|
||||
|
||||
// Offset to next ifd
|
||||
ifd.NextIFDOffset = conv.ToUInt32(data, offset + 2 + (12 * fieldcount));
|
||||
|
||||
return ifd;
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an entry in the image file directory.
|
||||
/// </summary>
|
||||
internal struct ImageFileDirectoryEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The tag that identifies the field.
|
||||
/// </summary>
|
||||
public ushort Tag;
|
||||
|
||||
/// <summary>
|
||||
/// Field type identifier.
|
||||
/// </summary>
|
||||
public ushort Type;
|
||||
|
||||
/// <summary>
|
||||
/// Count of Type.
|
||||
/// </summary>
|
||||
public uint Count;
|
||||
|
||||
/// <summary>
|
||||
/// Field data.
|
||||
/// </summary>
|
||||
public byte[] Data;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ImageFileDirectoryEntry" /> struct.
|
||||
/// </summary>
|
||||
/// <param name="tag">The tag that identifies the field.</param>
|
||||
/// <param name="type">Field type identifier.</param>
|
||||
/// <param name="count">Count of Type.</param>
|
||||
/// <param name="data">Field data.</param>
|
||||
public ImageFileDirectoryEntry(ushort tag, ushort type, uint count, byte[] data)
|
||||
{
|
||||
Tag = tag;
|
||||
Type = type;
|
||||
Count = count;
|
||||
Data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="ImageFileDirectoryEntry" /> initialized from the given byte data.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <param name="offset">The offset into <paramref name="data" />.</param>
|
||||
/// <param name="byteOrder">The byte order of <paramref name="data" />.</param>
|
||||
/// <returns>A <see cref="ImageFileDirectoryEntry" /> initialized from the given byte data.</returns>
|
||||
public static ImageFileDirectoryEntry FromBytes(byte[] data, uint offset, BitConverterEx.ByteOrder byteOrder)
|
||||
{
|
||||
// Tag ID
|
||||
var tag = BitConverterEx.ToUInt16(data, offset, byteOrder, BitConverterEx.SystemByteOrder);
|
||||
|
||||
// Tag Type
|
||||
var type = BitConverterEx.ToUInt16(data, offset + 2, byteOrder, BitConverterEx.SystemByteOrder);
|
||||
|
||||
// Count of Type
|
||||
var count = BitConverterEx.ToUInt32(data, offset + 4, byteOrder, BitConverterEx.SystemByteOrder);
|
||||
|
||||
// Field value or offset to field data
|
||||
var value = new byte[4];
|
||||
Array.Copy(data, offset + 8, value, 0, 4);
|
||||
|
||||
// Calculate the bytes we need to read
|
||||
var baselength = GetBaseLength(type);
|
||||
var totallength = count * baselength;
|
||||
|
||||
// If field value does not fit in 4 bytes
|
||||
// the value field is an offset to the actual
|
||||
// field value
|
||||
if (totallength > 4)
|
||||
{
|
||||
var dataoffset = BitConverterEx.ToUInt32(value, 0, byteOrder, BitConverterEx.SystemByteOrder);
|
||||
value = new byte[totallength];
|
||||
Array.Copy(data, dataoffset, value, 0, totallength);
|
||||
}
|
||||
|
||||
// Reverse array order if byte orders are different
|
||||
if (byteOrder != BitConverterEx.SystemByteOrder)
|
||||
{
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
var val = new byte[baselength];
|
||||
Array.Copy(value, i * baselength, val, 0, baselength);
|
||||
Array.Reverse(val);
|
||||
Array.Copy(val, 0, value, i * baselength, baselength);
|
||||
}
|
||||
}
|
||||
|
||||
return new ImageFileDirectoryEntry(tag, type, count, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base byte length for the given type.
|
||||
/// </summary>
|
||||
/// <param name="type">Type identifier.</param>
|
||||
private static uint GetBaseLength(ushort type)
|
||||
{
|
||||
// BYTE and SBYTE
|
||||
if (type == 1 || type == 6)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ASCII and UNDEFINED
|
||||
if (type == 2 || type == 7)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// SHORT and SSHORT
|
||||
if (type == 3 || type == 8)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
// LONG and SLONG
|
||||
if (type == 4 || type == 9)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
// RATIONAL (2xLONG) and SRATIONAL (2xSLONG)
|
||||
if (type == 5 || type == 10)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
// FLOAT
|
||||
if (type == 11)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
// DOUBLE
|
||||
if (type == 12)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Unknown type identifier.", "type");
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the format of the <see cref="ImageFile" />.
|
||||
/// </summary>
|
||||
internal enum ImageFileFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// The file is not recognized.
|
||||
/// </summary>
|
||||
Unknown,
|
||||
|
||||
/// <summary>
|
||||
/// The file is a JPEG/Exif or JPEG/JFIF file.
|
||||
/// </summary>
|
||||
JPEG,
|
||||
|
||||
/// <summary>
|
||||
/// The file is a TIFF File.
|
||||
/// </summary>
|
||||
TIFF,
|
||||
|
||||
/// <summary>
|
||||
/// The file is a SVG File.
|
||||
/// </summary>
|
||||
SVG,
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the units for the X and Y densities
|
||||
/// for a JFIF file.
|
||||
/// </summary>
|
||||
internal enum JFIFDensityUnit : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// No units, XDensity and YDensity specify the pixel aspect ratio.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// XDensity and YDensity are dots per inch.
|
||||
/// </summary>
|
||||
DotsPerInch = 1,
|
||||
|
||||
/// <summary>
|
||||
/// XDensity and YDensity are dots per cm.
|
||||
/// </summary>
|
||||
DotsPerCm = 2,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the JFIF extension.
|
||||
/// </summary>
|
||||
internal enum JFIFExtension : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Thumbnail coded using JPEG.
|
||||
/// </summary>
|
||||
ThumbnailJPEG = 0x10,
|
||||
|
||||
/// <summary>
|
||||
/// Thumbnail stored using a 256-Color RGB palette.
|
||||
/// </summary>
|
||||
ThumbnailPaletteRGB = 0x11,
|
||||
|
||||
/// <summary>
|
||||
/// Thumbnail stored using 3 bytes/pixel (24-bit) RGB values.
|
||||
/// </summary>
|
||||
Thumbnail24BitRGB = 0x13,
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the JFIF version as a 16 bit unsigned integer. (EXIF Specification: SHORT)
|
||||
/// </summary>
|
||||
internal class JFIFVersion : ExifUShort
|
||||
{
|
||||
public JFIFVersion(ExifTag tag, ushort value)
|
||||
: base(tag, value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the major version.
|
||||
/// </summary>
|
||||
public byte Major => (byte)(mValue >> 8);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the minor version.
|
||||
/// </summary>
|
||||
public byte Minor => (byte)(mValue - ((mValue >> 8) * 256));
|
||||
|
||||
public override string ToString() => string.Format("{0}.{1:00}", Major, Minor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a JFIF thumbnail. (EXIF Specification: BYTE)
|
||||
/// </summary>
|
||||
internal class JFIFThumbnailProperty : ExifProperty
|
||||
{
|
||||
protected JFIFThumbnail mValue;
|
||||
|
||||
public JFIFThumbnailProperty(ExifTag tag, JFIFThumbnail value)
|
||||
: base(tag) =>
|
||||
mValue = value;
|
||||
|
||||
public new JFIFThumbnail Value
|
||||
{
|
||||
get => mValue;
|
||||
set => mValue = value;
|
||||
}
|
||||
|
||||
protected override object _Value
|
||||
{
|
||||
get => Value;
|
||||
set => Value = (JFIFThumbnail)value;
|
||||
}
|
||||
|
||||
public override ExifInterOperability Interoperability
|
||||
{
|
||||
get
|
||||
{
|
||||
if (mValue.Format == JFIFThumbnail.ImageFormat.BMP24Bit)
|
||||
{
|
||||
return new ExifInterOperability(ExifTagFactory.GetTagID(mTag), 1, (uint)mValue.PixelData.Length, mValue.PixelData);
|
||||
}
|
||||
|
||||
if (mValue.Format == JFIFThumbnail.ImageFormat.BMPPalette)
|
||||
{
|
||||
var data = new byte[mValue.Palette.Length + mValue.PixelData.Length];
|
||||
Array.Copy(mValue.Palette, data, mValue.Palette.Length);
|
||||
Array.Copy(mValue.PixelData, 0, data, mValue.Palette.Length, mValue.PixelData.Length);
|
||||
return new ExifInterOperability(ExifTagFactory.GetTagID(mTag), 1, (uint)data.Length, data);
|
||||
}
|
||||
|
||||
if (mValue.Format == JFIFThumbnail.ImageFormat.JPEG)
|
||||
{
|
||||
return new ExifInterOperability(ExifTagFactory.GetTagID(mTag), 1, (uint)mValue.PixelData.Length, mValue.PixelData);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Unknown thumbnail type.");
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => mValue.Format.ToString();
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a JFIF thumbnail.
|
||||
/// </summary>
|
||||
internal class JFIFThumbnail
|
||||
{
|
||||
#region Public Enums
|
||||
|
||||
public enum ImageFormat
|
||||
{
|
||||
JPEG,
|
||||
BMPPalette,
|
||||
BMP24Bit,
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the 256 color RGB palette.
|
||||
/// </summary>
|
||||
public byte[] Palette { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets raw image data.
|
||||
/// </summary>
|
||||
public byte[] PixelData { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image format.
|
||||
/// </summary>
|
||||
public ImageFormat Format { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
protected JFIFThumbnail()
|
||||
{
|
||||
Palette = new byte[0];
|
||||
PixelData = new byte[0];
|
||||
}
|
||||
|
||||
public JFIFThumbnail(ImageFormat format, byte[] data)
|
||||
: this()
|
||||
{
|
||||
Format = format;
|
||||
PixelData = data;
|
||||
}
|
||||
|
||||
public JFIFThumbnail(byte[] palette, byte[] data)
|
||||
: this()
|
||||
{
|
||||
Format = ImageFormat.BMPPalette;
|
||||
Palette = palette;
|
||||
PixelData = data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -7,6 +7,7 @@ namespace Umbraco.Cms.Core.Media.Exif;
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Exception" />
|
||||
[Serializable]
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class NotValidJPEGFileException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,95 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a JPEG marker byte.
|
||||
/// </summary>
|
||||
internal enum JPEGMarker : byte
|
||||
{
|
||||
// Start Of Frame markers, non-differential, Huffman coding
|
||||
SOF0 = 0xc0,
|
||||
SOF1 = 0xc1,
|
||||
SOF2 = 0xc2,
|
||||
SOF3 = 0xc3,
|
||||
|
||||
// Start Of Frame markers, differential, Huffman coding
|
||||
SOF5 = 0xc5,
|
||||
SOF6 = 0xc6,
|
||||
SOF7 = 0xc7,
|
||||
|
||||
// Start Of Frame markers, non-differential, arithmetic coding
|
||||
JPG = 0xc8,
|
||||
SOF9 = 0xc9,
|
||||
SOF10 = 0xca,
|
||||
SOF11 = 0xcb,
|
||||
|
||||
// Start Of Frame markers, differential, arithmetic coding
|
||||
SOF13 = 0xcd,
|
||||
SOF14 = 0xce,
|
||||
SOF15 = 0xcf,
|
||||
|
||||
// Huffman table specification
|
||||
DHT = 0xc4,
|
||||
|
||||
// Arithmetic coding conditioning specification
|
||||
DAC = 0xcc,
|
||||
|
||||
// Restart interval termination
|
||||
RST0 = 0xd0,
|
||||
RST1 = 0xd1,
|
||||
RST2 = 0xd2,
|
||||
RST3 = 0xd3,
|
||||
RST4 = 0xd4,
|
||||
RST5 = 0xd5,
|
||||
RST6 = 0xd6,
|
||||
RST7 = 0xd7,
|
||||
|
||||
// Other markers
|
||||
SOI = 0xd8,
|
||||
EOI = 0xd9,
|
||||
SOS = 0xda,
|
||||
DQT = 0xdb,
|
||||
DNL = 0xdc,
|
||||
DRI = 0xdd,
|
||||
DHP = 0xde,
|
||||
EXP = 0xdf,
|
||||
|
||||
// application segments
|
||||
APP0 = 0xe0,
|
||||
APP1 = 0xe1,
|
||||
APP2 = 0xe2,
|
||||
APP3 = 0xe3,
|
||||
APP4 = 0xe4,
|
||||
APP5 = 0xe5,
|
||||
APP6 = 0xe6,
|
||||
APP7 = 0xe7,
|
||||
APP8 = 0xe8,
|
||||
APP9 = 0xe9,
|
||||
APP10 = 0xea,
|
||||
APP11 = 0xeb,
|
||||
APP12 = 0xec,
|
||||
APP13 = 0xed,
|
||||
APP14 = 0xee,
|
||||
APP15 = 0xef,
|
||||
|
||||
// JPEG extensions
|
||||
JPG0 = 0xf0,
|
||||
JPG1 = 0xf1,
|
||||
JPG2 = 0xf2,
|
||||
JPG3 = 0xf3,
|
||||
JPG4 = 0xf4,
|
||||
JPG5 = 0xf5,
|
||||
JPG6 = 0xf6,
|
||||
JPG7 = 0xf7,
|
||||
JPG8 = 0xf8,
|
||||
JPG9 = 0xf9,
|
||||
JPG10 = 0xfa,
|
||||
JPG11 = 0xfb,
|
||||
JP1G2 = 0xfc,
|
||||
JPG13 = 0xfd,
|
||||
|
||||
// Comment
|
||||
COM = 0xfe,
|
||||
|
||||
// Temporary
|
||||
TEM = 0x01,
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the memory view of a JPEG section.
|
||||
/// A JPEG section is the data between markers of the JPEG file.
|
||||
/// </summary>
|
||||
internal class JPEGSection
|
||||
{
|
||||
#region Instance Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string representation of the current section.
|
||||
/// </summary>
|
||||
/// <returns>A System.String that represents the current section.</returns>
|
||||
public override string ToString() => string.Format("{0} => Header: {1} bytes, Entropy Data: {2} bytes", Marker, Header.Length, EntropyData.Length);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// The marker byte representing the section.
|
||||
/// </summary>
|
||||
public JPEGMarker Marker { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Section header as a byte array. This is different from the header
|
||||
/// definition in JPEG specification in that it does not include the
|
||||
/// two byte section length.
|
||||
/// </summary>
|
||||
public byte[] Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For the SOS and RST markers, this contains the entropy coded data.
|
||||
/// </summary>
|
||||
public byte[] EntropyData { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a JPEGSection represented by the marker byte and containing
|
||||
/// the given data.
|
||||
/// </summary>
|
||||
/// <param name="marker">The marker byte representing the section.</param>
|
||||
/// <param name="data">Section data.</param>
|
||||
/// <param name="entropydata">Entropy coded data.</param>
|
||||
public JPEGSection(JPEGMarker marker, byte[] data, byte[] entropydata)
|
||||
{
|
||||
Marker = marker;
|
||||
Header = data;
|
||||
EntropyData = entropydata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a JPEGSection represented by the marker byte.
|
||||
/// </summary>
|
||||
/// <param name="marker">The marker byte representing the section.</param>
|
||||
public JPEGSection(JPEGMarker marker)
|
||||
: this(marker, new byte[0], new byte[0])
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,31 +0,0 @@
|
||||
using System.Globalization;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
internal class SvgFile : ImageFile
|
||||
{
|
||||
public SvgFile(Stream fileStream)
|
||||
{
|
||||
fileStream.Position = 0;
|
||||
|
||||
var document =
|
||||
XDocument.Load(fileStream); // if it throws an exception the ugly try catch in MediaFileSystem will catch it
|
||||
|
||||
var width = document.Root?.Attributes().Where(x => x.Name == "width").Select(x => x.Value).FirstOrDefault();
|
||||
var height = document.Root?.Attributes().Where(x => x.Name == "height").Select(x => x.Value).FirstOrDefault();
|
||||
|
||||
Properties.Add(new ExifSInt(
|
||||
ExifTag.PixelYDimension,
|
||||
height == null ? Constants.Conventions.Media.DefaultSize : int.Parse(height, CultureInfo.InvariantCulture)));
|
||||
Properties.Add(new ExifSInt(
|
||||
ExifTag.PixelXDimension,
|
||||
width == null ? Constants.Conventions.Media.DefaultSize : int.Parse(width, CultureInfo.InvariantCulture)));
|
||||
|
||||
Format = ImageFileFormat.SVG;
|
||||
}
|
||||
|
||||
public override void Save(Stream stream)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the binary view of a TIFF file.
|
||||
/// </summary>
|
||||
internal class TIFFFile : ImageFile
|
||||
{
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JPEGFile" /> class from the
|
||||
/// specified data stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">A <see cref="Sytem.IO.Stream" /> that contains image data.</param>
|
||||
/// <param name="encoding">The encoding to be used for text metadata when the source encoding is unknown.</param>
|
||||
protected internal TIFFFile(Stream stream, Encoding encoding)
|
||||
{
|
||||
Format = ImageFileFormat.TIFF;
|
||||
IFDs = new List<ImageFileDirectory>();
|
||||
Encoding = encoding;
|
||||
|
||||
// Read the entire stream
|
||||
var data = Utility.GetStreamBytes(stream);
|
||||
|
||||
// Read the TIFF header
|
||||
TIFFHeader = TIFFHeader.FromBytes(data, 0);
|
||||
var nextIFDOffset = TIFFHeader.IFDOffset;
|
||||
if (nextIFDOffset == 0)
|
||||
{
|
||||
throw new NotValidTIFFileException("The first IFD offset is zero.");
|
||||
}
|
||||
|
||||
// Read IFDs in order
|
||||
while (nextIFDOffset != 0)
|
||||
{
|
||||
var ifd = ImageFileDirectory.FromBytes(data, nextIFDOffset, TIFFHeader.ByteOrder);
|
||||
nextIFDOffset = ifd.NextIFDOffset;
|
||||
IFDs.Add(ifd);
|
||||
}
|
||||
|
||||
// Process IFDs
|
||||
// TODO: Add support for multiple frames
|
||||
foreach (ImageFileDirectoryEntry field in IFDs[0].Fields)
|
||||
{
|
||||
Properties.Add(ExifPropertyFactory.Get(field.Tag, field.Type, field.Count, field.Data, BitConverterEx.SystemByteOrder, IFD.Zeroth, Encoding));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the TIFF header.
|
||||
/// </summary>
|
||||
public TIFFHeader TIFFHeader { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <summary>
|
||||
/// Saves the <see cref="ImageFile" /> to the given stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The data stream used to save the image.</param>
|
||||
public override void Save(Stream stream)
|
||||
{
|
||||
BitConverterEx conv = BitConverterEx.SystemEndian;
|
||||
|
||||
// Write TIFF header
|
||||
uint ifdoffset = 8;
|
||||
|
||||
// Byte order
|
||||
stream.Write(
|
||||
BitConverterEx.SystemByteOrder == BitConverterEx.ByteOrder.LittleEndian
|
||||
? new byte[] { 0x49, 0x49 }
|
||||
: new byte[] { 0x4D, 0x4D },
|
||||
0,
|
||||
2);
|
||||
|
||||
// TIFF ID
|
||||
stream.Write(conv.GetBytes((ushort)42), 0, 2);
|
||||
|
||||
// Offset to 0th IFD, will be corrected below
|
||||
stream.Write(conv.GetBytes(ifdoffset), 0, 4);
|
||||
|
||||
// Write IFD sections
|
||||
for (var i = 0; i < IFDs.Count; i++)
|
||||
{
|
||||
ImageFileDirectory ifd = IFDs[i];
|
||||
|
||||
// Save the location of IFD offset
|
||||
var ifdLocation = stream.Position - 4;
|
||||
|
||||
// Write strips first
|
||||
var stripOffsets = new byte[4 * ifd.Strips.Count];
|
||||
var stripLengths = new byte[4 * ifd.Strips.Count];
|
||||
var stripOffset = ifdoffset;
|
||||
for (var j = 0; j < ifd.Strips.Count; j++)
|
||||
{
|
||||
var stripData = ifd.Strips[j].Data;
|
||||
var oBytes = BitConverter.GetBytes(stripOffset);
|
||||
var lBytes = BitConverter.GetBytes((uint)stripData.Length);
|
||||
Array.Copy(oBytes, 0, stripOffsets, 4 * j, 4);
|
||||
Array.Copy(lBytes, 0, stripLengths, 4 * j, 4);
|
||||
stream.Write(stripData, 0, stripData.Length);
|
||||
stripOffset += (uint)stripData.Length;
|
||||
}
|
||||
|
||||
// Remove old strip tags
|
||||
for (var j = ifd.Fields.Count - 1; j > 0; j--)
|
||||
{
|
||||
var tag = ifd.Fields[j].Tag;
|
||||
if (tag == 273 || tag == 279)
|
||||
{
|
||||
ifd.Fields.RemoveAt(j);
|
||||
}
|
||||
}
|
||||
|
||||
// Write new strip tags
|
||||
ifd.Fields.Add(new ImageFileDirectoryEntry(273, 4, (uint)ifd.Strips.Count, stripOffsets));
|
||||
ifd.Fields.Add(new ImageFileDirectoryEntry(279, 4, (uint)ifd.Strips.Count, stripLengths));
|
||||
|
||||
// Write fields after strips
|
||||
ifdoffset = stripOffset;
|
||||
|
||||
// Correct IFD offset
|
||||
var currentLocation = stream.Position;
|
||||
stream.Seek(ifdLocation, SeekOrigin.Begin);
|
||||
stream.Write(conv.GetBytes(ifdoffset), 0, 4);
|
||||
stream.Seek(currentLocation, SeekOrigin.Begin);
|
||||
|
||||
// Offset to field data
|
||||
var dataOffset = ifdoffset + 2 + ((uint)ifd.Fields.Count * 12) + 4;
|
||||
|
||||
// Field count
|
||||
stream.Write(conv.GetBytes((ushort)ifd.Fields.Count), 0, 2);
|
||||
|
||||
// Fields
|
||||
foreach (ImageFileDirectoryEntry field in ifd.Fields)
|
||||
{
|
||||
// Tag
|
||||
stream.Write(conv.GetBytes(field.Tag), 0, 2);
|
||||
|
||||
// Type
|
||||
stream.Write(conv.GetBytes(field.Type), 0, 2);
|
||||
|
||||
// Count
|
||||
stream.Write(conv.GetBytes(field.Count), 0, 4);
|
||||
|
||||
// Field data
|
||||
var data = field.Data;
|
||||
if (data.Length <= 4)
|
||||
{
|
||||
stream.Write(data, 0, data.Length);
|
||||
for (var j = data.Length; j < 4; j++)
|
||||
{
|
||||
stream.WriteByte(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.Write(conv.GetBytes(dataOffset), 0, 4);
|
||||
var currentOffset = stream.Position;
|
||||
stream.Seek(dataOffset, SeekOrigin.Begin);
|
||||
stream.Write(data, 0, data.Length);
|
||||
dataOffset += (uint)data.Length;
|
||||
stream.Seek(currentOffset, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
// Offset to next IFD
|
||||
ifdoffset = dataOffset;
|
||||
stream.Write(conv.GetBytes(i == IFDs.Count - 1 ? 0 : ifdoffset), 0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image file directories.
|
||||
/// </summary>
|
||||
public List<ImageFileDirectory> IFDs { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a TIFF Header.
|
||||
/// </summary>
|
||||
internal struct TIFFHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// The byte order of the image file.
|
||||
/// </summary>
|
||||
public BitConverterEx.ByteOrder ByteOrder;
|
||||
|
||||
/// <summary>
|
||||
/// TIFF ID. This value should always be 42.
|
||||
/// </summary>
|
||||
public byte ID;
|
||||
|
||||
/// <summary>
|
||||
/// The offset to the first IFD section from the
|
||||
/// start of the TIFF header.
|
||||
/// </summary>
|
||||
public uint IFDOffset;
|
||||
|
||||
/// <summary>
|
||||
/// The byte order of the TIFF header itself.
|
||||
/// </summary>
|
||||
public BitConverterEx.ByteOrder TIFFHeaderByteOrder;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TIFFHeader" /> struct.
|
||||
/// </summary>
|
||||
/// <param name="byteOrder">The byte order.</param>
|
||||
/// <param name="id">The TIFF ID. This value should always be 42.</param>
|
||||
/// <param name="ifdOffset">
|
||||
/// The offset to the first IFD section from the
|
||||
/// start of the TIFF header.
|
||||
/// </param>
|
||||
/// <param name="headerByteOrder">The byte order of the TIFF header itself.</param>
|
||||
public TIFFHeader(BitConverterEx.ByteOrder byteOrder, byte id, uint ifdOffset, BitConverterEx.ByteOrder headerByteOrder)
|
||||
{
|
||||
if (id != 42)
|
||||
{
|
||||
throw new NotValidTIFFHeader();
|
||||
}
|
||||
|
||||
ByteOrder = byteOrder;
|
||||
ID = id;
|
||||
IFDOffset = ifdOffset;
|
||||
TIFFHeaderByteOrder = headerByteOrder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="TIFFHeader" /> initialized from the given byte data.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <param name="offset">The offset into <paramref name="data" />.</param>
|
||||
/// <returns>A <see cref="TIFFHeader" /> initialized from the given byte data.</returns>
|
||||
public static TIFFHeader FromBytes(byte[] data, int offset)
|
||||
{
|
||||
var header = default(TIFFHeader);
|
||||
|
||||
// TIFF header
|
||||
if (data[offset] == 0x49 && data[offset + 1] == 0x49)
|
||||
{
|
||||
header.ByteOrder = BitConverterEx.ByteOrder.LittleEndian;
|
||||
}
|
||||
else if (data[offset] == 0x4D && data[offset + 1] == 0x4D)
|
||||
{
|
||||
header.ByteOrder = BitConverterEx.ByteOrder.BigEndian;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotValidTIFFHeader();
|
||||
}
|
||||
|
||||
// TIFF header may have a different byte order
|
||||
if (BitConverterEx.LittleEndian.ToUInt16(data, offset + 2) == 42)
|
||||
{
|
||||
header.TIFFHeaderByteOrder = BitConverterEx.ByteOrder.LittleEndian;
|
||||
}
|
||||
else if (BitConverterEx.BigEndian.ToUInt16(data, offset + 2) == 42)
|
||||
{
|
||||
header.TIFFHeaderByteOrder = BitConverterEx.ByteOrder.BigEndian;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotValidTIFFHeader();
|
||||
}
|
||||
|
||||
header.ID = 42;
|
||||
|
||||
// IFD offset
|
||||
header.IFDOffset =
|
||||
BitConverterEx.ToUInt32(data, offset + 4, header.TIFFHeaderByteOrder, BitConverterEx.SystemByteOrder);
|
||||
|
||||
return header;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a strip of compressed image data in a TIFF file.
|
||||
/// </summary>
|
||||
internal class TIFFStrip
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TIFFStrip" /> class.
|
||||
/// </summary>
|
||||
/// <param name="data">The byte array to copy strip from.</param>
|
||||
/// <param name="offset">The offset to the beginning of strip.</param>
|
||||
/// <param name="length">The length of strip.</param>
|
||||
public TIFFStrip(byte[] data, uint offset, uint length)
|
||||
{
|
||||
Data = new byte[length];
|
||||
Array.Copy(data, offset, Data, 0, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compressed image data contained in this strip.
|
||||
/// </summary>
|
||||
public byte[] Data { get; }
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
namespace Umbraco.Cms.Core.Media.Exif;
|
||||
|
||||
/// <summary>
|
||||
/// Contains utility functions.
|
||||
/// </summary>
|
||||
internal class Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads the entire stream and returns its contents as a byte array.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="System.IO.Stream" /> to read.</param>
|
||||
/// <returns>Contents of the <paramref name="stream" /> as a byte array.</returns>
|
||||
public static byte[] GetStreamBytes(Stream stream)
|
||||
{
|
||||
using (var mem = new MemoryStream())
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var b = new byte[32768];
|
||||
int r;
|
||||
while ((r = stream.Read(b, 0, b.Length)) > 0)
|
||||
{
|
||||
mem.Write(b, 0, r);
|
||||
}
|
||||
|
||||
return mem.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<Suppression>
|
||||
<DiagnosticId>PKV006</DiagnosticId>
|
||||
<Target>net6.0</Target>
|
||||
</Suppression>
|
||||
</Suppressions>
|
||||
@@ -1,7 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<Suppression>
|
||||
<DiagnosticId>PKV006</DiagnosticId>
|
||||
<Target>net6.0</Target>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Umbraco.Cms.Core.Deploy.IGridCellValueConnector.GetValue(Umbraco.Cms.Core.Models.GridValue.GridControl,System.Collections.Generic.ICollection{Umbraco.Cms.Core.Deploy.ArtifactDependency},Umbraco.Cms.Core.Deploy.IContextCache)</Target>
|
||||
<Left>lib/net7.0/Umbraco.Infrastructure.dll</Left>
|
||||
<Right>lib/net7.0/Umbraco.Infrastructure.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Umbraco.Cms.Core.Deploy.IGridCellValueConnector.SetValue(Umbraco.Cms.Core.Models.GridValue.GridControl,Umbraco.Cms.Core.Deploy.IContextCache)</Target>
|
||||
<Left>lib/net7.0/Umbraco.Infrastructure.dll</Left>
|
||||
<Right>lib/net7.0/Umbraco.Infrastructure.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
</Suppressions>
|
||||
@@ -296,18 +296,7 @@ public static partial class UmbracoBuilderExtensions
|
||||
|
||||
private static IUmbracoBuilder AddPreValueMigrators(this IUmbracoBuilder builder)
|
||||
{
|
||||
builder.WithCollectionBuilder<PreValueMigratorCollectionBuilder>()
|
||||
.Append<RenamingPreValueMigrator>()
|
||||
.Append<RichTextPreValueMigrator>()
|
||||
.Append<UmbracoSliderPreValueMigrator>()
|
||||
.Append<MediaPickerPreValueMigrator>()
|
||||
.Append<ContentPickerPreValueMigrator>()
|
||||
.Append<NestedContentPreValueMigrator>()
|
||||
.Append<DecimalPreValueMigrator>()
|
||||
.Append<ListViewPreValueMigrator>()
|
||||
.Append<DropDownFlexiblePreValueMigrator>()
|
||||
.Append<ValueListPreValueMigrator>()
|
||||
.Append<MarkdownEditorPreValueMigrator>();
|
||||
builder.WithCollectionBuilder<PreValueMigratorCollectionBuilder>();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -1,25 +1,7 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Core.Semver;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.Common;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_10_0_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_10_2_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_1;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_1_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_10_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_15_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_17_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_6_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_7_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_9_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_1_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_2_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_3_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_4_0;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade;
|
||||
|
||||
@@ -29,10 +11,6 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade;
|
||||
/// <seealso cref="MigrationPlan" />
|
||||
public class UmbracoPlan : MigrationPlan
|
||||
{
|
||||
private const string InitPrefix = "{init-";
|
||||
private const string InitSuffix = "}";
|
||||
private readonly IUmbracoVersion _umbracoVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoPlan" /> class.
|
||||
/// </summary>
|
||||
@@ -40,7 +18,6 @@ public class UmbracoPlan : MigrationPlan
|
||||
public UmbracoPlan(IUmbracoVersion umbracoVersion)
|
||||
: base(Constants.Conventions.Migrations.UmbracoUpgradePlanName)
|
||||
{
|
||||
_umbracoVersion = umbracoVersion;
|
||||
DefinePlan();
|
||||
}
|
||||
|
||||
@@ -57,74 +34,9 @@ public class UmbracoPlan : MigrationPlan
|
||||
/// upgrades (from a tool old version, or going back in time, etc).
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public override string InitialState
|
||||
{
|
||||
get
|
||||
{
|
||||
SemVersion currentVersion = _umbracoVersion.SemanticVersion;
|
||||
public override string InitialState => "{DED98755-4059-41BB-ADBD-3FEAB12D1D7B}";
|
||||
|
||||
// only from 8.0.0 and above
|
||||
var minVersion = new SemVersion(8);
|
||||
if (currentVersion < minVersion)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Version {currentVersion} cannot be migrated to {_umbracoVersion.SemanticVersion}."
|
||||
+ $" Please upgrade first to at least {minVersion}.");
|
||||
}
|
||||
|
||||
// Force versions between 7.14.*-7.15.* into into 7.14 initial state. Because there is no db-changes,
|
||||
// and we don't want users to workaround my putting in version 7.14.0 them self.
|
||||
if (minVersion <= currentVersion && currentVersion < new SemVersion(7, 16))
|
||||
{
|
||||
return GetInitState(minVersion);
|
||||
}
|
||||
|
||||
// initial state is eg "{init-7.14.0}"
|
||||
return GetInitState(currentVersion);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void ThrowOnUnknownInitialState(string state)
|
||||
{
|
||||
if (TryGetInitStateVersion(state, out var initVersion))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Version {_umbracoVersion.SemanticVersion} does not support migrating from {initVersion}."
|
||||
+ $" Please verify which versions support migrating from {initVersion}.");
|
||||
}
|
||||
|
||||
base.ThrowOnUnknownInitialState(state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the initial state corresponding to a version.
|
||||
/// </summary>
|
||||
/// <param name="version">The version.</param>
|
||||
/// <returns>
|
||||
/// The initial state.
|
||||
/// </returns>
|
||||
private static string GetInitState(SemVersion version) => InitPrefix + version + InitSuffix;
|
||||
|
||||
/// <summary>
|
||||
/// Tries to extract a version from an initial state.
|
||||
/// </summary>
|
||||
/// <param name="state">The state.</param>
|
||||
/// <param name="version">The version.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> when the state contains a version; otherwise, <c>false</c>.D
|
||||
/// </returns>
|
||||
private static bool TryGetInitStateVersion(string state, [MaybeNullWhen(false)] out string version)
|
||||
{
|
||||
if (state.StartsWith(InitPrefix) && state.EndsWith(InitSuffix))
|
||||
{
|
||||
version = state.TrimStart(InitPrefix).TrimEnd(InitSuffix);
|
||||
return true;
|
||||
}
|
||||
|
||||
version = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the plan.
|
||||
@@ -138,154 +50,23 @@ public class UmbracoPlan : MigrationPlan
|
||||
// * Creating a migration for version 8:
|
||||
// Append the migration to the main chain, using a new guid, before the "//FINAL" comment
|
||||
//
|
||||
//
|
||||
// If the new migration causes a merge conflict, because someone else also added another
|
||||
// new migration, you NEED to fix the conflict by providing one default path, and paths
|
||||
// out of the conflict states (see examples below).
|
||||
// out of the conflict states, eg:
|
||||
//
|
||||
// * Porting from version 7:
|
||||
// Append the ported migration to the main chain, using a new guid (same as above).
|
||||
// Create a new special chain from the {init-...} state to the main chain.
|
||||
// .From("state-1")
|
||||
// .To<ChangeA>("state-a")
|
||||
// .To<ChangeB>("state-b") // Some might already be in this state, without having applied ChangeA
|
||||
//
|
||||
// .From("state-1")
|
||||
// .Merge()
|
||||
// .To<ChangeA>("state-a")
|
||||
// .With()
|
||||
// .To<ChangeB>("state-b")
|
||||
// .As("state-2");
|
||||
|
||||
// plan starts at 7.14.0 (anything before 7.14.0 is not supported)
|
||||
From(GetInitState(new SemVersion(7, 14)));
|
||||
|
||||
// begin migrating from v7 - remove all keys and indexes
|
||||
To<DeleteKeysAndIndexes>("{B36B9ABD-374E-465B-9C5F-26AB0D39326F}");
|
||||
|
||||
To<AddLockObjects>("{7C447271-CA3F-4A6A-A913-5D77015655CB}");
|
||||
To<AddContentNuTable>("{CBFF58A2-7B50-4F75-8E98-249920DB0F37}");
|
||||
To<RenameMediaVersionTable>("{5CB66059-45F4-48BA-BCBD-C5035D79206B}");
|
||||
To<VariantsMigration>("{FB0A5429-587E-4BD0-8A67-20F0E7E62FF7}");
|
||||
To<DropMigrationsTable>("{F0C42457-6A3B-4912-A7EA-F27ED85A2092}");
|
||||
To<DataTypeMigration>("{8640C9E4-A1C0-4C59-99BB-609B4E604981}");
|
||||
To<TagsMigration>("{DD1B99AF-8106-4E00-BAC7-A43003EA07F8}");
|
||||
To<SuperZero>("{9DF05B77-11D1-475C-A00A-B656AF7E0908}");
|
||||
To<PropertyEditorsMigration>("{6FE3EF34-44A0-4992-B379-B40BC4EF1C4D}");
|
||||
To<LanguageColumns>("{7F59355A-0EC9-4438-8157-EB517E6D2727}");
|
||||
ToWithReplace<AddVariationTables2, AddVariationTables1A>(
|
||||
"{941B2ABA-2D06-4E04-81F5-74224F1DB037}",
|
||||
"{76DF5CD7-A884-41A5-8DC6-7860D95B1DF5}"); // kill AddVariationTable1
|
||||
To<RefactorMacroColumns>("{A7540C58-171D-462A-91C5-7A9AA5CB8BFD}");
|
||||
|
||||
Merge()
|
||||
.To<UserForeignKeys>("{3E44F712-E2E3-473A-AE49-5D7F8E67CE3F}")
|
||||
.With()
|
||||
.To<AddTypedLabels>("{65D6B71C-BDD5-4A2E-8D35-8896325E9151}")
|
||||
.As("{4CACE351-C6B9-4F0C-A6BA-85A02BBD39E4}");
|
||||
|
||||
To<ContentVariationMigration>("{1350617A-4930-4D61-852F-E3AA9E692173}");
|
||||
To<FallbackLanguage>("{CF51B39B-9B9A-4740-BB7C-EAF606A7BFBF}");
|
||||
To<UpdateDefaultMandatoryLanguage>("{5F4597F4-A4E0-4AFE-90B5-6D2F896830EB}");
|
||||
To<RefactorVariantsModel>("{290C18EE-B3DE-4769-84F1-1F467F3F76DA}");
|
||||
To<DropTaskTables>("{6A2C7C1B-A9DB-4EA9-B6AB-78E7D5B722A7}");
|
||||
To<AddLogTableColumns>("{8804D8E8-FE62-4E3A-B8A2-C047C2118C38}");
|
||||
To<DropPreValueTable>("{23275462-446E-44C7-8C2C-3B8C1127B07D}");
|
||||
To<DropDownPropertyEditorsMigration>("{6B251841-3069-4AD5-8AE9-861F9523E8DA}");
|
||||
To<TagsMigrationFix>("{EE429F1B-9B26-43CA-89F8-A86017C809A3}");
|
||||
To<DropTemplateDesignColumn>("{08919C4B-B431-449C-90EC-2B8445B5C6B1}");
|
||||
To<TablesForScheduledPublishing>("{7EB0254C-CB8B-4C75-B15B-D48C55B449EB}");
|
||||
To<MakeTagsVariant>("{C39BF2A7-1454-4047-BBFE-89E40F66ED63}");
|
||||
To<MakeRedirectUrlVariant>("{64EBCE53-E1F0-463A-B40B-E98EFCCA8AE2}");
|
||||
To<AddContentTypeIsElementColumn>("{0009109C-A0B8-4F3F-8FEB-C137BBDDA268}");
|
||||
To<ConvertRelatedLinksToMultiUrlPicker>("{ED28B66A-E248-4D94-8CDB-9BDF574023F0}");
|
||||
To<UpdatePickerIntegerValuesToUdi>("{38C809D5-6C34-426B-9BEA-EFD39162595C}");
|
||||
To<RenameUmbracoDomainsTable>("{6017F044-8E70-4E10-B2A3-336949692ADD}");
|
||||
|
||||
Merge()
|
||||
.To<DropXmlTables>("{CDBEDEE4-9496-4903-9CF2-4104E00FF960}")
|
||||
.With()
|
||||
.To<RadioAndCheckboxPropertyEditorsMigration>("{940FD19A-00A8-4D5C-B8FF-939143585726}")
|
||||
.As("{0576E786-5C30-4000-B969-302B61E90CA3}");
|
||||
|
||||
To<FixLanguageIsoCodeLength>("{48AD6CCD-C7A4-4305-A8AB-38728AD23FC5}");
|
||||
To<AddPackagesSectionAccess>("{DF470D86-E5CA-42AC-9780-9D28070E25F9}");
|
||||
|
||||
// finish migrating from v7 - recreate all keys and indexes
|
||||
To<CreateKeysAndIndexes>("{3F9764F5-73D0-4D45-8804-1240A66E43A2}");
|
||||
|
||||
To<RenameLabelAndRichTextPropertyEditorAliases>("{E0CBE54D-A84F-4A8F-9B13-900945FD7ED9}");
|
||||
To<MergeDateAndDateTimePropertyEditor>("{78BAF571-90D0-4D28-8175-EF96316DA789}");
|
||||
|
||||
// release-8.0.0
|
||||
|
||||
// to 8.0.1
|
||||
To<ChangeNuCacheJsonFormat>("{80C0A0CB-0DD5-4573-B000-C4B7C313C70D}");
|
||||
|
||||
// release-8.0.1
|
||||
|
||||
// to 8.1.0
|
||||
To<ConvertTinyMceAndGridMediaUrlsToLocalLink>("{B69B6E8C-A769-4044-A27E-4A4E18D1645A}");
|
||||
To<RenameUserLoginDtoDateIndex>("{0372A42B-DECF-498D-B4D1-6379E907EB94}");
|
||||
To<FixContentNuCascade>("{5B1E0D93-F5A3-449B-84BA-65366B84E2D4}");
|
||||
|
||||
// to 8.6.0
|
||||
To<UpdateRelationTypeTable>("{4759A294-9860-46BC-99F9-B4C975CAE580}");
|
||||
To<AddNewRelationTypes>("{0BC866BC-0665-487A-9913-0290BD0169AD}");
|
||||
To<AddPropertyTypeValidationMessageColumns>("{3D67D2C8-5E65-47D0-A9E1-DC2EE0779D6B}");
|
||||
To<MissingContentVersionsIndexes>("{EE288A91-531B-4995-8179-1D62D9AA3E2E}");
|
||||
To<AddMainDomLock>("{2AB29964-02A1-474D-BD6B-72148D2A53A2}");
|
||||
|
||||
// to 8.7.0
|
||||
To<MissingDictionaryIndex>("{a78e3369-8ea3-40ec-ad3f-5f76929d2b20}");
|
||||
|
||||
// to 8.9.0
|
||||
To<ExternalLoginTableUserData>("{B5838FF5-1D22-4F6C-BCEB-F83ACB14B575}");
|
||||
|
||||
// to 8.10.0
|
||||
To<AddPropertyTypeLabelOnTopColumn>("{D6A8D863-38EC-44FB-91EC-ACD6A668BD18}");
|
||||
|
||||
// NOTE: we need to do a merge migration here because as of 'now',
|
||||
// v9-beta* is already out and 8.15 isn't out yet
|
||||
// so we need to ensure that migrations from 8.15 are included in the next
|
||||
// v9*.
|
||||
|
||||
// to 8.15.0
|
||||
To<AddCmsContentNuByteColumn>("{8DDDCD0B-D7D5-4C97-BD6A-6B38CA65752F}");
|
||||
To<UpgradedIncludeIndexes>("{4695D0C9-0729-4976-985B-048D503665D8}");
|
||||
To<UpdateCmsPropertyGroupIdSeed>("{5C424554-A32D-4852-8ED1-A13508187901}");
|
||||
|
||||
// to 8.17.0
|
||||
To<AddPropertyTypeGroupColumns>("{153865E9-7332-4C2A-9F9D-F20AEE078EC7}");
|
||||
|
||||
// Hack to support migration from 8.18
|
||||
To<NoopMigration>("{03482BB0-CF13-475C-845E-ECB8319DBE3C}");
|
||||
|
||||
// This should be safe to execute again. We need it with a new name to ensure updates from all the following has executed this step.
|
||||
// - 8.15.0 RC - Current state: {4695D0C9-0729-4976-985B-048D503665D8}
|
||||
// - 8.15.0 Final - Current state: {5C424554-A32D-4852-8ED1-A13508187901}
|
||||
// - 9.0.0 RC1 - Current state: {5060F3D2-88BE-4D30-8755-CF51F28EAD12}
|
||||
To<UpdateCmsPropertyGroupIdSeed>("{622E5172-42E1-4662-AD80-9504AF5A4E53}");
|
||||
To<ExternalLoginTableIndexesFixup>("{10F7BB61-C550-426B-830B-7F954F689CDF}");
|
||||
To<DictionaryTablesIndexes>("{5AAE6276-80DB-4ACF-B845-199BC6C37538}");
|
||||
|
||||
// to 9.0.0 RC1
|
||||
To<MigrateLogViewerQueriesFromFileToDb>("{22D801BA-A1FF-4539-BFCC-2139B55594F8}");
|
||||
To<ExternalLoginTableIndexes>("{50A43237-A6F4-49E2-A7A6-5DAD65C84669}");
|
||||
To<ExternalLoginTokenTable>("{3D8DADEF-0FDA-4377-A5F0-B52C2110E8F2}");
|
||||
To<MemberTableColumns>("{1303BDCF-2295-4645-9526-2F32E8B35ABD}");
|
||||
To<AddPasswordConfigToMemberTable>("{5060F3D2-88BE-4D30-8755-CF51F28EAD12}");
|
||||
To<AddPropertyTypeGroupColumns>(
|
||||
"{A2686B49-A082-4B22-97FD-AAB154D46A57}"); // Re-run this migration to make sure it has executed to account for migrations going out of sync between versions.
|
||||
|
||||
// TO 9.0.0-rc4
|
||||
To<UmbracoServerColumn>(
|
||||
"5E02F241-5253-403D-B5D3-7DB00157E20F"); // Jaddie: This GUID is missing the { }, although this likely can't be changed now as it will break installs going forwards
|
||||
|
||||
// TO 9.1.0
|
||||
To<AddContentVersionCleanupFeature>("{8BAF5E6C-DCB7-41AE-824F-4215AE4F1F98}");
|
||||
|
||||
// TO 9.2.0
|
||||
To<AddUserGroup2NodeTable>("{0571C395-8F0B-44E9-8E3F-47BDD08D817B}");
|
||||
To<AddDefaultForNotificationsToggle>("{AD3D3B7F-8E74-45A4-85DB-7FFAD57F9243}");
|
||||
|
||||
// TO 9.3.0
|
||||
To<MovePackageXMLToDb>("{A2F22F17-5870-4179-8A8D-2362AA4A0A5F}");
|
||||
To<UpdateExternalLoginToUseKeyInsteadOfId>("{CA7A1D9D-C9D4-4914-BC0A-459E7B9C3C8C}");
|
||||
To<AddTwoFactorLoginTable>("{0828F206-DCF7-4F73-ABBB-6792275532EB}");
|
||||
|
||||
// TO 9.4.0
|
||||
To<AddScheduledPublishingLock>("{DBBA1EA0-25A1-4863-90FB-5D306FB6F1E1}");
|
||||
To<UpdateRelationTypesToHandleDependencies>("{DED98755-4059-41BB-ADBD-3FEAB12D1D7B}");
|
||||
From(InitialState);
|
||||
|
||||
// TO 10.0.0
|
||||
To<AddMemberPropertiesAsColumns>("{B7E0D53C-2B0E-418B-AB07-2DDE486E225F}");
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
internal class AddContentNuTable : MigrationBase
|
||||
{
|
||||
public AddContentNuTable(IMigrationContext context)
|
||||
: base(context)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Migrate()
|
||||
{
|
||||
IEnumerable<string> tables = SqlSyntax.GetTablesInSchema(Context.Database);
|
||||
if (tables.InvariantContains("cmsContentNu"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Create.Table<ContentNuDto>(true).Do();
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class AddContentTypeIsElementColumn : MigrationBase
|
||||
{
|
||||
public AddContentTypeIsElementColumn(IMigrationContext context)
|
||||
|
||||
@@ -4,6 +4,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class AddLockObjects : MigrationBase
|
||||
{
|
||||
public AddLockObjects(IMigrationContext context)
|
||||
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class AddLogTableColumns : MigrationBase
|
||||
{
|
||||
public AddLogTableColumns(IMigrationContext context)
|
||||
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Core;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class AddPackagesSectionAccess : MigrationBase
|
||||
{
|
||||
public AddPackagesSectionAccess(IMigrationContext context)
|
||||
|
||||
@@ -6,6 +6,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class AddTypedLabels : MigrationBase
|
||||
{
|
||||
public AddTypedLabels(IMigrationContext context)
|
||||
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class AddVariationTables1A : MigrationBase
|
||||
{
|
||||
public AddVariationTables1A(IMigrationContext context)
|
||||
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class AddVariationTables2 : MigrationBase
|
||||
{
|
||||
public AddVariationTables2(IMigrationContext context)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.Models;
|
||||
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class ContentVariationMigration : MigrationBase
|
||||
{
|
||||
public ContentVariationMigration(IMigrationContext context)
|
||||
@@ -12,50 +13,7 @@ public class ContentVariationMigration : MigrationBase
|
||||
|
||||
protected override void Migrate()
|
||||
{
|
||||
static byte GetNewValue(byte oldValue)
|
||||
{
|
||||
switch (oldValue)
|
||||
{
|
||||
case 0: // Unknown
|
||||
case 1: // InvariantNeutral
|
||||
return 0; // Unknown
|
||||
case 2: // CultureNeutral
|
||||
case 3: // CultureNeutral | InvariantNeutral
|
||||
return 1; // Culture
|
||||
case 4: // InvariantSegment
|
||||
case 5: // InvariantSegment | InvariantNeutral
|
||||
return 2; // Segment
|
||||
case 6: // InvariantSegment | CultureNeutral
|
||||
case 7: // InvariantSegment | CultureNeutral | InvariantNeutral
|
||||
case 8: // CultureSegment
|
||||
case 9: // CultureSegment | InvariantNeutral
|
||||
case 10: // CultureSegment | CultureNeutral
|
||||
case 11: // CultureSegment | CultureNeutral | InvariantNeutral
|
||||
case 12: // etc
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
return 3; // Culture | Segment
|
||||
default:
|
||||
throw new NotSupportedException($"Invalid value {oldValue}.");
|
||||
}
|
||||
}
|
||||
|
||||
List<PropertyTypeDto80>? propertyTypes =
|
||||
Database.Fetch<PropertyTypeDto80>(Sql().Select<PropertyTypeDto80>().From<PropertyTypeDto80>());
|
||||
foreach (PropertyTypeDto80? dto in propertyTypes)
|
||||
{
|
||||
dto.Variations = GetNewValue(dto.Variations);
|
||||
Database.Update(dto);
|
||||
}
|
||||
|
||||
List<ContentTypeDto80>? contentTypes =
|
||||
Database.Fetch<ContentTypeDto80>(Sql().Select<ContentTypeDto80>().From<ContentTypeDto80>());
|
||||
foreach (ContentTypeDto80? dto in contentTypes)
|
||||
{
|
||||
dto.Variations = GetNewValue(dto.Variations);
|
||||
Database.Update(dto);
|
||||
}
|
||||
}
|
||||
|
||||
// we *need* to use these private DTOs here, which does *not* have extra properties, which would kill the migration
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
using System.Globalization;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
using NPoco;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.Models;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class ConvertRelatedLinksToMultiUrlPicker : MigrationBase
|
||||
{
|
||||
public ConvertRelatedLinksToMultiUrlPicker(IMigrationContext context)
|
||||
@@ -19,144 +10,7 @@ public class ConvertRelatedLinksToMultiUrlPicker : MigrationBase
|
||||
|
||||
protected override void Migrate()
|
||||
{
|
||||
Sql<ISqlContext> sqlDataTypes = Sql()
|
||||
.Select<DataTypeDto>()
|
||||
.From<DataTypeDto>()
|
||||
.Where<DataTypeDto>(x => x.EditorAlias == Constants.PropertyEditors.Legacy.Aliases.RelatedLinks
|
||||
|| x.EditorAlias == Constants.PropertyEditors.Legacy.Aliases.RelatedLinks2);
|
||||
|
||||
List<DataTypeDto>? dataTypes = Database.Fetch<DataTypeDto>(sqlDataTypes);
|
||||
var dataTypeIds = dataTypes.Select(x => x.NodeId).ToList();
|
||||
|
||||
if (dataTypeIds.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (DataTypeDto? dataType in dataTypes)
|
||||
{
|
||||
dataType.EditorAlias = Constants.PropertyEditors.Aliases.MultiUrlPicker;
|
||||
Database.Update(dataType);
|
||||
}
|
||||
|
||||
Sql<ISqlContext> sqlPropertyTpes = Sql()
|
||||
.Select<PropertyTypeDto80>()
|
||||
.From<PropertyTypeDto80>()
|
||||
.Where<PropertyTypeDto80>(x => dataTypeIds.Contains(x.DataTypeId));
|
||||
|
||||
var propertyTypeIds = Database.Fetch<PropertyTypeDto80>(sqlPropertyTpes).Select(x => x.Id).ToList();
|
||||
|
||||
if (propertyTypeIds.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Sql<ISqlContext> sqlPropertyData = Sql()
|
||||
.Select<PropertyDataDto>()
|
||||
.From<PropertyDataDto>()
|
||||
.Where<PropertyDataDto>(x => propertyTypeIds.Contains(x.PropertyTypeId));
|
||||
|
||||
List<PropertyDataDto>? properties = Database.Fetch<PropertyDataDto>(sqlPropertyData);
|
||||
|
||||
// Create a Multi URL Picker datatype for the converted RelatedLinks data
|
||||
foreach (PropertyDataDto? property in properties)
|
||||
{
|
||||
var value = property.Value?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
List<RelatedLink>? relatedLinks = JsonConvert.DeserializeObject<List<RelatedLink>>(value);
|
||||
var links = new List<LinkDto>();
|
||||
if (relatedLinks is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (RelatedLink relatedLink in relatedLinks)
|
||||
{
|
||||
GuidUdi? udi = null;
|
||||
if (relatedLink.IsInternal)
|
||||
{
|
||||
var linkIsUdi = UdiParser.TryParse(relatedLink.Link, out udi);
|
||||
if (linkIsUdi == false)
|
||||
{
|
||||
// oh no.. probably an integer, yikes!
|
||||
if (int.TryParse(relatedLink.Link, NumberStyles.Integer, CultureInfo.InvariantCulture,
|
||||
out var intId))
|
||||
{
|
||||
Sql<ISqlContext> sqlNodeData = Sql()
|
||||
.Select<NodeDto>()
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(x => x.NodeId == intId);
|
||||
|
||||
NodeDto? node = Database.Fetch<NodeDto>(sqlNodeData).FirstOrDefault();
|
||||
if (node != null)
|
||||
|
||||
// Note: RelatedLinks did not allow for picking media items,
|
||||
// so if there's a value this will be a content item - hence
|
||||
// the hardcoded "document" here
|
||||
{
|
||||
udi = new GuidUdi("document", node.UniqueId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var link = new LinkDto
|
||||
{
|
||||
Name = relatedLink.Caption,
|
||||
Target = relatedLink.NewWindow ? "_blank" : null,
|
||||
Udi = udi,
|
||||
|
||||
// Should only have a URL if it's an external link otherwise it wil be a UDI
|
||||
Url = relatedLink.IsInternal == false ? relatedLink.Link : null,
|
||||
};
|
||||
|
||||
links.Add(link);
|
||||
}
|
||||
|
||||
var json = JsonConvert.SerializeObject(links);
|
||||
|
||||
// Update existing data
|
||||
property.TextValue = json;
|
||||
Database.Update(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class RelatedLink
|
||||
{
|
||||
public int? Id { get; internal set; }
|
||||
|
||||
[JsonProperty("caption")]
|
||||
public string? Caption { get; set; }
|
||||
|
||||
internal bool IsDeleted { get; set; }
|
||||
|
||||
[JsonProperty("link")]
|
||||
public string? Link { get; set; }
|
||||
|
||||
[JsonProperty("newWindow")]
|
||||
public bool NewWindow { get; set; }
|
||||
|
||||
[JsonProperty("isInternal")]
|
||||
public bool IsInternal { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
internal class LinkDto
|
||||
{
|
||||
[DataMember(Name = "name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[DataMember(Name = "target")]
|
||||
public string? Target { get; set; }
|
||||
|
||||
[DataMember(Name = "udi")]
|
||||
public GuidUdi? Udi { get; set; }
|
||||
|
||||
[DataMember(Name = "url")]
|
||||
public string? Url { get; set; }
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class DataTypeMigration : MigrationBase
|
||||
{
|
||||
private static readonly ISet<string> _legacyAliases = new HashSet<string>
|
||||
@@ -45,100 +46,6 @@ public class DataTypeMigration : MigrationBase
|
||||
|
||||
protected override void Migrate()
|
||||
{
|
||||
// drop and create columns
|
||||
Delete.Column("pk").FromTable("cmsDataType").Do();
|
||||
|
||||
// rename the table
|
||||
Rename.Table("cmsDataType").To(Constants.DatabaseSchema.Tables.DataType).Do();
|
||||
|
||||
// create column
|
||||
AddColumn<DataTypeDto>(Constants.DatabaseSchema.Tables.DataType, "config");
|
||||
Execute.Sql(Sql().Update<DataTypeDto>(u => u.Set(x => x.Configuration, string.Empty))).Do();
|
||||
|
||||
// renames
|
||||
Execute.Sql(Sql()
|
||||
.Update<DataTypeDto>(u => u.Set(x => x.EditorAlias, "Umbraco.ColorPicker"))
|
||||
.Where<DataTypeDto>(x => x.EditorAlias == "Umbraco.ColorPickerAlias")).Do();
|
||||
|
||||
// from preValues to configuration...
|
||||
Sql<ISqlContext> sql = Sql()
|
||||
.Select<DataTypeDto>()
|
||||
.AndSelect<PreValueDto>(x => x.Id, x => x.Alias, x => x.SortOrder, x => x.Value)
|
||||
.From<DataTypeDto>()
|
||||
.InnerJoin<PreValueDto>().On<DataTypeDto, PreValueDto>((left, right) => left.NodeId == right.NodeId)
|
||||
.OrderBy<DataTypeDto>(x => x.NodeId)
|
||||
.AndBy<PreValueDto>(x => x.SortOrder);
|
||||
|
||||
IEnumerable<IGrouping<int, PreValueDto>> dtos = Database.Fetch<PreValueDto>(sql).GroupBy(x => x.NodeId);
|
||||
|
||||
foreach (IGrouping<int, PreValueDto> group in dtos)
|
||||
{
|
||||
DataTypeDto? dataType = Database.Fetch<DataTypeDto>(Sql()
|
||||
.Select<DataTypeDto>()
|
||||
.From<DataTypeDto>()
|
||||
.Where<DataTypeDto>(x => x.NodeId == group.Key)).First();
|
||||
|
||||
// check for duplicate aliases
|
||||
var aliases = group.Select(x => x.Alias).Where(x => !string.IsNullOrWhiteSpace(x)).ToArray();
|
||||
if (aliases.Distinct().Count() != aliases.Length)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Cannot migrate prevalues for datatype id={dataType.NodeId}, editor={dataType.EditorAlias}: duplicate alias.");
|
||||
}
|
||||
|
||||
// handle null/empty aliases
|
||||
var index = 0;
|
||||
var dictionary = group.ToDictionary(x => string.IsNullOrWhiteSpace(x.Alias) ? index++.ToString() : x.Alias);
|
||||
|
||||
// migrate the preValues to configuration
|
||||
IPreValueMigrator migrator =
|
||||
_preValueMigrators.GetMigrator(dataType.EditorAlias) ?? new DefaultPreValueMigrator();
|
||||
var config = migrator.GetConfiguration(dataType.NodeId, dataType.EditorAlias, dictionary);
|
||||
var json = _configurationEditorJsonSerializer.Serialize(config);
|
||||
|
||||
// validate - and kill the migration if it fails
|
||||
var newAlias = migrator.GetNewAlias(dataType.EditorAlias);
|
||||
if (newAlias == null)
|
||||
{
|
||||
if (!_legacyAliases.Contains(dataType.EditorAlias))
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Skipping validation of configuration for data type {NodeId} : {EditorAlias}."
|
||||
+ " Please ensure that the configuration is valid. The site may fail to start and / or load data types and run.",
|
||||
dataType.NodeId, dataType.EditorAlias);
|
||||
}
|
||||
}
|
||||
else if (!_propertyEditors.TryGet(newAlias, out IDataEditor? propertyEditor))
|
||||
{
|
||||
if (!_legacyAliases.Contains(newAlias))
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Skipping validation of configuration for data type {NodeId} : {NewEditorAlias} (was: {EditorAlias})"
|
||||
+ " because no property editor with that alias was found."
|
||||
+ " Please ensure that the configuration is valid. The site may fail to start and / or load data types and run.",
|
||||
dataType.NodeId, newAlias, dataType.EditorAlias);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IConfigurationEditor configEditor = propertyEditor.GetConfigurationEditor();
|
||||
try
|
||||
{
|
||||
var _ = configEditor.FromDatabase(json, _configurationEditorJsonSerializer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
e,
|
||||
"Failed to validate configuration for data type {NodeId} : {NewEditorAlias} (was: {EditorAlias})."
|
||||
+ " Please fix the configuration and ensure it is valid. The site may fail to start and / or load data types and run.",
|
||||
dataType.NodeId, newAlias, dataType.EditorAlias);
|
||||
}
|
||||
}
|
||||
|
||||
// update
|
||||
dataType.Configuration = _configurationEditorJsonSerializer.Serialize(config);
|
||||
Database.Update(dataType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
using Umbraco.Cms.Core;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class ContentPickerPreValueMigrator : DefaultPreValueMigrator
|
||||
{
|
||||
public override bool CanMigrate(string editorAlias)
|
||||
=> editorAlias == Constants.PropertyEditors.Legacy.Aliases.ContentPicker2;
|
||||
|
||||
public override string? GetNewAlias(string editorAlias)
|
||||
=> null;
|
||||
|
||||
protected override object? GetPreValueValue(PreValueDto preValue)
|
||||
{
|
||||
if (preValue.Alias == "showOpenButton" ||
|
||||
preValue.Alias == "ignoreUserStartNodes")
|
||||
{
|
||||
return preValue.Value == "1";
|
||||
}
|
||||
|
||||
return base.GetPreValueValue(preValue);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class DecimalPreValueMigrator : DefaultPreValueMigrator
|
||||
{
|
||||
public override bool CanMigrate(string editorAlias)
|
||||
=> editorAlias == "Umbraco.Decimal";
|
||||
|
||||
protected override object? GetPreValueValue(PreValueDto preValue)
|
||||
{
|
||||
if (preValue.Alias == "min" ||
|
||||
preValue.Alias == "step" ||
|
||||
preValue.Alias == "max")
|
||||
{
|
||||
return decimal.TryParse(preValue.Value, out var d) ? (decimal?)d : null;
|
||||
}
|
||||
|
||||
return preValue.Value?.DetectIsJson() ?? false ? JsonConvert.DeserializeObject(preValue.Value) : preValue.Value;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class DefaultPreValueMigrator : IPreValueMigrator
|
||||
{
|
||||
public virtual bool CanMigrate(string editorAlias)
|
||||
=> true;
|
||||
|
||||
public virtual string? GetNewAlias(string editorAlias)
|
||||
=> editorAlias;
|
||||
|
||||
public object GetConfiguration(int dataTypeId, string editorAlias, Dictionary<string, PreValueDto> preValues)
|
||||
{
|
||||
var preValuesA = preValues.Values.ToList();
|
||||
var aliases = preValuesA.Select(x => x.Alias).Distinct().ToArray();
|
||||
if (aliases.Length == 1 && string.IsNullOrWhiteSpace(aliases[0]))
|
||||
{
|
||||
// array-based prevalues
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
["values"] = preValuesA.OrderBy(x => x.SortOrder).Select(x => x.Value).ToArray(),
|
||||
};
|
||||
}
|
||||
|
||||
// assuming we don't want to fall back to array
|
||||
if (aliases.Any(string.IsNullOrWhiteSpace))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Cannot migrate prevalues for datatype id={dataTypeId}, editor={editorAlias}: null/empty alias.");
|
||||
}
|
||||
|
||||
// dictionary-base prevalues
|
||||
return GetPreValues(preValuesA).ToDictionary(x => x.Alias, GetPreValueValue);
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<PreValueDto> GetPreValues(IEnumerable<PreValueDto> preValues)
|
||||
=> preValues;
|
||||
|
||||
protected virtual object? GetPreValueValue(PreValueDto preValue) => preValue.Value?.DetectIsJson() ?? false
|
||||
? JsonConvert.DeserializeObject(preValue.Value)
|
||||
: preValue.Value;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class DropDownFlexiblePreValueMigrator : IPreValueMigrator
|
||||
{
|
||||
public bool CanMigrate(string editorAlias)
|
||||
=> editorAlias == "Umbraco.DropDown.Flexible";
|
||||
|
||||
public virtual string? GetNewAlias(string editorAlias)
|
||||
=> null;
|
||||
|
||||
public object GetConfiguration(int dataTypeId, string editorAlias, Dictionary<string, PreValueDto> preValues)
|
||||
{
|
||||
var config = new DropDownFlexibleConfiguration();
|
||||
foreach (PreValueDto preValue in preValues.Values)
|
||||
{
|
||||
if (preValue.Alias == "multiple")
|
||||
{
|
||||
config.Multiple = preValue.Value == "1";
|
||||
}
|
||||
else
|
||||
{
|
||||
config.Items.Add(new ValueListConfiguration.ValueListItem { Id = preValue.Id, Value = preValue.Value });
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
/// <summary>
|
||||
/// Defines a service migrating preValues.
|
||||
/// </summary>
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public interface IPreValueMigrator
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class ListViewPreValueMigrator : DefaultPreValueMigrator
|
||||
{
|
||||
public override bool CanMigrate(string editorAlias)
|
||||
=> editorAlias == "Umbraco.ListView";
|
||||
|
||||
protected override IEnumerable<PreValueDto> GetPreValues(IEnumerable<PreValueDto> preValues) =>
|
||||
preValues.Where(preValue => preValue.Alias != "displayAtTabNumber");
|
||||
|
||||
protected override object? GetPreValueValue(PreValueDto preValue)
|
||||
{
|
||||
if (preValue.Alias == "pageSize")
|
||||
{
|
||||
return int.TryParse(preValue.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var i)
|
||||
? (int?)i
|
||||
: null;
|
||||
}
|
||||
|
||||
return preValue.Value?.DetectIsJson() ?? false ? JsonConvert.DeserializeObject(preValue.Value) : preValue.Value;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using Umbraco.Cms.Core;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class MarkdownEditorPreValueMigrator : DefaultPreValueMigrator // PreValueMigratorBase
|
||||
{
|
||||
public override bool CanMigrate(string editorAlias)
|
||||
=> editorAlias == Constants.PropertyEditors.Aliases.MarkdownEditor;
|
||||
|
||||
protected override object? GetPreValueValue(PreValueDto preValue)
|
||||
{
|
||||
if (preValue.Alias == "preview")
|
||||
{
|
||||
return preValue.Value == "1";
|
||||
}
|
||||
|
||||
return base.GetPreValueValue(preValue);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using Umbraco.Cms.Core;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class MediaPickerPreValueMigrator : DefaultPreValueMigrator // PreValueMigratorBase
|
||||
{
|
||||
private readonly string[] _editors =
|
||||
{
|
||||
Constants.PropertyEditors.Legacy.Aliases.MediaPicker2, Constants.PropertyEditors.Aliases.MediaPicker,
|
||||
};
|
||||
|
||||
public override bool CanMigrate(string editorAlias)
|
||||
=> _editors.Contains(editorAlias);
|
||||
|
||||
public override string GetNewAlias(string editorAlias)
|
||||
=> Constants.PropertyEditors.Aliases.MediaPicker;
|
||||
|
||||
// you wish - but MediaPickerConfiguration lives in Umbraco.Web
|
||||
/*
|
||||
public override object GetConfiguration(int dataTypeId, string editorAlias, Dictionary<string, PreValueDto> preValues)
|
||||
{
|
||||
return new MediaPickerConfiguration { ... };
|
||||
}
|
||||
*/
|
||||
|
||||
protected override object? GetPreValueValue(PreValueDto preValue)
|
||||
{
|
||||
if (preValue.Alias == "multiPicker" ||
|
||||
preValue.Alias == "onlyImages" ||
|
||||
preValue.Alias == "disableFolderSelect")
|
||||
{
|
||||
return preValue.Value == "1";
|
||||
}
|
||||
|
||||
return base.GetPreValueValue(preValue);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class NestedContentPreValueMigrator : DefaultPreValueMigrator // PreValueMigratorBase
|
||||
{
|
||||
public override bool CanMigrate(string editorAlias)
|
||||
=> editorAlias == "Umbraco.NestedContent";
|
||||
|
||||
// you wish - but NestedContentConfiguration lives in Umbraco.Web
|
||||
/*
|
||||
public override object GetConfiguration(int dataTypeId, string editorAlias, Dictionary<string, PreValueDto> preValues)
|
||||
{
|
||||
return new NestedContentConfiguration { ... };
|
||||
}
|
||||
*/
|
||||
|
||||
protected override object? GetPreValueValue(PreValueDto preValue)
|
||||
{
|
||||
if (preValue.Alias == "confirmDeletes" ||
|
||||
preValue.Alias == "showIcons" ||
|
||||
preValue.Alias == "hideLabel")
|
||||
{
|
||||
return preValue.Value == "1";
|
||||
}
|
||||
|
||||
if (preValue.Alias == "minItems" ||
|
||||
preValue.Alias == "maxItems")
|
||||
{
|
||||
return int.TryParse(preValue.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var i)
|
||||
? (int?)i
|
||||
: null;
|
||||
}
|
||||
|
||||
return preValue.Value?.DetectIsJson() ?? false ? JsonConvert.DeserializeObject(preValue.Value) : preValue.Value;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using NPoco;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
[TableName("cmsDataTypePreValues")]
|
||||
[ExplicitColumns]
|
||||
public class PreValueDto
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public abstract class PreValueMigratorBase : IPreValueMigrator
|
||||
{
|
||||
public abstract bool CanMigrate(string editorAlias);
|
||||
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Cms.Core.Composing;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class PreValueMigratorCollection : BuilderCollectionBase<IPreValueMigrator>
|
||||
{
|
||||
private readonly ILogger<PreValueMigratorCollection> _logger;
|
||||
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Core.Composing;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class PreValueMigratorCollectionBuilder : OrderedCollectionBuilderBase<PreValueMigratorCollectionBuilder,
|
||||
PreValueMigratorCollection, IPreValueMigrator>
|
||||
{
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Exceptions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class RenamingPreValueMigrator : DefaultPreValueMigrator
|
||||
{
|
||||
private readonly string[] _editors = { "Umbraco.NoEdit" };
|
||||
|
||||
public override bool CanMigrate(string editorAlias)
|
||||
=> _editors.Contains(editorAlias);
|
||||
|
||||
public override string GetNewAlias(string editorAlias)
|
||||
{
|
||||
switch (editorAlias)
|
||||
{
|
||||
case "Umbraco.NoEdit":
|
||||
return Constants.PropertyEditors.Aliases.Label;
|
||||
default:
|
||||
throw new PanicException($"The alias {editorAlias} is not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class RichTextPreValueMigrator : DefaultPreValueMigrator
|
||||
{
|
||||
public override bool CanMigrate(string editorAlias)
|
||||
=> editorAlias == "Umbraco.TinyMCEv3";
|
||||
|
||||
public override string GetNewAlias(string editorAlias)
|
||||
=> Constants.PropertyEditors.Aliases.TinyMce;
|
||||
|
||||
protected override object? GetPreValueValue(PreValueDto preValue)
|
||||
{
|
||||
if (preValue.Alias == "hideLabel")
|
||||
{
|
||||
return preValue.Value == "1";
|
||||
}
|
||||
|
||||
return preValue.Value?.DetectIsJson() ?? false ? JsonConvert.DeserializeObject(preValue.Value) : preValue.Value;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class UmbracoSliderPreValueMigrator : PreValueMigratorBase
|
||||
{
|
||||
public override bool CanMigrate(string editorAlias)
|
||||
=> editorAlias == "Umbraco.Slider";
|
||||
|
||||
public override object GetConfiguration(int dataTypeId, string editorAlias,
|
||||
Dictionary<string, PreValueDto> preValues) =>
|
||||
new SliderConfiguration
|
||||
{
|
||||
EnableRange = GetBoolValue(preValues, "enableRange"),
|
||||
InitialValue = GetDecimalValue(preValues, "initVal1"),
|
||||
InitialValue2 = GetDecimalValue(preValues, "initVal2"),
|
||||
MaximumValue = GetDecimalValue(preValues, "maxVal"),
|
||||
MinimumValue = GetDecimalValue(preValues, "minVal"),
|
||||
StepIncrements = GetDecimalValue(preValues, "step"),
|
||||
};
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.DataTypes;
|
||||
|
||||
internal class ValueListPreValueMigrator : IPreValueMigrator
|
||||
{
|
||||
private readonly string[] _editors =
|
||||
{
|
||||
"Umbraco.RadioButtonList", "Umbraco.CheckBoxList", "Umbraco.DropDown", "Umbraco.DropdownlistPublishingKeys",
|
||||
"Umbraco.DropDownMultiple", "Umbraco.DropdownlistMultiplePublishKeys",
|
||||
};
|
||||
|
||||
public bool CanMigrate(string editorAlias)
|
||||
=> _editors.Contains(editorAlias);
|
||||
|
||||
public virtual string? GetNewAlias(string editorAlias)
|
||||
=> null;
|
||||
|
||||
public object GetConfiguration(int dataTypeId, string editorAlias, Dictionary<string, PreValueDto> preValues)
|
||||
{
|
||||
var config = new ValueListConfiguration();
|
||||
foreach (PreValueDto preValue in preValues.Values)
|
||||
{
|
||||
config.Items.Add(new ValueListConfiguration.ValueListItem { Id = preValue.Id, Value = preValue.Value });
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class DropDownPropertyEditorsMigration : PropertyEditorsMigrationBase
|
||||
{
|
||||
private readonly IConfigurationEditorJsonSerializer _configurationEditorJsonSerializer;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class DropMigrationsTable : MigrationBase
|
||||
{
|
||||
public DropMigrationsTable(IMigrationContext context)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class DropPreValueTable : MigrationBase
|
||||
{
|
||||
public DropPreValueTable(IMigrationContext context)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class DropTaskTables : MigrationBase
|
||||
{
|
||||
public DropTaskTables(IMigrationContext context)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class DropTemplateDesignColumn : MigrationBase
|
||||
{
|
||||
public DropTemplateDesignColumn(IMigrationContext context)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class DropXmlTables : MigrationBase
|
||||
{
|
||||
public DropXmlTables(IMigrationContext context)
|
||||
|
||||
@@ -5,6 +5,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
/// <summary>
|
||||
/// Adds a new, self-joined field to umbracoLanguages to hold the fall-back language for
|
||||
/// a given language.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class FixLanguageIsoCodeLength : MigrationBase
|
||||
{
|
||||
public FixLanguageIsoCodeLength(IMigrationContext context)
|
||||
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class LanguageColumns : MigrationBase
|
||||
{
|
||||
public LanguageColumns(IMigrationContext context)
|
||||
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class MakeRedirectUrlVariant : MigrationBase
|
||||
{
|
||||
public MakeRedirectUrlVariant(IMigrationContext context)
|
||||
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class MakeTagsVariant : MigrationBase
|
||||
{
|
||||
public MakeTagsVariant(IMigrationContext context)
|
||||
|
||||
@@ -11,6 +11,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class MergeDateAndDateTimePropertyEditor : MigrationBase
|
||||
{
|
||||
private readonly IConfigurationEditorJsonSerializer _configurationEditorJsonSerializer;
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
using NPoco;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot of the <see cref="ContentTypeDto" /> as it was at version 8.0
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is required during migrations the schema of this table changed and running SQL against the new table would
|
||||
/// result in errors
|
||||
/// </remarks>
|
||||
[TableName(TableName)]
|
||||
[PrimaryKey("pk")]
|
||||
[ExplicitColumns]
|
||||
internal class ContentTypeDto80
|
||||
{
|
||||
public const string TableName = Constants.DatabaseSchema.Tables.ContentType;
|
||||
|
||||
[Column("pk")]
|
||||
[PrimaryKeyColumn(IdentitySeed = 535)]
|
||||
public int PrimaryKey { get; set; }
|
||||
|
||||
[Column("nodeId")]
|
||||
[ForeignKey(typeof(NodeDto))]
|
||||
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsContentType")]
|
||||
public int NodeId { get; set; }
|
||||
|
||||
[Column("alias")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string? Alias { get; set; }
|
||||
|
||||
[Column("icon")]
|
||||
[Index(IndexTypes.NonClustered)]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string? Icon { get; set; }
|
||||
|
||||
[Column("thumbnail")]
|
||||
[Constraint(Default = "folder.png")]
|
||||
public string? Thumbnail { get; set; }
|
||||
|
||||
[Column("description")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(1500)]
|
||||
public string? Description { get; set; }
|
||||
|
||||
[Column("isContainer")]
|
||||
[Constraint(Default = "0")]
|
||||
public bool IsContainer { get; set; }
|
||||
|
||||
[Column("allowAtRoot")]
|
||||
[Constraint(Default = "0")]
|
||||
public bool AllowAtRoot { get; set; }
|
||||
|
||||
[Column("variations")]
|
||||
[Constraint(Default = "1" /*ContentVariation.InvariantNeutral*/)]
|
||||
public byte Variations { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public NodeDto? NodeDto { get; set; }
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
using NPoco;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot of the <see cref="PropertyDataDto" /> as it was at version 8.0
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is required during migrations the schema of this table changed and running SQL against the new table would
|
||||
/// result in errors
|
||||
/// </remarks>
|
||||
[TableName(TableName)]
|
||||
[PrimaryKey("id")]
|
||||
[ExplicitColumns]
|
||||
internal class PropertyDataDto80
|
||||
{
|
||||
public const string TableName = Constants.DatabaseSchema.Tables.PropertyData;
|
||||
public const int VarcharLength = 512;
|
||||
public const int SegmentLength = 256;
|
||||
|
||||
private decimal? _decimalValue;
|
||||
|
||||
// pk, not used at the moment (never updating)
|
||||
[Column("id")] [PrimaryKeyColumn] public int Id { get; set; }
|
||||
|
||||
[Column("versionId")]
|
||||
[ForeignKey(typeof(ContentVersionDto))]
|
||||
[Index(IndexTypes.UniqueNonClustered, Name = "IX_" + TableName + "_VersionId",
|
||||
ForColumns = "versionId,propertyTypeId,languageId,segment")]
|
||||
public int VersionId { get; set; }
|
||||
|
||||
[Column("propertyTypeId")]
|
||||
[ForeignKey(typeof(PropertyTypeDto80))]
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_PropertyTypeId")]
|
||||
public int PropertyTypeId { get; set; }
|
||||
|
||||
[Column("languageId")]
|
||||
[ForeignKey(typeof(LanguageDto))]
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_LanguageId")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public int? LanguageId { get; set; }
|
||||
|
||||
[Column("segment")]
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_Segment")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(SegmentLength)]
|
||||
public string? Segment { get; set; }
|
||||
|
||||
[Column("intValue")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public int? IntegerValue { get; set; }
|
||||
|
||||
[Column("decimalValue")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public decimal? DecimalValue
|
||||
{
|
||||
get => _decimalValue;
|
||||
set => _decimalValue = value?.Normalize();
|
||||
}
|
||||
|
||||
[Column("dateValue")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public DateTime? DateValue { get; set; }
|
||||
|
||||
[Column("varcharValue")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(VarcharLength)]
|
||||
public string? VarcharValue { get; set; }
|
||||
|
||||
[Column("textValue")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[SpecialDbType(SpecialDbTypes.NTEXT)]
|
||||
public string? TextValue { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
[Reference(ReferenceType.OneToOne, ColumnName = "PropertyTypeId")]
|
||||
public PropertyTypeDto80? PropertyTypeDto { get; set; }
|
||||
|
||||
[Ignore]
|
||||
public object? Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IntegerValue.HasValue)
|
||||
{
|
||||
return IntegerValue.Value;
|
||||
}
|
||||
|
||||
if (DecimalValue.HasValue)
|
||||
{
|
||||
return DecimalValue.Value;
|
||||
}
|
||||
|
||||
if (DateValue.HasValue)
|
||||
{
|
||||
return DateValue.Value;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(VarcharValue))
|
||||
{
|
||||
return VarcharValue;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(TextValue))
|
||||
{
|
||||
return TextValue;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyDataDto80 Clone(int versionId) =>
|
||||
new PropertyDataDto80
|
||||
{
|
||||
VersionId = versionId,
|
||||
PropertyTypeId = PropertyTypeId,
|
||||
LanguageId = LanguageId,
|
||||
Segment = Segment,
|
||||
IntegerValue = IntegerValue,
|
||||
DecimalValue = DecimalValue,
|
||||
DateValue = DateValue,
|
||||
VarcharValue = VarcharValue,
|
||||
TextValue = TextValue,
|
||||
PropertyTypeDto = PropertyTypeDto
|
||||
};
|
||||
|
||||
protected bool Equals(PropertyDataDto other) => Id == other.Id;
|
||||
|
||||
public override bool Equals(object? other) =>
|
||||
!ReferenceEquals(null, other) // other is not null
|
||||
&& (ReferenceEquals(this, other) // and either ref-equals, or same id
|
||||
|| (other is PropertyDataDto pdata && pdata.Id == Id));
|
||||
|
||||
public override int GetHashCode() =>
|
||||
// ReSharper disable once NonReadonlyMemberInGetHashCode
|
||||
Id;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
using NPoco;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot of the <see cref="PropertyTypeDto" /> as it was at version 8.0
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is required during migrations before 8.6 since the schema has changed and running SQL against the new table
|
||||
/// would result in errors
|
||||
/// </remarks>
|
||||
[TableName(Constants.DatabaseSchema.Tables.PropertyType)]
|
||||
[PrimaryKey("id")]
|
||||
[ExplicitColumns]
|
||||
internal class PropertyTypeDto80
|
||||
{
|
||||
[Column("id")]
|
||||
[PrimaryKeyColumn(IdentitySeed = 50)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("dataTypeId")]
|
||||
[ForeignKey(typeof(DataTypeDto), Column = "nodeId")]
|
||||
public int DataTypeId { get; set; }
|
||||
|
||||
[Column("contentTypeId")]
|
||||
[ForeignKey(typeof(ContentTypeDto), Column = "nodeId")]
|
||||
public int ContentTypeId { get; set; }
|
||||
|
||||
[Column("propertyTypeGroupId")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[ForeignKey(typeof(PropertyTypeGroupDto))]
|
||||
public int? PropertyTypeGroupId { get; set; }
|
||||
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_cmsPropertyTypeAlias")]
|
||||
[Column("Alias")]
|
||||
public string Alias { get; set; } = null!;
|
||||
|
||||
[Column("Name")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[Column("sortOrder")]
|
||||
[Constraint(Default = "0")]
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
[Column("mandatory")]
|
||||
[Constraint(Default = "0")]
|
||||
public bool Mandatory { get; set; }
|
||||
|
||||
[Column("validationRegExp")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string? ValidationRegExp { get; set; }
|
||||
|
||||
[Column("Description")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(2000)]
|
||||
public string? Description { get; set; }
|
||||
|
||||
[Column("variations")]
|
||||
[Constraint(Default = "1" /*ContentVariation.InvariantNeutral*/)]
|
||||
public byte Variations { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
[Reference(ReferenceType.OneToOne, ColumnName = "DataTypeId")]
|
||||
public DataTypeDto? DataTypeDto { get; set; }
|
||||
|
||||
[Column("UniqueID")]
|
||||
[NullSetting(NullSetting = NullSettings.NotNull)]
|
||||
[Constraint(Default = SystemMethods.NewGuid)]
|
||||
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsPropertyTypeUniqueID")]
|
||||
public Guid UniqueId { get; set; }
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class PropertyEditorsMigration : MigrationBase
|
||||
{
|
||||
public PropertyEditorsMigration(IMigrationContext context)
|
||||
|
||||
@@ -12,6 +12,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public abstract class PropertyEditorsMigrationBase : MigrationBase
|
||||
{
|
||||
protected PropertyEditorsMigrationBase(IMigrationContext context)
|
||||
|
||||
@@ -13,6 +13,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class RadioAndCheckboxPropertyEditorsMigration : PropertyEditorsMigrationBase
|
||||
{
|
||||
private readonly IConfigurationEditorJsonSerializer _configurationEditorJsonSerializer;
|
||||
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class RefactorMacroColumns : MigrationBase
|
||||
{
|
||||
public RefactorMacroColumns(IMigrationContext context)
|
||||
|
||||
@@ -6,6 +6,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class RefactorVariantsModel : MigrationBase
|
||||
{
|
||||
public RefactorVariantsModel(IMigrationContext context)
|
||||
|
||||
@@ -4,6 +4,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class RenameLabelAndRichTextPropertyEditorAliases : MigrationBase
|
||||
{
|
||||
public RenameLabelAndRichTextPropertyEditorAliases(IMigrationContext context)
|
||||
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class RenameMediaVersionTable : MigrationBase
|
||||
{
|
||||
public RenameMediaVersionTable(IMigrationContext context)
|
||||
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Core;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class RenameUmbracoDomainsTable : MigrationBase
|
||||
{
|
||||
public RenameUmbracoDomainsTable(IMigrationContext context)
|
||||
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Core;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class SuperZero : MigrationBase
|
||||
{
|
||||
public SuperZero(IMigrationContext context)
|
||||
|
||||
@@ -4,6 +4,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class TablesForScheduledPublishing : MigrationBase
|
||||
{
|
||||
public TablesForScheduledPublishing(IMigrationContext context)
|
||||
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class TagsMigration : MigrationBase
|
||||
{
|
||||
public TagsMigration(IMigrationContext context)
|
||||
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Core;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class TagsMigrationFix : MigrationBase
|
||||
{
|
||||
public TagsMigrationFix(IMigrationContext context)
|
||||
|
||||
@@ -6,6 +6,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class UpdateDefaultMandatoryLanguage : MigrationBase
|
||||
{
|
||||
public UpdateDefaultMandatoryLanguage(IMigrationContext context)
|
||||
|
||||
@@ -9,6 +9,7 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class UpdatePickerIntegerValuesToUdi : MigrationBase
|
||||
{
|
||||
public UpdatePickerIntegerValuesToUdi(IMigrationContext context)
|
||||
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
/// <summary>
|
||||
/// Creates/Updates non mandatory FK columns to the user table
|
||||
/// </summary>
|
||||
|
||||
@@ -5,6 +5,7 @@ using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class VariantsMigration : MigrationBase
|
||||
{
|
||||
public VariantsMigration(IMigrationContext context)
|
||||
|
||||
@@ -2,6 +2,7 @@ using Umbraco.Cms.Infrastructure.Migrations.PostMigrations;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_1;
|
||||
|
||||
[Obsolete("This is not used anymore and will be removed in Umbraco 13")]
|
||||
public class ChangeNuCacheJsonFormat : MigrationBase
|
||||
{
|
||||
public ChangeNuCacheJsonFormat(IMigrationContext context)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user