Return-Path: X-Original-To: apmail-chemistry-commits-archive@www.apache.org Delivered-To: apmail-chemistry-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id EC0071860D for ; Mon, 20 Jul 2015 08:49:09 +0000 (UTC) Received: (qmail 70842 invoked by uid 500); 20 Jul 2015 08:49:00 -0000 Delivered-To: apmail-chemistry-commits-archive@chemistry.apache.org Received: (qmail 70790 invoked by uid 500); 20 Jul 2015 08:49:00 -0000 Mailing-List: contact commits-help@chemistry.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@chemistry.apache.org Delivered-To: mailing list commits@chemistry.apache.org Received: (qmail 70758 invoked by uid 99); 20 Jul 2015 08:49:00 -0000 Received: from eris.apache.org (HELO hades.apache.org) (140.211.11.105) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 20 Jul 2015 08:49:00 +0000 Received: from hades.apache.org (localhost [127.0.0.1]) by hades.apache.org (ASF Mail Server at hades.apache.org) with ESMTP id EFC18AC0A50 for ; Mon, 20 Jul 2015 08:48:59 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r1691890 [4/14] - in /chemistry/portcmis: ./ PortCMIS/ PortCMIS/Properties/ PortCMIS/binding/ PortCMIS/binding/atompub/ PortCMIS/binding/browser/ PortCMIS/binding/browser/json/ PortCMIS/client/ PortCMIS/const/ PortCMIS/data/ PortCMIS/enum/ ... Date: Mon, 20 Jul 2015 08:48:59 -0000 To: commits@chemistry.apache.org From: fmui@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20150720084859.EFC18AC0A50@hades.apache.org> Added: chemistry/portcmis/PortCMIS/binding/atompub/XmlUtils.cs URL: http://svn.apache.org/viewvc/chemistry/portcmis/PortCMIS/binding/atompub/XmlUtils.cs?rev=1691890&view=auto ============================================================================== --- chemistry/portcmis/PortCMIS/binding/atompub/XmlUtils.cs (added) +++ chemistry/portcmis/PortCMIS/binding/atompub/XmlUtils.cs Mon Jul 20 08:48:57 2015 @@ -0,0 +1,281 @@ +/* +* 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. +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using PortCMIS.Enums; +using System.Globalization; +using PortCMIS.Exceptions; + +namespace PortCMIS.Binding.AtomPub +{ + class XmlUtils + { + + // -------------- + // --- writer --- + // -------------- + + /** + * Creates a new XML writer. + */ + public static XmlWriter createWriter(Stream stream) + { + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Encoding = Encoding.UTF8; + return XmlWriter.Create(stream, settings); + } + + /** + * Starts a XML document. + */ + public static void startXmlDocument(XmlWriter writer, string rootLocalName, string rootNamespace) + { + // writer.setPrefix(XmlConstants.PREFIX_ATOM, XmlConstants.NAMESPACE_ATOM); + // writer.setPrefix(XmlConstants.PREFIX_CMIS, XmlConstants.NAMESPACE_CMIS); + // writer.setPrefix(XmlConstants.PREFIX_RESTATOM, XmlConstants.NAMESPACE_RESTATOM); + // writer.setPrefix(XmlConstants.PREFIX_APACHE_CHEMISTY, XmlConstants.NAMESPACE_APACHE_CHEMISTRY); + + writer.WriteStartDocument(); + } + + /** + * Ends a XML document. + */ + public static void endXmlDocument(XmlWriter writer) + { + writer.WriteEndDocument(); + writer.Dispose(); + } + + /** + * Writes a String tag. + */ + public static void write(XmlWriter writer, string prefix, string ns, string tag, string value) + { + if (value == null) + { + return; + } + + if (ns == null) + { + writer.WriteStartElement(tag); + } + else + { + writer.WriteStartElement(prefix, tag, ns); + } + writer.WriteString(value); + writer.WriteEndElement(); + } + + /** + * Writes an Integer tag. + */ + public static void write(XmlWriter writer, string prefix, string ns, string tag, BigInteger? value) + { + if (value == null) + { + return; + } + + write(writer, prefix, ns, tag, ((BigInteger)value).ToString("#", CultureInfo.InvariantCulture)); + } + + /** + * Writes a Decimal tag. + */ + public static void write(XmlWriter writer, String prefix, String ns, String tag, decimal? value) + { + if (value == null) + { + return; + } + + if (ns == null) + { + writer.WriteStartElement(tag); + } + else + { + writer.WriteStartElement(prefix, tag, ns); + } + writer.WriteValue(value); + writer.WriteEndElement(); + } + + /** + * Writes a DateTime tag. + */ + public static void write(XmlWriter writer, String prefix, String ns, String tag, DateTime? value) + { + if (value == null) + { + return; + } + + if (ns == null) + { + writer.WriteStartElement(tag); + } + else + { + writer.WriteStartElement(prefix, tag, ns); + } + writer.WriteValue(value); + writer.WriteEndElement(); + } + + /** + * Writes a Boolean tag. + */ + public static void write(XmlWriter writer, string prefix, string ns, string tag, bool? value) + { + if (value == null) + { + return; + } + + write(writer, prefix, ns, tag, (bool)value ? "true" : "false"); + } + + /** + * Writes an Enum tag. + */ + public static void write(XmlWriter writer, String prefix, String ns, String tag, Enum value) + { + if (value == null) + { + return; + } + + write(writer, prefix, ns, tag, value.GetCmisValue()); + } + + + // --------------- + // ---- parser --- + // --------------- + + /** + * Creates a new XML parser with OpenCMIS default settings. + */ + public static XmlReader createParser(Stream stream) + { + XmlReaderSettings settings = new XmlReaderSettings(); + settings.MaxCharactersInDocument = 0; + settings.CloseInput = true; + return XmlReader.Create(stream, settings); + } + + /** + * Moves the parser to the next element. + */ + public static bool next(XmlReader parser) + { + return parser.Read(); + } + + /** + * Skips a tag or subtree. + */ + public static void skip(XmlReader parser) + { + parser.Skip(); + } + + /** + * Moves the parser to the next start element. + * + * @return true if another start element has been found, + * false otherwise + */ + public static bool findNextStartElemenet(XmlReader parser) + { + while (true) + { + XmlNodeType nodeType = parser.NodeType; + + if (nodeType == XmlNodeType.Element) + { + return true; + } + + if (!parser.Read()) + { + return false; + } + } + } + + /** + * Parses a tag that contains text. + */ + public static String readText(XmlReader parser, int maxLength) + { + StringBuilder sb = new StringBuilder(); + + next(parser); + + while (true) + { + XmlNodeType nodeType = parser.NodeType; + if (nodeType == XmlNodeType.EndElement) + { + break; + } + else if (nodeType == XmlNodeType.Text || nodeType == XmlNodeType.CDATA) + { + char[] buffer = new char[8 * 1024]; + + int len; + while ((len = parser.ReadValueChunk(buffer, 0, buffer.Length)) > 0) + { + if (sb.Length + len > maxLength) + { + throw new CmisInvalidArgumentException("String limit exceeded!"); + } + + sb.Append(buffer, 0, len); + } + } + else if (nodeType == XmlNodeType.Element) + { + throw new CmisInvalidArgumentException("Unexpected tag: " + parser.Name); + } + + if (!next(parser)) + { + break; + } + } + + next(parser); + + return sb.ToString(); + } + } +} Added: chemistry/portcmis/PortCMIS/binding/atompub/XmlWalker.cs URL: http://svn.apache.org/viewvc/chemistry/portcmis/PortCMIS/binding/atompub/XmlWalker.cs?rev=1691890&view=auto ============================================================================== --- chemistry/portcmis/PortCMIS/binding/atompub/XmlWalker.cs (added) +++ chemistry/portcmis/PortCMIS/binding/atompub/XmlWalker.cs Mon Jul 20 08:48:57 2015 @@ -0,0 +1,289 @@ +/* +* 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. +*/ + +using PortCMIS.Binding.AtomPub; +using PortCMIS.Data.Extensions; +using PortCMIS.Exceptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using PortCMIS.Enums; +using System.Globalization; + +namespace PortCMIS.Binding.AtomPub +{ + internal abstract class XMLWalker + { + + public T walk(XmlReader parser) + { + T result = prepareTarget(parser, parser.LocalName, parser.NamespaceURI); + + XmlUtils.next(parser); + + // walk through all tags + while (true) + { + XmlNodeType nodeType = parser.NodeType; + if (nodeType == XmlNodeType.Element) + { + if (!read(parser, parser.LocalName, parser.NamespaceURI, result)) + { + if (result is IExtensionsData) + { + handleExtension(parser, (IExtensionsData)result); + } + else + { + XmlUtils.skip(parser); + } + } + } + else if (nodeType == XmlNodeType.EndElement) + { + break; + } + else + { + if (!XmlUtils.next(parser)) + { + break; + } + } + } + + XmlUtils.next(parser); + + return result; + } + + protected bool isCmisNamespace(string ns) + { + return XmlConstants.NAMESPACE_CMIS == ns; + } + + protected bool isAtomNamespace(string ns) + { + return XmlConstants.NAMESPACE_ATOM == ns; + } + + protected bool isTag(string name, string tag) + { + return name == tag; + } + + protected void handleExtension(XmlReader parser, IExtensionsData extData) + { + IList extensions = extData.Extensions; + if (extensions == null) + { + extensions = new List(); + extData.Extensions = extensions; + } + + if (extensions.Count + 1 > XMLConstraints.MAX_EXTENSIONS_WIDTH) + { + throw new CmisInvalidArgumentException("Too many extensions!"); + } + + extensions.Add(handleExtensionLevel(parser, 0)); + } + + private ICmisExtensionElement handleExtensionLevel(XmlReader parser, int level) + { + string localname = parser.Name; + string ns = parser.NamespaceURI; + IDictionary attributes = null; + StringBuilder sb = new StringBuilder(); + IList children = null; + + if (parser.HasAttributes) + { + attributes = new Dictionary(); + + while (parser.MoveToNextAttribute()) + { + attributes.Add(parser.Name, parser.Value); + } + } + + XmlUtils.next(parser); + + while (true) + { + XmlNodeType nodeType = parser.NodeType; + if (nodeType == XmlNodeType.EndElement) + { + break; + } + else if (nodeType == XmlNodeType.Text) + { + string s = parser.Value; + if (s != null) + { + if (sb.Length + s.Length > XMLConstraints.MAX_STRING_LENGTH) + { + throw new CmisInvalidArgumentException("String limit exceeded!"); + } + sb.Append(s); + } + } + else if (nodeType == XmlNodeType.Element) + { + if (level + 1 > XMLConstraints.MAX_EXTENSIONS_DEPTH) + { + throw new CmisInvalidArgumentException("Extensions tree too deep!"); + } + + if (children == null) + { + children = new List(); + } + + if (children.Count + 1 > XMLConstraints.MAX_EXTENSIONS_WIDTH) + { + throw new CmisInvalidArgumentException("Extensions tree too wide!"); + } + + children.Add(handleExtensionLevel(parser, level + 1)); + + continue; + } + + if (!XmlUtils.next(parser)) + { + break; + } + } + + XmlUtils.next(parser); + + CmisExtensionElement element = new CmisExtensionElement() + { + Name = localname, + Namespace = ns, + Attributes = attributes + }; + + if (children != null) + { + element.Children = children; + } + else + { + element.Value = sb.ToString(); + } + + return element; + } + + protected IList addToList(IList list, S value) + { + if (list == null) + { + list = new List(); + } + list.Add(value); + + return list; + } + + protected string readText(XmlReader parser) + { + return XmlUtils.readText(parser, XMLConstraints.MAX_STRING_LENGTH); + } + + protected bool? readBoolean(XmlReader parser) + { + parser.MoveToContent(); + + try + { + return parser.ReadContentAsBoolean(); + } + catch (Exception e) + { + throw new CmisInvalidArgumentException("Invalid boolean value!", e); + } + } + + protected BigInteger readInteger(XmlReader parser) + { + string value = readText(parser); + + try + { + return BigInteger.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + } + catch (Exception e) + { + throw new CmisInvalidArgumentException("Invalid integer value!", e); + } + } + + protected decimal readDecimal(XmlReader parser) + { + parser.MoveToContent(); + + try + { + return parser.ReadContentAsDecimal(); + } + catch (Exception e) + { + throw new CmisInvalidArgumentException("Invalid decimal value!", e); + } + } + + protected DateTime readDateTime(XmlReader parser) + { + string value = readText(parser); + + DateTime result = DateTimeHelper.ParseISO8601(value); + if (result == null) + { + throw new CmisInvalidArgumentException("Invalid datetime value!"); + } + + return result; + } + + protected E readEnum(XmlReader parser) + { + return readText(parser).GetCmisEnum(); + } + + protected abstract T prepareTarget(XmlReader parser, string localname, string ns); + + protected abstract bool read(XmlReader parser, string localname, string ns, T target); + + } + + internal class XMLConstraints + { + public const int MAX_STRING_LENGTH = 100 * 1024; + + public const int MAX_EXTENSIONS_WIDTH = 500; + public const int MAX_EXTENSIONS_DEPTH = 20; + } +} \ No newline at end of file