Skip to content

Commit

Permalink
Merge pull request #15 from dgaspary/master
Browse files Browse the repository at this point in the history
Update
  • Loading branch information
joecare99 authored May 5, 2021
2 parents 1a5bfa6 + 4bfa38c commit da0ca9b
Showing 1 changed file with 174 additions and 13 deletions.
187 changes: 174 additions & 13 deletions odf_types.pas
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
fpOdf is a library used to help users to create and to modify OpenDocument
Files(ODF)
Copyright (C) 2013-2019 Daniel F. Gaspary https://github.com/dgaspary
Copyright (C) 2013-2021 Daniel F. Gaspary https://github.com/dgaspary
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
Expand Down Expand Up @@ -249,6 +249,7 @@ TOdfElementTypeSet = class(specialize TFPGList<TElementType>)

TOdfXmlFiles = ofManifestRdf .. High(TOdfFile);


const
OdfXmlFileRoot: array[TOdfXmlFiles] of TElementType =
(
Expand Down Expand Up @@ -411,6 +412,9 @@ TOdfXPathNsResolver = class;

TOdfDocument = class
private
FTempDir: string;
FRemoveTempDir: boolean;

FXmlDocument: TXMLDocument;

//Document Root Elements (Ref: Table 7)
Expand All @@ -425,7 +429,7 @@ TOdfDocument = class
FMasterStyles: TDOMElement;

FBody: TDOMElement;
FManifest: TDOMElement;
FManifest: TXMLDocument;
FManifestRdf: TDOMElement;

FXPathNsResolver: TOdfXPathNsResolver;
Expand All @@ -438,6 +442,8 @@ TOdfDocument = class
procedure FindOdfRootElements;virtual;
procedure InitBodyContent; virtual; abstract;

procedure ResetRootElements; virtual;

function GetMimeType: TOdfMimetype;
procedure SetCreationMeta;

Expand Down Expand Up @@ -542,8 +548,10 @@ TOdfDocument = class
property AutomaticStyles: TDOMElement read FAutomaticStyles write FAutomaticStyles;
property MasterStyles: TDOMElement read FMasterStyles write FMasterStyles;

property Manifest: TDOMElement read FManifest write FManifest;
property Manifest: TXMLDocument read FManifest write FManifest;
property ManifestRdf: TDOMElement read FManifestRdf write FManifestRdf;

property RemoveTempDir: boolean read FRemoveTempDir write FRemoveTempDir;
end;


Expand Down Expand Up @@ -622,6 +630,8 @@ TOdfTextDocument = class(TOdfDocument)
FText: TDOMElement;
procedure InitXmlDocument; override;

procedure ResetRootElements; override;

procedure InitBodyContent; override;
Procedure GenerateAutoStyles;
public
Expand Down Expand Up @@ -1273,6 +1283,13 @@ procedure TOdfTextDocument.InitXmlDocument;
MimeType:=omtText;
end;

procedure TOdfTextDocument.ResetRootElements;
begin
inherited ResetRootElements;

FText:=nil;
end;

procedure TOdfTextDocument.InitBodyContent;
begin
if Assigned(FText)
Expand Down Expand Up @@ -2070,18 +2087,25 @@ class procedure TOdfDocument.ReadPackage(ADir: String; AOdf: TOdfDocument);
LoadXml('settings.xml');
AOdf.Settings:=MoveElem(vNsURI, 'settings');

vDoc.Free;
LoadXml(IncludeTrailingPathDelimiter('META-INF') + 'manifest.xml');

DeleteDirectory(ADir, false);
AOdf.Manifest:=vDoc;
vDoc:=nil;

AOdf.InitBodyContent;
end;

procedure TOdfDocument.SetXmlDocument(AValue: TXMLDocument);
begin
if assigned(FXmlDocument) then
FreeAndNil(FXmlDocument);
FXmlDocument:=AValue;
if Assigned(FXmlDocument)
then
begin
FreeAndNil(FXmlDocument);

ResetRootElements;
end;

FXmlDocument:=AValue;
end;

function OdfCreateManifestRdfFile: TXMLDocument;
Expand Down Expand Up @@ -2165,9 +2189,9 @@ function OdfCreateManifestFile: TXMLDocument;
AddFileEntry('manifest.rdf', 'application/rdf+xml');
AddFileEntry('styles.xml', 'text/xml');
AddFileEntry('meta.xml', 'text/xml');
AddFileEntry('Thumbnails/thumbnail.png', 'image/png');
{ AddFileEntry('Thumbnails/thumbnail.png', 'image/png');
AddFileEntry('Thumbnails/');

}

{ TODO : Configurations2 seems to be an OpenOffice specific directory. }
AddFileEntry('Configurations2/accelerator/current.xml');
Expand Down Expand Up @@ -2266,7 +2290,13 @@ class procedure TOdfDocument.WritePackage(DestFile: String;
nsSet:=[];
case f of
ofManifestRdf : vDoc:=OdfCreateManifestRdfFile;
ofManifest : vDoc:=OdfCreateManifestFile;
ofManifest : begin
if Assigned(AOdf.Manifest)
then
vDoc:=AOdf.Manifest
else
vDoc:=OdfCreateManifestFile;
end
else
begin
vDoc:=TXMLDocument.Create;
Expand Down Expand Up @@ -2319,7 +2349,101 @@ class procedure TOdfDocument.WritePackage(DestFile: String;

z.Entries.AddFileEntry(ATempDir + vFilename, vFilename);

vDoc.Free;
if (f<>ofManifest) // ?? or ( (f=ofManifest) and (AOdf.Manifest=nil))
then
vDoc.Free;
end;

procedure UpdateManifest(ASubDir, AFileName: string);
var
vNode: TDOMNode;
vElement: TDOMElement;
vMediaType: string;
begin
if not Assigned(AOdf.Manifest)
then
begin
{ TODO : Create manifest }
end;

ASubDir:=ExcludeTrailingPathDelimiter(ASubDir);

vNode:=AOdf.Manifest.DocumentElement.FirstChild;
while Assigned(vNode) do
begin
if (vNode is TDOMElement)
then
begin
vElement:=(vNode as TDOMElement);

if TOdfElement.SameType(vElement, oetManifestFileEntry) and
(TOdfElement(vElement).GetAttributeString(oatManifestFullPath) = ASubDir + '/' + AFileName)
then
break;
end;

vElement:=nil;

vNode:=vNode.NextSibling;
end;

if vElement=nil
then
begin
vElement:=TOdfElement.CreateDomElement(oetManifestFileEntry, AOdf.Manifest,
oatManifestFullPath, ASubDir + '/' + AFileName);


{ TODO : The Discovering of media type should have a dedicated procedure/classes }
vMediaType:=ExtractFileExt(AFileName);
if vMediaType='jpg'
then
vMediaType:='jpeg';


if (vMediaType='jpeg') or (vMediaType='png')
then
vMediaType:='image/' + vMediaType;

TOdfElement(vElement).SetAttribute(oatManifestMediaType, vMediaType);

AOdf.Manifest.DocumentElement.AppendChild(vElement);
end;

end;

procedure AddFilesToZipper(ASubDir: string);
var
FileInfo : TSearchRec;
vBaseDir, vFile: string;
begin
vBaseDir:=IncludeTrailingPathDelimiter(AOdf.FTempDir);

if (AOdf.FTempDir='') or (not DirectoryExistsUTF8(vBaseDir + ASubDir))
then
exit;

ASubDir:=IncludeTrailingPathDelimiter(ASubDir);

if FindFirst (vBaseDir + ASubDir + '*',faAnyFile,FileInfo)=0
then
begin
repeat
With FileInfo do
begin
if (Attr and faDirectory) = faDirectory
then
Continue;

vFile:=vBaseDir + ASubDir + Name;
zfe:=z.Entries.AddFileEntry(vFile, ASubDir + Name);
//(zfe as TZipFileEntry).CompressionLevel:=Tcompressionlevel.clnone;

UpdateManifest(ASubDir, Name);
end;
until FindNext(FileInfo)<>0;
FindClose(FileInfo);
end;
end;

begin
Expand All @@ -2345,6 +2469,11 @@ class procedure TOdfDocument.WritePackage(DestFile: String;

vBodyStyles:=AOdf.StylesUsed(AOdf.Body);

{ TODO : List and extract filenames using XPath, avoiding hardcoded directories.
Example Element: <draw:image xlink:href="Pictures/12345.jpg" }
AddFilesToZipper('Pictures');
AddFilesToZipper('Thumbnails');

for f in TOdfXmlFiles do
begin
WriteFileToDisk;
Expand Down Expand Up @@ -2517,10 +2646,34 @@ procedure TOdfDocument.FindOdfRootElements;
FBody:=OdfGetElement(oetOfficeBody,e);
end;
end;

procedure TOdfDocument.ResetRootElements;
begin
FMeta:=nil;
FSettings:=nil;
FScripts:=nil;
FFontFaceDecls:=nil;
FStyles:=nil;
FAutomaticStyles:=nil;
FMasterStyles:=nil;

FBody:=nil;

if Assigned(FManifest)
then
FManifest.Free;

FManifest:=nil;
FManifestRdf:=nil;
end;

constructor TOdfDocument.Create;
begin
inherited Create;

FTempDir:='';
FRemoveTempDir:=true;

InitXmlDocument;
end;

Expand All @@ -2529,6 +2682,14 @@ destructor TOdfDocument.Destroy;
FXPathNsResolver.Free;
FXmlDocument.Free;

if Assigned(FManifest)
then
FManifest.Free;

if FRemoveTempDir and DirectoryExistsUTF8(FTempDir)
then
RemoveDirUTF8(FTempDir);

inherited Destroy;
end;

Expand Down Expand Up @@ -2629,7 +2790,7 @@ class function TOdfDocument.LoadFromZipFile(AFilename, TempDir: string): TOdfDoc

result.MimeType:=mt;

RemoveDirUTF8(TempDir);
Result.FTempDir:=TempDir;
end;

class function TOdfDocument.CreateFromXml(ADoc: TXMLDocument): TOdfDocument;
Expand Down

0 comments on commit da0ca9b

Please sign in to comment.