001: ///////////////////////////////////////////////////////////////////////////////
002: //
003: // This program is free software; you can redistribute it and/or modify
004: // it under the terms of the GNU General Public License and GNU Library
005: // General Public License as published by the Free Software Foundation;
006: // either version 2, or (at your option) any later version.
007: //
008: // This program is distributed in the hope that it will be useful,
009: // but WITHOUT ANY WARRANTY; without even the implied warranty of
010: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: // GNU General Public License and GNU Library General Public License
012: // for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // and GNU Library General Public License along with this program; if
016: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
017: // MA 02139, USA.
018: //
019: //////////////////////////////////////////////////////////////////////////////
020:
021: package org.rdesktop.server.rdp.rdp5.cliprdr;
022:
023: import java.io.*;
024: import java.awt.event.*;
025: import java.awt.Toolkit;
026: import java.awt.datatransfer.*;
027: import java.util.Iterator;
028:
029: import org.rdesktop.server.rdp.*;
030: import org.rdesktop.server.rdp.rdp5.*;
031: import org.rdesktop.server.rdp.crypto.CryptoException;
032:
033: public class ClipChannel extends VChannel implements ClipInterface,
034: ClipboardOwner, FocusListener {
035: public static final int CLIPRDR_CONNECT = 1;
036: public static final int CLIPRDR_FORMAT_ANNOUNCE = 2;
037: public static final int CLIPRDR_FORMAT_ACK = 3;
038: public static final int CLIPRDR_DATA_REQUEST = 4;
039: public static final int CLIPRDR_DATA_RESPONSE = 5;
040:
041: public static final int CLIPRDR_REQUEST = 0;
042: public static final int CLIPRDR_RESPONSE = 1;
043: public static final int CLIPRDR_ERROR = 2;
044:
045: private Clipboard m_clipboard;
046: private TypeHandler m_currentHandler = null;
047: private TypeHandlerList m_allHandlers = null;
048:
049: public ClipChannel(RdpSecure secureLayer) {
050: super (secureLayer);
051:
052: m_clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
053:
054: m_allHandlers = new TypeHandlerList();
055: m_allHandlers.add(new UnicodeHandler());
056: m_allHandlers.add(new TextHandler());
057: m_allHandlers.add(new DIBHandler());
058: }
059:
060: private void reset_bool(boolean[] x) {
061: for (int i = 0; i < x.length; i++) {
062: x[i] = false;
063: }
064: }
065:
066: private void handle_clip_format_announce(RdpPacket data, int length)
067: throws RdpDesktopException, IOException, CryptoException {
068: TypeHandlerList serverTypeList = new TypeHandlerList();
069:
070: for (int c = length; c >= 36; c -= 36) {
071: int typeCode = data.getLittleEndian32();
072: data.incrementPosition(32);
073: serverTypeList.add(m_allHandlers
074: .getHandlerForFormat(typeCode));
075: }
076:
077: send_null(CLIPRDR_FORMAT_ACK, CLIPRDR_RESPONSE);
078: m_currentHandler = serverTypeList.getFirst();
079:
080: if (m_currentHandler != null) {
081: request_clipboard_data(m_currentHandler.preferredFormat());
082: }
083: }
084:
085: protected void send_format_announce() throws RdpDesktopException,
086: IOException, CryptoException {
087: Transferable clipData = m_clipboard.getContents(m_clipboard);
088: DataFlavor[] dataTypes = clipData.getTransferDataFlavors();
089:
090: TypeHandlerList availableFormats = m_allHandlers
091: .getHandlersForClipboard(dataTypes);
092:
093: int number_of_formats = availableFormats.count();
094:
095: RdpPacket packet = new RdpPacket(number_of_formats * 36 + 12);
096: packet.setLittleEndian16(CLIPRDR_FORMAT_ANNOUNCE);
097: packet.setLittleEndian16(CLIPRDR_REQUEST);
098: packet.setLittleEndian32(number_of_formats * 36);
099:
100: for (Iterator iter = availableFormats.iterator(); iter
101: .hasNext();) {
102: TypeHandler handler = (TypeHandler) iter.next();
103: packet.setLittleEndian32(handler.preferredFormat());
104: packet.incrementPosition(32);
105: }
106:
107: packet.setLittleEndian32(0);
108: packet.markEnd();
109: send_packet(packet);
110: }
111:
112: protected void handle_data_request(RdpPacket data)
113: throws RdpDesktopException, IOException, CryptoException {
114: int format = data.getLittleEndian32();
115: Transferable clipData = m_clipboard.getContents(this );
116: byte[] outData = null;
117:
118: TypeHandler outputHandler = m_allHandlers
119: .getHandlerForFormat(format);
120: if (outputHandler != null) {
121: outputHandler.send_data(clipData, this );
122: }
123: }
124:
125: protected void handle_data_response(RdpPacket data, int length) {
126: if (m_currentHandler != null) {
127: m_currentHandler.handleData(data, length, this );
128: }
129:
130: m_currentHandler = null;
131: }
132:
133: protected void request_clipboard_data(int formatcode)
134: throws RdpDesktopException, IOException, CryptoException {
135: RdpPacket packet = m_secureLayer.init(
136: RdpOptions.encryption ? RdpSecure.SEC_ENCRYPT : 0, 24);
137: packet.setLittleEndian32(16);
138:
139: int flags = VChannels.CHANNEL_FLAG_FIRST
140: | VChannels.CHANNEL_FLAG_LAST;
141: if ((this .flags() & VChannels.CHANNEL_OPTION_SHOW_PROTOCOL) != 0) {
142: flags |= VChannels.CHANNEL_FLAG_SHOW_PROTOCOL;
143: }
144:
145: packet.setLittleEndian32(flags);
146: packet.setLittleEndian16(CLIPRDR_DATA_REQUEST);
147: packet.setLittleEndian16(CLIPRDR_REQUEST);
148: packet.setLittleEndian32(4);
149: packet.setLittleEndian32(formatcode);
150: packet.setLittleEndian32(0);
151: packet.markEnd();
152:
153: m_secureLayer.send_to_channel(packet,
154: RdpOptions.encryption ? RdpSecure.SEC_ENCRYPT : 0, this
155: .mcs_id());
156: }
157:
158: public String name() {
159: return "cliprdr";
160: }
161:
162: public int flags() {
163: return VChannels.CHANNEL_OPTION_INITIALIZED
164: | VChannels.CHANNEL_OPTION_ENCRYPT_RDP
165: | VChannels.CHANNEL_OPTION_COMPRESS_RDP
166: | VChannels.CHANNEL_OPTION_SHOW_PROTOCOL;
167: }
168:
169: public void process(RdpPacket data) throws RdpDesktopException,
170: IOException, CryptoException {
171: int type, status;
172: int length, format;
173:
174: type = data.getLittleEndian16();
175: status = data.getLittleEndian16();
176: length = data.getLittleEndian32();
177:
178: if (status == CLIPRDR_ERROR) {
179: if (type == CLIPRDR_FORMAT_ACK) {
180: send_format_announce();
181: return;
182: }
183:
184: return;
185: }
186:
187: switch (type) {
188: case CLIPRDR_CONNECT: {
189: send_format_announce();
190: break;
191: }
192: case CLIPRDR_FORMAT_ANNOUNCE: {
193: handle_clip_format_announce(data, length);
194: return;
195: }
196: case CLIPRDR_FORMAT_ACK: {
197: break;
198: }
199: case CLIPRDR_DATA_REQUEST: {
200: handle_data_request(data);
201: break;
202: }
203: case CLIPRDR_DATA_RESPONSE: {
204: handle_data_response(data, length);
205: break;
206: }
207: case 7: {
208: break;
209: }
210: default: {
211: break;
212: }
213: }
214: }
215:
216: public void send_null(int type, int status) {
217: RdpPacket packet = new RdpPacket(12);
218: packet.setLittleEndian16(type);
219: packet.setLittleEndian16(status);
220: packet.setLittleEndian32(0);
221: packet.setLittleEndian32(0);
222: packet.markEnd();
223:
224: try {
225: send_packet(packet);
226: } catch (RdpDesktopException e) {
227: System.err.println(e.getMessage());
228: e.printStackTrace();
229: } catch (IOException e) {
230: System.err.println(e.getMessage());
231: e.printStackTrace();
232: } catch (CryptoException e) {
233: System.err.println(e.getMessage());
234: e.printStackTrace();
235: }
236: }
237:
238: public void send_data(byte[] data, int length) {
239: synchronized (this ) {
240: RdpPacket packet = new RdpPacket(12 + length);
241:
242: packet.setLittleEndian16(CLIPRDR_DATA_RESPONSE);
243: packet.setLittleEndian16(CLIPRDR_RESPONSE);
244: packet.setLittleEndian32(length + 4);
245: packet.copyFromByteArray(data, 0, packet.getPosition(),
246: length);
247: packet.incrementPosition(length);
248: packet.setLittleEndian32(0);
249:
250: try {
251: send_packet(packet);
252: } catch (RdpDesktopException e) {
253: System.err.println(e.getMessage());
254: e.printStackTrace();
255: } catch (IOException e) {
256: System.err.println(e.getMessage());
257: e.printStackTrace();
258: } catch (CryptoException e) {
259: System.err.println(e.getMessage());
260: e.printStackTrace();
261: }
262: }
263: }
264:
265: public void focusGained(FocusEvent arg0) {
266: if (RdpOptions.use_rdp5) {
267: try {
268: send_format_announce();
269: } catch (RdpDesktopException e) {
270: } catch (IOException e) {
271: } catch (CryptoException e) {
272: }
273: }
274: }
275:
276: public void focusLost(FocusEvent arg0) {
277: }
278:
279: public void lostOwnership(Clipboard arg0, Transferable arg1) {
280: }
281:
282: public void copyToClipboard(Transferable transferable) {
283: m_clipboard.setContents(transferable, this);
284: }
285: }
|