-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlogger.py
230 lines (200 loc) · 5.54 KB
/
logger.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
import serial
import time
from Tkinter import *
###
# configuration
###
# only mac is currently supported
OS = 'mac'
# tty for Bluetooth device with baud
SERIAL_TERMINAL = '/dev/tty.VIRTKEY-DevB'
BAUD = 2400
# connect and transmit to serial device?
TRANSMIT = False
# font size for GUI
FONT_SIZE = 16
###
# end configuration
###
# Keys on Arduino
#####
# Key Hexadecimal value Decimal value
# KEY_LEFT_CTRL 0x80 128
# KEY_LEFT_SHIFT 0x81 129
# KEY_LEFT_ALT 0x82 130
# KEY_LEFT_GUI 0x83 131
# KEY_RIGHT_CTRL 0x84 132
# KEY_RIGHT_SHIFT 0x85 133
# KEY_RIGHT_ALT 0x86 134
# KEY_RIGHT_GUI 0x87 135
# KEY_UP_ARROW 0xDA 218
# KEY_DOWN_ARROW 0xD9 217
# KEY_LEFT_ARROW 0xD8 216
# KEY_RIGHT_ARROW 0xD7 215
# KEY_BACKSPACE 0xB2 178
# KEY_TAB 0xB3 179
# KEY_RETURN 0xB0 176
# KEY_ESC 0xB1 177
# KEY_INSERT 0xD1 209
# KEY_DELETE 0xD4 212
# KEY_PAGE_UP 0xD3 211
# KEY_PAGE_DOWN 0xD6 214
# KEY_HOME 0xD2 210
# KEY_END 0xD5 213
# KEY_CAPS_LOCK 0xC1 193
# KEY_F1 0xC2 194
# KEY_F2 0xC3 195
# KEY_F3 0xC4 196
# KEY_F4 0xC5 197
# KEY_F5 0xC6 198
# KEY_F6 0xC7 199
# KEY_F7 0xC8 200
# KEY_F8 0xC9 201
# KEY_F9 0xCA 202
# KEY_F10 0xCB 203
# KEY_F11 0xCC 204
# KEY_F12 0xCD 205
special_mappings = {
# ctrl-0 to cmd-space
('0', ('<C>',)): (' ', ('<M>',))
}
special_characters = {
'Up': '<u>',
'Down': '<d>',
'Left': '<l>',
'Right': '<r>',
'BackSpace': '<b>',
'Tab': '<t>',
'Return': '<R>',
'Escape': '<e>',
# TODO: insert
'Delete': '<D>',
'Prior': '<U>', # page up
'Next': '<n>', # page down
'Home': '<h>',
'End': '<E>',
# TODO: caps lock
}
# insert the F keys
for i in range(1, 10):
key = 'F{}'.format(i)
special_characters[key] = '<{}>'.format(i)
# ASCII 10, 11, 12
special_characters['F10'] = '<:>'
special_characters['F11'] = '<;>'
special_characters['F12'] = '<<>'
# print(special_characters)
# Mask on event.state
#####
# 0x0001 Shift.
# 0x0002 Caps Lock.
# 0x0004 Control.
# 0x0008 Left-hand Alt.
# 0x0010 Num Lock.
# 0x0080 Right-hand Alt.
def is_alt(s):
if OS == 'mac':
return (s & 0x10) != 0
def is_command(s):
if OS == 'mac':
return (s & 0x8) != 0 or (s & 0x80) != 0
def get_modifiers(s):
modifiers = set()
ctrl = (s & 0x4) != 0
# for some reason these don't work on mac is they are supposed to
alt = is_alt(s)
command = is_command(s)
# alt = (s & 0x8) != 0 or (s & 0x80) != 0
shift = (s & 0x1) != 0
# number_lock = (s & 0x10) != 0
caps_lock = (s & 0x2) != 0
if ctrl:
modifiers.add('<C>')
if alt:
modifiers.add('<A>')
if shift:
modifiers.add('<S>')
if command:
modifiers.add('<M>')
# if number_lock:
# modifiers.add('num_lock')
# if caps_lock:
# modifiers.add('caps_lock')
return modifiers
def get_key(event):
symbol = event.keysym
# print 'event.char "{}" "{}" "{}" "{}"'.format(event.char, repr(event.char), len(event.char), symbol)
if symbol in special_characters:
# print 'symbol: {}'.format(symbol)
return special_characters[symbol]
# elif len(event.char) == 0:
# return ''
elif len(symbol) == 1:
return symbol
elif len(event.char) == 1:
# print 'lower: {}'.format(event.char.lower())
return event.char
else:
return 'ERROR'
def set_to_tuple(s):
return tuple(list(s))
def translate_keys(key, modifiers):
current_combo = (key, set_to_tuple(modifiers))
# print current_combo
if current_combo in special_mappings:
translation = special_mappings[current_combo]
print 'translating {} to {}'.format(current_combo, translation)
return translation
return (key, modifiers)
def encode(key, modifiers):
key, modifiers = translate_keys(key, modifiers)
n_pressed = len(modifiers) + (0 if key == '' else 1)
modifier_string = ''.join(modifiers)
return '{}{}{}'.format(n_pressed, modifier_string, key)
class KeyHandler():
def __init__(self, parent, ser, status_label):
self.parent = parent
self.parent.bind("<Key>", self.keypress)
self.status_label = status_label
self.ser = ser
# set the state to be disabled so we don't get weird special characters
self.parent.config(state = DISABLED)
def parent_insert(self, c):
self.parent.config(state = NORMAL)
self.parent.insert(END, c)
self.parent.config(state = DISABLED)
def keypress(self, event):
if len(event.char) == 0:
return
# print repr(event.char)
modifiers = get_modifiers(event.state)
key = get_key(event)
encoding = encode(key, modifiers)
print encoding
for x in encoding:
print "writing: '{}'".format(x)
if self.ser is not None:
self.ser.write(x)
time.sleep(1 / 1000000)
self.parent_insert(event.char)
self.status_label.set(encoding)
# begin main
root = Tk()
root.wm_title('replay keys')
frame = Frame(root, width = 400, height = 300)
frame.pack(fill = BOTH, expand = True)
text_box = Text(frame, font = ("Helvetica", FONT_SIZE))
text_box.config(state = DISABLED)
text_box.focus_set()
text_box.grid(row = 0, rowspan = 5)
status_text = StringVar()
label = Label(frame, textvariable = status_text, font = ("Helvetica", FONT_SIZE))
label.grid(row = 5, rowspan = 1)
status_text.set('No keys transmitted yet.')
if TRANSMIT:
with serial.Serial(SERIAL_TERMINAL, BAUD) as ser:
key_handler = KeyHandler(text_box, ser, status_text)
root.mainloop()
else:
key_handler = KeyHandler(text_box, None, status_text)
root.mainloop()