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 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 */ 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 } 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 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 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 201 Reference< XInputStream > CSerializationURLEncoded::getInputStream() 202 { 203 return Reference< XInputStream >(m_aPipe, UNO_QUERY); 204 } 205 206 207