fpexif: Fix crash when the image file contains xmp data with invalid xml structure (missing first '<')
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8994 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
180d051924
commit
116abaad54
@ -6,10 +6,10 @@ object MainForm: TMainForm
|
|||||||
Caption = 'Metadata viewer'
|
Caption = 'Metadata viewer'
|
||||||
ClientHeight = 714
|
ClientHeight = 714
|
||||||
ClientWidth = 926
|
ClientWidth = 926
|
||||||
|
ShowHint = True
|
||||||
|
LCLVersion = '3.99.0.0'
|
||||||
OnCreate = FormCreate
|
OnCreate = FormCreate
|
||||||
OnDestroy = FormDestroy
|
OnDestroy = FormDestroy
|
||||||
ShowHint = True
|
|
||||||
LCLVersion = '2.3.0.0'
|
|
||||||
object ShellPanel: TPanel
|
object ShellPanel: TPanel
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 691
|
Height = 691
|
||||||
@ -31,11 +31,11 @@ object MainForm: TMainForm
|
|||||||
HideSelection = False
|
HideSelection = False
|
||||||
ReadOnly = True
|
ReadOnly = True
|
||||||
TabOrder = 0
|
TabOrder = 0
|
||||||
OnGetImageIndex = ShellTreeViewGetImageIndex
|
|
||||||
OnSelectionChanged = ShellTreeViewSelectionChanged
|
|
||||||
Options = [tvoAutoItemHeight, tvoKeepCollapsedNodes, tvoReadOnly, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips, tvoThemedDraw]
|
Options = [tvoAutoItemHeight, tvoKeepCollapsedNodes, tvoReadOnly, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips, tvoThemedDraw]
|
||||||
ObjectTypes = [otFolders]
|
ObjectTypes = [otFolders]
|
||||||
ShellListView = ShellListView
|
ShellListView = ShellListView
|
||||||
|
OnGetImageIndex = ShellTreeViewGetImageIndex
|
||||||
|
OnSelectionChanged = ShellTreeViewSelectionChanged
|
||||||
end
|
end
|
||||||
object Splitter1: TSplitter
|
object Splitter1: TSplitter
|
||||||
Cursor = crVSplit
|
Cursor = crVSplit
|
||||||
@ -59,9 +59,9 @@ object MainForm: TMainForm
|
|||||||
ReadOnly = True
|
ReadOnly = True
|
||||||
SortColumn = 0
|
SortColumn = 0
|
||||||
TabOrder = 2
|
TabOrder = 2
|
||||||
OnSelectItem = ShellListViewSelectItem
|
|
||||||
ObjectTypes = [otNonFolders]
|
ObjectTypes = [otNonFolders]
|
||||||
ShellTreeView = ShellTreeView
|
ShellTreeView = ShellTreeView
|
||||||
|
OnSelectItem = ShellListViewSelectItem
|
||||||
end
|
end
|
||||||
object PreviewImage: TImage
|
object PreviewImage: TImage
|
||||||
Left = 0
|
Left = 0
|
||||||
@ -136,16 +136,16 @@ object MainForm: TMainForm
|
|||||||
Caption = 'File: '
|
Caption = 'File: '
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
object PageControl1: TPageControl
|
object PageControl: TPageControl
|
||||||
Left = 0
|
Left = 0
|
||||||
Height = 539
|
Height = 539
|
||||||
Top = 23
|
Top = 23
|
||||||
Width = 647
|
Width = 647
|
||||||
ActivePage = PgXMP
|
ActivePage = PgMetadata
|
||||||
Align = alClient
|
Align = alClient
|
||||||
TabIndex = 1
|
TabIndex = 0
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
OnChange = PageControl1Change
|
OnChange = PageControlChange
|
||||||
object PgMetadata: TTabSheet
|
object PgMetadata: TTabSheet
|
||||||
Caption = 'EXIF, IPTC'
|
Caption = 'EXIF, IPTC'
|
||||||
ClientHeight = 511
|
ClientHeight = 511
|
||||||
@ -223,9 +223,9 @@ object MainForm: TMainForm
|
|||||||
BorderSpacing.Left = 8
|
BorderSpacing.Left = 8
|
||||||
Caption = 'Show tag IDs'
|
Caption = 'Show tag IDs'
|
||||||
Checked = True
|
Checked = True
|
||||||
OnChange = CbShowTagIDsChange
|
|
||||||
State = cbChecked
|
State = cbChecked
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
|
OnChange = CbShowTagIDsChange
|
||||||
end
|
end
|
||||||
object CbShowParentTagID: TCheckBox
|
object CbShowParentTagID: TCheckBox
|
||||||
AnchorSideLeft.Control = CbShowTagIDs
|
AnchorSideLeft.Control = CbShowTagIDs
|
||||||
@ -798,8 +798,8 @@ object MainForm: TMainForm
|
|||||||
AutoSize = True
|
AutoSize = True
|
||||||
BorderSpacing.Left = 16
|
BorderSpacing.Left = 16
|
||||||
Caption = 'Apply changes'
|
Caption = 'Apply changes'
|
||||||
OnClick = btnApplyChangesXMPClick
|
|
||||||
TabOrder = 0
|
TabOrder = 0
|
||||||
|
OnClick = btnApplyChangesXMPClick
|
||||||
end
|
end
|
||||||
object btnSaveXMP: TButton
|
object btnSaveXMP: TButton
|
||||||
AnchorSideLeft.Control = btnApplyChangesXMP
|
AnchorSideLeft.Control = btnApplyChangesXMP
|
||||||
@ -812,8 +812,8 @@ object MainForm: TMainForm
|
|||||||
AutoSize = True
|
AutoSize = True
|
||||||
BorderSpacing.Left = 4
|
BorderSpacing.Left = 4
|
||||||
Caption = 'Save'
|
Caption = 'Save'
|
||||||
OnClick = btnSaveXMPClick
|
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
|
OnClick = btnSaveXMPClick
|
||||||
end
|
end
|
||||||
object cbProcessXMP: TCheckBox
|
object cbProcessXMP: TCheckBox
|
||||||
AnchorSideLeft.Control = Panel5
|
AnchorSideLeft.Control = Panel5
|
||||||
@ -917,8 +917,8 @@ object MainForm: TMainForm
|
|||||||
BorderSpacing.Left = 8
|
BorderSpacing.Left = 8
|
||||||
BorderSpacing.Bottom = 4
|
BorderSpacing.Bottom = 4
|
||||||
Caption = 'Execute'
|
Caption = 'Execute'
|
||||||
OnClick = BtnChangeDateClick
|
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
|
OnClick = BtnChangeDateClick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -29,7 +29,7 @@ type
|
|||||||
Panel5: TPanel;
|
Panel5: TPanel;
|
||||||
XMPListView: TListView;
|
XMPListView: TListView;
|
||||||
Messages: TMemo;
|
Messages: TMemo;
|
||||||
PageControl1: TPageControl;
|
PageControl: TPageControl;
|
||||||
Panel1: TPanel;
|
Panel1: TPanel;
|
||||||
Panel2: TPanel;
|
Panel2: TPanel;
|
||||||
Panel3: TPanel;
|
Panel3: TPanel;
|
||||||
@ -57,7 +57,7 @@ type
|
|||||||
procedure CbShowTagIDsChange(Sender: TObject);
|
procedure CbShowTagIDsChange(Sender: TObject);
|
||||||
procedure FormCreate(Sender: TObject);
|
procedure FormCreate(Sender: TObject);
|
||||||
procedure FormDestroy(Sender: TObject);
|
procedure FormDestroy(Sender: TObject);
|
||||||
procedure PageControl1Change(Sender: TObject);
|
procedure PageControlChange(Sender: TObject);
|
||||||
procedure ShellListViewSelectItem(Sender: TObject; Item: TListItem;
|
procedure ShellListViewSelectItem(Sender: TObject; Item: TListItem;
|
||||||
Selected: Boolean);
|
Selected: Boolean);
|
||||||
procedure ShellTreeViewGetImageIndex(Sender: TObject; Node: TTreeNode);
|
procedure ShellTreeViewGetImageIndex(Sender: TObject; Node: TTreeNode);
|
||||||
@ -408,7 +408,7 @@ begin
|
|||||||
Messages.Show;
|
Messages.Show;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if PageControl1.ActivePage = PgImage then begin
|
if PageControl.ActivePage = PgImage then begin
|
||||||
crs := Screen.Cursor;
|
crs := Screen.Cursor;
|
||||||
try
|
try
|
||||||
Screen.Cursor := crHourglass;
|
Screen.Cursor := crHourglass;
|
||||||
@ -466,6 +466,8 @@ begin
|
|||||||
h := ini.ReadInteger('MainForm', 'TreeHeight', 0);
|
h := ini.ReadInteger('MainForm', 'TreeHeight', 0);
|
||||||
if h <> 0 then ShellTreeView.Height := h;
|
if h <> 0 then ShellTreeView.Height := h;
|
||||||
|
|
||||||
|
PageControl.ActivePageIndex := ini.ReadInteger('MainForm', 'PageControl', 0);
|
||||||
|
|
||||||
for i:=0 to TagListView.Columns.Count-1 do begin
|
for i:=0 to TagListView.Columns.Count-1 do begin
|
||||||
w := ini.ReadInteger('TagList', 'ColWidth'+IntToStr(i), 0);
|
w := ini.ReadInteger('TagList', 'ColWidth'+IntToStr(i), 0);
|
||||||
if w <> 0 then
|
if w <> 0 then
|
||||||
@ -504,7 +506,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.PageControl1Change(Sender: TObject);
|
procedure TMainForm.PageControlChange(Sender: TObject);
|
||||||
var
|
var
|
||||||
crs: TCursor;
|
crs: TCursor;
|
||||||
begin
|
begin
|
||||||
@ -541,6 +543,7 @@ begin
|
|||||||
ini.WriteString('MainForm', 'Path', ShellTreeView.Path);
|
ini.WriteString('MainForm', 'Path', ShellTreeView.Path);
|
||||||
ini.WriteInteger('MainForm', 'LeftPanelWidth', ShellPanel.Width);
|
ini.WriteInteger('MainForm', 'LeftPanelWidth', ShellPanel.Width);
|
||||||
ini.WriteInteger('MainForm', 'TreeHeight', ShellTreeView.Height);
|
ini.WriteInteger('MainForm', 'TreeHeight', ShellTreeView.Height);
|
||||||
|
ini.WriteInteger('MainForm', 'PageControl', PageControl.ActivePageIndex);
|
||||||
|
|
||||||
ini.WriteBool('TagList', 'ShowTagIDs', CbShowTagIDs.Checked);
|
ini.WriteBool('TagList', 'ShowTagIDs', CbShowTagIDs.Checked);
|
||||||
ini.WriteBool('TagList', 'ShowParentTagID', CbShowParentTagID.Checked);
|
ini.WriteBool('TagList', 'ShowParentTagID', CbShowParentTagID.Checked);
|
||||||
|
@ -577,8 +577,11 @@ begin
|
|||||||
try
|
try
|
||||||
FXmpData.LoadFromStream(AStream, size - Length(XMP_KEY));
|
FXmpData.LoadFromStream(AStream, size - Length(XMP_KEY));
|
||||||
except
|
except
|
||||||
FreeAndNil(FXmpData);
|
on E:Exception do
|
||||||
raise;
|
begin
|
||||||
|
FreeAndNil(FXmpData);
|
||||||
|
raise EFpExifReader.Create('Error reading XMP data: ' + E.Message);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -159,13 +159,25 @@ end;
|
|||||||
procedure TXMPData.LoadFromStream(AStream: TStream; ASize: Integer = -1);
|
procedure TXMPData.LoadFromStream(AStream: TStream; ASize: Integer = -1);
|
||||||
var
|
var
|
||||||
p: Int64;
|
p: Int64;
|
||||||
|
i: SizeInt;
|
||||||
begin
|
begin
|
||||||
if ASize = -1 then
|
if ASize = -1 then
|
||||||
ASize := AStream.Size;
|
ASize := AStream.Size;
|
||||||
SetLength(FData, ASize);
|
SetLength(FData, ASize);
|
||||||
p := AStream.Position;
|
p := AStream.Position;
|
||||||
AStream.Read(FData[1], ASize);
|
AStream.Read(FData[1], ASize);
|
||||||
|
|
||||||
|
// Sometimes there are incomplete xml files, missing the initial '<'.
|
||||||
|
// https://superuser.com/questions/1389971/error-0x80070057-the-parameter-is-incorrect-when-editing-jpeg-metadata
|
||||||
|
// Fixing this is better than rejecting the file...
|
||||||
|
if pos('?xpacket', FData) = 1 then
|
||||||
|
begin
|
||||||
|
SetLength(FData, ASize+1);
|
||||||
|
for i := ASize downto 1 do
|
||||||
|
FData[i+1] := FData[i];
|
||||||
|
FData[1] := '<';
|
||||||
|
end;
|
||||||
|
|
||||||
AStream.Position := p;
|
AStream.Position := p;
|
||||||
{$IFDEF FPC}
|
{$IFDEF FPC}
|
||||||
CreateTags;
|
CreateTags;
|
||||||
|
Loading…
Reference in New Issue
Block a user