REMOTE DESKTOP PROTOCOL INTEGRATION Lakshmi Nidadavolu B.E., Nagpur University, 2005 PROJECT Submitted in partial satisfaction of the requirements for the degree of MASTER OF SCIENCE in COMPUTER SCIENCE at CALIFORNIA STATE UNIVERSITY, SACRAMENTO FALL 2011 © 2011 Lakshmi Nidadavolu ALL RIGHTS RESERVED ii REMOTE DESKTOP PROTOCOL INTEGRATION A Project by Lakshmi Nidadavolu Approved by: __________________________________, Committee Chair Du Zhang, Ph.D. __________________________________, Second Reader Ahmed Salem, Ph.D. ____________________________ Date iii Student: Lakshmi Nidadavolu I certify that this student has met the requirements for format contained in the University format manual, and that this project is suitable for shelving in the Library and credit is to be awarded for the project. __________________________, Graduate Coordinator Nikrouz Faroughi, Ph.D. Department of Computer Science iv ___________________ Date Abstract of REMOTE DESKTOP PROTOCOL INTEGRATION by Lakshmi Nidadavolu Currently few Remote Desktop Protocol (RDP) Clients are capable of presenting the user’s windows desktop and giving the keyboard control over the client computer. The existing RDP clients are interactive in nature. Each keystroke is sent to the remote desktop in an interactive basis. Recently, there is more demand for automated tasks to perform a set of actions on the remote desktop. The aim of this project is to implement Remote Desktop Protocol Integration to perform a set of actions on the remote desktop as an automated task with minimum manual assistance. The integration includes the following main components. RDP client takes file input The client reads the file, then converts each character into a set of key strokes as key pressed, key typed and key released and sends the scancodes of the keys to the remote desktop in the same order. Record user actions The client records all the user actions along with the delays in between the actions to a file. Actions recorded to the file are of the format: v (scan codes, key pressed / key released, time delay between consecutive actions). The user selects a portion of the snapshot and compare to any other saved snapshot/image based on the co-ordinates. Playback actions The client plays back the recorded actions from the saved file. The existing RDP clients are not capable of performing a set of actions without manual assistance on the remote server. Hence, RDP integration is an enhancement to an existing RDP client called properJavaRDP. This integration is capable of performing a set of actions on the remote server. , Committee Chair Du Zhang, Ph.D. ______________________ Date vi DEDICATION To my family vii ACKNOWLEDGMENTS I would like to thank my project advisor Dr. Du Zhang for taking time and giving me guidance through the project. I would also like to thank all the professors who taught me during my masters’ course work. I would like to thank my family for all the support. viii TABLE OF CONTENTS Page Dedication………………………………………………………………………………..vii Acknowledgements .......................................................................................................... viii List of Figures ................................................................................................................... xii List of Tables ................................................................................................................... xiii Chapter 1. INTRODUCTION ...................................................................................................... …1 1.1 Current state of practice for properJavaRDP client……………. …..………………1 1.2 Scope of Remote Desktop Protocol Integration.......................... …..………………1 1.3 Benefits of RDP Integration.................................................................................. …3 2. BACKGROUND ........................................................................................................ …4 2.1 Current exixting RDP clients ................................................................................ …4 2.1.1 rdesktop RDP Client ...................................................................................... …4 2.1.2 Seamless Java RDP Client ................................................................................. 5 2.1.3 Elusiva RDP Client ............................................................................................ 5 2.2 properJavaRDP Client .............................................................................................. 6 2.2.1 Keyboard shortcuts ............................................................................................ 6 2.2.2 Key map ............................................................................................................. 7 2.2.3 Process orders .................................................................................................... 8 3. ARCHITECTURE AND TECHNOLOGY .................................................................. 11 ix 3.1 Basic Architecture of RDP Integration ................................................................... 11 3.1.1 Communication steps ....................................................................................... 12 3.2 Features and Capabilities………………………………………………………….13 3.3 Technology used in RDP Integration ...................................................................... 15 3.3.1 Client-Server Connection................................................................................. 16 4. IMPLEMENTATION DETAILS ................................................................................. 19 4.1 File input ................................................................................................................. 21 4.2 Record actions ......................................................................................................... 22 4.2.1 Capture snapshots ............................................................................................ 23 4.2.2 Crop, confirm and save snapshot. .................................................................... 24 4.3 Playback actions...................................................................................................... 25 5. PERFORMANCE EVALUATION .............................................................................. 27 6. CONCLUSION AND FUTURE WORK ..................................................................... 29 6.1 Advantages .............................................................................................................. 29 6.1.1 Efficient and accurate ...................................................................................... 29 6.1.2 Visual confirmation ......................................................................................... 29 6.2 Future work ............................................................................................................. 29 6.2.1 Alerts on remote server .................................................................................... 29 6.2.2 Security ............................................................................................................ 29 6.2.3 Revert to initiation point .................................................................................. 30 6.2.4 Run parallel automated tasks ........................................................................... 30 Appendix Source Code .................................................................................................... 31 x Bibliography ..................................................................................................................... 49 xi LIST OF FIGURES Page Figure 1 Key map I ............................................................................................................. 7 Figure 2 Key map II ............................................................................................................ 8 Figure 3 Process rectangle orders ....................................................................................... 9 Figure 4 Process text orders .............................................................................................. 10 Figure 5 Architecture diagram .......................................................................................... 12 Figure 6 Wrapped image ................................................................................................... 15 Figure 7 TCP socket flow diagram ................................................................................... 17 Figure 8 Flow diagram of RDP Integration ...................................................................... 19 Figure 9 User options ........................................................................................................ 20 Figure 10 User file input ................................................................................................... 20 Figure 11 User authentication ........................................................................................... 21 Figure 12 Input file ........................................................................................................... 22 Figure 13 File to record actions ........................................................................................ 23 Figure 14 Capture snapshot .............................................................................................. 24 Figure 15 Crop snapshot ................................................................................................... 25 Figure 16 Performance evaluation chart ........................................................................... 27 xii LIST OF TABLES Page Table 1 Keyboard shortcuts ................................................................................................ 7 xiii 1 Chapter 1 INTRODUCTION Remote Desktop Protocol (RDP) [4] provides remote control on the windows computers including both desktops and servers. RDP includes properties like encryption, authentication, bandwidth, resource sharing over secure network communications protocol. While running the RDP client, all the client-side execution, data processing, data storage and data execution occurs on the server. All the keyboard inputs transmit to the remote sever over the network from the client. 1.1 Current state of practice for properJavaRDP client The properJavaRDP client initializes the RDP5 communication layer and then establishes a connection with the remote server based on the username and password on the default port 3389. After the license negotiation with the remote server, the client is notified that the connection is ready to send messages to the remote server. It then pops up a window frame showing the remote desktop on the client system. At this point, the properJavaRDP identifies each keystroke interactively and then sends the scan code of the key to the remote server. In addition, it logs the details showing whether the key is pressed, typed or released for each keystroke. 1.2 Scope of Remote Desktop Protocol Integration RDP integration is an enhancement to the properJavaRDP [2]. Instead of listening to each keystroke, this integration translates a set of actions into respective keystrokes and sends their scan codes to the remote server in the required order. Such functionality can be used 2 to automate tasks on the remote desktop. The automation of tasks on the remote server can be achieved with the following capabilities of the RDP integration. RDP integration takes a file as an input. It reads the file one character at a time. Determines the scancode of the character from the data file. Sends the scancode to the remote server. Also sends the value of whether the key is pressed, typed or released. These values are sent in the required order. RDP integration records user actions The user can record the set of actions to a file that can be later automated on the remote server. Format of the actions recorded to the file is (scan codes, key pressed / key released, time delay between consecutive actions). The scan codes of the keys are stored in a file using the key listener. The state of the key i.e. pressed, typed or released is stored next to the scan code in the file. The time delay between two consecutive scan codes is stored along with the later scan code in the file. RDP integration plays back the recorded actions. Sends the scan codes to the remote desktop in the same order as in the file. 3 The time delay helps the actions to play back in the same time frame as they were recorded to the file. RDP integration captures snapshot of the remote desktop. At anytime of recording the actions, the user can also capture the snapshot of the remote server and view it on the client side. The user can select a portion of the snapshot and compare it to any saved image. The captured snapshot of the remote server is a confirmation to the user during the play back of the recorded actions. 1.3 Benefits of RDP Integration The remote desktops are commonly used for development and testing. Different options are available to work interactively with the remote desktops. However, there is no option to automate the work to be done on the remote desktop. Hence, the RDP integration provides the feature to automate the frequent tasks on the remote desktop that can save lot of time, effort and can be reused. Chapter 2 includes the background on the Java RDP Clients. Detailed information on the properJavaRDP client includes keyboard shortcuts, key mapping and processing orders on the client. Chapter 3 includes the architecture and features of the Java RDP client (properJavaRDP client). Also, it includes the technology used and the steps involved in client-server connection. Chapter 4 includes implementation details of different modules of the RDP integration. Chapter 5 includes the performance evaluation of the RDP integration. Chapter 6 includes the conclusion and future work. 4 Chapter 2 BACKGROUND There is extensive use of remote desktop protocol for most of the development, testing and business purposes on the remote server [1, 4, 5]. This project is an enhancement to the properJavaRDP client. Most of the existing Java RDP Clients are based on the rdesktop RDP client. 2.1 Current existing RDP clients Some of the existing Java RDP clients are listed below [2, 9-11]. 2.1.1 rdesktop RDP Client rdesktop is an open source Java RDP client on an Unix platform. The latest version of rdesktop includes bitmap caching, encryption, file system redirection, keyboard mapping, audio redirection, login authentication, etc [10]. It helps to connect from an Ubuntu machine to a windows machine. The windows machine can be remotely controlled from a linux machine. The rdesktop is compared to the VNC in the following aspects. rdesktop is faster when compared to the VNC in terms of performance. The connection using VNC is unencrypted whereas; the rdesktop sends the login details encrypted as network packets. VNC can work on most of the operating systems. VNC allows multiple sessions. 5 2.1.2 Seamless Java RDP Client Seamless RDP client is based on the properJavaRDP client but in a seamless fashion. As rdesktop RDP client, the seamless RDP client is also a RDP client on linux. Using seamless RDP, the applications run locally on the client machine. The seamless client allows connection sharing, i.e. it can launch multiple applications using a single connection. The client allows rdesktop to run as a slave and notifies the master rdesktop to run a new command. The applications launched by the seamless Java RDP client run as local applications. Once the connection is established with the remote server, multiple applications can be launched as local applications. It enhanced the properJavaRDP client from AWT to Swing [9]. 2.1.3 Elusiva RDP Client Elusiva client is also an open source based on both rdesktop and properJavaRDP client. It runs on windows, linux and other java enabled systems. It enables sound redirection and allows virtualization [11]. Elusiva RDP client has the following features. It is compatible with RDP 4.0, 5.0, 5.1, 5.2, 6.0, 6.1 and 7 It also supports clipboard mapping. Enables encryption and security during communication. Allows serial and parallel ports redirection. Enables local audio. Supports various keyboard shortcuts. 6 2.2 properJavaRDP Client properJavaRDP is an open source Java RDP client based on rdesktop. The Remote Desktop Protocol Integration is an enhancement based on the properJavaRDP client. The properJavaRDP supports only clipboard transfer, but does not support file transfer. In addition, it supports only single session on the remote server [3]. The debug options used in properJavaRDP are as follows. --debug-key: At execution shows, the scan codes sent for each key press. --debug-hex: At execution shows, the raw bytes sent and received over the network. 2.2.1 Keyboard shortcuts As shown in the table 1 [2] different key combinations are used on the remote server to perform an action that conflicts with the client key combinations. For example, the tab key would cycle through the recent windows on the client. The key combination to enforce tab on the remote server is Alt+Insert. In this case, when the key listener detects the key combination of Alt+Insert, then the client sends the scancode of tab key to the remote server. 7 Table 1 Keyboard shortcuts Ctrl+Alt+End To open NT security dialog box. Alt+Page Up To switch between windows from left to right. Alt+Page Down To switch between windows from right to left. Alt+Insert To tab through the recent windows. Alt+Home To open the start menu. Alt+Delete To open the context menu. Ctrl+Alt+Minus To take a snapshot of the window that is active. Ctrl+Alt+Plus To take a snapshot of the entire screen. 2.2.2 Key map The figure 1 shows the key map used to retrieve the information about the scan codes of the keys entered. Key map includes key codes, scan codes and the name of the file. Figure 1 Key map I 8 The figure 2 shows that the special keys have id 0 and all other keys have id 1. Figure 2 Key map II 2.2.3 Process orders The remote server sends the network packets containing orders to the client. A network packet received by the client has n orders to process. The client interprets the orders as primary and secondary. For example, the client receives the rectangle order as below. X 11Y 58CX 58CY 15Color 15220 It consists of the x-y co-ordinates of the rectangle. It also includes the information about the color to fill in the rectangle. After the client encounters the order for a rectangle, it is processed by drawing rectangle and filling the rectangle with the given color. For example, Alt+Home key is pressed to open the start menu. As shown in the figure 3, the client draws the rectangle for the start menu. 9 Figure 3 Process rectangle orders As shown in the figure 4, the rectangle is filled with the color received in the order. Next steps include drawing the text on the rectangle of the start menu. In this way, each order is processed on the remote server. To display the processed orders on the server, it uses its own video card. 10 Figure 4 Process text orders 11 Chapter 3 ARCHITECTURE AND TECHNOLOGY 3.1 Basic Architecture of RDP Integration The architecture of the RDP integration is same as the architecture of the properJavaRDP client. Figure 5 [8] shows the client and the remote server components. After the connection is established between the client and the server and the connection is ready to send messages to the server, a window frame of the remote server pops up on the client. The pop up window frame is represented as the “Server-side Application GUI” in the Client component of the architecture diagram. The “Server-side Application” in the Remote server component represents any application running on the remote server. The “Server-side Application” can be viewed, controlled and manipulated using the “Serverside Application GUI” on the client. The communication channel between the client and the server is on the default port 3389 and using remote desktop protocol. The remote server should be configured to allow remote connections [6]. 12 Figure 5 Architecture diagram 3.1.1 Communication steps Figure 5 [7, 8] shows the communication between client and the remote server is over default port 3389 and using remote desktop protocol. Following are the steps of communication between the RDP client and the remote server. The client sends keystrokes data over the network to the remote desktop based on the key pressed, key typed and key released. The remote server uses its own video driver to render display output. The remote server constructs the information into network packets using RDP protocol. The remote server sends the network packets containing orders to the client. A single network packet includes n orders. The client interprets and processes these orders. 13 The client draws the required shapes based on these orders on the remote server. The orders also include the color to fill in these shapes. 3.2 Features and Capabilities The main features and capabilities of the RDP integration are listed below. These features are based on the properJavaRDP client. Key listener RDP Client adds key listener to receive key events from the keyboard. The key listener detects the action performed on a key using keyboard. Encryption RDP Client has an option to disable encryption from client to server. If encryption is disabled, then only the packet with login information is encrypted and all the other packets are delivered without encryption over the virtual channel. Both 40or 128-bit keys are supported for encryption [4]. Bandwidth RDP Client has an option to enable/disable latency option for bandwidth reductions by saving the tcp packets transmitted over a network connection. Connection with remote server A user can connect to the remote server using the RDP Client using the server login credentials and by setting different logging levels like debug, warn, error, etc. The user can disconnect the remote server without logging off. 14 Clipboard mapping Users can transfer the clipboard data between applications running on the client and those running on the remote session [4]. Virtual channels RDP Client has an option specify the virtual channel to initialize the RDP communication layer. The data packets process over the virtual channels. Remote control RDP Client shows the graphical interface of the remote server and enables control over the remote server. The user can also specify the dimensions of the remote window to view. It does not allow multiple sessions of the remote server [4]. Wrapped Images The RDP Client receives a buffered image of the remote desktop in every few seconds as shown in figure 6. 15 Figure 6 Wrapped image Figure 6 Wrapped image 3.3 Technology used in RDP Integration As the properJavaRDP client is based on java, the RDP integration is also developed in java using the eclipse IDE. properJavaRDP can run on Java 1.1 and up. The eclipse IDE is an open source integrated development environment. The downloaded jar of the properJavaRDP 1.1 is included in the build path of a new java project in eclipse. The RDP integration can be compiled and executed directly in the eclipse IDE as a java application. Java (TM) SE Development Kit 6 Update 22 is used for the development of RDP integration. It is developed by Oracle and the version 1.6 of this product is used. The Java (TM) SE Development Kit Update 22 includes the following. 16 The Java Runtime Environment (JRE) Capable of developing applications and applets with the help of command line tools like debuggers and compilers. The RDP integration is tested against a virtual machine with a Windows Server 2008 R2 operating system. The virtual machine is created using the VMWare vSphere Client 4.1. The windows test machine should have the feature to allow connections from computers enabled. Also it should be verified that firewall settings of the test machine allows the remote desktop connections to this system. The RDP integration can successfully execute on any windows machine that has the remote connections enabled. 3.3.1 Client-Server Connection The network socket is used for bidirectional communication. As shown in the figure 7 [12], the client and the server use the TCP socket communication to send and receive data as network packets. 17 Figure 7 TCP socket flow diagram The steps involved are as follows: The TCP transport protocol is used for communication between client and server. Initially the client sends a TCP connection request to the remote server with the details of the client protocol version. After establishing the connection, the client sends data to the server and the server receives the data. The server converts the received data into network packets and sends back to the client. The client then receives these network packets and then processes the orders included in the packets. 18 After processing all the data, the client sends an end message to the server requesting to close the socket. The server receives the close socket message and finally closes the socket and causes the RDP client to release the resources allocated to the client and server socket. Finally disconnects from a RDP session closing all the sockets. 19 Chapter 4 IMPLEMENTATION DETAILS Figure 8 shows the overall flow diagram of the RDP integration. For all the features of RDP integration, it transforms the input as scan codes that can be executed at the remote server. The RDP integration finally uses the RDP client for sending the scan codes to the remote server over network communications. Figure 8 Flow diagram of RDP Integration The RDP integration uses the methodology of FIFO (first in, first out). During automation, the scan codes of the actions are sent to the remote server in the same order as they were entered to the file. As shown below, buffered writer is used to write the scan codes to a file specified by this.myString. BufferedWriter writer; 20 writer = new BufferedWriter(new FileWriter(this.myString)); The RDP integration prompts the user to choose from the below listed options as shown in figure 9. 1. Read from file 2. Record 3. Playback Figure 9 User options To read from a file, the input file is passed as a part of the arguments to the RDP client. For the options record and playback, the user is prompted to enter the local file path as shown in figure 10. Figure 10 User file input After the connection is established with the remote server, the user is prompted to enter the credentials as shown in figure 11. 21 Figure 11 User authentication 4.1 File input When a file as shown in figure 12 is given as an input to the RDP integration, the RDP client reads each line from the file and determines the scan codes based on the key mapping. The file performs an automated task on the remote server that includes the following steps. 1. Opens a notepad from the start menu. 2. Types the string “Hello World” in the notepad. 22 3. Saves the file from the file menu of the notepad. 4. Names the files as test1. 5. Closes the notepad window. 6. Deletes the test1 file. 7. Opens the command prompt from the start menu. 8. Types the dir command from the current location. 9. Closes the command prompt. Figure 12 Input file 4.2 Record actions Actions recorded to a file are of the format (scan codes, key is pressed / released, time delay between consecutive actions) as shown in the figure 13. 0 indicates the key pressed and 49152 indicates the key released. The file shown in figure 13 is the result of the record actions feature of the RDP integration. This file would be the input to the playback actions feature of the RDP integration. 23 While recording the actions to a file, the user can capture the snapshot at different intervals. At the same time intervals, the snapshot will be displayed at the time of automation. Figure 13 File to record actions 4.2.1 Capture snapshots At anytime of recording actions the key F8 is used to capture the snapshot of the remote server. if(scancode == 0x42 && diag == null){ diag = new wizard("Screenshot", bi_local); The scan code of F8 key is 0x42. Only one JFrame window can be opened while recording a set of actions. Hence in the above code, the condition if the JFrame object is null or not. bi_local, a BufferedImage object is obtained from the wrapped images that are sent to RDP client in every few seconds. As shown in the figure 14, the menu item capture has an option to update the snapshot on the JFrame window. Also using the mouse click the portion of the image can be selected for comparison with any other image. 24 Figure 14 Capture snapshot 4.2.2 Crop, confirm and save snapshot The capture menu also has an option to crop the snapshot. The figure 15 is the snapshot after cropping the selected portion of the image in figure 14. To compare and confirm based on the co-ordinates the below code is used. Here, ‘r’ is the selected rectangular portion. PixelGrabber g1 = new PixelGrabber(image1, r.x, r.y, r.width, r.height, false); PixelGrabber g2 = new PixelGrabber(image2, r.x, r.y, r.width, r.height, false); Then the pixels are retrieved based on the width and height of the rectangle as an integer array. 25 if (g1.grabPixels()){ data1 = (int[]) g1.getPixels(); if (g2.grabPixels()){ data2 = (int[]) g2.getPixels(); Then both the images are compared pixel by pixel. Figure 15 Crop snapshot The file menu of the JFrame window also has the option to save the snapshot to the local system. 4.3 Playback actions The file shown in figure 13 is an input to the playback actions’ feature of the RDP integration. The input file is scanned line by line. The three values in a line (scan code, key pressed/ key released, time delay) are converted into tokens. Each respective token value is retrieved as shown in the code below. 26 int time = Integer.parseInt(tokens[0]); int act = Integer.parseInt(tokens[1]); int code = Integer.parseInt(tokens[2]); The above retrieved values are used to playback the recorded actions as automated task on the remote desktop. During playback the snapshots of the remote desktop are displayed at the same intervals as they were captured during the recording of the actions. This gives a visual confirmation at different intervals of the execution of the automated task. 27 Chapter 5 PERFORMANCE EVALUATION The main advantage of the RDP integration is with respect to time, effort and usability. RDP integration saves ample amount of time because it does not need manual effort to perform tasks on the remote desktop. The tasks that are to be performed repeatedly on the remote server can be recorded once using RDP integration. The recorded file can be reused any number of times to perform same task frequently. Figure 16 shows the comparison between the properJavaRDP client and the RDP integration to perform the same set of actions against the same test machine (remote server). Figure 16 Performance evaluation chart 28 It represents the time taken to perform a set of actions using the RDP client on the remote server using red. It represents the time taken to perform a set of actions using the enhanced RDP integration in blue. The time of execution is represented in milliseconds. As the figure 16 shows, there is not much time difference between the two. With respect to the performance of the RDP integration, it takes about the same time. The main difference between the original RDP client and the RDP integration is with respect to the effort. The RDP client is only interactive in nature whereas, RDP integration in automated in nature. Hence, there is less scope for errors and incorrect results if the environment is set correctly. The only issue with the RDP integration is that the user has no control over the automated task once it is initiated. The RDP client has more control on the remote actions as it is more interactive in nature. 29 Chapter 6 CONCLUSION AND FUTURE WORK The Remote Desktop Protocol Integration successfully accomplishes the goal to automate tasks using file input, recording actions and playing back recorded actions. 6.1 Advantages 6.1.1 Efficient and accurate The RDP integration efficiently runs the automated tasks on the remote server within the estimated time. It saves time and effort with minimum manual interference. 6.1.2 Visual confirmation Provides a snapshot of the remote server including its current state. The snapshot is an accurate form of visual confirmation. 6.2 Future work 6.2.1 Alerts on remote server There has to some kind of notification or alerts that gives user some information about the other applications that initiated before the automated task started by the RDP integration was completed. 6.2.2 Security The RDP integration does not guarantee the security of the automated task running on the remote server. There is a possibility of a windows application to interfere with the running automated task. 30 6.2.3 Revert to initiation point If the automated task has to end abruptly due to interference, then the user should have an option to revert to the initiation point to avoid unwanted results. 6.2.4 Run parallel automated tasks Currently the RDP integration is capable of running only one automated task at a time. It should the capability to initiate multiple automated tasks to improve performance. It should also be possible using command line option. 31 APPENDIX Source Code Input_Local.java package com.hp.oo.content; import java.io.*; import java.util.Iterator; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.propero.rdp.Input; import net.propero.rdp.RdesktopCanvas; import net.propero.rdp.Rdp; import net.propero.rdp.keymapping.KeyCode; import net.propero.rdp.keymapping.KeyCode_FileBased; import net.propero.rdp.keymapping.MapDef; /** * @author Lakshmi * Process all the keys and convert it to keystroke to determine its scan code. */ public class Input_Local extends Input{ StringBuilder contents = new StringBuilder(); String flag = null; public Input_Local(RdesktopCanvas c, Rdp r, KeyCode_FileBased k){ super(c, r, k); } // New thread to scan each character from a file class MyThread extends Thread{ public MyThread(){ } public void run(){ File file = new File("C:\\data.txt"); try { Scanner scanner = new Scanner(file); while (scanner.hasNextLine()) { String line = scanner.nextLine(); 32 line = line.replace("<#>", "\r"); line = line.replace("<##>", "\n"); try { MyThread.sleep(2000); inputStr(line); } catch (InterruptedException e) { e.printStackTrace(); } } scanner.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } } // This sends a signal that the connection is ready to send messages. Also //checks if only one thread is running to process the file public void triggerReadyToSend() { try{ Thread mythread = new MyThread(); if(flag != "done") { flag = "done"; mythread.start(); } } catch(Exception e) { logger.debug(e.getMessage()); } } //Process all the special keys public void inputStr(String str) { boolean alt_pressed = false; boolean ctl_pressed = false; modifiersValid = true; char[] ac = {'?','<','>',':','"','+','_','{','}','|','!','@','#','$','%','^','&','*','(',')'}; String[] strArr = str.split("[<>]+"); Pattern pattern = Pattern.compile("F[0-9]*"); int action = 1; long time = getTime(); for(int l=0; l<strArr.length; l++){ 33 try { MyThread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Matcher matcher = pattern.matcher(strArr[l]); char[] arr; if(strArr[l].length() > 3 && strArr[l].substring(0, 4).equalsIgnoreCase("alt-")){ sendScancode(time,0,56); scancodeToFile(0,56); alt_pressed = true; arr = altCombinationKeys(strArr[l]); if(arr == null) continue; } else if(strArr[l].length() > 3 && strArr[l].substring(0, 4).equalsIgnoreCase("ctl-")){ sendScancode(time,0,29); scancodeToFile(0,29); ctl_pressed = true; if(strArr[l].length() > 12 && strArr[l].substring(4, 8).equalsIgnoreCase("alt-") && strArr[l].substring(8, 14).equalsIgnoreCase("delete")){ sendScancode(time,0,56); scancodeToFile(0,56); alt_pressed = true; sendScancode(time,0,211); scancodeToFile(0,211); continue; } else arr = strArr[l].substring(4, 5).toCharArray(); } else if(strArr[l].length() > 3 && strArr[l].equalsIgnoreCase("delete")){ sendScancode(time,0,211); scancodeToFile(0,211); continue; } else if(strArr[l].length() > 10 && strArr[l].substring(0, 6).equalsIgnoreCase("shift-")){ sendScancode(time,0,42); scancodeToFile(0,42); if(strArr[l].substring(6, 12).equalsIgnoreCase("delete")) sendScancode(time,0,211); scancodeToFile(0,211); 34 sendScancode(time,49152,42); scancodeToFile(49152,42); continue; } else if(strArr[l].length() > 0 && matcher.find()){ functionKeys(strArr[l]); continue; } else if(strArr[l].equals("right")){ sendScancode(time,0,205); scancodeToFile(0,205); continue; } else if(strArr[l].equals("left")){ sendScancode(time,0,203); scancodeToFile(0,203); continue; } else if(strArr[l].equals("up")){ sendScancode(time,0,200); scancodeToFile(0,200); continue; } else if(strArr[l].equals("down")){ sendScancode(time,0,208); scancodeToFile(0,208); continue; } else arr = strArr[l].toCharArray(); for(int i=0;i<arr.length; i++){ boolean setFlag = false; for(int n=0; n<ac.length; n++){ if(ac[n] == arr[i]) setFlag = true; } int flags = 0; action = 1; String debugString = "Sending keypresses: "; time = getTime(); int keycode; int scancode=0; char keyChar; boolean upper = Character.isUpperCase(arr[i]); if(upper || setFlag) { 35 debugString += "(0x" + Integer.toHexString(42) + ", " + ((action == KeyCode_FileBased.UP || action == KeyCode_FileBased.QUIETUP) ? "up": "down") + ((flags & KBD_FLAG_QUIET) != 0 ? " quiet" : "") + " at " + time + ")"; sendScancode(time,0,42); scancodeToFile(0,42); logger.debug(debugString); } Iterator j = this.canvas.fbKeys.keyMap.iterator(); MapDef best = null; MapDef current = null; while (j.hasNext()) { current = (MapDef) j.next(); if (current.appliesTo(arr[i])) { best = current; } else if(Character.isWhitespace(arr[i])){ if(arr[i] == '\t') { if(current.getKeyCode() == 9) best = current; } if(arr[i] == '\n'){ if(current.getKeyCode() == 10) best = current; } if(arr[i] == ' '){ if(current.getKeyCode() == 32) best = current; } if(arr[i] == '\b'){ if(current.getKeyCode() == 8) best = current; } if(arr[i] == '\r'){ if(current.getKeyCode() == 10) best = current; } } } scancode = best.getScancode(); 36 keycode = current.getKeyCode(); keyChar = best.getKeyChar(); logger.debug("PRESSED keychar='" + arr[i] + " char='" + keyChar + "'"); logger.debug("TYPED keychar='" + arr[i] + " char='" + keyChar + "'"); debugString += "(0x" + Integer.toHexString(scancode) + ", " + ((action == KeyCode_FileBased.UP || action == KeyCode_FileBased.QUIETUP) ? "up" : "down") + ((flags & KBD_FLAG_QUIET) != 0 ? " quiet" : "") + " at " + time + ")"; sendScancode(time,0,scancode); scancodeToFile(0,scancode); logger.debug(debugString); //To release the alt key if its pressed if(alt_pressed){ sendScancode(time,49152,56); scancodeToFile(49152,56); alt_pressed = false; } //To release the ctl key if its pressed if(ctl_pressed){ sendScancode(time,49152,29); scancodeToFile(49152,29); ctl_pressed = false; } logger.debug("RELEASED keychar='" + arr[i] + " char='" + keyChar + "'"); sendScancode(time,49152,scancode); scancodeToFile(49152,scancode); if(upper || setFlag){ action = 0; debugString += "(0x" + Integer.toHexString(42) + ", " 37 + ((action == KeyCode_FileBased.UP || action == KeyCode_FileBased.QUIETUP) ? "up" : "down") + ((flags & KBD_FLAG_QUIET) != 0 ? " quiet" : "") + " at " + time + ")"; sendScancode(time,49152,42); scancodeToFile(49152,42); logger.debug(debugString); } } } // Checks if the keys pressed are in the combination of the alt key public char[] altCombinationKeys(String str){ char[] arr; if(str.substring(4).equalsIgnoreCase("Home")){ sendScancode(time, 49152, 56); // ALT scancodeToFile(49152,56); sendScancode(time, 0, 29); // left Ctrl scancodeToFile(0,29); sendScancode(time, 0, 1); // Esc scancodeToFile(0,1); sendScancode(time,49152,1); scancodeToFile(49152,1); sendScancode(time,49152,29); scancodeToFile(49152,29); return null; } else if(str.substring(4).equalsIgnoreCase("delete")){ sendScancode(time, 49152, 56); // ALT sendScancode(time, 0, 56); // ALT sendScancode(time, 49152, 56); // ALT sendScancode(time, 0, 93 | KeyCode.SCANCODE_EXTENDED); // Menu sendScancode(time, 49152, 93 | KeyCode.SCANCODE_EXTENDED); // Menu scancodeToFile(0,93); scancodeToFile(49152,93); return null; } else if(str.substring(4).equalsIgnoreCase("F4")){ sendScancode(time, 0, 62); // F4 scancodeToFile(0,62); sendScancode(time, 49152, 56); // ALT scancodeToFile(49152,56); 38 return null; } else if(str.substring(4).equalsIgnoreCase("\t")){ sendScancode(time, 0, 15); // F4 scancodeToFile(0,15); sendScancode(time, 49152, 56); // ALT scancodeToFile(49152,56); return null; } else{ arr = str.substring(4, 5).toCharArray(); return arr; } } // Checks if the key pressed is a function key and then sends the scancode to the // file public void functionKeys(String func_str){ if(func_str.equals("F1")){ sendScancode(time,0,59); scancodeToFile(0,59); sendScancode(time,49152,59); scancodeToFile(49152,59); } else if(func_str.equals("F2")){ sendScancode(time,0,60); scancodeToFile(0,60); sendScancode(time,49152,60); scancodeToFile(49152,60); } else if(func_str.equals("F3")){ sendScancode(time,0,61); scancodeToFile(0,61); sendScancode(time,49152,61); scancodeToFile(49152,61); } else if(func_str.equals("F4")){ sendScancode(time,0,62); scancodeToFile(0,62); sendScancode(time,49152,62); scancodeToFile(49152,62); } else if(func_str.equals("F5")){ sendScancode(time,0,63); scancodeToFile(0,63); sendScancode(time,49152,63); scancodeToFile(49152,63); } 39 else if(func_str.equals("F6")){ sendScancode(time,0,64); scancodeToFile(0,64); sendScancode(time,49152,64); scancodeToFile(49152,64); } else if(func_str.equals("F7")){ sendScancode(time,0,65); scancodeToFile(0,65); sendScancode(time,49152,65); scancodeToFile(49152,65); } else if(func_str.equals("F8")){ sendScancode(time,0,66); scancodeToFile(0,66); sendScancode(time,49152,66); scancodeToFile(49152,66); } else if(func_str.equals("F9")){ sendScancode(time,0,67); scancodeToFile(0,67); sendScancode(time,49152,67); scancodeToFile(49152,67); } else if(func_str.equals("F10")){ sendScancode(time,0,68); scancodeToFile(0,68); sendScancode(time,49152,68); scancodeToFile(49152,68); } else if(func_str.equals("F11")){ sendScancode(time,0,87); scancodeToFile(0,87); sendScancode(time,49152,87); scancodeToFile(49152,87); } else if(func_str.equals("F12")){ sendScancode(time,0,88); scancodeToFile(0,88); sendScancode(time,49152,88); scancodeToFile(49152,88); } } public void scancodeToFile(int action, int scancode){ try { 40 BufferedWriter writer; String text = action + "," + scancode; writer = new BufferedWriter(new FileWriter("C:\\write.txt")); contents.append(text); contents.append(System.getProperty("line.separator")); String aContents = contents.toString(); writer.write(aContents); writer.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } Input_Record.java package com.hp.oo.content; import java.awt.AWTException; import java.awt.BorderLayout; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.image.BufferedImage; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.util.Calendar; import java.util.Date; import java.util.Vector; import javax.imageio.ImageIO; import javax.swing.ImageIcon; 41 import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.event.MouseInputAdapter; import net.propero.rdp.Input; import net.propero.rdp.Options; import net.propero.rdp.RdesktopCanvas; import net.propero.rdp.RdesktopFrame_Localised; import net.propero.rdp.Rdp; import net.propero.rdp.WrappedImage; import net.propero.rdp.keymapping.KeyCode; import net.propero.rdp.keymapping.KeyCode_FileBased; import org.apache.log4j.Level; /** * @author Lakshmi * Records user actions to a file * Scans each key stroke to determine its scan code and saves it to a file. */ public class Input_Record extends Input { String myString; BufferedImage bi_local; JFrame diag = null; StringBuilder contents = new StringBuilder(); Date prevTime = getCurrentTime(); Date curTime = getCurrentTime(); File[] nFiles = new File("C:/temp/screenshots2/").listFiles(); public Input_Record(RdesktopCanvas c, Rdp r, KeyCode_FileBased k, String fname, BufferedImage bi){ super(c, r, k); this.myString = fname; this.bi_local = bi; for (File file : nFiles) { file.delete(); } File yourFile = new File(fname); yourFile.delete(); File yourNewFile = new File(fname); 42 try { yourNewFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } // Sends the key presses to the remote desktop public void sendKeyPresses(String pressSequence) { try { String debugString = "Sending keypresses: "; for (int i = 0; i < pressSequence.length(); i += 2) { int scancode = (int) pressSequence.charAt(i); int action = (int) pressSequence.charAt(i + 1); int flags = 0; if (action == KeyCode_FileBased.UP) flags = RDP_KEYRELEASE; else if (action == KeyCode_FileBased.DOWN) flags = RDP_KEYPRESS; else if (action == KeyCode_FileBased.QUIETUP) flags = RDP_KEYRELEASE | KBD_FLAG_QUIET; else if (action == KeyCode_FileBased.QUIETDOWN) flags = RDP_KEYPRESS | KBD_FLAG_QUIET; long t = getTime(); debugString += "(0x" + Integer.toHexString(scancode) + ", " + ((action == KeyCode_FileBased.UP || action == KeyCode_FileBased.QUIETUP) ? "up" : "down") + ((flags & KBD_FLAG_QUIET) != 0 ? " quiet" : "") + " at " + t + ")"; // Checks if the key F8 is pressed and then captures and //displays the screen shot of the remote desktop if(scancode == 0x42 && diag == null){ diag = new wizard("Screenshot", bi_local); } else if (scancode == 0x42) { diag.show(); } 43 sendScancode(t, flags, scancode); prevTime = curTime; curTime = getCurrentTime(); scancodeToFile(prevTime, curTime, flags, scancode); } if (pressSequence.length() > 0) logger.debug(debugString); } catch (Exception ex) { return; } } // Writes the scancodes of the keystrokes to file public void scancodeToFile(Date prev, Date cur, int action, int scancode){ try { long diff = cur.getTime() - prev.getTime(); BufferedWriter writer; String text = diff + "," + action + "," + scancode; writer = new BufferedWriter(new FileWriter(this.myString)); contents.append(text); contents.append(System.getProperty("line.separator")); String aContents = contents.toString(); writer.write(aContents); writer.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } // Gets the current time to calculate the time delay between two consecutive key // strokes. public Date getCurrentTime(){ Calendar cal = Calendar.getInstance(); Date date = cal.getTime(); return date; } 44 //Gets the most recent snapshot of the remote desktop public JLabel getJLabel() throws IOException, AWTException { long lastMod = Long.MIN_VALUE; File choise = null; for (File file : nFiles) { if (file.lastModified() > lastMod) { choise = file; lastMod = file.lastModified(); } } File last = new File(choise.toString()); BufferedImage image = ImageIO.read(last); if (image == null) { return null; } ImageIcon icon = new ImageIcon(image); return new JLabel(icon); // no image available } } Input_play.java package com.hp.oo.content; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.Scanner; import net.propero.rdp.Input; import net.propero.rdp.RdesktopCanvas; import net.propero.rdp.Rdp; import net.propero.rdp.keymapping.KeyCode_FileBased; import com.hp.oo.content.Input_Local.MyThread; /** * @author Lakshmi * Play back recorded user actions * Reads each scan code, key status (pressed or released) and the time delay from the file * and sends it to the remote desktop in the same order. */ public class Input_Play extends Input { String flag = null; 45 String str; BufferedImage bi_local; long t = getTime(); public Input_Play(RdesktopCanvas c, Rdp r, KeyCode_FileBased k, String fname, BufferedImage bi){ super(c,r,k); this.str = fname; this.bi_local = bi; } class MyThread extends Thread{ public MyThread(){ } public void run(){ File myfile = new File(str); MyThread th = new MyThread(); Scanner scanner; try { scanner = new Scanner(myfile); while (scanner.hasNextLine()) { String line = scanner.nextLine(); String[] tokens = line.split(","); int time = Integer.parseInt(tokens[0]); int act = Integer.parseInt(tokens[1]); int code = Integer.parseInt(tokens[2]); try { th.sleep(time); if(code == 0x42){ new wizard("Screenshot", bi_local); } else sendScancode(t, act, code); } catch (InterruptedException e) { e.printStackTrace(); } } scanner.close(); } catch (FileNotFoundException e1) { // TODO Auto-generated catch block 46 e1.printStackTrace(); } } } // This sends a signal that the connection is ready to send messages. Also checks if only // one thread is running to play back the recorded actions. public void triggerReadyToSend() { Thread mythread = new MyThread(); if(flag != "done") { flag = "done"; mythread.start(); } } } Compare.java package com.hp.oo.content; import java.awt.Image; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.awt.image.PixelGrabber; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JOptionPane; /** * @author Lakshmi * Compare two images based on the co-ordinates pixel by pixel and then return the * response if the two images are same or not. */ public class test { static void processImage(Rectangle r, Image img, Image image) throws IOException { String inFile = "C:/temp/screenshots1/screenCapture_6.PNG"; String inFile2 = "C:/temp/screenshots1/screenCapture_6.PNG"; 47 try { PixelGrabber grabber = new PixelGrabber(image, r.x, r.y, r.width, r.height, false); PixelGrabber grabber2 = new PixelGrabber(img, r.x, r.y, r.width, r.height, false); BufferedImage bi = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB); int[] data = null; int[] data2 = null; if (grabber.grabPixels()){ data = (int[]) grabber.getPixels(); //save a part of the png image BufferedImage b = ImageIO.read(new File("C:/temp/screenshots2/screenCapture_6.PNG")); BufferedImage bm = b.getSubimage(20, 20, 400, 400); String fileNameToSaveTo = "C:/temp/screenCapture_" + ".PNG"; writeImage(bm, fileNameToSaveTo, "PNG"); } if (grabber2.grabPixels()){ data2 = (int[]) grabber2.getPixels(); } if(java.util.Arrays.equals(data, data2) ) JOptionPane.showMessageDialog(null, "The Same"); else JOptionPane.showMessageDialog(null, "Not the same"); } catch (InterruptedException e1) { e1.printStackTrace(); } } public static void writeImage(BufferedImage img, String fileLocation, String extension) { try { BufferedImage bi = img; File outputfile = new File(fileLocation); ImageIO.write(bi, extension, outputfile); } 48 catch (IOException e) { e.printStackTrace(); } } } 49 BIBLIOGRAPHY [1] Remote Desktop Protocol (RDP), [Online] Available: http://etutorials.org/Microsoft+Products/microsoft+windows+server+2003+terminal+serv ices/Chapter+3+Communication+Protocols+and+Thin+Clients/Remote+Desktop+Protoc ol+RDP/ [2] properJavaRDP, [Online] Available: http://properjavardp.sourceforge.net/ [3] Comparison of Java Remote Desktop projects, [Online] Available: http://en.wikipedia.org/wiki/Comparison_of_Java_Remote_Desktop_projects [4] Remote Desktop Protocol, [Online] Available: http://msdn.microsoft.com/enus/library/windows/desktop/aa383015(v=vs.85).aspx [5] Java Remote Desktop Administration, [Online] Available: http://www.codeproject.com/KB/IP/RemoteAdminJava.aspx [6] RDP Security – Designing Terminal Server Security, [Online] Available: http://www.petri.co.il/securing-rdp-remote-desktop-and-terminal-serverconnections.htm [7] WS2008: Remote Desktop Connection Architecture, [Online] Available: http://blogs.technet.com/b/askperf/archive/2008/02/19/ws2008-remotedesktop-connection-architecture.aspx [8] Thin Client Architecture, [Online] 50 Available: http://msdn.microsoft.com/en-us/library/ee480537(v=winembedded.60).aspx [9] Everyday is a new day, [Online] Available: http://zhoupengylx.blogspot.com/ [10] rdesktop, [Online] Available: http://en.wikipedia.org/wiki/Rdesktop [11] Elusiva - Remote Desktop Client, [Online] Available: http://www.elusiva.com/products/RemoteDesktopClient.aspx [12] Internet socket, [Online] Available: http://en.wikipedia.org/wiki/Internet_socket