├── BUILDING.txt ├── CHANGES.txt ├── COPYRIGHT.txt ├── README.txt ├── RFCs.txt ├── build-awt.xml ├── build-blackberry-enterprise.properties ├── build-blackberry-midp1.properties ├── build-blackberry-midp2.properties ├── build-blackberry.properties ├── build-blackberry.xml ├── build-kindle.xml ├── build-package.xml ├── build-ssh1-lite.properties ├── build-ssh1.properties ├── build-ssh2-lite.properties ├── build-ssh2.properties ├── build.properties ├── build.xml ├── conf ├── KindleTERM.manifest ├── developer.keystore ├── httpserver-manifest.txt ├── log4j.properties ├── midpssh.alx └── session.properties ├── excludes.cfg ├── lib ├── antenna-bin-1.2.1-beta.jar ├── kdk.jar └── proguard.jar ├── res ├── font ├── font3x6lcd.png ├── font4x6lcd.png ├── font4x6lcdV.png ├── font4x7lcd.png ├── font5x9lcd.png ├── font8x13lcd.png ├── large.png └── small.png └── src ├── httpserver └── midpssh │ ├── ChunkedInputStream.java │ ├── FiniteInputStream.java │ ├── HttpFields.java │ ├── HttpInputStream.java │ ├── HttpOutputStream.java │ ├── ParseException.java │ ├── Server.java │ └── Session.java ├── j2me ├── app │ ├── LineInputStream.java │ ├── Main.java │ ├── MyRecordStore.java │ ├── SessionManager.java │ ├── SessionSpec.java │ ├── Settings.java │ └── session │ │ ├── HttpInboundStream.java │ │ ├── HttpOutboundStream.java │ │ ├── ISshSession.java │ │ ├── MacroSetManager.java │ │ ├── Session.java │ │ ├── SessionIOHandler.java │ │ ├── SshSession.java │ │ └── TelnetSession.java ├── awt │ ├── AwtMain.java │ ├── AwtSession.java │ ├── AwtSshSession.java │ └── AwtTerminal.java ├── gui │ ├── Activatable.java │ ├── EditableForm.java │ ├── EditableMenu.java │ ├── ImportSessionsForm.java │ ├── MainMenu.java │ ├── Redrawable.java │ ├── SessionForm.java │ ├── SessionsMenu.java │ ├── session │ │ ├── SpecialMenu.java │ │ └── macros │ │ │ ├── MacroForm.java │ │ │ ├── MacroSet.java │ │ │ └── MacrosMenu.java │ └── settings │ │ ├── SettingsForm.java │ │ └── SettingsMenu.java ├── kindle │ ├── FlashPanel.java │ ├── KindleTerminal.java │ ├── ProxyKeyEvent.java │ ├── RemoteKbdReceiver.java │ ├── RemoteKeyboard.java │ └── TermKindlet.java ├── ssh │ ├── SshIO.java │ ├── SshPacket.java │ ├── v1 │ │ ├── BigInteger.java │ │ ├── Blowfish.java │ │ ├── Cipher.java │ │ ├── DES.java │ │ ├── DES3.java │ │ ├── IDEA.java │ │ ├── MD5.java │ │ ├── NONE.java │ │ ├── SshCrypto.java │ │ └── SshPacket1.java │ └── v2 │ │ ├── BigInteger.java │ │ ├── BufferedDESedeCBC.java │ │ ├── DHKeyExchange.java │ │ ├── HMACSHA1.java │ │ ├── PublicKeyAuthentication.java │ │ ├── SHA1Digest.java │ │ ├── SshCrypto2.java │ │ └── SshPacket2.java ├── telnet │ ├── Dimension.java │ └── TelnetProtocolHandler.java └── terminal │ ├── LCDFont.java │ ├── Terminal.java │ └── VT320.java └── tasks ├── FileLength.java └── RewriteBlackberryJAD.java /BUILDING.txt: -------------------------------------------------------------------------------- 1 | To build MidpSSH you need to have the following software installed: 2 | 3 | * Apache Ant (ant.apache.org) 4 | * J2ME Wireless Toolkit (java.sun.com/j2me) 5 | 6 | MidpSSH uses an Ant pluggin called Antenna (antenna.sourceforge.net). Antenna must 7 | be installed in your Ant classpath. For more information please see the Antenna 8 | website. 9 | 10 | -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | 1.7.3 2 | Fix SSH protocol error that caused connection drop on ScreenOS firewall - thanks Stefan Brunner 3 | Improve security of SSH implementation by simple state tracking - thanks to Aleksy Schubert for bringing this to my attention 4 | 5 | 1.7.2 6 | Add BB Wi-fi support 7 | 8 | 1.7.1 9 | Attempt to fix BB OTA JAD files 10 | Upgrade to Antenna 1.0.0 11 | Upgrade to WTK2.5.2 12 | Upgrade to Proguard 4.1 13 | 14 | 1.7.0 15 | Proguard upgrade from 3.3.2 to 3.8. Reduces lite build sizes by 13 and 24 bytes respectively. 16 | Antenna upgrade from 0.9.13 to 0.9.14. No significant improvements. Just the latest. 17 | Upgrade to WTK2.5 18 | BlackBerry JDE upgrade to 4.2.0 19 | Settings forms no longer have an OK and Back option. They just have a back option, no longer any way to cancel changes. 20 | Fix Blackberry Pearl ChoiceGroup bug by changing from EXCLUSIVE to POPUP ChoiceGroups for MIDP2. 21 | 22 | 1.5.8 becomes 1.6.0 23 | Release version. 24 | Testing support for avoiding InputStream.available() method 25 | Improved build process - now deploys each new version into a separate URL so that old versions can be maintained 26 | Updated to BB 4.0.2 27 | Checksums created for all files 28 | Field access permissions tightened as per recommendations in the paper by Erik Poll and Aleksy Schubert (http://zls.mimuw.edu.pl/~alx/papers/wits.pdf) 29 | 30 | 1.5.4 31 | Keyboard-interactive support 32 | 33 | 1.5.3 34 | Released HTTP proxy support 35 | 36 | 1.4.20 37 | Changed lcdfont8x16 to lcdfont8x13 38 | 39 | 1.4.19 40 | Added lcdfont8x16 41 | 42 | 1.4.18 43 | Fixes for BB bad packets (due to noiosync issue) 44 | Fix for bad packet type 0 on SSH 1 keep-alive 45 | Check for accumulated data waiting to send upon ready to send 46 | 47 | 1.4.12 48 | Fix for devices that AIOOB on LCD fonts 49 | BB MIDP2 version 50 | 51 | 1.4.11 52 | Added more LCD font sizes 53 | Added BGR mode for LCD fonts 54 | Added vertical LCD font 55 | Bug fix for Siemens full screen and rotated view (thanks to DarkBear) 56 | 57 | 1.4.10 58 | Public key authentication added 59 | Special menu refactored 60 | Source code overhaul to reduce file size for lite versions 61 | 62 | 1.4.9 63 | Added settings menu for SSH2 Lite (as a result of size savings elsewhere) 64 | Username & Password now optional on sessions and both will be prompted for at connect 65 | Roar font test 66 | 67 | 1.4.8 68 | Fix for BitVise SSH (and maybe others) which sends KEX_INIT immediately after its id string 69 | Support for typing control chars and newlines in macros 70 | 71 | 1.4.7 72 | Setting for polling I/O 73 | Keep-alive sending re-added for Blackberry (and other no-io-sync). 74 | Code tidy and shrinkage, especially in SSH2 code 75 | SSH2 lite version now <64KB 76 | Predictive text usage is now a setting 77 | Settings renamed and slighly reorganised 78 | 79 | 1.4.6 80 | Function keys and insert keys now work on Blackberry and some other builds where they didn't work before. 81 | Connection type option for session import on Blackberries 82 | Sorting of sessions and macro sets fixed 83 | IOOBException on BB better fixed 84 | 85 | 1.4.5 86 | Blackberry type mode freeze fix 87 | Blackberry enterprise version added (for MDS only to avoid split-pipe security constraint) 88 | More text fields non-predictive 89 | 90 | 1.4.4 91 | Setting for ssh2 private key strength 92 | Setting to pregenerate ssh2 private and public key on phone and store 93 | Patch for BigInteger.modPow improved performance (http://www.bouncycastle.org/devmailarchive/msg03877.html) 94 | Changed default ssh2 key size from 32 to 512 (recommended minimum, http://www.bouncycastle.org/devmailarchive/msg03877.html) 95 | Display host key fingerprint 96 | 97 | 1.4.3 98 | 99 | Added password prompt if no password provided in session spec 100 | Added session list download 101 | Blackberry IOOB fix when using menus 102 | Choose preferred SSH version for connecting to 1.99 hosts 103 | Properly implemented ANSI colours, including bold 104 | 105 | 1.4.2 106 | 107 | Vibrate on beep 108 | INSERT & DELETE special keys added 109 | Trial removing sync on I/O for Blackberry 110 | Fixed SSH2 broken in 1.4.1 111 | Turn off predictive text in input boxes 112 | Fixed < in tiny font - thanks Goetz Schwandtner 113 | 114 | 1.4.1 115 | 116 | Fixed AraryIndexOutOfBoundsException when connecting to a host with a large key. 117 | Added Blackberry OTA 118 | 119 | 1.3.12 120 | 121 | Application error on Motorola (and others) fixed - problem in javac target 122 | Session report no longer displayed if a crash closes the connection, to enable the user to view the error message. 123 | 124 | 1.3.11 125 | 126 | Fixed magenta colour - thanks GeniusOne2 127 | Added connection type option for Blackberry (default of BES) 128 | 129 | 1.3.10 130 | 131 | Fixed problems introduced in 1.3.9 for Motorola phones due to rolling of SshMisc into SshIO. 132 | 133 | 1.3.9 134 | 135 | Back button added to Key Bindings popup 136 | Input dialog changed to not blank content if you use the Back button 137 | Fixed cols/rows, broken in 1.3.8 138 | 139 | 1.3.8 140 | 141 | Fix fullscreen on some devices. 142 | Reduction in file size. 143 | Improved functionality on lite builds. 144 | Added program icon 145 | 146 | 1.3.7 147 | 148 | Settings reorganisation 149 | "Use" option on macros 150 | Default macro set when none exist 151 | 152 | 1.3.6 153 | 154 | Fixed game actions interfering in connected mode 155 | Added home and end keys 156 | Fixed back-to-main-menu on resume 157 | 158 | 1.3.5 159 | 160 | Disconnect menu item changed so not default on some phones 161 | Fullscreen option added 162 | Page up / Page down added 163 | 164 | 1.3.4 165 | 166 | Newlines changed from \n to \r\n then back to \r with fix for telnet 167 | Interactive typing mode fixed (some phones were interpreting keypresses as game actions - and thus as cursor movements) 168 | 169 | 1.3.3 170 | 171 | Font size options 172 | Added Midlet-Permission tag to JAD - does this help siemens phones? 173 | Additional rotation option 174 | 175 | 1.3.2 176 | 177 | terminal type preference, eg. vt320 etc 178 | joystick operates the cursor all the time rather than just in cursor mode 179 | FAILED Ssh2 lite < 64KB? 180 | rotated version - so it could be wider than tall 181 | Find and fix disconnection on blackberry using ssh2 when pressing backspace in typing mode 182 | Fixed 1.3.1 bug where you could no longer connect on MIDP 1.0 phones! 183 | 184 | 1.3.1 185 | 186 | Changed select command code so that it shouldn't appear twice on the Blackberry, 187 | and may work better on midp 1.0 phones. 188 | Fixed SSH1 lite size so that it will work better on 64KB limited phones. 189 | Fixed SSH2 idle disconnect problem 190 | 191 | 1.2.2 192 | Fixed exceptions when using edit/delete etc on empty lists (session menu, macros menu) 193 | 194 | 1.2.1 195 | Reinstated special midp2 enhancements; preprocess symbol wasn't being set correctly 196 | 197 | 1.2 198 | SSH2 support 199 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/README.txt -------------------------------------------------------------------------------- /RFCs.txt: -------------------------------------------------------------------------------- 1 | The Secure Shell (SSH) Protocol Architecture 2 | http://www.ietf.org/rfc/rfc4251.txt 3 | 4 | The Secure Shell (SSH) Authentication Protocol 5 | http://www.ietf.org/rfc/rfc4252.txt 6 | 7 | The Secure Shell (SSH) Transport Layer Protocol 8 | http://www.ietf.org/rfc/rfc4253.txt 9 | 10 | The Secure Shell (SSH) Connection Protocol 11 | http://www.ietf.org/rfc/rfc4254.txt 12 | 13 | Generic Message Exchange Authentication for 14 | the Secure Shell Protocol (SSH) 15 | http://www.ietf.org/rfc/rfc4256.txt 16 | -------------------------------------------------------------------------------- /build-awt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 63 | 64 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /build-blackberry-enterprise.properties: -------------------------------------------------------------------------------- 1 | preprocess.symbols=ssh2,blackberry,simplevt320,noiosync,nopaintsync,blackberryenterprise 2 | jad.icon=large.png 3 | obfuscate-blackberry=true 4 | -------------------------------------------------------------------------------- /build-blackberry-midp1.properties: -------------------------------------------------------------------------------- 1 | # Blackberry JDE 2 | bb.home=c:/Program Files/Research In Motion/BlackBerry JDE 3.7 3 | #bb.home=C:/Program Files/Research In Motion/BlackBerry JDE Component Package 4.3.0 4 | bb.buildjars.home=${bb.home}/bin 5 | bb.lib.home=${bb.home}/lib 6 | 7 | # BB simulator 8 | bb.simulator=${bb.home}/simulator 9 | bb.simulator.run=${bb.home}/bin/run.bat 10 | 11 | # BB 7500 simulator 12 | #bb.simulator=${bb.home}/simulator2 13 | #bb.simulator.run=${bb.home}/simulator2/runOs7500.bat 14 | 15 | # BB 7700 simulator 16 | #bb.simulator=${bb.home}/simulator3 17 | #bb.simulator.run=${bb.home}/simulator3/runOs7700.bat 18 | 19 | bb.ota=true -------------------------------------------------------------------------------- /build-blackberry-midp2.properties: -------------------------------------------------------------------------------- 1 | # Blackberry JDE 2 | bb.home=C:/Program Files/Research In Motion/BlackBerry JDE Component Package 4.3.0 3 | bb.buildjars.home=${bb.home}/bin 4 | bb.lib.home=${bb.home}/lib 5 | 6 | # BB simulator 7 | bb.simulator=${bb.home}/simulator 8 | bb.simulator.run=${bb.home}/simulator/8100.bat 9 | 10 | bb.ota=true 11 | -------------------------------------------------------------------------------- /build-blackberry.properties: -------------------------------------------------------------------------------- 1 | preprocess.symbols=ssh2,blackberry,noiosync,nopaintsync,blackberryconntypes,keybrdinteractive 2 | jad.icon=large.png 3 | obfuscate-blackberry=true 4 | -------------------------------------------------------------------------------- /build-blackberry.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 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 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /build-kindle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 66 | 67 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 88 | 89 | 90 | 91 | 93 | 97 | 101 | 105 | 106 | 107 | 108 | 109 | 110 | 112 | 113 | 114 | 115 | 119 | 120 | 122 | 123 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /build-ssh1-lite.properties: -------------------------------------------------------------------------------- 1 | #preprocess.symbols=nosettings,nodocs,notelnet,simplevt320,small,notyping,nospecialmenu,nocursororscroll 2 | preprocess.symbols=nodocs,notelnet,simplevt320,small,noinstructions,nosessionimport,nofonts 3 | 4 | obfuscate-lite=true 5 | -------------------------------------------------------------------------------- /build-ssh1.properties: -------------------------------------------------------------------------------- 1 | preprocess.symbols=NONE 2 | jad.icon=small.png 3 | obfuscate-normal=true 4 | -------------------------------------------------------------------------------- /build-ssh2-lite.properties: -------------------------------------------------------------------------------- 1 | preprocess.symbols=nodocs,notelnet,simplevt320,ssh2,nossh1,small,noinstructions,nosessionimport,nofonts,nocursororscroll,nospecialmenu 2 | # to reduce size by 500 bytes - nocursororscroll 3 | obfuscate-lite-nossh1=true 4 | -------------------------------------------------------------------------------- /build-ssh2.properties: -------------------------------------------------------------------------------- 1 | preprocess.symbols=ssh2,keybrdinteractive 2 | jad.icon=small.png 3 | obfuscate-normal=true 4 | -------------------------------------------------------------------------------- /build.properties: -------------------------------------------------------------------------------- 1 | # MidpSSH build properties 2 | version=1.7.3 3 | jad.target=http://www.xk72.com/midpssh/v${version} 4 | 5 | name=MidpSSH 6 | 7 | #wtk.home=c:/WTK21 8 | #deviceName=DefaultColorPhone 9 | 10 | #wtk.home=c:/WTK22 11 | #deviceName=DefaultColorPhone 12 | 13 | wtk.home=../../../../WTK-2.5.1 14 | deviceName=DefaultColorPhone 15 | 16 | #wtk.home=c:/SonyEricsson/J2ME_SDK/PC_Emulation/WTK2 17 | #deviceName=SonyEricsson_K700 18 | 19 | build.dir=build 20 | dist.dir=dist 21 | zip.file=midpssh.zip 22 | 23 | #preprocess.symbols.global=debug 24 | #preprocess.symbols.global=io.no_available 25 | preprocess.symbols.global=NONE 26 | 27 | jad.vendor=XK72 28 | -------------------------------------------------------------------------------- /conf/KindleTERM.manifest: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: kindle.TermKindlet 3 | Implementation-Title: KindleTERM 4 | Implementation-Version: 1 5 | Implementation-Vendor: VDP 6 | -------------------------------------------------------------------------------- /conf/developer.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/conf/developer.keystore -------------------------------------------------------------------------------- /conf/httpserver-manifest.txt: -------------------------------------------------------------------------------- 1 | Main-Class: midpssh.Server 2 | -------------------------------------------------------------------------------- /conf/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=debug, R 2 | 3 | log4j.category.kindle.KindleTerminal=info 4 | log4j.category.kindle.KindleTerminal$Redrawer=warn 5 | 6 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 7 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 8 | 9 | # Pattern to output the caller's file name and line number. 10 | log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n 11 | 12 | log4j.appender.R=org.apache.log4j.RollingFileAppender 13 | log4j.appender.R.File=/mnt/us/developer/KindleTERM/work/kterm.log 14 | 15 | log4j.appender.R.MaxFileSize=100KB 16 | # Keep one backup file 17 | log4j.appender.R.MaxBackupIndex=1 18 | 19 | log4j.appender.R.layout=org.apache.log4j.PatternLayout 20 | log4j.appender.R.layout.ConversionPattern=%d{dd MMM HH:mm:ss} %5p [%t] (%F:%L) - %m%n 21 | -------------------------------------------------------------------------------- /conf/midpssh.alx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @NAME@ 5 | 6 | 7 | Telnet and SSH application for Java compatible phone and other mobile devices. 8 | Please visit the project website for more information: 9 | http://www.xk72.com/midpssh/ 10 | 11 | 12 | @VERSION@ 13 | 14 | 15 | Developed by Karl von Randow, based upon FloydSSH and Telnet Floyd by Radek Polak 16 | 17 | 18 | Distributed under the GPL License. 19 | 20 | 21 | 22 | 23 | 24 | 25 | @CODNAME@.cod 26 | @CODNAME@-1.cod 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /conf/session.properties: -------------------------------------------------------------------------------- 1 | host localhost 2 | port 22 3 | user root 4 | pass pass -------------------------------------------------------------------------------- /excludes.cfg: -------------------------------------------------------------------------------- 1 | app/SessionSpec.java 2 | app/Main.java 3 | app/SessionManager.java 4 | app/MyRecordStore.java 5 | app/session/HttpOutboundStream.java 6 | app/session/SshSession.java 7 | app/session/Session.java 8 | app/session/MacroSetManager.java 9 | app/session/TelnetSession.java 10 | app/session/HttpInboundStream.java 11 | app/Settings.java 12 | app/LineInputStream.java 13 | gui/MainMenu.java 14 | gui/settings 15 | gui/settings/SettingsForm.java 16 | gui/settings/SettingsMenu.java 17 | gui/EditableMenu.java 18 | gui/SessionForm.java 19 | gui/SessionsMenu.java 20 | gui/session 21 | gui/session/SpecialMenu.java 22 | gui/session/macros 23 | gui/session/macros/MacroSet.java 24 | gui/session/macros/MacroForm.java 25 | gui/session/macros/MacrosMenu.java 26 | gui/ImportSessionsForm.java 27 | gui/Activatable.java 28 | gui/EditableForm.java 29 | terminal/LCDFont.java 30 | terminal/Terminal.java -------------------------------------------------------------------------------- /lib/antenna-bin-1.2.1-beta.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/lib/antenna-bin-1.2.1-beta.jar -------------------------------------------------------------------------------- /lib/kdk.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/lib/kdk.jar -------------------------------------------------------------------------------- /lib/proguard.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/lib/proguard.jar -------------------------------------------------------------------------------- /res/font: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/res/font -------------------------------------------------------------------------------- /res/font3x6lcd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/res/font3x6lcd.png -------------------------------------------------------------------------------- /res/font4x6lcd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/res/font4x6lcd.png -------------------------------------------------------------------------------- /res/font4x6lcdV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/res/font4x6lcdV.png -------------------------------------------------------------------------------- /res/font4x7lcd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/res/font4x7lcd.png -------------------------------------------------------------------------------- /res/font5x9lcd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/res/font5x9lcd.png -------------------------------------------------------------------------------- /res/font8x13lcd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/res/font8x13lcd.png -------------------------------------------------------------------------------- /res/large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/res/large.png -------------------------------------------------------------------------------- /res/small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/res/small.png -------------------------------------------------------------------------------- /src/httpserver/midpssh/ChunkedInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)ChunkedInputStream.java 0.3-3 06/05/2001 3 | * 4 | * This file is part of the HTTPClient package 5 | * Copyright (C) 1996-2001 Ronald Tschal�r 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free 19 | * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 | * MA 02111-1307, USA 21 | * 22 | * For questions, suggestions, bug-reports, enhancement-requests etc. 23 | * I may be contacted at: 24 | * 25 | * ronald@innovation.ch 26 | * 27 | * The HTTPClient's home page is located at: 28 | * 29 | * http://www.innovation.ch/java/HTTPClient/ 30 | * 31 | */ 32 | 33 | package midpssh; 34 | 35 | import java.io.EOFException; 36 | import java.io.FilterInputStream; 37 | import java.io.IOException; 38 | import java.io.InputStream; 39 | 40 | /** 41 | * This class de-chunks an input stream. 42 | * 43 | * @version 0.3-3 06/05/2001 44 | * @author Ronald Tschal�r 45 | */ 46 | public class ChunkedInputStream extends FilterInputStream { 47 | /** 48 | * @param is 49 | * the input stream to dechunk 50 | */ 51 | public ChunkedInputStream(InputStream is) { 52 | super(is); 53 | } 54 | 55 | byte[] one = new byte[1]; 56 | 57 | public synchronized int read() throws IOException { 58 | int b = read(one, 0, 1); 59 | if (b == 1) 60 | return (one[0] & 0xff); 61 | else 62 | return -1; 63 | } 64 | 65 | private long chunk_len = -1; 66 | 67 | private boolean eof = false; 68 | 69 | public synchronized int read(byte[] buf, int off, int len) throws IOException { 70 | if (eof) 71 | return -1; 72 | 73 | if (chunk_len == -1) // it's a new chunk 74 | { 75 | try { 76 | chunk_len = getChunkLength(in); 77 | } catch (ParseException pe) { 78 | throw new IOException(pe.toString()); 79 | } 80 | } 81 | 82 | if (chunk_len > 0) // it's data 83 | { 84 | if (len > chunk_len) 85 | len = (int) chunk_len; 86 | int rcvd = in.read(buf, off, len); 87 | if (rcvd == -1) 88 | throw new EOFException("Premature EOF encountered"); 89 | 90 | chunk_len -= rcvd; 91 | if (chunk_len == 0) // got the whole chunk 92 | { 93 | in.read(); // CR 94 | in.read(); // LF 95 | chunk_len = -1; 96 | } 97 | 98 | return rcvd; 99 | } else // the footers (trailers) 100 | { 101 | // discard 102 | /* 103 | * try { readLines(); } catch ( IOException e ) {} 104 | */ 105 | 106 | eof = true; 107 | return -1; 108 | } 109 | } 110 | 111 | /** 112 | * Gets the length of the chunk. 113 | * 114 | * @param input 115 | * the stream from which to read the next chunk. 116 | * @return the length of chunk to follow (w/o trailing CR LF). 117 | * @exception ParseException 118 | * If any exception during parsing occured. 119 | * @exception IOException 120 | * If any exception during reading occured. 121 | */ 122 | final static long getChunkLength(InputStream input) throws ParseException, IOException { 123 | byte[] hex_len = new byte[16]; // if they send more than 8EB chunks... 124 | int off = 0, ch; 125 | 126 | // read chunk length 127 | 128 | while ((ch = input.read()) > 0 && (ch == ' ' || ch == '\t')) 129 | ; 130 | if (ch < 0) 131 | throw new EOFException("Premature EOF while reading chunk length"); 132 | hex_len[off++] = (byte) ch; 133 | while ((ch = input.read()) > 0 && ch != '\r' && ch != '\n' && ch != ' ' && ch != '\t' && ch != ';' && off < hex_len.length) 134 | hex_len[off++] = (byte) ch; 135 | 136 | while ((ch == ' ' || ch == '\t') && (ch = input.read()) > 0) 137 | ; 138 | if (ch == ';') // chunk-ext (ignore it) 139 | while ((ch = input.read()) > 0 && ch != '\r' && ch != '\n') 140 | ; 141 | 142 | if (ch < 0) 143 | throw new EOFException("Premature EOF while reading chunk length"); 144 | if (ch != '\n' && (ch != '\r' || input.read() != '\n')) 145 | throw new ParseException("Didn't find valid chunk length: " + new String(hex_len, 0, off, "8859_1")); 146 | 147 | // parse chunk length 148 | 149 | try { 150 | return Long.parseLong(new String(hex_len, 0, off, "8859_1").trim(), 16); 151 | } catch (NumberFormatException nfe) { 152 | throw new ParseException("Didn't find valid chunk length: " + new String(hex_len, 0, off, "8859_1")); 153 | } 154 | } 155 | 156 | // private void readLines() throws IOException { 157 | // /* This loop is a merge of readLine() from DataInputStream and 158 | // * the necessary header logic to merge continued lines and terminate 159 | // * after an empty line. The reason this is explicit is because of 160 | // * the need to handle InterruptedIOExceptions. 161 | // */ 162 | // loop: while ( true ) { 163 | // boolean got_cr = false, bol = false; 164 | // int b = super.read(); 165 | // switch ( b ) { 166 | // case -1: 167 | // throw new EOFException( "Encountered premature EOF while reading 168 | // trailers" ); 169 | // case '\r': 170 | // got_cr = true; 171 | // break; 172 | // case '\n': 173 | // if ( bol ) break loop; // all headers read 174 | // bol = true; 175 | // got_cr = false; 176 | // break; 177 | // case ' ': 178 | // case '\t': 179 | // if ( bol ) // a continued line 180 | // { 181 | // // replace previous \n with SP 182 | // bol = false; 183 | // break; 184 | // } 185 | // default: 186 | // if ( got_cr ) { 187 | // got_cr = false; 188 | // } 189 | // bol = false; 190 | // break; 191 | // } 192 | // } 193 | // } 194 | 195 | public synchronized long skip(long num) throws IOException { 196 | byte[] tmp = new byte[(int) num]; 197 | int got = read(tmp, 0, (int) num); 198 | 199 | if (got > 0) 200 | return (long) got; 201 | else 202 | return 0L; 203 | } 204 | 205 | public synchronized int available() throws IOException { 206 | if (eof) 207 | return 0; 208 | 209 | if (chunk_len != -1) 210 | return (int) chunk_len + in.available(); 211 | else 212 | return in.available(); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /src/httpserver/midpssh/FiniteInputStream.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2006 Karl von Randow. 3 | * 4 | * --LICENSE NOTICE-- 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | * --LICENSE NOTICE-- 19 | * 20 | */ 21 | 22 | package midpssh; 23 | 24 | import java.io.FilterInputStream; 25 | import java.io.IOException; 26 | import java.io.InputStream; 27 | 28 | /** 29 | * FiniteInputStream is a FilterInputStream implementation that takes a limit on 30 | * the number of bytes that can be read from the stream. 31 | */ 32 | public class FiniteInputStream extends FilterInputStream { 33 | private long size; 34 | 35 | private long counter; 36 | 37 | public FiniteInputStream(InputStream in, long size) { 38 | super(in); 39 | this.size = size; 40 | counter = 0; 41 | } 42 | 43 | public int read() throws IOException { 44 | if (counter < size) { 45 | int c = in.read(); 46 | if (c != -1) { 47 | counter++; 48 | return c; 49 | } else { 50 | return -1; 51 | } 52 | } else { 53 | return -1; 54 | } 55 | } 56 | 57 | public int read(byte b[]) throws IOException { 58 | return read(b, 0, b.length); 59 | } 60 | 61 | public int read(byte b[], int off, int len) throws IOException { 62 | if (counter + len >= size) { 63 | len = (int) (size - counter); 64 | if (len <= 0) 65 | return -1; 66 | } 67 | int n = in.read(b, off, len); 68 | if (n > 0) { 69 | counter += n; 70 | } 71 | return n; 72 | } 73 | 74 | public long skip(long n) throws IOException { 75 | if (counter + n >= size) { 76 | n = size - counter; 77 | } 78 | long skipped = in.skip(n); 79 | counter += skipped; 80 | return skipped; 81 | } 82 | 83 | public int available() throws IOException { 84 | int n = in.available(); 85 | if (counter + n >= size) { 86 | n = (int) (size - counter); 87 | } 88 | return n; 89 | } 90 | 91 | public long getCounter() { 92 | return counter; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/httpserver/midpssh/HttpFields.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2006 Karl von Randow. 3 | * 4 | * --LICENSE NOTICE-- 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | * --LICENSE NOTICE-- 19 | * 20 | */ 21 | 22 | package midpssh; 23 | 24 | import java.io.EOFException; 25 | import java.io.IOException; 26 | import java.io.Serializable; 27 | import java.util.ArrayList; 28 | 29 | /** 30 | * 31 | * @author karl 32 | * @version 33 | */ 34 | public class HttpFields extends Object implements Serializable, Cloneable { 35 | 36 | private ArrayList fieldNames = new ArrayList(); 37 | 38 | private ArrayList fieldValues = new ArrayList(); 39 | 40 | /** Holds value of property firstLine. */ 41 | private String firstLine; 42 | 43 | /** Creates new HttpFields */ 44 | public HttpFields() { 45 | } 46 | 47 | public boolean read(HttpInputStream in) throws IOException { 48 | firstLine = in.readLineInclusive(); 49 | if (firstLine == null) 50 | throw new EOFException("EOF reading HTTP headers"); 51 | String trimmedFirstLine = HttpInputStream.trimNewline(firstLine); 52 | if (trimmedFirstLine.length() == 0) { 53 | firstLine = ""; 54 | return false; 55 | } 56 | 57 | // Sanity check, some servers don't return headers they just return body 58 | // straight away (eg. images on Tucows.com) 59 | if (firstLine.indexOf("HTTP/") == -1) { 60 | in.unreadLine(firstLine); 61 | firstLine = null; 62 | return true; 63 | } 64 | 65 | // Trim the newline characters 66 | firstLine = trimmedFirstLine; 67 | 68 | String line = in.readLine(); 69 | String key = null; 70 | StringBuffer value = null; 71 | 72 | // System.out.println(); 73 | // System.out.println( firstLine ); 74 | while (line != null && line.length() != 0) { 75 | // System.out.println( line ); 76 | if (line.startsWith(" ")) { 77 | if (value == null) { 78 | throw new IOException("Found header field continuation before a header field!: \"" + line + "\""); 79 | } 80 | // value.append( " " ); 81 | value.append(line); // .trim() 82 | } else { 83 | int colon = line.indexOf(":"); 84 | if (colon == -1) { 85 | if (value != null) { 86 | value.append(' '); 87 | value.append(line); 88 | } 89 | } else { 90 | if (key != null) { 91 | addField(key, value.toString().trim()); 92 | } 93 | key = line.substring(0, colon); 94 | value = new StringBuffer(); 95 | if (colon + 2 < line.length()) { 96 | value.append(line.substring(colon + 2)); // .trim() 97 | } 98 | } 99 | } 100 | 101 | line = in.readLine(); 102 | } 103 | 104 | if (key != null) { 105 | addField(key, value.toString().trim()); 106 | } 107 | 108 | if (line == null) 109 | throw new EOFException("EOF reading HTTP headers"); 110 | return true; 111 | } 112 | 113 | public String get(String fieldName) { 114 | return getField(fieldName); 115 | } 116 | 117 | public String getField(String fieldName) { 118 | int n = fieldNames.size(); 119 | 120 | for (int i = 0; i < n; i++) { 121 | String key = (String) fieldNames.get(i); 122 | if (key.equalsIgnoreCase(fieldName)) { 123 | return (String) fieldValues.get(i); 124 | } 125 | } 126 | 127 | return null; 128 | } 129 | 130 | public int getIntField(String fieldName) throws NumberFormatException { 131 | return getIntField(fieldName, -1); 132 | } 133 | 134 | public int getIntField(String fieldName, int defaultValue) throws NumberFormatException { 135 | String value = getField(fieldName); 136 | if (value != null) { 137 | value = value.trim(); 138 | try { 139 | return Integer.parseInt(value); 140 | } catch (NumberFormatException e) { 141 | // Try to get some numbers from the front as some spastic web 142 | // servers return something after the number, 143 | /* 144 | * eg. from 145 | * http://ad.nz.doubleclick.net/viewad/622507/asb_matrix_home_tile_260x80.gif 146 | * HTTP/1.0 200 OK Server: DCLK-HttpSvr Content-Type: image/gif 147 | * Content-Length: 7996Wed, 13 Aug 2003 04:51:35 GMT 148 | */ 149 | int iValue = -1; 150 | for (int i = 1; i <= value.length(); i++) { 151 | try { 152 | iValue = Integer.parseInt(value.substring(0, i)); 153 | } catch (NumberFormatException f) { 154 | // If possible return the last number that was valid 155 | if (i > 1) 156 | return iValue; 157 | // Otherwise throw the original exception 158 | break; 159 | } 160 | } 161 | throw e; 162 | } 163 | } else { 164 | return defaultValue; 165 | } 166 | } 167 | 168 | /** 169 | */ 170 | public void addField(String key, String value) { 171 | fieldNames.add(key); 172 | fieldValues.add(value); 173 | } 174 | 175 | /** 176 | * Getter for property firstLine. 177 | * 178 | * @return Value of property firstLine. 179 | */ 180 | public String getFirstLine() { 181 | return firstLine; 182 | } 183 | 184 | } 185 | -------------------------------------------------------------------------------- /src/httpserver/midpssh/HttpInputStream.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2006 Karl von Randow. 3 | * 4 | * --LICENSE NOTICE-- 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | * --LICENSE NOTICE-- 19 | * 20 | */ 21 | 22 | package midpssh; 23 | 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.io.PushbackInputStream; 27 | 28 | /** 29 | * 30 | * @author karl 31 | * @version 32 | */ 33 | public class HttpInputStream extends PushbackInputStream { 34 | 35 | public static final String CHARSET = "ISO-8859-1"; 36 | 37 | /** Creates new HttpInputStream */ 38 | public HttpInputStream(InputStream in) { 39 | super(in, 8192); 40 | } 41 | 42 | public void waitForData() throws IOException { 43 | int c = read(); 44 | unread(c); 45 | } 46 | 47 | /** 48 | * The String contains a line of text read from the stream, not including 49 | * the EOL character(s). The string is converted from bytes using ISO-8859-1 50 | * encoding - in the hope that ISO-8859-1 is 8-bit safe. That is, the bytes 51 | * can be converted to a String and back to bytes without changing the 52 | * bytes. 53 | * 54 | * @return 55 | * @throws IOException 56 | */ 57 | public String readLine() throws IOException { 58 | if (buf == null) { 59 | buf = new byte[128]; 60 | } 61 | 62 | int c = read(); 63 | if (c == -1) 64 | return null; 65 | int i = 0; 66 | while (c != -1) { 67 | if (c == '\r') { 68 | int d = read(); 69 | if (d == '\n') { 70 | break; 71 | } 72 | unread(d); 73 | break; 74 | } else if (c == '\n') { 75 | break; 76 | } 77 | 78 | addByteToBuffer(i++, c); 79 | c = read(); 80 | } 81 | return new String(buf, 0, i, CHARSET); 82 | } 83 | 84 | public String readLineInclusive() throws IOException { 85 | if (buf == null) { 86 | buf = new byte[128]; 87 | } 88 | 89 | int c = read(); 90 | if (c == -1) 91 | return null; 92 | int i = 0; 93 | while (c != -1) { 94 | // First put the byte in the buffer 95 | addByteToBuffer(i++, c); 96 | 97 | if (c == '\r') { 98 | int d = read(); 99 | if (d == '\n') { 100 | addByteToBuffer(i++, d); 101 | break; 102 | } 103 | unread(d); 104 | break; 105 | } else if (c == '\n') { 106 | break; 107 | } 108 | 109 | c = read(); 110 | } 111 | return new String(buf, 0, i, CHARSET); 112 | } 113 | 114 | public static String trimNewline(String line) { 115 | if (line.endsWith("\r\n")) { 116 | return line.substring(0, line.length() - 2); 117 | } else if (line.endsWith("\r") || line.endsWith("\n")) { 118 | return line.substring(0, line.length() - 1); 119 | } else { 120 | return line; 121 | } 122 | } 123 | 124 | private void addByteToBuffer(int i, int c) { 125 | if (i >= buf.length) { 126 | // Extend the buffer 127 | byte[] buf = new byte[this.buf.length + 128]; 128 | System.arraycopy(this.buf, 0, buf, 0, this.buf.length); 129 | this.buf = buf; 130 | } 131 | 132 | buf[i] = (byte) (c & 0xff); 133 | } 134 | 135 | public void unreadLine(String line) throws IOException { 136 | byte[] buf = line.getBytes(CHARSET); 137 | unread(buf); 138 | } 139 | 140 | private byte[] buf; 141 | } 142 | -------------------------------------------------------------------------------- /src/httpserver/midpssh/HttpOutputStream.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2006 Karl von Randow. 3 | * 4 | * --LICENSE NOTICE-- 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | * --LICENSE NOTICE-- 19 | * 20 | */ 21 | 22 | package midpssh; 23 | 24 | import java.io.FilterOutputStream; 25 | import java.io.IOException; 26 | import java.io.OutputStream; 27 | 28 | /** 29 | * 30 | * @author karl 31 | * @version 32 | */ 33 | public class HttpOutputStream extends FilterOutputStream { 34 | 35 | /** Creates new HttpOutputStream */ 36 | public HttpOutputStream(OutputStream out) { 37 | super(out); 38 | } 39 | 40 | public void write(String str) throws IOException { 41 | out.write(str.getBytes()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/httpserver/midpssh/ParseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)ParseException.java 0.3-3 06/05/2001 3 | * 4 | * This file is part of the HTTPClient package 5 | * Copyright (C) 1996-2001 Ronald Tschal�r 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free 19 | * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 | * MA 02111-1307, USA 21 | * 22 | * For questions, suggestions, bug-reports, enhancement-requests etc. 23 | * I may be contacted at: 24 | * 25 | * ronald@innovation.ch 26 | * 27 | * The HTTPClient's home page is located at: 28 | * 29 | * http://www.innovation.ch/java/HTTPClient/ 30 | * 31 | */ 32 | 33 | package midpssh; 34 | 35 | /** 36 | * Signals that something went wrong while parsing data. Usually means the input 37 | * data was invalid. 38 | * 39 | * @version 0.3-3 06/05/2001 40 | * @author Ronald Tschal�r 41 | */ 42 | public class ParseException extends Exception { 43 | 44 | /** 45 | * Constructs an ParseException with no detail message. A detail message is 46 | * a String that describes this particular exception. 47 | */ 48 | public ParseException() { 49 | super(); 50 | } 51 | 52 | /** 53 | * Constructs an ParseException class with the specified detail message. A 54 | * detail message is a String that describes this particular exception. 55 | * 56 | * @param s 57 | * the String containing a detail message 58 | */ 59 | public ParseException(String s) { 60 | super(s); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/httpserver/midpssh/Server.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2006 Karl von Randow. 3 | * 4 | * --LICENSE NOTICE-- 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | * --LICENSE NOTICE-- 19 | * 20 | */ 21 | 22 | package midpssh; 23 | 24 | import java.io.EOFException; 25 | import java.io.IOException; 26 | import java.io.InputStream; 27 | import java.io.OutputStream; 28 | import java.net.ServerSocket; 29 | import java.net.Socket; 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | import java.util.StringTokenizer; 33 | 34 | public class Server implements Runnable { 35 | 36 | private static final String HTTP_HEADERS = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-type: application/octet-stream\r\n"; 37 | 38 | private static final String CRLF = "\r\n"; 39 | 40 | private static Map current; 41 | 42 | private Socket clientSocket; 43 | 44 | private HttpInputStream in; 45 | 46 | private HttpOutputStream out; 47 | 48 | private Session session; 49 | 50 | private String key; 51 | 52 | private String host; 53 | 54 | private int port; 55 | 56 | /** 57 | * The application's main method. Starts listening on a socket and creates a new instance 58 | * of the Server class for each socket connection accepted. 59 | */ 60 | public static void main(String[] args) throws Exception { 61 | current = new HashMap(); 62 | 63 | int port = 8088; 64 | 65 | if (args.length > 0) { 66 | port = Integer.parseInt(args[0]); 67 | } 68 | 69 | System.out.println("Starting MidpSSH HTTP Proxy on port " + port); 70 | 71 | ServerSocket ss = new ServerSocket(port); 72 | 73 | while (true) { 74 | Socket s = ss.accept(); 75 | new Server(s); 76 | } 77 | } 78 | 79 | public Server(Socket socket) { 80 | this.clientSocket = socket; 81 | new Thread(this).start(); 82 | } 83 | 84 | /** 85 | * The main server loop. A new thread is created for each socket handled by the server. This 86 | * method handles that socket and exists until the socket is closed. 87 | */ 88 | public void run() { 89 | debug("Connection from " + clientSocket); 90 | try { 91 | in = new HttpInputStream(clientSocket.getInputStream()); 92 | out = new HttpOutputStream(clientSocket.getOutputStream()); 93 | 94 | // boolean keptAlive = false; 95 | while (true) { 96 | // if (keptAlive) { 97 | // System.out.println("trying a keep alive read"); 98 | // } 99 | HttpFields fields = new HttpFields(); 100 | fields.read(in); 101 | // if (keptAlive) { 102 | // System.out.println("kept alive!"); 103 | // } 104 | 105 | String firstLine = fields.getFirstLine(); 106 | if (firstLine != null) { 107 | StringTokenizer tok = new StringTokenizer(firstLine, " "); 108 | String method = tok.nextToken(); 109 | String path = tok.nextToken(); 110 | 111 | /* Determine the key that uniquely identifies the connection */ 112 | key = path; 113 | int i = key.indexOf('/', 1); 114 | host = key.substring(i + 1); 115 | 116 | i = host.indexOf(':'); 117 | port = Integer.parseInt(host.substring(i + 1)); 118 | host = host.substring(0, i); 119 | 120 | /* Look for that connection in our current list and use that if possible. Otherwise this 121 | * is a new connection. 122 | */ 123 | synchronized (current) { 124 | if (current.containsKey(key)) { 125 | session = (Session) current.get(key); 126 | session.setLastAccessed(System.currentTimeMillis()); 127 | } else { 128 | session = new Session(); 129 | current.put(key, session); 130 | } 131 | } 132 | 133 | synchronized (session) { 134 | if (!session.isConnected()) { 135 | session.connect(host, port); 136 | } 137 | } 138 | 139 | try { 140 | if (method.equalsIgnoreCase("POST")) { 141 | doClientOutbound(fields); 142 | } else { 143 | doClientInbound(fields); 144 | } 145 | } 146 | catch (IOException e) { 147 | /* Remove this connection from the current list */ 148 | current.remove(key); 149 | session.close(); 150 | throw e; 151 | } 152 | 153 | // keptAlive = true; 154 | break; 155 | } else { 156 | break; 157 | } 158 | } 159 | 160 | in.close(); 161 | out.close(); 162 | } catch (IOException e) { 163 | System.out.println(e); 164 | } 165 | 166 | try { 167 | clientSocket.close(); 168 | } catch (IOException e) { 169 | System.out.println(e); 170 | } 171 | } 172 | 173 | /** 174 | * Handle the outbound stream from MidpSSH. Can support chunked POST data, in which case MidpSSH may 175 | * be able to send all outbound data over a single chunked POST. Otherwise multiple and separate POSTs 176 | * are sent. 177 | * 178 | * We read all the data from the post and write it out to the destination server. 179 | * @param fields 180 | * @throws IOException 181 | */ 182 | public void doClientOutbound(HttpFields fields) throws IOException { 183 | OutputStream destout = session.getSocket().getOutputStream(); 184 | 185 | InputStream in = this.in; 186 | boolean chunking = fields.getField("Transfer-Encoding") != null && fields.getField("Transfer-Encoding").equalsIgnoreCase("chunked"); 187 | if (chunking) { 188 | in = new ChunkedInputStream(in); 189 | } else { 190 | int contentLength = fields.getIntField("Content-length"); 191 | in = new FiniteInputStream(in, contentLength); 192 | } 193 | 194 | byte[] buf = new byte[8192]; 195 | int read = in.read(buf); 196 | while (read != -1) { 197 | destout.write(buf, 0, read); 198 | destout.flush(); 199 | 200 | read = in.read(buf); 201 | } 202 | 203 | out.write(HTTP_HEADERS + CRLF); 204 | out.flush(); 205 | } 206 | 207 | /** 208 | * Handle the inbound stream to MidpSSH. Can support persistent connection to MidpSSH if the phone + network 209 | * can support it: the entire inbound stream is sent during one connection. Otherwise we send back what we have 210 | * and then close the connection. 211 | * @param fields 212 | * @throws IOException 213 | */ 214 | public void doClientInbound(HttpFields fields) throws IOException { 215 | InputStream destin = session.getSocket().getInputStream(); 216 | 217 | boolean persistent = fields.get("X-MidpSSH-Persistent") != null; 218 | boolean headers = false; 219 | 220 | byte[] buf = new byte[8192]; 221 | int read = destin.read(buf); 222 | while (read != -1) { 223 | if (!headers) { 224 | if (persistent) { 225 | out.write(HTTP_HEADERS + CRLF); 226 | } else { 227 | out.write(HTTP_HEADERS + "Content-length: " + read + CRLF + CRLF); 228 | } 229 | out.flush(); 230 | headers = true; 231 | } 232 | out.write(buf, 0, read); 233 | out.flush(); 234 | if (persistent) { 235 | read = destin.read(buf); 236 | } else { 237 | break; 238 | } 239 | } 240 | 241 | if (read == -1) { 242 | throw new EOFException("Remote server has closed connection"); 243 | } 244 | } 245 | 246 | // private String toHex(byte[] ray, int offset, int length) { 247 | // StringBuffer buf = new StringBuffer(); 248 | // for (int i = offset; i < offset + length; i++) { 249 | // buf.append("0x"); 250 | // buf.append(Integer.toHexString(ray[i])); 251 | // buf.append(' '); 252 | // } 253 | // buf.append('\n'); 254 | // buf.append(new String(ray, offset, length)); 255 | // return buf.toString(); 256 | // } 257 | 258 | private void debug(String message) { 259 | System.out.println(message); 260 | } 261 | 262 | } 263 | -------------------------------------------------------------------------------- /src/httpserver/midpssh/Session.java: -------------------------------------------------------------------------------- 1 | package midpssh; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | import java.net.UnknownHostException; 6 | 7 | public class Session { 8 | 9 | private Socket socket; 10 | 11 | private long lastAccessed; 12 | 13 | public Session() { 14 | lastAccessed = System.currentTimeMillis(); 15 | } 16 | 17 | public Socket getSocket() { 18 | return socket; 19 | } 20 | 21 | public void setSocket(Socket socket) { 22 | this.socket = socket; 23 | } 24 | 25 | public long getLastAccessed() { 26 | return lastAccessed; 27 | } 28 | 29 | public void setLastAccessed(long lastAccessed) { 30 | this.lastAccessed = lastAccessed; 31 | } 32 | 33 | public void close() throws IOException { 34 | socket.close(); 35 | } 36 | 37 | public void connect(String host, int port) throws UnknownHostException, IOException { 38 | socket = new Socket(host, port); 39 | } 40 | 41 | public boolean isConnected() { 42 | return socket != null; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/j2me/app/LineInputStream.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2005 Karl von Randow. 3 | * 4 | * --LICENSE NOTICE-- 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | * --LICENSE NOTICE-- 19 | * 20 | */ 21 | package app; 22 | 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | 26 | /** 27 | * @author Karl 28 | * 29 | */ 30 | public class LineInputStream extends InputStream { 31 | 32 | private static final int BUFSIZ = 8192; 33 | 34 | private InputStream in; 35 | 36 | private byte[] buf = new byte[BUFSIZ]; 37 | 38 | private int index = 0; 39 | 40 | public LineInputStream(InputStream in) { 41 | this.in = in; 42 | } 43 | 44 | public int read() throws IOException { 45 | return in.read(); 46 | } 47 | 48 | public void close() throws IOException { 49 | in.close(); 50 | } 51 | 52 | public String readLine() throws IOException { 53 | while (true) { 54 | /* Read into buffer */ 55 | int read; 56 | if (index < BUFSIZ) { 57 | read = in.read(buf, index, BUFSIZ - index); 58 | if (read > 0 ) { 59 | index += read; 60 | } 61 | } 62 | else { 63 | read = -1; 64 | } 65 | 66 | /* Look for EOL */ 67 | int eol = -1; 68 | int next = -1; 69 | 70 | for (int i = 0; i < index; i++) { 71 | if (buf[i] == '\r') { 72 | if (i + 1 < index && buf[i+1] == '\n') { 73 | eol = i; 74 | next = i + 2; 75 | } 76 | else { 77 | eol = i; 78 | next = i + 1; 79 | } 80 | break; 81 | } 82 | else if (buf[i] == '\n') { 83 | eol = i; 84 | next = i + 1; 85 | break; 86 | } 87 | } 88 | 89 | if (eol != -1) { 90 | String str = new String(buf, 0, eol); 91 | index = index - next; 92 | System.arraycopy(buf, next, buf, 0, index); 93 | return str; 94 | } 95 | else if (read == -1) { 96 | /* EOF */ 97 | if (index > 0) { 98 | String str = new String(buf, 0, index); 99 | index = 0; 100 | return str; 101 | } 102 | else { 103 | return null; 104 | } 105 | } 106 | } 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/j2me/app/Main.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | 24 | package app; 25 | 26 | import gui.MainMenu; 27 | 28 | import javax.microedition.midlet.MIDlet; 29 | 30 | public class Main extends MIDlet { 31 | 32 | public static Main instance; 33 | 34 | private static MainMenu mainMenu; 35 | 36 | private static boolean paused; 37 | 38 | /** Constructor */ 39 | public Main() { 40 | Main.instance = this; 41 | mainMenu = new MainMenu(); 42 | System.out.println("Test\n"); 43 | Settings.init(); 44 | } 45 | 46 | /** Main method */ 47 | protected void startApp() { 48 | if ( !paused ) { 49 | mainMenu.activate(); 50 | } 51 | paused = false; 52 | } 53 | 54 | /** Handle pausing the MIDlet */ 55 | protected void pauseApp() { 56 | paused = true; 57 | } 58 | 59 | /** Handle destroying the MIDlet */ 60 | protected void destroyApp( boolean unconditional ) { 61 | paused = false; 62 | } 63 | 64 | /** Quit the MIDlet */ 65 | public static void quitApp() { 66 | instance.destroyApp( true ); 67 | instance.notifyDestroyed(); 68 | instance = null; 69 | } 70 | 71 | public static void printStack(String msg, long pause) { 72 | msg += " (wait " + pause + "sec)"; 73 | try { 74 | throw new IllegalArgumentException(msg); 75 | } catch (IllegalArgumentException iae) { 76 | iae.printStackTrace(); 77 | } 78 | 79 | if (pause > 0) { 80 | try { 81 | Thread.sleep(pause * 1000); 82 | } 83 | catch(InterruptedException ie) { 84 | } 85 | } 86 | } 87 | 88 | /* 89 | public static void debug(String msg) { 90 | Alert alert = new Alert("DEBUG"); 91 | alert.setString(msg); 92 | alert.setTimeout(Alert.FOREVER); 93 | alert(alert, getDisplay().getCurrent()); 94 | } 95 | */ 96 | } -------------------------------------------------------------------------------- /src/j2me/app/MyRecordStore.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2005 Karl von Randow. 3 | * 4 | * --LICENSE NOTICE-- 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | * --LICENSE NOTICE-- 19 | * 20 | */ 21 | package app; 22 | 23 | import java.io.ByteArrayInputStream; 24 | import java.io.ByteArrayOutputStream; 25 | import java.io.DataInputStream; 26 | import java.io.DataOutputStream; 27 | import java.io.IOException; 28 | import java.util.Vector; 29 | 30 | import javax.microedition.rms.RecordEnumeration; 31 | import javax.microedition.rms.RecordStore; 32 | 33 | /** 34 | * @author Karl 35 | * 36 | */ 37 | public abstract class MyRecordStore { 38 | 39 | protected Vector load(String rmsName, boolean sort) { 40 | try { 41 | RecordStore rec = RecordStore.openRecordStore(rmsName, false); 42 | 43 | RecordEnumeration recs = rec.enumerateRecords(null, null, false); 44 | Vector vector = new Vector(); 45 | 46 | while (recs.hasNextElement()) { 47 | byte[] data = recs.nextRecord(); 48 | DataInputStream in = new DataInputStream(new ByteArrayInputStream(data)); 49 | try { 50 | vector.addElement(read(in)); 51 | } catch (IOException e) { 52 | 53 | } 54 | in.close(); 55 | } 56 | rec.closeRecordStore(); 57 | 58 | //#ifndef small 59 | if (sort) { 60 | insertSort(vector); 61 | } 62 | //#endif 63 | return vector; 64 | } catch (Exception e) { 65 | 66 | } 67 | return new Vector(); 68 | } 69 | 70 | protected void insertSort(Vector v) { 71 | int in, out; 72 | int n = v.size(); 73 | 74 | for (out = 1; out < n; out++) // out is dividing line 75 | { 76 | Object temp = v.elementAt(out); 77 | in = out; 78 | while (in > 0 && compare(v.elementAt(in - 1), temp) >= 0) { 79 | v.setElementAt(v.elementAt(in - 1), in); 80 | --in; 81 | } 82 | v.setElementAt(temp, in); 83 | } 84 | } 85 | 86 | protected int compare(Object a, Object b) { 87 | return 0; 88 | } 89 | 90 | protected void save(String rmsName, Vector vector) { 91 | if (vector != null) { 92 | try { 93 | try { 94 | RecordStore.deleteRecordStore(rmsName); 95 | } catch (Exception e) { 96 | 97 | } 98 | 99 | RecordStore rec = RecordStore.openRecordStore(rmsName, true); 100 | for (int i = 0; i < vector.size(); i++) { 101 | Object ob = vector.elementAt(i); 102 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 103 | DataOutputStream dout = new DataOutputStream(out); 104 | try { 105 | write(dout, ob); 106 | dout.close(); 107 | 108 | byte[] data = out.toByteArray(); 109 | rec.addRecord(data, 0, data.length); 110 | } catch (IOException e) { 111 | 112 | } 113 | } 114 | 115 | rec.closeRecordStore(); 116 | } catch (Exception e) { 117 | 118 | } 119 | } 120 | } 121 | 122 | protected abstract Object read(DataInputStream in) throws IOException; 123 | 124 | protected abstract void write(DataOutputStream out, Object ob) throws IOException; 125 | } 126 | -------------------------------------------------------------------------------- /src/j2me/app/SessionManager.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package app; 24 | 25 | import java.io.DataInputStream; 26 | import java.io.DataOutputStream; 27 | import java.io.EOFException; 28 | import java.io.IOException; 29 | import java.util.Vector; 30 | 31 | /** 32 | * @author Karl von Randow 33 | * 34 | */ 35 | public class SessionManager extends MyRecordStore { 36 | 37 | private static final String RMS_NAME = "sessions"; 38 | 39 | private static Vector sessions; 40 | 41 | private static SessionManager me = new SessionManager(); 42 | 43 | protected int compare(Object a, Object b) { 44 | return ((SessionSpec) a).alias.compareTo(((SessionSpec) b).alias); 45 | } 46 | 47 | public static Vector getSessions() { 48 | if ( sessions == null ) { 49 | SessionManager.sessions = me.load( RMS_NAME, true ); 50 | } 51 | return sessions; 52 | } 53 | 54 | private static void saveSessions() { 55 | me.save( RMS_NAME, sessions ); 56 | } 57 | 58 | /** 59 | * @param conn 60 | */ 61 | public static void addSession( SessionSpec conn ) { 62 | Vector connections = getSessions(); 63 | connections.addElement( conn ); 64 | saveSessions(); 65 | } 66 | 67 | /** 68 | * @param i 69 | * @return 70 | */ 71 | public static SessionSpec getSession( int i ) { 72 | Vector connections = getSessions(); 73 | return (i >= connections.size() ? null : (SessionSpec) connections.elementAt( i )); 74 | } 75 | 76 | /** 77 | * @param i 78 | */ 79 | public static void deleteSession( int i ) { 80 | Vector connections = getSessions(); 81 | if (i < connections.size()) { 82 | connections.removeElementAt( i ); 83 | saveSessions(); 84 | } 85 | } 86 | 87 | /** 88 | * @param connectionIndex 89 | * @param conn 90 | */ 91 | public static void replaceSession( int i, SessionSpec conn ) { 92 | Vector connections = getSessions(); 93 | if ( i >= connections.size() ) { 94 | connections.addElement( conn ); 95 | } 96 | else { 97 | connections.setElementAt( conn, i ); 98 | } 99 | saveSessions(); 100 | } 101 | /* (non-Javadoc) 102 | * @see app.MyRecordStore#read(java.io.DataInputStream) 103 | */ 104 | protected Object read(DataInputStream in) throws IOException { 105 | SessionSpec spec = new SessionSpec(); 106 | try { 107 | spec.read( in ); 108 | } 109 | catch (EOFException e) { 110 | /* ignore EOFExceptions as they result from us adding more fields to the end of the spec */ 111 | } 112 | return spec; 113 | } 114 | /* (non-Javadoc) 115 | * @see app.MyRecordStore#write(java.io.DataOutputStream, java.lang.Object) 116 | */ 117 | protected void write(DataOutputStream out, Object ob) throws IOException { 118 | SessionSpec spec = (SessionSpec) ob; 119 | spec.write( out ); 120 | } 121 | 122 | } -------------------------------------------------------------------------------- /src/j2me/app/SessionSpec.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package app; 24 | 25 | import java.io.DataInputStream; 26 | import java.io.DataOutputStream; 27 | import java.io.IOException; 28 | 29 | /** 30 | * @author Karl von Randow 31 | * 32 | */ 33 | public class SessionSpec { 34 | public static final String TYPE_SSH = "ssh"; 35 | 36 | public static final String TYPE_TELNET = "telnet"; 37 | 38 | public String alias, type, host, username, password; 39 | 40 | public boolean usepublickey; 41 | 42 | //#ifdef blackberryconntypes 43 | public static final int BLACKBERRY_CONN_TYPE_DEFAULT = 0; 44 | public static final int BLACKBERRY_CONN_TYPE_DEVICESIDE = 1; 45 | public static final int BLACKBERRY_CONN_TYPE_PROXY = 2; 46 | public static final int BLACKBERRY_CONN_TYPE_WIFI = 3; 47 | 48 | public int blackberryConnType; 49 | //#endif 50 | 51 | public void read( DataInputStream in ) throws IOException { 52 | alias = in.readUTF(); 53 | type = in.readUTF(); 54 | host = in.readUTF(); 55 | username = in.readUTF(); 56 | password = in.readUTF(); 57 | //#ifdef blackberryconntypes 58 | blackberryConnType = in.readInt(); 59 | //#endif 60 | usepublickey = in.readBoolean(); 61 | } 62 | 63 | public void write( DataOutputStream out ) throws IOException { 64 | out.writeUTF( alias ); 65 | out.writeUTF( type ); 66 | out.writeUTF( host ); 67 | out.writeUTF( username ); 68 | out.writeUTF( password ); 69 | //#ifdef blackberryconntypes 70 | out.writeInt(blackberryConnType); 71 | //#endif 72 | out.writeBoolean(usepublickey); 73 | } 74 | } -------------------------------------------------------------------------------- /src/j2me/app/Settings.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package app; 24 | 25 | import java.io.DataInputStream; 26 | import java.io.DataOutputStream; 27 | import java.io.IOException; 28 | import java.util.Vector; 29 | 30 | /** 31 | * @author Karl von Randow 32 | */ 33 | public class Settings extends MyRecordStore { 34 | 35 | public static final int DEFAULT_BGCOLOR = 0x000000, 36 | DEFAULT_FGCOLOR = 0xffffff; 37 | 38 | public static final int ROT_NORMAL = 0; 39 | 40 | public static final int ROT_270 = 1; 41 | 42 | public static final int ROT_90 = 2; 43 | 44 | public static final int FONT_NORMAL = 0; 45 | 46 | public static final int FONT_DEVICE = 1; 47 | 48 | private static final String RMS_NAME = "settings"; 49 | 50 | public static int bgcolor, fgcolor; 51 | 52 | public static int terminalCols, terminalRows; 53 | 54 | public static String terminalType; 55 | 56 | //#ifdef midp2 57 | public static int terminalRotated; 58 | //#endif 59 | 60 | public static int fontMode; 61 | 62 | //#ifndef nofonts 63 | //#ifdef midp2 64 | public static byte lcdFontMode; 65 | //#endif 66 | //#endif 67 | 68 | private static Settings me = new Settings(); 69 | 70 | //#ifdef midp2 71 | public static boolean terminalFullscreen; 72 | //#endif 73 | 74 | public static String sessionsImportUrl; 75 | 76 | //#ifdef ssh2 77 | public static int sshVersionPreferred; 78 | 79 | public static boolean ssh2StoreKey; 80 | 81 | public static byte[] ssh2x, ssh2y; 82 | 83 | public static byte[] x, y; 84 | 85 | public static int ssh2KeySize; 86 | //#endif 87 | 88 | public static boolean pollingIO; 89 | 90 | //#ifdef midp2 91 | public static boolean predictiveText; 92 | //#endif 93 | 94 | public static String httpProxy; 95 | 96 | public static int httpProxyMode; 97 | 98 | public static void print() {} 99 | 100 | public static void init() { 101 | defaults(); 102 | me.load(RMS_NAME, false); 103 | } 104 | 105 | /** 106 | * @param settings2 107 | */ 108 | public static void saveSettings() { 109 | Vector v = new Vector(); 110 | v.addElement(null); // doesn't matter what we pass through, it just 111 | // calls write() 112 | me.save(RMS_NAME, v); 113 | } 114 | 115 | public static void defaults() { 116 | bgcolor = DEFAULT_BGCOLOR; 117 | fgcolor = DEFAULT_FGCOLOR; 118 | terminalCols = 0; 119 | terminalRows = 0; 120 | terminalType = ""; 121 | //#ifdef midp2 122 | terminalRotated = ROT_NORMAL; 123 | //#endif 124 | fontMode = FONT_NORMAL; 125 | //#ifdef midp2 126 | terminalFullscreen = false; 127 | //#endif 128 | //#ifdef ssh2 129 | sshVersionPreferred = 1; 130 | //#endif 131 | sessionsImportUrl = "http://"; 132 | //#ifdef ssh2 133 | ssh2StoreKey = true; 134 | ssh2x = null; 135 | ssh2y = null; 136 | ssh2KeySize = 512; 137 | //#endif 138 | pollingIO = false; 139 | //#ifdef midp2 140 | predictiveText = true; 141 | //#endif 142 | //#ifdef ssh2 143 | x = null; 144 | y = null; 145 | //#endif 146 | //#ifndef nofonts 147 | //#ifdef midp2 148 | lcdFontMode = 0; 149 | //#endif 150 | //#endif 151 | httpProxy = ""; 152 | httpProxyMode = 0; 153 | } 154 | 155 | /* 156 | * (non-Javadoc) 157 | * 158 | * @see app.MyRecordStore#read(java.io.DataInputStream) 159 | */ 160 | protected Object read(DataInputStream in) throws IOException { 161 | fgcolor = in.readInt(); 162 | bgcolor = in.readInt(); 163 | terminalCols = in.readInt(); 164 | terminalRows = in.readInt(); 165 | terminalType = in.readUTF(); 166 | //#ifdef midp2 167 | terminalRotated = in.readInt(); 168 | //#endif 169 | fontMode = in.readInt(); 170 | //#ifdef midp2 171 | terminalFullscreen = in.readBoolean(); 172 | //#endif 173 | //#ifdef ssh2 174 | sshVersionPreferred = in.readInt(); 175 | //#endif 176 | sessionsImportUrl = in.readUTF(); 177 | //#ifdef ssh2 178 | ssh2StoreKey = in.readBoolean(); 179 | ssh2x = readByteArray(in); 180 | ssh2y = readByteArray(in); 181 | ssh2KeySize = in.readInt(); 182 | //#endif 183 | pollingIO = in.readBoolean(); 184 | //#ifdef midp2 185 | predictiveText = in.readBoolean(); 186 | //#endif 187 | //#ifdef ssh2 188 | x = readByteArray(in); 189 | y = readByteArray(in); 190 | //#endif 191 | //#ifndef nofonts 192 | //#ifdef midp2 193 | lcdFontMode = in.readByte(); 194 | //#endif 195 | //#endif 196 | httpProxy = in.readUTF(); 197 | httpProxyMode = in.readByte(); 198 | return null; 199 | } 200 | 201 | /* 202 | * (non-Javadoc) 203 | * 204 | * @see app.MyRecordStore#write(java.io.DataOutputStream, java.lang.Object) 205 | */ 206 | protected void write(DataOutputStream out, Object ob) throws IOException { 207 | out.writeInt(fgcolor); 208 | out.writeInt(bgcolor); 209 | out.writeInt(terminalCols); 210 | out.writeInt(terminalRows); 211 | out.writeUTF(terminalType); 212 | //#ifdef midp2 213 | out.writeInt(terminalRotated); 214 | //#endif 215 | out.writeInt(fontMode); 216 | //#ifdef midp2 217 | out.writeBoolean(terminalFullscreen); 218 | //#endif 219 | //#ifdef ssh2 220 | out.writeInt(sshVersionPreferred); 221 | //#endif 222 | out.writeUTF(sessionsImportUrl); 223 | //#ifdef ssh2 224 | out.writeBoolean(ssh2StoreKey); 225 | writeByteArray(out, ssh2x); 226 | writeByteArray(out, ssh2y); 227 | out.writeInt(ssh2KeySize); 228 | //#endif 229 | out.writeBoolean(pollingIO); 230 | //#ifdef midp2 231 | out.writeBoolean(predictiveText); 232 | //#endif 233 | //#ifdef ssh2 234 | writeByteArray(out, x); 235 | writeByteArray(out, y); 236 | //#endif 237 | //#ifndef nofonts 238 | //#ifdef midp2 239 | out.writeByte(lcdFontMode); 240 | //#endif 241 | //#endif 242 | out.writeUTF(httpProxy); 243 | out.writeByte(httpProxyMode); 244 | } 245 | 246 | //#ifdef ssh2 247 | private byte[] readByteArray(DataInputStream in) throws IOException { 248 | int length = in.readInt(); 249 | if (length == 0) { 250 | return null; 251 | } else { 252 | byte[] buf = new byte[length]; 253 | in.readFully(buf); 254 | return buf; 255 | } 256 | } 257 | 258 | private void writeByteArray(DataOutputStream out, byte[] ray) 259 | throws IOException { 260 | if (ray != null) { 261 | out.writeInt(ray.length); 262 | out.write(ray); 263 | } else { 264 | out.writeInt(0); 265 | } 266 | } 267 | //#endif 268 | } 269 | -------------------------------------------------------------------------------- /src/j2me/app/session/HttpInboundStream.java: -------------------------------------------------------------------------------- 1 | package app.session; 2 | 3 | import java.io.EOFException; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | import javax.microedition.io.Connector; 8 | import javax.microedition.io.HttpConnection; 9 | 10 | public class HttpInboundStream extends InputStream { 11 | 12 | private String url; 13 | 14 | private byte[] buf; 15 | 16 | private int offset, length; 17 | 18 | public HttpInboundStream(String url) { 19 | this.url = url; 20 | this.buf = new byte[10240]; 21 | this.offset = 0; 22 | this.length = 0; 23 | } 24 | 25 | public int read() throws IOException { 26 | if (length - offset <= 0) { 27 | fillBuffer(); 28 | } 29 | 30 | if (length - offset <= 0) { 31 | return -1; 32 | } 33 | 34 | return buf[offset++]; 35 | } 36 | 37 | public int read(byte[] destbuf, int destoffset, int destlength) throws IOException { 38 | if (length - offset <= 0) { 39 | fillBuffer(); 40 | } 41 | 42 | if (length - offset <= 0) { 43 | throw new EOFException(); 44 | } 45 | 46 | int readlength = Math.min(length - offset, destlength - destoffset); 47 | System.arraycopy(buf, offset, destbuf, destoffset, readlength); 48 | offset += readlength; 49 | return readlength; 50 | } 51 | 52 | public int read(byte[] buf) throws IOException { 53 | return read(buf, 0, buf.length); 54 | } 55 | 56 | private void fillBuffer() throws IOException { 57 | /* Note that we assume that the server will never send responses larger than our buffer size. If the server 58 | * does we'll probably go into an infinite loop. 59 | */ 60 | HttpConnection conn = (HttpConnection) Connector.open(url, Connector.READ_WRITE, false); 61 | InputStream in = conn.openInputStream(); 62 | int offset = 0; 63 | int read = in.read(buf, offset, buf.length - offset); 64 | while (read != -1) { 65 | offset += read; 66 | read = in.read(buf, offset, buf.length - offset); 67 | } 68 | 69 | length = offset; 70 | this.offset = 0; 71 | in.close(); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/j2me/app/session/HttpOutboundStream.java: -------------------------------------------------------------------------------- 1 | package app.session; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.OutputStream; 6 | 7 | import javax.microedition.io.Connector; 8 | import javax.microedition.io.HttpConnection; 9 | 10 | public class HttpOutboundStream extends ByteArrayOutputStream { 11 | 12 | private String url; 13 | 14 | public HttpOutboundStream(String url) { 15 | this.url = url; 16 | } 17 | 18 | public synchronized void close() throws IOException { 19 | flush(); 20 | super.close(); 21 | } 22 | 23 | public void flush() throws IOException { 24 | super.flush(); 25 | 26 | HttpConnection outbound = (HttpConnection) Connector.open(url, Connector.READ_WRITE, false); 27 | outbound.setRequestMethod(HttpConnection.POST); 28 | OutputStream out = outbound.openOutputStream(); 29 | out.write(toByteArray()); 30 | out.close(); 31 | outbound.openInputStream().close(); 32 | 33 | reset(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/j2me/app/session/ISshSession.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ISshSession.java 3 | * 4 | * Copyright (c) 2010 VDP . 5 | * 6 | * This file is part of MidpSSH. 7 | * 8 | * MidpSSH is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * MidpSSH is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with MidpSSH. If not, see . 20 | */ 21 | 22 | package app.session; 23 | 24 | import java.io.IOException; 25 | 26 | /** 27 | * 28 | * @author VDP 29 | */ 30 | public interface ISshSession { 31 | public void sendData( byte [] data ) throws IOException; 32 | public void prompt(String name, String instruction, 33 | String[] prompts, boolean[] echos) throws IOException; 34 | public String getTerminalID(); 35 | public int getTerminalHeight(); 36 | public int getTerminalWidth(); 37 | } 38 | -------------------------------------------------------------------------------- /src/j2me/app/session/MacroSetManager.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package app.session; 24 | 25 | import gui.session.macros.MacroSet; 26 | 27 | import java.io.DataInputStream; 28 | import java.io.DataOutputStream; 29 | import java.io.IOException; 30 | import java.util.Vector; 31 | 32 | import app.MyRecordStore; 33 | 34 | /** 35 | * @author Karl von Randow 36 | * 37 | */ 38 | public class MacroSetManager extends MyRecordStore { 39 | 40 | private static final String RMS_NAME = "macros"; 41 | 42 | private static Vector macroSets; 43 | 44 | private static MacroSetManager me = new MacroSetManager(); 45 | 46 | protected int compare(Object a, Object b) { 47 | MacroSet aa = (MacroSet) a; 48 | MacroSet bb = (MacroSet) b; 49 | return aa.name.compareTo(bb.name); 50 | } 51 | 52 | public static Vector getMacroSets() { 53 | if ( macroSets == null ) { 54 | MacroSetManager.macroSets = me.load( RMS_NAME, true ); 55 | if ( macroSets.isEmpty() ) { 56 | MacroSet macroSet = new MacroSet(); 57 | macroSet.name = "Untitled Set"; 58 | macroSets.addElement( macroSet ); 59 | saveMacroSets(); 60 | } 61 | } 62 | return macroSets; 63 | } 64 | 65 | public static void saveMacroSets() { 66 | me.save( RMS_NAME, macroSets ); 67 | } 68 | 69 | /** 70 | * @param i 71 | * @return 72 | */ 73 | public static MacroSet getMacroSet( int i ) { 74 | Vector macroSets = getMacroSets(); 75 | return ( macroSets == null || i >= macroSets.size() ? null : (MacroSet) macroSets.elementAt( i )); 76 | } 77 | 78 | /** 79 | * @param conn 80 | */ 81 | public static void addMacroSet( MacroSet macroSet ) { 82 | Vector macroSets = getMacroSets(); 83 | macroSets.addElement( macroSet ); 84 | saveMacroSets(); 85 | } 86 | 87 | /** 88 | * @param i 89 | */ 90 | public static void deleteMacroSet( int i ) { 91 | Vector macroSets = getMacroSets(); 92 | if (i < macroSets.size() ) { 93 | macroSets.removeElementAt( i ); 94 | saveMacroSets(); 95 | } 96 | } 97 | 98 | /** 99 | * @param connectionIndex 100 | * @param conn 101 | */ 102 | public static void replaceMacroSet( int i, MacroSet macroSet ) { 103 | Vector macroSets = getMacroSets(); 104 | if ( i >= macroSets.size() ) { 105 | macroSets.addElement( macroSet ); 106 | } 107 | else { 108 | macroSets.setElementAt( macroSet, i ); 109 | } 110 | saveMacroSets(); 111 | } 112 | /* (non-Javadoc) 113 | * @see app.MyRecordStore#read(java.io.DataInputStream) 114 | */ 115 | protected Object read(DataInputStream in) throws IOException { 116 | MacroSet macroSet = new MacroSet(); 117 | macroSet.read( in ); 118 | return macroSet; 119 | } 120 | /* (non-Javadoc) 121 | * @see app.MyRecordStore#write(java.io.DataOutputStream, java.lang.Object) 122 | */ 123 | protected void write(DataOutputStream out, Object ob) throws IOException { 124 | MacroSet macroSet = (MacroSet) ob; 125 | macroSet.write( out ); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/j2me/app/session/SessionIOHandler.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package app.session; 24 | 25 | import java.io.IOException; 26 | 27 | /** 28 | * @author Karl von Randow 29 | * 30 | */ 31 | public interface SessionIOHandler { 32 | public void handleSendData( byte[] data, int offset, int length ) throws IOException; 33 | 34 | public void handleReceiveData( byte[] data, int offset, int length ) throws IOException; 35 | } -------------------------------------------------------------------------------- /src/j2me/app/session/SshSession.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package app.session; 24 | 25 | import gui.MainMenu; 26 | 27 | import java.io.IOException; 28 | 29 | import javax.microedition.lcdui.Command; 30 | import javax.microedition.lcdui.CommandListener; 31 | import javax.microedition.lcdui.Displayable; 32 | import javax.microedition.lcdui.Form; 33 | import javax.microedition.lcdui.StringItem; 34 | import javax.microedition.lcdui.TextField; 35 | 36 | import ssh.SshIO; 37 | import app.SessionSpec; 38 | import app.Settings; 39 | 40 | /** 41 | * @author Karl von Randow 42 | * 43 | */ 44 | public class SshSession extends Session 45 | implements SessionIOHandler, ISshSession 46 | //#ifdef keybrdinteractive 47 | , CommandListener 48 | //#endif 49 | { 50 | 51 | 52 | private SshIO sshIO; 53 | 54 | public void connect(SessionSpec spec, String username, String password) { 55 | sshIO = new SshIO( this ); 56 | sshIO.login = username != null ? username : spec.username; 57 | sshIO.password = password != null ? password : spec.password; 58 | sshIO.usepublickey = spec.usepublickey; 59 | super.connect( spec, this ); 60 | } 61 | 62 | /* 63 | * (non-Javadoc) 64 | * 65 | * @see telnet.Session#defaultPort() 66 | */ 67 | protected int defaultPort() { 68 | return 22; 69 | } 70 | /* 71 | * (non-Javadoc) 72 | * 73 | * @see app.session.SessionIOListener#receiveData(byte[], int, int) 74 | */ 75 | public void handleReceiveData( byte[] data, int offset, int length ) throws IOException { 76 | byte[] result; 77 | result = sshIO.handleSSH( data, offset, length ); 78 | super.receiveData( result, 0, result.length ); 79 | } 80 | 81 | /* 82 | * (non-Javadoc) 83 | * 84 | * @see app.session.SessionIOListener#sendData(byte[], int, int) 85 | */ 86 | public void handleSendData( byte[] data, int offset, int length ) throws IOException { 87 | if ( length > 0 ) { 88 | sshIO.sendData( data, offset, length ); 89 | } 90 | else { 91 | sshIO.Send_SSH_NOOP(); 92 | } 93 | } 94 | 95 | /* 96 | * Receive data send back by SshIO and send it out onto the network 97 | */ 98 | public void sendData( byte [] data ) throws IOException { 99 | super.sendData( data, 0, data.length ); 100 | } 101 | 102 | public String getTerminalID() { 103 | if ( Settings.terminalType.length() > 0 ) { 104 | return Settings.terminalType; 105 | } 106 | else { 107 | return emulation.getTerminalID(); 108 | } 109 | } 110 | 111 | public int getTerminalWidth() { 112 | return emulation.width; 113 | } 114 | 115 | public int getTerminalHeight() { 116 | return emulation.height; 117 | } 118 | 119 | //#ifdef keybrdinteractive 120 | public void prompt(String name, String instruction, String[] prompts, boolean[] echos) throws IOException { 121 | if (prompts.length > 0) { 122 | /* Show prompt */ 123 | if (name.length() == 0) { 124 | name = "Authenticate"; 125 | } 126 | Form form = new Form(name); 127 | 128 | if (instruction.length() > 0) { 129 | form.append(new StringItem("Instructions", instruction)); 130 | } 131 | promptFields = new TextField[prompts.length]; 132 | for (int i = 0; i < prompts.length; i++) { 133 | promptFields[i] = new TextField(prompts[i], "", 255, TextField.ANY | (echos[i] ? 0 : TextField.PASSWORD)); 134 | if (prompts[i].toLowerCase().startsWith("password:")) { 135 | promptFields[i].setString(sshIO.password); 136 | } 137 | form.append(promptFields[i]); 138 | } 139 | form.addCommand(MainMenu.okCommand); 140 | form.addCommand(MainMenu.backCommand); 141 | form.setCommandListener(this); 142 | MainMenu.setDisplay(form); 143 | } 144 | else { 145 | sshIO.sendUserauthInfoResponse(new String[0]); 146 | } 147 | } 148 | 149 | private TextField[] promptFields; 150 | 151 | public void commandAction(Command cmd, Displayable displayable) { 152 | try { 153 | if (cmd == MainMenu.okCommand) { 154 | String[] responses = new String[promptFields.length]; 155 | for (int i = 0; i < responses.length; i++) { 156 | responses[i] = promptFields[i].getString(); 157 | } 158 | sshIO.sendUserauthInfoResponse(responses); 159 | } 160 | else { 161 | sshIO.sendUserauthInfoResponse(new String[0]); 162 | } 163 | } 164 | catch (IOException e) { 165 | 166 | } 167 | 168 | promptFields = null; 169 | activate(); 170 | } 171 | //#endif 172 | } -------------------------------------------------------------------------------- /src/j2me/app/session/TelnetSession.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package app.session; 24 | 25 | import java.io.IOException; 26 | 27 | import telnet.Dimension; 28 | import telnet.TelnetProtocolHandler; 29 | import app.SessionSpec; 30 | import app.Settings; 31 | 32 | /** 33 | * @author Karl von Randow 34 | * 35 | */ 36 | public class TelnetSession extends Session implements SessionIOHandler { 37 | public TelnetSession() { 38 | super(); 39 | 40 | // Default to true in telnet and then turn off when told to 41 | emulation.setLocalEcho( true ); 42 | } 43 | 44 | public void connect( SessionSpec spec ) { 45 | telnet = new TelnetProtocolHandler() { 46 | /** get the current terminal type */ 47 | public String getTerminalType() { 48 | if ( Settings.terminalType.length() > 0 ) { 49 | return Settings.terminalType; 50 | } 51 | else { 52 | return emulation.getTerminalID(); 53 | } 54 | } 55 | 56 | /** get the current window size */ 57 | public Dimension getWindowSize() { 58 | return new Dimension( emulation.width, emulation.height ); 59 | } 60 | 61 | /** notify about local echo */ 62 | public void setLocalEcho( boolean echo ) { 63 | emulation.localecho = echo; 64 | } 65 | 66 | /** notify about EOR end of record */ 67 | public void notifyEndOfRecord() { 68 | // only used when EOR needed, like for line mode 69 | } 70 | 71 | /** write data to our back end */ 72 | public void write( byte[] b ) throws IOException { 73 | /*for ( int i = 0; i < b.length; i++ ) { 74 | System.out.println( "SEND " + b[i] + "=" + (char) b[i] ); 75 | }*/ 76 | TelnetSession.this.sendData( b, 0, b.length ); 77 | } 78 | }; 79 | 80 | super.connect( spec, this ); 81 | } 82 | 83 | /* 84 | * (non-Javadoc) 85 | * 86 | * @see telnet.Session#defaultPort() 87 | */ 88 | protected int defaultPort() { 89 | return 23; 90 | } 91 | 92 | private TelnetProtocolHandler telnet; 93 | 94 | /* 95 | * (non-Javadoc) 96 | * 97 | * @see terminal.TerminalIOListener#receiveData(byte[]) 98 | */ 99 | public void handleReceiveData( byte[] data, int offset, int length ) throws IOException { 100 | telnet.inputfeed( data, offset, length ); 101 | int n; 102 | do { 103 | n = telnet.negotiate( data, offset, length ); 104 | if ( n > 0 ) { 105 | /*for ( int i = offset; i < offset + n; i++ ) { 106 | System.out.println( "RECV " + data[i] + "=" + (char) data[i] ); 107 | }*/ 108 | TelnetSession.this.receiveData( data, offset, n ); 109 | } 110 | } 111 | while ( n != -1 ); 112 | } 113 | 114 | /* 115 | * (non-Javadoc) 116 | * 117 | * @see terminal.TerminalIOListener#sendData(byte[]) 118 | */ 119 | public void handleSendData( byte[] data, int offset, int length ) throws IOException { 120 | if ( length > 0 ) { 121 | telnet.transpose( data, offset, length ); 122 | } 123 | else { 124 | telnet.sendTelnetNOP(); 125 | } 126 | } 127 | } -------------------------------------------------------------------------------- /src/j2me/awt/AwtMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * AwtMain.java 3 | * 4 | * Copyright (c) 2010 VDP . 5 | * 6 | * This file is part of MidpSSH. 7 | * 8 | * MidpSSH is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * MidpSSH is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with MidpSSH. If not, see . 20 | */ 21 | 22 | package awt; 23 | 24 | import java.awt.BorderLayout; 25 | import java.awt.Button; 26 | import java.awt.Dimension; 27 | import java.awt.Frame; 28 | import java.awt.Panel; 29 | import java.awt.event.WindowAdapter; 30 | import java.awt.event.WindowEvent; 31 | import kindle.RemoteKbdReceiver; 32 | import org.apache.log4j.Logger; 33 | import org.apache.log4j.PropertyConfigurator; 34 | import terminal.VT320; 35 | 36 | /** 37 | * AWT interface on top of MidpSSH infrastructure 38 | * 39 | * @author VDP 40 | */ 41 | public class AwtMain { 42 | 43 | private Frame root; 44 | private AwtSshSession session; 45 | private Logger log; 46 | 47 | private void configLog() { 48 | PropertyConfigurator.configure("conf/log4j.properties"); 49 | } 50 | 51 | public AwtMain(String title) { 52 | configLog(); 53 | this.log = Logger.getLogger(AwtMain.class.getName()); 54 | log.debug("Log started"); 55 | //System.out.println("Work dir:" + System.getProperty("user.dir")); 56 | root = new Frame(title); 57 | root.setSize(800, 600); 58 | root.addWindowListener( 59 | new WindowAdapter() { 60 | public void windowClosing(WindowEvent e) { 61 | System.exit(0); 62 | } 63 | } 64 | ); 65 | Panel panel = new Panel(); 66 | Button b1 = new Button("Does nothing"); 67 | panel.add(b1); 68 | //root.add(panel, BorderLayout.NORTH); 69 | //Settings.defaults(); 70 | this.session = new AwtSshSession(); 71 | AwtTerminal term = new AwtTerminal(session.getEmulation(), session); 72 | 73 | RemoteKbdReceiver rk = new RemoteKbdReceiver(3333, term, term); 74 | rk.start(); 75 | 76 | root.add(term, BorderLayout.CENTER); 77 | session.connect("localhost", 22, "user", "pass"); 78 | //System.out.print("Connect ...\n"); 79 | term.setFocusable(true); 80 | term.setFocusTraversalKeysEnabled(false); 81 | term.setPreferredSize(new Dimension(1200, 950)); 82 | 83 | root.pack(); 84 | root.setVisible(true); 85 | //printTerminal(session.getTerminal().buffer); 86 | } 87 | 88 | public void printTerminal(VT320 buf) { 89 | for (int i = 0; i < buf.charArray.length; i++){ 90 | String line = new String(buf.charArray[i]); 91 | System.out.println(line + "\n"); 92 | } 93 | 94 | } 95 | 96 | public static void main(String[] args) { 97 | AwtMain am = new AwtMain("Test"); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/j2me/awt/AwtSshSession.java: -------------------------------------------------------------------------------- 1 | /* 2 | * AwtSshSession.java 3 | * 4 | * Copyright (c) 2010 VDP . 5 | * 6 | * This file is part of MidpSSH. 7 | * 8 | * MidpSSH is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * MidpSSH is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with MidpSSH. If not, see . 20 | */ 21 | 22 | package awt; 23 | 24 | import app.session.ISshSession; 25 | import app.session.SessionIOHandler; 26 | import java.io.IOException; 27 | import ssh.SshIO; 28 | 29 | /** 30 | * 31 | * @author VDP 32 | */ 33 | public class AwtSshSession extends AwtSession 34 | implements SessionIOHandler, ISshSession { 35 | 36 | private SshIO sshIO; 37 | 38 | public void connect(String host, int port, 39 | String username, String password) { 40 | sshIO = new SshIO(this); 41 | sshIO.login = username; 42 | sshIO.password = password; 43 | //sshIO.usepublickey = spec.usepublickey; 44 | super.connect(host, port, username, password, this); 45 | } 46 | 47 | /* 48 | * (non-Javadoc) 49 | * 50 | * @see telnet.Session#defaultPort() 51 | */ 52 | protected int defaultPort() { 53 | return 22; 54 | } 55 | /* 56 | * (non-Javadoc) 57 | * 58 | * @see app.session.SessionIOListener#receiveData(byte[], int, int) 59 | */ 60 | public void handleReceiveData( byte[] data, int offset, int length ) throws IOException { 61 | byte[] result; 62 | //System.out.println("Handle received data: " + new String(data) + "\n"); 63 | result = sshIO.handleSSH( data, offset, length ); 64 | super.receiveData( result, 0, result.length ); 65 | } 66 | 67 | /* 68 | * (non-Javadoc) 69 | * 70 | * @see app.session.SessionIOListener#sendData(byte[], int, int) 71 | */ 72 | public void handleSendData( byte[] data, int offset, int length ) throws IOException { 73 | if ( length > 0 ) { 74 | sshIO.sendData( data, offset, length ); 75 | } 76 | else { 77 | sshIO.Send_SSH_NOOP(); 78 | } 79 | } 80 | 81 | /* 82 | * Receive data send back by SshIO and send it out onto the network 83 | */ 84 | public void sendData( byte [] data ) throws IOException { 85 | super.sendData( data, 0, data.length ); 86 | } 87 | 88 | public String getTerminalID() { 89 | return emulation.getTerminalID(); 90 | } 91 | 92 | public int getTerminalWidth() { 93 | return emulation.width; 94 | } 95 | 96 | public int getTerminalHeight() { 97 | return emulation.height; 98 | } 99 | 100 | public void prompt(String name, String instruction, String[] prompts, boolean[] echos) throws IOException { 101 | System.out.println("PROMPT"); 102 | throw new UnsupportedOperationException("AWT SSH Session prompt()"); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/j2me/gui/Activatable.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package gui; 24 | 25 | 26 | /** 27 | * @author Karl von Randow 28 | * 29 | */ 30 | public interface Activatable { 31 | 32 | public void activate(); 33 | 34 | public void activate( Activatable back ); 35 | } -------------------------------------------------------------------------------- /src/j2me/gui/EditableForm.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package gui; 24 | 25 | import javax.microedition.lcdui.Command; 26 | import javax.microedition.lcdui.CommandListener; 27 | import javax.microedition.lcdui.Displayable; 28 | import javax.microedition.lcdui.Form; 29 | 30 | /** 31 | * @author Karl von Randow 32 | */ 33 | public abstract class EditableForm extends Form implements CommandListener, Activatable { 34 | 35 | private Activatable back; 36 | 37 | public EditableForm( String title ) { 38 | super( title ); 39 | 40 | addCommand( MainMenu.backCommand ); 41 | setCommandListener( this ); 42 | } 43 | 44 | /* 45 | * (non-Javadoc) 46 | * 47 | * @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, 48 | * javax.microedition.lcdui.Displayable) 49 | */ 50 | public void commandAction( Command command, Displayable displayed ) { 51 | if ( command == MainMenu.backCommand ) { 52 | doBack(); 53 | } else if (command == MainMenu.okCommand) { 54 | doOK(); 55 | } 56 | } 57 | 58 | protected void addOKCommand() { 59 | addCommand(MainMenu.okCommand); 60 | } 61 | 62 | protected void doBack() { 63 | back.activate(); 64 | } 65 | 66 | protected void doOK() { 67 | back.activate(); 68 | } 69 | 70 | /* (non-Javadoc) 71 | * @see gui.Activatable#activate() 72 | */ 73 | public void activate() { 74 | MainMenu.setDisplay( this ); 75 | } 76 | /* (non-Javadoc) 77 | * @see gui.Activatable#activate(gui.Activatable) 78 | */ 79 | public void activate( Activatable back ) { 80 | this.back = back; 81 | activate(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/j2me/gui/EditableMenu.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package gui; 24 | 25 | import javax.microedition.lcdui.Command; 26 | import javax.microedition.lcdui.CommandListener; 27 | import javax.microedition.lcdui.Displayable; 28 | import javax.microedition.lcdui.List; 29 | 30 | /** 31 | * @author Karl von Randow 32 | * 33 | */ 34 | public abstract class EditableMenu extends List implements CommandListener, Activatable { 35 | 36 | protected static Command newCommand = new Command( "New", Command.SCREEN, 8 ); 37 | 38 | protected static Command editCommand = new Command( "Edit", Command.ITEM, 9 ); 39 | 40 | protected static Command deleteCommand = new Command( "Delete", Command.ITEM, 10 ); 41 | 42 | protected Command selectCommand = List.SELECT_COMMAND; 43 | 44 | private Activatable back; 45 | 46 | public EditableMenu( String title ) { 47 | super( title, List.IMPLICIT ); 48 | 49 | //addCommand( selectCommand ); 50 | addCommand( newCommand ); 51 | addCommand( editCommand ); 52 | addCommand( deleteCommand ); 53 | addCommand( MainMenu.backCommand ); 54 | 55 | setCommandListener( this ); 56 | } 57 | 58 | protected void replaceSelectCommand( Command selectCommand ) { 59 | //removeCommand( this.selectCommand ); 60 | this.selectCommand = selectCommand; 61 | 62 | //#ifdef midp2 63 | super.setSelectCommand( selectCommand ); 64 | //#else 65 | //#ifndef blackberry 66 | // On the blackberry we don't require the command to be added as the implicit command is also listed in 67 | // the menu. 68 | addCommand( selectCommand ); 69 | //#endif 70 | //#endif 71 | } 72 | 73 | //#ifndef midp2 74 | public void deleteAll() { 75 | while ( size() > 0 ) { 76 | delete(0); 77 | } 78 | } 79 | //#endif 80 | 81 | protected abstract void addItems(); 82 | 83 | /* (non-Javadoc) 84 | * @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, javax.microedition.lcdui.Displayable) 85 | */ 86 | public void commandAction( Command command, Displayable displayable ) { 87 | if ( command == List.SELECT_COMMAND || command == selectCommand ) { 88 | int i = getSelectedIndex(); 89 | if ( i >= 0 && i < size() ) { 90 | doSelect( getSelectedIndex() ); 91 | } 92 | } 93 | else if ( command == newCommand ) { 94 | doNew(); 95 | } 96 | else if ( command == editCommand ) { 97 | int i = getSelectedIndex(); 98 | if ( i >= 0 && i < size() ) { 99 | doEdit( i ); 100 | } 101 | } 102 | else if ( command == deleteCommand ) { 103 | int i = getSelectedIndex(); 104 | if ( i >= 0 && i < size() ) { 105 | doDelete( i ); 106 | } 107 | } 108 | else if ( command == MainMenu.backCommand ) { 109 | doBack(); 110 | } 111 | } 112 | 113 | /* (non-Javadoc) 114 | * @see app.Activatable#activate() 115 | */ 116 | public void activate() { 117 | addItems(); 118 | MainMenu.setDisplay( this ); 119 | } 120 | 121 | public void activate( Activatable back ) { 122 | this.back = back; 123 | activate(); 124 | } 125 | 126 | protected abstract void doSelect( int i ); 127 | 128 | protected abstract void doEdit( int i ); 129 | 130 | protected abstract void doDelete( int i ); 131 | 132 | protected abstract void doNew(); 133 | 134 | protected void doBack() { 135 | back.activate(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/j2me/gui/MainMenu.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package gui; 24 | 25 | import gui.session.macros.MacrosMenu; 26 | import gui.settings.SettingsMenu; 27 | 28 | import javax.microedition.lcdui.Alert; 29 | import javax.microedition.lcdui.AlertType; 30 | import javax.microedition.lcdui.Command; 31 | import javax.microedition.lcdui.CommandListener; 32 | import javax.microedition.lcdui.Display; 33 | import javax.microedition.lcdui.Displayable; 34 | import javax.microedition.lcdui.Form; 35 | import javax.microedition.lcdui.List; 36 | import javax.microedition.lcdui.StringItem; 37 | 38 | import app.Main; 39 | import app.session.Session; 40 | 41 | /** 42 | * @author Karl von Randow 43 | */ 44 | public class MainMenu extends List implements CommandListener, Activatable { 45 | 46 | public static final Command okCommand = new Command( "OK", Command.OK, 1 ); 47 | 48 | public static final Command backCommand = new Command( "Back", Command.BACK, 99 ); 49 | 50 | private static Command quitCommand = new Command( "Quit", Command.EXIT, 2 ); 51 | 52 | private static MainMenu instance; 53 | 54 | public static boolean useColors; 55 | 56 | private static Session currentSession; 57 | 58 | private SessionsMenu sessionsMenu; 59 | 60 | //#ifndef nomacros 61 | private static MacrosMenu macrosMenu; 62 | //#endif 63 | private static Activatable settingsMenu; 64 | 65 | private static final String ITEM_SESSIONS = "Sessions"; 66 | //#ifndef nomacros 67 | private static final String ITEM_MACROS = "Macros"; 68 | //#endif 69 | //#ifndef nosettings 70 | private static final String ITEM_SETTINGS = "Settings"; 71 | //#endif 72 | //#ifndef nodocs 73 | private static final String ITEM_ABOUT = "About MidpSSH"; 74 | private static final String ITEM_HELP = "Help"; 75 | //#endif 76 | private static final String ITEM_QUIT = "Quit"; 77 | 78 | /** 79 | * @param arg0 80 | * @param arg1 81 | */ 82 | public MainMenu() { 83 | super( "MidpSSH", List.IMPLICIT ); 84 | 85 | MainMenu.instance = this; 86 | 87 | useColors = getDisplay().isColor(); 88 | 89 | append( ITEM_SESSIONS, null ); 90 | //#ifndef nomacros 91 | append( ITEM_MACROS, null ); 92 | //#endif 93 | //#ifndef nosettings 94 | append( ITEM_SETTINGS, null ); 95 | //#endif 96 | //#ifndef nodocs 97 | append( ITEM_ABOUT, null ); 98 | append( ITEM_HELP, null ); 99 | //#endif 100 | append( ITEM_QUIT, null ); 101 | 102 | //setSelectCommand( selectCommand ); 103 | addCommand( quitCommand ); 104 | 105 | setCommandListener( this ); 106 | } 107 | 108 | /* 109 | * (non-Javadoc) 110 | * 111 | * @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, 112 | * javax.microedition.lcdui.Displayable) 113 | */ 114 | public void commandAction( Command com, Displayable displayable ) { 115 | if ( com == List.SELECT_COMMAND /*|| com == selectCommand*/ ) { 116 | String command = getString( getSelectedIndex() ); 117 | if ( command.equals( ITEM_SESSIONS ) ) { 118 | doSessions(); 119 | } 120 | //#ifndef nomacros 121 | else if ( command.equals( ITEM_MACROS ) ) { 122 | doMacros( this ); 123 | } 124 | //#endif 125 | //#ifndef nosettings 126 | else if ( command.equals( ITEM_SETTINGS ) ) { 127 | doSettings(); 128 | } 129 | //#endif 130 | //#ifndef nodocs 131 | else if ( command.equals( ITEM_ABOUT ) ) { 132 | doAbout(); 133 | } 134 | else if ( command.equals( ITEM_HELP ) ) { 135 | doHelp(); 136 | } 137 | //#endif 138 | else if ( command.equals( ITEM_QUIT ) ) { 139 | Main.quitApp(); 140 | } 141 | } 142 | else if (com == okCommand) { 143 | goMainMenu(); 144 | } 145 | else if ( com == quitCommand ) { 146 | Main.quitApp(); 147 | } 148 | } 149 | 150 | private void doSessions() { 151 | if ( sessionsMenu == null ) { 152 | sessionsMenu = new SessionsMenu(); 153 | } 154 | sessionsMenu.activate( this ); 155 | } 156 | 157 | //#ifndef nomacros 158 | public static void doMacros( Activatable back ) { 159 | if ( macrosMenu == null ) { 160 | macrosMenu = new MacrosMenu(); 161 | } 162 | macrosMenu.activate( back ); 163 | } 164 | //#endif 165 | 166 | //#ifndef nosettings 167 | private void doSettings() { 168 | if ( settingsMenu == null ) { 169 | settingsMenu = new SettingsMenu(); 170 | } 171 | settingsMenu.activate( this ); 172 | } 173 | //#endif 174 | 175 | public static Form showMessage(String title, String msg, CommandListener commandListener) { 176 | Form form = new Form(title); 177 | form.append( new StringItem( null, msg ) ); 178 | form.addCommand(okCommand); 179 | form.setCommandListener(commandListener); 180 | setDisplay(form); 181 | return form; 182 | } 183 | 184 | private void doAbout() { 185 | showMessage( "About MidpSSH", 186 | "Version @VERSION@\n\n" + 187 | "MidpSSH is a Telnet and SSH application for Java compatible phones and other mobile devices.\n\n" + 188 | "Please visit the project website for more information:\n" + 189 | "http://www.xk72.com/midpssh/\n\n" + 190 | "MidpSSH is developed by Karl von Randow. MidpSSH is based upon " + 191 | "FloydSSH and Telnet Floyd by Radek Polak.\n\n" + 192 | "MidpSSH is distributed under the GPL licence. For more information please " + 193 | "visit the website.", 194 | this); 195 | } 196 | 197 | private void doHelp() { 198 | showMessage( "MidpSSH Help", 199 | "Connecting\n\n" + 200 | "To connect to a remote server choose the Sessions option " + 201 | "from the main menu - create a new session, entering in the host and other details. " + 202 | "You can then connect to that server by choosing the new session.\n\n" + 203 | 204 | "More Information\n\n" + 205 | "For more information please visit the project website http://www.xk72.com/midpssh/", 206 | this); 207 | } 208 | 209 | /* (non-Javadoc) 210 | * @see app.Activatable#activate() 211 | */ 212 | public void activate() { 213 | setDisplay( this ); 214 | } 215 | /* (non-Javadoc) 216 | * @see gui.Activatable#activate(gui.Activatable) 217 | */ 218 | public void activate( Activatable back ) { 219 | activate(); 220 | } 221 | 222 | public static void setDisplay( Displayable display ) { 223 | getDisplay().setCurrent( display ); 224 | } 225 | 226 | public static void alert( Alert alert, Displayable back ) { 227 | getDisplay().setCurrent( alert, back ); 228 | } 229 | 230 | public static Display getDisplay() { 231 | return Display.getDisplay(Main.instance); 232 | } 233 | 234 | public static void goMainMenu() { 235 | setDisplay(instance); 236 | } 237 | 238 | public static void alertBackToMain( Alert alert ) { 239 | getDisplay().setCurrent(alert, instance); 240 | } 241 | 242 | public static void openSession( Session session ) { 243 | currentSession = session; 244 | session.activate(); 245 | } 246 | 247 | public static Session currentSession() { 248 | return currentSession; 249 | } 250 | 251 | public static void showErrorMessage( String errorMessage ) { 252 | Alert alert = new Alert( "Error" ); 253 | alert.setString( errorMessage ); 254 | alert.setType( AlertType.ERROR ); 255 | MainMenu.setDisplay( alert ); 256 | } 257 | } -------------------------------------------------------------------------------- /src/j2me/gui/Redrawable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Redrawable.java 3 | * 4 | * Copyright (c) 2010 VDP . 5 | * 6 | * This file is part of MidpSSH. 7 | * 8 | * MidpSSH is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * MidpSSH is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with MidpSSH. If not, see . 20 | */ 21 | 22 | package gui; 23 | 24 | import terminal.VT320; 25 | 26 | /** 27 | * A common interface to be implemented by all classes 28 | * that are used as terminals within the {@link terminal.VT320}. 29 | * 30 | * @author VDP 31 | */ 32 | public interface Redrawable { 33 | 34 | /** 35 | * Invoked when screen refresh is needed 36 | */ 37 | public void redraw(); 38 | } 39 | -------------------------------------------------------------------------------- /src/j2me/gui/SessionsMenu.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package gui; 24 | 25 | import app.Main; 26 | import java.util.Vector; 27 | 28 | //import java.util.logging.Level; 29 | //import java.util.logging.Logger; 30 | import javax.microedition.lcdui.Command; 31 | import javax.microedition.lcdui.Displayable; 32 | import javax.microedition.lcdui.Form; 33 | import javax.microedition.lcdui.TextField; 34 | 35 | import app.SessionManager; 36 | import app.SessionSpec; 37 | import app.session.SshSession; 38 | import app.session.TelnetSession; 39 | 40 | /** 41 | * @author Karl von Randow 42 | * 43 | */ 44 | public class SessionsMenu extends EditableMenu { 45 | 46 | private static Command connectCommand = new Command( "Connect", Command.ITEM, 1 ); 47 | 48 | private static SessionForm newConnectionForm = new SessionForm( false ); 49 | 50 | private static SessionForm editConnectionForm = new SessionForm( true ); 51 | 52 | //#ifndef nosessionimport 53 | private static Command importCommand = new Command("Import", Command.SCREEN, 20); 54 | 55 | private ImportSessionsForm importSessionsForm; 56 | //#endif 57 | 58 | private Form authenticationDialog; 59 | 60 | private TextField usernameField, passwordField; 61 | 62 | private SessionSpec conn; 63 | 64 | public SessionsMenu() { 65 | super( "Sessions" ); 66 | replaceSelectCommand( connectCommand ); 67 | 68 | //#ifndef nosessionimport 69 | addCommand(importCommand); 70 | //#endif 71 | } 72 | 73 | public void commandAction(Command command, Displayable displayable) { 74 | if (displayable == authenticationDialog) { 75 | if (command == MainMenu.okCommand) { 76 | SshSession session = new SshSession(); 77 | session.connect(conn, usernameField.getString(), passwordField.getString()); 78 | Main.quitApp(); 79 | System.out.print("After session.connect()\n"); 80 | try { 81 | Thread.sleep(20000); 82 | } catch (InterruptedException ex) { 83 | //Logger.getLogger(SessionsMenu.class.getName()).log(Level.SEVERE, null, ex); 84 | } 85 | MainMenu.openSession( session ); 86 | } 87 | else { 88 | activate(); 89 | } 90 | } 91 | else { 92 | //#ifndef nosessionimport 93 | if (command == importCommand) { 94 | /* Import */ 95 | if (importSessionsForm == null) { 96 | importSessionsForm = new ImportSessionsForm(); 97 | } 98 | importSessionsForm.activate(this); 99 | } 100 | else 101 | //#endif 102 | { 103 | System.out.println("Tadaa\n"); 104 | super.commandAction(command, displayable); 105 | } 106 | } 107 | } 108 | 109 | 110 | protected void addItems() { 111 | deleteAll(); 112 | 113 | Vector connections = SessionManager.getSessions(); 114 | if ( connections != null ) { 115 | for ( int i = 0; i < connections.size(); i++ ) { 116 | SessionSpec conn = (SessionSpec) connections.elementAt( i ); 117 | append( conn.alias, null ); 118 | } 119 | } 120 | } 121 | 122 | protected void doSelect(int i) { 123 | if (i != -1) { 124 | conn = SessionManager.getSession(i); 125 | if (conn != null) { 126 | //#ifndef nossh 127 | if (conn.type.equals(SessionSpec.TYPE_SSH)) { 128 | String username = conn.username; 129 | String password = conn.password; 130 | 131 | if (username.length() == 0 || (password.length() == 0 && !conn.usepublickey)) { 132 | authenticationDialog = new Form("Authentication"); 133 | usernameField = new TextField("Username:", username, 255, TextField.ANY); 134 | authenticationDialog.append(usernameField); 135 | if (!conn.usepublickey) { 136 | passwordField = new TextField("Password:", password, 255, TextField.PASSWORD); 137 | authenticationDialog.append(passwordField); 138 | } 139 | authenticationDialog.addCommand(MainMenu.okCommand); 140 | authenticationDialog.addCommand(MainMenu.backCommand); 141 | authenticationDialog.setCommandListener(this); 142 | MainMenu.setDisplay(authenticationDialog); 143 | } else { 144 | SshSession session = new SshSession(); 145 | session.connect(conn, null, null); 146 | Main.printStack("After session.connect(conn, null, null)", 0); 147 | MainMenu.openSession(session); 148 | } 149 | } 150 | //#endif 151 | //#ifndef notelnet 152 | if (conn.type.equals(SessionSpec.TYPE_TELNET)) { 153 | TelnetSession session = new TelnetSession(); 154 | session.connect(conn); 155 | MainMenu.openSession(session); 156 | } 157 | //#endif 158 | } 159 | } 160 | } 161 | 162 | protected void doEdit( int i ) { 163 | if ( i != -1 ) { 164 | editConnectionForm.setConnectionIndex( i ); 165 | editConnectionForm.activate( this ); 166 | } 167 | } 168 | 169 | protected void doDelete( int i ) { 170 | if ( i != -1 ) { 171 | SessionManager.deleteSession( i ); 172 | delete( i ); 173 | } 174 | } 175 | 176 | protected void doNew() { 177 | newConnectionForm.activate( this ); 178 | } 179 | } -------------------------------------------------------------------------------- /src/j2me/gui/session/SpecialMenu.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2005 Karl von Randow. 3 | * 4 | * --LICENSE NOTICE-- 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | * --LICENSE NOTICE-- 19 | * 20 | */ 21 | package gui.session; 22 | 23 | import gui.Activatable; 24 | import gui.MainMenu; 25 | 26 | import javax.microedition.lcdui.Command; 27 | import javax.microedition.lcdui.CommandListener; 28 | import javax.microedition.lcdui.Displayable; 29 | import javax.microedition.lcdui.List; 30 | 31 | import ssh.v2.PublicKeyAuthentication; 32 | import terminal.VT320; 33 | import app.Settings; 34 | import app.session.Session; 35 | 36 | /** 37 | * @author Karl 38 | * 39 | */ 40 | public class SpecialMenu extends List implements CommandListener, Activatable { 41 | 42 | private Activatable back, done; 43 | 44 | private int index; 45 | 46 | /** 47 | * @param title 48 | * @param mode 49 | */ 50 | public SpecialMenu() { 51 | this( "Special", 0 ); 52 | } 53 | 54 | public SpecialMenu( String title, int index ) { 55 | super(title, List.IMPLICIT); 56 | 57 | //setSelectCommand( selectCommand ); 58 | addCommand( MainMenu.backCommand ); 59 | setCommandListener( this ); 60 | 61 | String options; 62 | this.index = index; 63 | switch (index) { 64 | case 0: 65 | options = "Keys|Funcs|Symbols|Output|"; 66 | break; 67 | case 1: 68 | options = "Bksp|Home|End|PgU|PgD|Del|Ins|"; 69 | break; 70 | case 2: 71 | options = "F1|F2|F3|F4|F5|F6|F7|F8|F9|F10|F11|F12|"; 72 | break; 73 | case 3: 74 | options = "||\\|~|:|;|'|\"|,|<|.|>|/|?|`|!|@|#|$|%|^|&|*|(|)|-|_|+|=|[|{|]|}|"; 75 | break; 76 | default: 77 | //#ifdef ssh2 78 | options = "Public Key|"; 79 | //#else 80 | options = ""; 81 | //#endif 82 | } 83 | 84 | int start = 0; 85 | int i = options.indexOf('|', 1); 86 | while (i != -1) { 87 | append(options.substring(start, i), null); 88 | start = i + 1; 89 | i = options.indexOf('|', start + 1); // +1 to that we see tokens that are single | 90 | } 91 | } 92 | 93 | public void commandAction( Command command, Displayable displayed ) { 94 | if ( command == List.SELECT_COMMAND ) { 95 | Session session = MainMenu.currentSession(); 96 | if ( session != null ) { 97 | int selectedIndex = getSelectedIndex(); 98 | String option = null; 99 | int keyCode = 0; 100 | if (index == 0) { 101 | new SpecialMenu(getString(selectedIndex), selectedIndex + 1).activate(this, done); 102 | } 103 | else if (index == 1) { 104 | switch (selectedIndex) { 105 | case 0: 106 | keyCode = VT320.VK_BACK_SPACE; 107 | break; 108 | case 1: 109 | keyCode = VT320.VK_HOME; 110 | break; 111 | case 2: 112 | keyCode = VT320.VK_END; 113 | break; 114 | case 3: 115 | keyCode = VT320.VK_PAGE_UP; 116 | break; 117 | case 4: 118 | keyCode = VT320.VK_PAGE_DOWN; 119 | break; 120 | case 5: 121 | keyCode = VT320.VK_DELETE; 122 | break; 123 | case 6: 124 | keyCode = VT320.VK_INSERT; 125 | break; 126 | } 127 | } 128 | else if (index == 2) { 129 | keyCode = VT320.VK_F1 + selectedIndex; 130 | } 131 | else if (index == 3) { 132 | option = getString(selectedIndex); 133 | } 134 | else if (index == 4) { 135 | //#ifdef ssh2 136 | if (Settings.x != null) { 137 | PublicKeyAuthentication pk = new PublicKeyAuthentication(); 138 | option = pk.getPublicKeyText(); 139 | } 140 | else { 141 | option = ""; 142 | } 143 | //#endif 144 | } 145 | 146 | if (keyCode != 0) { 147 | session.typeKey(keyCode, 0); 148 | done.activate(); 149 | } 150 | else if (option != null) { 151 | session.typeString(option); 152 | done.activate(); 153 | } 154 | } 155 | } 156 | else if ( command == MainMenu.backCommand ) { 157 | if ( back != null ) { 158 | back.activate(); 159 | } 160 | } 161 | } 162 | 163 | public void activate() { 164 | MainMenu.setDisplay( this ); 165 | } 166 | public void activate(Activatable back) { 167 | activate( back, back ); 168 | } 169 | public void activate(Activatable back, Activatable done) { 170 | this.back = back; 171 | this.done = done; 172 | activate(); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/j2me/gui/session/macros/MacroForm.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package gui.session.macros; 24 | 25 | import gui.EditableForm; 26 | import gui.MainMenu; 27 | import gui.SessionForm; 28 | 29 | import javax.microedition.lcdui.ChoiceGroup; 30 | import javax.microedition.lcdui.TextField; 31 | 32 | import app.Settings; 33 | import app.session.MacroSetManager; 34 | 35 | 36 | /** 37 | * @author Karl von Randow 38 | * 39 | */ 40 | public class MacroForm extends EditableForm { 41 | 42 | public static final int MODE_MACRO_SET = 1; 43 | public static final int MODE_MACRO = 2; 44 | 45 | private int macroSetIndex, macroIndex; 46 | 47 | private boolean edit; 48 | 49 | private TextField tfName, tfValue; 50 | 51 | private ChoiceGroup cgType; 52 | 53 | private boolean isMacroSet; 54 | 55 | /** 56 | * @param arg0 57 | */ 58 | public MacroForm( boolean edit, boolean isMacroSet ) { 59 | super( ( !isMacroSet ? ( edit ? "Edit Macro" : "New Macro" ) : 60 | ( edit ? "Edit Macro Set" : "New Macro Set" ) ) ); 61 | 62 | this.isMacroSet = isMacroSet; 63 | 64 | if ( isMacroSet ) { 65 | tfName = new TextField( "Macro Set Name:", null, 255, TextField.ANY ); 66 | append( tfName ); 67 | } 68 | else { 69 | tfValue = new TextField( "Value:", null, 255, TextField.ANY ); 70 | //#ifdef midp2 71 | if (!Settings.predictiveText) { 72 | tfValue.setConstraints(TextField.ANY | TextField.NON_PREDICTIVE); 73 | } 74 | //#endif 75 | 76 | tfName = new TextField( "Name (Optional):", null, 255, TextField.ANY ); 77 | cgType = new ChoiceGroup( "Mode", ChoiceGroup.EXCLUSIVE 78 | //#ifdef midp2 79 | * 0 + ChoiceGroup.POPUP 80 | //#endif 81 | ); 82 | cgType.append( "Enter", null ); 83 | cgType.append( "Type", null ); 84 | 85 | append( tfName ); 86 | append( tfValue ); 87 | append( cgType ); 88 | } 89 | 90 | if (!edit) { 91 | addOKCommand(); 92 | } 93 | this.edit = edit; 94 | } 95 | 96 | protected void doBack() { 97 | if (edit) { 98 | if (doSave(false)) { 99 | super.doBack(); 100 | } 101 | } else { 102 | super.doBack(); 103 | } 104 | } 105 | 106 | protected void doOK() { 107 | if (doSave(true)) { 108 | super.doOK(); 109 | } 110 | } 111 | 112 | /* (non-Javadoc) 113 | * @see gui.Activatable#activate() 114 | */ 115 | public void activate() { 116 | if ( !edit ) { 117 | tfName.setString( "" ); 118 | if ( tfValue != null ) { 119 | tfValue.setString( "" ); 120 | } 121 | } 122 | super.activate(); 123 | } 124 | 125 | /** 126 | * @param macroSetIndex The macroSetIndex to set. 127 | */ 128 | public void setMacroSetIndex( int macroSetIndex ) { 129 | this.macroSetIndex = macroSetIndex; 130 | 131 | if ( isMacroSet ) { 132 | MacroSet macroSet = MacroSetManager.getMacroSet( macroSetIndex ); 133 | if ( macroSet != null ) { 134 | tfName.setString( macroSet.name ); 135 | } 136 | } 137 | } 138 | 139 | public void setMacroIndices( int macroSetIndex, int macroIndex ) { 140 | this.macroSetIndex = macroSetIndex; 141 | this.macroIndex = macroIndex; 142 | 143 | MacroSet macroSet = MacroSetManager.getMacroSet( macroSetIndex ); 144 | MacroSet macro = macroSet.getMacro( macroIndex ); 145 | tfName.setString( macro.name ); 146 | 147 | String value = macro.value; 148 | if ( value.endsWith( "\n" ) ) { 149 | cgType.setSelectedIndex( 0, true ); 150 | value = value.substring( 0, value.length() - 1 ); 151 | } 152 | else { 153 | cgType.setSelectedIndex( 1, true ); 154 | } 155 | tfValue.setString( value ); 156 | } 157 | 158 | private boolean doSave(boolean create) { 159 | if (create || macroSetIndex != -1 ) { 160 | if ( validateForm() ) { 161 | if ( isMacroSet ) { 162 | MacroSet macroSet = create ? new MacroSet() : MacroSetManager.getMacroSet( macroSetIndex ); 163 | macroSet.name = tfName.getString(); 164 | if (create) { 165 | MacroSetManager.addMacroSet( macroSet ); 166 | } 167 | else { 168 | MacroSetManager.replaceMacroSet( macroSetIndex, macroSet ); 169 | } 170 | } 171 | else { 172 | MacroSet macroSet = MacroSetManager.getMacroSet( macroSetIndex ); 173 | String value = tfValue.getString(); 174 | if ( cgType.getSelectedIndex() == 0 ) { 175 | value += "\n"; 176 | } 177 | MacroSet macro = new MacroSet( tfName.getString(), value ); 178 | if (create) { 179 | macroSet.addMacro( macro ); 180 | } 181 | else { 182 | macroSet.replaceMacro( macroIndex, macro ); 183 | } 184 | } 185 | return true; 186 | } 187 | } 188 | return false; 189 | } 190 | 191 | protected boolean validateForm() { 192 | if ((isMacroSet && tfName.getString().length() == 0) 193 | || (!isMacroSet && tfValue.getString().length() == 0)) { 194 | MainMenu.showErrorMessage(SessionForm.WARNING_REQUIRED); 195 | return false; 196 | } 197 | else { 198 | return true; 199 | } 200 | } 201 | } -------------------------------------------------------------------------------- /src/j2me/gui/session/macros/MacroSet.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package gui.session.macros; 24 | 25 | import java.io.DataInputStream; 26 | import java.io.DataOutputStream; 27 | import java.io.IOException; 28 | import java.util.Vector; 29 | 30 | import app.session.MacroSetManager; 31 | 32 | /** 33 | * @author Karl von Randow 34 | * 35 | */ 36 | public class MacroSet { 37 | 38 | private static final byte VERSION = 1; 39 | 40 | public String name, value; 41 | 42 | public Vector macros; 43 | 44 | public MacroSet() { 45 | macros = new Vector(); 46 | } 47 | 48 | public MacroSet(String name, String value) { 49 | this.name = name; 50 | this.value = value; 51 | } 52 | 53 | /** 54 | * @param in 55 | * @throws IOException 56 | */ 57 | public void read( DataInputStream in ) throws IOException { 58 | in.readByte(); // a version byte, for future use 59 | name = in.readUTF(); 60 | 61 | int n = in.readByte(); 62 | for ( int i = 0; i < n; i++ ) { 63 | String name = in.readUTF(); 64 | String value = in.readUTF(); 65 | 66 | MacroSet macro = new MacroSet( name, value ); 67 | macros.addElement( macro ); 68 | } 69 | } 70 | /** 71 | * @param dout 72 | * @throws IOException 73 | */ 74 | public void write( DataOutputStream out ) throws IOException { 75 | out.writeByte( VERSION ); 76 | out.writeUTF( name ); 77 | 78 | out.writeByte( macros.size() ); 79 | for ( int i = 0; i < macros.size(); i++ ) { 80 | MacroSet macro = (MacroSet) macros.elementAt( i ); 81 | out.writeUTF( macro.name ); 82 | out.writeUTF( macro.value ); 83 | } 84 | } 85 | 86 | public MacroSet getMacro( int i ) { 87 | return ( i >= macros.size() ? null : (MacroSet) macros.elementAt( i )); 88 | } 89 | 90 | public void addMacro( MacroSet macro ) { 91 | macros.addElement( macro ); 92 | MacroSetManager.saveMacroSets(); 93 | } 94 | 95 | public void deleteMacro( int i ) { 96 | if ( i < macros.size() ) { 97 | macros.removeElementAt( i ); 98 | MacroSetManager.saveMacroSets(); 99 | } 100 | } 101 | 102 | public void replaceMacro( int i, MacroSet macro ) { 103 | if ( i >= macros.size() ) { 104 | macros.addElement( macro ); 105 | } 106 | else { 107 | macros.setElementAt( macro, i ); 108 | } 109 | MacroSetManager.saveMacroSets(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/j2me/gui/session/macros/MacrosMenu.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package gui.session.macros; 24 | 25 | import gui.EditableMenu; 26 | import gui.MainMenu; 27 | 28 | import java.util.Vector; 29 | 30 | import javax.microedition.lcdui.Command; 31 | import javax.microedition.lcdui.Displayable; 32 | 33 | import terminal.VT320; 34 | import app.session.MacroSetManager; 35 | import app.session.Session; 36 | 37 | /** 38 | * @author Karl von Randow 39 | * 40 | */ 41 | public class MacrosMenu extends EditableMenu { 42 | 43 | protected static final Command useCommand = new Command( "Use", Command.ITEM, 1 ); 44 | 45 | private MacroSet macroSet; 46 | 47 | private int macroSetIndex; 48 | 49 | private boolean isMacroSets; 50 | 51 | public MacrosMenu() { 52 | super( "Macro Sets" ); 53 | isMacroSets = true; 54 | } 55 | 56 | public MacrosMenu( MacroSet macroSet, int macroSetIndex ) { 57 | super( macroSet.name ); 58 | isMacroSets = false; 59 | this.macroSet = macroSet; 60 | this.macroSetIndex = macroSetIndex; 61 | 62 | if ( MainMenu.currentSession() != null ) { 63 | addCommand( useCommand ); 64 | } 65 | } 66 | 67 | /* (non-Javadoc) 68 | * @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, javax.microedition.lcdui.Displayable) 69 | */ 70 | public void commandAction(Command command, Displayable displayable) { 71 | if ( command == useCommand ) { 72 | int i = getSelectedIndex(); 73 | if ( i >= 0 && i < size() ) { 74 | Session session = MainMenu.currentSession(); 75 | if ( session != null ) { 76 | MacroSet macro = macroSet.getMacro( i ); 77 | if ( macro != null ) { 78 | session.getTerminal().doTextInput(macro.value.trim()); 79 | } 80 | } 81 | else { 82 | doEdit( i ); 83 | } 84 | } 85 | } 86 | else { 87 | super.commandAction(command, displayable); 88 | } 89 | } 90 | /* (non-Javadoc) 91 | * @see gui.EditableMenu#addItems() 92 | */ 93 | protected void addItems() { 94 | deleteAll(); 95 | 96 | if ( isMacroSets ) { 97 | Vector macroSets = MacroSetManager.getMacroSets(); 98 | for ( int i = 0; i < macroSets.size(); i++ ) { 99 | MacroSet macroSet = (MacroSet) macroSets.elementAt( i ); 100 | append( macroSet.name, null ); 101 | } 102 | } 103 | else { 104 | Vector macros = macroSet.macros; 105 | for ( int i = 0; i < macros.size(); i++ ) { 106 | MacroSet macro = (MacroSet) macros.elementAt( i ); 107 | String name = macro.name; 108 | if (name.length() == 0) { 109 | name = macro.value.trim(); // trim off whitespace as it may end with a newline 110 | } 111 | append( name, null ); 112 | } 113 | } 114 | } 115 | /* (non-Javadoc) 116 | * @see gui.EditableMenu#doDelete(int) 117 | */ 118 | protected void doDelete( int i ) { 119 | if ( i != -1 ) { 120 | if ( isMacroSets ) { 121 | MacroSetManager.deleteMacroSet( i ); 122 | } 123 | else { 124 | macroSet.deleteMacro( i ); 125 | } 126 | delete( i ); 127 | } 128 | } 129 | /* (non-Javadoc) 130 | * @see gui.EditableMenu#doSelect(int) 131 | */ 132 | protected void doSelect( int i ) { 133 | if ( i != -1 ) { 134 | if ( isMacroSets ) { 135 | MacroSet macroSet = MacroSetManager.getMacroSet( i ); 136 | MacrosMenu macrosMenu = new MacrosMenu( macroSet, i ); 137 | macrosMenu.activate( this ); 138 | } 139 | else { 140 | Session session = MainMenu.currentSession(); 141 | if ( session != null ) { 142 | MacroSet macro = macroSet.getMacro( i ); 143 | if ( macro != null ) { 144 | doMacro(session, macro); 145 | session.activate(); 146 | } 147 | } 148 | else { 149 | doEdit( i ); 150 | } 151 | } 152 | } 153 | } 154 | 155 | private static final char MACRO_CTRL = '^'; 156 | 157 | private static final char MACRO_BACKSLASH = '\\'; 158 | 159 | private int indexOfCommand(String value, int start) { 160 | int n = value.length(); 161 | for (int i = start; i < n; i++) { 162 | char c = value.charAt(i); 163 | if (c == MACRO_CTRL || c == MACRO_BACKSLASH) { 164 | return i; 165 | } 166 | } 167 | return -1; 168 | } 169 | 170 | private void doMacro(Session session, MacroSet macro) { 171 | String value = macro.value; 172 | 173 | int start = 0; 174 | int i = indexOfCommand(value, 0); 175 | while (i != -1) { 176 | if (i + 1 < value.length()) { 177 | if (i > start) { 178 | /* Output text before the control char */ 179 | session.typeString(value.substring(start, i)); 180 | } 181 | char com = value.charAt(i); 182 | char arg = value.charAt(i+1); 183 | if (arg == com) { 184 | /* An escaped command char */ 185 | session.typeString(value.substring(i, i + 2)); 186 | } 187 | else if (com == MACRO_CTRL) { 188 | /* Type control char */ 189 | session.typeChar(arg, VT320.KEY_CONTROL); 190 | } 191 | else if (com == MACRO_BACKSLASH) { 192 | if (arg == 'n') { 193 | session.typeChar('\n', 0); 194 | } 195 | else if (arg == 'r') { 196 | session.typeChar('\r', 0); 197 | } 198 | else if (arg == 't') { 199 | session.typeChar('\t', 0); 200 | } 201 | else if (arg == 'e') { 202 | session.typeChar((char)27, 0); 203 | } 204 | else { 205 | session.typeString(value.substring(i, i + 2)); 206 | } 207 | } 208 | start = i + 2; 209 | } 210 | else { 211 | start = i + 1; 212 | } 213 | i = indexOfCommand(value, start); 214 | } 215 | 216 | if (start < value.length()) { 217 | session.typeString(value.substring(start)); 218 | } 219 | } 220 | 221 | protected void doEdit( int i ) { 222 | if ( i != -1 ) { 223 | MacroForm editMacroForm = new MacroForm( true, isMacroSets ); 224 | if ( isMacroSets ) { 225 | editMacroForm.setMacroSetIndex( i ); 226 | } 227 | else { 228 | editMacroForm.setMacroIndices( macroSetIndex, i ); 229 | } 230 | editMacroForm.activate( this ); 231 | } 232 | } 233 | 234 | protected void doNew() { 235 | MacroForm newMacroForm = new MacroForm( false, isMacroSets ); 236 | if ( !isMacroSets ) { 237 | newMacroForm.setMacroSetIndex( macroSetIndex ); 238 | } 239 | newMacroForm.activate( this ); 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /src/j2me/gui/settings/SettingsMenu.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 2 10 | * of the License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * --LICENSE NOTICE-- 21 | * 22 | */ 23 | package gui.settings; 24 | 25 | import gui.Activatable; 26 | import gui.MainMenu; 27 | 28 | import javax.microedition.lcdui.Command; 29 | import javax.microedition.lcdui.CommandListener; 30 | import javax.microedition.lcdui.Displayable; 31 | import javax.microedition.lcdui.List; 32 | 33 | import app.Settings; 34 | 35 | /** 36 | * @author Karl von Randow 37 | */ 38 | public class SettingsMenu extends List implements Activatable, 39 | CommandListener { 40 | 41 | private Activatable back; 42 | 43 | protected SettingsMenu(String title) { 44 | super(title, List.IMPLICIT); 45 | 46 | append("Network", null); 47 | append("Interface", null); 48 | //#ifndef nofonts 49 | append("Fonts", null); 50 | //#endif 51 | //#ifdef ssh2 52 | append("SSH", null); 53 | //#endif 54 | append("Restore Defaults", null); 55 | 56 | // setSelectCommand( selectCommand ); 57 | addCommand(MainMenu.backCommand); 58 | 59 | setCommandListener(this); 60 | } 61 | 62 | public SettingsMenu() { 63 | this("Settings"); 64 | } 65 | 66 | /* 67 | * (non-Javadoc) 68 | * 69 | * @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, 70 | * javax.microedition.lcdui.Displayable) 71 | */ 72 | public void commandAction(Command command, Displayable displayable) { 73 | if (command == List.SELECT_COMMAND) { 74 | doSelect(getSelectedIndex()); 75 | } else if (command == MainMenu.backCommand) { 76 | doBack(); 77 | } 78 | } 79 | 80 | protected void doSelect(int i) { 81 | int j = 0; 82 | if (j++ == i) { 83 | showSettingsForm(i, SettingsForm.MODE_NETWORK); 84 | } else if (j++ == i) { 85 | showSettingsForm(i, SettingsForm.MODE_INTERFACE); 86 | //#ifndef nofonts 87 | } else if (j++ == i) { 88 | showSettingsForm(i, SettingsForm.MODE_FONTS); 89 | //#endif 90 | } 91 | //#ifdef ssh2 92 | else if (j++ == i) { 93 | showSettingsForm(i, SettingsForm.MODE_SSH); 94 | } 95 | //#endif 96 | else if (j++ == i) { 97 | Settings.defaults(); 98 | Settings.saveSettings(); 99 | // Main.alertBackToMain(new Alert("Settings", 100 | // "Default settings have been restored.", null, 101 | // AlertType.INFO)); 102 | MainMenu.goMainMenu(); 103 | } 104 | } 105 | 106 | private void showSettingsForm(int i, int mode) { 107 | SettingsForm f = new SettingsForm(getString(i), mode); 108 | f.activate(this); 109 | } 110 | 111 | private void doBack() { 112 | back.activate(); 113 | } 114 | 115 | /* 116 | * (non-Javadoc) 117 | * 118 | * @see gui.Activatable#activate() 119 | */ 120 | public void activate() { 121 | MainMenu.setDisplay(this); 122 | } 123 | 124 | /* 125 | * (non-Javadoc) 126 | * 127 | * @see gui.Activatable#activate(gui.Activatable) 128 | */ 129 | public void activate(Activatable back) { 130 | this.back = back; 131 | activate(); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/j2me/kindle/FlashPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * FlashPanel.java 3 | * 4 | * Copyright (c) 2010 VDP . 5 | * 6 | * This file is part of MidpSSH. 7 | * 8 | * MidpSSH is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * MidpSSH is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with MidpSSH. If not, see . 20 | */ 21 | package kindle; 22 | 23 | import com.amazon.kindle.kindlet.ui.KPanel; 24 | import com.amazon.kindle.kindlet.ui.KRepaintManager; 25 | import java.awt.Color; 26 | import java.awt.EventQueue; 27 | import java.awt.Graphics; 28 | import java.lang.reflect.InvocationTargetException; 29 | import org.apache.log4j.Logger; 30 | 31 | /** 32 | * 33 | * @author VDP 34 | */ 35 | public class FlashPanel extends KPanel { 36 | 37 | /** The object used for logging */ 38 | private Logger logger; 39 | /** indicator for flashing panel while repainting */ 40 | private boolean m_doFlash; 41 | 42 | public FlashPanel(Logger log) { 43 | super(); 44 | this.logger = log; 45 | } 46 | 47 | /** 48 | * {@inheritDoc} 49 | */ 50 | public void paint(final Graphics g) { 51 | if (m_doFlash) { 52 | g.setColor(Color.white); 53 | g.clearRect(0, 0, this.getWidth(), this.getHeight()); 54 | m_doFlash = false; 55 | } 56 | else { 57 | super.paint(g); 58 | } 59 | } 60 | 61 | /** 62 | * Overloads repaint that flashes the screen by doing two paints. 63 | * It first paints the panel black and then paints the contents again flashing the screen 64 | * @param flashingRepaint sets the repaint to cause a flash or do a regular paint. 65 | */ 66 | public void repaint(final boolean flashingRepaint) { 67 | m_doFlash = flashingRepaint; 68 | if (m_doFlash) { 69 | final FlashPanel currentFlashingPanel = this; 70 | EventQueue.invokeLater(new Runnable() { 71 | 72 | /** {@inheritDoc} */ 73 | public void run() { 74 | try { 75 | m_doFlash = true; 76 | KRepaintManager.paintImmediately(currentFlashingPanel, true); 77 | } catch (final InterruptedException e1) { 78 | logger.error("Error occured while repainting FlashingPanel", e1); 79 | } catch (final InvocationTargetException e2) { 80 | logger.error("Error occured while repainting FlashingPanel", e2); 81 | } 82 | } 83 | }); 84 | } 85 | super.repaint(); 86 | } 87 | 88 | /** 89 | * {@inheritDoc} 90 | */ 91 | public void repaint() { 92 | repaint(false); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/j2me/kindle/ProxyKeyEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ProxyKeyEvent.java 3 | * 4 | * Copyright (c) 2010 VDP . 5 | * 6 | * This file is part of MidpSSH. 7 | * 8 | * MidpSSH is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * MidpSSH is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with MidpSSH. If not, see . 20 | */ 21 | 22 | package kindle; 23 | 24 | import java.awt.Component; 25 | import java.awt.event.KeyEvent; 26 | import java.util.StringTokenizer; 27 | 28 | public class ProxyKeyEvent extends KeyEvent { 29 | private final static String HDR_EVENT_ID = "EVENT_ID"; 30 | private final static String HDR_MODIFIERS = "MODIFIERS"; 31 | private final static String HDR_KEY_CODE = "KEY_CODE"; 32 | private final static String HDR_KEY_CHAR = "KEY_CHAR"; 33 | 34 | private int id; 35 | 36 | public ProxyKeyEvent(Component source, int id, long when, int modifiers, 37 | int keyCode, char keyChar) { 38 | super(source, id, when, modifiers, keyCode, keyChar); 39 | this.id = id; 40 | } 41 | 42 | public ProxyKeyEvent(KeyEvent ke) { 43 | super(ke.getComponent(), ke.getID(), ke.getWhen(), ke.getModifiers(), 44 | ke.getKeyCode(), ke.getKeyChar()); 45 | this.id = ke.getID(); 46 | } 47 | 48 | /** 49 | * Event format in text (everything below is of type string) 50 | * EVENT_ID (KEY_PRESSED | KEY_RELEASED | KEY_TYPED) 51 | * MODIFIERS STRING_REPR_OF_INT 52 | * KEY_CODE STRING_REPR_OF_INT 53 | * KEY_CHAR STRING_REPR_OF_CHAR 54 | */ 55 | public static ProxyKeyEvent makeEvent(String eventDescr, Component source, long when) { 56 | int id = 0, modifiers = 0, code = 0; 57 | char keyChar = 0; 58 | 59 | StringTokenizer st = new StringTokenizer(eventDescr); 60 | while (st.hasMoreTokens()) { 61 | String token = st.nextToken(); 62 | 63 | if (token.equals(HDR_EVENT_ID)) { 64 | id = Integer.parseInt(st.nextToken()); 65 | } 66 | else if (token.equals(HDR_MODIFIERS)) { 67 | modifiers = Integer.parseInt(st.nextToken()); 68 | } 69 | else if (token.equals(HDR_KEY_CODE)) { 70 | code = Integer.parseInt(st.nextToken()); 71 | } 72 | else if (token.equals(HDR_KEY_CHAR)) { 73 | String charString = st.nextToken(); 74 | keyChar = charString.charAt(0); 75 | if (keyChar == '\\') { 76 | switch (charString.charAt(1)) { 77 | case 'n': 78 | keyChar = '\n'; 79 | break; 80 | case 't': 81 | keyChar = '\t'; 82 | break; 83 | case 's': 84 | keyChar = ' '; 85 | break; 86 | } 87 | } 88 | } 89 | else { 90 | //throw new IllegalArgumentException("Unexpected event token: " + token); 91 | } 92 | } 93 | 94 | ProxyKeyEvent theEvent = new ProxyKeyEvent(source, id, when, modifiers, code, keyChar); 95 | return theEvent; 96 | } 97 | 98 | public String toString() { 99 | String keyStr; 100 | 101 | StringBuffer sb = new StringBuffer(200); 102 | sb.append(HDR_EVENT_ID).append(' ').append(getID()).append('\n'); 103 | sb.append(HDR_MODIFIERS).append(' ').append(getModifiers()).append('\n'); 104 | sb.append(HDR_KEY_CODE).append(' ').append(getKeyCode()).append('\n'); 105 | sb.append(HDR_KEY_CHAR).append(' '); 106 | 107 | char kc = getKeyChar(); 108 | if (kc == '\n') { 109 | sb.append("\\n"); 110 | } 111 | else if (kc == '\t') { 112 | sb.append("\\t"); 113 | } 114 | else if (kc == ' ') { 115 | sb.append("\\s"); 116 | } 117 | else { 118 | sb.append(kc); 119 | } 120 | 121 | return sb.toString(); 122 | } 123 | 124 | public int getID() { 125 | return id; 126 | } 127 | 128 | public void setID(int id) { 129 | this.id = id; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/j2me/kindle/RemoteKbdReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * ProxyKbdReceiver.java 3 | * 4 | * Copyright (c) 2010 VDP . 5 | * 6 | * This file is part of MidpSSH. 7 | * 8 | * MidpSSH is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * MidpSSH is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with MidpSSH. If not, see . 20 | */ 21 | 22 | package kindle; 23 | 24 | import java.awt.Component; 25 | import java.awt.event.KeyEvent; 26 | import java.awt.event.KeyListener; 27 | import java.io.IOException; 28 | import java.net.ServerSocket; 29 | import java.net.Socket; 30 | import java.net.SocketException; 31 | import org.apache.log4j.Logger; 32 | 33 | /** 34 | * Listens on a UDP socket for keyboard events 35 | * and forwards them to the terminal window. 36 | */ 37 | public class RemoteKbdReceiver extends Thread { 38 | 39 | private boolean stopping; 40 | //private DatagramSocket socket; 41 | //private DatagramPacket packet; 42 | private ServerSocket sockServ; 43 | private Socket sock; 44 | byte[] readBuf = new byte[1024]; 45 | private Logger log; 46 | private KeyListener keyListener; 47 | private Component receiver; 48 | private Thread watchdog; 49 | private RKbdStatusListener rkbdListener; 50 | 51 | public RemoteKbdReceiver(int port, KeyListener listener, Component receiver) { 52 | stopping = false; 53 | log = Logger.getLogger(RemoteKbdReceiver.class.getName()); 54 | this.keyListener = listener; 55 | this.receiver = receiver; 56 | try { 57 | sockServ = new ServerSocket(port); 58 | } catch (Exception ex) { 59 | log.error(ex.toString()); 60 | } 61 | 62 | watchdog = new Thread(new Runnable() { 63 | 64 | public void run() { 65 | long sleepTime = 5 * 1000; 66 | while (!stopping) { 67 | try { 68 | Thread.sleep(sleepTime); 69 | } catch (InterruptedException ie) { 70 | log.debug("Watchdog thread interrupted"); 71 | } 72 | 73 | try { 74 | if (sock != null) 75 | sock.getOutputStream().write(1); 76 | } catch (Exception e) { 77 | if (sock != null) { 78 | try { 79 | sock.close(); 80 | sock = null; 81 | } catch (IOException ex) { 82 | log.warn(ex.toString()); 83 | } 84 | } 85 | log.debug("Remote keyboard probably disconnected ..."); 86 | } 87 | } 88 | } 89 | }); 90 | 91 | watchdog.start(); 92 | } 93 | 94 | public void kill() { 95 | try { 96 | stopping = true; 97 | if (sockServ != null) 98 | sockServ.close(); 99 | 100 | if (sock != null && !sock.isClosed()) { 101 | sock.close(); 102 | } 103 | 104 | watchdog.interrupt(); 105 | } catch (IOException ex) { 106 | log.error(ex.getMessage()); 107 | } 108 | } 109 | 110 | public void run() { 111 | try { 112 | while (!stopping) { 113 | if (sock == null) { 114 | log.info("Remote keyboard disconnected"); 115 | if (rkbdListener != null) { 116 | rkbdListener.statusChanged(false); 117 | } 118 | 119 | sock = sockServ.accept(); 120 | 121 | log.info("New remote keyboard attached"); 122 | if (rkbdListener != null) { 123 | rkbdListener.statusChanged(true); 124 | } 125 | } 126 | 127 | int i = 0; 128 | try { 129 | int b = sock.getInputStream().read(); 130 | while (b != 0) { 131 | readBuf[i++] = (byte) b; 132 | b = sock.getInputStream().read(); 133 | } 134 | } 135 | catch (SocketException se) { 136 | log.info("RKeyboard read() interrupted: " + se.toString()); 137 | sock = null; 138 | } 139 | catch (NullPointerException npe) { 140 | log.debug(npe.toString()); 141 | } 142 | 143 | String strEvent = new String(readBuf, 0, i); 144 | System.out.println("Received: " + strEvent); 145 | ProxyKeyEvent pe = ProxyKeyEvent.makeEvent(strEvent, receiver, 0); 146 | int id = pe.getID(); 147 | if (id == KeyEvent.KEY_PRESSED) { 148 | keyListener.keyPressed(pe); 149 | } 150 | else if (id == KeyEvent.KEY_RELEASED) { 151 | keyListener.keyReleased(pe); 152 | } 153 | else { 154 | keyListener.keyTyped(pe); 155 | } 156 | } 157 | } catch (IOException ex) { 158 | if (!stopping) { 159 | log.error(ex.toString()); 160 | } 161 | } 162 | } 163 | 164 | public void setRKbdStatusListener(RKbdStatusListener rkbdListener) { 165 | this.rkbdListener = rkbdListener; 166 | } 167 | 168 | /** 169 | * The objects interested whether a remote keyboard is attached 170 | * should implement this interface and register it with RemoteKbdReceiver 171 | */ 172 | public interface RKbdStatusListener { 173 | public void statusChanged(boolean isAttached); 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/j2me/kindle/RemoteKeyboard.java: -------------------------------------------------------------------------------- 1 | /* 2 | * RemoteKeyboard.java 3 | * 4 | * Copyright (c) 2010 VDP . 5 | * 6 | * This file is part of MidpSSH. 7 | * 8 | * MidpSSH is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * MidpSSH is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with MidpSSH. If not, see . 20 | */ 21 | 22 | package kindle; 23 | 24 | import java.awt.Dimension; 25 | import java.awt.Frame; 26 | import java.awt.GraphicsDevice; 27 | import java.awt.GraphicsEnvironment; 28 | import java.awt.event.KeyEvent; 29 | import java.awt.event.KeyListener; 30 | import java.awt.event.WindowAdapter; 31 | import java.awt.event.WindowEvent; 32 | import java.io.FileInputStream; 33 | import java.io.FileNotFoundException; 34 | import java.io.IOException; 35 | import java.io.OutputStream; 36 | import java.net.DatagramPacket; 37 | import java.net.DatagramSocket; 38 | import java.net.InetSocketAddress; 39 | import java.net.Socket; 40 | import java.net.SocketException; 41 | import java.util.Properties; 42 | import java.util.logging.Level; 43 | import java.util.logging.Logger; 44 | 45 | /** 46 | * Captures the key events on a host machine and relays them 47 | * to the Kindle in plain text format. 48 | * 49 | * @author VDP . 50 | */ 51 | public class RemoteKeyboard implements KeyListener { 52 | 53 | public static void main(String[] args) { 54 | // GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment(). 55 | // getDefaultScreenDevice(); 56 | // if (device.isFullScreenSupported()) { 57 | // System.out.println("Fullscreen supported"); 58 | // device.setFullScreenWindow(frame); 59 | // } 60 | // else { 61 | // System.err.println("Full screen not supported"); 62 | // } 63 | FileInputStream fis = null; 64 | try { 65 | final Frame frame = new Frame("Type here"); 66 | frame.setPreferredSize(new Dimension(800, 600)); 67 | frame.setSize(new Dimension(800, 600)); 68 | 69 | fis = new FileInputStream("remote_keyboard.properties"); 70 | Properties props = new Properties(); 71 | props.load(fis); 72 | String host = props.getProperty("host"); 73 | int port = Integer.parseInt(props.getProperty("port")); 74 | 75 | frame.addWindowListener(new WindowAdapter() { 76 | public void windowClosing(WindowEvent e) { 77 | frame.dispose(); 78 | System.exit(0); 79 | } 80 | }); 81 | 82 | RemoteKeyboard rk = new RemoteKeyboard(host, port); 83 | frame.addKeyListener(rk); 84 | frame.setFocusTraversalKeysEnabled(false); 85 | frame.setVisible(true); 86 | } catch (Exception ex) { 87 | ex.printStackTrace(); 88 | } finally { 89 | try { 90 | fis.close(); 91 | } catch (IOException ex) { 92 | ex.printStackTrace(); 93 | } 94 | } 95 | } 96 | 97 | private String host; 98 | private int port; 99 | 100 | private Socket socket; 101 | private OutputStream out; 102 | 103 | 104 | public RemoteKeyboard(String targetHost, int targetPort) { 105 | this.host = targetHost; 106 | this.port= targetPort; 107 | 108 | connect(); 109 | Thread reader = new Thread(new Runnable() { 110 | 111 | public void run() { 112 | while (true) { 113 | try { 114 | if (socket != null) { 115 | socket.getInputStream().read(); 116 | } 117 | } catch (Exception e) { 118 | e.printStackTrace(); 119 | } 120 | } 121 | } 122 | 123 | }); 124 | } 125 | 126 | private boolean connect() { 127 | boolean ok = true; 128 | try { 129 | System.out.println("Connecting to " + host + ':' + port + " ..."); 130 | socket = new Socket(host, port); 131 | out = socket.getOutputStream(); 132 | System.out.println("OK"); 133 | } catch (Exception ex) { 134 | System.out.println("Failed to connect"); 135 | ok = false; 136 | } 137 | 138 | return ok; 139 | } 140 | 141 | private void sendEvent(KeyEvent event) { 142 | try { 143 | ProxyKeyEvent pe = new ProxyKeyEvent(event); 144 | System.out.println("Key Event: " + pe); 145 | //ProxyKeyEvent reconstructed = ProxyKeyEvent.makeEvent(pe.toString(), event.getComponent(), 0); 146 | //System.out.println("Reconstructed: " + reconstructed); 147 | byte[] eventBytes = pe.toString().getBytes(); 148 | try { 149 | out.write(eventBytes); 150 | out.write(0); 151 | out.flush(); 152 | } 153 | catch (Exception ioe) { 154 | if (socket != null) socket.close(); 155 | connect(); 156 | } 157 | } catch (Exception ex) { 158 | ex.printStackTrace(); 159 | } 160 | } 161 | 162 | public void keyTyped(KeyEvent ke) { 163 | sendEvent(ke); 164 | } 165 | 166 | public void keyPressed(KeyEvent ke) { 167 | sendEvent(ke); 168 | } 169 | 170 | public void keyReleased(KeyEvent ke) { 171 | sendEvent(ke); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/j2me/ssh/SshPacket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of "The Java Telnet Application". 3 | * 4 | * (c) Matthias L. Jugel, Marcus Mei�ner 1996-2002. All Rights Reserved. 5 | * The file was changed by Radek Polak to work as midlet in MIDP 1.0 6 | * 7 | * Please visit http://javatelnet.org/ for updates and contact. 8 | * 9 | * --LICENSE NOTICE-- 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License 12 | * as published by the Free Software Foundation; either version 2 13 | * of the License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 | * --LICENSE NOTICE-- 24 | */ 25 | 26 | package ssh; 27 | 28 | abstract public class SshPacket { 29 | public SshPacket() { /* nothing */ 30 | } 31 | 32 | // Data management 33 | protected byte[] byteArray = new byte[0]; 34 | 35 | protected int offset; 36 | 37 | private boolean finished; 38 | 39 | public byte[] getData() { 40 | return byteArray; 41 | } 42 | 43 | public void putData(byte[] data) { 44 | byteArray = data; 45 | offset = 0; 46 | finished = true; 47 | } 48 | 49 | public boolean isFinished() { 50 | return finished; 51 | } 52 | 53 | abstract public int addPayload(byte[] buff, int boffset, int length); 54 | 55 | // Type 56 | protected byte packet_type; 57 | 58 | public byte getType() { 59 | return packet_type; 60 | } 61 | 62 | public abstract void putMpInt(byte[] bi); 63 | 64 | public int getInt32() { 65 | short d0 = byteArray[offset++]; 66 | short d1 = byteArray[offset++]; 67 | short d2 = byteArray[offset++]; 68 | short d3 = byteArray[offset++]; 69 | 70 | if (d0 < 0) 71 | d0 = (short) (256 + d0); 72 | if (d1 < 0) 73 | d1 = (short) (256 + d1); 74 | if (d2 < 0) 75 | d2 = (short) (256 + d2); 76 | if (d3 < 0) 77 | d3 = (short) (256 + d3); 78 | 79 | return (d0 << 24) + (d1 << 16) + (d2 << 8) + d3; 80 | } 81 | 82 | public int getInt16() { 83 | short d0 = byteArray[offset++]; 84 | short d1 = byteArray[offset++]; 85 | 86 | if (d0 < 0) 87 | d0 = (short) (256 + d0); 88 | if (d1 < 0) 89 | d1 = (short) (256 + d1); 90 | 91 | return (d0 << 8) + d1; 92 | } 93 | 94 | public String getString() { 95 | int length = getInt32(); 96 | 97 | StringBuffer str = new StringBuffer(); 98 | for (int i = 0; i < length; i++) { 99 | /* 100 | * if ( byteArray[offset] >= 0 ) str.append( (char) ( 101 | * byteArray[offset++] ) ); else str.append( (char) ( 256 + 102 | * byteArray[offset++] ) ); 103 | */ 104 | str.append((char) byteArray[offset++]); 105 | } 106 | return str.toString(); 107 | } 108 | 109 | public byte[] getByteString() { 110 | int length = getInt32(); 111 | return getBytes(length); 112 | } 113 | 114 | public byte getByte() { 115 | return byteArray[offset++]; 116 | } 117 | 118 | public byte[] getBytes(int cnt) { 119 | byte[] bytes = new byte[cnt]; 120 | 121 | System.arraycopy(byteArray, offset, bytes, 0, cnt); 122 | offset += cnt; 123 | return bytes; 124 | } 125 | 126 | private void grow(int howmuch) { 127 | byte[] value = new byte[byteArray.length + howmuch]; 128 | System.arraycopy(byteArray, 0, value, 0, byteArray.length); 129 | byteArray = value; 130 | } 131 | 132 | public void putInt16(int xint) { 133 | int boffset = byteArray.length; 134 | grow(2); 135 | byteArray[boffset + 1] = (byte) ((xint) & 0xff); 136 | byteArray[boffset] = (byte) ((xint >> 8) & 0xff); 137 | } 138 | 139 | public void putInt32(int xint) { 140 | int boffset = byteArray.length; 141 | grow(4); 142 | byteArray[boffset + 3] = (byte) ((xint) & 0xff); 143 | byteArray[boffset + 2] = (byte) ((xint >> 8) & 0xff); 144 | byteArray[boffset + 1] = (byte) ((xint >> 16) & 0xff); 145 | byteArray[boffset + 0] = (byte) ((xint >> 24) & 0xff); 146 | } 147 | 148 | public void putByte(byte xbyte) { 149 | grow(1); 150 | byteArray[byteArray.length - 1] = xbyte; 151 | } 152 | 153 | public void putBytes(byte[] bytes) { 154 | int oldlen = byteArray.length; 155 | grow(bytes.length); 156 | System.arraycopy(bytes, 0, byteArray, oldlen, bytes.length); 157 | } 158 | 159 | public void putBytes(byte[] bytes, int offset, int length) { 160 | int oldlen = byteArray.length; 161 | grow(length); 162 | System.arraycopy(bytes, offset, byteArray, oldlen, length); 163 | } 164 | 165 | /** 166 | * Add a SSH String to a packet. The incore representation is a INT32 length 167 | * BYTE[length] data 168 | * 169 | * @param str: 170 | * The string to be added. 171 | */ 172 | public void putString(String str) { 173 | putInt32(str.length()); 174 | putBytes(str.getBytes()); 175 | } 176 | 177 | public void putString(byte[] foo) { 178 | putString(foo, 0, foo.length); 179 | } 180 | 181 | public void putString(byte[] foo, int begin, int length) { 182 | putInt32(length); 183 | putBytes(foo, begin, length); 184 | } 185 | } -------------------------------------------------------------------------------- /src/j2me/ssh/v1/Blowfish.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/src/j2me/ssh/v1/Blowfish.java -------------------------------------------------------------------------------- /src/j2me/ssh/v1/Cipher.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/src/j2me/ssh/v1/Cipher.java -------------------------------------------------------------------------------- /src/j2me/ssh/v1/DES.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/src/j2me/ssh/v1/DES.java -------------------------------------------------------------------------------- /src/j2me/ssh/v1/DES3.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/src/j2me/ssh/v1/DES3.java -------------------------------------------------------------------------------- /src/j2me/ssh/v1/IDEA.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/src/j2me/ssh/v1/IDEA.java -------------------------------------------------------------------------------- /src/j2me/ssh/v1/NONE.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/src/j2me/ssh/v1/NONE.java -------------------------------------------------------------------------------- /src/j2me/ssh/v1/SshCrypto.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/src/j2me/ssh/v1/SshCrypto.java -------------------------------------------------------------------------------- /src/j2me/ssh/v2/HMACSHA1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of "MidpSSH". 3 | * 4 | * This file was adapted from Java Secure Channel (www.jcraft.com/jsch/) for 5 | * MidpSSH by Karl von Randow 6 | * 7 | * Copyright (c) 2002,2003,2004 ymnk, JCraft,Inc. All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * 1. Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * 15 | * 2. Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * 19 | * 3. The names of the authors may not be used to endorse or promote products 20 | * derived from this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 23 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, 25 | * INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | package ssh.v2; 34 | 35 | public class HMACSHA1 { 36 | private String name = "hmac-sha1"; 37 | 38 | private int bsize = 20; 39 | 40 | private byte[] tmp = new byte[4]; 41 | 42 | private final static int BLOCK_LENGTH = 64; 43 | 44 | private final static byte IPAD = (byte) 0x36; 45 | 46 | private final static byte OPAD = (byte) 0x5C; 47 | 48 | private SHA1Digest digest; 49 | 50 | private int digestSize; 51 | 52 | private byte[] inputPad = new byte[BLOCK_LENGTH]; 53 | 54 | private byte[] outputPad = new byte[BLOCK_LENGTH]; 55 | 56 | public int getBlockSize() { 57 | return bsize; 58 | }; 59 | 60 | public void init(byte[] key) { 61 | if (key.length > bsize) { 62 | byte[] tmp = new byte[bsize]; 63 | System.arraycopy(key, 0, tmp, 0, bsize); 64 | key = tmp; 65 | } 66 | 67 | digest = new SHA1Digest(); 68 | digestSize = digest.getDigestSize(); 69 | 70 | digest.reset(); 71 | 72 | if (key.length > BLOCK_LENGTH) { 73 | digest.update(key, 0, key.length); 74 | digest.doFinal(inputPad, 0); 75 | for (int i = digestSize; i < inputPad.length; i++) { 76 | inputPad[i] = 0; 77 | } 78 | } else { 79 | System.arraycopy(key, 0, inputPad, 0, key.length); 80 | for (int i = key.length; i < inputPad.length; i++) { 81 | inputPad[i] = 0; 82 | } 83 | } 84 | 85 | outputPad = new byte[inputPad.length]; 86 | System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length); 87 | 88 | for (int i = 0; i < inputPad.length; i++) { 89 | inputPad[i] ^= IPAD; 90 | } 91 | 92 | for (int i = 0; i < outputPad.length; i++) { 93 | outputPad[i] ^= OPAD; 94 | } 95 | 96 | digest.update(inputPad, 0, inputPad.length); 97 | } 98 | 99 | public void update(int i) { 100 | tmp[0] = (byte) (i >>> 24); 101 | tmp[1] = (byte) (i >>> 16); 102 | tmp[2] = (byte) (i >>> 8); 103 | tmp[3] = (byte) i; 104 | update(tmp, 0, 4); 105 | } 106 | 107 | public void update(byte foo[], int s, int l) { 108 | digest.update(foo, s, l); 109 | } 110 | 111 | public byte[] doFinal() { 112 | byte[] out = new byte[digestSize]; 113 | 114 | byte[] tmp = new byte[digestSize]; 115 | digest.doFinal(tmp, 0); 116 | 117 | digest.update(outputPad, 0, outputPad.length); 118 | digest.update(tmp, 0, tmp.length); 119 | 120 | digest.doFinal(out, 0); 121 | 122 | reset(); 123 | 124 | return out; 125 | } 126 | 127 | /** 128 | * Reset the mac generator. 129 | */ 130 | public void reset() { 131 | /* 132 | * reset the underlying digest. 133 | */ 134 | digest.reset(); 135 | 136 | /* 137 | * reinitialize the digest. 138 | */ 139 | digest.update(inputPad, 0, inputPad.length); 140 | } 141 | 142 | public String getName() { 143 | return name; 144 | } 145 | } -------------------------------------------------------------------------------- /src/j2me/ssh/v2/PublicKeyAuthentication.java: -------------------------------------------------------------------------------- 1 | package ssh.v2; 2 | 3 | import java.util.Random; 4 | //#ifndef noj2me 5 | import app.Settings; 6 | //#endif 7 | 8 | public class PublicKeyAuthentication { 9 | 10 | public static final BigInteger p = new BigInteger( 11 | "d1c9009c7f181e9b27ce020e014d72c499f604c8d978a4dd9a8614362b09a74be4004cdd1b6ccf2bb2d2a4d4710be0817a375c85e8b0ce05e92a1f7c0b4886418dc6de84457dfd8dc19efdc0efb5c15bbab7a860b3e95c169d6e8aceef445deddc85ab44a11d5870847b99239011ff7d36a0f52cd11c3a0a33c415cdd58d85a1", 12 | 16), 13 | q = new BigInteger("e691d26b30a8b43081b981d96a8189fe78d04f8f", 16), 14 | g = new BigInteger( 15 | "6ded9dc637ecc98f7ccf5a50839e13354972985cb901ca164fb8174318c84fec50ce84bfef5f4ee4981c239ed7c2bcf0718fcc0f30382df782221f64bfd09c9dc8e098ad10f296eadd9f5650f17414a77d3ff5ca8d103235e2de14a392c9a1156b2a5652d135111858af96d531688d80e962c52c75738f3d48aa09d59ca064a6", 16 | 16); 17 | 18 | public BigInteger x, y; 19 | 20 | //#ifdef ssh2 21 | public PublicKeyAuthentication() { 22 | //#ifndef noj2me 23 | this.x = new BigInteger(Settings.x); 24 | this.y = new BigInteger(Settings.y); 25 | //#else 26 | this.x = null; 27 | this.y = null; 28 | //#endif 29 | } 30 | //#endif 31 | 32 | public byte[] sign(byte[] session_id, byte[] message) { 33 | SshPacket2 buf = new SshPacket2(); 34 | buf.putString(session_id); 35 | buf.putByte((byte) 50); // SSH2_MSG_USERAUTH_REQUEST 36 | buf.putBytes(message); 37 | 38 | message = buf.getData(); 39 | 40 | SHA1Digest digest = new SHA1Digest(); 41 | digest.update(message, 0, message.length); 42 | byte[] hash = new byte[digest.getDigestSize()]; 43 | digest.doFinal(hash, 0); 44 | 45 | BigInteger[] rs = generateSignature(hash); 46 | 47 | buf = new SshPacket2(); 48 | buf.putString(DHKeyExchange.SSH_DSS); 49 | byte[] r = rs[0].toByteArray(); 50 | byte[] s = rs[1].toByteArray(); 51 | byte[] sig = new byte[40]; 52 | System.arraycopy(r, r.length > 20 ? 1 : 0, sig, r.length > 20 ? 0 53 | : 20 - r.length, r.length > 20 ? 20 : r.length); 54 | System.arraycopy(s, s.length > 20 ? 1 : 0, sig, s.length > 20 ? 20 55 | : 40 - s.length, s.length > 20 ? 20 : s.length); 56 | buf.putString(sig); 57 | 58 | return buf.getData(); 59 | } 60 | 61 | /** 62 | * generate a signature for the given message using the key we were 63 | * initialised with. For conventional DSA the message should be a SHA-1 hash 64 | * of the message of interest. 65 | * 66 | * @param message 67 | * the message that will be verified later. 68 | */ 69 | public BigInteger[] generateSignature(byte[] message) { 70 | BigInteger m = new BigInteger(1, message); 71 | BigInteger k; 72 | int qBitLength = q.bitLength(); 73 | 74 | do { 75 | k = new BigInteger(qBitLength, new Random()); 76 | } while (k.compareTo(q) >= 0); 77 | 78 | BigInteger r = g.modPow(k, p).mod(q); 79 | 80 | k = k.modInverse(q).multiply(m.add(x.multiply(r))); 81 | 82 | BigInteger s = k.mod(q); 83 | 84 | BigInteger[] res = new BigInteger[2]; 85 | 86 | res[0] = r; 87 | res[1] = s; 88 | 89 | return res; 90 | } 91 | 92 | public String getPublicKeyText() { 93 | byte[] pubblob = getPublicKeyBlob(); 94 | byte[] pub = toBase64(pubblob, 0, pubblob.length); 95 | return DHKeyExchange.SSH_DSS + " " + new String(pub); 96 | } 97 | 98 | public byte[] getPublicKeyBlob() { 99 | SshPacket2 buf = new SshPacket2(); 100 | buf.putString(DHKeyExchange.SSH_DSS); 101 | buf.putMpInt(p.toByteArray()); 102 | buf.putMpInt(q.toByteArray()); 103 | buf.putMpInt(g.toByteArray()); 104 | buf.putMpInt(y.toByteArray()); 105 | return buf.getData(); 106 | } 107 | 108 | public static byte[][] generateKeyPair() { 109 | BigInteger x, y; 110 | 111 | do { 112 | x = new BigInteger(160, new Random()); 113 | } while (x.equals(BigInteger.ZERO) || x.compareTo(q) >= 0); 114 | 115 | // 116 | // calculate the public key. 117 | // 118 | y = g.modPow(x, p); 119 | 120 | byte[][] res = new byte[2][]; 121 | res[0] = x.toByteArray(); 122 | res[1] = y.toByteArray(); 123 | return res; 124 | } 125 | 126 | private static final byte[] b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" 127 | .getBytes(); 128 | 129 | private static byte[] toBase64(byte[] buf, int start, int length) { 130 | 131 | byte[] tmp = new byte[length * 2]; 132 | int i, j, k; 133 | 134 | int foo = (length / 3) * 3 + start; 135 | i = 0; 136 | for (j = start; j < foo; j += 3) { 137 | k = (buf[j] >>> 2) & 0x3f; 138 | tmp[i++] = b64[k]; 139 | k = (buf[j] & 0x03) << 4 | (buf[j + 1] >>> 4) & 0x0f; 140 | tmp[i++] = b64[k]; 141 | k = (buf[j + 1] & 0x0f) << 2 | (buf[j + 2] >>> 6) & 0x03; 142 | tmp[i++] = b64[k]; 143 | k = buf[j + 2] & 0x3f; 144 | tmp[i++] = b64[k]; 145 | } 146 | 147 | foo = (start + length) - foo; 148 | if (foo == 1) { 149 | k = (buf[j] >>> 2) & 0x3f; 150 | tmp[i++] = b64[k]; 151 | k = ((buf[j] & 0x03) << 4) & 0x3f; 152 | tmp[i++] = b64[k]; 153 | tmp[i++] = (byte) '='; 154 | tmp[i++] = (byte) '='; 155 | } else if (foo == 2) { 156 | k = (buf[j] >>> 2) & 0x3f; 157 | tmp[i++] = b64[k]; 158 | k = (buf[j] & 0x03) << 4 | (buf[j + 1] >>> 4) & 0x0f; 159 | tmp[i++] = b64[k]; 160 | k = ((buf[j + 1] & 0x0f) << 2) & 0x3f; 161 | tmp[i++] = b64[k]; 162 | tmp[i++] = (byte) '='; 163 | } 164 | byte[] bar = new byte[i]; 165 | System.arraycopy(tmp, 0, bar, 0, i); 166 | return bar; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/j2me/ssh/v2/SHA1Digest.java: -------------------------------------------------------------------------------- 1 | /* This file is part of "MidpSSH". 2 | * 3 | * This file was adapted from Bouncy Castle JCE (www.bouncycastle.org) 4 | * for MidpSSH by Karl von Randow 5 | */ 6 | package ssh.v2; 7 | 8 | /** 9 | * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", 10 | * pages 346 - 349. 11 | * 12 | * It is interesting to ponder why the, apart from the extra IV, the other 13 | * difference here from MD5 is the "endienness" of the word processing! 14 | */ 15 | public class SHA1Digest { 16 | private static final int DIGEST_LENGTH = 20; 17 | 18 | private int H1, H2, H3, H4, H5; 19 | 20 | private int[] X = new int[80]; 21 | 22 | private int xOff; 23 | 24 | private byte[] xBuf; 25 | 26 | private int xBufOff; 27 | 28 | private long byteCount; 29 | 30 | /** 31 | * Standard constructor 32 | */ 33 | public SHA1Digest() { 34 | xBuf = new byte[4]; 35 | xBufOff = 0; 36 | 37 | reset(); 38 | } 39 | 40 | public String getAlgorithmName() { 41 | return "SHA-1"; 42 | } 43 | 44 | public int getDigestSize() { 45 | return DIGEST_LENGTH; 46 | } 47 | 48 | protected void processWord(byte[] in, int inOff) { 49 | X[xOff++] = ((in[inOff] & 0xff) << 24) | ((in[inOff + 1] & 0xff) << 16) 50 | | ((in[inOff + 2] & 0xff) << 8) | ((in[inOff + 3] & 0xff)); 51 | 52 | if (xOff == 16) { 53 | processBlock(); 54 | } 55 | } 56 | 57 | private void unpackWord(int word, byte[] out, int outOff) { 58 | out[outOff] = (byte) (word >>> 24); 59 | out[outOff + 1] = (byte) (word >>> 16); 60 | out[outOff + 2] = (byte) (word >>> 8); 61 | out[outOff + 3] = (byte) word; 62 | } 63 | 64 | protected void processLength(long bitLength) { 65 | if (xOff > 14) { 66 | processBlock(); 67 | } 68 | 69 | X[14] = (int) (bitLength >>> 32); 70 | X[15] = (int) (bitLength & 0xffffffff); 71 | } 72 | 73 | public int doFinal(byte[] out, int outOff) { 74 | finish(); 75 | 76 | unpackWord(H1, out, outOff); 77 | unpackWord(H2, out, outOff + 4); 78 | unpackWord(H3, out, outOff + 8); 79 | unpackWord(H4, out, outOff + 12); 80 | unpackWord(H5, out, outOff + 16); 81 | 82 | reset(); 83 | 84 | return DIGEST_LENGTH; 85 | } 86 | 87 | /** 88 | * reset the chaining variables 89 | */ 90 | public void reset() { 91 | byteCount = 0; 92 | 93 | xBufOff = 0; 94 | for (int i = 0; i < xBuf.length; i++) { 95 | xBuf[i] = 0; 96 | } 97 | 98 | H1 = 0x67452301; 99 | H2 = 0xefcdab89; 100 | H3 = 0x98badcfe; 101 | H4 = 0x10325476; 102 | H5 = 0xc3d2e1f0; 103 | 104 | xOff = 0; 105 | for (int i = 0; i != X.length; i++) { 106 | X[i] = 0; 107 | } 108 | } 109 | 110 | public void update(byte in) { 111 | xBuf[xBufOff++] = in; 112 | 113 | if (xBufOff == xBuf.length) { 114 | processWord(xBuf, 0); 115 | xBufOff = 0; 116 | } 117 | 118 | byteCount++; 119 | } 120 | 121 | public void update(byte[] in, int inOff, int len) { 122 | // 123 | // fill the current word 124 | // 125 | while ((xBufOff != 0) && (len > 0)) { 126 | update(in[inOff]); 127 | 128 | inOff++; 129 | len--; 130 | } 131 | 132 | // 133 | // process whole words. 134 | // 135 | while (len > xBuf.length) { 136 | processWord(in, inOff); 137 | 138 | inOff += xBuf.length; 139 | len -= xBuf.length; 140 | byteCount += xBuf.length; 141 | } 142 | 143 | // 144 | // load in the remainder. 145 | // 146 | while (len > 0) { 147 | update(in[inOff]); 148 | 149 | inOff++; 150 | len--; 151 | } 152 | } 153 | 154 | public void finish() { 155 | long bitLength = (byteCount << 3); 156 | 157 | // 158 | // add the pad bytes. 159 | // 160 | update((byte) 128); 161 | 162 | while (xBufOff != 0) { 163 | update((byte) 0); 164 | } 165 | 166 | processLength(bitLength); 167 | 168 | processBlock(); 169 | } 170 | 171 | // 172 | // Additive constants 173 | // 174 | private static final int Y1 = 0x5a827999; 175 | 176 | private static final int Y2 = 0x6ed9eba1; 177 | 178 | private static final int Y3 = 0x8f1bbcdc; 179 | 180 | private static final int Y4 = 0xca62c1d6; 181 | 182 | private int f(int u, int v, int w) { 183 | return ((u & v) | ((~u) & w)); 184 | } 185 | 186 | private int h(int u, int v, int w) { 187 | return (u ^ v ^ w); 188 | } 189 | 190 | private int g(int u, int v, int w) { 191 | return ((u & v) | (u & w) | (v & w)); 192 | } 193 | 194 | private int rotateLeft(int x, int n) { 195 | return (x << n) | (x >>> (32 - n)); 196 | } 197 | 198 | protected void processBlock() { 199 | // 200 | // expand 16 word block into 80 word block. 201 | // 202 | for (int i = 16; i <= 79; i++) { 203 | X[i] = rotateLeft((X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]), 1); 204 | } 205 | 206 | // 207 | // set up working variables. 208 | // 209 | int A = H1; 210 | int B = H2; 211 | int C = H3; 212 | int D = H4; 213 | int E = H5; 214 | 215 | // 216 | // round 1 217 | // 218 | for (int j = 0; j <= 19; j++) { 219 | int t = rotateLeft(A, 5) + f(B, C, D) + E + X[j] + Y1; 220 | 221 | E = D; 222 | D = C; 223 | C = rotateLeft(B, 30); 224 | B = A; 225 | A = t; 226 | } 227 | 228 | // 229 | // round 2 230 | // 231 | for (int j = 20; j <= 39; j++) { 232 | int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y2; 233 | 234 | E = D; 235 | D = C; 236 | C = rotateLeft(B, 30); 237 | B = A; 238 | A = t; 239 | } 240 | 241 | // 242 | // round 3 243 | // 244 | for (int j = 40; j <= 59; j++) { 245 | int t = rotateLeft(A, 5) + g(B, C, D) + E + X[j] + Y3; 246 | 247 | E = D; 248 | D = C; 249 | C = rotateLeft(B, 30); 250 | B = A; 251 | A = t; 252 | } 253 | 254 | // 255 | // round 4 256 | // 257 | for (int j = 60; j <= 79; j++) { 258 | int t = rotateLeft(A, 5) + h(B, C, D) + E + X[j] + Y4; 259 | 260 | E = D; 261 | D = C; 262 | C = rotateLeft(B, 30); 263 | B = A; 264 | A = t; 265 | } 266 | 267 | H1 += A; 268 | H2 += B; 269 | H3 += C; 270 | H4 += D; 271 | H5 += E; 272 | 273 | // 274 | // reset the offset and clean out the word buffer. 275 | // 276 | xOff = 0; 277 | for (int i = 0; i != X.length; i++) { 278 | X[i] = 0; 279 | } 280 | } 281 | } -------------------------------------------------------------------------------- /src/j2me/ssh/v2/SshCrypto2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of "MidpSSH". Copyright (c) 2004 Karl von Randow. 3 | * 4 | * MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak. 5 | * 6 | * --LICENSE NOTICE-- This program is free software; you can redistribute it 7 | * and/or modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; either version 2 of the License, 9 | * or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 | * details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * this program; if not, write to the Free Software Foundation, Inc., 675 Mass 18 | * Ave, Cambridge, MA 02139, USA. --LICENSE NOTICE-- 19 | * 20 | */ 21 | package ssh.v2; 22 | 23 | 24 | public class SshCrypto2 { 25 | private BufferedDESedeCBC sndCipher, rcvCipher; 26 | 27 | private HMACSHA1 sndHmac, rcvHmac; 28 | 29 | public SshCrypto2(byte[] IVc2s, byte[] IVs2c, byte[] Ec2s, byte[] Es2c, 30 | byte[] MACc2s, byte[] MACs2c) { 31 | sndCipher = new BufferedDESedeCBC(); 32 | sndCipher.init(true, IVc2s, Ec2s); 33 | rcvCipher = new BufferedDESedeCBC(); 34 | rcvCipher.init(false, IVs2c, Es2c); 35 | 36 | sndHmac = new HMACSHA1(); 37 | sndHmac.init(MACc2s); 38 | 39 | rcvHmac = new HMACSHA1(); 40 | rcvHmac.init(MACs2c); 41 | } 42 | 43 | public byte[] encrypt(byte[] src) { 44 | byte[] dest = new byte[src.length]; 45 | sndCipher.processBytes(src, 0, src.length, dest, 0); 46 | return dest; 47 | } 48 | 49 | public byte[] decrypt(byte[] src) { 50 | byte[] dest = new byte[src.length]; 51 | rcvCipher.processBytes(src, 0, src.length, dest, 0); 52 | return dest; 53 | } 54 | 55 | /** 56 | * @return Returns the rcvHmac. 57 | */ 58 | public HMACSHA1 getRcvHmac() { 59 | return rcvHmac; 60 | } 61 | 62 | /** 63 | * @return Returns the sndHmac. 64 | */ 65 | public HMACSHA1 getSndHmac() { 66 | return sndHmac; 67 | } 68 | } -------------------------------------------------------------------------------- /src/j2me/telnet/Dimension.java: -------------------------------------------------------------------------------- 1 | package telnet; 2 | 3 | /* This file is part of "Telnet Floyd". 4 | * 5 | * (c) Radek Polak 2003-2004. All Rights Reserved. 6 | * 7 | * Please visit project homepage at http://phoenix.inf.upol.cz/~polakr 8 | * 9 | * --LICENSE NOTICE-- 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License 12 | * as published by the Free Software Foundation; either version 2 13 | * of the License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 | * --LICENSE NOTICE-- 24 | * 25 | */ 26 | 27 | /** 28 | * Class used instead of missing java.awt.Dimension. 29 | */ 30 | 31 | public class Dimension { 32 | 33 | public int width, height; 34 | 35 | public Dimension() { 36 | } 37 | 38 | public Dimension( int width, int height ) { 39 | this.width = width; 40 | this.height = height; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/j2me/telnet/TelnetProtocolHandler.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdp/KindleTERM/e3f55e2f5745a43f52b64c854e3ee911e71bef5c/src/j2me/telnet/TelnetProtocolHandler.java -------------------------------------------------------------------------------- /src/j2me/terminal/LCDFont.java: -------------------------------------------------------------------------------- 1 | // LCDFont: Class for using tiny fonts with subpixel antialising 2 | // 3 | // Copyright 2005 Roar Lauritzsen 4 | // 5 | // This class is free software; you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation; either version 2 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This class is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // The following link provides a copy of the GNU General Public License: 16 | // http://www.gnu.org/licenses/gpl.txt 17 | // If you are unable to obtain the copy from this address, write to 18 | // the Free Software Foundation, Inc., 59 Temple Place, Suite 330, 19 | // Boston, MA 02111-1307 USA 20 | 21 | package terminal; 22 | 23 | import java.io.IOException; 24 | 25 | import javax.microedition.lcdui.Graphics; 26 | import javax.microedition.lcdui.Image; 27 | 28 | public class LCDFont { 29 | //#ifdef midp2 30 | 31 | public final int fontWidth; // Width of one character 32 | 33 | public final int fontHeight; // Height of one character 34 | 35 | private final int imageWidth, imageHeight; 36 | 37 | private int[] bwBuf; // Black-white version of font 38 | 39 | private int[] colorBuf; // Colored version of font 40 | 41 | private int[] currentBuf; 42 | 43 | private long currentColor; 44 | 45 | private long[] cacheColor; // Color of each cached character 46 | 47 | private int FR, FG, FB, BR, BG, BB; 48 | 49 | // Create subpixel-antialiased font based on image resource name. 50 | // If BGR is set to true, subpixel order is reversed (normal is RGB) 51 | public LCDFont(String fontImageName, boolean BGR) { 52 | Image fontImage; 53 | try { 54 | fontImage = Image.createImage(fontImageName); 55 | } catch (IOException e) { 56 | throw new RuntimeException("Cannot load LCDFont: " + e); 57 | } 58 | imageWidth = fontImage.getWidth(); 59 | imageHeight = fontImage.getHeight(); 60 | fontWidth = imageWidth / 32; 61 | fontHeight = imageHeight / 3; 62 | bwBuf = new int[imageWidth * (imageHeight + 1)]; 63 | colorBuf = new int[imageWidth * (imageHeight + 1)]; 64 | /* Karl: add 1 to the imageHeight because some device seek beyond the bottom of the array when 65 | * drawing. 66 | */ 67 | fontImage.getRGB(bwBuf, 0, imageWidth, 0, 0, imageWidth, imageHeight); 68 | if (BGR) { 69 | // For screens with BGR subpixel ordering, or for ROT_180 70 | for (int i = 0; i < bwBuf.length; i++) { 71 | int c = bwBuf[i]; 72 | bwBuf[i] = ((c >> 16) & 0xff) + (c & 0xff00) 73 | + ((c & 0xff) << 16); 74 | } 75 | } 76 | cacheColor = new long[96]; 77 | currentBuf = bwBuf; 78 | currentColor = 0; 79 | } 80 | 81 | // Set the foreground and background color of font 82 | // For readability, input font colors will be modified 83 | public void setColor(int fg, int bg) { 84 | if (fg == 0xffffff && bg == 0) { 85 | currentBuf = bwBuf; 86 | } else if (((long) fg << 32) + bg != currentColor) { 87 | currentColor = ((long) fg << 32) + bg; 88 | currentBuf = colorBuf; 89 | 90 | // Because of the subpixel antialising, we cannot use the color 91 | // directly. Instead, we have to select a more "pastel" color, 92 | // and differentiate properly between background and foreground 93 | 94 | FR = (fg >> 16) & 0xff; 95 | FG = (fg >> 8) & 0xff; 96 | FB = fg & 0xff; 97 | 98 | BR = (bg >> 16) & 0xff; 99 | BG = (bg >> 8) & 0xff; 100 | BB = bg & 0xff; 101 | 102 | if (28 * FR + 55 * FG + 17 * FB >= 28 * BR + 55 * BG + 17 * BB) { 103 | // bright on dark 104 | FR = (6 * FR + 10 * 0xff) / 16; // Brighten foreground 105 | FG = (6 * FG + 10 * 0xff) / 16; 106 | FB = (6 * FB + 10 * 0xff) / 16; 107 | BR = (10 * BR) / 16; // Darken background 108 | BG = (10 * BG) / 16; 109 | BB = (10 * BB) / 16; 110 | } else { 111 | // dark on bright 112 | FR = (10 * FR) / 16; // Darken foreground 113 | FG = (10 * FG) / 16; 114 | FB = (10 * FB) / 16; 115 | BR = (6 * BR + 10 * 0xff) / 16; // Brighten background 116 | BG = (6 * BG + 10 * 0xff) / 16; 117 | BB = (6 * BB + 10 * 0xff) / 16; 118 | } 119 | // Scale to range 0-256 for later ">>8" instead of "/255" 120 | FR += FR >> 7; 121 | FG += FG >> 7; 122 | FB += FB >> 7; 123 | BR += BR >> 7; 124 | BG += BG >> 7; 125 | BB += BB >> 7; 126 | } 127 | } 128 | 129 | // Colored characters are cached in colorBuf and rendered as needed 130 | private void renderColorChar(int offset) { 131 | for (int y = 0; y < fontHeight; y++) 132 | for (int x = 0; x < fontWidth; x++) { 133 | int col = bwBuf[offset + y * imageWidth + x]; 134 | int R = (col >> 16) & 0xff; 135 | int G = (col >> 8) & 0xff; 136 | int B = col & 0xff; 137 | 138 | R = (FR * R + BR * (255 - R)) >> 8; 139 | G = (FG * G + BG * (255 - G)) >> 8; 140 | B = (FB * B + BB * (255 - B)) >> 8; 141 | 142 | colorBuf[offset + y * imageWidth + x] = (R << 16) + (G << 8) 143 | + B; 144 | } 145 | } 146 | 147 | // Draw one char 148 | public void drawChar(Graphics g, char c, int x, int y) { 149 | if (c <= ' ' || c > '~') 150 | return; 151 | c -= ' '; 152 | int offset = (c >> 5) * fontHeight * imageWidth + (c & 31) * fontWidth; 153 | if (currentBuf == colorBuf && cacheColor[c] != currentColor) { 154 | renderColorChar(offset); 155 | cacheColor[c] = currentColor; 156 | } 157 | g.drawRGB(currentBuf, offset, imageWidth, x, y, fontWidth, fontHeight, 158 | false); 159 | } 160 | //#endif 161 | } -------------------------------------------------------------------------------- /src/tasks/FileLength.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | 3 | /* 4 | * Created on 15/04/2005 5 | * 6 | */ 7 | 8 | /** 9 | * @author Karl 10 | * 11 | */ 12 | public class FileLength { 13 | public static void main(String[] argv) { 14 | if (argv.length != 1) { 15 | System.err.println("Usage: filename"); 16 | System.exit(1); 17 | } 18 | 19 | File file = new File(argv[0]); 20 | System.out.println(file.length()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/tasks/RewriteBlackberryJAD.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedReader; 2 | import java.io.BufferedWriter; 3 | import java.io.DataInputStream; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.FileReader; 7 | import java.io.FileWriter; 8 | import java.io.IOException; 9 | import java.io.PrintWriter; 10 | import java.security.MessageDigest; 11 | import java.security.NoSuchAlgorithmException; 12 | 13 | /* 14 | * Created on 15/04/2005 15 | * 16 | */ 17 | 18 | /** 19 | * @author Karl 20 | * 21 | */ 22 | public class RewriteBlackberryJAD { 23 | 24 | public static void main(String[] args) throws IOException, NoSuchAlgorithmException { 25 | File jadIn = new File(args[0]); 26 | File jadOut = new File(args[1]); 27 | String sha1 = sha1(new File(args[2])); 28 | String sha2 = sha1(new File(args[3])); 29 | String cod1 = args[4]; 30 | String cod2 = args[5]; 31 | long length1 = Long.parseLong(args[6]); 32 | long length2 = Long.parseLong(args[7]); 33 | 34 | BufferedReader in = new BufferedReader(new FileReader(jadIn)); 35 | PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(jadOut))); 36 | 37 | String line = in.readLine(); 38 | while (line != null) { 39 | if (line.startsWith("RIM-COD-URL") || line.startsWith("RIM-COD-SHA1") || line.startsWith("RIM-COD-Size")) { 40 | /* Ignore these lines */ 41 | } 42 | else { 43 | out.println(line); 44 | } 45 | line = in.readLine(); 46 | } 47 | 48 | out.println("RIM-COD-URL-1: " + cod1); 49 | out.println("RIM-COD-URL-2: " + cod2); 50 | out.println("RIM-COD-Size-1: " + length1); 51 | out.println("RIM-COD-Size-2: " + length2); 52 | out.println("RIM-COD-SHA1-1: " + sha1); 53 | out.println("RIM-COD-SHA1-2: " + sha2); 54 | 55 | in.close(); 56 | out.close(); 57 | } 58 | 59 | private static String sha1(File file) throws IOException, NoSuchAlgorithmException { 60 | byte[] data = new byte[(int) file.length()]; 61 | DataInputStream in = new DataInputStream(new FileInputStream(file)); 62 | in.readFully(data); 63 | 64 | MessageDigest md = MessageDigest.getInstance("SHA-1"); 65 | byte[] hash = md.digest(data); 66 | 67 | StringBuffer hashString = new StringBuffer(); 68 | for (int i = 0; i < hash.length; i++) { 69 | String hex = Integer.toHexString((int) (hash[i] & 0xff)); 70 | if (hex.length() < 2) { 71 | hashString.append('0'); 72 | } 73 | hashString.append(hex); 74 | hashString.append(" "); 75 | } 76 | 77 | return hashString.toString().trim(); 78 | } 79 | } 80 | --------------------------------------------------------------------------------