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  // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_filter.hxx"
24 
25 //This file is about the conversion of the UOF v2.0 and ODF document format
26 #include <com/sun/star/io/XActiveDataSource.hpp>
27 #include <com/sun/star/uno/Exception.hpp>
28 #include <com/sun/star/embed/ElementModes.hpp>
29 #include <comphelper/storagehelper.hxx>
30 #include <comphelper/attributelist.hxx>
31 #include <xmloff/attrlist.hxx>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/uno/Any.hxx>
34 
35 
36 #include "uof2splithandler.hxx"
37 
38 using namespace XSLT;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::io;
41 using namespace ::com::sun::star::xml::sax;
42 using namespace ::com::sun::star::embed;
43 using namespace ::com::sun::star::beans;
44 using namespace ::rtl;
45 
46 
47 
UOF2SplitHandler(::com::sun::star::uno::Reference<::com::sun::star::lang::XMultiServiceFactory> & rMultiFactory,::com::sun::star::uno::Reference<::com::sun::star::io::XStream> & rStream)48 UOF2SplitHandler::UOF2SplitHandler(
49 		::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rMultiFactory,
50 		::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rStream )
51 : m_rStream( rStream )
52 , m_rMultiFactory( rMultiFactory )
53 , m_bIsStart( sal_False )
54 {
55 	_Init();
56 }
57 
_Init()58 void UOF2SplitHandler::_Init()
59 {
60 	if ( m_rMultiFactory.is() && m_rStream.is() )
61 	{
62 		try {
63 			m_pStore = new UOF2Storage( m_rMultiFactory, m_rStream );
64 			if ( m_pStore != NULL )
65 				m_pMainStore = m_pStore->getMainStorageRef();
66 
67 			m_xHandler = Reference< XExtendedDocumentHandler >( m_rMultiFactory->createInstance(
68 				OUString::createFromAscii("com.sun.star.xml.sax.Writer")), UNO_QUERY );
69 			Reference< XActiveDataSource > xSource( m_xHandler, UNO_QUERY );
70 			xSource->setOutputStream( m_rStream->getOutputStream() );
71 		}
72 		catch( Exception& e)
73 		{
74 			OSL_ENSURE(0, ::rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US).getStr());
75 		}
76 	}
77 }
78 
~UOF2SplitHandler()79 UOF2SplitHandler::~UOF2SplitHandler()
80 {
81 	delete m_pStore;
82 }
83 
startDocument()84 void UOF2SplitHandler::startDocument() throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException )
85 {
86 	m_xHandler->startDocument();
87 }
88 
endDocument()89 void UOF2SplitHandler::endDocument() throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException )
90 {
91 	m_xHandler->endDocument();
92 }
93 
startElement(const::rtl::OUString & qName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & AttrList)94 void UOF2SplitHandler::startElement(const ::rtl::OUString& qName, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& AttrList )
95         throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException )
96 {
97 	if ( qName.equalsAscii("pzip:entry") )
98 	{
99 		namespaceMap( AttrList );
100 	}
101 	else if ( qName.equalsAscii("pzip:target") )
102 	{
103 		aOutFileName = AttrList->getValueByName(::rtl::OUString::createFromAscii("pzip:path"));
104 		m_bIsStart = sal_True;
105 		Write( aOutFileName , m_bIsStart );
106 	}
107 	else
108 	{
109 		if ( m_bIsStart )  // start a sub file
110 		{
111 			// insert namespace declaration for the root element in each sub file
112 			::comphelper::AttributeList * aTmpAtt = new ::comphelper::AttributeList();
113 			if ( aTmpAtt != NULL )
114 			{
115 				typedef ::std::map< OUString, NamespaceValue >::iterator NSItr;
116 				for( NSItr it = aNamespaceMap.begin(); it != aNamespaceMap.end(); it++ )
117 				{
118 					aTmpAtt->AddAttribute( it->first, it->second.aType, it->second.aValue );
119 				}
120 				aTmpAtt->AppendAttributeList( AttrList );
121 				m_bIsStart = sal_False;
122 				const Reference< XAttributeList > xnewAttr( aTmpAtt );
123 				m_xHandler->startElement( qName, xnewAttr );
124 			}
125 		}
126 		else
127 			m_xHandler->startElement( qName, AttrList );
128 	}
129 }
130 
endElement(const::rtl::OUString & qName)131 void UOF2SplitHandler::endElement(const ::rtl::OUString& qName )
132         throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException )
133 {
134 	if ( qName.equalsAscii("pzip:entry") )
135 	{
136 		m_pMainStore->commit();
137 	}
138 	else if ( qName.equalsAscii("pzip:target" ) )
139 	{
140 		Write( aOutFileName, sal_False );
141 	}
142 	else
143 	{
144 		m_xHandler->endElement( qName );
145 	}
146 }
147 
characters(const::rtl::OUString & rStr)148 void UOF2SplitHandler::characters(const ::rtl::OUString& rStr )
149         throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException )
150 {
151 	m_xHandler->characters( rStr );
152 }
153 
ignorableWhitespace(const::rtl::OUString & str)154 void UOF2SplitHandler::ignorableWhitespace(const ::rtl::OUString& str)
155         throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException )
156 {
157 	m_xHandler->ignorableWhitespace( str );
158 }
159 
processingInstruction(const::rtl::OUString &,const::rtl::OUString &)160 void UOF2SplitHandler::processingInstruction(const ::rtl::OUString& /*str*/, const ::rtl::OUString& /*str2*/)
161         throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException )
162 {
163 }
164 
setDocumentLocator(const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XLocator> &)165 void UOF2SplitHandler::setDocumentLocator(const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XLocator >&/* doclocator*/)
166         throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException )
167 {
168 }
169 
170 /* ----
171     create substream and write sub file when starting a <pzip:target> element
172 	close substream when ending a <pzip:target> element
173 ---- */
Write(OUString & rFileName,sal_Bool bStart)174 void UOF2SplitHandler::Write( OUString & rFileName , sal_Bool bStart ) throw( RuntimeException )
175 {
176 	if ( bStart )
177 	{
178 		try {
179 			OUString sPath;
180 			sal_Int32 nIndex = rFileName.lastIndexOf( sal_Unicode('/') );
181 			if ( nIndex != -1 )
182 			{
183 				OUString aTmp = rFileName;
184 				sPath = aTmp.copy(0, nIndex);
185 				rFileName = aTmp.copy( nIndex+1 );
186 				m_pCurStore = m_pMainStore->openSubStorage( sPath, sal_True );
187 
188 				m_xOutputStream = m_pCurStore->openOutputStream( rFileName );
189 			}
190 			else
191 				m_xOutputStream = m_pMainStore->openOutputStream( rFileName );
192 
193 			if ( !m_xHandler.is() )
194 			{
195 				m_xHandler = Reference< XExtendedDocumentHandler >( m_rMultiFactory->createInstance(
196 					OUString::createFromAscii("com.sun.star.xml.sax.Writer")), UNO_QUERY );
197 			}
198 			Reference< XActiveDataSource > xSource( m_xHandler, UNO_QUERY );
199 			xSource->setOutputStream( m_xOutputStream );
200 
201 			if ( m_xHandler.is() )
202 				m_xHandler->startDocument();
203 			else
204 			{
205 				SAXException except;
206 				except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "startElement called before startDocument" ));
207 				throw except;
208 			}
209 		}
210 		catch( ::com::sun::star::uno::Exception& e )
211 		{
212 			OSL_ENSURE(0, ::rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US).getStr());
213 		}
214 	}
215 	else
216 	{
217 		if ( m_xHandler.is() )
218 			m_xHandler->endDocument();
219 	}
220 }
221 
222 /* -----
223     collect namesapce declaration of the <pzip:entry> element
224 ---- */
namespaceMap(const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & AttrList)225 void UOF2SplitHandler::namespaceMap( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& AttrList )
226 {
227 	sal_Int16 aAttrCount = AttrList->getLength();
228 	for ( sal_Int16 i = 0; i< aAttrCount; i++ )
229 	{
230 		OUString aName = AttrList->getNameByIndex( i );
231 		sal_Int32 nToken = aName.indexOf( sal_Unicode(':') );
232 		OUString aPrefix = aName.copy( 0, nToken );
233 		if ( aPrefix.equalsAscii("xmlns") )
234 		{
235 			if ( aNamespaceMap.find( aName ) == aNamespaceMap.end() )
236 			{
237 				OUString sType = AttrList->getTypeByIndex( i );
238 				OUString sValue = AttrList->getValueByIndex( i );
239 				aNamespaceMap.insert( ::std::map< OUString, NamespaceValue >::value_type(aName , NamespaceValue( sType , sValue )) );
240 			}
241 		}
242 	}
243 }
244