1*06b3ce53SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*06b3ce53SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*06b3ce53SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*06b3ce53SAndrew Rist  * distributed with this work for additional information
6*06b3ce53SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*06b3ce53SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*06b3ce53SAndrew Rist  * "License"); you may not use this file except in compliance
9*06b3ce53SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*06b3ce53SAndrew Rist  *
11*06b3ce53SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*06b3ce53SAndrew Rist  *
13*06b3ce53SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*06b3ce53SAndrew Rist  * software distributed under the License is distributed on an
15*06b3ce53SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*06b3ce53SAndrew Rist  * KIND, either express or implied.  See the License for the
17*06b3ce53SAndrew Rist  * specific language governing permissions and limitations
18*06b3ce53SAndrew Rist  * under the License.
19*06b3ce53SAndrew Rist  *
20*06b3ce53SAndrew Rist  *************************************************************/
21*06b3ce53SAndrew Rist 
22*06b3ce53SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_xmlsecurity.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir /*
28cdf0e10cSrcweir  * Implementation of the I/O interfaces based on stream and URI binding
29cdf0e10cSrcweir  */
30cdf0e10cSrcweir #include "xmlstreamio.hxx"
31cdf0e10cSrcweir #include <rtl/ustring.hxx>
32cdf0e10cSrcweir #include "rtl/uri.hxx"
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <libxml/uri.h>
35cdf0e10cSrcweir #include <sal/types.h>
36cdf0e10cSrcweir //For reasons that escape me, this is what xmlsec does when size_t is not 4
37cdf0e10cSrcweir #if SAL_TYPES_SIZEOFPOINTER != 4
38cdf0e10cSrcweir #    define XMLSEC_NO_SIZE_T
39cdf0e10cSrcweir #endif
40cdf0e10cSrcweir #include <xmlsec/io.h>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir #define XMLSTREAMIO_INITIALIZED 0x01
43cdf0e10cSrcweir #define XMLSTREAMIO_REGISTERED  0x02
44cdf0e10cSrcweir 
45cdf0e10cSrcweir /* Global variables */
46cdf0e10cSrcweir /*-
47cdf0e10cSrcweir  * Enable stream I/O or not.
48cdf0e10cSrcweir  */
49cdf0e10cSrcweir static char enableXmlStreamIO = 0x00 ;
50cdf0e10cSrcweir 
51cdf0e10cSrcweir ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XUriBinding > m_xUriBinding ;
52cdf0e10cSrcweir 
53cdf0e10cSrcweir extern "C"
xmlStreamMatch(const char * uri)54cdf0e10cSrcweir int xmlStreamMatch( const char* uri )
55cdf0e10cSrcweir {
56cdf0e10cSrcweir 	::com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xInputStream ;
57cdf0e10cSrcweir 
58cdf0e10cSrcweir 	if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) &&
59cdf0e10cSrcweir 		( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) {
60cdf0e10cSrcweir 		if( uri == NULL || !m_xUriBinding.is() )
61cdf0e10cSrcweir 			return 0 ;
62cdf0e10cSrcweir         //XMLSec first unescapes the uri and  calls this function. For example, we pass the Uri
63cdf0e10cSrcweir         //ObjectReplacements/Object%201 then XMLSec passes ObjectReplacements/Object 1
64cdf0e10cSrcweir         //first. If this failed it would try this
65cdf0e10cSrcweir         //again with the original escaped string. However, it does not get this far, because there
66cdf0e10cSrcweir         //is another callback registered by libxml which claims to be able to handle this uri.
67cdf0e10cSrcweir         ::rtl::OUString sUri =
68cdf0e10cSrcweir             ::rtl::Uri::encode( ::rtl::OUString::createFromAscii( uri ),
69cdf0e10cSrcweir             rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes, RTL_TEXTENCODING_UTF8);
70cdf0e10cSrcweir 		xInputStream = m_xUriBinding->getUriBinding( sUri ) ;
71cdf0e10cSrcweir         if (!xInputStream.is())
72cdf0e10cSrcweir         {
73cdf0e10cSrcweir             //Try the the passed in uri directly.
74cdf0e10cSrcweir             //For old documents prior OOo 3.0. We did not use URIs then.
75cdf0e10cSrcweir             xInputStream = m_xUriBinding->getUriBinding(
76cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(uri));
77cdf0e10cSrcweir         }
78cdf0e10cSrcweir 	}
79cdf0e10cSrcweir     if (xInputStream.is())
80cdf0e10cSrcweir         return 1;
81cdf0e10cSrcweir     else
82cdf0e10cSrcweir 	    return 0 ;
83cdf0e10cSrcweir }
84cdf0e10cSrcweir 
85cdf0e10cSrcweir extern "C"
xmlStreamOpen(const char * uri)86cdf0e10cSrcweir void* xmlStreamOpen( const char* uri )
87cdf0e10cSrcweir {
88cdf0e10cSrcweir 	::com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xInputStream ;
89cdf0e10cSrcweir 	::com::sun::star::io::XInputStream* pInputStream ;
90cdf0e10cSrcweir 
91cdf0e10cSrcweir 	if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) &&
92cdf0e10cSrcweir 		( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) {
93cdf0e10cSrcweir 		if( uri == NULL || !m_xUriBinding.is() )
94cdf0e10cSrcweir 			return NULL ;
95cdf0e10cSrcweir 
96cdf0e10cSrcweir         //see xmlStreamMatch
97cdf0e10cSrcweir         ::rtl::OUString sUri =
98cdf0e10cSrcweir             ::rtl::Uri::encode( ::rtl::OUString::createFromAscii( uri ),
99cdf0e10cSrcweir             rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes, RTL_TEXTENCODING_UTF8);
100cdf0e10cSrcweir         xInputStream = m_xUriBinding->getUriBinding( sUri ) ;
101cdf0e10cSrcweir         if (!xInputStream.is())
102cdf0e10cSrcweir         {
103cdf0e10cSrcweir             //For old documents.
104cdf0e10cSrcweir             //try the the passed in uri directly.
105cdf0e10cSrcweir             xInputStream = m_xUriBinding->getUriBinding(
106cdf0e10cSrcweir                 ::rtl::OUString::createFromAscii(uri));
107cdf0e10cSrcweir         }
108cdf0e10cSrcweir 
109cdf0e10cSrcweir 		if( xInputStream.is() ) {
110cdf0e10cSrcweir 			pInputStream = xInputStream.get() ;
111cdf0e10cSrcweir 			pInputStream->acquire() ;
112cdf0e10cSrcweir 			return ( void* )pInputStream ;
113cdf0e10cSrcweir 		}
114cdf0e10cSrcweir 	}
115cdf0e10cSrcweir 
116cdf0e10cSrcweir 	return NULL ;
117cdf0e10cSrcweir }
118cdf0e10cSrcweir 
119cdf0e10cSrcweir extern "C"
xmlStreamRead(void * context,char * buffer,int len)120cdf0e10cSrcweir int xmlStreamRead( void* context, char* buffer, int len )
121cdf0e10cSrcweir {
122cdf0e10cSrcweir 	int numbers ;
123cdf0e10cSrcweir 	::com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xInputStream ;
124cdf0e10cSrcweir 	::com::sun::star::uno::Sequence< sal_Int8 > outSeqs( len ) ;
125cdf0e10cSrcweir 
126cdf0e10cSrcweir 	numbers = 0 ;
127cdf0e10cSrcweir 	if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) &&
128cdf0e10cSrcweir 		( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) {
129cdf0e10cSrcweir 		if( context != NULL ) {
130cdf0e10cSrcweir 			xInputStream = ( com::sun::star::io::XInputStream* )context ;
131cdf0e10cSrcweir 			if( !xInputStream.is() )
132cdf0e10cSrcweir 				return 0 ;
133cdf0e10cSrcweir 
134cdf0e10cSrcweir 			numbers = xInputStream->readBytes( outSeqs, len ) ;
135cdf0e10cSrcweir 			const sal_Int8* readBytes = ( const sal_Int8* )outSeqs.getArray() ;
136cdf0e10cSrcweir 			for( int i = 0 ; i < numbers ; i ++ )
137cdf0e10cSrcweir 				*( buffer + i ) = *( readBytes + i ) ;
138cdf0e10cSrcweir 		}
139cdf0e10cSrcweir 	}
140cdf0e10cSrcweir 
141cdf0e10cSrcweir 	return numbers ;
142cdf0e10cSrcweir }
143cdf0e10cSrcweir 
144cdf0e10cSrcweir extern "C"
xmlStreamClose(void * context)145cdf0e10cSrcweir int xmlStreamClose( void * context )
146cdf0e10cSrcweir {
147cdf0e10cSrcweir 	::com::sun::star::io::XInputStream* pInputStream ;
148cdf0e10cSrcweir 
149cdf0e10cSrcweir 	if( ( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) &&
150cdf0e10cSrcweir 		( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) {
151cdf0e10cSrcweir 		if( context != NULL ) {
152cdf0e10cSrcweir 			pInputStream = ( ::com::sun::star::io::XInputStream* )context ;
153cdf0e10cSrcweir 			pInputStream->release() ;
154cdf0e10cSrcweir 		}
155cdf0e10cSrcweir 	}
156cdf0e10cSrcweir 
157cdf0e10cSrcweir 	return 0 ;
158cdf0e10cSrcweir }
159cdf0e10cSrcweir 
xmlEnableStreamInputCallbacks()160cdf0e10cSrcweir int xmlEnableStreamInputCallbacks()
161cdf0e10cSrcweir {
162cdf0e10cSrcweir 	int cbs = 0 ;
163cdf0e10cSrcweir 
164cdf0e10cSrcweir 	if( !( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) ) {
165cdf0e10cSrcweir 		//Register the callbacks into libxml2
166cdf0e10cSrcweir 		//cbs = xmlRegisterInputCallbacks(
167cdf0e10cSrcweir 		//			xmlStreamMatch,
168cdf0e10cSrcweir 		//			xmlStreamOpen,
169cdf0e10cSrcweir 		//			xmlStreamRead,
170cdf0e10cSrcweir 		//			xmlStreamClose ) ;
171cdf0e10cSrcweir 		//if( cbs < 0 ) {
172cdf0e10cSrcweir 		//	return -1 ;
173cdf0e10cSrcweir 		//}
174cdf0e10cSrcweir 
175cdf0e10cSrcweir 		//Register the callbacks into xmlSec
176cdf0e10cSrcweir 		//In order to make the xmlsec io finding the callbacks firstly,
177cdf0e10cSrcweir 		//I put the callbacks at the very begining.
178cdf0e10cSrcweir 
179cdf0e10cSrcweir 		//Cleanup the older callbacks.
180cdf0e10cSrcweir 		//Notes: all none default callbacks will lose.
181cdf0e10cSrcweir 		xmlSecIOCleanupCallbacks() ;
182cdf0e10cSrcweir 
183cdf0e10cSrcweir 		//Register my classbacks.
184cdf0e10cSrcweir 		cbs = xmlSecIORegisterCallbacks(
185cdf0e10cSrcweir 					xmlStreamMatch,
186cdf0e10cSrcweir 					xmlStreamOpen,
187cdf0e10cSrcweir 					xmlStreamRead,
188cdf0e10cSrcweir 					xmlStreamClose ) ;
189cdf0e10cSrcweir 		if( cbs < 0 ) {
190cdf0e10cSrcweir 			return -1 ;
191cdf0e10cSrcweir 		}
192cdf0e10cSrcweir 
193cdf0e10cSrcweir 		//Register the default callbacks.
194cdf0e10cSrcweir 		//Notes: the error will cause xmlsec working problems.
195cdf0e10cSrcweir 		cbs = xmlSecIORegisterDefaultCallbacks() ;
196cdf0e10cSrcweir 		if( cbs < 0 ) {
197cdf0e10cSrcweir 			return -1 ;
198cdf0e10cSrcweir 		}
199cdf0e10cSrcweir 
200cdf0e10cSrcweir 		enableXmlStreamIO |= XMLSTREAMIO_INITIALIZED ;
201cdf0e10cSrcweir 	}
202cdf0e10cSrcweir 
203cdf0e10cSrcweir 	return 0 ;
204cdf0e10cSrcweir }
205cdf0e10cSrcweir 
xmlRegisterStreamInputCallbacks(::com::sun::star::uno::Reference<::com::sun::star::xml::crypto::XUriBinding> & aUriBinding)206cdf0e10cSrcweir int xmlRegisterStreamInputCallbacks(
207cdf0e10cSrcweir 	::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XUriBinding >& aUriBinding
208cdf0e10cSrcweir ) {
209cdf0e10cSrcweir 	if( !( enableXmlStreamIO & XMLSTREAMIO_INITIALIZED ) ) {
210cdf0e10cSrcweir 		if( xmlEnableStreamInputCallbacks() < 0 )
211cdf0e10cSrcweir 			return -1 ;
212cdf0e10cSrcweir 	}
213cdf0e10cSrcweir 
214cdf0e10cSrcweir 	if( !( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) {
215cdf0e10cSrcweir 		enableXmlStreamIO |= XMLSTREAMIO_REGISTERED ;
216cdf0e10cSrcweir 	}
217cdf0e10cSrcweir 
218cdf0e10cSrcweir 	m_xUriBinding = aUriBinding ;
219cdf0e10cSrcweir 
220cdf0e10cSrcweir 	return 0 ;
221cdf0e10cSrcweir }
222cdf0e10cSrcweir 
xmlUnregisterStreamInputCallbacks(void)223cdf0e10cSrcweir int xmlUnregisterStreamInputCallbacks( void )
224cdf0e10cSrcweir {
225cdf0e10cSrcweir 	if( ( enableXmlStreamIO & XMLSTREAMIO_REGISTERED ) ) {
226cdf0e10cSrcweir 		//Clear the uir-stream binding
227cdf0e10cSrcweir 		m_xUriBinding.clear() ;
228cdf0e10cSrcweir 
229cdf0e10cSrcweir 		//disable the registered flag
230cdf0e10cSrcweir 		enableXmlStreamIO &= ~XMLSTREAMIO_REGISTERED ;
231cdf0e10cSrcweir 	}
232cdf0e10cSrcweir 
233cdf0e10cSrcweir 	return 0 ;
234cdf0e10cSrcweir }
235cdf0e10cSrcweir 
xmlDisableStreamInputCallbacks()236cdf0e10cSrcweir void xmlDisableStreamInputCallbacks() {
237cdf0e10cSrcweir 	xmlUnregisterStreamInputCallbacks() ;
238cdf0e10cSrcweir 	enableXmlStreamIO &= ~XMLSTREAMIO_INITIALIZED ;
239cdf0e10cSrcweir }
240cdf0e10cSrcweir 
241