001/* 002 * Copyright 2017 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.workspaces.documents; 017 018import java.util.Collections; 019import java.util.HashSet; 020import java.util.Set; 021 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024import org.apache.commons.lang.StringUtils; 025 026import org.ametys.cms.transformation.URIResolver; 027import org.ametys.core.authentication.token.AuthenticationTokenManager; 028import org.ametys.core.user.CurrentUserProvider; 029import org.ametys.core.user.UserIdentity; 030import org.ametys.core.util.URIUtils; 031import org.ametys.plugins.explorer.resources.Resource; 032import org.ametys.plugins.explorer.resources.ResourceCollection; 033import org.ametys.plugins.repository.AmetysObject; 034import org.ametys.plugins.repository.UnknownAmetysObjectException; 035import org.ametys.plugins.repository.version.VersionableAmetysObject; 036import org.ametys.plugins.workspaces.project.objects.Project; 037 038/** 039 * {@link URIResolver} for webdav "project-resource". <br> 040 * These links point to a file from the resources of a project through webdav 041 */ 042public class WebdavProjectResourceURIResolver extends ProjectResourceURIResolver 043{ 044 /** The authentication token manager */ 045 protected AuthenticationTokenManager _authenticationTokenManager; 046 047 /** Current User Provider */ 048 protected CurrentUserProvider _currentUserProvider; 049 050 @Override 051 public void service(ServiceManager manager) throws ServiceException 052 { 053 super.service(manager); 054 _authenticationTokenManager = (AuthenticationTokenManager) manager.lookup(AuthenticationTokenManager.ROLE); 055 _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); 056 } 057 058 @Override 059 public String getType() 060 { 061 return "webdav-project-resource"; 062 } 063 064 // Override to single encoded instead of twice 065 @Override 066 protected String _resolve(String uri, boolean download, boolean absolute, boolean internal, String prefix, String suffix) 067 { 068 String version = null; 069 String path; 070 AmetysObject resource = null; 071 try 072 { 073 String resourceId = uri; 074 int i = uri.indexOf(";"); 075 if (i != -1) 076 { 077 resourceId = uri.substring(0, i); 078 version = uri.substring(i + 1); 079 } 080 081 resource = _resolver.resolveById(resourceId); 082 path = getPath(resource); 083 if (StringUtils.isBlank(path)) 084 { 085 return ""; 086 } 087 } 088 catch (UnknownAmetysObjectException e) 089 { 090 getLogger().warn("Link to unexisting resource " + uri); 091 return ""; 092 } 093 094 int i = path.lastIndexOf("."); 095 String extension = i != -1 ? path.substring(i) : null; 096 path = i != -1 ? path.substring(0, i) : path; 097 098 StringBuilder result = new StringBuilder(); 099 100 result.append(getUriPrefix(resource, download, absolute, internal)); 101 102 String realPrefix = null; 103 if (resource instanceof Resource) 104 { 105 realPrefix = getRealPrefix((Resource) resource, prefix); 106 } 107 108 if (StringUtils.isNotEmpty(realPrefix)) 109 { 110 result.append("/_").append(realPrefix); 111 } 112 113 if (StringUtils.isNotEmpty(version) && resource instanceof VersionableAmetysObject) 114 { 115 result.append("/__version").append(version); 116 } 117 118 result.append(path); 119 120 if (suffix != null) 121 { 122 result.append(suffix); 123 } 124 125 if (extension != null) 126 { 127 result.append(extension); 128 } 129 130 String fullUri = result.toString(); 131 132 // the ';' char is handled by Tomcat as an URI path parameter 133 // Replace it by its encoded value, which may look weird in Office, but at least it won't fail 134 fullUri = fullUri.replaceAll(";", "%3B"); 135 136 return URIUtils.encodeURI(fullUri, download ? Collections.singletonMap("download", "true") : null); 137 } 138 139 @Override 140 protected String getUriPrefix(AmetysObject object, boolean download, boolean absolute, boolean internal) 141 { 142 Project project = null; 143 String projectName = null; 144 String siteName = null; 145 146 UserIdentity user = _currentUserProvider.getUser(); 147 long duration = 12 * 60 * 60; // 12h 148 boolean autoRenew = true; // Auto Renew the token to be able to continue to edit it 149 150 Set<String> contexts = new HashSet<>(); 151 String path = getPath(object); // Token only usable on this resource 152 path = StringUtils.removeStart(path, "/"); // / at the beginning is removed because it is used in a uri path 153 contexts.add(path); 154 155 if (object instanceof Resource) 156 { 157 String parentPath = getPath(object.getParent()); 158 parentPath = StringUtils.removeStart(parentPath, "/").concat("/"); // / at the beginning is removed because it is used in a uri path, / at the end to avoid identical folders 159 contexts.add(parentPath); 160 } 161 String type = "Workspaces-Webdav"; 162 String comment = "Token created to modify content : '" + object.getId() + "'"; 163 String token = _authenticationTokenManager.generateToken(user, duration, autoRenew, null, contexts, type, comment); 164 165 project = _getProject(object); 166 projectName = project.getName(); 167 168 siteName = project.getSites().iterator().next().getName(); 169 170 if (internal) 171 { 172 return "cocoon://_workspaces/dav/" + projectName + "/" + token; 173 } 174 else if (absolute) 175 { 176 return _webPrefixHandler.getAbsoluteUriPrefix(siteName) + "/_workspaces/dav/" + projectName + "/" + token; 177 } 178 else 179 { 180 return _webPrefixHandler.getUriPrefix(siteName) + "/_workspaces/dav/" + projectName + "/" + token; 181 } 182 } 183 184 /** 185 * Get the path of a {@link Resource} or a {@link ResourceCollection} 186 * @param resource the resource to work with 187 * @return the path 188 */ 189 protected String getPath(AmetysObject resource) 190 { 191 String path = null; 192 if (resource instanceof Resource) 193 { 194 path = getResourcePath((Resource) resource); 195 } 196 else if (resource instanceof ResourceCollection) 197 { 198 path = ((ResourceCollection) resource).getExplorerPath(); 199 } 200 else 201 { 202 getLogger().error("Trying to access to something that is not a Resource or a ResourceCollection : " + resource.getId()); 203 } 204 return path; 205 } 206 207 @Override 208 protected String getRealPrefix(Resource resource, String prefix) 209 { 210 return null; 211 } 212}