001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.xml; 029 030import org.opencms.file.CmsResource; 031import org.opencms.file.history.CmsHistoryResourceHandler; 032import org.opencms.main.CmsLog; 033import org.opencms.util.CmsStringUtil; 034 035import java.net.URI; 036import java.util.Collection; 037import java.util.Collections; 038import java.util.HashSet; 039import java.util.Set; 040import java.util.regex.Pattern; 041import java.util.regex.PatternSyntaxException; 042 043import org.apache.commons.logging.Log; 044import org.apache.http.client.utils.URIBuilder; 045 046/** 047 * Does final postprocessing on a link by cutting off specific path suffixes (e.g. index.html). 048 */ 049public class CmsLinkFinisher { 050 051 /** Logger instance for this class. */ 052 private static final Log LOG = CmsLog.getLog(CmsLinkFinisher.class); 053 054 /** True if the link finisher is enabled. */ 055 private boolean m_enabled; 056 057 /** Default file names to remove. */ 058 private Set<String> m_defaultFileNames; 059 060 /** If a link matches this, it shouldn't be finished. */ 061 private Pattern m_excludePattern; 062 063 /** 064 * Creates a new instance. 065 * 066 * @param enabled true if it should be enabled 067 * @param defaultFileNames the default file names to remove 068 * @param exclude regex to prevent certain links from being finished if they match 069 */ 070 public CmsLinkFinisher(boolean enabled, Collection<String> defaultFileNames, String exclude) { 071 072 m_enabled = enabled; 073 m_defaultFileNames = Collections.unmodifiableSet(new HashSet<>(defaultFileNames)); 074 if (exclude != null) { 075 try { 076 m_excludePattern = Pattern.compile(exclude); 077 } catch (PatternSyntaxException e) { 078 LOG.error(e.getLocalizedMessage(), e); 079 } 080 } 081 082 } 083 084 /** 085 * Transforms the link into a finished format. 086 * 087 * @param link the link 088 * @param full in full mode, remove all configured suffixes, otherwise just remove trailing slashes 089 * @return 090 */ 091 public String transformLink(String link, boolean full) { 092 093 if (!m_enabled) { 094 return link; 095 } 096 if (CmsStringUtil.isEmptyOrWhitespaceOnly(link)) { 097 return link; 098 } 099 if (link.startsWith(CmsHistoryResourceHandler.HISTORY_HANDLER)) { 100 return link; 101 } 102 if (link.startsWith("javascript:")) { 103 return link; 104 } 105 if (m_excludePattern != null) { 106 if (m_excludePattern.matcher(link).matches()) { 107 return link; 108 } 109 } 110 try { 111 URI uri = new URI(link); 112 URIBuilder builder = new URIBuilder(uri); 113 String path = builder.getPath(); 114 if (path != null) { 115 path = path.replaceFirst("/$", ""); 116 if (full) { 117 if (path.length() > 1) { 118 String name = CmsResource.getName(path); 119 if (m_defaultFileNames.contains(name)) { 120 path = path.substring(0, path.lastIndexOf('/')); 121 } 122 } 123 } 124 // since we usually put the result of link substitution into hrefs, we need to avoid an empty path if there is no host, otherwise the href will link to the current page 125 if ((uri.getAuthority() == null) && "".equals(path)) { 126 path = "/"; 127 } 128 builder.setPath(path); 129 link = builder.toString(); 130 } 131 } catch (Exception e) { 132 LOG.error(e.getLocalizedMessage(), e); 133 } 134 135 return link; 136 } 137 138}