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_xmlsecurity.hxx" 30 31 /* 32 * Implementation of the I/O interfaces based on stream and URI binding 33 */ 34 #include "xmlstreamio.hxx" 35 #include <rtl/ustring.hxx> 36 #include "rtl/uri.hxx" 37 38 #include <libxml/uri.h> 39 #include <sal/types.h> 40 //For reasons that escape me, this is what xmlsec does when size_t is not 4 41 #if SAL_TYPES_SIZEOFPOINTER != 4 42 # define XMLSEC_NO_SIZE_T 43 #endif 44 #include <xmlsec/io.h> 45 46 #define XMLSTREAMIO_INITIALIZED 0x01 47 #define XMLSTREAMIO_REGISTERED 0x02 48 49 /* Global variables */ 50 /*- 51 * Enable stream I/O or not. 52 */ 53 static char enableXmlStreamIO = 0x00 ; 54 55 ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XUriBinding > m_xUriBinding ; 56 57 extern "C" 58 int xmlStreamMatch( const char* uri ) 59 { 60 ::com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xInputStream ; 61 62 if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) && 63 ( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 64 if( uri == NULL || !m_xUriBinding.is() ) 65 return 0 ; 66 //XMLSec first unescapes the uri and calls this function. For example, we pass the Uri 67 //ObjectReplacements/Object%201 then XMLSec passes ObjectReplacements/Object 1 68 //first. If this failed it would try this 69 //again with the original escaped string. However, it does not get this far, because there 70 //is another callback registered by libxml which claims to be able to handle this uri. 71 ::rtl::OUString sUri = 72 ::rtl::Uri::encode( ::rtl::OUString::createFromAscii( uri ), 73 rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes, RTL_TEXTENCODING_UTF8); 74 xInputStream = m_xUriBinding->getUriBinding( sUri ) ; 75 if (!xInputStream.is()) 76 { 77 //Try the the passed in uri directly. 78 //For old documents prior OOo 3.0. We did not use URIs then. 79 xInputStream = m_xUriBinding->getUriBinding( 80 ::rtl::OUString::createFromAscii(uri)); 81 } 82 } 83 if (xInputStream.is()) 84 return 1; 85 else 86 return 0 ; 87 } 88 89 extern "C" 90 void* xmlStreamOpen( const char* uri ) 91 { 92 ::com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xInputStream ; 93 ::com::sun::star::io::XInputStream* pInputStream ; 94 95 if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) && 96 ( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 97 if( uri == NULL || !m_xUriBinding.is() ) 98 return NULL ; 99 100 //see xmlStreamMatch 101 ::rtl::OUString sUri = 102 ::rtl::Uri::encode( ::rtl::OUString::createFromAscii( uri ), 103 rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes, RTL_TEXTENCODING_UTF8); 104 xInputStream = m_xUriBinding->getUriBinding( sUri ) ; 105 if (!xInputStream.is()) 106 { 107 //For old documents. 108 //try the the passed in uri directly. 109 xInputStream = m_xUriBinding->getUriBinding( 110 ::rtl::OUString::createFromAscii(uri)); 111 } 112 113 if( xInputStream.is() ) { 114 pInputStream = xInputStream.get() ; 115 pInputStream->acquire() ; 116 return ( void* )pInputStream ; 117 } 118 } 119 120 return NULL ; 121 } 122 123 extern "C" 124 int xmlStreamRead( void* context, char* buffer, int len ) 125 { 126 int numbers ; 127 ::com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xInputStream ; 128 ::com::sun::star::uno::Sequence< sal_Int8 > outSeqs( len ) ; 129 130 numbers = 0 ; 131 if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) && 132 ( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 133 if( context != NULL ) { 134 xInputStream = ( com::sun::star::io::XInputStream* )context ; 135 if( !xInputStream.is() ) 136 return 0 ; 137 138 numbers = xInputStream->readBytes( outSeqs, len ) ; 139 const sal_Int8* readBytes = ( const sal_Int8* )outSeqs.getArray() ; 140 for( int i = 0 ; i < numbers ; i ++ ) 141 *( buffer + i ) = *( readBytes + i ) ; 142 } 143 } 144 145 return numbers ; 146 } 147 148 extern "C" 149 int xmlStreamClose( void * context ) 150 { 151 ::com::sun::star::io::XInputStream* pInputStream ; 152 153 if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) && 154 ( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 155 if( context != NULL ) { 156 pInputStream = ( ::com::sun::star::io::XInputStream* )context ; 157 pInputStream->release() ; 158 } 159 } 160 161 return 0 ; 162 } 163 164 int xmlEnableStreamInputCallbacks() 165 { 166 int cbs = 0 ; 167 168 if( !( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) ) { 169 //Register the callbacks into libxml2 170 //cbs = xmlRegisterInputCallbacks( 171 // xmlStreamMatch, 172 // xmlStreamOpen, 173 // xmlStreamRead, 174 // xmlStreamClose ) ; 175 //if( cbs < 0 ) { 176 // return -1 ; 177 //} 178 179 //Register the callbacks into xmlSec 180 //In order to make the xmlsec io finding the callbacks firstly, 181 //I put the callbacks at the very begining. 182 183 //Cleanup the older callbacks. 184 //Notes: all none default callbacks will lose. 185 xmlSecIOCleanupCallbacks() ; 186 187 //Register my classbacks. 188 cbs = xmlSecIORegisterCallbacks( 189 xmlStreamMatch, 190 xmlStreamOpen, 191 xmlStreamRead, 192 xmlStreamClose ) ; 193 if( cbs < 0 ) { 194 return -1 ; 195 } 196 197 //Register the default callbacks. 198 //Notes: the error will cause xmlsec working problems. 199 cbs = xmlSecIORegisterDefaultCallbacks() ; 200 if( cbs < 0 ) { 201 return -1 ; 202 } 203 204 enableXmlStreamIO |= XMLSTREAMIO_INITIALIZED ; 205 } 206 207 return 0 ; 208 } 209 210 int xmlRegisterStreamInputCallbacks( 211 ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XUriBinding >& aUriBinding 212 ) { 213 if( !( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) ) { 214 if( xmlEnableStreamInputCallbacks() < 0 ) 215 return -1 ; 216 } 217 218 if( !( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 219 enableXmlStreamIO |= XMLSTREAMIO_REGISTERED ; 220 } 221 222 m_xUriBinding = aUriBinding ; 223 224 return 0 ; 225 } 226 227 int xmlUnregisterStreamInputCallbacks( void ) 228 { 229 if( ( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) { 230 //Clear the uir-stream binding 231 m_xUriBinding.clear() ; 232 233 //disable the registered flag 234 enableXmlStreamIO &= ~XMLSTREAMIO_REGISTERED ; 235 } 236 237 return 0 ; 238 } 239 240 void xmlDisableStreamInputCallbacks() { 241 xmlUnregisterStreamInputCallbacks() ; 242 enableXmlStreamIO &= ~XMLSTREAMIO_INITIALIZED ; 243 } 244 245