Line data Source code
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 "oox/core/relations.hxx"
21 :
22 : #include <rtl/ustrbuf.hxx>
23 : #include "oox/helper/helper.hxx"
24 :
25 : namespace oox {
26 : namespace core {
27 :
28 : namespace {
29 :
30 5772 : OUString lclRemoveFileName( const OUString& rPath )
31 : {
32 5772 : return rPath.copy( 0, ::std::max< sal_Int32 >( rPath.lastIndexOf( '/' ), 0 ) );
33 : }
34 :
35 9542 : OUString lclAppendFileName( const OUString& rPath, const OUString& rFileName )
36 : {
37 9542 : return rPath.isEmpty() ? rFileName :
38 9542 : OUStringBuffer( rPath ).append( '/' ).append( rFileName ).makeStringAndClear();
39 : }
40 :
41 4987 : OUString createOfficeDocRelationTypeTransitional(const OUString& rType)
42 : {
43 4987 : return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/" + rType;
44 : }
45 :
46 1646 : OUString createOfficeDocRelationTypeStrict(const OUString& rType)
47 : {
48 1646 : return "http://purl.oclc.org/ooxml/officeDocument/relationships/" + rType;
49 : }
50 :
51 : }
52 :
53 4805 : Relations::Relations( const OUString& rFragmentPath )
54 : : maMap()
55 4805 : , maFragmentPath( rFragmentPath )
56 : {
57 4805 : }
58 :
59 1799 : const Relation* Relations::getRelationFromRelId( const OUString& rId ) const
60 : {
61 1799 : ::std::map< OUString, Relation >::const_iterator aIt = maMap.find( rId );
62 1799 : return (aIt == maMap.end()) ? 0 : &aIt->second;
63 : }
64 :
65 6341 : const Relation* Relations::getRelationFromFirstType( const OUString& rType ) const
66 : {
67 33207 : for( ::std::map< OUString, Relation >::const_iterator aIt = maMap.begin(), aEnd = maMap.end(); aIt != aEnd; ++aIt )
68 30374 : if( aIt->second.maType.equalsIgnoreAsciiCase( rType ) )
69 3508 : return &aIt->second;
70 2833 : return 0;
71 : }
72 :
73 882 : RelationsRef Relations::getRelationsFromTypeFromOfficeDoc( const OUString& rType ) const
74 : {
75 882 : RelationsRef xRelations( new Relations( maFragmentPath ) );
76 1329 : for( ::std::map< OUString, Relation >::const_iterator aIt = maMap.begin(), aEnd = maMap.end(); aIt != aEnd; ++aIt )
77 1624 : if( aIt->second.maType.equalsIgnoreAsciiCase( createOfficeDocRelationTypeTransitional(rType) ) ||
78 1177 : aIt->second.maType.equalsIgnoreAsciiCase( createOfficeDocRelationTypeStrict(rType) ))
79 82 : xRelations->maMap[ aIt->first ] = aIt->second;
80 882 : return xRelations;
81 : }
82 :
83 18 : OUString Relations::getExternalTargetFromRelId( const OUString& rRelId ) const
84 : {
85 18 : const Relation* pRelation = getRelationFromRelId( rRelId );
86 18 : return (pRelation && pRelation->mbExternal) ? pRelation->maTarget : OUString();
87 : }
88 :
89 2 : OUString Relations::getInternalTargetFromRelId( const OUString& rRelId ) const
90 : {
91 2 : const Relation* pRelation = getRelationFromRelId( rRelId );
92 2 : return (pRelation && !pRelation->mbExternal) ? pRelation->maTarget : OUString();
93 : }
94 :
95 5165 : OUString Relations::getFragmentPathFromRelation( const Relation& rRelation ) const
96 : {
97 : // no target, no fragment path
98 5165 : if( rRelation.mbExternal || rRelation.maTarget.isEmpty() )
99 10 : return OUString();
100 :
101 : // absolute target: return it without leading slash (#i100978)
102 5155 : if( rRelation.maTarget[ 0 ] == '/' )
103 0 : return rRelation.maTarget.copy( 1 );
104 :
105 : // empty fragment path: return target
106 5155 : if( maFragmentPath.isEmpty() )
107 228 : return rRelation.maTarget;
108 :
109 : // resolve relative target path according to base path
110 4927 : OUString aPath = lclRemoveFileName( maFragmentPath );
111 4927 : sal_Int32 nStartPos = 0;
112 20241 : while( nStartPos < rRelation.maTarget.getLength() )
113 : {
114 10387 : sal_Int32 nSepPos = rRelation.maTarget.indexOf( '/', nStartPos );
115 10387 : if( nSepPos < 0 ) nSepPos = rRelation.maTarget.getLength();
116 : // append next directory name from aTarget to aPath, or remove last directory on '../'
117 10387 : if( (nStartPos + 2 == nSepPos) && (rRelation.maTarget[ nStartPos ] == '.') && (rRelation.maTarget[ nStartPos + 1 ] == '.') )
118 845 : aPath = lclRemoveFileName( aPath );
119 : else
120 9542 : aPath = lclAppendFileName( aPath, rRelation.maTarget.copy( nStartPos, nSepPos - nStartPos ) );
121 : // move nStartPos to next directory name
122 10387 : nStartPos = nSepPos + 1;
123 : }
124 :
125 4927 : return aPath;
126 : }
127 :
128 1505 : OUString Relations::getFragmentPathFromRelId( const OUString& rRelId ) const
129 : {
130 1505 : const Relation* pRelation = getRelationFromRelId( rRelId );
131 1505 : return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
132 : }
133 :
134 520 : OUString Relations::getFragmentPathFromFirstType( const OUString& rType ) const
135 : {
136 520 : const Relation* pRelation = getRelationFromFirstType( rType );
137 520 : return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
138 : }
139 :
140 4540 : OUString Relations::getFragmentPathFromFirstTypeFromOfficeDoc( const OUString& rType ) const
141 : {
142 4540 : OUString aTransitionalType(createOfficeDocRelationTypeTransitional(rType));
143 4540 : const Relation* pRelation = getRelationFromFirstType( aTransitionalType );
144 4540 : if(!pRelation)
145 : {
146 1281 : OUString aStrictType = createOfficeDocRelationTypeStrict(rType);
147 1281 : pRelation = getRelationFromFirstType( aStrictType );
148 : }
149 4540 : return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString();
150 : }
151 :
152 : } // namespace core
153 : } // namespace oox
154 :
155 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|