001/* 002 * (C) Copyright 2018 Nuxeo (http://nuxeo.com/) and others. 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 * 016 * Contributors: 017 * Antoine Taillefer 018 * Thomas Roger 019 */ 020 021package org.nuxeo.wopi; 022 023import static java.nio.charset.StandardCharsets.UTF_8; 024import static org.nuxeo.wopi.Constants.ACCESS_TOKEN_ATTRIBUTE; 025import static org.nuxeo.wopi.Constants.ACCESS_TOKEN_TTL_ATTRIBUTE; 026import static org.nuxeo.wopi.Constants.FILES_ENDPOINT_PATH; 027import static org.nuxeo.wopi.Constants.FORM_URL; 028import static org.nuxeo.wopi.Constants.WOPI_BASE_URL_PROPERTY; 029import static org.nuxeo.wopi.Constants.WOPI_JSP; 030import static org.nuxeo.wopi.Constants.WOPI_SRC; 031 032import java.io.IOException; 033import java.net.URLEncoder; 034import java.util.Arrays; 035 036import javax.servlet.RequestDispatcher; 037import javax.servlet.ServletException; 038import javax.servlet.http.HttpServlet; 039import javax.servlet.http.HttpServletRequest; 040import javax.servlet.http.HttpServletResponse; 041 042import org.nuxeo.ecm.core.api.Blob; 043import org.nuxeo.ecm.core.api.CloseableCoreSession; 044import org.nuxeo.ecm.core.api.CoreInstance; 045import org.nuxeo.ecm.core.api.DocumentModel; 046import org.nuxeo.ecm.core.api.DocumentRef; 047import org.nuxeo.ecm.core.api.IdRef; 048import org.nuxeo.ecm.platform.web.common.vh.VirtualHostHelper; 049import org.nuxeo.runtime.api.Framework; 050 051/** 052 * @since 10.3 053 */ 054public class WOPIServlet extends HttpServlet { 055 056 private static final long serialVersionUID = 1L; 057 058 @Override 059 protected void doGet(HttpServletRequest request, HttpServletResponse response) 060 throws ServletException, IOException { 061 String path = request.getPathInfo(); 062 if (path == null) { 063 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Null path"); 064 return; 065 } 066 // remove first / 067 path = path.substring(1); 068 String[] parts = path.split("/"); 069 int length = parts.length; 070 if (length < 4) { 071 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid path: " + path); 072 return; 073 } 074 075 WOPIService wopiService = Framework.getService(WOPIService.class); 076 if (!wopiService.isEnabled()) { 077 response.sendError(HttpServletResponse.SC_NOT_FOUND, "WOPI not enabled"); 078 return; 079 } 080 081 String action = parts[0]; 082 String repository = parts[1]; 083 String docId = parts[2]; 084 String xpath = String.join("/", Arrays.asList(parts).subList(3, length)); 085 try (CloseableCoreSession session = CoreInstance.openCoreSession(repository)) { 086 DocumentRef ref = new IdRef(docId); 087 if (!session.exists(ref)) { 088 response.sendError(HttpServletResponse.SC_NOT_FOUND, "Document not found"); 089 return; 090 } 091 092 DocumentModel doc = session.getDocument(ref); 093 Blob blob = Helpers.getEditableBlob(doc, xpath); 094 if (blob == null) { 095 response.sendError(HttpServletResponse.SC_NOT_FOUND, "No editable blob on document"); 096 return; 097 } 098 099 String actionURL = wopiService.getActionURL(blob, action); 100 if (actionURL == null) { 101 // TODO http code? 102 response.sendError(HttpServletResponse.SC_NOT_FOUND, "Cannot open file with Office Online"); 103 return; 104 } 105 106 String token = Helpers.createJWTToken(); 107 request.setAttribute(ACCESS_TOKEN_ATTRIBUTE, token); 108 request.setAttribute(ACCESS_TOKEN_TTL_ATTRIBUTE, Helpers.getJWTTokenExp(token)); 109 String baseURL = VirtualHostHelper.getBaseURL(request); 110 String wopiBaseURL = Framework.getProperty(WOPI_BASE_URL_PROPERTY, baseURL); 111 String fileId = FileInfo.computeFileId(doc, xpath); 112 String wopiSrc = URLEncoder.encode(String.format("%s%s%s", wopiBaseURL, FILES_ENDPOINT_PATH, fileId), 113 UTF_8.name()); 114 request.setAttribute(FORM_URL, String.format("%s%s=%s", actionURL, WOPI_SRC, wopiSrc)); 115 RequestDispatcher requestDispatcher = request.getRequestDispatcher(WOPI_JSP); 116 requestDispatcher.forward(request, response); 117 } 118 } 119 120}