xref: /AOO41X/main/xmlsecurity/source/xmlsec/xmlstreamio.cxx (revision 06b3ce531745799678cf4bb887ef37436d81238b)
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 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 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