build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / xmloff / source / meta / xmlversion.cxx
blobcb664689a47708753adc69bd315b615153fe4bce
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/embed/ElementModes.hpp>
21 #include <unotools/streamwrap.hxx>
22 #include <xmlversion.hxx>
23 #include <xmloff/xmlmetae.hxx>
25 #include <xmloff/xmltoken.hxx>
26 #include <comphelper/processfactory.hxx>
27 #include <com/sun/star/io/XActiveDataSource.hpp>
28 #include <com/sun/star/io/XOutputStream.hpp>
29 #include <com/sun/star/util/DateTime.hpp>
30 #include <com/sun/star/util/MeasureUnit.hpp>
31 #include <com/sun/star/xml/sax/InputSource.hpp>
32 #include <com/sun/star/xml/sax/Parser.hpp>
33 #include <com/sun/star/xml/sax/Writer.hpp>
34 #include <cppuhelper/supportsservice.hxx>
36 using namespace ::com::sun::star::xml::sax;
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star;
40 const char XMLN_VERSIONSLIST[] = "VersionList.xml";
42 XMLVersionListExport::XMLVersionListExport(
43 const css::uno::Reference< css::uno::XComponentContext >& rContext,
44 const css::uno::Sequence < css::util::RevisionTag >& rVersions,
45 const OUString &rFileName,
46 Reference< XDocumentHandler > &rHandler )
47 : SvXMLExport( rContext, "", rFileName, util::MeasureUnit::CM, rHandler ),
48 maVersions( rVersions )
50 GetNamespaceMap_().AddAtIndex( XML_NAMESPACE_DC_IDX, xmloff::token::GetXMLToken(xmloff::token::XML_NP_DC),
51 xmloff::token::GetXMLToken(xmloff::token::XML_N_DC), XML_NAMESPACE_DC );
52 GetNamespaceMap_().AddAtIndex( XML_NAMESPACE_FRAMEWORK_IDX, xmloff::token::GetXMLToken(xmloff::token::XML_NP_VERSIONS_LIST),
53 xmloff::token::GetXMLToken(xmloff::token::XML_N_VERSIONS_LIST), XML_NAMESPACE_FRAMEWORK );
56 sal_uInt32 XMLVersionListExport::exportDoc( enum ::xmloff::token::XMLTokenEnum )
58 GetDocHandler()->startDocument();
60 addChaffWhenEncryptedStorage();
62 sal_uInt16 nPos = SvXMLNamespaceMap::GetIndexByKey( XML_NAMESPACE_DC );
64 AddAttribute( XML_NAMESPACE_NONE, GetNamespaceMap_().GetAttrNameByIndex( nPos ),
65 GetNamespaceMap_().GetNameByIndex ( nPos ) );
67 nPos = SvXMLNamespaceMap::GetIndexByKey( XML_NAMESPACE_FRAMEWORK );
68 AddAttribute( XML_NAMESPACE_NONE, GetNamespaceMap_().GetAttrNameByIndex( nPos ),
69 GetNamespaceMap_().GetNameByIndex ( nPos ) );
72 // the following object will write all collected attributes in its dtor
73 SvXMLElementExport aRoot( *this, XML_NAMESPACE_FRAMEWORK, xmloff::token::XML_VERSION_LIST, true, true );
75 for ( sal_Int32 n=0; n<maVersions.getLength(); n++ )
77 const util::RevisionTag& rInfo = maVersions[n];
78 AddAttribute( XML_NAMESPACE_FRAMEWORK,
79 xmloff::token::XML_TITLE,
80 OUString( rInfo.Identifier ) );
81 AddAttribute( XML_NAMESPACE_FRAMEWORK,
82 xmloff::token::XML_COMMENT,
83 OUString( rInfo.Comment ) );
84 AddAttribute( XML_NAMESPACE_FRAMEWORK,
85 xmloff::token::XML_CREATOR,
86 OUString( rInfo.Author ) );
88 OUString aDateStr =
89 SvXMLMetaExport::GetISODateTimeString( rInfo.TimeStamp );
91 AddAttribute( XML_NAMESPACE_DC, xmloff::token::XML_DATE_TIME, aDateStr );
93 // the following object will write all collected attributes in its dtor
94 SvXMLElementExport aEntry( *this, XML_NAMESPACE_FRAMEWORK, xmloff::token::XML_VERSION_ENTRY, true, true );
97 GetDocHandler()->endDocument();
98 return 0;
101 XMLVersionListImport::XMLVersionListImport(
102 const css::uno::Reference< css::uno::XComponentContext >& rContext,
103 css::uno::Sequence < css::util::RevisionTag >& rVersions )
104 : SvXMLImport(rContext, ""),
105 maVersions( rVersions )
107 GetNamespaceMap().AddAtIndex( XML_NAMESPACE_FRAMEWORK_IDX, xmloff::token::GetXMLToken(xmloff::token::XML_NP_VERSIONS_LIST),
108 xmloff::token::GetXMLToken(xmloff::token::XML_N_VERSIONS_LIST), XML_NAMESPACE_FRAMEWORK );
111 XMLVersionListImport::~XMLVersionListImport() throw()
114 SvXMLImportContext *XMLVersionListImport::CreateContext(
115 sal_uInt16 nPrefix,
116 const OUString& rLocalName,
117 const Reference< XAttributeList > & xAttrList )
119 SvXMLImportContext *pContext = nullptr;
121 if ( XML_NAMESPACE_FRAMEWORK == nPrefix &&
122 rLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_VERSION_LIST) )
124 pContext = new XMLVersionListContext( *this, nPrefix, rLocalName, xAttrList );
126 else
128 pContext = SvXMLImport::CreateContext( nPrefix, rLocalName, xAttrList );
131 return pContext;
134 XMLVersionListContext::XMLVersionListContext( XMLVersionListImport& rImport,
135 sal_uInt16 nPrefix,
136 const OUString& rLocalName,
137 const Reference< XAttributeList > & )
138 : SvXMLImportContext( rImport, nPrefix, rLocalName )
139 , rLocalRef( rImport )
143 XMLVersionListContext::~XMLVersionListContext()
146 SvXMLImportContext *XMLVersionListContext::CreateChildContext( sal_uInt16 nPrefix,
147 const OUString& rLocalName,
148 const Reference< XAttributeList > & xAttrList )
150 SvXMLImportContext *pContext = nullptr;
152 if ( nPrefix == XML_NAMESPACE_FRAMEWORK &&
153 rLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_VERSION_ENTRY) )
155 pContext = new XMLVersionContext( rLocalRef, nPrefix, rLocalName, xAttrList );
157 else
159 pContext = new SvXMLImportContext( rLocalRef, nPrefix, rLocalName );
162 return pContext;
165 XMLVersionContext::XMLVersionContext( XMLVersionListImport& rImport,
166 sal_uInt16 nPref,
167 const OUString& rLocalName,
168 const Reference< XAttributeList > & xAttrList )
169 : SvXMLImportContext( rImport, nPref, rLocalName )
170 , rLocalRef( rImport )
172 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
174 if ( !nAttrCount )
175 return;
177 util::RevisionTag aInfo;
178 for ( sal_Int16 i=0; i < nAttrCount; i++ )
180 OUString aLocalName;
181 const OUString& rAttrName = xAttrList->getNameByIndex( i );
182 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName );
184 if ( XML_NAMESPACE_FRAMEWORK == nPrefix )
186 if ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_TITLE) )
188 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
189 aInfo.Identifier = rAttrValue;
191 else if ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_COMMENT) )
193 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
194 aInfo.Comment = rAttrValue;
196 else if ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_CREATOR) )
198 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
199 aInfo.Author = rAttrValue;
202 else if ( ( XML_NAMESPACE_DC == nPrefix ) &&
203 ( aLocalName == xmloff::token::GetXMLToken(xmloff::token::XML_DATE_TIME) ) )
205 const OUString& rAttrValue = xAttrList->getValueByIndex( i );
206 util::DateTime aTime;
207 if ( ParseISODateTimeString( rAttrValue, aTime ) )
208 aInfo.TimeStamp = aTime;
212 uno::Sequence < util::RevisionTag >& aList = rLocalRef.GetList();
213 sal_Int32 nLength = aList.getLength();
214 aList.realloc( nLength+1 );
215 aList[nLength] = aInfo;
218 XMLVersionContext::~XMLVersionContext()
221 bool XMLVersionContext::ParseISODateTimeString(
222 const OUString& rString,
223 util::DateTime& rDateTime )
225 bool bSuccess = true;
227 OUString aDateStr, aTimeStr;
228 sal_Int32 nPos = rString.indexOf( (sal_Unicode) 'T' );
229 if ( nPos >= 0 )
231 aDateStr = rString.copy( 0, nPos );
232 aTimeStr = rString.copy( nPos + 1 );
234 else
235 aDateStr = rString; // no separator: only date part
237 sal_Int32 nYear = 0;
238 sal_Int32 nMonth = 1;
239 sal_Int32 nDay = 1;
240 sal_Int32 nHour = 0;
241 sal_Int32 nMin = 0;
242 sal_Int32 nSec = 0;
244 const sal_Unicode* pStr = aDateStr.getStr();
245 sal_Int32 nDateTokens = 1;
246 while ( *pStr )
248 if ( *pStr == '-' )
249 nDateTokens++;
250 pStr++;
252 if ( nDateTokens > 3 || aDateStr.isEmpty() )
253 bSuccess = false;
254 else
256 sal_Int32 n = 0;
257 nYear = aDateStr.getToken( 0, '-', n ).toInt32();
258 if ( nYear > 9999 )
259 bSuccess = false;
260 else if ( nDateTokens >= 2 )
262 nMonth = aDateStr.getToken( 0, '-', n ).toInt32();
263 if ( nMonth > 12 )
264 bSuccess = false;
265 else if ( nDateTokens >= 3 )
267 nDay = aDateStr.getToken( 0, '-', n ).toInt32();
268 if ( nDay > 31 )
269 bSuccess = false;
274 if ( bSuccess && !aTimeStr.isEmpty() ) // time is optional
276 pStr = aTimeStr.getStr();
277 sal_Int32 nTimeTokens = 1;
278 while ( *pStr )
280 if ( *pStr == ':' )
281 nTimeTokens++;
282 pStr++;
284 if ( nTimeTokens > 3 )
285 bSuccess = false;
286 else
288 sal_Int32 n = 0;
289 nHour = aTimeStr.getToken( 0, ':', n ).toInt32();
290 if ( nHour > 23 )
291 bSuccess = false;
292 else if ( nTimeTokens >= 2 )
294 nMin = aTimeStr.getToken( 0, ':', n ).toInt32();
295 if ( nMin > 59 )
296 bSuccess = false;
297 else if ( nTimeTokens >= 3 )
299 nSec = aTimeStr.getToken( 0, ':', n ).toInt32();
300 if ( nSec > 59 )
301 bSuccess = false;
307 if ( bSuccess )
309 rDateTime.Day = sal::static_int_cast< sal_uInt16 >(nDay);
310 rDateTime.Month = sal::static_int_cast< sal_uInt16 >(nMonth);
311 rDateTime.Year = sal::static_int_cast< sal_uInt16 >(nYear);
312 rDateTime.Hours = sal::static_int_cast< sal_uInt16 >(nHour);
313 rDateTime.Minutes = sal::static_int_cast< sal_uInt16 >(nMin);
314 rDateTime.Seconds = sal::static_int_cast< sal_uInt16 >(nSec);
317 return bSuccess;
320 void SAL_CALL XMLVersionListPersistence::store( const uno::Reference< embed::XStorage >& xRoot, const uno::Sequence< util::RevisionTag >& rVersions )
321 throw (css::io::IOException, css::uno::Exception, css::uno::RuntimeException, std::exception)
323 // no storage, no version list!
324 if ( xRoot.is() )
326 // get the services needed for writing the xml data
327 Reference< uno::XComponentContext > xContext =
328 comphelper::getProcessComponentContext();
330 Reference< XWriter > xWriter = Writer::create(xContext);
332 // check whether there's already a sub storage with the version info
333 // and delete it
334 OUString sVerName( XMLN_VERSIONSLIST );
336 try {
337 // open (create) the sub storage with the version info
338 uno::Reference< io::XStream > xVerStream = xRoot->openStreamElement(
339 sVerName,
340 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
341 if ( !xVerStream.is() )
342 throw uno::RuntimeException();
344 Reference< io::XOutputStream > xOut = xVerStream->getOutputStream();
345 if ( !xOut.is() )
346 throw uno::RuntimeException(); // the stream was successfully opened for writing already
348 Reference< io::XActiveDataSource > xSrc( xWriter, uno::UNO_QUERY );
349 xSrc->setOutputStream(xOut);
351 Reference< XDocumentHandler > xHandler( xWriter, uno::UNO_QUERY );
353 rtl::Reference< XMLVersionListExport > xExp( new XMLVersionListExport( xContext, rVersions, sVerName, xHandler ) );
355 xExp->exportDoc( ::xmloff::token::XML_VERSION );
357 xVerStream.clear(); // use refcounting for now to dispose
359 catch( uno::Exception& )
361 // TODO: error handling
366 uno::Sequence< util::RevisionTag > SAL_CALL XMLVersionListPersistence::load( const uno::Reference< embed::XStorage >& xRoot )
367 throw (css::container::NoSuchElementException, css::io::IOException, css::uno::Exception, css::uno::RuntimeException, std::exception)
369 css::uno::Sequence < css::util::RevisionTag > aVersions;
371 const OUString sDocName( XMLN_VERSIONSLIST );
372 uno::Reference< container::XNameAccess > xRootNames( xRoot, uno::UNO_QUERY );
374 try {
375 if ( xRootNames.is() && xRootNames->hasByName( sDocName ) && xRoot->isStreamElement( sDocName ) )
377 Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
379 InputSource aParserInput;
381 uno::Reference< beans::XPropertySet > xProps( xRoot, uno::UNO_QUERY );
382 OSL_ENSURE( xProps.is(), "Storage must implement XPropertySet!\n" );
383 if ( xProps.is() )
385 try {
386 xProps->getPropertyValue("URL") >>= aParserInput.sSystemId;
388 catch( uno::Exception& )
392 uno::Reference< io::XStream > xDocStream = xRoot->openStreamElement(
393 sDocName,
394 embed::ElementModes::READ );
395 if ( !xDocStream.is() )
396 throw uno::RuntimeException();
398 aParserInput.aInputStream = xDocStream->getInputStream();
399 OSL_ENSURE( aParserInput.aInputStream.is(),
400 "The stream was successfully opened for reading, the input part must be accessible!\n" );
401 if ( !aParserInput.aInputStream.is() )
402 throw uno::RuntimeException();
404 // get filter
405 Reference< XDocumentHandler > xFilter = new XMLVersionListImport( xContext, aVersions );
407 // connect parser and filter
408 Reference< XParser > xParser = xml::sax::Parser::create(xContext);
409 xParser->setDocumentHandler( xFilter );
411 // parse
414 xParser->parseStream( aParserInput );
416 catch( SAXParseException& ) {}
417 catch( SAXException& ) {}
418 catch( io::IOException& ) {}
421 catch( uno::Exception& )
423 // TODO: error handling
426 return aVersions;
429 OUString XMLVersionListPersistence::getImplementationName()
430 throw (css::uno::RuntimeException, std::exception)
432 return OUString("XMLVersionListPersistence");
435 sal_Bool XMLVersionListPersistence::supportsService(
436 OUString const & ServiceName)
437 throw (css::uno::RuntimeException, std::exception)
439 return cppu::supportsService(this, ServiceName);
442 css::uno::Sequence<OUString>
443 XMLVersionListPersistence::getSupportedServiceNames()
444 throw (css::uno::RuntimeException, std::exception)
446 return css::uno::Sequence<OUString>{
447 "com.sun.star.document.DocumentRevisionListPersistence"};
450 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
451 XMLVersionListPersistence_get_implementation(
452 css::uno::XComponentContext *,
453 css::uno::Sequence<css::uno::Any> const &)
455 return cppu::acquire(new XMLVersionListPersistence());
458 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */