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.CoreInstance;
044import org.nuxeo.ecm.core.api.CoreSession;
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        CoreSession session = CoreInstance.getCoreSession(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}