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 
25 #include <oox/core/relations.hxx>
26 
27 namespace oox::core {
28 
29 namespace {
30 
31 OUString lclRemoveFileName( const OUString& rPath )
32 {
33  return rPath.copy( 0, ::std::max< sal_Int32 >( rPath.lastIndexOf( '/' ), 0 ) );
34 }
35 
36 OUString lclAppendFileName( std::u16string_view rPath, const OUString& rFileName )
37 {
38  return rPath.empty() ? rFileName :
39  rPath + OUStringChar('/') + rFileName;
40 }
41 
42 OUString createOfficeDocRelationTypeTransitional(std::u16string_view rType)
43 {
44  return OUString::Concat("http://schemas.openxmlformats.org/officeDocument/2006/relationships/")
45  + rType;
46 }
47 
48 OUString createOfficeDocRelationTypeStrict(std::u16string_view rType)
49 {
50  return OUString::Concat("http://purl.oclc.org/ooxml/officeDocument/relationships/") + rType;
51 }
52 
53 }
54 
55 Relations::Relations( const OUString& rFragmentPath )
56  : maFragmentPath( rFragmentPath )
57 {
58 }
59 
60 const Relation* Relations::getRelationFromRelId( const OUString& rId ) const
61 {
62  ::std::map< OUString, Relation >::const_iterator aIt = maMap.find( rId );
63  return (aIt == maMap.end()) ? nullptr : &aIt->second;
64 }
65 
66 const Relation* Relations::getRelationFromFirstType( std::u16string_view rType ) const
67 {
68  for (auto const& elem : maMap)
69  if( elem.second.maType.equalsIgnoreAsciiCase( rType ) )
70  return &elem.second;
71  return nullptr;
72 }
73 
75 {
76  RelationsRef xRelations = std::make_shared<Relations>( maFragmentPath );
77  for (auto const& elem : maMap)
78  if( elem.second.maType.equalsIgnoreAsciiCase( createOfficeDocRelationTypeTransitional(rType) ) ||
79  elem.second.maType.equalsIgnoreAsciiCase( createOfficeDocRelationTypeStrict(rType) ))
80  xRelations->maMap[ elem.first ] = elem.second;
81  return xRelations;
82 }
83 
84 OUString Relations::getExternalTargetFromRelId( const OUString& rRelId ) const
85 {
86  const Relation* pRelation = getRelationFromRelId( rRelId );
87  return (pRelation && pRelation->mbExternal) ? pRelation->maTarget : OUString();
88 }
89 
90 OUString Relations::getInternalTargetFromRelId( const OUString& rRelId ) const
91 {
92  const Relation* pRelation = getRelationFromRelId( rRelId );
93  return (pRelation && !pRelation->mbExternal) ? pRelation->maTarget : OUString();
94 }
95 
96 OUString Relations::getFragmentPathFromRelation( const Relation& rRelation ) const
97 {
98  // no target, no fragment path
99  if( rRelation.mbExternal || rRelation.maTarget.isEmpty() )
100  return OUString();
101 
102  // absolute target: return it without leading slash (#i100978)
103  if( rRelation.maTarget[ 0 ] == '/' )
104  return rRelation.maTarget.copy( 1 );
105 
106  // empty fragment path: return target
107  if( maFragmentPath.isEmpty() )
108  return rRelation.maTarget;
109 
110  // resolve relative target path according to base path
111  OUString aPath = lclRemoveFileName( maFragmentPath );
112  sal_Int32 nStartPos = 0;
113  while( nStartPos < rRelation.maTarget.getLength() )
114  {
115  sal_Int32 nSepPos = rRelation.maTarget.indexOf( '/', nStartPos );
116  if( nSepPos < 0 ) nSepPos = rRelation.maTarget.getLength();
117  // append next directory name from aTarget to aPath, or remove last directory on '../'
118  if( (nStartPos + 2 == nSepPos) && (rRelation.maTarget[ nStartPos ] == '.') && (rRelation.maTarget[ nStartPos + 1 ] == '.') )
119  aPath = lclRemoveFileName( aPath );
120  else
121  aPath = lclAppendFileName( aPath, rRelation.maTarget.copy( nStartPos, nSepPos - nStartPos ) );
122  // move nStartPos to next directory name
123  nStartPos = nSepPos + 1;
124  }
125 
126  return aPath;
127 }
128 
129 OUString Relations::getFragmentPathFromRelId( const OUString& rRelId ) const
130 {
131  const Relation* pRelation = getRelationFromRelId( rRelId );
132  return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
133 }
134 
135 OUString Relations::getFragmentPathFromFirstType( std::u16string_view rType ) const
136 {
137  const Relation* pRelation = getRelationFromFirstType( rType );
138  return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
139 }
140 
141 OUString Relations::getFragmentPathFromFirstTypeFromOfficeDoc( std::u16string_view rType ) const
142 {
143  OUString aTransitionalType(createOfficeDocRelationTypeTransitional(rType));
144  const Relation* pRelation = getRelationFromFirstType( aTransitionalType );
145  if(!pRelation)
146  {
147  OUString aStrictType = createOfficeDocRelationTypeStrict(rType);
148  pRelation = getRelationFromFirstType( aStrictType );
149  }
150  return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
151 }
152 
153 } // namespace oox::core
154 
155 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::shared_ptr< Relations > RelationsRef
Definition: relations.hxx:63
OUString getInternalTargetFromRelId(const OUString &rRelId) const
Returns the internal target of the relation with the passed relation identifier.
Definition: relations.cxx:90
::std::map< OUString, Relation > maMap
Definition: relations.hxx:111
const Relation * getRelationFromFirstType(std::u16string_view rType) const
Returns the first relation with the passed type.
Definition: relations.cxx:66
OUString getExternalTargetFromRelId(const OUString &rRelId) const
Returns the external target of the relation with the passed relation identifier.
Definition: relations.cxx:84
const Relation * getRelationFromRelId(const OUString &rId) const
Returns the relation with the passed relation identifier.
Definition: relations.cxx:60
RelationsRef getRelationsFromTypeFromOfficeDoc(std::u16string_view rType) const
Finds all relations associated with the passed type.
Definition: relations.cxx:74
OUString getFragmentPathFromFirstType(std::u16string_view rType) const
Returns the full fragment path for the first relation of the passed type.
Definition: relations.cxx:135
OUString getFragmentPathFromRelation(const Relation &rRelation) const
Returns the full fragment path for the target of the passed relation.
Definition: relations.cxx:96
Relations(const OUString &rFragmentPath)
Definition: relations.cxx:55
OUString getFragmentPathFromRelId(const OUString &rRelId) const
Returns the full fragment path for the passed relation identifier.
Definition: relations.cxx:129
OUString getFragmentPathFromFirstTypeFromOfficeDoc(std::u16string_view rType) const
Definition: relations.cxx:141