/[pcsclite]/website/matrix.py
ViewVC logotype

Contents of /website/matrix.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3453 - (show annotations) (download) (as text)
Thu Apr 16 11:27:44 2009 UTC (4 years, 1 month ago) by rousseau
File MIME type: text/x-python
File size: 11060 byte(s)
add a function to check that all .txt files are mentionned in
supported_readers.txt
1 #!/usr/bin/env python
2
3 # matrix.py generate a matrix of all readers characteristics
4 # Copyright (C) 2009 Ludovic Rousseau
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along
17 # with this program; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 import glob
21 import os
22 import ConfigParser
23 import pprint
24 import templayer
25 import time
26
27 pp = pprint.PrettyPrinter(indent=4)
28
29 def parse_reader(path, reader):
30 """
31 parse a reader CCID descriptor and return a dictionnary
32 """
33 reader_dict = {}
34 reader_file = open(path+reader)
35 for line in reader_file.readlines():
36 line = line[0:-1]
37 l = line.strip(" ").split(':')
38 if (len(l) > 1):
39 reader_dict[l[0]] = l[1].strip(" ")
40 reader_file.close()
41 return reader_dict
42
43 def parse_all(path, reader_list):
44 """
45 parse each reader from list
46 return a dictionnary
47 """
48 readers = {}
49 for reader in reader_list:
50 p = parse_reader(path, reader)
51 readers[reader] = p
52
53 return readers
54
55 def parse_ini(path, section):
56 """
57 parse a foobas.ini file to extract all informations
58 """
59 config = ConfigParser.ConfigParser()
60 # do not use the default case insensitive transform for key value
61 config.optionxform = str
62 config.read(section + ".ini")
63 reader_list = config.sections()
64
65 readers = parse_all(path, reader_list)
66 for r in readers.keys():
67 readers[r]['section'] = section
68 for o in config.options(r):
69 if o == 'features':
70 # for the features we use a list
71 readers[r][o] = [ config.get(r, o) ]
72 else:
73 readers[r][o] = config.get(r, o)
74
75 bPINSupport = int(readers[r]['bPINSupport'], 16)
76 if bPINSupport != 0 and not 'features' in readers[r]:
77 readers[r]['features'] = list()
78 if bPINSupport & 1:
79 readers[r]['features'].append("PIN Verification")
80 if bPINSupport & 2:
81 readers[r]['features'].append("PIN Modification")
82
83 #pp.pprint(readers["GemPCPinpad.txt"])
84 return readers
85
86 def check_list(path, reader_list):
87 """
88 Check that all .txt files are listed
89 """
90 cwd = os.getcwd()
91 os.chdir(path)
92 real_list = glob.glob("*.txt")
93 os.chdir(cwd)
94
95 # check that each reader file is listed
96 #print real_list
97 for r in reader_list:
98 #print "remove ", r
99 try:
100 real_list.remove(r)
101 except:
102 print "reader %s not yet listed" % r
103
104 # also remove the non-reader supported_readers.txt file
105 real_list.remove("supported_readers.txt")
106
107 # some USB descriptor are not listed in readers.txt?
108 if len(real_list) > 0:
109 raise Exception("readers %s are not listed" % real_list)
110
111 def check_supported(path, all_readers):
112 """
113 Check that all .txt files are mentionned in supported_readers.txt
114 """
115 supported_readers = file(path + "supported_readers.txt").readlines()
116 # convert in a long string and in uppercase
117 s = "".join(supported_readers).upper()
118
119 display = True
120 for r in all_readers.keys():
121 pattern = "%s:%s" % (all_readers[r]['idVendor'], all_readers[r]['idProduct'])
122 if not pattern.upper() in s:
123 if display:
124 print "Reader(s) not in supported_readers.txt"
125 display = False
126 print pattern + " " + r
127 #pp.pprint(supported_readers)
128
129 def get_by_manufacturer(readers):
130 """
131 return a dict of the readers grouped by manufacturer
132 d['manufacturer'] is a list of the manufacturer's readers
133 """
134 d = {}
135 for r in readers.keys():
136 d.setdefault(readers[r]['iManufacturer'], []).append(r)
137 return d
138
139 def generate_page(section, title, comment, readers):
140 """
141 generate a web page for the corresponding section
142 """
143 # sort the readers by manufacturers
144 manufacturer_readers = get_by_manufacturer(readers)
145 manufacturers = list(manufacturer_readers)
146 # sort the manufacturers list alphabetically
147 manufacturers.sort(key=str.lower)
148
149 template = templayer.HTMLTemplate("webpage.template")
150 file_writer = template.start_file(file=file(section + ".html", "w"))
151 main_layer = file_writer.open(date=time.asctime(),
152 title=title, comment=comment, section=section)
153
154 # for each manufacturer
155 for m in manufacturers:
156 main_layer.write_layer('manufacturer', manufacturer=m)
157
158 # for each reader
159 for r in sorted(manufacturer_readers[m]):
160 note_layer = main_layer.open_layer('reader',
161 manufacturer = m,
162 product = readers[r]['iProduct'],
163 idVendor = readers[r]['idVendor'],
164 idProduct = readers[r]['idProduct'],
165 image = "img/" + readers[r].get('image', "no_image.png"))
166
167 note_layer.write_layer('descriptor', descriptor = "readers/%s" % r)
168
169 url = readers[r].get('url', "")
170 if url:
171 note_layer.write_layer('url',
172 url = url,
173 manufacturer = m,
174 product = readers[r]['iProduct'])
175
176 features = ", ".join(readers[r].get('features', ""))
177 if features:
178 note_layer.write_layer('features', features = features)
179
180 note = readers[r].get('note', "").split('\n')
181 for n in note:
182 note_layer.write_layer('note', contents = n)
183
184 file_writer.close()
185
186 def generate_table(readers, field, index, fields):
187 """
188 generate a web page with all the reader attributes
189 readers are in the order given by index
190 """
191 header = """<?xml version="1.0" encoding="UTF-8"?>
192 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
193 <html>
194 <head>
195 <title>%s</title>
196 <link rel="stylesheet" type="text/css" href="default.css">
197 </head>
198 <body>"""
199 footer = """
200 <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"> </script> <script type="text/javascript"> _uacct = "UA-2404298-2"; urchinTracker(); </script>
201 </body>
202 </html>"""
203 documentation = """
204 <p>Click on the column header to sort by that column.</p>
205 <p>The background color indicates the section of the reader:
206 <table border="1">
207 <tr><td>supported</td>
208 <td bgcolor="#aff">should work</td>
209 <td bgcolor="#faa">unsupported</td></tr></table></p>
210 """
211
212 file = open(field + ".html", "w")
213 title = "Readers sorted by '%s' field" % field
214 file.write(header % title)
215
216 file.write("<h1>" + title + "</h1>")
217 file.write(documentation)
218
219 file.write('<table border="1" summary="">\n')
220
221 file.write('<tr>')
222 file.write("<th>#</th>")
223 for f in fields:
224 file.write("<th><a href='%s'>%s</a></th>" % (f+".html", f))
225 file.write('</tr>\n')
226
227 num = 0
228 for r in index:
229 num += 1
230 if readers[r]['section'] == "unsupported":
231 file.write('<tr bgcolor="#faa">')
232 elif readers[r]['section'] == "shouldwork":
233 file.write('<tr bgcolor="#aff">')
234 else:
235 file.write('<tr>')
236 file.write("<td>%d</td>" % num)
237 for f in fields:
238 if f == 'iProduct':
239 file.write("<td><a href='%s.html#%s%s'>%s</a></td>" % (readers[r]['section'], readers[r]['idVendor'], readers[r]['idProduct'], readers[r][f]))
240 elif f == 'iManufacturer':
241 file.write('<td><a onmouseover="">%s<img src="%s"></td>' % (readers[r][f], "img/" + readers[r].get('image', "no_image.png")))
242 else:
243 file.write("<td>%s</td>" % readers[r].get(f, ""))
244 file.write('</tr>\n')
245
246 file.write('</table>\n')
247
248 file.write("<hr><p>Generated: %s</p>" % time.asctime())
249
250 file.write(footer)
251 file.close()
252
253 def generate_tables(readers):
254 """
255 generate all the web page tables with all the fields values
256 """
257 fields = [ 'section', 'iManufacturer', 'iProduct', 'idVendor',
258 'idProduct', 'bNumEndpoints', 'bInterfaceClass', 'bcdCCID',
259 'bMaxSlotIndex', 'bVoltageSupport', 'dwProtocols',
260 'dwDefaultClock', 'dwMaximumClock', 'dwDataRate',
261 'dwMaxDataRate', 'dwMaxIFSD', 'dwSynchProtocols',
262 'dwMechanical', 'dwFeatures', 'dwMaxCCIDMessageLength',
263 'bClassGetResponse', 'bClassEnveloppe', 'wLcdLayout',
264 'bPINSupport', 'bMaxCCIDBusySlots', 'features' ]
265
266 for f in fields:
267 index = list()
268 for r in readers.keys():
269 index.append([readers[r].get(f, ""), r])
270 if f == 'section':
271 # hack to sort in the order supported, shouldwork, unsupported
272 index = [(s.replace('supported', 'asupported'),r) for s,r in index]
273 if f in ['dwDefaultClock', 'dwMaximumClock', 'dwDataRate',
274 'dwMaxDataRate', 'dwMaxIFSD', 'dwMaxCCIDMessageLength']:
275 # convert from text to decimal
276 index = [(float(s.split(' ')[0])*1000,r) for s,r in index]
277 index.sort()
278 sorted_fields = list(fields)
279 sorted_fields.remove(f)
280 sorted_fields.insert(0, f)
281 generate_table(readers, f, [r for f, r in index], sorted_fields)
282
283 if __name__ == "__main__":
284 path = "../trunk/Drivers/ccid/readers/"
285
286 supported_readers = parse_ini(path, "supported")
287 shouldwork_readers = parse_ini(path, "shouldwork")
288 unsupported_readers = parse_ini(path, "unsupported")
289
290 # all_readers contain the union of the 3 lists
291 all_readers = dict(supported_readers)
292 all_readers.update(shouldwork_readers)
293 all_readers.update(unsupported_readers)
294
295 check_list(path, all_readers.keys())
296 check_supported(path, all_readers)
297
298 generate_page("supported", "Supported CCID readers/ICCD tokens", "If you are a reader manufacturer and your reader is not listed here then contact me at ludovic.rousseau@free.fr", supported_readers)
299 generate_page("shouldwork", "Should work but untested by me", "The CCID readers and ICCD tokens listed bellow should work with the driver but have not be validated by me. I would like to get these readers to perform test and validation and move them in the supported list above. If you are one of the manufacturers, please, contact me at ludovic.rousseau@free.fr.", shouldwork_readers)
300 generate_page("unsupported", "Unsupported or partly supported CCID readers", "These readers have problems or serious limitations.", unsupported_readers)
301
302 generate_tables(all_readers)

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.5