1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
23 #include <string_view>
25 #include <oox/core/relations.hxx>
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/")
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
) )
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
;
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() )
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
);
125 aPath
= lclAppendFileName( aPath
, rRelation
.maTarget
.copy( nStartPos
, nSepPos
- nStartPos
) );
126 // move nStartPos to next directory name
127 nStartPos
= nSepPos
+ 1;
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
);
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: */