LibreOffice Module oox (master) 1
relations.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
22#include <algorithm>
23#include <string_view>
24
26#include <utility>
27
28namespace oox::core {
29
30namespace {
31
32std::u16string_view lclRemoveFileName( std::u16string_view rPath )
33{
34 size_t idx = rPath.rfind( '/' );
35 if (idx == std::u16string_view::npos)
36 return std::u16string_view();
37 return rPath.substr( 0, idx );
38}
39
40OUString lclAppendFileName( std::u16string_view rPath, const OUString& rFileName )
41{
42 return rPath.empty() ? rFileName :
43 rPath + OUStringChar('/') + rFileName;
44}
45
46OUString createOfficeDocRelationTypeTransitional(std::u16string_view rType)
47{
48 return OUString::Concat("http://schemas.openxmlformats.org/officeDocument/2006/relationships/")
49 + rType;
50}
51
52OUString createOfficeDocRelationTypeStrict(std::u16string_view rType)
53{
54 return OUString::Concat("http://purl.oclc.org/ooxml/officeDocument/relationships/") + rType;
55}
56
57}
58
59Relations::Relations( OUString aFragmentPath )
60 : maFragmentPath(std::move( aFragmentPath ))
61{
62}
63
64const Relation* Relations::getRelationFromRelId( const OUString& rId ) const
65{
66 ::std::map< OUString, Relation >::const_iterator aIt = maMap.find( rId );
67 return (aIt == maMap.end()) ? nullptr : &aIt->second;
68}
69
70const Relation* Relations::getRelationFromFirstType( std::u16string_view rType ) const
71{
72 for (auto const& elem : maMap)
73 if( elem.second.maType.equalsIgnoreAsciiCase( rType ) )
74 return &elem.second;
75 return nullptr;
76}
77
79{
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;
86}
87
88OUString Relations::getExternalTargetFromRelId( const OUString& rRelId ) const
89{
90 const Relation* pRelation = getRelationFromRelId( rRelId );
91 return (pRelation && pRelation->mbExternal) ? pRelation->maTarget : OUString();
92}
93
94OUString Relations::getInternalTargetFromRelId( const OUString& rRelId ) const
95{
96 const Relation* pRelation = getRelationFromRelId( rRelId );
97 return (pRelation && !pRelation->mbExternal) ? pRelation->maTarget : OUString();
98}
99
100OUString Relations::getFragmentPathFromRelation( const Relation& rRelation ) const
101{
102 // no target, no fragment path
103 if( rRelation.mbExternal || rRelation.maTarget.isEmpty() )
104 return OUString();
105
106 // absolute target: return it without leading slash (#i100978)
107 if( rRelation.maTarget[ 0 ] == '/' )
108 return rRelation.maTarget.copy( 1 );
109
110 // empty fragment path: return target
111 if( maFragmentPath.isEmpty() )
112 return rRelation.maTarget;
113
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() )
118 {
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;
128 }
129
130 return aPath;
131}
132
133OUString Relations::getFragmentPathFromRelId( const OUString& rRelId ) const
134{
135 const Relation* pRelation = getRelationFromRelId( rRelId );
136 return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
137}
138
139OUString Relations::getFragmentPathFromFirstType( std::u16string_view rType ) const
140{
141 const Relation* pRelation = getRelationFromFirstType( rType );
142 return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
143}
144
145OUString Relations::getFragmentPathFromFirstTypeFromOfficeDoc( std::u16string_view rType ) const
146{
147 OUString aTransitionalType(createOfficeDocRelationTypeTransitional(rType));
148 const Relation* pRelation = getRelationFromFirstType( aTransitionalType );
149 if(!pRelation)
150 {
151 OUString aStrictType = createOfficeDocRelationTypeStrict(rType);
152 pRelation = getRelationFromFirstType( aStrictType );
153 }
154 return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
155}
156
157} // namespace oox::core
158
159/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::map< OUString, Relation > maMap
Definition: relations.hxx:111
OUString getInternalTargetFromRelId(const OUString &rRelId) const
Returns the internal target of the relation with the passed relation identifier.
Definition: relations.cxx:94
const Relation * getRelationFromFirstType(std::u16string_view rType) const
Returns the first relation with the passed type.
Definition: relations.cxx:70
OUString getFragmentPathFromRelId(const OUString &rRelId) const
Returns the full fragment path for the passed relation identifier.
Definition: relations.cxx:133
OUString getExternalTargetFromRelId(const OUString &rRelId) const
Returns the external target of the relation with the passed relation identifier.
Definition: relations.cxx:88
OUString getFragmentPathFromRelation(const Relation &rRelation) const
Returns the full fragment path for the target of the passed relation.
Definition: relations.cxx:100
const Relation * getRelationFromRelId(const OUString &rId) const
Returns the relation with the passed relation identifier.
Definition: relations.cxx:64
Relations(OUString aFragmentPath)
Definition: relations.cxx:59
OUString getFragmentPathFromFirstTypeFromOfficeDoc(std::u16string_view rType) const
Definition: relations.cxx:145
OUString getFragmentPathFromFirstType(std::u16string_view rType) const
Returns the full fragment path for the first relation of the passed type.
Definition: relations.cxx:139
RelationsRef getRelationsFromTypeFromOfficeDoc(std::u16string_view rType) const
Finds all relations associated with the passed type.
Definition: relations.cxx:78
const sal_uInt16 idx[]
std::shared_ptr< Relations > RelationsRef
Definition: relations.hxx:63