Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve jcappuccino and add options #2

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

# Package Files #
*.jar
!JCappuccino_sebastien.jar
*.war
*.ear

Expand Down Expand Up @@ -42,4 +43,6 @@ local.properties
.buildpath

# TeXlipse plugin
.texlipse
.texlipse

keystore.jks
28 changes: 26 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
jcappuccino
===========

Standalone interface for access to hardware. Currently supports Card Readers using PC/SC.
Standalone interface for access to hardware using Websockets on TCP (default port : 9191).

Currently supports Card Readers using PC/SC (with Java `javax.smartcardio` library).

First of all, check that `pcscd` is running and detects your card reader (eventually run `pcscd -df` to see its output).

Run the jcappuccino using :
### Usages :

Run the jcappuccino (Mac OS or generic Linux/Unix) :

$ java -jar jcappuccino.jar

Run the jcappuccino (Ubuntu from version 14.04 on 64bit, due to a JVM bug) :

$ java -Dsun.security.smartcardio.library=/lib/x86_64-linux-gnu/libpcsclite.so.1 -jar jcappuccino.jar

### Options :

| Option | Description |
| ------------------------ |:--------------------------------------------------------------------------------:|
| `ws-port=9191` | specify port to launch ws server (default: 9191) |
| `wss-port=9192` | launch a wss server on 9192 port, `ws-port` and `wss-port` should be different |
| `no-reader-simulation` | returning error message instead of simulate a card reader |
| `card-id` | set the simulated card ID (default: 123456AB) |
| `limit-localhost` | limit access to 127.0.0.1 |

Exemple :

$ java -Dwss-port=9192 -Dno-reader-simulation -jar jcappuccino.jar

Be careful to place all `-D` options before the `-jar` option.
Binary file added build/JCappuccino_sebastien.jar
Binary file not shown.
63 changes: 58 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
<modelVersion>4.0.0</modelVersion>
<groupId>fr.utc.assos.payutc</groupId>
<artifactId>jcappuccino</artifactId>
<version>0.1-SNAPSHOT</version>
<version>0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>JCappuccino Giga Teuf</name>

<repositories>
<repository>
<id>org.eclipse.jetty</id>
<name>Jetty Eclipse Repository</name>
<url>http://mvnrepository.com/artifact/org.eclipse.jetty</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
Expand All @@ -32,7 +32,7 @@
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
Expand All @@ -46,6 +46,59 @@
<mainClass>fr.utc.assos.payutc.JCappuccino</mainClass>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fr.utc.assos.payutc.JCappuccino</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached><!-- Prevents warning in Netbeans -->
<finalName>jcappuccino</finalName>
<filters>
<filter>
<artifact>org.eclipse.*:*</artifact>
<excludes>
<exclude>about.html</exclude>
<exclude>jetty-dir.css</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>fr.utc.assos.payutc.JCappuccino</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
</project>
37 changes: 0 additions & 37 deletions src/fr/utc/assos/payutc/JCappuccino.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import javax.smartcardio.Card;
Expand All @@ -15,85 +16,116 @@

public class CardReader {
private CardTerminal mReader;
private EventSocket mSocket;
private static List<EventSocket> mSockets = new ArrayList<EventSocket>();

private byte[] mApduArray = {
(byte) 0xFF,
(byte) 0xCA,
(byte) 0x00,
(byte) 0x00,
(byte) 0x00
};

private CardThread mThread;

public CardReader(EventSocket socket) {
public CardReader(Boolean simulateReader) {
this(simulateReader, null);
}

public CardReader(Boolean simulateReader, String cardId) {
try {
// Store pointer to socket
mSocket = socket;


// Get the list of readers
TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals = factory.terminals().list();
System.out.println("Liste des lecteurs détectés : " + terminals);

// Choose the first reader
if(terminals.size() > 0){
mReader = terminals.get(0);
System.out.println("Connecté au premier lecteur.");

// Start loop in a thread
mThread = new CardThread();
new Thread(mThread).start();
}
else {
System.out.println("Aucun lecteur détecté, passage en mode simulation");
mThread = new FakeCardThread();
new Thread(mThread).start();
noReaderAction(simulateReader, cardId);
}
} catch (CardException e) {
System.out.println("Impossible de récupérer la liste de lecteurs, passage en mode simulation");
mThread = new FakeCardThread();
new Thread(mThread).start();
System.out.println("Impossible de récupérer la liste de lecteurs");
noReaderAction(simulateReader, cardId);
}
}

public void close() {
// Tell the loop to stop
mThread.stop();
}


private void noReaderAction(Boolean simulateReader) {
noReaderAction(simulateReader, null);
}

private void noReaderAction(Boolean simulateReader, String cardId) {
if (simulateReader) {
System.out.println("Passage en mode simulation");
mThread = new FakeCardThread(cardId);
new Thread(mThread).start();
} else {
System.out.println("Envoie d'un message 'badgeuseNotFound'");
dispatch("badgeuseNotFound", "1");
}
}

public static boolean addEventSocket(EventSocket e) {
System.out.println("Added EventSocket callback: "+e.toString()+" (Count="+(mSockets.size()+1)+")");
return mSockets.add(e);
}

public static boolean removeEventSocket(EventSocket e) {
System.out.println("Removed EventSocket callback: "+e.toString()+" (Count="+(mSockets.size()-1)+")");
return mSockets.remove(e);
}

public void dispatch(String message, String value) {
for (EventSocket mSocket : mSockets) {
mSocket.sendData(message + ":" + value);
}
}

private class CardThread implements Runnable {
private volatile boolean mRun = true;

public void stop() {
mRun = false;
}

public void run() {
CommandAPDU GetData = new CommandAPDU(mApduArray);
while(mRun){
try {
if(mReader.waitForCardPresent(500)) {
System.out.println("Carte détectée.");

// Connect to the card currently in the reader
Card card = mReader.connect("*");

// Exchange APDUs with the card
CardChannel channel = card.getBasicChannel();
ResponseAPDU CardApduResponse = channel.transmit(GetData);

// Disconnect
card.disconnect(true);

System.out.println("Carte lue");

String carduid = getHexString(CardApduResponse.getData());

System.out.println("cardInserted:" + carduid);
mSocket.sendData("cardInserted:" + carduid);
dispatch("cardInserted", carduid);

mReader.waitForCardAbsent(0);
}
} catch (CardException e) {
Expand All @@ -102,35 +134,37 @@ public void run() {
}
}
}

private class FakeCardThread extends CardThread {
private volatile boolean mRun = true;

private String cardId;

public FakeCardThread(String cardId) {
this.cardId = cardId;
}

@Override
public void stop() {
mRun = false;
}

@Override
public void run() {
try {
String cardId = "123456AB";
while(mRun){
System.out.println("Appuyer sur entrée pour envoyer " + cardId.toString() + "...");
BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
buffer.readLine();
if(mSocket.isConnected()) {
System.out.println("cardInserted:" + cardId.toString());
mSocket.sendData("cardInserted:" + cardId.toString());
}

System.out.println("cardInserted:" + cardId.toString());
dispatch("cardInserted", cardId.toString());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

private String getHexString(byte[] b) {
String result = "";
for (int i=0; i < b.length; i++) {
Expand All @@ -139,4 +173,3 @@ private String getHexString(byte[] b) {
return result.toUpperCase();
}
}

Loading