extern crate pcsc;
#[macro_use]
extern crate simple_error;
+#[macro_use]
+extern crate serde_json;
use pcsc::*;
use core::task::{Context, Poll};
*response.status_mut() = StatusCode::BAD_REQUEST;
}
(&Method::POST, "/scard/version/") => {
- *response.body_mut() = Body::from("{\"version\":\"1.3.9.46\"}");
+ let reply = json!({
+ "version": "1.3.9.46"
+ });
+ *response.body_mut() = Body::from(reply.to_string());
}
(&Method::POST, "/scard/list/") => {
return unwrap_result_into_response(get_readers(), response);
}
(&Method::POST, "/scard/disconnect/") => {
- *response.body_mut() = Body::from("{\"errorcode\":0,\"errordetail\":0,\"apduresponses\":null}");
+ *response.body_mut() = Body::from("");
println!("Disconnecting from card.");
let mut card = GLOBAL_CARD.lock().unwrap();
*card = None;
}
(&Method::POST, "/scard/getref/") => {
- let mut reply = "{\"data\":\"".to_owned();
-
// This is seemingly so that the PIN isn't sent “in the clear”, over TLS, to localhost.
// We send a key (in the form of 16 bytes) with an ID (the reference),
// the first four bytes are XORed with the next four bytes, and the PIN
// be a noop. (The reference is a handle to the key, in case we've given
// out multiple ones. We set it to some dummy value.)
let random_bytes = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
- reply += &hex::encode(random_bytes).to_ascii_uppercase();
- reply += "\",\"ref\":195948557}";
- println!("Reply: {}", reply);
- *response.body_mut() = Body::from(reply);
+ let reply = json!({
+ "data": &hex::encode(random_bytes).to_ascii_uppercase(),
+ "ref": 195948557
+ });
+ println!("Reply: {}", reply.to_string());
+ *response.body_mut() = Body::from(reply.to_string());
}
// Catch-all 404.
_ => {
// Establish a PC/SC context.
let ctx = pcsc::Context::establish(Scope::User)?;
- let mut reply : String = "{\"errorcode\":0,\"errordetail\":0,\"readers\":[".to_owned();
-
// List available readers.
let mut readers_buf = [0; 2048];
- let mut reader_json : Vec<String> = Vec::new();
+ let mut reader_json : Vec<serde_json::Value> = Vec::new();
for r in ctx.list_readers(&mut readers_buf)? {
// Check the card status by connecting to it.
let status = match ctx.connect(r, ShareMode::Shared, Protocols::ANY) {
- Ok(_) => "302",
- Err(_) => "303"
+ Ok(_) => 302,
+ Err(_) => 303
};
- let mut json = "{\"cardstatus\":".to_owned();
- json += status;
- json += ",\"name\":\"";
- json += r.to_str()?;
- json += "\"}";
- reader_json.push(json);
+ reader_json.push(json!({
+ "cardstatus": status,
+ "name": r.to_str()?
+ }));
}
- reply += &reader_json.join(",");
- reply += "]}";
- println!("Reply: {}", reply);
- return Ok(Body::from(reply));
+ let reply = json!({
+ "errorcode": 0,
+ "errordetail": 0,
+ "readers": reader_json
+ });
+ println!("Reply: {}", reply.to_string());
+ return Ok(Body::from(reply.to_string()));
}
fn transmit_apdu(card: &Card, mut apdu: &[u8]) -> Result<String, Box<dyn std::error::Error>> {
};
}
- let mut reply : String = "{\"errorcode\":0,\"errordetail\":0,\"apduresponses\":[".to_owned();
-
- let mut response_json : Vec<String> = Vec::new();
+ let mut response_json : Vec<serde_json::Value> = Vec::new();
for apdu in apdus {
- let mut reply : String = "{\"apdu\":\"".to_owned();
- reply += &transmit_apdu(card.as_mut().unwrap(), &apdu)?;
- reply += "\"}";
- response_json.push(reply);
+ let reply = &transmit_apdu(card.as_mut().unwrap(), &apdu)?;
+ response_json.push(json!({
+ "apdu": reply
+ }));
}
-
- reply += &response_json.join(",");
- reply += "]}";
- println!("Reply: {}", reply);
- return Ok(Body::from(reply));
+ let reply = json!({
+ "errorcode": 0,
+ "errordetail": 0,
+ "apduresponses": response_json
+ });
+ println!("Reply: {}", reply.to_string());
+ return Ok(Body::from(reply.to_string()));
}