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