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