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 0 : : m_aPipe(Pipe::create(comphelper::getProcessComponentContext()))
44 : {
45 0 : }
46 :
47 :
48 : /*
49 : rfc2396
50 : reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
51 : "$" | ","
52 : mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
53 : unreserved = alphanum | mark
54 : */
55 0 : sal_Bool CSerializationURLEncoded::is_unreserved(sal_Char c)
56 : {
57 0 : if (comphelper::string::isalnumAscii(c))
58 0 : return sal_True;
59 0 : switch (c) {
60 : case '-':
61 : case '_':
62 : case '.':
63 : case '!':
64 : case '~':
65 : case '*':
66 : case '\'':
67 : case '(':
68 : case ')':
69 0 : return sal_True;
70 : }
71 0 : return sal_False;
72 : }
73 0 : void CSerializationURLEncoded::encode_and_append(const OUString& aString, OStringBuffer& aBuffer)
74 : {
75 0 : OString utf8String = OUStringToOString(aString, RTL_TEXTENCODING_UTF8);
76 0 : const sal_uInt8 *pString = reinterpret_cast< const sal_uInt8 * >( utf8String.getStr() );
77 0 : sal_Char tmpChar[4]; tmpChar[3] = 0;
78 :
79 0 : while( *pString != 0)
80 : {
81 0 : if( *pString < 0x80 )
82 : {
83 0 : if ( is_unreserved(*pString) ) {
84 0 : aBuffer.append(*pString);
85 0 : } else if (*pString == 0x20) {
86 0 : aBuffer.append('+');
87 0 : } else if (*pString == 0x0d && *(pString+1) == 0x0a) {
88 0 : aBuffer.append("%0D%0A");
89 0 : pString++;
90 0 : } else if (*pString == 0x0a) {
91 0 : aBuffer.append("%0D%0A");
92 : } else {
93 0 : snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
94 0 : aBuffer.append(tmpChar);
95 : }
96 : } else {
97 0 : snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
98 0 : aBuffer.append(tmpChar);
99 0 : while (*pString >= 0x80) {
100 : // continuation...
101 0 : pString++;
102 0 : snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
103 0 : aBuffer.append(tmpChar);
104 : }
105 : }
106 0 : pString++;
107 0 : }
108 0 : }
109 :
110 0 : void CSerializationURLEncoded::serialize_node(const Reference< XNode >& aNode)
111 : {
112 : // serialize recursive
113 : // every element node E that has a text child T will be serialized in document order
114 : // <E1>T1<E2>T2</E2></E1><E3>T3</E3> -> E1=T2&E2=T2&E3=T3 (En := local name)
115 :
116 : // this node
117 0 : Reference< XNodeList > aChildList = aNode->getChildNodes();
118 0 : Reference< XNode > aChild;
119 : // is this an element node?
120 0 : if (aNode->getNodeType() == NodeType_ELEMENT_NODE)
121 : {
122 0 : OUString aName = aNode->getNodeName();
123 : // find any text children
124 0 : OUStringBuffer aValue;
125 0 : Reference< XText > aText;
126 0 : for(sal_Int32 i=0; i < aChildList->getLength(); i++)
127 : {
128 0 : aChild = aChildList->item(i);
129 0 : if (aChild->getNodeType() == NodeType_TEXT_NODE)
130 : {
131 0 : aText = Reference< XText >(aChild, UNO_QUERY);
132 0 : aValue.append(aText->getData());
133 : }
134 : }
135 :
136 : // found anything?
137 0 : if (!aValue.isEmpty())
138 : {
139 0 : OUString aUnencValue = aValue.makeStringAndClear();
140 0 : OStringBuffer aEncodedBuffer;
141 0 : encode_and_append(aName, aEncodedBuffer);
142 0 : aEncodedBuffer.append("=");
143 0 : encode_and_append(aUnencValue, aEncodedBuffer);
144 0 : aEncodedBuffer.append("&");
145 0 : sal_Int8 *pData = (sal_Int8*)aEncodedBuffer.getStr();
146 0 : Sequence< sal_Int8 > sData(pData, aEncodedBuffer.getLength());
147 0 : m_aPipe->writeBytes(sData);
148 0 : }
149 : }
150 :
151 : // element children...
152 0 : for(sal_Int32 i=0; i < aChildList->getLength(); i++)
153 : {
154 0 : aChild = aChildList->item(i);
155 : // if this is an element node, it might be a candidate for serialization
156 0 : if (aChild.is() && aChild->getNodeType() == NodeType_ELEMENT_NODE)
157 0 : serialize_node(aChild);
158 0 : }
159 0 : }
160 :
161 0 : void CSerializationURLEncoded::serialize()
162 : {
163 :
164 : // output stream to the pipe buffer
165 0 : Reference< XOutputStream > out(m_aPipe, UNO_QUERY);
166 :
167 0 : CSS::uno::Reference< CSS::xml::dom::XNode > cur = m_aFragment->getFirstChild();
168 0 : while (cur.is())
169 : {
170 0 : serialize_node(cur);
171 0 : cur = cur->getNextSibling();
172 : }
173 0 : m_aPipe->closeOutput();
174 0 : }
175 :
176 0 : Reference< XInputStream > CSerializationURLEncoded::getInputStream()
177 : {
178 0 : return Reference< XInputStream >(m_aPipe, UNO_QUERY);
179 : }
180 :
181 :
182 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|