com.zextras.zimbradrive.CreateTempAttachmentFileHttpHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.zextras.zimbradrive.CreateTempAttachmentFileHttpHandler.java

Source

/*
 * Copyright (C) 2017 ZeXtras SRL
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, version 2 of
 * the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License.
 * If not, see <http://www.gnu.org/licenses/>.
 */

package com.zextras.zimbradrive;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.openzal.zal.Account;
import org.openzal.zal.http.HttpHandler;
import org.openzal.zal.log.ZimbraLog;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class CreateTempAttachmentFileHttpHandler implements HttpHandler {
    private final static String CONTENT_DISPOSITION_HTTP_HEADER = "Content-Disposition";
    private final static int HTTP_LOWEST_ERROR_STATUS = 300;

    private final CloudHttpRequestUtils mCloudHttpRequestUtils;
    private final BackendUtils mBackendUtils;
    private ZimbraDriveLog mZimbraDriveLog;

    public CreateTempAttachmentFileHttpHandler(CloudHttpRequestUtils cloudServerUtils, BackendUtils backendUtils,
            ZimbraDriveLog zimbraDriveLog) {
        mCloudHttpRequestUtils = cloudServerUtils;
        mBackendUtils = backendUtils;
        mZimbraDriveLog = zimbraDriveLog;
    }

    @Override
    public void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws IOException {
        mZimbraDriveLog.setLogContext(httpServletRequest);
        try {
            doInternalPost(httpServletRequest, httpServletResponse);
        } catch (Exception exception) {
            String errorMessage = mZimbraDriveLog.getLogIntroduction() + "Unable to add attachment";
            ZimbraLog.extensions.error(errorMessage, exception);
            httpServletResponse.sendError(500, errorMessage);
        } finally {
            ZimbraLog.clearContext();
        }
    }

    private void doInternalPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        Account account = mBackendUtils.assertAccountFromAuthToken(httpServletRequest);
        ZimbraLog.addAccountNameToContext(account.getName());
        String path;
        BufferedReader reader = httpServletRequest.getReader();
        while ((path = reader.readLine()) != null) {
            HttpResponse fileRequestResponse = mCloudHttpRequestUtils.queryCloudServerService(account, path);

            int responseCode = fileRequestResponse.getStatusLine().getStatusCode();
            if (responseCode < HTTP_LOWEST_ERROR_STATUS) {
                HttpPost post = new HttpPost(mBackendUtils.getServerServiceUrl("/service/upload?fmt=extended,raw"));
                post.setHeader(CONTENT_DISPOSITION_HTTP_HEADER, "attachment; filename=\" "
                        + convertToUnicode(path.substring(path.lastIndexOf("/") + 1)) + " \"");
                post.setHeader("Cache-Control", "no-cache");
                post.setHeader("Cookie", httpServletRequest.getHeader("Cookie"));
                post.setHeader("X-Zimbra-Csrf-Token", httpServletRequest.getHeader("X-Zimbra-Csrf-Token"));
                post.setEntity(fileRequestResponse.getEntity());

                SSLContextBuilder builder = new SSLContextBuilder();
                builder.loadTrustMaterial(null, new TrustStrategy() {
                    @Override
                    public boolean isTrusted(X509Certificate[] x509Certificates, String s)
                            throws CertificateException {
                        return true;
                    }
                });
                SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(builder.build());
                CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(sslSocketFactory).build();

                HttpResponse response = client.execute(post);

                response.getEntity().writeTo(httpServletResponse.getOutputStream());
            } else {
                httpServletResponse.setStatus(responseCode);
                PrintWriter respWriter = httpServletResponse.getWriter();
                respWriter.println("Error");
                respWriter.close();
                break;
            }
        }
    }

    @Override
    public void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws ServletException, IOException {
        throw new RuntimeException();
    }

    @Override
    public void doOptions(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws ServletException, IOException {
        throw new RuntimeException();
    }

    @Override
    public String getPath() {
        return "ZimbraDrive_CreateTempFiles";
    }

    private String convertToUnicode(String source) {
        StringBuilder resultsBuilder = new StringBuilder();
        if (source.length() == 0)
            return source;
        for (int i = 0; i < source.length(); i++) {
            int charCode = (int) source.charAt(i);
            // Encode non-ascii or double quotes
            if ((charCode > 127) || (charCode == 34)) {
                String temp = Integer.toString(charCode);
                while (temp.length() < 4) {
                    temp = "0" + temp;
                }
                resultsBuilder.append("&#").append(temp).append(";");
            } else {
                resultsBuilder.append(source.charAt(i));
            }
        }
        return resultsBuilder.toString();
    }
}