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 "oox/core/relations.hxx"
22 #include <rtl/ustrbuf.hxx>
23 #include "oox/helper/helper.hxx"
30 OUString
lclRemoveFileName( const OUString
& rPath
)
32 return rPath
.copy( 0, ::std::max
< sal_Int32
>( rPath
.lastIndexOf( '/' ), 0 ) );
35 OUString
lclAppendFileName( const OUString
& rPath
, const OUString
& rFileName
)
37 return rPath
.isEmpty() ? rFileName
:
38 OUStringBuffer( rPath
).append( '/' ).append( rFileName
).makeStringAndClear();
41 OUString
createOfficeDocRelationTypeTransitional(const OUString
& rType
)
43 return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/" + rType
;
46 OUString
createOfficeDocRelationTypeStrict(const OUString
& rType
)
48 return "http://purl.oclc.org/ooxml/officeDocument/relationships/" + rType
;
53 Relations::Relations( const OUString
& rFragmentPath
)
55 , maFragmentPath( rFragmentPath
)
59 const Relation
* Relations::getRelationFromRelId( const OUString
& rId
) const
61 ::std::map
< OUString
, Relation
>::const_iterator aIt
= maMap
.find( rId
);
62 return (aIt
== maMap
.end()) ? 0 : &aIt
->second
;
65 const Relation
* Relations::getRelationFromFirstType( const OUString
& rType
) const
67 for( ::std::map
< OUString
, Relation
>::const_iterator aIt
= maMap
.begin(), aEnd
= maMap
.end(); aIt
!= aEnd
; ++aIt
)
68 if( aIt
->second
.maType
.equalsIgnoreAsciiCase( rType
) )
73 RelationsRef
Relations::getRelationsFromTypeFromOfficeDoc( const OUString
& rType
) const
75 RelationsRef
xRelations( new Relations( maFragmentPath
) );
76 for( ::std::map
< OUString
, Relation
>::const_iterator aIt
= maMap
.begin(), aEnd
= maMap
.end(); aIt
!= aEnd
; ++aIt
)
77 if( aIt
->second
.maType
.equalsIgnoreAsciiCase( createOfficeDocRelationTypeTransitional(rType
) ) ||
78 aIt
->second
.maType
.equalsIgnoreAsciiCase( createOfficeDocRelationTypeStrict(rType
) ))
79 xRelations
->maMap
[ aIt
->first
] = aIt
->second
;
83 OUString
Relations::getExternalTargetFromRelId( const OUString
& rRelId
) const
85 const Relation
* pRelation
= getRelationFromRelId( rRelId
);
86 return (pRelation
&& pRelation
->mbExternal
) ? pRelation
->maTarget
: OUString();
89 OUString
Relations::getInternalTargetFromRelId( const OUString
& rRelId
) const
91 const Relation
* pRelation
= getRelationFromRelId( rRelId
);
92 return (pRelation
&& !pRelation
->mbExternal
) ? pRelation
->maTarget
: OUString();
95 OUString
Relations::getFragmentPathFromRelation( const Relation
& rRelation
) const
97 // no target, no fragment path
98 if( rRelation
.mbExternal
|| rRelation
.maTarget
.isEmpty() )
101 // absolute target: return it without leading slash (#i100978)
102 if( rRelation
.maTarget
[ 0 ] == '/' )
103 return rRelation
.maTarget
.copy( 1 );
105 // empty fragment path: return target
106 if( maFragmentPath
.isEmpty() )
107 return rRelation
.maTarget
;
109 // resolve relative target path according to base path
110 OUString aPath
= lclRemoveFileName( maFragmentPath
);
111 sal_Int32 nStartPos
= 0;
112 while( nStartPos
< rRelation
.maTarget
.getLength() )
114 sal_Int32 nSepPos
= rRelation
.maTarget
.indexOf( '/', nStartPos
);
115 if( nSepPos
< 0 ) nSepPos
= rRelation
.maTarget
.getLength();
116 // append next directory name from aTarget to aPath, or remove last directory on '../'
117 if( (nStartPos
+ 2 == nSepPos
) && (rRelation
.maTarget
[ nStartPos
] == '.') && (rRelation
.maTarget
[ nStartPos
+ 1 ] == '.') )
118 aPath
= lclRemoveFileName( aPath
);
120 aPath
= lclAppendFileName( aPath
, rRelation
.maTarget
.copy( nStartPos
, nSepPos
- nStartPos
) );
121 // move nStartPos to next directory name
122 nStartPos
= nSepPos
+ 1;
128 OUString
Relations::getFragmentPathFromRelId( const OUString
& rRelId
) const
130 const Relation
* pRelation
= getRelationFromRelId( rRelId
);
131 return pRelation
? getFragmentPathFromRelation( *pRelation
) : OUString();
134 OUString
Relations::getFragmentPathFromFirstType( const OUString
& rType
) const
136 const Relation
* pRelation
= getRelationFromFirstType( rType
);
137 return pRelation
? getFragmentPathFromRelation( *pRelation
) : OUString();
140 OUString
Relations::getFragmentPathFromFirstTypeFromOfficeDoc( const OUString
& rType
) const
142 OUString
aTransitionalType(createOfficeDocRelationTypeTransitional(rType
));
143 const Relation
* pRelation
= getRelationFromFirstType( aTransitionalType
);
146 OUString aStrictType
= createOfficeDocRelationTypeStrict(rType
);
147 pRelation
= getRelationFromFirstType( aStrictType
);
149 return pRelation
? getFragmentPathFromRelation( *pRelation
) : OUString();
155 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */