/*
* Buffer.java
*
* Created on August 2, 2007, 7:48 PM
*
* @author pquiring
*
*/
import java.io.*;
import java.net.*;
import javax.net.ssl.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import java.util.*;
import javax.swing.*;
import javaforce.*;
import javaforce.jni.*;
import javaforce.jni.lnx.*;
import javaforce.jni.win.*;
import com.jcraft.jsch.*;
public class Buffer extends JComponent implements KeyListener, MouseListener, MouseMotionListener {
public Buffer() {
changeFont();
}
public void finalize() {
JFLog.log("Buffer.finalize()");
}
private void init() {
//now runs in the EDT
JFLog.log("Buffer.init start");
try {
lock = new Object();
setFocusable(true);
setRequestFocusEnabled(true);
addKeyListener(this);
addMouseListener(this);
addMouseMotionListener(this);
scrollBack = Settings.settings.scrollBack;
foreColor = Settings.settings.foreColor;
backColor = Settings.settings.backColor;
gotoPos(1,1);
ansi = new ANSI(this, sd.protocol.equals("telnet"));
telnet = new Telnet();
utf8 = new UTF8();
timer = new java.util.Timer();
timer.schedule(new TimerTask() {
public void run() {
timer();
}
}, 500, 500);
pane = (JScrollPane)getClientProperty("pane");
pane.getVerticalScrollBar().setUnitIncrement(8); //faster!
if (sd.autoSize) {
Dimension d;
d = pane.getViewport().getExtentSize();
if (d.width < fx) d.width = fx;
if (d.height < fy) d.height = fy;
sd.sx = d.width / fx;
sd.sy = d.height / fy;
}
sx = sd.sx;
sy = sd.sy;
y1 = 0;
y2 = sy-1;
chars = new Char[sx*(sy+scrollBack)];
for(int a=0;a<sx*(sy+scrollBack);a++) chars[a] = new Char();
init = true;
if (sd.autoSize)
changeSize();
else
reSize();
setVisible(true);
requestFocus();
ready = true; //ready to paint
render = new Render();
render.setPriority(RenderPriority);
render.start();
reader = new Reader();
reader.setPriority(ReaderPriority);
reader.start();
} catch (Exception e) {
JFLog.log(e);
}
JFLog.log("Buffer.init done");
}
//public data
public int sx, sy; //screen size x/y (80x24)
public boolean applet = false; //non-signed applet
private int y1,y2; //scroll range
public Script script = null;
//private static data
private static int fx, fy; //font size x/y
private static int descent;
//private data
private volatile boolean ready = false;
private Object lock;
private Render render;
private final int RenderPriority = Thread.MAX_PRIORITY-1;
private Reader reader;
private final int ReaderPriority = Thread.MAX_PRIORITY-1;
private InputStream in;
private OutputStream out;
private Socket s; //telnet
private Session session; //ssh
private Channel channel; //ssh
private SSLSocket ssl; //ssl
/** Number of lines that user can scroll back to. */
private int scrollBack;
private Telnet telnet;
private ANSI ansi;
private UTF8 utf8;
/** Current Telnet/ANSI code */
private char code[] = new char[64]; //Telnet/ANSI code
private int codelen = 0;
private final char IAC = 255;
private final char ESC = 27; //0x1b
/** The actual screen buffer.*/
private Char chars[] = null;
private int cx, cy; //cursor position (0,0 = top left)
/** A timer to blink the cursor, the blinky text. */
private java.util.Timer timer;
private Color foreColor, backColor; //current foreColor, backColor
private boolean cursorShown = false;
private int selectStart = -1, selectEnd = -1;
private FileOutputStream fos; //log file
private boolean blinker = false;
private boolean reverse = false;
private boolean blinkerShown = false;
//connection info
private boolean connected = false, connecting = false;
private boolean failed = false;
private Frame parent;
private SiteDetails sd;
/** eol means we are 1 char beyond the end of a line but haven't moved down to the next line yet */
private boolean eol = false;
private boolean closed = false;
private boolean init = false;
private JScrollPane pane;
private LnxPty pty;
private boolean autowrap = true;
private long profile_last = 0;
private void profile(boolean show, String msg) {
long current = System.nanoTime();
if (show) System.out.println(msg + "Diff=" + (current-profile_last));
profile_last = current;
}
public byte[] char2byte(char buf[], int buflen) {
byte tmp[] = new byte[buflen];
for(int a=0;a<buflen;a++) tmp[a] = (byte)buf[a];
return tmp;
}
public char[] byte2char(byte buf[], int buflen) {
char tmp[] = new char[buflen];
for(int a=0;a<buflen;a++) {
tmp[a] = (char)buf[a];
tmp[a] &= 0xff;
}
return tmp;
}
public void output(char buf[]) {
if (sd.localecho) input(buf, buf.length);
byte tmp[] = char2byte(buf, buf.length);
try {
out.write(tmp);
out.flush();
} catch (Exception e) {
JFLog.log(e);
if (!closed) {
close();
}
}
}
public void output(char ch) {
if (sd.localecho) input(ch);
try {
out.write(new byte[] {(byte)ch});
out.flush();
} catch (Exception e) {
JFLog.log(e);
if (!closed) {
close();
}
}
}
private void input(String str) {
input(str.toCharArray(), str.length());
}
private void input(char buf[], int buflen) {
//process Telnet/ANSI code
if (fos != null) {
byte tmp[] = char2byte(buf, buflen);
JF.write(fos, tmp, 0, tmp.length);
}
char newbuf[] = new char[buflen];
int newbuflen = 0;
for(int a=0;a<buflen;a++) {
if (codelen == 0) {
if ((buf[a] == IAC) || (buf[a] == ESC) || (sd.utf8 && utf8.isUTF8(buf[a]))) {
if (newbuflen > 0) {print(newbuf, newbuflen); newbuflen = 0;}
codelen = 1;
code[0] = buf[a];
continue;
}
newbuf[newbuflen++] = ansi.encodeChar(buf[a]);
} else {
code[codelen++] = buf[a]; //TODO: check overflow
//some systems generate two ESC in a row (ignore the 1st ESC)
if ((codelen == 2) && (code[0] == ESC) && (code[1] == ESC)) {codelen = 1;}
if (code[0] == IAC) {
if (telnet.decode(code, codelen, this)) codelen = 0;
} else if (code[0] == ESC) {
if (ansi.decode(code, codelen, this)) codelen = 0;
} else /*if (utf8.isUTF8(code[0]))*/ {
if (utf8.decode(code, codelen, this)) {
codelen = 0;
newbuf[newbuflen++] = utf8.char16;
}
}
}
}
if (newbuflen > 0) print(newbuf, newbuflen);
}
private void input(char ch) {
char tmp[] = new char[1];
tmp[0] = ch;
input(tmp, 1);
}
public static void changeFont() {
{
int metrics[] = JF.getFontMetrics(Settings.fnt);
//[0] = width
//[1] = ascent
//[2] = descent
// JFLog.log("metrics=" + metrics[0] + "," + metrics[1] + "," + metrics[2]);
fx = metrics[0] + Settings.settings.fontWidth;
fy = metrics[1] + metrics[2] + Settings.settings.fontHeight;
descent = metrics[2] + Settings.settings.fontDescent;
}
}
private void setPreferredSize() {
setPreferredSize(new Dimension(fx * sx, fy * (sy + scrollBack)));
}
public void reSize() {
setPreferredSize();
revalidate(); //must call this after resizing
signalRepaint(true);
}
public synchronized void changeSize() {
if (!init) return;
if (!sd.autoSize) return;
Dimension d;
d = pane.getViewport().getExtentSize();
if (d.width < fx) d.width = fx;
if (d.height < fy) d.height = fy;
int newsx = d.width / fx;
int newsy = d.height / fy;
y1 = 0;
y2 = newsy-1;
Char newChars[] = new Char[newsx*(newsy+scrollBack)];
int sy2 = sy + scrollBack;
int newsy2 = newsy + scrollBack;
if (newsy2 > sy2) {
for(int y=0;y<sy2;y++) {
if (newsx > sx) {
for(int x=0;x<sx;x++) newChars[y * newsx + x] = chars[y * sx + x];
for(int x=sx;x<newsx;x++) newChars[y * newsx + x] = new Char();
} else {
for(int x=0;x<newsx;x++) newChars[y * newsx + x] = chars[y * sx + x];
}
}
for(int y=sy2;y<newsy2;y++) {
for(int x=0;x<newsx;x++) newChars[y * newsx + x] = new Char();
}
} else {
for(int y=0;y<newsy2;y++) {
if (newsx > sx) {
for(int x=0;x<sx;x++) newChars[y * newsx + x] = chars[y * sx + x];
for(int x=sx;x<newsx;x++) newChars[y * newsx + x] = new Char();
} else {
for(int x=0;x<newsx;x++) newChars[y * newsx + x] = chars[y * sx + x];
}
}
}
synchronized(lock) {
sx = newsx;
sy = newsy;
if (channel != null) {
((ChannelShell)channel).setPtyType(Settings.settings.termType, sx, sy, sx * 8, sy * 8);
}
if (sd.protocol.equals("local")) {
pty_setsize();
}
if (cx >= sx) cx = sx-1;
if (cy >= sy) cy = sy-1;
chars = newChars;
System.gc();
}
setPreferredSize();
revalidate(); //must call this after resizing
signalRepaint(true);
}
public void changeScrollBack(int newSize) {
Char newChars[] = new Char[sx*(sy+newSize)];
int diff, pos;
if (newSize > scrollBack) {
diff = newSize - scrollBack;
for(int y=0;y<diff;y++) {for(int x=0;x<sx;x++) newChars[y * sx + x] = new Char();}
pos = 0;
for(int y=diff;y<(sy + newSize);y++) {
for(int x=0;x<sx;x++) {
newChars[y * sx + x] = chars[pos * sx + x];
}
pos++;
if (pos == sy + scrollBack) pos = 0;
}
} else {
diff = scrollBack - newSize;
pos = diff;
if (pos >= sy + scrollBack) pos -= sy + scrollBack;
for(int y=0;y<(sy + newSize);y++) {
for(int x=0;x<sx;x++) {
newChars[y * sx + x] = chars[pos * sx + x];
}
pos++;
if (pos == sy + scrollBack) pos = 0;
}
}
synchronized(lock) {
scrollBack = newSize;
chars = newChars;
}
setPreferredSize();
revalidate(); //must call this after resizing
signalRepaint(true);
}
public void setForeColor(int newClr) {
foreColor = new Color(newClr);
}
public void setBackColor(int newClr) {
backColor = new Color(newClr);
}
public void setForeColor(Color newClr) {
foreColor = newClr;
}
public void setBackColor(Color newClr) {
backColor = newClr;
}
public void setBlinker(boolean state) {
blinker = state;
}
public void setReverse(boolean state) {
reverse = state;
}
public Color getForeColor() { return foreColor; }
public Color getBackColor() { return backColor; }
public void repaint(boolean showCursor) {
if (showCursor) scrollRectToVisible(new Rectangle(0,fy * scrollBack,fx * sx, fy * (scrollBack + sy)));
repaint();
}
public void paintComponent(Graphics g) {
if (!ready) {
if (!init) init();
return;
}
synchronized(lock) {
paintComponentLocked(g);
}
}
private JFImage img = new JFImage(); //double buffering image for paint
public void paintComponentLocked(Graphics gc) {
Rectangle r = gc.getClipBounds();
if (img.getWidth() != r.width || img.getHeight() != r.height) {
img.setImageSize(r.width, r.height);
}
img.fill(0,0,r.width,r.height,Settings.settings.backColor.getRGB());
Graphics g = img.getGraphics();
g.setFont(Settings.settings.fnt);
int startx, starty; //char
int endx, endy; //char
int offx, offy; //offset
startx = r.x / fx;
offx = r.x % fx;
endx = (r.x + r.width) / fx + 1;
if (endx > sx) endx = sx;
starty = r.y / fy;
offy = r.y % fy;
endy = (r.y + r.height) / fy + 1;
if (endy > sy + scrollBack) endy = sy + scrollBack;
char ch;
for(int y = starty;y < endy;y++) {
for(int x = startx;x < endx;x++) {
int p = y * sx + x;
if ((x == cx) && (y == cy + scrollBack) && (cursorShown)) {
//draw Cursor
g.setColor(Settings.settings.cursorColor);
} else {
//normal background
if (((p >= selectStart) && (p <= selectEnd)) || ((p >= selectEnd) && (p <= selectStart) && (selectEnd > 0))) {
g.setColor(Settings.settings.selectColor);
} else {
g.setColor(chars[p].bc);
}
}
g.fillRect((x - startx) * fx - offx,(y - starty) * fy - offy,fx,fy);
if ((blinkerShown) && (chars[p].blink))
g.setColor(chars[p].bc);
else
g.setColor(chars[p].fc);
ch = chars[p].ch;
if (ch != 0) g.drawString("" + ch, (x - startx) * fx - offx,(y+1-starty) * fy - descent - offy);
}
if ((y == scrollBack) && (scrollBack > 0)) {
g.setColor(Color.RED);
g.drawLine(0 - offx, (y - starty) * fy - 2 - offy, (endx - startx) * fx - 1 - offx, (y - starty) * fy - 2 - offy);
}
}
gc.drawImage(img.getImage(), r.x, r.y, null);
}
public void clrscr() {
for(int pos=0;pos<sx * (sy+scrollBack);pos++) {
chars[pos].ch = 0;
chars[pos].fc = foreColor;
chars[pos].bc = backColor;
chars[pos].blink = false;
}
cx = 0;
cy = 0;
signalRepaint(true);
if (sd.protocol.equals("local")) {
pty_setsize(); //test
}
}
public void print(String txt) {
print(txt.toCharArray(), txt.length());
}
public void print(char buf[], int buflen) {
for(int a=0;a<buflen;a++) {
if (script != null) script.input(buf[a], this);
switch (buf[a]) {
case 127:
case 8:
decPosX();
break;
case 9:
int ts = (getx()-1) % Settings.settings.tabStops;
for(int t=0;t<Settings.settings.tabStops - ts;t++) {
if (eol) incPosX();
// setChar(cx+1, cy+1, ' '); //don't do that
incPosX();
}
break;
case 10: //LF
incPosY();
break;
case 13: //CR
gotoPos(1, gety());
break;
default:
if ((buf[a] < 32) && (buf[a] >= 0)) break;
if (eol) incPosX();
setChar(cx+1, cy+1, buf[a]);
incPosX();
break;
}
}
signalRepaint(true);
}
public void print(char ch) {
char x[] = new char[1];
x[0] = ch;
print(x, 1);
}
/** Sets a char in buffer. Uses 1,1 based coords. */
public void setChar(int cx, int cy, char ch) {
cx--;
cy--;
int pos = (cy+scrollBack) * sx + cx;
chars[pos].ch = ch;
if (reverse) {
chars[pos].fc = backColor;
chars[pos].bc = foreColor;
} else {
chars[pos].fc = foreColor;
chars[pos].bc = backColor;
}
chars[pos].blink = blinker;
}
private void decPosX() {
if (cx > 0) {
eol = false;
cx--;
} else {
cx = sx-1;
decPosY();
eol = true;
}
}
private void decPosY() {
if (cy > 0) cy--;
}
private void incPosX() {
if (eol) {
if (!autowrap) return;
cx = 0;
incPosY();
eol = false;
} else {
if (cx < (sx-1)) {
cx++;
} else {
eol = true;
}
}
}
private void incPosY() {
if (cy < y2)
cy++;
else
scrollUp(1);
}
public void setAutoWrap(boolean state) {
autowrap = state;
}
public int getx() {return cx + 1;}
public int gety() {return cy + 1;}
public void gotoPos(int x,int y) {
cx = x-1;
if (cx < 0) cx = 0;
if (cx >= sx) cx = sx-1;
cy = y-1;
if (cy < 0) cy = 0;
if (cy >= sy) cy = sy-1;
eol = false;
}
public int gety1() {return y1 + 1;}
public int gety2() {return y2 + 1;}
public void sety1(int v) {y1 = v-1;}
public void sety2(int v) {y2 = v-1;}
public void scrollUp(int cnt) {
while (cnt > 0) {
if (y1==0)
for(int p=0;p<sx * (y2+1 + scrollBack-1);p++) chars[p] = chars[p + sx];
else
for(int p=sx * (y1 + scrollBack);p<sx * (y2+1 + scrollBack-1);p++) chars[p] = chars[p + sx];
for(int p=0;p<sx;p++) chars[p + (sx * (y2+1 + scrollBack - 1))] = new Char(foreColor, backColor, blinker);
selectStart = selectEnd = -1;
cnt--;
}
}
public void scrollDown(int cnt) {
while (cnt > 0) {
for(int p=sx * (y2+1 + scrollBack)-1;p>=sx * (y1 + scrollBack+1);p--) chars[p] = chars[p - sx];
for(int p=0;p<sx;p++) chars[p + (sx * (y1 + scrollBack))] = new Char(foreColor, backColor, blinker);
selectStart = selectEnd = -1;
cnt--;
}
}
public void delete() {
for(int p=cx;p<sx-1;p++) chars[(cy+scrollBack) * sx + p] = chars[(cy+scrollBack) * sx + p + 1];
chars[(cy+scrollBack) * sx + sx-1] = new Char(foreColor, backColor, blinker);
}
public void insert() {
for(int p=sx-2;p>=cx;p--) chars[(cy+scrollBack) * sx + p + 1] = chars[(cy+scrollBack) * sx + p];
chars[(cy+scrollBack) * sx + cx] = new Char(foreColor, backColor, blinker);
}
public void close() {
//this method is overloaded in TermApp to also close the tab
synchronized(reader) {
closed = true;
connected = false;
connecting = false;
}
signalRepaint(false); //allow render thread to exit
signalReconnect(); //allow reader thread to exit (if connection failed)
try {if (pty != null) {pty.close(); pty = null;}} catch(Exception e) {}
try {if (wincom != null) {wincom.close(); wincom = null;}} catch(Exception e) {}
try {if (lnxcom != null) {lnxcom.close(); lnxcom = null;}} catch(Exception e) {}
try {if (session != null) {session.disconnect(); session = null;}} catch(Exception e) {}
try {if (out != null) {out.close(); out = null;}} catch(Exception e) {}
try {if (in != null) {in.close(); in = null;}} catch(Exception e) {}
try {if (s != null) {s.close(); s = null;}} catch(Exception e) {}
if (timer != null) {timer.cancel(); timer = null;}
}
//these methods are overloaded to allow such functionality
public void nextTab() {System.out.println("nextTab");}
public void prevTab() {System.out.println("prevTab");}
public void setTab(int idx) {System.out.println("setTab" + idx);}
public void setName(String str) {}
/** This thread handles the actual setSiteDetailsing and reading the input.*/
private class Reader extends Thread {
public void run() {
while (!closed) {
try {
connecting = true;
input("Connecting...");
signalRepaint(true); //show cursor
if (doConnect() == false) {
input("\r\nConnection failed! Press any key to retry...");
signalRepaint(true); //show cursor
failed = true;
synchronized(reader) {
if (closed) break;
try {reader.wait();} catch (Exception e) {}
}
input("\r\n");
continue;
}
connected = true;
connecting = false;
input("" + ESC + "[2J"); //clrscr
//keep reading in until it's disconnected
byte buf[] = new byte[1024];
int buflen;
while (connected) {
buflen = in.read(buf);
if (buflen == -1) throw new Exception("read error");
if (buflen > 0) input(byte2char(buf, buflen), buflen);
}
} catch (Exception e) {
JFLog.log(e);
if (!closed) {
close();
}
}
}
JFLog.log("Reader thread done");
}
}
public void signalReconnect() {
synchronized(reader) { reader.notify(); }
}
/** This thread handles requesting screen repaints.*/
private class Render extends Thread {
public volatile boolean findCursor = true;
public volatile boolean draw = false;
public void run() {
while (!closed) {
draw = false;
repaint(findCursor);
synchronized(this) {
if (draw) continue;
try{wait();} catch(Exception e) {}
}
}
JFLog.log("Render thread done");
}
}
public void signalRepaint(boolean findScreen) {
if (render == null) return;
synchronized(render) {
render.findCursor = findScreen;
render.draw = true;
render.notify();
}
}
public void logFile() {
if (fos == null) {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.setMultiSelectionEnabled(false);
if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
fos = JF.filecreate(chooser.getSelectedFile().getAbsolutePath());
if (fos != null) setName(sd.name + "*");
}
} else {
fos = null;
setName(sd.name);
}
}
public void copy() {
if ((selectStart == -1) || (selectEnd == -1)) return; //nothing to copy
try {
StringBuilder str = new StringBuilder();
if (selectStart > selectEnd) {
int tmp = selectStart;
selectStart = selectEnd;
selectEnd = tmp;
}
boolean eol = false;
for(int a=selectStart;a<=selectEnd;a++) {
if (chars[a].ch != 0) {
str.append(chars[a].ch);
if (eol) eol = false;
if (a % sx == sx-1) str.append("\n");
} else {
if (!eol) {
eol = true;
str.append("\n");
}
}
}
StringSelection ss = new StringSelection(str.toString());
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
if (cb == null) return;
cb.setContents(ss, ss);
} catch (Exception e) {}
}
public void paste() {
if (!connected) return;
try {
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
String str = (String)cb.getContents(null).getTransferData(DataFlavor.stringFlavor);
if (str == null) return;
output(str.replaceAll("\r", "\n").toCharArray());
} catch (Exception e) {
JFLog.log(e);
}
signalRepaint(true);
}
public void setSiteDetails(SiteDetails sd) {
this.sd = sd;
}
private boolean doConnect() {
if (sd.protocol.equals("com")) return connectCom(sd);
if (sd.protocol.equals("local")) return connectLocal(sd);
if (sd.protocol.equals("telnet")) return connectTelnet(sd);
if (sd.protocol.equals("ssh")) return connectSSH(parent, sd);
if (sd.protocol.equals("ssl")) return connectSSL(sd);
return false;
}
private void sendTT() {
//trigger a request for TT ???
input(new char[] {Telnet.IAC, Telnet.SB, Telnet.TO_TT, Telnet.IAC, Telnet.SE}, 5);
}
private void pty_setsize() {
if (pty == null) return;
pty.setSize(sx, sy);
}
private WinCom wincom;
private LnxCom lnxcom;
private boolean connectCom(SiteDetails sd) {
try {
if (!Settings.hasComm) throw new Exception("no com support");
String f[] = sd.host.split(","); //com1,56000
if (JF.isWindows()) {
wincom = WinCom.open(f[0], JF.atoi(f[1]));
if (wincom == null) return false;
in = new InputStream() {
public int read() throws IOException {
byte data[] = new byte[1];
int read = 0;
do {
read = wincom.read(data);
} while (read != 1);
return data[0];
}
public int read(byte buf[]) throws IOException {
int read;
do {
read = wincom.read(buf);
} while (read <= 0);
return read;
}
};
out = new OutputStream() {
public void write(int b) throws IOException {
wincom.write(new byte[] {(byte)b});
}
public void write(byte buf[]) throws IOException {
wincom.write(buf);
}
};
} else {
lnxcom = LnxCom.open(f[0], JF.atoi(f[1]));
if (lnxcom == null) return false;
in = new InputStream() {
public int read() throws IOException {
byte data[] = new byte[1];
int read;
do {
read = lnxcom.read(data);
} while (read <= 0);
return data[0];
}
public int read(byte buf[]) throws IOException {
int read;
do {
read = lnxcom.read(buf);
} while (read <= 0);
return read;
}
};
out = new OutputStream() {
public void write(int b) throws IOException {
lnxcom.write(new byte[] {(byte)b});
}
public void write(byte buf[]) throws IOException {
lnxcom.write(buf);
}
};
}
return true;
} catch (Throwable t) {
if (!closed) input(t.toString());
return false;
}
}
private boolean connectLocal(SiteDetails sd) {
try {
pty = LnxPty.exec(Settings.settings.termApp
, new String[] {Settings.settings.termApp, "-i", "-l", null}
, LnxPty.makeEnvironment(new String[] {"TERM=" + Settings.settings.termType}));
if (pty == null) throw new Exception("pty failed");
in = new InputStream() {
public int read() {return -1;}
public int read(byte buf[]) {
return pty.read(buf);
}
};
out = new OutputStream() {
public void write(int x) {};
public void write(byte buf[]) {
pty.write(buf);
}
};
return true;
} catch (Exception e) {
JFLog.log(e);
if (!closed) input(e.toString());
}
return false;
}
private boolean connectTelnet(SiteDetails sd) {
try {
s = new Socket(sd.host, JF.atoi(sd.port));
in = s.getInputStream();
out = s.getOutputStream();
return true;
} catch (Exception e) {
if (!closed) input(e.toString());
}
return false;
}
private int detectX11port() {
int port = 6000;
/* Socket tmp;
for(int a=6000;a<6009;a++) {
try {
tmp = new Socket("localhost", a);
port = a;
tmp.close();
break;
} catch (Exception e) {}
}*/
return port;
}
private boolean connectSSH(Frame parent, SiteDetails sd) {
try{
if (sd.sshKey.length() == 0) {
if (sd.password.length() == 0) sd.password = GetPassword.getPassword(parent);
if (sd.password == null) return false;
}
Object pipes[];
JSch jsch=new JSch();
if (!applet) jsch.setKnownHosts(JF.getUserPath() + "/.jfterm.ssh");
session=jsch.getSession(sd.username, sd.host, JF.atoi(sd.port));
if (sd.x11) {
session.setX11Host("127.0.0.1");
session.setX11Port(detectX11port());
}
if (sd.sshKey.length() == 0) {
session.setPassword(sd.password);
UserInfo ui=new SSHUserInfo(sd.password);
session.setUserInfo(ui);
} else {
JFLog.log("using key:" + sd.sshKey);
jsch.addIdentity(sd.sshKey);
java.util.Properties config = new java.util.Properties ();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
}
session.connect(30000);
channel=session.openChannel("shell");
if (sd.x11) {
channel.setXForwarding(true);
} else {
// Enable agent-forwarding.
((ChannelShell)channel).setAgentForwarding(true);
}
pipes = createPipes();
if (pipes == null) return false;
out = (OutputStream)pipes[1];
channel.setInputStream((InputStream)pipes[0]);
pipes = createPipes();
if (pipes == null) return false;
in = (InputStream)pipes[0];
channel.setOutputStream((OutputStream)pipes[1]);
((ChannelShell)channel).setPtyType(Settings.settings.termType, sd.sx, sd.sy, sd.sx * 8, sd.sy * 8);
// ((ChannelShell)channel).setEnv(hashMap); //???
/*
java.util.Hashtable env=new java.util.Hashtable();
env.put("LANG", "ja_JP.eucJP");
((ChannelShell)channel).setEnv(env);
*/
channel.connect(30000);
return true;
} catch (Exception e) {
if (!closed) input(e.toString());
}
return false;
}
private Object[] createPipes() {
Object[] ret = new Object[2];
try {
ret[0] = new PipedInputStream();
ret[1] = new PipedOutputStream((PipedInputStream)ret[0]);
return ret;
} catch (Exception e) {
return null;
}
}
private static class SSHUserInfo implements UserInfo {
public String password;
public SSHUserInfo(String password) {this.password = password;}
public String getPassword(){
return password;
}
public boolean promptYesNo(String str){
Object[] options={ "yes", "no" };
int foo=JOptionPane.showOptionDialog(null,
str,
"Warning",
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
return foo==0;
}
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return true; }
public boolean promptPassword(String message){ return true; }
public void showMessage(String message){
JOptionPane.showMessageDialog(null, message);
}
}
private boolean connectSSL(SiteDetails sd) {
try {
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
}
};
// Let us create the factory where we can set some parameters for the connection
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
// SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); //this method will only work with trusted certs
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) sc.getSocketFactory(); //this method will work with untrusted certs
ssl = (SSLSocket) sslsocketfactory.createSocket(sd.host, JF.atoi(sd.port));
s = (Socket)ssl;
in = s.getInputStream();
out = s.getOutputStream();
return true;
} catch (Exception e) {
if (!closed) input(e.toString());
}
return false;
}
public String toString() {
return "Buffer";
}
//interface KeyListener
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
int keyMods = e.getModifiers();
if (keyMods == KeyEvent.CTRL_MASK) {
switch (keyCode) {
case KeyEvent.VK_A: selectStart = 0; selectEnd = sx * (sy + scrollBack) - 1; break;
case KeyEvent.VK_W: close(); break;
case KeyEvent.VK_C:
case KeyEvent.VK_INSERT: copy(); break;
case KeyEvent.VK_V: paste(); break;
case KeyEvent.VK_TAB: nextTab(); break;
case KeyEvent.VK_HOME:
case KeyEvent.VK_END: e.consume(); break;
}
}
if (keyMods == KeyEvent.SHIFT_MASK) {
switch (keyCode) {
case KeyEvent.VK_INSERT: paste(); break;
}
}
if (keyMods == (KeyEvent.SHIFT_MASK & KeyEvent.CTRL_MASK)) {
switch (keyCode) {
case KeyEvent.VK_TAB: prevTab(); break;
}
}
if (keyMods == KeyEvent.ALT_MASK) {
switch (keyCode) {
case KeyEvent.VK_HOME: clrscr(); break;
case KeyEvent.VK_1: setTab(0); break;
case KeyEvent.VK_2: setTab(1); break;
case KeyEvent.VK_3: setTab(2); break;
case KeyEvent.VK_4: setTab(3); break;
case KeyEvent.VK_5: setTab(4); break;
case KeyEvent.VK_6: setTab(5); break;
case KeyEvent.VK_7: setTab(6); break;
case KeyEvent.VK_8: setTab(7); break;
case KeyEvent.VK_9: setTab(8); break;
case KeyEvent.VK_0: setTab(9); break;
}
}
if (keyMods == 0) {
switch (keyCode) {
case KeyEvent.VK_UP: //arrow keys cause JScrollPane to move
case KeyEvent.VK_DOWN:
case KeyEvent.VK_LEFT:
case KeyEvent.VK_RIGHT:
case KeyEvent.VK_PAGE_UP:
case KeyEvent.VK_PAGE_DOWN:
case KeyEvent.VK_F10: //F10 would open menu
e.consume();
break;
}
}
if (!connected) return;
// System.out.println("keyPressed=" + keyCode); //test
ansi.keyPressed(keyCode, keyMods, this);
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
if (!connected) {
if (failed) {
failed = false;
signalReconnect();
}
return;
}
char key = e.getKeyChar();
if (e.getModifiers() == KeyEvent.CTRL_MASK) {
if ((key == 10) || (key == 13)) {output('\r'); output('\n');}
return;
}
if (e.getModifiers() == KeyEvent.ALT_MASK) return;
if (e.getModifiers() == (KeyEvent.CTRL_MASK | KeyEvent.ALT_MASK)) return;
if (key == 10) key = 13;
if (key == KeyEvent.VK_DELETE) return; //handled in keyPressed
// System.out.println("keyTyped=" + ((int)key)); //test
output(key);
}
//interface MouseListener
public void mouseClicked(MouseEvent e) {
if (e.getButton() == e.BUTTON2) paste();
if (e.getButton() == e.BUTTON1) requestFocus();
}
public void mousePressed(MouseEvent e) {
//start selection process
if (e.getButton() != e.BUTTON1) return;
int x = e.getX();
int y = e.getY();
selectStart = ((y / fy) * sx + (x / fx));
selectEnd = -1;
}
public void mouseReleased(MouseEvent e) {
if (e.getButton() != e.BUTTON1) return;
if (selectStart == -1) return;
int x = e.getX();
int y = e.getY();
selectEnd = ((y / fy) * sx + (x / fx));
if (selectEnd == selectStart) {selectStart = selectEnd = -1;}
signalRepaint(false);
if (selectStart != -1) copy();
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
//interface MouseMotionListener
public void mouseDragged(MouseEvent e) {
if (selectStart == -1) return;
int x = e.getX();
int y = e.getY();
if (x < 0) x = 0;
if (x > sx * fx) x = (sx * fx)-1;
if (y < 0) y = 0;
if (y > (sy + scrollBack) * fy) y = (sy + scrollBack) * fy - 1;
selectEnd = ((y / fy) * sx + (x / fx));
signalRepaint(false);
scrollRectToVisible(new Rectangle(e.getX(), e.getY(), 1, 1));
}
public void mouseMoved(MouseEvent e) {
}
public void timer() {
if (cursorShown) {
if (blinkerShown) blinkerShown = false; else blinkerShown = true;
cursorShown = false;
} else {
cursorShown = true;
}
if (script != null) {
if (script.process(this)) script = null;
}
signalRepaint(false);
}
}