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