@Override public void contextDestroyed(ServletContextEvent sce) { TerminalManager terminalManager = (TerminalManager) sce.getServletContext().getAttribute(TerminalManager.class.getName()); terminalManager.shutdown(); }
/** Force disconnection of this terminal bridge. */ public void dispatchDisconnect(boolean immediate) { // We don't need to do this multiple times. synchronized (this) { if (disconnected && !immediate) return; disconnected = true; } // Cancel any pending prompts. promptHelper.cancelPrompt(); // disconnection request hangs if we havent really connected to a host yet // temporary fix is to just spawn disconnection into a thread Thread disconnectThread = new Thread( new Runnable() { public void run() { if (transport != null && transport.isConnected()) transport.close(); } }); disconnectThread.setName("Disconnect"); disconnectThread.start(); if (immediate) { awaitingClose = true; if (disconnectListener != null) disconnectListener.onDisconnected(TerminalBridge.this); } else { { final String line = manager.res.getString(R.string.alert_disconnect_msg); ((vt320) buffer).putString("\r\n" + line + "\r\n"); } if (host.getStayConnected()) { manager.requestReconnect(this); return; } Thread disconnectPromptThread = new Thread( new Runnable() { public void run() { Boolean result = promptHelper.requestBooleanPrompt( null, manager.res.getString(R.string.prompt_host_disconnected)); if (result == null || result.booleanValue()) { awaitingClose = true; // Tell the TerminalManager that we can be destroyed now. if (disconnectListener != null) disconnectListener.onDisconnected(TerminalBridge.this); } } }); disconnectPromptThread.setName("DisconnectPrompt"); disconnectPromptThread.setDaemon(true); disconnectPromptThread.start(); } }
@Override public void run() { while (!requestStopFlag) { List<ClientTerminal> list = TerminalManager.getInstance().queueTerminal(); log.info(" Scan client terminals size: " + list.size()); for (ClientTerminal ter : list) { boolean triggerTimeout = false; boolean remove = false; synchronized (ter) { if (ter.isTimeout()) { if ((System.currentTimeMillis() - ter.getTimeout()) / 1000 > 20) { triggerTimeout = true; remove = true; } } else { if ((System.currentTimeMillis() - ter.lastUpdate) / 1000 > 40) { triggerTimeout = true; ter.setTimeout(true); } } } if (triggerTimeout) { ter.postEvent(new TimeoutEvent()); } if (remove) { TerminalManager.getInstance().removeTerminal(ter.token); } log.info(" Terminal " + ter + " remove:" + remove + " timeout:" + triggerTimeout + ""); } synchronized (this) { try { wait(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
private static void work(CardTerminal reader, OptionSet args) throws CardException { if (!reader.isCardPresent()) { System.out.println("No card in " + reader.getName()); return; } FileOutputStream o = null; if (args.has(OPT_DUMP)) { try { o = new FileOutputStream((File) args.valueOf(OPT_DUMP)); } catch (FileNotFoundException e) { System.err.println("Can not dump to " + args.valueOf(OPT_DUMP)); } } reader = LoggingCardTerminal.getInstance(reader, o); // This allows to override the protocol for RemoteTerminal as well. final String protocol; if (args.has(OPT_T0)) { protocol = "T=0"; } else if (args.has(OPT_T1)) { protocol = "T=1"; } else { protocol = "*"; } if (args.has(CMD_APDU)) { Card c = null; try { c = reader.connect(protocol); if (args.has(CMD_APDU)) { for (Object s : args.valuesOf(CMD_APDU)) { CommandAPDU a = new CommandAPDU(HexUtils.stringToBin((String) s)); ResponseAPDU r = c.getBasicChannel().transmit(a); if (args.has(OPT_ERROR) && r.getSW() != 0x9000) { System.out.println( "Card returned " + String.format("%04X", r.getSW()) + ", exiting!"); return; } } } } catch (CardException e) { if (TerminalManager.getExceptionMessage(e) != null) { System.out.println("PC/SC failure: " + TerminalManager.getExceptionMessage(e)); } else { throw e; } } finally { if (c != null) { c.disconnect(true); } } } else if (args.has(OPT_CONNECT)) { String remote = (String) args.valueOf(OPT_CONNECT); JSONMessagePipe transport = null; try { if (remote.startsWith("http://") || remote.startsWith("https://")) { if (args.has(OPT_PINNED)) { transport = HTTPTransport.open( new URL(remote), certFromPEM(((File) args.valueOf(OPT_PINNED)).getPath())); } else { transport = HTTPTransport.open(new URL(remote), null); } } else { transport = SocketTransport.connect(string2socket(remote), null); } // Connect the transport and the terminal CmdlineRemoteTerminal c = new CmdlineRemoteTerminal(transport, reader); c.forceProtocol(protocol); // Run c.run(); } catch (IOException e) { System.err.println("Communication error: " + e.getMessage()); } finally { if (transport != null) transport.close(); } } }
public static void main(String[] argv) throws Exception { OptionSet args = parseOptions(argv); if (args.has(OPT_VERBOSE)) { verbose = true; // Set up slf4j simple in a way that pleases us System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug"); System.setProperty("org.slf4j.simpleLogger.showThreadName", "true"); System.setProperty("org.slf4j.simpleLogger.showShortLogName", "true"); System.setProperty("org.slf4j.simpleLogger.levelInBrackets", "true"); } else { System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "warn"); } if (args.has(OPT_VERSION)) { String version = "apdu4j " + getVersion(SCTool.class); // Append host information version += "\nRunning on " + System.getProperty("os.name"); version += " " + System.getProperty("os.version"); version += " " + System.getProperty("os.arch"); version += ", Java " + System.getProperty("java.version"); version += " by " + System.getProperty("java.vendor"); System.out.println(version); } if (args.has(OPT_TEST_SERVER)) { // TODO: have the possibility to run SocketServer as well? RemoteTerminalServer srv = new RemoteTerminalServer(TestServer.class); srv.start(string2socket((String) args.valueOf(OPT_TEST_SERVER))); System.console().readLine("Press enter to stop\n"); srv.stop(1); System.exit(0); } // List TerminalFactory providers if (args.has(OPT_PROVIDERS)) { Provider providers[] = Security.getProviders("TerminalFactory.PC/SC"); if (providers != null) { System.out.println("Existing TerminalFactory providers:"); for (Provider p : providers) { System.out.println(p.getName()); } } } // Fix properties on non-windows platforms TerminalManager.fixPlatformPaths(); // Only applies to SunPCSC if (args.has(OPT_NO_GET_RESPONSE)) { System.setProperty("sun.security.smartcardio.t0GetResponse", "false"); System.setProperty("sun.security.smartcardio.t1GetResponse", "false"); } // Override PC/SC library path if (args.has(OPT_LIB)) { System.setProperty("sun.security.smartcardio.library", (String) args.valueOf(OPT_LIB)); } TerminalFactory tf = null; CardTerminals terminals = null; try { // Get a terminal factory if (args.has(OPT_PROVIDER)) { String pn = (String) args.valueOf(OPT_PROVIDER); String pt = (String) args.valueOf(OPT_PROVIDER_TYPE); tf = loadFactory(pn, pt); } else if (args.has(OPT_SUN)) { tf = loadFactory(SUN_CLASS, null); } else if (args.has(OPT_JNA)) { tf = loadFactory(JNA_CLASS, null); } else { tf = TerminalFactory.getDefault(); } if (verbose) { System.out.println( "# Using " + tf.getProvider().getClass().getCanonicalName() + " - " + tf.getProvider()); if (System.getProperty(TerminalManager.lib_prop) != null) { System.out.println( "# " + TerminalManager.lib_prop + "=" + System.getProperty(TerminalManager.lib_prop)); } } // Get all terminals terminals = tf.terminals(); } catch (Exception e) { // XXX: we catch generic Exception here to avoid importing JNA. // Try to get a meaningful message String msg = TerminalManager.getExceptionMessage(e); if (msg == null) msg = e.getMessage(); System.out.println("No readers: " + msg); System.exit(1); } // Terminals to work on List<CardTerminal> do_readers = new ArrayList<CardTerminal>(); try { // List Terminals if (args.has(CMD_LIST)) { List<CardTerminal> terms = terminals.list(); if (verbose) { System.out.println( "# Found " + terms.size() + " terminal" + (terms.size() == 1 ? "" : "s")); } if (terms.size() == 0) { System.err.println("No readers found"); System.exit(1); } for (CardTerminal t : terms) { String vmd = " "; try (PinPadTerminal pp = new PinPadTerminal(t)) { pp.probe(); // Verify, Modify, Display if (verbose) { vmd += "["; vmd += pp.canVerify() ? "V" : " "; vmd += pp.canModify() ? "M" : " "; vmd += pp.hasDisplay() ? "D" : " "; vmd += "] "; } } catch (CardException e) { if (verbose) { System.err.println("Could not probe PinPad: " + e.getMessage()); } } System.out.println((t.isCardPresent() ? "[*]" : "[ ]") + vmd + t.getName()); if (args.has(OPT_VERBOSE) && t.isCardPresent()) { Card c = t.connect("DIRECT"); String atr = HexUtils.encodeHexString(c.getATR().getBytes()).toUpperCase(); c.disconnect(false); System.out.println(" " + atr); if (args.has(OPT_WEB)) { String url = "http://smartcard-atr.appspot.com/parse?ATR=" + atr; if (Desktop.isDesktopSupported()) { Desktop.getDesktop().browse(new URI(url + "&from=apdu4j")); } else { System.out.println(" " + url); } } } } } // Select terminals to work on if (args.has(OPT_READER)) { String reader = (String) args.valueOf(OPT_READER); CardTerminal t = terminals.getTerminal(reader); if (t == null) { System.err.println("Reader \"" + reader + "\" not found."); System.exit(1); } do_readers = Arrays.asList(t); } else { do_readers = terminals.list(State.CARD_PRESENT); if (do_readers.size() > 1 && !args.hasArgument(OPT_ALL)) { System.err.println("More than one reader with a card found."); System.err.println("Run with --" + OPT_ALL + " to work with all found cards"); System.exit(1); } else if (do_readers.size() == 0 && !args.has(CMD_LIST)) { // But if there is a single reader, wait for a card insertion List<CardTerminal> empty = terminals.list(State.CARD_ABSENT); if (empty.size() == 1 && args.has(OPT_WAIT)) { CardTerminal rdr = empty.get(0); System.out.println("Please enter a card into " + rdr.getName()); if (!empty.get(0).waitForCardPresent(30000)) { System.out.println("Timeout."); } else { do_readers = Arrays.asList(rdr); } } else { System.err.println("No reader with a card found!"); System.exit(1); } } } } catch (CardException e) { System.out.println("Could not list readers: " + TerminalManager.getExceptionMessage(e)); e.printStackTrace(); } for (CardTerminal t : do_readers) { work(t, args); } }
/** * Something changed in our parent {@link TerminalView}, maybe it's a new parent, or maybe it's an * updated font size. We should recalculate terminal size information and request a PTY resize. */ public final synchronized void parentChanged(TerminalView parent) { if (manager != null && !manager.isResizeAllowed()) { Log.d(TAG, "Resize is not allowed now"); return; } this.parent = parent; final int width = parent.getWidth(); final int height = parent.getHeight(); // Something has gone wrong with our layout; we're 0 width or height! if (width <= 0 || height <= 0) return; clipboard = (ClipboardManager) parent.getContext().getSystemService(Context.CLIPBOARD_SERVICE); keyListener.setClipboardManager(clipboard); if (!forcedSize) { // recalculate buffer size int newColumns, newRows; newColumns = width / charWidth; newRows = height / charHeight; // If nothing has changed in the terminal dimensions and not an intial // draw then don't blow away scroll regions and such. if (newColumns == columns && newRows == rows) return; columns = newColumns; rows = newRows; } // reallocate new bitmap if needed boolean newBitmap = (bitmap == null); if (bitmap != null) newBitmap = (bitmap.getWidth() != width || bitmap.getHeight() != height); if (newBitmap) { discardBitmap(); bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); canvas.setBitmap(bitmap); } // clear out any old buffer information defaultPaint.setColor(Color.BLACK); canvas.drawPaint(defaultPaint); // Stroke the border of the terminal if the size is being forced; if (forcedSize) { int borderX = (columns * charWidth) + 1; int borderY = (rows * charHeight) + 1; defaultPaint.setColor(Color.GRAY); defaultPaint.setStrokeWidth(0.0f); if (width >= borderX) canvas.drawLine(borderX, 0, borderX, borderY + 1, defaultPaint); if (height >= borderY) canvas.drawLine(0, borderY, borderX + 1, borderY, defaultPaint); } try { // request a terminal pty resize synchronized (buffer) { buffer.setScreenSize(columns, rows, true); } if (transport != null) transport.setDimensions(columns, rows, width, height); } catch (Exception e) { Log.e(TAG, "Problem while trying to resize screen or PTY", e); } // redraw local output if we don't have a sesson to receive our resize request if (transport == null) { synchronized (localOutput) { ((vt320) buffer).reset(); for (String line : localOutput) ((vt320) buffer).putString(line); } } // force full redraw with new buffer size fullRedraw = true; redraw(); parent.notifyUser(String.format("%d x %d", columns, rows)); Log.i(TAG, String.format("parentChanged() now width=%d, height=%d", columns, rows)); }
public synchronized void tryScrollVibrate() { manager.tryScrollVibrate(); }
public synchronized void tryKeyVibrate() { manager.tryKeyVibrate(); }
/** * Create new terminal bridge with following parameters. We will immediately launch thread to * start SSH connection and handle any hostkey verification and password authentication. */ public TerminalBridge(final TerminalManager manager, final HostBean host) throws IOException { Typeface type; this.manager = manager; this.host = host; emulation = manager.getEmulation(); scrollback = manager.getScrollback(); // create prompt helper to relay password and hostkey requests up to gui promptHelper = new PromptHelper(this); // create our default paint defaultPaint = new Paint(); defaultPaint.setAntiAlias(true); type = Typeface.createFromAsset(this.manager.res.getAssets(), "UbuntuMono-R.ttf"); defaultPaint.setTypeface(type); defaultPaint.setFakeBoldText(true); // more readable? localOutput = new LinkedList<String>(); fontSizeChangedListeners = new LinkedList<FontSizeChangedListener>(); int hostFontSize = host.getFontSize(); if (hostFontSize <= 0) hostFontSize = DEFAULT_FONT_SIZE; setFontSize(hostFontSize); // create terminal buffer and handle outgoing data // this is probably status reply information buffer = new vt320() { @Override public void debug(String s) { Log.d(TAG, s); } @Override public void write(byte[] b) { try { if (b != null && transport != null) transport.write(b); } catch (IOException e) { Log.e(TAG, "Problem writing outgoing data in vt320() thread", e); } } @Override public void write(int b) { try { if (transport != null) transport.write(b); } catch (IOException e) { Log.e(TAG, "Problem writing outgoing data in vt320() thread", e); } } // We don't use telnet sequences. @Override public void sendTelnetCommand(byte cmd) {} // We don't want remote to resize our window. @Override public void setWindowSize(int c, int r) {} @Override public void beep() { if (parent.isShown()) manager.playBeep(); else manager.sendActivityNotification(host); } }; // Don't keep any scrollback if a session is not being opened. if (host.getWantSession()) buffer.setBufferSize(scrollback); else buffer.setBufferSize(0); resetColors(); buffer.setDisplay(this); selectionArea = new SelectionArea(); keyListener = new TerminalKeyListener(manager, this, buffer, host.getEncoding()); }