FlashCrossDomainHandler.java 6.1 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 21 22
 */

package org.jivesoftware.openfire;

23 24 25 26 27 28 29 30
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

31 32 33 34 35
import org.jivesoftware.openfire.container.BasicModule;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

36
public class FlashCrossDomainHandler extends BasicModule {
37 38 39
	
	private static final Logger Log = LoggerFactory.getLogger(FlashCrossDomainHandler.class);

40 41 42 43 44 45
    private ServerSocket serverSocket;

    public static String CROSS_DOMAIN_TEXT = "<?xml version=\"1.0\"?>" +
            "<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">" +
            "<cross-domain-policy>" +
            "<allow-access-from domain=\"*\" to-ports=\"";
46

47
    public static String CROSS_DOMAIN_END_TEXT = "\" /></cross-domain-policy>";
48 49 50 51 52

    public FlashCrossDomainHandler() {
        super("Flash CrossDomain Handler");
    }

53 54
    @Override
	public void start() {
55 56 57 58 59 60
        Thread thread = new Thread(new Runnable() {
            public void run() {
                try {
                    startServer();
                }
                catch (Exception e) {
61
                    Log.error(e.getMessage(), e);
62 63 64
                }
            }
        }, "Flash Cross Domain");
65

66
        thread.start();
67 68
    }

69 70
    @Override
	public void stop() {
71 72 73
        try {
            if (serverSocket != null) {
                serverSocket.close();
74 75
            }
        }
76
        catch (IOException e) {
77
            Log.error(e.getMessage(), e);
78
        }
79 80
    }

81 82 83 84 85
    public int getPort() {
        return serverSocket != null ? serverSocket.getLocalPort() : 0;
    }

    private void startServer() throws Exception {
86 87 88 89 90 91
        if(!JiveGlobals.getBooleanProperty("flash.crossdomain.enabled",true)){
            Log.debug("Flash cross domain listener is disabled");
            return;
        }
        
        int port = JiveGlobals.getIntProperty("flash.crossdomain.port",5229);
92
        try {
93
            // Listen on a specific network interface if it has been set.
94 95 96 97 98 99 100 101 102
            String interfaceName = JiveGlobals.getXMLProperty("network.interface");
            InetAddress bindInterface = null;
            if (interfaceName != null) {
                if (interfaceName.trim().length() > 0) {
                    bindInterface = InetAddress.getByName(interfaceName);
                }
            }
            serverSocket = new ServerSocket(port, -1, bindInterface);
            Log.debug("Flash cross domain is listening on " + interfaceName + " on port " + port);
103
        }
104
        catch (IOException e) {
105
            Log.error("Could not listen on port: " + port, e);
106 107 108
            return;
        }

109 110 111 112 113 114 115
        while (true) {
            Socket clientSocket = null;
            PrintWriter out = null;
            BufferedReader in = null;
            try {
                clientSocket = serverSocket.accept();
                clientSocket.setSoTimeout(10000); // 10 second timeout
116

117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
                out = new PrintWriter(clientSocket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                
                String request = "";
            	request = read(in);
                
                if (request.contains("<policy-file-request/>") || request.contains("GET /crossdomain.xml")) {
	                out.write(CROSS_DOMAIN_TEXT +
	                        XMPPServer.getInstance().getConnectionManager().getClientListenerPort() +
	                        CROSS_DOMAIN_END_TEXT+"\u0000");
                }
            }
            catch (IOException e) {
                if (XMPPServer.getInstance().isShuttingDown()) {
                    break;
                }
133
                Log.error(e.getMessage(), e);
134 135 136 137 138 139 140 141 142 143 144 145 146 147
            }
            finally {
            	if (out != null) {
            		out.flush();
            		out.close();
            	}
            	if (in != null) {
            		in.close();
            	}
            	if (clientSocket != null) {
            		clientSocket.close();
            	}
            }
        }
148
    }
149 150
    
    /**
151 152 153 154
     * Safely read a string from the reader until a zero character or a newline
     * is received, more then 100 invalid code points where read or the 200
     * character is reached.
     * 
155 156 157 158 159
     * @return the string read from the reader.
     */
    protected String read(BufferedReader in) {
        StringBuffer buffer = new StringBuffer();
        int codePoint;
160 161 162
        boolean stopReading = false;
        int invalidCodePoints = 0;

163 164 165
        try {
            do {
                codePoint = in.read();
166

167 168
                if (codePoint == 0 || codePoint == '\n' || codePoint == -1) {
                    stopReading = true;
169 170 171
                }
                else if (Character.isValidCodePoint(codePoint)) {
                    buffer.appendCodePoint(codePoint);
172 173
                } else {
                    invalidCodePoints++;
174
                }
175 176
            } while (!stopReading && buffer.length() < 200
                    && invalidCodePoints < 100);
177 178 179 180 181 182
        }
        catch (Exception e) {
            Log.debug("Exception (read): " + e.getMessage());
        }
        
        return buffer.toString();
183
    }
184

185
}