blob: 3507586ed91a5be7c879322b98a2d6e78fc04bff [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "DFPlatform.h"
#include "ODFPackage.h"
#include "DFDOM.h"
#include "DFXML.h"
#include "DFString.h"
#include "DFFilesystem.h"
#include "DFCommon.h"
#include <stdlib.h>
#include <string.h>
static DFDocument *createDocument(Tag rootTag, Tag childTag)
{
DFDocument *doc = DFDocumentNewWithRoot(rootTag);
DFCreateChildElement(doc->root,childTag);
return doc;
}
static DFDocument *readDocument(ODFPackage *package, const char *filename, DFError **error)
{
DFDocument *doc = DFParseXMLStorage(package->storage,filename,error);
if (doc == NULL) {
DFErrorFormat(error,"%s: %s",filename,DFErrorMessage(error));
return NULL;
}
return doc;
}
static ODFManifest *readManifest(ODFPackage *package, DFError **error)
{
DFDocument *manifestDoc = DFParseXMLStorage(package->storage,"META-INF/manifest.xml",error);
if (manifestDoc == NULL) {
DFErrorFormat(error,"META-INF/manifest.xml: %s",DFErrorMessage(error));
return NULL;
}
return ODFManifestNewWithDoc(manifestDoc);
}
static int writeDocument(ODFPackage *package, DFDocument *doc, NamespaceID defaultNS,
const char *filename, DFError **error)
{
int ok = DFSerializeXMLStorage(doc,defaultNS,0,package->storage,filename,error);
if (!ok)
DFErrorFormat(error,"%s: %s",filename,DFErrorMessage(error));
return ok;
}
static int writeString(ODFPackage *package, const char *str, const char *filename, DFError **error)
{
DFBuffer *buf = DFBufferNew();
DFBufferAppendString(buf,str);
int ok = DFBufferWriteToStorage(buf,package->storage,filename,error);
DFBufferRelease(buf);
if (!ok)
DFErrorFormat(error,"%s: %s",filename,DFErrorMessage(error));
return ok;
}
ODFPackage *ODFPackageOpenNew(DFStorage *storage, DFError **error)
{
ODFPackage *package = (ODFPackage *)xcalloc(1,sizeof(ODFPackage));
package->retainCount = 1;
package->storage = DFStorageRetain(storage);
// Create XML documents
package->contentDoc = createDocument(OFFICE_DOCUMENT_CONTENT,OFFICE_BODY);
package->metaDoc = createDocument(OFFICE_DOCUMENT_META,OFFICE_META);
package->settingsDoc = createDocument(OFFICE_DOCUMENT_SETTINGS,OFFICE_SETTINGS);
package->stylesDoc = createDocument(OFFICE_DOCUMENT_STYLES,OFFICE_STYLES);
// Create manifst
package->manifest = ODFManifestNew();
ODFManifestAddEntry(package->manifest,"/","application/vnd.oasis.opendocument.text","1.2");
ODFManifestAddEntry(package->manifest,"content.xml","text/xml",NULL);
ODFManifestAddEntry(package->manifest,"meta.xml","text/xml",NULL);
ODFManifestAddEntry(package->manifest,"settings.xml","text/xml",NULL);
ODFManifestAddEntry(package->manifest,"styles.xml","text/xml",NULL);
// Setup ODF objects
package->sheet = ODFSheetNew(package->stylesDoc,package->contentDoc);
return package;
}
ODFPackage *ODFPackageOpenFrom(DFStorage *storage, DFError **error)
{
ODFPackage *package = (ODFPackage *)xcalloc(1,sizeof(ODFPackage));
package->retainCount = 1;
package->storage = DFStorageRetain(storage);
// Read XML documents
if ((package->contentDoc = readDocument(package,"content.xml",error)) == NULL)
goto end;
if ((package->metaDoc = readDocument(package,"meta.xml",error)) == NULL)
goto end;
if ((package->settingsDoc = readDocument(package,"settings.xml",error)) == NULL)
goto end;
if ((package->stylesDoc = readDocument(package,"styles.xml",error)) == NULL)
goto end;
// Read manifest
if ((package->manifest = readManifest(package,error)) == NULL)
goto end;
// Setup ODF objects
package->sheet = ODFSheetNew(package->stylesDoc,package->contentDoc);
return package;
end:
ODFPackageRelease(package);
return NULL;
}
ODFPackage *ODFPackageRetain(ODFPackage *package)
{
if (package != NULL)
package->retainCount++;
return package;
}
void ODFPackageRelease(ODFPackage *package)
{
if ((package == NULL) || (--package->retainCount > 0))
return;
DFStorageRelease(package->storage);
ODFManifestRelease(package->manifest);
ODFSheetRelease(package->sheet);
DFDocumentRelease(package->contentDoc);
DFDocumentRelease(package->metaDoc);
DFDocumentRelease(package->settingsDoc);
DFDocumentRelease(package->stylesDoc);
free(package);
}
int ODFPackageSave(ODFPackage *package, DFError **error)
{
if (!writeDocument(package,package->contentDoc,NAMESPACE_NULL,"content.xml",error))
return 0;
if (!writeDocument(package,package->metaDoc,NAMESPACE_NULL,"meta.xml",error))
return 0;
if (!writeDocument(package,package->settingsDoc,NAMESPACE_NULL,"settings.xml",error))
return 0;
if (!writeDocument(package,package->stylesDoc,NAMESPACE_NULL,"styles.xml",error))
return 0;
if (!writeDocument(package,package->manifest->doc,NAMESPACE_NULL,"META-INF/manifest.xml",error))
return 0;
if (!writeString(package,"application/vnd.oasis.opendocument.text","mimetype",error))
return 0;
if (!DFStorageSave(package->storage,error))
return 0;
return 1;
}