FlashCrossDomainServlet.java 6.88 KB
Newer Older
1 2 3 4 5
/**
 * $RCSfile$
 * $Revision: $
 * $Date: $
 *
6
 * Copyright (C) 2005-2008 Jive Software. All rights reserved.
7
 *
8 9 10 11 12 13 14 15 16 17 18
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
19
 */
20
package org.jivesoftware.openfire.http;
21

22 23 24 25
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
26

27
import javax.servlet.ServletException;
28 29 30
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
31 32 33 34 35

import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
36 37

/**
38 39 40 41 42 43 44 45
 * Serves up the flash cross domain xml file which allows other domains to
 * access http-binding using flash.
 * 
 * This implementation will first try to serve
 * <tt>&lt;OpenfireHome&gt;/conf/crossdomain.xml</tt>. If this file is
 * unavailable, a crossdomain file will be generated dynamically, based on the
 * current settings of the Openfire BOSH functionality.
 * 
46
 * @author Alexander Wenckus
47
 * @author Guus der Kinderen, guus.der.kinderen@gmail.com
48 49 50
 */
public class FlashCrossDomainServlet extends HttpServlet {

51 52 53 54 55 56 57
	private static Logger Log = LoggerFactory.getLogger(FlashCrossDomainServlet.class);
	
    public static String CROSS_DOMAIN_TEXT = "<?xml version=\"1.0\"?>\n" +
            "<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">\n" +
            "<cross-domain-policy>\n" +
            "\t<site-control permitted-cross-domain-policies=\"all\"/>\n" +
            "\t<allow-access-from domain=\"*\" to-ports=\"";
58

59
    public static String CROSS_DOMAIN_MIDDLE_TEXT = "\" secure=\"";
60
    public static String CROSS_DOMAIN_END_TEXT = "\"/>\n</cross-domain-policy>";
61 62 63 64
    
    private static String CROSS_DOMAIN_SECURE_ENABLED = "httpbind.crossdomain.secure";
    private static boolean CROSS_DOMAIN_SECURE_DEFAULT = true;
    
65 66 67 68
    @Override
    protected void doGet(HttpServletRequest httpServletRequest,
                         HttpServletResponse response) throws
            ServletException, IOException {
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
        response.setContentType("text/xml");
        response.getOutputStream().write(getCrossDomainContent().getBytes());
    }
    
    /**
	 * Returns the content for <tt>crossdomain.xml</tt>, either by generating
	 * content, or by passing the provided file in
	 * <tt>&lt;OpenfireHome&gt;/conf/crossdomain.xml</tt>
	 * 
	 * @return content for the <tt>crossdomain.xml</tt> that should be served
	 *         for this service.
	 */
    public static String getCrossDomainContent() {
    	final String override = getContent(getOverride());
    	if (override != null && override.trim().length() > 0) {
    		return override;
    	} else {
    		return generateOutput();
    	}
    }
    
    /**
	 * Returns <tt>&lt;OpenfireHome&gt;/conf/crossdomain.xml</tt> as a File
	 * object (even if the file does not exist on the file system).
	 * 
	 * @return <tt>&lt;OpenfireHome&gt;/conf/crossdomain.xml</tt>
	 */
    private static File getOverride() {
    	final StringBuilder sb = new StringBuilder();
    	sb.append(JiveGlobals.getHomeDirectory());
    	if (!sb.substring(sb.length()-1).startsWith(File.separator)) {
    		sb.append(File.separator);
    	}
    	sb.append("conf");
    	sb.append(File.separator);

    	return new File(sb.toString(), "crossdomain.xml");
    }
    
    /**
	 * Return content of the provided file as a String.
	 * 
	 * @param file
	 *            The file from which to get the content.
	 * @return String-based content of the provided file.
	 */
    private static String getContent(File file) {
		final StringBuilder content = new StringBuilder();
		if (file.canRead()) {
			try {
				final BufferedReader in = new BufferedReader(new FileReader(
						file));
				String str;
				while ((str = in.readLine()) != null) {
					content.append(str);
					content.append('\n');
				}
				in.close();
			} catch (IOException ex) {
				Log.warn("Unexpected exception while trying to read file: " + file.getName(), ex);
				return null;
			}
		}

		return content.toString();
	}
    
    /**
     * Dynamically generates content for a non-restrictive <tt>crossdomain.xml</tt> file. 
     */
    private static String generateOutput() {
        final StringBuilder builder = new StringBuilder();
141 142 143 144 145
        builder.append(CROSS_DOMAIN_TEXT);
        getPortList(builder);
        builder.append(CROSS_DOMAIN_MIDDLE_TEXT);
        getSecure(builder);
        builder.append(CROSS_DOMAIN_END_TEXT);
146
        builder.append("\n");
147 148
        
        return builder.toString();
149
    }
150
    
151
    private static StringBuilder getPortList(StringBuilder builder) {
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
        boolean multiple = false;
        if(XMPPServer.getInstance().getConnectionManager().getClientListenerPort() > 0) {
            builder.append(XMPPServer.getInstance().getConnectionManager().getClientListenerPort());
            multiple = true;
        }
        if(XMPPServer.getInstance().getConnectionManager().getClientSSLListenerPort() > 0) {
            if(multiple) {
                builder.append(",");
            }
            builder.append(XMPPServer.getInstance().getConnectionManager().getClientSSLListenerPort());
            multiple = true;
        }
        
        if(HttpBindManager.getInstance().isHttpBindEnabled()) {
            // ports for http-binding may not be strictly needed in here, but it doesn't hurt
            if(HttpBindManager.getInstance().getHttpBindUnsecurePort() > 0) {
                if(multiple) {
                    builder.append(",");
                }
                builder.append(HttpBindManager.getInstance().getHttpBindUnsecurePort());
                multiple = true;
            }
174 175
            if (HttpBindManager.getInstance().isHttpsBindActive()) {
                if (multiple) {
176 177 178 179 180 181 182 183 184
                    builder.append(",");
                }
                builder.append(HttpBindManager.getInstance().getHttpBindSecurePort());
            }
        }
        
        return builder;
    }
    
185
    private static StringBuilder getSecure(StringBuilder builder) {
186 187 188 189 190 191 192
        if (JiveGlobals.getBooleanProperty(CROSS_DOMAIN_SECURE_ENABLED,CROSS_DOMAIN_SECURE_DEFAULT)) {
            builder.append("true");
        } else {
            builder.append("false");
        }
        return builder;
    }
193
}