Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <com/sun/star/io/Pipe.hpp>
22 : #include <com/sun/star/xml/xpath/XPathObjectType.hpp>
23 : #include <com/sun/star/xml/dom/XNode.hpp>
24 : #include <com/sun/star/xml/dom/XText.hpp>
25 : #include <com/sun/star/xml/dom/XNodeList.hpp>
26 : #include <com/sun/star/xml/dom/NodeType.hpp>
27 :
28 : #include <rtl/ustrbuf.hxx>
29 : #include <rtl/strbuf.hxx>
30 : #include <comphelper/processfactory.hxx>
31 : #include <comphelper/string.hxx>
32 :
33 : #include <stdio.h>
34 :
35 : #include "serialization_urlencoded.hxx"
36 :
37 : using namespace CSS::uno;
38 : using namespace CSS::io;
39 : using namespace CSS::xml::xpath;
40 : using namespace CSS::xml::dom;
41 :
42 0 : CSerializationURLEncoded::CSerializationURLEncoded()
43 : : m_aFactory(comphelper::getProcessServiceFactory())
44 0 : , m_aPipe(Pipe::create(comphelper::getProcessComponentContext()))
45 : {
46 0 : }
47 :
48 :
49 : /*
50 : rfc2396
51 : reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
52 : "$" | ","
53 : mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
54 : unreserved = alphanum | mark
55 : */
56 0 : sal_Bool CSerializationURLEncoded::is_unreserved(sal_Char c)
57 : {
58 0 : if (comphelper::string::isalnumAscii(c))
59 0 : return sal_True;
60 0 : switch (c) {
61 : case '-':
62 : case '_':
63 : case '.':
64 : case '!':
65 : case '~':
66 : case '*':
67 : case '\'':
68 : case '(':
69 : case ')':
70 0 : return sal_True;
71 : }
72 0 : return sal_False;
73 : }
74 0 : void CSerializationURLEncoded::encode_and_append(const ::rtl::OUString& aString, ::rtl::OStringBuffer& aBuffer)
75 : {
76 0 : ::rtl::OString utf8String = OUStringToOString(aString, RTL_TEXTENCODING_UTF8);
77 0 : const sal_uInt8 *pString = reinterpret_cast< const sal_uInt8 * >( utf8String.getStr() );
78 0 : sal_Char tmpChar[4]; tmpChar[3] = 0;
79 :
80 0 : while( *pString != 0)
81 : {
82 0 : if( *pString < 0x80 )
83 : {
84 0 : if ( is_unreserved(*pString) ) {
85 0 : aBuffer.append(*pString);
86 0 : } else if (*pString == 0x20) {
87 0 : aBuffer.append('+');
88 0 : } else if (*pString == 0x0d && *(pString+1) == 0x0a) {
89 0 : aBuffer.append("%0D%0A");
90 0 : pString++;
91 0 : } else if (*pString == 0x0a) {
92 0 : aBuffer.append("%0D%0A");
93 : } else {
94 0 : snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
95 0 : aBuffer.append(tmpChar);
96 : }
97 : } else {
98 0 : snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
99 0 : aBuffer.append(tmpChar);
100 0 : while (*pString >= 0x80) {
101 : // continuation...
102 0 : pString++;
103 0 : snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
104 0 : aBuffer.append(tmpChar);
105 : }
106 : }
107 0 : pString++;
108 0 : }
109 0 : }
110 :
111 0 : void CSerializationURLEncoded::serialize_node(const Reference< XNode >& aNode)
112 : {
113 : // serialize recursive
114 : // every element node E that has a text child T will be serialized in document order
115 : // <E1>T1<E2>T2</E2></E1><E3>T3</E3> -> E1=T2&E2=T2&E3=T3 (En := local name)
116 :
117 : // this node
118 0 : Reference< XNodeList > aChildList = aNode->getChildNodes();
119 0 : Reference< XNode > aChild;
120 : // is this an element node?
121 0 : if (aNode->getNodeType() == NodeType_ELEMENT_NODE)
122 : {
123 0 : ::rtl::OUString aName = aNode->getNodeName();
124 : // find any text children
125 0 : ::rtl::OUStringBuffer aValue;
126 0 : Reference< XText > aText;
127 0 : for(sal_Int32 i=0; i < aChildList->getLength(); i++)
128 : {
129 0 : aChild = aChildList->item(i);
130 0 : if (aChild->getNodeType() == NodeType_TEXT_NODE)
131 : {
132 0 : aText = Reference< XText >(aChild, UNO_QUERY);
133 0 : aValue.append(aText->getData());
134 : }
135 : }
136 :
137 : // found anything?
138 0 : if (aValue.getLength() > 0)
139 : {
140 0 : ::rtl::OUString aUnencValue = aValue.makeStringAndClear();
141 0 : ::rtl::OStringBuffer aEncodedBuffer;
142 0 : encode_and_append(aName, aEncodedBuffer);
143 0 : aEncodedBuffer.append("=");
144 0 : encode_and_append(aUnencValue, aEncodedBuffer);
145 0 : aEncodedBuffer.append("&");
146 0 : sal_Int8 *pData = (sal_Int8*)aEncodedBuffer.getStr();
147 0 : Sequence< sal_Int8 > sData(pData, aEncodedBuffer.getLength());
148 0 : m_aPipe->writeBytes(sData);
149 0 : }
150 : }
151 :
152 : // element children...
153 0 : for(sal_Int32 i=0; i < aChildList->getLength(); i++)
154 : {
155 0 : aChild = aChildList->item(i);
156 : // if this is an element node, it might be a candidate for serialization
157 0 : if (aChild.is() && aChild->getNodeType() == NodeType_ELEMENT_NODE)
158 0 : serialize_node(aChild);
159 0 : }
160 0 : }
161 :
162 0 : void CSerializationURLEncoded::serialize()
163 : {
164 :
165 : // output stream to the pipe buffer
166 0 : Reference< XOutputStream > out(m_aPipe, UNO_QUERY);
167 :
168 0 : CSS::uno::Reference< CSS::xml::dom::XNode > cur = m_aFragment->getFirstChild();
169 0 : while (cur.is())
170 : {
171 0 : serialize_node(cur);
172 0 : cur = cur->getNextSibling();
173 : }
174 0 : m_aPipe->closeOutput();
175 0 : }
176 :
177 0 : Reference< XInputStream > CSerializationURLEncoded::getInputStream()
178 : {
179 0 : return Reference< XInputStream >(m_aPipe, UNO_QUERY);
180 : }
181 :
182 :
183 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|