smartcard 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +14 -0
- data/LICENSE +22 -0
- data/Manifest +19 -0
- data/README +22 -0
- data/ext/smartcard_pcsc/extconf.rb +23 -4
- data/ext/smartcard_pcsc/pcsc.h +9 -1
- data/ext/smartcard_pcsc/pcsc_card.c +82 -53
- data/ext/smartcard_pcsc/pcsc_constants.c +4 -0
- data/ext/smartcard_pcsc/pcsc_context.c +27 -16
- data/ext/smartcard_pcsc/pcsc_io_request.c +4 -1
- data/ext/smartcard_pcsc/pcsc_multi_strings.c +31 -14
- data/ext/smartcard_pcsc/pcsc_reader_states.c +26 -13
- data/smartcard.gemspec +53 -0
- data/test/test_all.rb +0 -0
- metadata +15 -9
data/CHANGELOG
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
v0.2.0 Added automatic builds
|
2
|
+
Rakefile for auto builds using echoe
|
3
|
+
extconf.rb: hack to fix Windows makefiles
|
4
|
+
|
5
|
+
v0.1.2 Added Windows compatibility
|
6
|
+
*.c: restructured code so VC2005 likes it
|
7
|
+
(variable declarations before function body)
|
8
|
+
docs: license, readme, and what the gem is
|
9
|
+
|
10
|
+
v0.1.1 Added support for Ubuntu 7.10
|
11
|
+
ext/smartcard_pcsc/extconf.rb: better header
|
12
|
+
detection
|
13
|
+
|
14
|
+
v0.1.0 Initial release for OSX Leopard
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2007 Victor Costan
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
22
|
+
|
data/Manifest
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
ext/smartcard_pcsc/extconf.rb
|
3
|
+
ext/smartcard_pcsc/pcsc.h
|
4
|
+
ext/smartcard_pcsc/pcsc_card.c
|
5
|
+
ext/smartcard_pcsc/pcsc_constants.c
|
6
|
+
ext/smartcard_pcsc/pcsc_context.c
|
7
|
+
ext/smartcard_pcsc/pcsc_io_request.c
|
8
|
+
ext/smartcard_pcsc/pcsc_main.c
|
9
|
+
ext/smartcard_pcsc/pcsc_multi_strings.c
|
10
|
+
ext/smartcard_pcsc/pcsc_namespace.c
|
11
|
+
ext/smartcard_pcsc/pcsc_reader_states.c
|
12
|
+
ext/smartcard_pcsc/pcsc_surrogate_reader.h
|
13
|
+
ext/smartcard_pcsc/pcsc_surrogate_wintypes.h
|
14
|
+
lib/smartcard.rb
|
15
|
+
LICENSE
|
16
|
+
README
|
17
|
+
test/test_all.rb
|
18
|
+
tests/ts_pcsc_ext.rb
|
19
|
+
Manifest
|
data/README
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
SUMMARY
|
2
|
+
|
3
|
+
'smartcard' aims to become the de-facto support library for smart-card development on ruby.
|
4
|
+
At the moment, 'smartcard' offers a PC/SC binding that is working on ruby 1.8, under
|
5
|
+
linux, osx, and windows. Future plans include a high level abstraction for the PC/SC binding
|
6
|
+
(and any other bindings people need), and an interface for Java cards.
|
7
|
+
|
8
|
+
LICENSE
|
9
|
+
|
10
|
+
'smartcard' is released under the MIT license. This means you're free to do whatever you want
|
11
|
+
with it. For the legalese version, please see the 'LICENSE' file.
|
12
|
+
|
13
|
+
DOCUMENTATION
|
14
|
+
|
15
|
+
The API is fully documented with RDoc. If you installed the 'smartcard' gem, you should be
|
16
|
+
able to use ri to see the documentation. If you're using the SVN version, you can use rdoc to
|
17
|
+
build the HTML and RI documentation yourself.
|
18
|
+
|
19
|
+
ACKNOWLEDGEMENTS
|
20
|
+
|
21
|
+
'smartcard' was developed for Victor Costan while working as a Research Assistant for MIT.
|
22
|
+
The work was sponsored by a grant from Quanta Computer Inc (www.quanta.com.tw)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'mkmf'
|
2
|
-
require 'pp'
|
3
2
|
|
4
3
|
$CFLAGS ||= ''
|
5
4
|
$LDFLAGS ||= ''
|
@@ -7,7 +6,7 @@ $LDFLAGS ||= ''
|
|
7
6
|
if RUBY_PLATFORM =~ /darwin/
|
8
7
|
$LDFLAGS += ' -framework PCSC'
|
9
8
|
elsif RUBY_PLATFORM =~ /win/
|
10
|
-
|
9
|
+
have_library('winscard')
|
11
10
|
else
|
12
11
|
# pcsc is retarded and uses stuff like '#include <wintypes.h>'
|
13
12
|
$CFLAGS += ' -I /usr/include/PCSC -I /usr/local/include/pcsc'
|
@@ -26,9 +25,29 @@ end
|
|
26
25
|
|
27
26
|
pcsc_defines = []
|
28
27
|
|
29
|
-
File.open('
|
28
|
+
File.open('pcsc_autogen.h', 'w') do |f|
|
30
29
|
pcsc_defines.each { |d| f.write "\#define #{d}\n" }
|
31
30
|
pcsc_headers.each { |h| f.write "\#include #{h}\n" }
|
32
31
|
end
|
33
32
|
|
34
|
-
create_makefile('smartcard/pcsc')
|
33
|
+
create_makefile('smartcard/pcsc')
|
34
|
+
|
35
|
+
def win32_hack(mf_name)
|
36
|
+
# evil, evil, evil -- hack the makefile to embed the manifest in the extension dll
|
37
|
+
make_contents = File.open(mf_name, 'r') { |f| f.read }
|
38
|
+
make_rules = make_contents.split(/(\n|\r)(\n|\r)+/)
|
39
|
+
new_make_rules = make_rules.map do |rule|
|
40
|
+
if rule =~ /^\$\(DLLIB\)\:/
|
41
|
+
rule + "\n\tmt.exe -manifest $(@).manifest -outputresource:$(@);2"
|
42
|
+
else
|
43
|
+
rule
|
44
|
+
end
|
45
|
+
end
|
46
|
+
File.open(mf_name, 'w') { |f| f.write new_make_rules.join("\n\n")}
|
47
|
+
end
|
48
|
+
|
49
|
+
case RUBY_PLATFORM
|
50
|
+
when /darwin/
|
51
|
+
when /win/
|
52
|
+
win32_hack 'Makefile'
|
53
|
+
end
|
data/ext/smartcard_pcsc/pcsc.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/* Ruby extension API. */
|
2
2
|
#include <ruby.h>
|
3
3
|
/* Generated by 'extconf.rb' to point to the PC/SC header. */
|
4
|
-
#include "
|
4
|
+
#include "pcsc_autogen.h"
|
5
5
|
|
6
6
|
/* Entrypoint into the Ruby extension. */
|
7
7
|
void Init_pcsc();
|
@@ -36,3 +36,11 @@ void Init_PCSC_Consts();
|
|
36
36
|
/* Multi-string (win32 abomination) tools. */
|
37
37
|
VALUE PCSC_Internal_multistring_to_ruby_array(char *mstr, size_t mstr_len);
|
38
38
|
int PCSC_Internal_ruby_strings_to_multistring(VALUE rbStrings, char **strings);
|
39
|
+
|
40
|
+
/* Messing up with constants that aren't uniformly defined. */
|
41
|
+
#if !defined(MAX_ATR_SIZE)
|
42
|
+
#define MAX_ATR_SIZE 32
|
43
|
+
#endif
|
44
|
+
#if !defined(SCARD_PROTOCOL_ANY)
|
45
|
+
#define SCARD_PROTOCOL_ANY (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
|
46
|
+
#endif
|
@@ -43,24 +43,26 @@ static VALUE PCSC_Card_alloc(VALUE klass) {
|
|
43
43
|
*/
|
44
44
|
static VALUE PCSC_Card_initialize(VALUE self, VALUE rbContext, VALUE rbReaderName, VALUE rbShareMode, VALUE rbPreferredProtocols) {
|
45
45
|
struct SCardHandleEx *card;
|
46
|
+
SCARDCONTEXT context;
|
47
|
+
VALUE rbFinalReaderName;
|
48
|
+
DWORD share_mode, preferred_protocols, active_protocol;
|
49
|
+
|
46
50
|
Data_Get_Struct(self, struct SCardHandleEx, card);
|
47
51
|
|
48
|
-
SCARDCONTEXT context;
|
49
52
|
if(_PCSC_Context_lowlevel_get(rbContext, &context) == 0) {
|
50
53
|
rb_raise(rb_eArgError, "first argument is not a Context instance");
|
51
54
|
return self;
|
52
55
|
}
|
53
56
|
|
54
|
-
|
57
|
+
rbFinalReaderName = rb_check_string_type(rbReaderName);
|
55
58
|
if(NIL_P(rbFinalReaderName)) {
|
56
59
|
rb_raise(rb_eArgError, "second argument (should be reader name) does not convert to a String");
|
57
60
|
return self;
|
58
61
|
}
|
59
62
|
|
60
|
-
|
61
|
-
|
63
|
+
share_mode = NUM2UINT(rbShareMode);
|
64
|
+
preferred_protocols = NUM2UINT(rbPreferredProtocols);
|
62
65
|
|
63
|
-
DWORD active_protocol;
|
64
66
|
card->pcsc_error = SCardConnect(context, RSTRING(rbFinalReaderName)->ptr, share_mode, preferred_protocols, &card->card_handle, &active_protocol);
|
65
67
|
if(card->pcsc_error != SCARD_S_SUCCESS)
|
66
68
|
rb_raise(rb_eRuntimeError, "SCardConnect: %s", pcsc_stringify_error(card->pcsc_error));
|
@@ -82,14 +84,15 @@ static VALUE PCSC_Card_initialize(VALUE self, VALUE rbContext, VALUE rbReaderNam
|
|
82
84
|
*/
|
83
85
|
static VALUE PCSC_Card_reconnect(VALUE self, VALUE rbShareMode, VALUE rbPreferredProtocols, VALUE rbInitialization) {
|
84
86
|
struct SCardHandleEx *card;
|
87
|
+
DWORD share_mode, preferred_protocols, initialization, active_protocol;
|
88
|
+
|
85
89
|
Data_Get_Struct(self, struct SCardHandleEx, card);
|
86
90
|
if(card == NULL) return self;
|
87
91
|
|
88
|
-
|
89
|
-
|
90
|
-
|
92
|
+
share_mode = NUM2UINT(rbShareMode);
|
93
|
+
preferred_protocols = NUM2UINT(rbPreferredProtocols);
|
94
|
+
initialization = NUM2UINT(rbInitialization);
|
91
95
|
|
92
|
-
uint32_t active_protocol;
|
93
96
|
card->pcsc_error = SCardReconnect(card->card_handle, share_mode, preferred_protocols, initialization, &active_protocol);
|
94
97
|
if(card->pcsc_error != SCARD_S_SUCCESS)
|
95
98
|
rb_raise(rb_eRuntimeError, "SCardReconnect: %s", pcsc_stringify_error(card->pcsc_error));
|
@@ -107,11 +110,13 @@ static VALUE PCSC_Card_reconnect(VALUE self, VALUE rbShareMode, VALUE rbPreferre
|
|
107
110
|
* +disposition+:: action to be taken on the card inside the reader; use one of the Smartcard::PCSC::DISPOSITION_ constants
|
108
111
|
*/
|
109
112
|
static VALUE PCSC_Card_disconnect(VALUE self, VALUE rbDisposition) {
|
110
|
-
struct SCardHandleEx *card;
|
113
|
+
struct SCardHandleEx *card;
|
114
|
+
DWORD disposition;
|
115
|
+
|
111
116
|
Data_Get_Struct(self, struct SCardHandleEx, card);
|
112
117
|
if(card == NULL) return self;
|
113
118
|
|
114
|
-
|
119
|
+
disposition = NUM2UINT(rbDisposition);
|
115
120
|
if(!card->released) {
|
116
121
|
card->pcsc_error = SCardDisconnect(card->card_handle, disposition);
|
117
122
|
card->released = 1;
|
@@ -129,7 +134,8 @@ static VALUE PCSC_Card_disconnect(VALUE self, VALUE rbDisposition) {
|
|
129
134
|
* Wraps _SCardBeginTransaction_ in PC/SC.
|
130
135
|
*/
|
131
136
|
static VALUE PCSC_Card_begin_transaction(VALUE self) {
|
132
|
-
struct SCardHandleEx *card;
|
137
|
+
struct SCardHandleEx *card;
|
138
|
+
|
133
139
|
Data_Get_Struct(self, struct SCardHandleEx, card);
|
134
140
|
if(card == NULL) return self;
|
135
141
|
|
@@ -149,11 +155,13 @@ static VALUE PCSC_Card_begin_transaction(VALUE self) {
|
|
149
155
|
* +disposition+:: action to be taken on the card inside the reader; use one of the Smartcard::PCSC::DISPOSITION_ constants
|
150
156
|
*/
|
151
157
|
static VALUE PCSC_Card_end_transaction(VALUE self, VALUE rbDisposition) {
|
152
|
-
struct SCardHandleEx *card;
|
158
|
+
struct SCardHandleEx *card;
|
159
|
+
DWORD disposition;
|
160
|
+
|
153
161
|
Data_Get_Struct(self, struct SCardHandleEx, card);
|
154
162
|
if(card == NULL) return self;
|
155
163
|
|
156
|
-
|
164
|
+
disposition = NUM2UINT(rbDisposition);
|
157
165
|
card->pcsc_error = SCardEndTransaction(card->card_handle, disposition);
|
158
166
|
if(card->pcsc_error != SCARD_S_SUCCESS)
|
159
167
|
rb_raise(rb_eRuntimeError, "SCardEndTransaction: %s", pcsc_stringify_error(card->pcsc_error));
|
@@ -174,19 +182,23 @@ static VALUE PCSC_Card_end_transaction(VALUE self, VALUE rbDisposition) {
|
|
174
182
|
* +attribute_id+:: identifies the attribute to be read; use one of the Smartcard::PCSC::ATTR_ constants
|
175
183
|
*/
|
176
184
|
static VALUE PCSC_Card_get_attribute(VALUE self, VALUE rbAttributeId) {
|
177
|
-
struct SCardHandleEx *card;
|
185
|
+
struct SCardHandleEx *card;
|
186
|
+
char *attribute_buffer;
|
187
|
+
DWORD attribute_id, attribute_length;
|
188
|
+
VALUE rbAttribute;
|
189
|
+
|
178
190
|
Data_Get_Struct(self, struct SCardHandleEx, card);
|
179
191
|
if(card == NULL) return Qnil;
|
180
192
|
|
181
|
-
|
182
|
-
|
193
|
+
attribute_id = NUM2UINT(rbAttributeId);
|
194
|
+
attribute_length;
|
183
195
|
card->pcsc_error = SCardGetAttrib(card->card_handle, attribute_id, NULL, &attribute_length);
|
184
196
|
if(card->pcsc_error == SCARD_S_SUCCESS) {
|
185
|
-
|
197
|
+
attribute_buffer = ALLOC_N(char, attribute_length);
|
186
198
|
if(attribute_buffer != NULL) {
|
187
199
|
card->pcsc_error = SCardGetAttrib(card->card_handle, attribute_id, (LPSTR)attribute_buffer, &attribute_length);
|
188
200
|
if(card->pcsc_error == SCARD_S_SUCCESS) {
|
189
|
-
|
201
|
+
rbAttribute = rb_str_new(attribute_buffer, attribute_length);
|
190
202
|
xfree(attribute_buffer);
|
191
203
|
return rbAttribute;
|
192
204
|
}
|
@@ -210,13 +222,16 @@ static VALUE PCSC_Card_get_attribute(VALUE self, VALUE rbAttributeId) {
|
|
210
222
|
* +attribute_value+:: the value to be assigned to the attribute; wrap the bytes in a string-like object (low-level API, remember?)
|
211
223
|
*/
|
212
224
|
static VALUE PCSC_Card_set_attribute(VALUE self, VALUE rbAttributeId, VALUE rbAttributeValue) {
|
213
|
-
struct SCardHandleEx *card;
|
225
|
+
struct SCardHandleEx *card;
|
226
|
+
DWORD attribute_id;
|
227
|
+
VALUE rbFinalAttributeValue;
|
228
|
+
|
214
229
|
Data_Get_Struct(self, struct SCardHandleEx, card);
|
215
230
|
if(card == NULL) return self;
|
216
231
|
|
217
|
-
|
232
|
+
attribute_id = NUM2UINT(rbAttributeId);
|
218
233
|
|
219
|
-
|
234
|
+
rbFinalAttributeValue = rb_check_string_type(rbAttributeValue);
|
220
235
|
if(NIL_P(rbFinalAttributeValue)) {
|
221
236
|
rb_raise(rb_eArgError, "second argument (attribute buffer) does not convert to a String");
|
222
237
|
return self;
|
@@ -242,35 +257,38 @@ static VALUE PCSC_Card_set_attribute(VALUE self, VALUE rbAttributeId, VALUE rbAt
|
|
242
257
|
* +recv_io_request+:: Smartcard::PCSC::IoRequest instance receving information about the recv protocol; you can use the result of Smartcard::PCSC::IoRequest#new
|
243
258
|
*/
|
244
259
|
static VALUE PCSC_Card_transmit(VALUE self, VALUE rbSendData, VALUE rbSendIoRequest, VALUE rbRecvIoRequest) {
|
245
|
-
struct SCardHandleEx *card;
|
260
|
+
struct SCardHandleEx *card;
|
261
|
+
VALUE rbFinalSendData, rbRecvData;
|
262
|
+
SCARD_IO_REQUEST *send_io_request, *recv_io_request;
|
263
|
+
char *recv_buffer;
|
264
|
+
DWORD recv_length;
|
265
|
+
|
246
266
|
Data_Get_Struct(self, struct SCardHandleEx, card);
|
247
267
|
if(card == NULL) return Qnil;
|
248
268
|
|
249
|
-
|
269
|
+
rbFinalSendData = rb_check_string_type(rbSendData);
|
250
270
|
if(NIL_P(rbFinalSendData)) {
|
251
271
|
rb_raise(rb_eArgError, "first argument (send buffer) does not convert to a String");
|
252
272
|
return Qnil;
|
253
273
|
}
|
254
274
|
|
255
|
-
SCARD_IO_REQUEST *send_io_request;
|
256
275
|
if(_PCSC_IoRequest_lowlevel_get(rbSendIoRequest, &send_io_request) == 0) {
|
257
276
|
rb_raise(rb_eArgError, "second argument (send io request) is not an IoRequest instance");
|
258
277
|
return Qnil;
|
259
278
|
}
|
260
|
-
SCARD_IO_REQUEST *recv_io_request;
|
261
279
|
if(_PCSC_IoRequest_lowlevel_get(rbRecvIoRequest, &recv_io_request) == 0) {
|
262
280
|
rb_raise(rb_eArgError, "second argument (recv io request) is not an IoRequest instance");
|
263
281
|
return Qnil;
|
264
282
|
}
|
265
283
|
|
266
284
|
#if defined(PCSCLITE_MAX_MESSAGE_SIZE)
|
267
|
-
|
285
|
+
recv_length = PCSCLITE_MAX_MESSAGE_SIZE;
|
268
286
|
#elif defined(MAX_BUFFER_SIZE_EXTENDED)
|
269
|
-
|
287
|
+
recv_length = MAX_BUFFER_SIZE_EXTENDED;
|
270
288
|
#else
|
271
|
-
|
289
|
+
recv_length = 65536;
|
272
290
|
#endif
|
273
|
-
|
291
|
+
recv_buffer = ALLOC_N(char, recv_length);
|
274
292
|
if(recv_buffer == NULL) return Qnil;
|
275
293
|
|
276
294
|
card->pcsc_error = SCardTransmit(card->card_handle, send_io_request,
|
@@ -282,7 +300,7 @@ static VALUE PCSC_Card_transmit(VALUE self, VALUE rbSendData, VALUE rbSendIoRequ
|
|
282
300
|
return Qnil;
|
283
301
|
}
|
284
302
|
|
285
|
-
|
303
|
+
rbRecvData = rb_str_new(recv_buffer, recv_length);
|
286
304
|
xfree(recv_buffer);
|
287
305
|
return rbRecvData;
|
288
306
|
}
|
@@ -308,18 +326,22 @@ static VALUE PCSC_Card_transmit(VALUE self, VALUE rbSendData, VALUE rbSendIoRequ
|
|
308
326
|
*/
|
309
327
|
static VALUE PCSC_Card_control(VALUE self, VALUE rbControlCode, VALUE rbSendData, VALUE rbMaxRecvBytes) {
|
310
328
|
struct SCardHandleEx *card;
|
329
|
+
VALUE rbFinalSendData, rbRecvData;
|
330
|
+
char *recv_buffer;
|
331
|
+
DWORD control_code, recv_length;
|
332
|
+
|
311
333
|
Data_Get_Struct(self, struct SCardHandleEx, card);
|
312
334
|
if(card == NULL) return Qnil;
|
313
335
|
|
314
|
-
|
336
|
+
rbFinalSendData = rb_check_string_type(rbSendData);
|
315
337
|
if(NIL_P(rbFinalSendData)) {
|
316
338
|
rb_raise(rb_eArgError, "second argument (send buffer) does not convert to a String");
|
317
339
|
return Qnil;
|
318
340
|
}
|
319
341
|
|
320
|
-
|
321
|
-
|
322
|
-
|
342
|
+
control_code = NUM2UINT(rbControlCode);
|
343
|
+
recv_length = NUM2UINT(rbMaxRecvBytes);
|
344
|
+
recv_buffer = ALLOC_N(char, recv_length);
|
323
345
|
if(recv_buffer == NULL) return Qnil;
|
324
346
|
|
325
347
|
card->pcsc_error = SCardControl(card->card_handle, control_code,
|
@@ -331,7 +353,7 @@ static VALUE PCSC_Card_control(VALUE self, VALUE rbControlCode, VALUE rbSendData
|
|
331
353
|
return Qnil;
|
332
354
|
}
|
333
355
|
|
334
|
-
|
356
|
+
rbRecvData = rb_str_new(recv_buffer, recv_length);
|
335
357
|
xfree(recv_buffer);
|
336
358
|
return rbRecvData;
|
337
359
|
}
|
@@ -352,21 +374,24 @@ static VALUE _rbStateKey, _rbProtocolKey, _rbAtrKey, _rbReaderNamesKey;
|
|
352
374
|
* <tt>:reader_names</tt> :: array of strings containing all the names of the reader containing the smartcard
|
353
375
|
*/
|
354
376
|
static VALUE PCSC_Card_status(VALUE self) {
|
355
|
-
struct SCardHandleEx *card;
|
377
|
+
struct SCardHandleEx *card;
|
378
|
+
char *atr_buffer, *reader_names_buffer;
|
379
|
+
DWORD atr_length, reader_names_length, state, protocol;
|
380
|
+
VALUE rbStateVal, rbProtocolVal, rbAtrVal, rbReaderNamesVal, rbReturnHash;
|
381
|
+
|
356
382
|
Data_Get_Struct(self, struct SCardHandleEx, card);
|
357
383
|
if(card == NULL) return Qnil;
|
358
384
|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
385
|
+
atr_length = MAX_ATR_SIZE;
|
386
|
+
atr_buffer = ALLOC_N(char, atr_length);
|
387
|
+
reader_names_length = 4096;
|
388
|
+
reader_names_buffer = ALLOC_N(char, reader_names_length);
|
363
389
|
if(atr_buffer == NULL || reader_names_buffer == NULL) {
|
364
390
|
if(reader_names_buffer != NULL) xfree(reader_names_buffer);
|
365
391
|
if(atr_buffer != NULL) xfree(atr_buffer);
|
366
392
|
return Qnil;
|
367
393
|
}
|
368
394
|
|
369
|
-
DWORD state, protocol;
|
370
395
|
card->pcsc_error = SCardStatus(card->card_handle, reader_names_buffer, &reader_names_length, &state, &protocol, (LPSTR)atr_buffer, &atr_length);
|
371
396
|
if(card->pcsc_error != SCARD_S_SUCCESS) {
|
372
397
|
xfree(reader_names_buffer); xfree(atr_buffer);
|
@@ -374,12 +399,12 @@ static VALUE PCSC_Card_status(VALUE self) {
|
|
374
399
|
return Qnil;
|
375
400
|
}
|
376
401
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
402
|
+
rbStateVal = UINT2NUM(state);
|
403
|
+
rbProtocolVal = UINT2NUM(protocol);
|
404
|
+
rbAtrVal = rb_str_new(atr_buffer, atr_length);
|
405
|
+
rbReaderNamesVal = PCSC_Internal_multistring_to_ruby_array(reader_names_buffer, reader_names_length);
|
381
406
|
|
382
|
-
|
407
|
+
rbReturnHash = rb_hash_new();
|
383
408
|
rb_hash_aset(rbReturnHash, _rbStateKey, rbStateVal);
|
384
409
|
rb_hash_aset(rbReturnHash, _rbProtocolKey, rbProtocolVal);
|
385
410
|
rb_hash_aset(rbReturnHash, _rbAtrKey, rbAtrVal);
|
@@ -398,6 +423,7 @@ static VALUE PCSC_Card_status(VALUE self) {
|
|
398
423
|
*/
|
399
424
|
static VALUE PCSC_Card_last_error(VALUE self) {
|
400
425
|
struct SCardHandleEx *card;
|
426
|
+
|
401
427
|
Data_Get_Struct(self, struct SCardHandleEx, card);
|
402
428
|
if(card == NULL) return Qnil;
|
403
429
|
|
@@ -414,16 +440,18 @@ static VALUE PCSC_Card_last_error(VALUE self) {
|
|
414
440
|
* Wraps a _SCARDHANDLE_ structure.
|
415
441
|
*/
|
416
442
|
void Init_PCSC_Card() {
|
417
|
-
ID state_id
|
418
|
-
|
419
|
-
|
420
|
-
|
443
|
+
ID state_id, protocol_id, atr_id, reader_names_id;
|
444
|
+
|
445
|
+
state_id = rb_intern("status"); _rbStateKey = ID2SYM(state_id);
|
446
|
+
protocol_id = rb_intern("protocol"); _rbProtocolKey = ID2SYM(protocol_id);
|
447
|
+
atr_id = rb_intern("atr"); _rbAtrKey = ID2SYM(atr_id);
|
448
|
+
reader_names_id = rb_intern("reader_names"); _rbReaderNamesKey = ID2SYM(reader_names_id);
|
421
449
|
|
422
450
|
cPcscCard = rb_define_class_under(mPcsc, "Card", rb_cObject);
|
423
451
|
rb_define_alloc_func(cPcscCard, PCSC_Card_alloc);
|
424
452
|
rb_define_method(cPcscCard, "initialize", PCSC_Card_initialize, 4);
|
425
|
-
rb_define_method(cPcscCard, "reconnect", PCSC_Card_reconnect, 3);
|
426
453
|
rb_define_method(cPcscCard, "disconnect", PCSC_Card_disconnect, 1);
|
454
|
+
rb_define_method(cPcscCard, "reconnect", PCSC_Card_reconnect, 3);
|
427
455
|
rb_define_method(cPcscCard, "begin_transaction", PCSC_Card_begin_transaction, 0);
|
428
456
|
rb_define_method(cPcscCard, "end_transaction", PCSC_Card_end_transaction, 1);
|
429
457
|
rb_define_method(cPcscCard, "get_attribute", PCSC_Card_get_attribute, 1);
|
@@ -436,10 +464,11 @@ void Init_PCSC_Card() {
|
|
436
464
|
|
437
465
|
/* Retrieves the SCARDHANDLE wrapped into a Smartcard::PCSC::Card instance. */
|
438
466
|
int _PCSC_Card_lowlevel_get(VALUE rbCard, SCARDHANDLE *card_handle) {
|
467
|
+
struct SCardHandleEx *card;
|
468
|
+
|
439
469
|
if(TYPE(rbCard) != T_DATA || RDATA(rbCard)->dfree != (void (*)(void *))PCSC_Card_free)
|
440
470
|
return 0;
|
441
471
|
|
442
|
-
struct SCardHandleEx *card;
|
443
472
|
Data_Get_Struct(rbCard, struct SCardHandleEx, card);
|
444
473
|
*card_handle = card->card_handle;
|
445
474
|
return 1;
|
@@ -133,16 +133,20 @@ void Init_PCSC_Consts() {
|
|
133
133
|
/* SCARD_SPECIFIC : PTS has been set. */
|
134
134
|
rb_define_const(mPcsc, "STATUS_SPECIFIC", INT2NUM(SCARD_SPECIFIC));
|
135
135
|
|
136
|
+
#if defined(SCARD_PROTOCOL_UNSET)
|
136
137
|
/* SCARD_PROTOCOL_UNSET : Protocol not set. */
|
137
138
|
rb_define_const(mPcsc, "PROTOCOL_UNSET", INT2NUM(SCARD_PROTOCOL_UNSET));
|
139
|
+
#endif /* SCARD_PROTOCOL_UNSET */
|
138
140
|
/* SCARD_PROTOCOL_T0 : T=0 active protocol. */
|
139
141
|
rb_define_const(mPcsc, "PROTOCOL_T0", INT2NUM(SCARD_PROTOCOL_T0));
|
140
142
|
/* SCARD_PROTOCOL_T1 : T=1 active protocol. */
|
141
143
|
rb_define_const(mPcsc, "PROTOCOL_T1", INT2NUM(SCARD_PROTOCOL_T1));
|
142
144
|
/* SCARD_PROTOCOL_RAW : Raw active protocol. */
|
143
145
|
rb_define_const(mPcsc, "PROTOCOL_RAW", INT2NUM(SCARD_PROTOCOL_RAW));
|
146
|
+
#if defined(SCARD_PROTOCOL_UNSET)
|
144
147
|
/* SCARD_PROTOCOL_T15 : T=15 protocol. */
|
145
148
|
rb_define_const(mPcsc, "PROTOCOL_T15", INT2NUM(SCARD_PROTOCOL_T15));
|
149
|
+
#endif /* SCARD_PROTOCOL_UNSET */
|
146
150
|
/* SCARD_PROTOCOL_ANY : IFD determines protocol. */
|
147
151
|
rb_define_const(mPcsc, "PROTOCOL_ANY", INT2NUM(SCARD_PROTOCOL_ANY));
|
148
152
|
|
@@ -40,6 +40,7 @@ static VALUE PCSC_Context_alloc(VALUE klass) {
|
|
40
40
|
*/
|
41
41
|
static VALUE PCSC_Context_initialize(VALUE self, VALUE scope) {
|
42
42
|
struct SCardContextEx *context;
|
43
|
+
|
43
44
|
Data_Get_Struct(self, struct SCardContextEx, context);
|
44
45
|
|
45
46
|
context->pcsc_error = SCardEstablishContext(NUM2INT(scope), NULL, NULL, &context->pcsc_context);
|
@@ -60,6 +61,7 @@ static VALUE PCSC_Context_initialize(VALUE self, VALUE scope) {
|
|
60
61
|
*/
|
61
62
|
static VALUE PCSC_Context_release(VALUE self) {
|
62
63
|
struct SCardContextEx *context;
|
64
|
+
|
63
65
|
Data_Get_Struct(self, struct SCardContextEx, context);
|
64
66
|
if(context == NULL) return self;
|
65
67
|
|
@@ -87,8 +89,8 @@ static VALUE PCSC_Context_is_valid(VALUE self) {
|
|
87
89
|
Data_Get_Struct(self, struct SCardContextEx, context);
|
88
90
|
if(context == NULL) return self;
|
89
91
|
|
90
|
-
|
91
|
-
return (pcsc_error == SCARD_S_SUCCESS) ? Qtrue : Qfalse;
|
92
|
+
context->pcsc_error = SCardIsValidContext(context->pcsc_context);
|
93
|
+
return (context->pcsc_error == SCARD_S_SUCCESS) ? Qtrue : Qfalse;
|
92
94
|
}
|
93
95
|
|
94
96
|
/* :Document-method: list_reader_groups
|
@@ -101,18 +103,21 @@ static VALUE PCSC_Context_is_valid(VALUE self) {
|
|
101
103
|
* Returns an array of strings containing the names of all the smart-card readers in the system.
|
102
104
|
*/
|
103
105
|
static VALUE PCSC_Context_list_reader_groups(VALUE self) {
|
104
|
-
struct SCardContextEx *context;
|
106
|
+
struct SCardContextEx *context;
|
107
|
+
VALUE rbGroups;
|
108
|
+
char *groups;
|
109
|
+
DWORD groups_length;
|
110
|
+
|
105
111
|
Data_Get_Struct(self, struct SCardContextEx, context);
|
106
112
|
if(context == NULL) return Qnil;
|
107
113
|
|
108
|
-
DWORD groups_length;
|
109
114
|
context->pcsc_error = SCardListReaderGroups(context->pcsc_context, NULL, &groups_length);
|
110
115
|
if(context->pcsc_error == SCARD_S_SUCCESS) {
|
111
|
-
|
116
|
+
groups = ALLOC_N(char, groups_length);
|
112
117
|
if(groups != NULL) {
|
113
118
|
context->pcsc_error = SCardListReaderGroups(context->pcsc_context, groups, &groups_length);
|
114
119
|
if(context->pcsc_error == SCARD_S_SUCCESS) {
|
115
|
-
|
120
|
+
rbGroups = PCSC_Internal_multistring_to_ruby_array(groups, groups_length);
|
116
121
|
xfree(groups);
|
117
122
|
return rbGroups;
|
118
123
|
}
|
@@ -137,24 +142,26 @@ static VALUE PCSC_Context_list_reader_groups(VALUE self) {
|
|
137
142
|
* +reader_groups+:: array of strings indicating the reader groups to list; also accepts a string or +nil+ (meaning all readers)
|
138
143
|
*/
|
139
144
|
static VALUE PCSC_Context_list_readers(VALUE self, VALUE rbGroups) {
|
140
|
-
struct SCardContextEx *context;
|
145
|
+
struct SCardContextEx *context;
|
146
|
+
VALUE rbReaders;
|
147
|
+
char *groups;
|
148
|
+
DWORD readers_length;
|
149
|
+
|
141
150
|
Data_Get_Struct(self, struct SCardContextEx, context);
|
142
151
|
if(context == NULL) return Qnil;
|
143
152
|
|
144
|
-
char *groups;
|
145
153
|
if(PCSC_Internal_ruby_strings_to_multistring(rbGroups, &groups) == 0) {
|
146
154
|
rb_raise(rb_eArgError, "invalid reader groups set (expecting nil or string or array of strings)");
|
147
155
|
return Qnil;
|
148
156
|
}
|
149
157
|
|
150
|
-
DWORD readers_length;
|
151
158
|
context->pcsc_error = SCardListReaders(context->pcsc_context, groups, NULL, &readers_length);
|
152
159
|
if(context->pcsc_error == SCARD_S_SUCCESS) {
|
153
160
|
char *readers = ALLOC_N(char, readers_length);
|
154
161
|
if(readers != NULL) {
|
155
162
|
context->pcsc_error = SCardListReaders(context->pcsc_context, groups, readers, &readers_length);
|
156
163
|
if(context->pcsc_error == SCARD_S_SUCCESS) {
|
157
|
-
|
164
|
+
rbReaders = PCSC_Internal_multistring_to_ruby_array(readers, readers_length);
|
158
165
|
xfree(readers);
|
159
166
|
if(groups != NULL) xfree(groups);
|
160
167
|
return rbReaders;
|
@@ -177,7 +184,8 @@ static VALUE PCSC_Context_list_readers(VALUE self, VALUE rbGroups) {
|
|
177
184
|
* Wraps _SCardCancel_ in PC/SC.
|
178
185
|
*/
|
179
186
|
static VALUE PCSC_Context_cancel(VALUE self) {
|
180
|
-
struct SCardContextEx *context;
|
187
|
+
struct SCardContextEx *context;
|
188
|
+
|
181
189
|
Data_Get_Struct(self, struct SCardContextEx, context);
|
182
190
|
if(context == NULL) return self;
|
183
191
|
|
@@ -202,18 +210,19 @@ static VALUE PCSC_Context_cancel(VALUE self) {
|
|
202
210
|
* ReaderStates#set_event_state_of and ReaderStates#event_state_of)
|
203
211
|
*/
|
204
212
|
static VALUE PCSC_Context_get_status_change(VALUE self, VALUE rbReaderStates, VALUE rbTimeout) {
|
205
|
-
struct SCardContextEx *context;
|
213
|
+
struct SCardContextEx *context;
|
214
|
+
SCARD_READERSTATE *reader_states;
|
215
|
+
size_t reader_states_count;
|
216
|
+
DWORD timeout;
|
217
|
+
|
206
218
|
Data_Get_Struct(self, struct SCardContextEx, context);
|
207
219
|
if(context == NULL) return self;
|
208
220
|
|
209
|
-
unsigned int timeout;
|
210
221
|
if(TYPE(rbTimeout) == T_NIL || TYPE(rbTimeout) == T_FALSE)
|
211
222
|
timeout = INFINITE;
|
212
223
|
else
|
213
224
|
timeout = NUM2INT(rbTimeout);
|
214
225
|
|
215
|
-
SCARD_READERSTATE *reader_states;
|
216
|
-
size_t reader_states_count;
|
217
226
|
if(_PCSC_ReaderStates_lowlevel_get(rbReaderStates, &reader_states, &reader_states_count) == 0)
|
218
227
|
rb_raise(rb_eArgError, "first parameter is not a ReaderStates instance or nil");
|
219
228
|
else {
|
@@ -235,6 +244,7 @@ static VALUE PCSC_Context_get_status_change(VALUE self, VALUE rbReaderStates, VA
|
|
235
244
|
*/
|
236
245
|
static VALUE PCSC_Context_last_error(VALUE self) {
|
237
246
|
struct SCardContextEx *context;
|
247
|
+
|
238
248
|
Data_Get_Struct(self, struct SCardContextEx, context);
|
239
249
|
if(context == NULL) return Qnil;
|
240
250
|
|
@@ -265,10 +275,11 @@ void Init_PCSC_Context() {
|
|
265
275
|
|
266
276
|
/* Retrieves the SCARDCONTEXT wrapped into a Smartcard::PCSC::Context instance. */
|
267
277
|
int _PCSC_Context_lowlevel_get(VALUE rbContext, SCARDCONTEXT *pcsc_context) {
|
278
|
+
struct SCardContextEx *context;
|
279
|
+
|
268
280
|
if(TYPE(rbContext) != T_DATA || RDATA(rbContext)->dfree != (void (*)(void *))PCSC_Context_free)
|
269
281
|
return 0;
|
270
282
|
|
271
|
-
struct SCardContextEx *context;
|
272
283
|
Data_Get_Struct(rbContext, struct SCardContextEx, context);
|
273
284
|
*pcsc_context = context->pcsc_context;
|
274
285
|
return 1;
|
@@ -26,6 +26,7 @@ static VALUE PCSC_IoRequest_alloc(VALUE klass) {
|
|
26
26
|
*/
|
27
27
|
static VALUE PCSC_IoRequest_get_protocol(VALUE self) {
|
28
28
|
SCARD_IO_REQUEST *request;
|
29
|
+
|
29
30
|
Data_Get_Struct(self, SCARD_IO_REQUEST, request);
|
30
31
|
if(request == NULL) return Qnil;
|
31
32
|
|
@@ -42,6 +43,7 @@ static VALUE PCSC_IoRequest_get_protocol(VALUE self) {
|
|
42
43
|
*/
|
43
44
|
static VALUE PCSC_IoRequest_set_protocol(VALUE self, VALUE rbProtocol) {
|
44
45
|
SCARD_IO_REQUEST *request;
|
46
|
+
|
45
47
|
Data_Get_Struct(self, SCARD_IO_REQUEST, request);
|
46
48
|
if(request == NULL) return self;
|
47
49
|
|
@@ -70,6 +72,8 @@ void Init_PCSC_IoRequest() {
|
|
70
72
|
|
71
73
|
/* Retrieves the SCARD_IO_REQUEST wrapped into a Smartcard::PCSC::IoRequest instance. */
|
72
74
|
int _PCSC_IoRequest_lowlevel_get(VALUE rbIoRequest, SCARD_IO_REQUEST **io_request) {
|
75
|
+
SCARD_IO_REQUEST *request;
|
76
|
+
|
73
77
|
if(TYPE(rbIoRequest) == T_NIL || TYPE(rbIoRequest) == T_FALSE) {
|
74
78
|
*io_request = NULL;
|
75
79
|
return 1;
|
@@ -77,7 +81,6 @@ int _PCSC_IoRequest_lowlevel_get(VALUE rbIoRequest, SCARD_IO_REQUEST **io_reques
|
|
77
81
|
if(TYPE(rbIoRequest) != T_DATA || RDATA(rbIoRequest)->dfree != (void (*)(void *))PCSC_IoRequest_free)
|
78
82
|
return 0;
|
79
83
|
|
80
|
-
SCARD_IO_REQUEST *request;
|
81
84
|
Data_Get_Struct(rbIoRequest, SCARD_IO_REQUEST, request);
|
82
85
|
*io_request = request;
|
83
86
|
return 1;
|
@@ -3,14 +3,16 @@
|
|
3
3
|
|
4
4
|
/* Converts a multi-string "str1\0str_2\0str3\0\0" into a Ruby array of Ruby strings. */
|
5
5
|
VALUE PCSC_Internal_multistring_to_ruby_array(char *mstr, size_t mstr_len) {
|
6
|
-
VALUE rbArray
|
7
|
-
|
8
|
-
|
6
|
+
VALUE rbArray, rbString;
|
7
|
+
size_t i, start_offset;
|
8
|
+
|
9
|
+
rbArray = rb_ary_new();
|
10
|
+
for(i = 0; i < mstr_len; i++) {
|
9
11
|
if(mstr[i] == '\0') break;
|
10
|
-
|
12
|
+
start_offset = i;
|
11
13
|
for(; i < mstr_len; i++)
|
12
14
|
if(mstr[i] == '\0') break;
|
13
|
-
|
15
|
+
rbString = rb_str_new(mstr + start_offset, i - start_offset);
|
14
16
|
rb_ary_push(rbArray, rbString);
|
15
17
|
}
|
16
18
|
return rbArray;
|
@@ -21,6 +23,10 @@ VALUE PCSC_Internal_multistring_to_ruby_array(char *mstr, size_t mstr_len) {
|
|
21
23
|
* If false is returned, something went wrong and the method did not return a buffer.
|
22
24
|
*/
|
23
25
|
int PCSC_Internal_ruby_strings_to_multistring(VALUE rbStrings, char **strings) {
|
26
|
+
VALUE *array_elements;
|
27
|
+
char *buffer;
|
28
|
+
size_t string_length, array_length, buffer_length, i;
|
29
|
+
|
24
30
|
/* nil -> NULL */
|
25
31
|
if(TYPE(rbStrings) == T_NIL || TYPE(rbStrings) == T_FALSE) {
|
26
32
|
*strings = NULL;
|
@@ -28,8 +34,8 @@ int PCSC_Internal_ruby_strings_to_multistring(VALUE rbStrings, char **strings) {
|
|
28
34
|
}
|
29
35
|
/* string -> [string] */
|
30
36
|
if(TYPE(rbStrings) == T_STRING) {
|
31
|
-
|
32
|
-
|
37
|
+
string_length = RSTRING(rbStrings)->len;
|
38
|
+
buffer = ALLOC_N(char, string_length + 2);
|
33
39
|
memcpy(buffer, RSTRING(rbStrings)->ptr, string_length);
|
34
40
|
buffer[string_length] = buffer[string_length + 1] = '\0';
|
35
41
|
*strings = buffer;
|
@@ -38,20 +44,19 @@ int PCSC_Internal_ruby_strings_to_multistring(VALUE rbStrings, char **strings) {
|
|
38
44
|
/* array -> array */
|
39
45
|
if(TYPE(rbStrings) == T_ARRAY) {
|
40
46
|
/* compute buffer length */
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
for(; i < array_length; i++) {
|
47
|
+
array_length = RARRAY(rbStrings)->len;
|
48
|
+
array_elements = RARRAY(rbStrings)->ptr;
|
49
|
+
buffer_length = 1; /* for the trailing '\0' */
|
50
|
+
for(i = 0; i < array_length; i++) {
|
46
51
|
if(TYPE(array_elements[i]) != T_STRING)
|
47
52
|
return 0;
|
48
53
|
buffer_length += RSTRING(array_elements[i])->len + 1;
|
49
54
|
}
|
50
55
|
|
51
56
|
/* concatenate strings into buffer */
|
52
|
-
|
57
|
+
buffer = ALLOC_N(char, buffer_length);
|
53
58
|
for(buffer_length = 0, i = 0; i < array_length; i++) {
|
54
|
-
|
59
|
+
string_length = RSTRING(array_elements[i])->len;
|
55
60
|
memcpy(buffer + buffer_length, RSTRING(array_elements[i])->ptr, string_length);
|
56
61
|
buffer[buffer_length] = '\0';
|
57
62
|
buffer_length += string_length + 1;
|
@@ -63,3 +68,15 @@ int PCSC_Internal_ruby_strings_to_multistring(VALUE rbStrings, char **strings) {
|
|
63
68
|
|
64
69
|
return 0;
|
65
70
|
}
|
71
|
+
|
72
|
+
#if defined(WIN32)
|
73
|
+
char scard_error_buffer[128];
|
74
|
+
|
75
|
+
/* Produces a string for an error code yielded by the SCard* PC/SC functions. Returns a static global buffer. */
|
76
|
+
char *pcsc_stringify_error(DWORD scard_error) {
|
77
|
+
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
78
|
+
NULL, scard_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
79
|
+
scard_error_buffer, sizeof(scard_error_buffer), NULL );
|
80
|
+
return scard_error_buffer;
|
81
|
+
}
|
82
|
+
#endif
|
@@ -10,10 +10,10 @@ struct PCSCReaderStates {
|
|
10
10
|
|
11
11
|
/* Custom free for Smartcard::PCSC::ReaderStates. Also releases the referenced buffers (for the reader names). */
|
12
12
|
static void PCSC_ReaderStates_free(struct PCSCReaderStates *_states) {
|
13
|
+
size_t i;
|
13
14
|
if(_states != NULL) {
|
14
15
|
if(_states->states != NULL) {
|
15
|
-
|
16
|
-
for(; i < _states->states_count; i++) {
|
16
|
+
for(i = 0; i < _states->states_count; i++) {
|
17
17
|
if(_states->states[i].szReader != NULL)
|
18
18
|
xfree((char *)_states->states[i].szReader);
|
19
19
|
}
|
@@ -42,15 +42,16 @@ static VALUE PCSC_ReaderStates_alloc(VALUE klass) {
|
|
42
42
|
*/
|
43
43
|
static VALUE PCSC_ReaderStates_initialize(VALUE self, VALUE rbNumStates) {
|
44
44
|
struct PCSCReaderStates *states;
|
45
|
+
size_t states_count, i;
|
46
|
+
|
45
47
|
Data_Get_Struct(self, struct PCSCReaderStates, states);
|
46
48
|
|
47
|
-
|
49
|
+
states_count = NUM2UINT(rbNumStates);
|
48
50
|
if(states_count > 0) {
|
49
51
|
states->states = ALLOC_N(SCARD_READERSTATE, states_count);
|
50
52
|
if(states->states != NULL) {
|
51
53
|
states->states_count = states_count;
|
52
|
-
|
53
|
-
for(; i < states_count; i++) {
|
54
|
+
for(i = 0; i < states_count; i++) {
|
54
55
|
states->states[i].szReader = NULL;
|
55
56
|
states->states[i].dwCurrentState = SCARD_STATE_UNAWARE;
|
56
57
|
}
|
@@ -86,6 +87,7 @@ static int _validate_readerstates_args(VALUE rbReaderStates, VALUE rbIndex, stru
|
|
86
87
|
static VALUE PCSC_ReaderStates_current_state_of(VALUE self, VALUE rbIndex) {
|
87
88
|
struct PCSCReaderStates *states;
|
88
89
|
size_t index;
|
90
|
+
|
89
91
|
if(_validate_readerstates_args(self, rbIndex, &states, &index) == 0)
|
90
92
|
return Qnil;
|
91
93
|
|
@@ -106,6 +108,7 @@ static VALUE PCSC_ReaderStates_current_state_of(VALUE self, VALUE rbIndex) {
|
|
106
108
|
static VALUE PCSC_ReaderStates_event_state_of(VALUE self, VALUE rbIndex) {
|
107
109
|
struct PCSCReaderStates *states;
|
108
110
|
size_t index;
|
111
|
+
|
109
112
|
if(_validate_readerstates_args(self, rbIndex, &states, &index) == 0)
|
110
113
|
return Qnil;
|
111
114
|
|
@@ -126,6 +129,7 @@ static VALUE PCSC_ReaderStates_event_state_of(VALUE self, VALUE rbIndex) {
|
|
126
129
|
static VALUE PCSC_ReaderStates_set_current_state_of(VALUE self, VALUE rbIndex, VALUE rbCurrentState) {
|
127
130
|
struct PCSCReaderStates *states;
|
128
131
|
size_t index;
|
132
|
+
|
129
133
|
if(_validate_readerstates_args(self, rbIndex, &states, &index) == 0)
|
130
134
|
return self;
|
131
135
|
|
@@ -146,6 +150,7 @@ static VALUE PCSC_ReaderStates_set_current_state_of(VALUE self, VALUE rbIndex, V
|
|
146
150
|
static VALUE PCSC_ReaderStates_set_event_state_of(VALUE self, VALUE rbIndex, VALUE rbEventState) {
|
147
151
|
struct PCSCReaderStates *states;
|
148
152
|
size_t index;
|
153
|
+
|
149
154
|
if(_validate_readerstates_args(self, rbIndex, &states, &index) == 0)
|
150
155
|
return self;
|
151
156
|
|
@@ -167,6 +172,7 @@ static VALUE PCSC_ReaderStates_set_event_state_of(VALUE self, VALUE rbIndex, VAL
|
|
167
172
|
static VALUE PCSC_ReaderStates_atr_of(VALUE self, VALUE rbIndex) {
|
168
173
|
struct PCSCReaderStates *states;
|
169
174
|
size_t index;
|
175
|
+
|
170
176
|
if(_validate_readerstates_args(self, rbIndex, &states, &index) == 0)
|
171
177
|
return Qnil;
|
172
178
|
|
@@ -186,10 +192,12 @@ static VALUE PCSC_ReaderStates_atr_of(VALUE self, VALUE rbIndex) {
|
|
186
192
|
static VALUE PCSC_ReaderStates_set_atr_of(VALUE self, VALUE rbIndex, VALUE rbAtr) {
|
187
193
|
struct PCSCReaderStates *states;
|
188
194
|
size_t index;
|
195
|
+
VALUE rbFinalAtr;
|
196
|
+
|
189
197
|
if(_validate_readerstates_args(self, rbIndex, &states, &index) == 0)
|
190
198
|
return self;
|
191
199
|
|
192
|
-
|
200
|
+
rbFinalAtr = rb_check_string_type(rbAtr);
|
193
201
|
if(NIL_P(rbFinalAtr))
|
194
202
|
return self;
|
195
203
|
|
@@ -215,6 +223,7 @@ static VALUE PCSC_ReaderStates_set_atr_of(VALUE self, VALUE rbIndex, VALUE rbAtr
|
|
215
223
|
static VALUE PCSC_ReaderStates_reader_name_of(VALUE self, VALUE rbIndex) {
|
216
224
|
struct PCSCReaderStates *states;
|
217
225
|
size_t index;
|
226
|
+
|
218
227
|
if(_validate_readerstates_args(self, rbIndex, &states, &index) == 0)
|
219
228
|
return Qnil;
|
220
229
|
|
@@ -233,15 +242,17 @@ static VALUE PCSC_ReaderStates_reader_name_of(VALUE self, VALUE rbIndex) {
|
|
233
242
|
*/
|
234
243
|
static VALUE PCSC_ReaderStates_set_reader_name_of(VALUE self, VALUE rbIndex, VALUE rbReaderName) {
|
235
244
|
struct PCSCReaderStates *states;
|
236
|
-
size_t index;
|
245
|
+
size_t index, reader_name_length;
|
246
|
+
VALUE rbFinalReaderName;
|
247
|
+
|
237
248
|
if(_validate_readerstates_args(self, rbIndex, &states, &index) == 0)
|
238
249
|
return self;
|
239
250
|
|
240
|
-
|
251
|
+
rbFinalReaderName = rb_check_string_type(rbReaderName);
|
241
252
|
if(NIL_P(rbFinalReaderName))
|
242
253
|
return self;
|
243
254
|
|
244
|
-
|
255
|
+
reader_name_length = RSTRING(rbFinalReaderName)->len;
|
245
256
|
if(states->states[index].szReader != NULL)
|
246
257
|
xfree((char *)states->states[index].szReader);
|
247
258
|
states->states[index].szReader = ALLOC_N(char, reader_name_length + 1);
|
@@ -261,11 +272,12 @@ static VALUE PCSC_ReaderStates_set_reader_name_of(VALUE self, VALUE rbIndex, VAL
|
|
261
272
|
* (and thus prepare for a new call).
|
262
273
|
*/
|
263
274
|
static VALUE PCSC_ReaderStates_acknowledge_events(VALUE self) {
|
264
|
-
struct PCSCReaderStates *states;
|
275
|
+
struct PCSCReaderStates *states;
|
276
|
+
size_t i;
|
277
|
+
|
265
278
|
Data_Get_Struct(self, struct PCSCReaderStates, states);
|
266
279
|
if(states != NULL) {
|
267
|
-
|
268
|
-
for(; i < states->states_count; i++)
|
280
|
+
for(i = 0; i < states->states_count; i++)
|
269
281
|
states->states[i].dwCurrentState = states->states[i].dwEventState;
|
270
282
|
}
|
271
283
|
return self;
|
@@ -297,6 +309,8 @@ void Init_PCSC_ReaderStates() {
|
|
297
309
|
|
298
310
|
/* Retrieves the SCARD_READERSTATE array wrapped into a Smartcard::PCSC::ReaderStates instance. */
|
299
311
|
int _PCSC_ReaderStates_lowlevel_get(VALUE rbReaderStates, SCARD_READERSTATE **reader_states, size_t *reader_states_count) {
|
312
|
+
struct PCSCReaderStates *states;
|
313
|
+
|
300
314
|
if(TYPE(rbReaderStates) == T_NIL || TYPE(rbReaderStates) == T_FALSE) {
|
301
315
|
*reader_states = NULL;
|
302
316
|
*reader_states_count = 0;
|
@@ -305,7 +319,6 @@ int _PCSC_ReaderStates_lowlevel_get(VALUE rbReaderStates, SCARD_READERSTATE **re
|
|
305
319
|
if(TYPE(rbReaderStates) != T_DATA || RDATA(rbReaderStates)->dfree != (void (*)(void *))PCSC_ReaderStates_free)
|
306
320
|
return 0;
|
307
321
|
|
308
|
-
struct PCSCReaderStates *states;
|
309
322
|
Data_Get_Struct(rbReaderStates, struct PCSCReaderStates, states);
|
310
323
|
*reader_states = states->states;
|
311
324
|
*reader_states_count = states->states_count;
|
data/smartcard.gemspec
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
# Gem::Specification for Smartcard-0.2.0
|
3
|
+
# Originally generated by Echoe
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = %q{smartcard}
|
7
|
+
s.version = "0.2.0"
|
8
|
+
s.date = %q{2007-11-18}
|
9
|
+
s.summary = %q{Interface with ISO 7816 smart cards.}
|
10
|
+
s.require_paths = ["lib", "ext"]
|
11
|
+
s.email = %q{victor@costan.us}
|
12
|
+
s.homepage = %q{http://www.costan.us/smartcard}
|
13
|
+
s.rubyforge_project = %q{smartcard}
|
14
|
+
s.description = %q{Interface with ISO 7816 smart cards.}
|
15
|
+
s.has_rdoc = true
|
16
|
+
s.authors = ["Victor Costan"]
|
17
|
+
s.files = ["CHANGELOG", "ext/smartcard_pcsc/extconf.rb", "ext/smartcard_pcsc/pcsc.h", "ext/smartcard_pcsc/pcsc_card.c", "ext/smartcard_pcsc/pcsc_constants.c", "ext/smartcard_pcsc/pcsc_context.c", "ext/smartcard_pcsc/pcsc_io_request.c", "ext/smartcard_pcsc/pcsc_main.c", "ext/smartcard_pcsc/pcsc_multi_strings.c", "ext/smartcard_pcsc/pcsc_namespace.c", "ext/smartcard_pcsc/pcsc_reader_states.c", "ext/smartcard_pcsc/pcsc_surrogate_reader.h", "ext/smartcard_pcsc/pcsc_surrogate_wintypes.h", "lib/smartcard.rb", "LICENSE", "README", "test/test_all.rb", "tests/ts_pcsc_ext.rb", "Manifest", "smartcard.gemspec"]
|
18
|
+
s.test_files = ["test/test_all.rb"]
|
19
|
+
s.extensions = ["ext/smartcard_pcsc/extconf.rb"]
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# # Original Rakefile source (requires the Echoe gem):
|
24
|
+
#
|
25
|
+
# # Needs the 'echoe' gem
|
26
|
+
# require 'echoe'
|
27
|
+
#
|
28
|
+
# Echoe.new('smartcard') do |p|
|
29
|
+
# p.project = 'smartcard' # rubyforge project
|
30
|
+
#
|
31
|
+
# p.author = 'Victor Costan'
|
32
|
+
# p.email = 'victor@costan.us'
|
33
|
+
# p.summary = 'Interface with ISO 7816 smart cards.'
|
34
|
+
# p.url = 'http://www.costan.us/smartcard'
|
35
|
+
#
|
36
|
+
# p.need_tar_gz = false
|
37
|
+
# p.clean_pattern += ['ext/**/*.manifest', 'ext/**/*_autogen.h']
|
38
|
+
#
|
39
|
+
# p.eval = proc do |p|
|
40
|
+
# case RUBY_PLATFORM
|
41
|
+
# when /mswin/
|
42
|
+
# p.files += ['lib/smartcard/pcsc.so']
|
43
|
+
# p.platform = Gem::Platform::WIN32
|
44
|
+
#
|
45
|
+
# # take out the extension info from the gemspec
|
46
|
+
# task :postcompile_hacks => [:compile] do
|
47
|
+
# p.extensions.clear
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# task :package => [ :clean, :compile, :postcompile_hacks ]
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
# end
|
data/test/test_all.rb
ADDED
File without changes
|
metadata
CHANGED
@@ -3,16 +3,17 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: smartcard
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-11-
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2007-11-18 00:00:00 -05:00
|
8
8
|
summary: Interface with ISO 7816 smart cards.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
|
+
- ext
|
11
12
|
email: victor@costan.us
|
12
13
|
homepage: http://www.costan.us/smartcard
|
13
|
-
rubyforge_project:
|
14
|
-
description:
|
15
|
-
autorequire:
|
14
|
+
rubyforge_project: smartcard
|
15
|
+
description: Interface with ISO 7816 smart cards.
|
16
|
+
autorequire:
|
16
17
|
default_executable:
|
17
18
|
bindir: bin
|
18
19
|
has_rdoc: true
|
@@ -29,8 +30,7 @@ post_install_message:
|
|
29
30
|
authors:
|
30
31
|
- Victor Costan
|
31
32
|
files:
|
32
|
-
-
|
33
|
-
- ext/smartcard_pcsc
|
33
|
+
- CHANGELOG
|
34
34
|
- ext/smartcard_pcsc/extconf.rb
|
35
35
|
- ext/smartcard_pcsc/pcsc.h
|
36
36
|
- ext/smartcard_pcsc/pcsc_card.c
|
@@ -43,9 +43,15 @@ files:
|
|
43
43
|
- ext/smartcard_pcsc/pcsc_reader_states.c
|
44
44
|
- ext/smartcard_pcsc/pcsc_surrogate_reader.h
|
45
45
|
- ext/smartcard_pcsc/pcsc_surrogate_wintypes.h
|
46
|
+
- lib/smartcard.rb
|
47
|
+
- LICENSE
|
48
|
+
- README
|
49
|
+
- test/test_all.rb
|
46
50
|
- tests/ts_pcsc_ext.rb
|
47
|
-
|
48
|
-
|
51
|
+
- Manifest
|
52
|
+
- smartcard.gemspec
|
53
|
+
test_files:
|
54
|
+
- test/test_all.rb
|
49
55
|
rdoc_options: []
|
50
56
|
|
51
57
|
extra_rdoc_files: []
|