1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "oox/core/relations.hxx" 25 26 #include <rtl/ustrbuf.hxx> 27 #include "oox/helper/helper.hxx" 28 29 namespace oox { 30 namespace core { 31 32 // ============================================================================ 33 34 using ::rtl::OUString; 35 using ::rtl::OUStringBuffer; 36 37 // ============================================================================ 38 39 namespace { 40 41 OUString lclRemoveFileName( const OUString& rPath ) 42 { 43 return rPath.copy( 0, ::std::max< sal_Int32 >( rPath.lastIndexOf( '/' ), 0 ) ); 44 } 45 46 OUString lclAppendFileName( const OUString& rPath, const OUString& rFileName ) 47 { 48 return (rPath.getLength() == 0) ? rFileName : 49 OUStringBuffer( rPath ).append( sal_Unicode( '/' ) ).append( rFileName ).makeStringAndClear(); 50 } 51 52 } // namespace 53 54 // ============================================================================ 55 56 Relations::Relations( const OUString& rFragmentPath ) : 57 maFragmentPath( rFragmentPath ) 58 { 59 } 60 61 const Relation* Relations::getRelationFromRelId( const OUString& rId ) const 62 { 63 const_iterator aIt = find( rId ); 64 return (aIt == end()) ? 0 : &aIt->second; 65 } 66 67 const Relation* Relations::getRelationFromFirstType( const OUString& rType ) const 68 { 69 for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) 70 if( aIt->second.maType.equalsIgnoreAsciiCase( rType ) ) 71 return &aIt->second; 72 return 0; 73 } 74 75 RelationsRef Relations::getRelationsFromType( const OUString& rType ) const 76 { 77 RelationsRef xRelations( new Relations( maFragmentPath ) ); 78 for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) 79 if( aIt->second.maType.equalsIgnoreAsciiCase( rType ) ) 80 (*xRelations)[ aIt->first ] = aIt->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::getExternalTargetFromFirstType( const OUString& rType ) const 91 { 92 const Relation* pRelation = getRelationFromFirstType( rType ); 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.getLength() == 0) ) 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.getLength() == 0 ) 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( const OUString& rType ) const 136 { 137 const Relation* pRelation = getRelationFromFirstType( rType ); 138 return pRelation ? getFragmentPathFromRelation( *pRelation ) : OUString(); 139 } 140 141 // ============================================================================ 142 143 } // namespace core 144 } // namespace oox 145