Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / oox / source / core / relations.cxx
blobcda3f451094a52e52af0e503d8956394e1587916
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 <sal/config.h>
22 #include <algorithm>
23 #include <string_view>
25 #include <oox/core/relations.hxx>
26 #include <utility>
28 namespace oox::core {
30 namespace {
32 std::u16string_view lclRemoveFileName( std::u16string_view rPath )
34 size_t idx = rPath.rfind( '/' );
35 if (idx == std::u16string_view::npos)
36 return std::u16string_view();
37 return rPath.substr( 0, idx );
40 OUString lclAppendFileName( std::u16string_view rPath, const OUString& rFileName )
42 return rPath.empty() ? rFileName :
43 rPath + OUStringChar('/') + rFileName;
46 OUString createOfficeDocRelationTypeTransitional(std::u16string_view rType)
48 return OUString::Concat("http://schemas.openxmlformats.org/officeDocument/2006/relationships/")
49 + rType;
52 OUString createOfficeDocRelationTypeStrict(std::u16string_view rType)
54 return OUString::Concat("http://purl.oclc.org/ooxml/officeDocument/relationships/") + rType;
59 Relations::Relations( OUString aFragmentPath )
60 : maFragmentPath(std::move( aFragmentPath ))
64 const Relation* Relations::getRelationFromRelId( const OUString& rId ) const
66 ::std::map< OUString, Relation >::const_iterator aIt = maMap.find( rId );
67 return (aIt == maMap.end()) ? nullptr : &aIt->second;
70 const Relation* Relations::getRelationFromFirstType( std::u16string_view rType ) const
72 for (auto const& elem : maMap)
73 if( elem.second.maType.equalsIgnoreAsciiCase( rType ) )
74 return &elem.second;
75 return nullptr;
78 RelationsRef Relations::getRelationsFromTypeFromOfficeDoc( std::u16string_view rType ) const
80 RelationsRef xRelations = std::make_shared<Relations>( maFragmentPath );
81 for (auto const& elem : maMap)
82 if( elem.second.maType.equalsIgnoreAsciiCase( createOfficeDocRelationTypeTransitional(rType) ) ||
83 elem.second.maType.equalsIgnoreAsciiCase( createOfficeDocRelationTypeStrict(rType) ))
84 xRelations->maMap[ elem.first ] = elem.second;
85 return xRelations;
88 OUString Relations::getExternalTargetFromRelId( const OUString& rRelId ) const
90 const Relation* pRelation = getRelationFromRelId( rRelId );
91 return (pRelation && pRelation->mbExternal) ? pRelation->maTarget : OUString();
94 OUString Relations::getInternalTargetFromRelId( const OUString& rRelId ) const
96 const Relation* pRelation = getRelationFromRelId( rRelId );
97 return (pRelation && !pRelation->mbExternal) ? pRelation->maTarget : OUString();
100 OUString Relations::getFragmentPathFromRelation( const Relation& rRelation ) const
102 // no target, no fragment path
103 if( rRelation.mbExternal || rRelation.maTarget.isEmpty() )
104 return OUString();
106 // absolute target: return it without leading slash (#i100978)
107 if( rRelation.maTarget[ 0 ] == '/' )
108 return rRelation.maTarget.copy( 1 );
110 // empty fragment path: return target
111 if( maFragmentPath.isEmpty() )
112 return rRelation.maTarget;
114 // resolve relative target path according to base path
115 OUString aPath( lclRemoveFileName( maFragmentPath ) );
116 sal_Int32 nStartPos = 0;
117 while( nStartPos < rRelation.maTarget.getLength() )
119 sal_Int32 nSepPos = rRelation.maTarget.indexOf( '/', nStartPos );
120 if( nSepPos < 0 ) nSepPos = rRelation.maTarget.getLength();
121 // append next directory name from aTarget to aPath, or remove last directory on '../'
122 if( (nStartPos + 2 == nSepPos) && (rRelation.maTarget[ nStartPos ] == '.') && (rRelation.maTarget[ nStartPos + 1 ] == '.') )
123 aPath = lclRemoveFileName( aPath );
124 else
125 aPath = lclAppendFileName( aPath, rRelation.maTarget.copy( nStartPos, nSepPos - nStartPos ) );
126 // move nStartPos to next directory name
127 nStartPos = nSepPos + 1;
130 return aPath;
133 OUString Relations::getFragmentPathFromRelId( const OUString& rRelId ) const
135 const Relation* pRelation = getRelationFromRelId( rRelId );
136 return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
139 OUString Relations::getFragmentPathFromFirstType( std::u16string_view rType ) const
141 const Relation* pRelation = getRelationFromFirstType( rType );
142 return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
145 OUString Relations::getFragmentPathFromFirstTypeFromOfficeDoc( std::u16string_view rType ) const
147 OUString aTransitionalType(createOfficeDocRelationTypeTransitional(rType));
148 const Relation* pRelation = getRelationFromFirstType( aTransitionalType );
149 if(!pRelation)
151 OUString aStrictType = createOfficeDocRelationTypeStrict(rType);
152 pRelation = getRelationFromFirstType( aStrictType );
154 return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
157 } // namespace oox::core
159 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */