Commit 26e3bed1 authored by Elen.Subbotina's avatar Elen.Subbotina Committed by Alexander Trofimov

подключена новая конвертация в ods

git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@55493 954022d7-b5bf-4e40-9824-e11837661b57
parent 366325f5
......@@ -45,6 +45,7 @@ namespace ASCOfficeEWSEditor.Editor.FileFormats
case Format.XLS:
{
XlsxSaver.Save(wb.GetXmlDocument(), temp_dir_path, wb.BinaryDataStorage);
ASCOfficeXlsFile.CXlsFileClass converter = new ASCOfficeXlsFile.CXlsFileClass();
converter.SaveToFile(path, temp_dir_path, "");
break;
......@@ -59,14 +60,10 @@ namespace ASCOfficeEWSEditor.Editor.FileFormats
}
case Format.ODS:
{
XlsxSaver saver = new XlsxSaver(wb.GetXmlDocument(), wb.BinaryDataStorage);
ASCOfficeUtils.COfficeUtilsClass ooxArchiver = new ASCOfficeUtils.COfficeUtilsClass();
if (!ooxArchiver.CompressFilesFromMemory(temp_dir_path + ".xlsx", saver, -1))
{
throw new Events.ReportableException(new Events.InternalError("Compression to \"" + path + "\" failed for unknown reason"));
}
XlsxSaver.Save(wb.GetXmlDocument(), temp_dir_path, wb.BinaryDataStorage);
ODSConverter.ODSConverter.ConvertFile(temp_dir_path + ".xlsx", path, CleverAge.OdfConverter.OdfConverterLib.ConversionDirection.XlsxToOds);
ASCOfficeOdfFileWLib.COfficeOdfFileWClass converter = new ASCOfficeOdfFileWLib.COfficeOdfFileWClass();
converter.SaveToFile(path, temp_dir_path, "");
break;
}
default:
......
using System;
using System.IO;
using OdfConverter.OdfConverterLib;
using CleverAge.OdfConverter.OdfConverterLib;
namespace ASCOfficeEWSEditor.Editor.ODSConverter
{
public class ConverterFactory
{
private static AbstractConverter spreadsheetInstance;
public static AbstractConverter Instance(ConversionDirection transformDirection)
{
if (spreadsheetInstance == null)
{
spreadsheetInstance = new CleverAge.OdfConverter.Spreadsheet.Converter();
}
return spreadsheetInstance;
}
}
public class ODSConverter
{
#region Constants
private const string GENERATOR = "";
private const int NOT_CONVERTED = 0;
private const int VALIDATED = 1;
private const int NOT_VALIDATED = 2;
#endregion
#region Methods
static public void ConvertFile(string InputFileName, string OutputFileName, ConversionDirection oDirection)
{
ConversionOptions options = new ConversionOptions();
options.InputFullName = InputFileName;
options.OutputFullName = OutputFileName;
options.Generator = GENERATOR;
options.InputFullName = Path.GetFullPath(options.InputFullName);
options.ForceOverwrite = true;
options.ConversionDirection = oDirection;
options.InputBaseFolder = Path.GetDirectoryName(options.InputFullName);
options.OutputBaseFolder = Path.GetDirectoryName(options.OutputFullName);
proceed(options);
}
static private void proceed(ConversionOptions options)
{
if (!File.Exists(options.InputFullName))
{
return;
}
options.DocumentType = DocumentType.Document;
if (File.Exists(options.OutputFullName) && !options.ForceOverwrite)
{
return;
}
proceedSingleFile(options);
FileInfo oFileInfo = new FileInfo(options.OutputFullName);
System.Security.AccessControl.FileSystemAccessRule oRule = new System.Security.AccessControl.FileSystemAccessRule("Everyone",
System.Security.AccessControl.FileSystemRights.FullControl,
System.Security.AccessControl.AccessControlType.Allow);
System.Security.AccessControl.FileSecurity oFileSecurity = oFileInfo.GetAccessControl();
oFileSecurity.AddAccessRule(oRule);
oFileInfo.SetAccessControl(oFileSecurity);
}
static private int proceedSingleFile(ConversionOptions options)
{
bool converted = false;
converted = convertFile(options.InputFullName, options.OutputFullName, options);
if (!converted)
{
Environment.ExitCode = 1;
return NOT_CONVERTED;
}
else
return VALIDATED;
}
static private bool convertFile(string input, string output, ConversionOptions options)
{
AbstractConverter converter = ConverterFactory.Instance(options.ConversionDirection);
converter.DirectTransform = options.ConversionDirection == ConversionDirection.OdsToXlsx;
converter.Transform(input, output, options);
return true;
}
#endregion
}
}
/*
* Copyright (c) 2008 DIaLOGIKa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of copyright holders, nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace CleverAge.OdfConverter.OdfConverterLib
{
public enum LogLevel
{
Debug = 1,
Info = 2,
Warning = 3,
Error = 4
}
public class ConversionReport
{
private StreamWriter _writer = null;
private LogLevel _level = LogLevel.Info;
public ConversionReport(string filename, LogLevel level)
{
this._level = level;
if (filename != null)
{
this._writer = new StreamWriter(new FileStream(filename, FileMode.Create, FileAccess.Write));
Console.WriteLine("Using report file: " + filename);
}
}
public void AddComment(string message, params object[] args)
{
string text = "*** " + string.Format(message, args);
if (this._writer != null)
{
this._writer.WriteLine(text);
this._writer.Flush();
}
Console.WriteLine(text);
}
public void LogError(string filename, string message, params object[] args)
{
addLog(filename, string.Format(message, args), LogLevel.Error);
}
public void LogWarning(string filename, string message, params object[] args)
{
addLog(filename, string.Format(message, args), LogLevel.Warning);
}
public void LogInfo(string filename, string message, params object[] args)
{
addLog(filename, string.Format(message, args), LogLevel.Info);
}
public void LogDebug(string filename, string message, params object[] args)
{
addLog(filename, string.Format(message, args), LogLevel.Debug);
}
private void addLog(string filename, string message, LogLevel level)
{
if (level >= this._level)
{
string label = null;
switch (level)
{
case LogLevel.Error:
label = "ERROR";
break;
case LogLevel.Warning:
label = "WARNING";
break;
case LogLevel.Info:
label = "INFO";
break;
default:
label = "DEBUG";
break;
}
string text = "[" + label + "]" + "[" + filename + "] " + message;
if (this._writer != null)
{
this._writer.WriteLine(text);
this._writer.Flush();
}
Console.WriteLine(text);
}
}
public void Close()
{
if (this._writer != null)
{
this._writer.Close();
this._writer = null;
}
}
}
}
using System;
using System.IO;
using System.Collections;
using System.Text;
using System.Reflection;
using System.Xml;
namespace CleverAge.OdfConverter.OdfConverterLib
{
/// <summary>
/// An XmlUrlResolver for embedded resources.
/// Looks for resources in the specified assemby first, then in the 'common' assembly.
/// </summary>
public class EmbeddedResourceResolver : XmlUrlResolver
{
private const string ODFToOOX_LOCATION = ".resources.odf2oox.";
private const string OOXToODF_LOCATION = ".resources.oox2odf.";
public const string ASSEMBLY_URI_SCHEME = "assembly";
public const string ASSEMBLY_URI_HOST = "localhost";
private Assembly appAssembly;
private Assembly defaultAssembly;
private string appNamespace;
private string defaultNamespace;
private bool isDirectTransform;
private string resourceLocation;
/// <summary>
/// Constructor
/// </summary>
/// <param name="assembly">The assembly embedding resources</param>
/// <param name="prefix">The prefix used to locate resources within the assembly</param>
/// <param name="isDirectTransform">Is the direction of conversion direct</param>
public EmbeddedResourceResolver(Assembly appAssembly, string appNamespace, bool isDirectTransform)
:
this(appAssembly, appNamespace)
{
this.isDirectTransform = isDirectTransform;
}
public EmbeddedResourceResolver(Assembly appAssembly, string appNamespace, string resourceLocation, bool isDirectTransform)
:
this(appAssembly, appNamespace, isDirectTransform)
{
this.resourceLocation = resourceLocation;
}
public EmbeddedResourceResolver(Assembly appAssembly, string appNamespace)
{
this.appAssembly = appAssembly;
//this.appNamespace = appNamespace;
//this.defaultNamespace = this.GetType().Namespace;
this.appNamespace = "ASCOfficeEWSEditor.Editor.ODSConverter.SpreadsheetConverter";
this.defaultNamespace = "ASCOfficeEWSEditor.Editor.ODSConverter.OdfConverterLib";
this.defaultAssembly = Assembly.GetExecutingAssembly();
}
public bool IsDirectTransform
{
set { this.isDirectTransform = value; }
}
public override Uri ResolveUri(Uri baseUri, String relativeUri)
{
// Console.WriteLine("ResolveUri: baseUri="+baseUri+" relativeUri="+relativeUri);
if (baseUri == null && !relativeUri.Contains("://"))
{
return new Uri(ASSEMBLY_URI_SCHEME + "://" + ASSEMBLY_URI_HOST + "/" + relativeUri);
}
else if (relativeUri.Contains("DTD"))
{
return new Uri(ASSEMBLY_URI_SCHEME + "://" + ASSEMBLY_URI_HOST + "/dummy.dtd");
}
else
{
return base.ResolveUri(baseUri, relativeUri);
}
}
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
if (ASSEMBLY_URI_SCHEME.Equals(absoluteUri.Scheme))
{
string location = null;
if (this.resourceLocation == null)
{
location = this.isDirectTransform ? ODFToOOX_LOCATION : OOXToODF_LOCATION;
}
else
{
location = this.resourceLocation;
}
string resource = location + absoluteUri.OriginalString.Remove(0, ASSEMBLY_URI_SCHEME.Length + ASSEMBLY_URI_HOST.Length + 4).Replace("/", ".");
Stream stream = this.appAssembly.GetManifestResourceStream(this.appNamespace + resource);
if (stream != null)
{
return stream;
}
// fallback to the shared embedded resources
else
{
stream = this.defaultAssembly.GetManifestResourceStream(this.defaultNamespace + resource);
if (stream != null)
{
return stream;
}
}
}
// use default behaviour instead
return base.GetEntity(absoluteUri, role, ofObjectToReturn);
}
public Stream GetInnerStream(String fileName)
{
string location = null;
if (this.resourceLocation == null)
{
location = this.isDirectTransform ? ODFToOOX_LOCATION : OOXToODF_LOCATION;
}
else
{
location = this.resourceLocation;
}
string path = this.appNamespace + location;
return this.appAssembly.GetManifestResourceStream(path + fileName);
}
public static Stream GetSharedResource(string filename)
{
Assembly a = Assembly.GetExecutingAssembly();
return a.GetManifestResourceStream(a.GetName() + ".resources." + filename);
}
}
}
using System;
using System.Runtime.Serialization;
namespace CleverAge.OdfConverter.OdfConverterLib
{
/// <summary>Thrown whenever an error occurs during the build.</summary>
[Serializable]
public class EncryptedDocumentException : Exception
{
/// <summary>Constructs an exception with no descriptive information.</summary>
public EncryptedDocumentException()
: base()
{
}
/// <summary>Constructs an exception with a descriptive message.</summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public EncryptedDocumentException(String message)
: base(message)
{
}
/// <summary>Constructs an exception with a descriptive message and a reference to the instance of the <c>Exception</c> that is the root cause of the this exception.</summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">An instance of <c>Exception</c> that is the cause of the current Exception. If <paramref name="innerException"/> is non-null, then the current Exception is raised in a catch block handling <paramref>innerException</paramref>.</param>
public EncryptedDocumentException(String message, Exception innerException)
: base(message, innerException)
{
}
/// <summary>Initializes a new instance of the exception class with serialized data.</summary>
/// <param name="info">The object that holds the serialized object data.</param>
/// <param name="context">The contextual information about the source or destination.</param>
public EncryptedDocumentException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace OdfConverter.Transforms
{
public class PointCoordinates
{
private double _x, _y, _z;
public double X
{
get
{
return _x;
}
}
public double Y
{
get
{
return _y;
}
}
public double Z
{
get
{
return _z;
}
}
public PointCoordinates(double x, double y)
{
_x = x;
_y = y;
_z = 1;
}
public PointCoordinates(double x, double y, double z)
{
_x = x;
_y = y;
_z = z;
}
}
public class TransformationMatrix
{
double _v11, _v12, _v13;
double _v21, _v22, _v23;
double _v31, _v32, _v33;
public TransformationMatrix(double v11, double v12, double v13,
double v21, double v22, double v23,
double v31, double v32, double v33)
{
_v11 = v11;
_v12 = v12;
_v13 = v13;
_v21 = v21;
_v22 = v22;
_v23 = v23;
_v31 = v31;
_v32 = v32;
_v33 = v33;
}
public static TransformationMatrix Identity
{
get
{
return new TransformationMatrix(1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0);
}
}
public PointCoordinates Transform(PointCoordinates pt)
{
return new PointCoordinates(_v11 * pt.X + _v12 * pt.Y + _v13 * pt.Z,
_v21 * pt.X + _v22 * pt.Y + _v23 * pt.Z,
_v31 * pt.X + _v32 * pt.Y + _v33 * pt.Z);
}
// _v11, _v12, _v13
// _v21, _v22, _v23
// _v31, _v32, _v33
// _v11, _v12, _v13
// _v21, _v22, _v23
// _v31, _v32, _v33
public static TransformationMatrix operator *(TransformationMatrix m1, TransformationMatrix m2)
{
return new TransformationMatrix(
m1._v11 * m2._v11 + m1._v12 * m2._v21 + m1._v13 * m2._v31,
m1._v11 * m2._v12 + m1._v12 * m2._v22 + m1._v13 * m2._v32,
m1._v11 * m2._v13 + m1._v12 * m2._v23 + m1._v13 * m2._v33,
m1._v21 * m2._v11 + m1._v22 * m2._v21 + m1._v23 * m2._v31,
m1._v21 * m2._v12 + m1._v22 * m2._v22 + m1._v23 * m2._v32,
m1._v21 * m2._v13 + m1._v22 * m2._v23 + m1._v23 * m2._v33,
m1._v31 * m2._v11 + m1._v32 * m2._v21 + m1._v33 * m2._v31,
m1._v31 * m2._v12 + m1._v32 * m2._v22 + m1._v33 * m2._v32,
m1._v31 * m2._v13 + m1._v32 * m2._v23 + m1._v33 * m2._v33);
}
}
}
\ No newline at end of file
using System;
using System.Runtime.Serialization;
namespace CleverAge.OdfConverter.OdfConverterLib
{
/// <summary>Thrown whenever an error occurs during the build.</summary>
[Serializable]
public class NotAnOdfDocumentException : Exception
{
/// <summary>Constructs an exception with no descriptive information.</summary>
public NotAnOdfDocumentException()
: base()
{
}
/// <summary>Constructs an exception with a descriptive message.</summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public NotAnOdfDocumentException(String message)
: base(message)
{
}
/// <summary>Constructs an exception with a descriptive message and a reference to the instance of the <c>Exception</c> that is the root cause of the this exception.</summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">An instance of <c>Exception</c> that is the cause of the current Exception. If <paramref name="innerException"/> is non-null, then the current Exception is raised in a catch block handling <paramref>innerException</paramref>.</param>
public NotAnOdfDocumentException(String message, Exception innerException)
: base(message, innerException)
{
}
/// <summary>Initializes a new instance of the exception class with serialized data.</summary>
/// <param name="info">The object that holds the serialized object data.</param>
/// <param name="context">The contextual information about the source or destination.</param>
public NotAnOdfDocumentException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}
using System;
using System.Runtime.Serialization;
namespace CleverAge.OdfConverter.OdfConverterLib
{
/// <summary>Thrown whenever an error occurs during the build.</summary>
[Serializable]
public class NotAnOoxDocumentException : Exception
{
/// <summary>Constructs an exception with no descriptive information.</summary>
public NotAnOoxDocumentException()
: base()
{
}
/// <summary>Constructs an exception with a descriptive message.</summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public NotAnOoxDocumentException(String message)
: base(message)
{
}
/// <summary>Constructs an exception with a descriptive message and a reference to the instance of the <c>Exception</c> that is the root cause of the this exception.</summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">An instance of <c>Exception</c> that is the cause of the current Exception. If <paramref name="innerException"/> is non-null, then the current Exception is raised in a catch block handling <paramref>innerException</paramref>.</param>
public NotAnOoxDocumentException(String message, Exception innerException)
: base(message, innerException)
{
}
/// <summary>Initializes a new instance of the exception class with serialized data.</summary>
/// <param name="info">The object that holds the serialized object data.</param>
/// <param name="context">The contextual information about the source or destination.</param>
public NotAnOoxDocumentException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace CleverAge.OdfConverter.OdfConverterLib
{
public class OdfEventArgs : EventArgs
{
private string message;
public OdfEventArgs(string message)
{
this.message = message;
}
public string Message
{
get
{
return message;
}
}
}
}
using System;
using OdfConverter.Transforms;
namespace OdfConverter.Transforms.Test
{
public class OoxShape
{
// unused
//static double Scale = 10.0;
//static int DeltaX = 0;
//static int DeltaY = 0;
OoxTransform _transform;
public OoxTransform OoxTransform
{
get
{
return _transform;
}
}
public OoxShape(OoxTransform transform)
{
_transform = transform;
}
}
}
\ No newline at end of file
/*
* Copyright (c) 2006, Clever Age
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Clever Age nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.IO;
using System.Collections;
using System.Text;
using System.Reflection;
using System.Xml;
namespace CleverAge.OdfConverter.OdfConverterLib
{
/// <summary>
/// An XmlUrlResolver for embedded resources.
/// </summary>
public class SharedXmlUrlResolver : XmlUrlResolver
{
private Assembly shared;
private bool isDirectTransform;
public SharedXmlUrlResolver(bool isDirectTransform)
{
this.shared = Assembly.GetExecutingAssembly();
this.isDirectTransform = isDirectTransform;
}
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
if (!File.Exists(absoluteUri.LocalPath))
{
// look into shared embedded resources
string resource = absoluteUri.OriginalString.Substring(absoluteUri.OriginalString.LastIndexOf('/') + 1);
string path = isDirectTransform ? this.GetType().Namespace + ".resources.odf2oox." + resource :
this.GetType().Namespace + ".resources.oox2odf." + resource;
return this.shared.GetManifestResourceStream(path);
}
else
{
return base.GetEntity(absoluteUri, role, ofObjectToReturn);
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<!--
* Copyright (c) 2006, Clever Age
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Clever Age nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<source xmlns="urn:odf"/>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment