1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_forms.hxx"
26
27 #include <com/sun/star/xml/xpath/XPathObjectType.hpp>
28 #include <com/sun/star/xml/dom/XNode.hpp>
29 #include <com/sun/star/xml/dom/XText.hpp>
30 #include <com/sun/star/xml/dom/XNodeList.hpp>
31 #include <com/sun/star/xml/dom/NodeType.hpp>
32
33 #include <rtl/ustrbuf.hxx>
34 #include <rtl/strbuf.hxx>
35 #include <unotools/processfactory.hxx>
36
37 #include <stdio.h>
38
39 #include "serialization_urlencoded.hxx"
40
41 using namespace utl;
42 using namespace CSS::uno;
43 using namespace CSS::io;
44 using namespace CSS::xml::xpath;
45 using namespace CSS::xml::dom;
46
CSerializationURLEncoded()47 CSerializationURLEncoded::CSerializationURLEncoded()
48 : m_aFactory(getProcessServiceFactory())
49 , m_aPipe(Reference< XOutputStream > (m_aFactory->createInstance(
50 ::rtl::OUString::createFromAscii("com.sun.star.io.Pipe")), UNO_QUERY))
51 {
52 }
53
54
55 /*
56 rfc2396
57 reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
58 "$" | ","
59 mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
60 unreserved = alphanum | mark
61 */
is_unreserved(sal_Char c)62 sal_Bool CSerializationURLEncoded::is_unreserved(sal_Char c)
63 {
64 //digit?
65 if (c >= '0' && c <= '9') return sal_True;
66 if (c >= 'A' && c <= 'Z') return sal_True;
67 if (c >= 'a' && c <= 'z') return sal_True;
68 switch (c) {
69 case '-':
70 case '_':
71 case '.':
72 case '!':
73 case '~':
74 case '*':
75 case '\'':
76 case '(':
77 case ')':
78 return sal_True;
79 }
80 return sal_False;
81 }
encode_and_append(const::rtl::OUString & aString,::rtl::OStringBuffer & aBuffer)82 void CSerializationURLEncoded::encode_and_append(const ::rtl::OUString& aString, ::rtl::OStringBuffer& aBuffer)
83 {
84 ::rtl::OString utf8String = OUStringToOString(aString, RTL_TEXTENCODING_UTF8);
85 const sal_uInt8 *pString = reinterpret_cast< const sal_uInt8 * >( utf8String.getStr() );
86 sal_Char tmpChar[4]; tmpChar[3] = 0;
87
88 while( *pString != 0)
89 {
90 if( *pString < 0x80 )
91 {
92 if ( is_unreserved(*pString) ) {
93 aBuffer.append(*pString);
94 } else if (*pString == 0x20) {
95 aBuffer.append('+');
96 } else if (*pString == 0x0d && *(pString+1) == 0x0a) {
97 aBuffer.append("%0D%0A");
98 pString++;
99 } else if (*pString == 0x0a) {
100 aBuffer.append("%0D%0A");
101 } else {
102 snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
103 aBuffer.append(tmpChar);
104 }
105 } else {
106 snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
107 aBuffer.append(tmpChar);
108 while (*pString >= 0x80) {
109 // continuation...
110 pString++;
111 snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
112 aBuffer.append(tmpChar);
113 }
114 }
115 pString++;
116 }
117 }
118
serialize_node(const Reference<XNode> & aNode)119 void CSerializationURLEncoded::serialize_node(const Reference< XNode >& aNode)
120 {
121 // serialize recursive
122 // every element node E that has a text child T will be serialized in document order
123 // <E1>T1<E2>T2</E2></E1><E3>T3</E3> -> E1=T2&E2=T2&E3=T3 (En := local name)
124
125 // this node
126 Reference< XNodeList > aChildList = aNode->getChildNodes();
127 Reference< XNode > aChild;
128 // is this an element node?
129 if (aNode->getNodeType() == NodeType_ELEMENT_NODE)
130 {
131 ::rtl::OUString aName = aNode->getNodeName();
132 // find any text children
133 ::rtl::OUStringBuffer aValue;
134 Reference< XText > aText;
135 for(sal_Int32 i=0; i < aChildList->getLength(); i++)
136 {
137 aChild = aChildList->item(i);
138 if (aChild->getNodeType() == NodeType_TEXT_NODE)
139 {
140 aText = Reference< XText >(aChild, UNO_QUERY);
141 aValue.append(aText->getData());
142 }
143 }
144
145 // found anything?
146 if (aValue.getLength() > 0)
147 {
148 ::rtl::OUString aUnencValue = aValue.makeStringAndClear();
149 ::rtl::OStringBuffer aEncodedBuffer;
150 encode_and_append(aName, aEncodedBuffer);
151 aEncodedBuffer.append("=");
152 encode_and_append(aUnencValue, aEncodedBuffer);
153 aEncodedBuffer.append("&");
154 sal_Int8 *pData = (sal_Int8*)aEncodedBuffer.getStr();
155 Sequence< sal_Int8 > sData(pData, aEncodedBuffer.getLength());
156 m_aPipe->writeBytes(sData);
157 }
158 }
159
160 // element children...
161 for(sal_Int32 i=0; i < aChildList->getLength(); i++)
162 {
163 aChild = aChildList->item(i);
164 // if this is an element node, it might be a candidate for serialization
165 if (aChild.is() && aChild->getNodeType() == NodeType_ELEMENT_NODE)
166 serialize_node(aChild);
167 }
168
169 // siblings...
170 // Reference< XNode > aSibling = aNode->getNextSibling();
171 // if (aSibling.is())
172 // serialize_node(aSibling);
173
174 }
175
176 /*
177 void CSerializationURLEncoded::serialize_nodeset()
178 {
179 Reference< XNodeList > aNodeList = m_aXPathObject->getNodeList();
180 for (sal_Int32 i=0; i<aNodeList->getLength(); i++)
181 serialize_node(aNodeList->item(i));
182 m_aPipe->closeOutput();
183 }
184 */
185
serialize()186 void CSerializationURLEncoded::serialize()
187 {
188
189 // output stream to the pipe buffer
190 Reference< XOutputStream > out(m_aPipe, UNO_QUERY);
191
192 CSS::uno::Reference< CSS::xml::dom::XNode > cur = m_aFragment->getFirstChild();
193 while (cur.is())
194 {
195 serialize_node(cur);
196 cur = cur->getNextSibling();
197 }
198 m_aPipe->closeOutput();
199 }
200
getInputStream()201 Reference< XInputStream > CSerializationURLEncoded::getInputStream()
202 {
203 return Reference< XInputStream >(m_aPipe, UNO_QUERY);
204 }
205
206
207