3 # Copyright (C) 2010 Sergio Martins <sergio97@gmail.com>
4 # Copyright (C) 2011 Jelmer Vernooij <jelmer@samba.org>
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 3 of the License, or
9 # (at your option) any later version.
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.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 """Registry-related dialogs."""
30 from samba.dcerpc import misc
32 class RegistryValue(object):
34 def __init__(self, name, type, data, parent):
40 def get_absolute_path(self):
41 if self.parent is None:
44 return self.parent.get_absolute_path() + "\\" + self.name
46 def get_data_string(self):
47 interpreted_data = self.get_interpreted_data()
49 if interpreted_data is None or len(self.data) == 0:
50 return "(value not set)"
51 elif self.type in (misc.REG_SZ, misc.REG_EXPAND_SZ):
52 return interpreted_data
53 elif self.type == misc.REG_BINARY:
54 return "".join(["%02X" % byte for byte in interpreted_data])
55 elif self.type == misc.REG_DWORD:
56 return "0x%08X" % (interpreted_data)
57 elif self.type == misc.REG_DWORD_BIG_ENDIAN:
58 return "0x%08X" % (interpreted_data)
59 elif self.type == misc.REG_MULTI_SZ:
60 return " ".join(interpreted_data)
61 elif self.type == misc.REG_QWORD:
62 return "0x%016X" % (interpreted_data)
64 return str(interpreted_data)
66 def get_interpreted_data(self):
70 if self.type in (misc.REG_SZ, misc.REG_EXPAND_SZ):
74 while (index + 1 < len(self.data)): #The +1 ensures that the whole char is valid. Corrupt keys can otherwise cause exceptions
75 word = ((self.data[index + 1] << 8) + self.data[index])
77 result += unichr(word)
81 elif self.type == misc.REG_BINARY:
83 elif self.type == misc.REG_DWORD:
86 if len(self.data) < 4:
90 result = (result << 8) + self.data[3 - i]
93 elif self.type == misc.REG_DWORD_BIG_ENDIAN:
96 if len(self.data) < 4:
100 result = (result << 8) + self.data[i]
103 elif self.type == misc.REG_MULTI_SZ:
107 if len(self.data) == 0:
111 while (index < len(self.data)):
112 word = ((self.data[index + 1] << 8) + self.data[index])
114 result.append(string)
117 string += unichr(word)
121 result.pop() # remove last systematic empty string
124 elif self.type == misc.REG_QWORD:
127 if len(self.data) < 8:
131 result = (result << 8) + self.data[7 - i]
137 def set_interpreted_data(self, data):
142 elif self.type in (misc.REG_SZ, misc.REG_EXPAND_SZ):
145 self.data.append(int(word & 0x00FF))
146 self.data.append(int((word >> 8) & 0x00FF))
147 elif self.type == misc.REG_BINARY:
150 self.data.append(int(elem))
151 elif self.type == misc.REG_DWORD:
153 self.data.append(int(data >> (8 * i) & 0xFF))
154 elif self.type == misc.REG_DWORD_BIG_ENDIAN:
155 for i in xrange(3, -1, -1):
156 self.data.append(int(data >> (8 * i) & 0xFF))
157 elif self.type == misc.REG_MULTI_SZ:
163 self.data.append(int(word & 0x00FF))
164 self.data.append(int((word >> 8) & 0x00FF))
171 elif self.type == misc.REG_QWORD:
173 self.data.append(int(data >> (8 * i) & 0xFF))
177 def list_view_representation(self):
178 return [self.name, RegistryValue.get_type_string(self.type),
179 self.get_data_string(), self]
182 def get_type_string(type):
184 misc.REG_SZ:"String",
185 misc.REG_BINARY:"Binary Data",
186 misc.REG_EXPAND_SZ:"Expandable String",
187 misc.REG_DWORD:"32-bit Number (little endian)",
188 misc.REG_DWORD_BIG_ENDIAN:"32-bit Number (big endian)",
189 misc.REG_MULTI_SZ:"Multi-String",
190 misc.REG_QWORD:"64-bit Number (little endian)"
193 return type_strings[type]
196 class RegistryKey(object):
198 def __init__(self, name, parent):
203 def get_absolute_path(self):
204 if self.parent is None:
207 return self.parent.get_absolute_path() + "\\" + self.name
209 def get_root_key(self):
210 if self.parent is None:
213 return self.parent.get_root_key()
215 def list_view_representation(self):
216 return [self.name, self]
219 class RegValueEditDialog(gtk.Dialog):
221 def __init__(self, reg_value, type):
222 super(RegValueEditDialog, self).__init__()
224 if reg_value is None:
225 self.brand_new = True
226 self.reg_value = RegistryValue("", type, [], None)
228 self.brand_new = False
229 self.reg_value = reg_value
231 self.disable_signals = False
232 self.ascii_cursor_shift = 0 # because moving the cursor in some functions has no effect, we need to keep this value and apply it at the right time
233 self.hex_cursor_shift = 0
236 self.reg_value_to_values()
239 self.set_title(["Edit registry value", "New registry value"][self.brand_new])
240 self.set_border_width(5)
242 self.icon_registry_number_filename = os.path.join(sys.path[0],
243 "images", "registry-number.png")
244 self.icon_registry_string_filename = os.path.join(sys.path[0],
245 "images", "registry-string.png")
246 self.icon_registry_binary_filename = os.path.join(sys.path[0],
247 "images", "registry-binary.png")
249 self.set_resizable(True)
253 self.vbox.pack_start(hbox, False, False, 10)
255 label = gtk.Label("Value name:")
256 hbox.pack_start(label, False, True, 10)
258 self.name_entry = gtk.Entry()
259 self.name_entry.set_activates_default(True)
260 self.name_entry.set_sensitive(self.brand_new)
261 hbox.pack_start(self.name_entry, True, True, 10)
263 separator = gtk.HSeparator()
264 self.vbox.pack_start(separator, False, True, 5)
267 frame = gtk.Frame(" Value data: ")
268 self.vbox.pack_start(frame, True, True, 10)
270 self.type_notebook = gtk.Notebook()
271 self.type_notebook.set_border_width(5)
272 self.type_notebook.set_show_tabs(False)
273 self.type_notebook.set_show_border(False)
274 frame.add(self.type_notebook)
277 self.string_data_entry = gtk.Entry()
278 self.string_data_entry.set_activates_default(True)
279 self.type_notebook.append_page(self.string_data_entry)
283 scrolledwindow = gtk.ScrolledWindow(None, None)
284 scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
285 scrolledwindow.set_shadow_type(gtk.SHADOW_NONE)
286 self.type_notebook.append_page(scrolledwindow)
289 scrolledwindow.add_with_viewport(hbox)
291 self.binary_data_addr_text_view = gtk.TextView()
292 self.binary_data_addr_text_view.set_wrap_mode(gtk.WRAP_WORD)
293 self.binary_data_addr_text_view.set_editable(False)
294 self.binary_data_addr_text_view.modify_font(pango.FontDescription("mono 10"))
295 self.binary_data_addr_text_view.set_size_request(60, -1)
296 hbox.pack_start(self.binary_data_addr_text_view, False, False, 0)
298 self.binary_data_hex_text_view = gtk.TextView()
299 self.binary_data_hex_text_view.set_wrap_mode(gtk.WRAP_WORD)
300 self.binary_data_hex_text_view.set_accepts_tab(False)
301 self.binary_data_hex_text_view.modify_font(pango.FontDescription("mono bold 10"))
302 self.binary_data_hex_text_view.set_size_request(275, -1)
303 hbox.pack_start(self.binary_data_hex_text_view, False, False, 0)
305 self.binary_data_ascii_text_view = gtk.TextView()
306 self.binary_data_ascii_text_view.set_wrap_mode(gtk.WRAP_CHAR)
307 #self.binary_data_ascii_text_view.set_editable(False)
308 self.binary_data_ascii_text_view.modify_font(pango.FontDescription("mono 10"))
309 self.binary_data_ascii_text_view.set_accepts_tab(False)
310 self.binary_data_ascii_text_view.set_size_request(100, -1)
311 hbox.pack_start(self.binary_data_ascii_text_view, False, False, 0)
316 self.type_notebook.append_page(hbox)
318 self.number_data_entry = gtk.Entry()
319 self.number_data_entry.set_activates_default(True)
320 hbox.pack_start(self.number_data_entry, True, True, 5)
322 self.number_data_dec_radio = gtk.RadioButton(None, "Decimal")
323 hbox.pack_start(self.number_data_dec_radio, False, True, 5)
325 self.number_data_hex_radio = gtk.RadioButton(self.number_data_dec_radio, "Hexadecimal")
326 hbox.pack_start(self.number_data_hex_radio, False, True, 5)
328 self.number_data_hex_radio.set_active(True)
330 # multi-string type page
331 scrolledwindow = gtk.ScrolledWindow(None, None)
332 scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
333 scrolledwindow.set_shadow_type(gtk.SHADOW_IN)
334 self.type_notebook.append_page(scrolledwindow)
336 self.multi_string_data_text_view = gtk.TextView()
337 self.multi_string_data_text_view.set_wrap_mode(gtk.WRAP_NONE)
338 scrolledwindow.add(self.multi_string_data_text_view)
341 self.action_area.set_layout(gtk.BUTTONBOX_END)
343 self.cancel_button = gtk.Button("Cancel", gtk.STOCK_CANCEL)
344 self.cancel_button.set_flags(gtk.CAN_DEFAULT)
345 self.add_action_widget(self.cancel_button, gtk.RESPONSE_CANCEL)
347 self.apply_button = gtk.Button("Apply", gtk.STOCK_APPLY)
348 self.apply_button.set_flags(gtk.CAN_DEFAULT)
349 self.apply_button.set_sensitive(not self.brand_new) # disabled for new task
350 self.add_action_widget(self.apply_button, gtk.RESPONSE_APPLY)
352 self.ok_button = gtk.Button("OK", gtk.STOCK_OK)
353 self.ok_button.set_flags(gtk.CAN_DEFAULT)
354 self.add_action_widget(self.ok_button, gtk.RESPONSE_OK)
356 self.set_default_response(gtk.RESPONSE_OK)
359 self.binary_data_hex_text_view.get_buffer().connect("changed", self.on_binary_data_hex_text_view_buffer_changed)
360 self.binary_data_hex_text_view.get_buffer().connect("insert-text", self.on_binary_data_hex_text_view_buffer_insert_text)
361 self.binary_data_hex_text_view.get_buffer().connect("delete-range", self.on_binary_data_hex_text_view_buffer_delete_range)
363 # Ascii text view callbacks. This view requires special attention to
364 # facilitate the crazy editing it needs to do
365 self.binary_data_ascii_text_view.get_buffer().connect("insert-text", self.on_binary_data_ascii_text_view_buffer_insert_text) #manually handles inserting text
366 self.binary_data_ascii_text_view.get_buffer().connect("delete-range", self.on_binary_data_ascii_text_view_buffer_delete_range) #manually handles deleting text
367 self.binary_data_ascii_text_view.get_buffer().connect("changed", self.on_binary_data_ascii_text_view_buffer_changed)
368 self.binary_data_ascii_text_view.connect("move-cursor", self.on_binary_data_ascii_text_view_move_cursor)
370 self.number_data_dec_radio.connect("toggled", self.on_number_data_dec_radio_toggled)
371 self.number_data_hex_radio.connect("toggled", self.on_number_data_hex_radio_toggled)
372 self.number_data_entry.connect("changed", self.on_number_data_entry_changed)
374 def check_for_problems(self):
375 if len(self.name_entry.get_text().strip()) == 0:
376 return "Please specify a name."
378 if self.reg_value.type in [misc.REG_DWORD, misc.REG_DWORD_BIG_ENDIAN, misc.REG_QWORD]:
379 number_str = self.number_data_entry.get_text()
380 if len(number_str) == 0:
381 return "Please enter a number."
383 if self.number_data_dec_radio.get_active():
385 number = string.atoi(number_str, 10)
387 return "Please enter a valid decimal number."
389 number_str_hex = "%X" % number
391 if self.reg_value.type in [misc.REG_DWORD, misc.REG_DWORD_BIG_ENDIAN]:
396 if len(number_str_hex) > max_hex_len:
397 return "Please enter a smaller decimal number."
400 def reg_value_to_values(self):
401 if self.reg_value is None:
402 raise Exception("registry value not set")
404 self.name_entry.set_text(self.reg_value.name)
406 if self.reg_value.type in [misc.REG_SZ, misc.REG_EXPAND_SZ]:
407 self.set_icon_from_file(self.icon_registry_string_filename)
408 self.set_size_request(430, 200)
410 self.string_data_entry.set_text(self.reg_value.get_interpreted_data())
411 elif self.reg_value.type == misc.REG_BINARY:
412 self.set_icon_from_file(self.icon_registry_binary_filename)
413 self.set_size_request(483, 400) #extra few pixels for the scroll bar
415 self.binary_data_hex_text_view.get_buffer().set_text(RegValueEditDialog.byte_array_to_hex(self.reg_value.get_interpreted_data(), 8))
416 #self.on_binary_data_hex_text_view_buffer_changed(None) #this is already called with the statement above
418 elif self.reg_value.type in [misc.REG_DWORD, misc.REG_DWORD_BIG_ENDIAN, misc.REG_QWORD]:
419 self.set_icon_from_file(self.icon_registry_number_filename)
420 self.set_size_request(430, 200)
422 if self.reg_value.type == misc.REG_QWORD:
423 self.number_data_entry.set_text("%016X" % self.reg_value.get_interpreted_data())
425 self.number_data_entry.set_text("%08X" % self.reg_value.get_interpreted_data())
427 elif self.reg_value.type == misc.REG_MULTI_SZ:
428 self.set_icon_from_file(self.icon_registry_string_filename)
429 self.set_size_request(430, 400)
432 for line in self.reg_value.get_interpreted_data():
435 self.multi_string_data_text_view.get_buffer().set_text(text)
437 def values_to_reg_value(self):
438 if self.reg_value is None:
439 raise Exception("registry value not set")
441 self.reg_value.name = self.name_entry.get_text()
443 if self.reg_value.type in [misc.REG_SZ, misc.REG_EXPAND_SZ]:
444 self.reg_value.set_interpreted_data(self.string_data_entry.get_text())
445 elif self.reg_value.type == misc.REG_BINARY:
446 buffer = self.binary_data_hex_text_view.get_buffer()
447 text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())
448 self.reg_value.set_interpreted_data(RegValueEditDialog.hex_to_byte_array(text))
449 elif self.reg_value.type in [misc.REG_DWORD, misc.REG_DWORD_BIG_ENDIAN, misc.REG_QWORD]:
450 if self.number_data_dec_radio.get_active():
451 self.reg_value.set_interpreted_data(string.atoi(self.number_data_entry.get_text(), 10))
453 self.reg_value.set_interpreted_data(string.atoi(self.number_data_entry.get_text(), 0x10))
455 elif self.reg_value.type == misc.REG_MULTI_SZ:
459 buffer = self.multi_string_data_text_view.get_buffer()
460 for ch in buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter()):
470 self.reg_value.set_interpreted_data(lines)
472 def update_type_page_after_show(self):
473 if self.reg_value.type == misc.REG_SZ:
474 self.type_notebook.set_current_page(0)
475 self.string_data_entry.grab_focus()
476 if self.reg_value.type == misc.REG_EXPAND_SZ:
477 self.type_notebook.set_current_page(0)
478 self.string_data_entry.grab_focus()
479 if self.reg_value.type == misc.REG_BINARY:
480 self.type_notebook.set_current_page(1)
481 self.binary_data_hex_text_view.grab_focus()
482 if self.reg_value.type == misc.REG_DWORD:
483 self.type_notebook.set_current_page(2)
484 self.number_data_entry.grab_focus()
485 if self.reg_value.type == misc.REG_DWORD_BIG_ENDIAN:
486 self.type_notebook.set_current_page(2)
487 self.number_data_entry.grab_focus()
488 if self.reg_value.type == misc.REG_MULTI_SZ:
489 self.type_notebook.set_current_page(3)
490 self.multi_string_data_text_view.grab_focus()
491 if self.reg_value.type == misc.REG_QWORD:
492 self.type_notebook.set_current_page(2)
493 self.number_data_entry.grab_focus()
495 self.name_entry.grab_focus()
497 def on_binary_data_hex_text_view_buffer_changed(self, widget):
498 if self.disable_signals:
500 self.disable_signals = True
502 hex_buffer = self.binary_data_hex_text_view.get_buffer() #this is the same as 'widget'
503 ascii_buffer = self.binary_data_ascii_text_view.get_buffer()
504 addr_buffer = self.binary_data_addr_text_view.get_buffer()
506 insert_iter = hex_buffer.get_iter_at_mark(hex_buffer.get_insert())
507 insert_char_offs = insert_iter.get_offset()
508 #print "cursor at:", insert_char_offs
510 text = hex_buffer.get_text(hex_buffer.get_start_iter(), hex_buffer.get_end_iter())
511 before_len = len(text)
512 text = RegValueEditDialog.check_hex_string(text).strip()
513 after_len = len(text)
515 hex_buffer.set_text(text)
516 ascii_buffer.set_text(RegValueEditDialog.hex_to_ascii(text))
517 addr_buffer.set_text(RegValueEditDialog.hex_to_addr(text))
519 #print "cursor now at:", insert_char_offs + (after_len - before_len)
520 hex_buffer.place_cursor(hex_buffer.get_iter_at_offset(insert_char_offs + self.hex_cursor_shift))
521 self.hex_cursor_shift = 0
522 self.disable_signals = False
524 def on_binary_data_hex_text_view_buffer_insert_text(self, widget, iter, text, length):
525 """callback for text inserted into the hex field. \nThe purpose of this function is only to update the cursor"""
526 if self.disable_signals:
528 self.disable_signals = True
530 offset = iter.get_offset()
531 whole_text = widget.get_text(widget.get_start_iter(), widget.get_end_iter())
533 #construct the final text
535 for i in range(offset):
536 final_text += whole_text[i]
539 for i in range(offset, len(whole_text)):
540 final_text += whole_text[i]
541 final_text = self.check_hex_string(final_text)
543 #here we properly adjust the cursor
545 limit = len(final_text) #it could be that the user typed an invalid character, so we'll play it safe
546 for i in range(offset, offset + length + count + 1): #go through the inserted characters and see if any have been replaced by white space
547 if (i < limit) and ((final_text[i] == ' ') or (final_text[i] == '\n')):
549 self.hex_cursor_shift = count
551 self.disable_signals = False
553 def on_binary_data_hex_text_view_buffer_delete_range(self, widget, start, end):
554 """callback for text inserted into the hex field. \nThe purpose of this function is only to update the cursor"""
555 if (self.disable_signals):
557 self.disable_signals = True
559 text = widget.get_text(start, end)
560 if (text == ' ') or (text == '\n'):
561 #if the user deleted whitespace, they probably wanted to delete whatever was before it
562 new_start = widget.get_iter_at_offset(start.get_offset() - 1)
563 #widget.delete(new_start, start) #if this worked as expected, programming would be too easy :P
565 self.disable_signals = False
567 def on_binary_data_ascii_text_view_buffer_changed(self, widget):
568 """this function formats the text in the ascii field whenever it's changed"""
569 if (self.disable_signals):
572 self.disable_signals = True
574 widget = self.binary_data_ascii_text_view.get_buffer()
576 #stuff we need to move the cursor properly later
577 cursor_iter = widget.get_iter_at_mark(widget.get_insert()) #insert means cursor, or "the insertion point" as gtk calls it
578 cursor_offset = cursor_iter.get_offset()
580 text = widget.get_text(widget.get_start_iter(), widget.get_end_iter())
581 text = self.check_ascii_string(text)
582 widget.set_text(text)
584 #Calling this function below will translate the hex back into our ascii box, making errors easier to spot
585 self.disable_signals = False
586 self.on_binary_data_hex_text_view_buffer_changed(None)
587 self.disable_signals = True
589 #now that we've overwritten everything in the textbuffer, we have to put the cursor back in the same spot
590 widget.place_cursor(widget.get_iter_at_offset(cursor_offset + self.ascii_cursor_shift))
591 self.ascii_cursor_shift = 0
593 self.disable_signals = False
595 def on_binary_data_ascii_text_view_buffer_insert_text(self, widget, iter, text, length):
596 if (self.disable_signals):
598 self.disable_signals = True
600 widget = self.binary_data_ascii_text_view.get_buffer()
602 #get stuff that we need
603 offset = iter.get_offset()
604 inclusive_text = widget.get_text(widget.get_start_iter(), iter)
605 hex_pos = int(iter.get_offset() * 3) #because each ascii character is 2 hex characters, plus a space
606 hex_pos -= inclusive_text.count('\n') * 2 #because '\n' counts as a character, but it doesn't take up 3 spaces in the hex string.
607 hex_buffer = self.binary_data_hex_text_view.get_buffer()
608 addr_buffer = self.binary_data_addr_text_view.get_buffer()
609 hex_text = hex_buffer.get_text(hex_buffer.get_start_iter(), hex_buffer.get_end_iter())
611 #insert into hex_text up to the point where the new character was inserted
613 for ch in hex_text: #this works best because the hex_pos can be greater than len(hex_text) when inserting at the end
614 if len(new_hex) >= hex_pos:
617 #insert the new character(s)
618 for i in range(length):
619 new_hex += "%X" % ((ord(text[i]) >> 4) & 0x0F) #handle the upper 4 bits of the char
620 new_hex += "%X " % (ord(text[i]) & 0x0F) #handle the lower 4 bits of the char
621 #insert the rest of the old characters into new_hex
622 while hex_pos < len(hex_text):
623 new_hex += hex_text[hex_pos]
625 new_hex = self.check_hex_string(new_hex)
627 #here we properly adjust the cursor
628 final_text = self.hex_to_ascii(new_hex)
630 for i in range(offset, offset + length + count): #go through the inserted characters and see if any have been replaced by '\n's
631 if (final_text[i] == '\n'):
633 hex_buffer.set_text(new_hex) #set the text
634 self.ascii_cursor_shift = count #tell the on_changed() function to shift the cursor, since it has no effect if we call place_cursor() from here
635 addr_buffer.set_text(self.hex_to_addr(new_hex)) #can't forget to update the address text!
636 self.disable_signals = False
638 def on_binary_data_ascii_text_view_buffer_delete_range(self, widget, start, end):
639 if (self.disable_signals):
641 self.disable_signals = True
643 #get stuff that we need
644 text = widget.get_text(start, end)
645 beginning_text = widget.get_text(widget.get_start_iter(), start)
646 inclusive_text = widget.get_text(widget.get_start_iter(), end)
647 hex_buffer = self.binary_data_hex_text_view.get_buffer()
648 addr_buffer = self.binary_data_addr_text_view.get_buffer()
649 hex_text = hex_buffer.get_text(hex_buffer.get_start_iter(), hex_buffer.get_end_iter())
650 new_end_iter = None #this will tell us if any extra characters need to be deleted later
652 if text == '\n': #we assume that the user pressed backspace and NOT delete. We don't get any indicator of which key was pressed so without adding another complex function, this is the best we can do
653 new_end_iter = start #so later we can delete from a new start to the current start
654 start = widget.get_iter_at_offset(start.get_offset() - 1) #also delete the character before the '\n'
656 #Adjust the values for use in the hex field. this is basically the same as count('\n') + 1
657 hex_start = int(start.get_offset() * 3) #because each ascii character is 2 hex characters, plus a space
658 hex_start -= beginning_text.count('\n') * 2 #because '\n' counts as a character, but it doesn't take up 3 spaces in the hex string.
659 hex_end = int(end.get_offset() * 3)
660 hex_end -= inclusive_text.count('\n') * 2
663 #insert into hex_text up to the point where characters were deleted
664 for i in range(hex_start):
665 new_hex += hex_text[i]
666 #insert the characters after the deleted characters. We simply ignore the deleted characters
667 for i in range(hex_end, len(hex_text)):
668 new_hex += hex_text[i]
670 hex_buffer.set_text(RegValueEditDialog.check_hex_string(new_hex)) #set the text
671 addr_buffer.set_text(RegValueEditDialog.hex_to_addr(new_hex)) #can't forget to update the address text!
673 if (new_end_iter is not None):
674 widget.delete(start, new_end_iter) #this causes a warning because of bad iterators! Makes no sense
676 self.disable_signals = False
678 def on_binary_data_ascii_text_view_move_cursor(self, textview, step_size, count, extend_selection):
679 """This function handles cursor movement. For now it only responds to text selection"""
680 print "ext_sel", extend_selection
681 #The following doesn't work... even if extend_selection is true, get_selection_bounds() still returns nothing
682 # if (not extend_selection) or (self.disable_signals):
684 # self.disable_signals = True
687 # ascii_buffer = textview.get_buffer()
688 # (start, end) = ascii_buffer.get_selection_bounds() #This function returns 2 iterators
689 # hex_buffer = self.binary_data_hex_text_view.get_buffer()
691 # hex_start = int(start.get_offset() * 3) #because each ascii character is 2 hex characters, plus a space
692 # hex_start -= (hex_start/25) * 2 #because '\n' counts as a character, but it doesn't take up 3 spaces in the hex string.
693 # hex_end = int(end.get_offset() * 3)
694 # hex_end -= (hex_end/25) * 2
695 # hex_buffer.select_range(hex_buffer.get_iter_at_offset(hex_start), hex_buffer.get_iter_at_offset(hex_end))
697 # self.disable_signals = False
699 def on_number_data_hex_radio_toggled(self, widget):
700 if (not widget.get_active()):
703 if (self.reg_value.type == misc.REG_QWORD):
708 number_str = self.number_data_entry.get_text()
709 if (len(number_str) == 0):
712 number = string.atoi(number_str, 10)
714 format = "%0" + str(digits) + "X"
716 self.number_data_entry.set_text(format % number)
718 def on_number_data_dec_radio_toggled(self, widget):
719 if (not widget.get_active()):
722 if (self.reg_value.type == misc.REG_QWORD):
727 number_str = self.number_data_entry.get_text()
728 if (len(number_str) == 0):
731 number = string.atoi(number_str, 0x10)
733 format = "%0" + str(digits) + "d"
735 self.number_data_entry.set_text(format % number)
737 def on_number_data_entry_changed(self, widget):
738 old_text = self.number_data_entry.get_text()
740 if (self.reg_value.type in [misc.REG_DWORD, misc.REG_DWORD_BIG_ENDIAN]):
746 if (self.number_data_hex_radio.get_active()):
748 if (ch in string.hexdigits):
750 if (len(new_text) > max_len):
751 new_text = new_text[:max_len]
755 if (ch in string.digits):
758 self.number_data_entry.set_text(new_text)
762 def remove_string_white_space(str):
763 return string.join(str.split(), "")
766 def check_hex_string(old_string, line_length=8, remove_orphaned = False):
770 for ch in old_string:
771 if (ch in string.hexdigits):
772 new_string += string.upper(ch)
776 insert_space = not insert_space
778 if (length >= line_length):
782 if (insert_space and remove_orphaned):
783 new_string = new_string.strip()[:len(new_string) - 1]
788 def check_ascii_string(string, line_length=8):
792 #insert a '\n' every line_length characters.
794 if ch != '\n': #ignore carrage returns alreadys present
797 if (length >= line_length):
801 return new_string.strip()
804 def hex_to_ascii(hex_string, line_length=8):
809 for ch in hex_string:
810 if (ch in string.hexdigits):
813 if (len(digits) >= 2):
814 new_chr = chr(string.atol(digits, 0x10))
815 if (new_chr in (string.punctuation + string.digits + string.ascii_letters + ' ')): #We don't just use string.printables because that inclues '\n' and '\r' which we don't want to put into the ascii box
816 ascii_string += new_chr
822 if (length >= line_length):
829 def hex_to_addr(old_string, line_length=8):
835 for ch in old_string:
836 if (ch in string.hexdigits):
839 if (len(digits) >= 2):
841 if (length % line_length) == 0:
842 new_string += "%04X\n" % addr
851 def byte_array_to_hex(array, line_length=8):
855 new_string += "%02x" % byte
857 return RegValueEditDialog.check_hex_string(new_string, line_length, False)
860 def hex_to_byte_array(hex_string):
864 for ch in hex_string:
865 if (ch in string.hexdigits):
868 if (len(digits) >= 2):
869 byte = string.atol(digits, 0x10)
876 class RegKeyEditDialog(gtk.Dialog):
878 def __init__(self, reg_key):
879 super(RegKeyEditDialog, self).__init__()
881 if (reg_key is None):
882 self.brand_new = True
883 self.reg_key = RegistryKey("", None)
886 self.brand_new = False
887 self.reg_key = reg_key
890 self.reg_key_to_values()
893 self.set_title(["Edit registry key", "New registry key"][self.brand_new])
894 self.set_border_width(5)
896 self.icon_registry_filename = os.path.join(sys.path[0], "images", "registry.png")
897 self.set_icon_from_file(self.icon_registry_filename)
899 self.set_resizable(False)
905 self.vbox.pack_start(hbox, False, False, 10)
907 label = gtk.Label("Key name:")
908 hbox.pack_start(label, False, True, 10)
910 self.name_entry = gtk.Entry()
911 self.name_entry.set_activates_default(True)
912 hbox.pack_start(self.name_entry, True, True, 10)
917 self.action_area.set_layout(gtk.BUTTONBOX_END)
919 self.cancel_button = gtk.Button("Cancel", gtk.STOCK_CANCEL)
920 self.cancel_button.set_flags(gtk.CAN_DEFAULT)
921 self.add_action_widget(self.cancel_button, gtk.RESPONSE_CANCEL)
923 self.apply_button = gtk.Button("Apply", gtk.STOCK_APPLY)
924 self.apply_button.set_flags(gtk.CAN_DEFAULT)
925 self.apply_button.set_sensitive(not self.brand_new) # disabled for new task
926 self.add_action_widget(self.apply_button, gtk.RESPONSE_APPLY)
928 self.ok_button = gtk.Button("OK", gtk.STOCK_OK)
929 self.ok_button.set_flags(gtk.CAN_DEFAULT)
930 self.add_action_widget(self.ok_button, gtk.RESPONSE_OK)
932 self.set_default_response(gtk.RESPONSE_OK)
937 def check_for_problems(self):
938 if (len(self.name_entry.get_text().strip()) == 0):
939 return "Please specify a name."
943 def reg_key_to_values(self):
944 if (self.reg_key is None):
945 raise Exception("registry key not set")
947 self.name_entry.set_text(self.reg_key.name)
949 def values_to_reg_key(self):
950 if (self.reg_key is None):
951 raise Exception("registry key not set")
953 self.reg_key.name = self.name_entry.get_text()
956 class RegRenameDialog(gtk.Dialog):
958 def __init__(self, reg_key, reg_value):
959 super(RegRenameDialog, self).__init__()
961 self.reg_key = reg_key
962 self.reg_value = reg_value
968 self.set_title(["Rename registry key", "Rename registry value"][self.reg_value is not None])
969 self.set_border_width(5)
971 self.icon_registry_filename = os.path.join(sys.path[0], "images", "registry.png")
972 self.set_icon_from_file(self.icon_registry_filename)
974 self.set_resizable(False)
980 self.vbox.pack_start(hbox, False, False, 10)
982 label = gtk.Label("Name:")
983 hbox.pack_start(label, False, True, 10)
985 self.name_entry = gtk.Entry()
986 self.name_entry.set_activates_default(True)
987 hbox.pack_start(self.name_entry, True, True, 10)
992 self.action_area.set_layout(gtk.BUTTONBOX_END)
994 self.cancel_button = gtk.Button("Cancel", gtk.STOCK_CANCEL)
995 self.cancel_button.set_flags(gtk.CAN_DEFAULT)
996 self.add_action_widget(self.cancel_button, gtk.RESPONSE_CANCEL)
998 self.apply_button = gtk.Button("Apply", gtk.STOCK_APPLY)
999 self.apply_button.set_flags(gtk.CAN_DEFAULT)
1000 self.add_action_widget(self.apply_button, gtk.RESPONSE_APPLY)
1002 self.ok_button = gtk.Button("OK", gtk.STOCK_OK)
1003 self.ok_button.set_flags(gtk.CAN_DEFAULT)
1004 self.add_action_widget(self.ok_button, gtk.RESPONSE_OK)
1006 self.set_default_response(gtk.RESPONSE_OK)
1011 def check_for_problems(self):
1012 if (len(self.name_entry.get_text().strip()) == 0):
1013 return "Please specify a name."
1016 def reg_to_values(self):
1017 if (self.reg_key is None):
1018 self.name_entry.set_text(self.reg_value.name)
1020 self.name_entry.set_text(self.reg_key.name)
1022 def values_to_reg(self):
1023 if (self.reg_key is None):
1024 self.reg_value.name = self.name_entry.get_text()
1026 self.reg_key.name = self.name_entry.get_text()
1028 class RegSearchDialog(gtk.Dialog):
1031 super(RegSearchDialog, self).__init__()
1038 self.set_title("Search the registry")
1039 self.set_border_width(5)
1041 self.icon_registry_filename = os.path.join(sys.path[0], "images", "registry.png")
1042 self.set_icon_from_file(self.icon_registry_filename)
1044 self.set_resizable(False)
1050 self.vbox.pack_start(hbox, False, False, 10)
1052 label = gtk.Label("Search for: ")
1053 hbox.pack_start(label, False, True, 10)
1055 self.search_entry = gtk.Entry()
1056 self.search_entry.set_activates_default(True)
1057 hbox.pack_start(self.search_entry, True, True, 10)
1062 frame = gtk.Frame("Match:")
1063 self.vbox.pack_start(frame, False, True, 0)
1066 vbox.set_border_width(4)
1069 self.check_match_keys = gtk.CheckButton("Keys")
1070 self.check_match_keys.set_active(True)
1071 vbox.pack_start(self.check_match_keys, False, False, 0)
1072 self.check_match_values = gtk.CheckButton("Values")
1073 self.check_match_values.set_active(True)
1074 vbox.pack_start(self.check_match_values, False, False, 0)
1075 self.check_match_data = gtk.CheckButton("Data")
1076 self.check_match_data.set_active(True)
1077 vbox.pack_start(self.check_match_data, False, False, 0)
1079 self.check_match_whole_string = gtk.CheckButton("Match whole string only")
1080 self.vbox.pack_start(self.check_match_whole_string, False, False, 5)
1085 self.action_area.set_layout(gtk.BUTTONBOX_END)
1087 self.cancel_button = gtk.Button("Cancel", gtk.STOCK_CANCEL)
1088 self.cancel_button.set_flags(gtk.CAN_DEFAULT)
1089 self.add_action_widget(self.cancel_button, gtk.RESPONSE_CANCEL)
1091 self.ok_button = gtk.Button("Search", gtk.STOCK_FIND)
1092 self.ok_button.set_flags(gtk.CAN_DEFAULT)
1093 self.add_action_widget(self.ok_button, gtk.RESPONSE_OK)
1095 self.set_default_response(gtk.RESPONSE_OK)
1100 def check_for_problems(self):
1101 if self.search_entry.get_text() == "":
1102 return ("You must enter text to search for!", gtk.MESSAGE_ERROR)
1103 elif not self.check_match_data.get_active() and not self.check_match_keys.get_active() and not self.check_match_values.get_active():
1104 return ("You much select at least one of: keys, values, or data to search", gtk.MESSAGE_ERROR)
1105 elif not self.check_match_whole_string.get_active() and not self.warned:
1106 for ch in self.search_entry.get_text():
1107 if ch in string.punctuation:
1109 return ("Search items should be separated by a space. Punctuation (such as commas) will be considered part of the search string.\n\nPress find again to continue anyways.", gtk.MESSAGE_INFO)
1113 class RegPermissionsDialog(gtk.Dialog):
1115 def __init__(self, users, permissions):
1116 super(RegPermissionsDialog, self).__init__()
1119 self.permissions = permissions
1123 if users is not None:
1125 self.user_store.append((user.username,
1129 self.set_title("Permissions")
1130 self.set_border_width(5)
1131 self.set_resizable(True)
1132 self.set_default_size(380, 480)
1134 self.icon_registry_filename = os.path.join(sys.path[0], "images", "registry.png")
1135 self.set_icon_from_file(self.icon_registry_filename)
1142 self.vbox.pack_start(vbox, True, True, 10)
1144 label = gtk.Label("Users:")
1145 label.set_alignment(0, 1)
1146 vbox.pack_start(label, False, False, 0)
1148 hpaned = gtk.HPaned()
1149 vbox.pack_start(hpaned, True, True, 0)
1151 scrolledwindow = gtk.ScrolledWindow(None, None)
1152 scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
1153 scrolledwindow.set_shadow_type(gtk.SHADOW_IN)
1154 hpaned.add1(scrolledwindow)
1156 self.user_tree_view = gtk.TreeView()
1157 self.user_tree_view.set_headers_visible(False)
1158 scrolledwindow.add(self.user_tree_view)
1160 column = gtk.TreeViewColumn()
1161 column.set_title("User")
1162 column.set_resizable(True)
1163 column.set_fixed_width(200)
1164 column.set_sort_column_id(0)
1165 renderer = gtk.CellRendererText()
1166 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1167 column.pack_start(renderer, True)
1168 self.user_tree_view.append_column(column)
1169 column.add_attribute(renderer, "text", 0)
1171 self.user_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
1172 self.user_tree_view.set_model(self.user_store)
1175 vbox.pack_start(hbox, False, False, 0)
1177 padding = gtk.HBox()
1178 hbox.pack_start(padding, True, True, 0)
1180 self.add_button = gtk.Button("Add", gtk.STOCK_ADD)
1181 hbox.pack_start(self.add_button, False, False, 2)
1183 self.remove_button = gtk.Button("Remove", gtk.STOCK_REMOVE)
1184 hbox.pack_start(self.remove_button, False, False, 2)
1191 self.vbox.pack_start(vbox, True, True, 10)
1193 self.permissions_label = gtk.Label("Permissions for UNKNOWN USER/GROUP:")
1194 self.permissions_label.set_alignment(0, 1)
1195 vbox.pack_start(self.permissions_label, False, False, 0)
1197 hpaned = gtk.HPaned()
1198 vbox.pack_start(hpaned, True, True, 0)
1200 scrolledwindow = gtk.ScrolledWindow(None, None)
1201 scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
1202 scrolledwindow.set_shadow_type(gtk.SHADOW_IN)
1203 hpaned.add1(scrolledwindow)
1205 self.permissions_tree_view = gtk.TreeView()
1206 scrolledwindow.add(self.permissions_tree_view)
1208 column = gtk.TreeViewColumn()
1209 column.set_title("Permission")
1210 column.set_resizable(True)
1211 column.set_min_width(160)
1212 column.set_sort_column_id(0)
1213 renderer = gtk.CellRendererText()
1214 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1215 column.pack_start(renderer, True)
1216 self.permissions_tree_view.append_column(column)
1217 column.add_attribute(renderer, "text", 0)
1219 column = gtk.TreeViewColumn()
1220 column.set_title("Allow")
1221 column.set_resizable(False)
1222 column.set_fixed_width(30)
1223 column.set_sort_column_id(1)
1224 renderer = gtk.CellRendererToggle()
1225 column.pack_start(renderer, True)
1226 self.permissions_tree_view.append_column(column)
1228 column = gtk.TreeViewColumn()
1229 column.set_title("Deny")
1230 column.set_resizable(False)
1231 column.set_fixed_width(30)
1232 column.set_sort_column_id(2)
1233 renderer = gtk.CellRendererToggle()
1234 column.pack_start(renderer, True)
1235 self.permissions_tree_view.append_column(column)
1237 self.permissions_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, gobject.TYPE_PYOBJECT)
1238 self.permissions_tree_view.set_model(self.permissions_store)
1241 vbox.pack_start(hbox, False, False, 0)
1243 padding = gtk.HBox()
1244 hbox.pack_start(padding, True, True, 0)
1246 self.advanced_button = gtk.Button("Advanced")
1247 hbox.pack_start(self.advanced_button, False, False, 2)
1253 self.action_area.set_layout(gtk.BUTTONBOX_END)
1255 self.cancel_button = gtk.Button("Cancel", gtk.STOCK_CANCEL)
1256 self.cancel_button.set_flags(gtk.CAN_DEFAULT)
1257 self.add_action_widget(self.cancel_button, gtk.RESPONSE_CANCEL)
1259 self.ok_button = gtk.Button("Ok", gtk.STOCK_OK)
1260 self.ok_button.set_flags(gtk.CAN_DEFAULT)
1261 self.add_action_widget(self.ok_button, gtk.RESPONSE_OK)
1263 self.ok_button = gtk.Button("Apply", gtk.STOCK_APPLY)
1264 self.ok_button.set_flags(gtk.CAN_DEFAULT)
1265 self.add_action_widget(self.ok_button, gtk.RESPONSE_APPLY)
1267 self.set_default_response(gtk.RESPONSE_APPLY)
1272 self.user_tree_view.get_selection().connect("changed", self.on_user_tree_view_selection_changed)
1273 self.add_button.connect("clicked", self.on_add_item_activate)
1274 self.remove_button.connect("clicked", self.on_remove_item_activate)
1276 #TODO: permission view data editing updates the store?
1277 self.advanced_button.connect("clicked", self.on_advanced_item_activate)
1279 def check_for_problems(self):
1280 #TODO: find problems?
1283 def on_user_tree_view_selection_changed(self, widget):
1284 self.permissions_store.clear()
1286 (iter, user) = self.get_selected_user()
1288 if (iter is not None):
1289 self.permissions_label.set_text("Permissions for " + user.username + ":")
1290 #TODO: update permissions view on selection changed
1292 self.permissions_label.set_text("")
1294 def on_add_item_activate(self, widget):
1295 #TODO: implement add user for permissions
1298 def on_remove_item_activate(self, widget):
1299 (iter, user) = self.get_selected_user()
1301 if (iter is not None):
1302 self.users.remove(user)
1303 self.user_store.remove(iter)
1304 #TODO: remove user permissions?
1306 def on_advanced_item_activate(self, widget):
1307 dialog = RegAdvancedPermissionsDialog(None, None)
1309 #TODO: handle advanced dialog
1314 def get_selected_user(self):
1315 (model, iter) = self.user_tree_view.get_selection().get_selected()
1316 if (iter is None): # no selection
1319 return (iter, model.get_value(iter, 1))
1321 class RegAdvancedPermissionsDialog(gtk.Dialog):
1322 def __init__(self, users, permissions):
1323 super(RegAdvancedPermissionsDialog, self).__init__()
1326 self.permissions = permissions
1330 self.insert_test_values() #TODO: remove
1333 self.on_auditing_tree_view_selection_changed(None)
1334 self.on_permissions_tree_view_selection_changed(None)
1337 self.set_title("Permissions")
1338 self.set_border_width(5)
1339 self.set_resizable(True)
1340 self.set_default_size(630, 490)
1342 self.icon_registry_filename = os.path.join(sys.path[0], "images", "registry.png")
1343 self.set_icon_from_file(self.icon_registry_filename)
1345 self.notebook = gtk.Notebook()
1346 self.vbox.pack_start(self.notebook, True, True, 0)
1352 hbox = gtk.HBox() #hbox is for the padding on the left & right.
1353 self.notebook.append_page(hbox, gtk.Label("Permissions"))
1356 hbox.pack_start(vbox, True, True, 10)
1358 label = gtk.Label("To view the details of special permissions entries, select it and then click Edit.\n")
1359 label.set_alignment(0, 0)
1360 vbox.pack_start(label, False, False, 15)
1362 label = gtk.Label("Permission entries:")
1363 label.set_alignment(0, 1)
1364 vbox.pack_start(label, False, False, 0)
1366 hpaned = gtk.HPaned()
1367 vbox.pack_start(hpaned, True, True, 0)
1369 scrolledwindow = gtk.ScrolledWindow(None, None)
1370 scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
1371 scrolledwindow.set_shadow_type(gtk.SHADOW_IN)
1372 hpaned.add1(scrolledwindow)
1374 self.permissions_tree_view = gtk.TreeView()
1375 scrolledwindow.add(self.permissions_tree_view)
1377 column = gtk.TreeViewColumn()
1378 column.set_title("Type")
1379 column.set_resizable(True)
1380 column.set_sort_column_id(0)
1381 renderer = gtk.CellRendererText()
1382 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1383 column.pack_start(renderer, True)
1384 self.permissions_tree_view.append_column(column)
1385 column.add_attribute(renderer, "text", 0)
1387 column = gtk.TreeViewColumn()
1388 column.set_title("Name")
1389 column.set_resizable(True)
1390 column.set_expand(True)
1391 column.set_sort_column_id(1)
1392 renderer = gtk.CellRendererText()
1393 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1394 column.pack_start(renderer, True)
1395 self.permissions_tree_view.append_column(column)
1396 column.add_attribute(renderer, "text", 1)
1398 column = gtk.TreeViewColumn()
1399 column.set_title("Permission")
1400 column.set_resizable(True)
1401 column.set_expand(True)
1402 column.set_sort_column_id(2)
1403 renderer = gtk.CellRendererText()
1404 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1405 column.pack_start(renderer, True)
1406 self.permissions_tree_view.append_column(column)
1407 column.add_attribute(renderer, "text", 2)
1409 column = gtk.TreeViewColumn()
1410 column.set_title("Inherited from")
1411 column.set_resizable(True)
1412 column.set_expand(True)
1413 column.set_sort_column_id(3)
1414 renderer = gtk.CellRendererText()
1415 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1416 column.pack_start(renderer, True)
1417 self.permissions_tree_view.append_column(column)
1418 column.add_attribute(renderer, "text", 3)
1420 column = gtk.TreeViewColumn()
1421 column.set_title("Applies to")
1422 column.set_resizable(True)
1423 column.set_expand(True)
1424 column.set_sort_column_id(4)
1425 renderer = gtk.CellRendererText()
1426 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1427 column.pack_start(renderer, True)
1428 self.permissions_tree_view.append_column(column)
1429 column.add_attribute(renderer, "text", 4)
1431 #Store contains: type (string), name (string), permission (string), inherited from (string), apply to (string, permissions (object)
1432 self.permissions_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
1433 self.permissions_tree_view.set_model(self.permissions_store)
1436 vbox.pack_start(hbox, False, False, 0)
1438 padding = gtk.HBox()
1439 hbox.pack_start(padding, True, True, 0)
1441 self.add_button_permissions = gtk.Button("Add", gtk.STOCK_ADD)
1442 hbox.pack_start(self.add_button_permissions, False, False, 2)
1444 self.edit_button_permissions = gtk.Button("Edit", gtk.STOCK_EDIT)
1445 hbox.pack_start(self.edit_button_permissions, False, False, 2)
1447 self.remove_button_permissions = gtk.Button("Remove", gtk.STOCK_REMOVE)
1448 hbox.pack_start(self.remove_button_permissions, False, False, 2)
1450 check_area = gtk.VBox()
1451 vbox.pack_start(check_area, False, False, 10)
1453 self.check_inherit_permissions = gtk.CheckButton("Inherit permissions from parents that apply to child objects.")
1454 check_area.pack_start(self.check_inherit_permissions, False, False, 0)
1457 check_area.pack_start(hbox, False, False, 0)
1459 self.replace_child_permissions_button = gtk.Button("Replace child permissions")
1460 hbox.pack_start(self.replace_child_permissions_button, False, False, 0)
1466 hbox = gtk.HBox() #hbox is for the padding on the left & right.
1467 self.notebook.append_page(hbox, gtk.Label("Auditing"))
1470 hbox.pack_start(vbox, True, True, 10)
1472 label = gtk.Label("To view the details of special auditing entries, select it and then click Edit.\n")
1473 label.set_alignment(0, 0)
1474 vbox.pack_start(label, False, False, 15)
1476 label = gtk.Label("Auditing entries:")
1477 label.set_alignment(0, 1)
1478 vbox.pack_start(label, False, False, 0)
1480 hpaned = gtk.HPaned()
1481 vbox.pack_start(hpaned, True, True, 0)
1483 scrolledwindow = gtk.ScrolledWindow(None, None)
1484 scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
1485 scrolledwindow.set_shadow_type(gtk.SHADOW_IN)
1486 hpaned.add1(scrolledwindow)
1488 self.auditing_tree_view = gtk.TreeView()
1489 scrolledwindow.add(self.auditing_tree_view)
1491 column = gtk.TreeViewColumn()
1492 column.set_title("Type")
1493 column.set_resizable(True)
1494 column.set_sort_column_id(0)
1495 renderer = gtk.CellRendererText()
1496 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1497 column.pack_start(renderer, True)
1498 self.auditing_tree_view.append_column(column)
1499 column.add_attribute(renderer, "text", 0)
1501 column = gtk.TreeViewColumn()
1502 column.set_title("Name")
1503 column.set_resizable(True)
1504 column.set_expand(True)
1505 column.set_sort_column_id(1)
1506 renderer = gtk.CellRendererText()
1507 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1508 column.pack_start(renderer, True)
1509 self.auditing_tree_view.append_column(column)
1510 column.add_attribute(renderer, "text", 1)
1512 column = gtk.TreeViewColumn()
1513 column.set_title("Permission")
1514 column.set_resizable(True)
1515 column.set_expand(True)
1516 column.set_sort_column_id(2)
1517 renderer = gtk.CellRendererText()
1518 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1519 column.pack_start(renderer, True)
1520 self.auditing_tree_view.append_column(column)
1521 column.add_attribute(renderer, "text", 2)
1523 column = gtk.TreeViewColumn()
1524 column.set_title("Inherited from")
1525 column.set_resizable(True)
1526 column.set_expand(True)
1527 column.set_sort_column_id(3)
1528 renderer = gtk.CellRendererText()
1529 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1530 column.pack_start(renderer, True)
1531 self.auditing_tree_view.append_column(column)
1532 column.add_attribute(renderer, "text", 3)
1534 column = gtk.TreeViewColumn()
1535 column.set_title("Applies to")
1536 column.set_resizable(True)
1537 column.set_expand(True)
1538 column.set_sort_column_id(4)
1539 renderer = gtk.CellRendererText()
1540 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1541 column.pack_start(renderer, True)
1542 self.auditing_tree_view.append_column(column)
1543 column.add_attribute(renderer, "text", 4)
1545 self.auditing_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
1546 self.auditing_tree_view.set_model(self.auditing_store)
1549 vbox.pack_start(hbox, False, False, 0)
1551 padding = gtk.HBox()
1552 hbox.pack_start(padding, True, True, 0)
1554 self.add_button_auditing = gtk.Button("Add", gtk.STOCK_ADD)
1555 hbox.pack_start(self.add_button_auditing, False, False, 2)
1557 self.edit_button_auditing = gtk.Button("Edit", gtk.STOCK_EDIT)
1558 hbox.pack_start(self.edit_button_auditing, False, False, 2)
1560 self.remove_button_auditing = gtk.Button("Remove", gtk.STOCK_REMOVE)
1561 hbox.pack_start(self.remove_button_auditing, False, False, 2)
1563 check_area = gtk.VBox()
1564 vbox.pack_start(check_area, False, False, 10)
1566 self.check_inherit_auditing = gtk.CheckButton("Inherit auditing options from parents that apply to child objects.")
1567 check_area.pack_start(self.check_inherit_auditing, False, False, 0)
1570 check_area.pack_start(hbox, False, False, 0)
1572 self.replace_child_auditing_button = gtk.Button("Replace child auditing options")
1573 hbox.pack_start(self.replace_child_auditing_button, False, False, 0)
1579 hbox = gtk.HBox() #hbox is for the padding on the left & right.
1580 self.notebook.append_page(hbox, gtk.Label("Ownership"))
1583 hbox.pack_start(vbox, True, True, 10)
1586 label = gtk.Label("You may take ownership of an object if you have the appropriate permissions.\n")
1587 label.set_alignment(0, 0)
1588 vbox.pack_start(label, False, False, 15)
1590 label = gtk.Label("Current owner of this item:")
1591 label.set_alignment(0, 1)
1592 vbox.pack_start(label, False, False, 0)
1594 textview = gtk.Entry()
1595 textview.set_editable(False)
1596 vbox.pack_start(textview, False, False, 0)
1598 label = gtk.Label("Change owner to:")
1599 label.set_alignment(0, 1)
1600 vbox.pack_start(label, False, False, 0)
1602 hpaned = gtk.HPaned()
1603 vbox.pack_start(hpaned, True, True, 0)
1605 scrolledwindow = gtk.ScrolledWindow(None, None)
1606 scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
1607 scrolledwindow.set_shadow_type(gtk.SHADOW_IN)
1608 hpaned.add1(scrolledwindow)
1610 self.owner_tree_view = gtk.TreeView()
1611 self.owner_tree_view.set_headers_visible(False)
1612 scrolledwindow.add(self.owner_tree_view)
1614 column = gtk.TreeViewColumn()
1615 column.set_title("Name")
1616 column.set_resizable(True)
1617 column.set_fixed_width(200)
1618 column.set_sort_column_id(0)
1619 renderer = gtk.CellRendererText()
1620 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
1621 column.pack_start(renderer, True)
1622 self.owner_tree_view.append_column(column)
1623 column.add_attribute(renderer, "text", 0)
1625 self.owner_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
1626 self.owner_tree_view.set_model(self.owner_store)
1628 self.check_replace_owner_child_objects = gtk.CheckButton("Replace ownership of child objects")
1629 vbox.pack_start(self.check_replace_owner_child_objects, False, False, 10)
1635 self.action_area.set_layout(gtk.BUTTONBOX_END)
1637 self.cancel_button = gtk.Button("Cancel", gtk.STOCK_CANCEL)
1638 self.cancel_button.set_flags(gtk.CAN_DEFAULT)
1639 self.add_action_widget(self.cancel_button, gtk.RESPONSE_CANCEL)
1641 self.ok_button = gtk.Button("Ok", gtk.STOCK_OK)
1642 self.ok_button.set_flags(gtk.CAN_DEFAULT)
1643 self.add_action_widget(self.ok_button, gtk.RESPONSE_OK)
1645 self.ok_button = gtk.Button("Apply", gtk.STOCK_APPLY)
1646 self.ok_button.set_flags(gtk.CAN_DEFAULT)
1647 self.add_action_widget(self.ok_button, gtk.RESPONSE_APPLY)
1649 self.set_default_response(gtk.RESPONSE_APPLY)
1651 # TODO: Effective permissions
1654 self.permissions_tree_view.get_selection().connect("changed", self.on_permissions_tree_view_selection_changed)
1655 self.auditing_tree_view.get_selection().connect("changed", self.on_auditing_tree_view_selection_changed)
1657 self.add_button_permissions.connect("clicked", self.on_add_permissions_button_clicked)
1658 self.edit_button_permissions.connect("clicked", self.on_edit_permissions_button_clicked)
1659 self.remove_button_permissions.connect("clicked", self.on_remove_permissions_button_clicked)
1660 self.replace_child_permissions_button.connect("clicked", self.on_replace_permissions_button_clicked)
1661 self.add_button_auditing.connect("clicked", self.on_add_auditing_button_clicked)
1662 self.edit_button_auditing.connect("clicked", self.on_edit_auditing_button_clicked)
1663 self.remove_button_auditing.connect("clicked", self.on_remove_auditing_button_clicked)
1664 self.replace_child_auditing_button.connect("clicked", self.on_replace_auditing_button_clicked)
1666 self.check_inherit_permissions.connect("clicked", self.on_check_inherit_permissions_changed)
1667 self.check_inherit_auditing.connect("clicked", self.on_check_inherit_auditing_changed)
1671 def insert_test_values(self):
1672 #TODO: remove this function when no longer needed
1673 self.check_inherit_permissions.set_active(True)
1674 self.check_inherit_auditing.set_active(True)
1676 user = User("Foo Bar", "", "", 0)
1677 self.permissions_store.append(("Allow", user.username, "Special Permissions", "Unicorns", "This key only", user))
1678 self.permissions_store.append(("Deny", "Pib", "Access to Playdoe", "HKEY_USERS", "This key and subkeys", user))
1680 self.auditing_store.append(("Deny", "Homer Simpson", "Double Rainbow", "HKEY_LOCAL_MACHINE\\made up key\\temp\\new", "This key and subkeys", user))
1681 self.auditing_store.append(("Allow", "Administrator", "Your Right to Party", "Earthworm Jim", "This key only", user))
1683 def get_selected_permission(self):
1684 (model, iter) = self.permissions_tree_view.get_selection().get_selected()
1685 if (iter is None): # no selection
1688 return (iter, model.get_value(iter, 1))
1690 def get_selected_audit(self):
1691 (model, iter) = self.auditing_tree_view.get_selection().get_selected()
1692 if iter is None: # no selection
1695 return (iter, model.get_value(iter, 1))
1697 def on_permissions_tree_view_selection_changed(self, widget):
1698 (iter, permission) = self.get_selected_permission()
1699 self.edit_button_permissions.set_sensitive(permission is not None)
1700 self.remove_button_permissions.set_sensitive(permission is not None)
1702 def on_auditing_tree_view_selection_changed(self, widget):
1703 (iter, audit) = self.get_selected_audit()
1704 self.edit_button_auditing.set_sensitive(audit is not None)
1705 self.remove_button_auditing.set_sensitive(audit is not None)
1707 def on_add_permissions_button_clicked(self, widget):
1711 def on_edit_permissions_button_clicked(self, widget):
1715 def on_remove_permissions_button_clicked(self, widget):
1716 (iter, permission) = self.get_selected_permission()
1717 if (iter is not None):
1718 self.permissions_store.remove(iter)
1720 def on_replace_permissions_button_clicked(self, widget):
1724 def on_add_auditing_button_clicked(self, widget):
1728 def on_edit_auditing_button_clicked(self, widget):
1732 def on_remove_auditing_button_clicked(self, widget):
1733 (iter, audit) = self.get_selected_audit()
1734 if (iter is not None):
1735 self.auditing_store.remove(iter)
1737 def on_replace_auditing_button_clicked(self, widget):
1741 def on_check_inherit_permissions_changed(self, widget):
1742 if widget.get_active():
1744 #TODO: if no permissions are inherited
1746 message_box = gtk.MessageDialog(self, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "Unchecking this option means permissions inherited from the parent object will be lost.\n\nDo you want to copy the inherited permissions for this object?")
1747 response = message_box.run()
1750 if (response == gtk.RESPONSE_YES):
1751 #TODO: copy permissions from the parent object
1753 elif (response == gtk.RESPONSE_NO):
1754 #TODO: delete all inherited permissions from the permissions store
1756 else:#probably gtk.RESPONSE_DELETE_EVENT (from pressing escape)
1757 widget.set_active(True)
1759 def on_check_inherit_auditing_changed(self, widget):
1760 if widget.get_active():
1762 #TODO: if no permissions are inherited
1764 message_box = gtk.MessageDialog(self, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "Unchecking this option means auditing options inherited from the parent object will be lost.\n\nDo you want to copy the inherited auditing options for this object?")
1765 response = message_box.run()
1768 if response == gtk.RESPONSE_YES:
1769 #TODO: copy auditing from the parent object
1771 elif response == gtk.RESPONSE_NO:
1772 #TODO: delete all inherited auditing from the permissions store
1774 else:#probably gtk.RESPONSE_DELETE_EVENT (from pressing escape)
1775 widget.set_active(True)
1778 class WinRegConnectDialog(gtk.Dialog):
1780 def __init__(self, server, transport_type, username, password=""):
1781 super(WinRegConnectDialog, self).__init__()
1783 self.server_address = server
1784 self.transport_type = transport_type
1785 self.username = username
1786 self.password = password
1790 self.update_sensitivity()
1793 self.set_title("Connect to a server")
1794 self.set_border_width(5)
1795 self.set_icon_name(gtk.STOCK_CONNECT)
1796 self.set_resizable(False)
1801 self.vbox.set_spacing(5)
1803 self.server_frame = gtk.Frame("Server")
1804 self.vbox.pack_start(self.server_frame, False, True, 0)
1806 table = gtk.Table(3, 2)
1807 table.set_border_width(5)
1808 self.server_frame.add(table)
1810 label = gtk.Label(" Server address: ")
1811 label.set_alignment(0, 0.5)
1812 table.attach(label, 0, 1, 0, 1, gtk.FILL, gtk.FILL | gtk.EXPAND, 0, 0)
1814 self.server_address_entry = gtk.Entry()
1815 self.server_address_entry.set_text(self.server_address)
1816 self.server_address_entry.set_activates_default(True)
1817 table.attach(self.server_address_entry, 1, 2, 0, 1, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 1, 1)
1819 label = gtk.Label(" Username: ")
1820 label.set_alignment(0, 0.5)
1821 table.attach(label, 0, 1, 1, 2, gtk.FILL, gtk.FILL | gtk.EXPAND, 0, 0)
1823 self.username_entry = gtk.Entry()
1824 self.username_entry.set_text(self.username)
1825 self.username_entry.set_activates_default(True)
1826 table.attach(self.username_entry, 1, 2, 1, 2, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 1, 1)
1828 label = gtk.Label(" Password: ")
1829 label.set_alignment(0, 0.5)
1830 table.attach(label, 0, 1, 2, 3, gtk.FILL, gtk.FILL | gtk.EXPAND, 0, 0)
1832 self.password_entry = gtk.Entry()
1833 self.password_entry.set_text(self.password)
1834 self.password_entry.set_visibility(False)
1835 self.password_entry.set_activates_default(True)
1836 table.attach(self.password_entry, 1, 2, 2, 3, gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 1, 1)
1841 self.transport_frame = gtk.Frame(" Transport type ")
1842 self.vbox.pack_start(self.transport_frame, False, True, 0)
1845 vbox.set_border_width(5)
1846 self.transport_frame.add(vbox)
1848 self.rpc_smb_tcpip_radio_button = gtk.RadioButton(None, "RPC over SMB over TCP/IP")
1849 self.rpc_smb_tcpip_radio_button.set_active(self.transport_type == 0)
1850 vbox.pack_start(self.rpc_smb_tcpip_radio_button)
1852 self.rpc_tcpip_radio_button = gtk.RadioButton(self.rpc_smb_tcpip_radio_button, "RPC over TCP/IP")
1853 self.rpc_tcpip_radio_button.set_active(self.transport_type == 1)
1854 vbox.pack_start(self.rpc_tcpip_radio_button)
1856 self.localhost_radio_button = gtk.RadioButton(self.rpc_tcpip_radio_button, "Localhost")
1857 self.localhost_radio_button.set_active(self.transport_type == 2)
1858 vbox.pack_start(self.localhost_radio_button)
1863 self.action_area.set_layout(gtk.BUTTONBOX_END)
1865 self.cancel_button = gtk.Button("Cancel", gtk.STOCK_CANCEL)
1866 self.add_action_widget(self.cancel_button, gtk.RESPONSE_CANCEL)
1868 self.connect_button = gtk.Button("Connect", gtk.STOCK_CONNECT)
1869 self.connect_button.set_flags(gtk.CAN_DEFAULT)
1870 self.add_action_widget(self.connect_button, gtk.RESPONSE_OK)
1872 self.set_default_response(gtk.RESPONSE_OK)
1877 self.rpc_smb_tcpip_radio_button.connect("toggled", self.on_radio_button_toggled)
1878 self.rpc_tcpip_radio_button.connect("toggled", self.on_radio_button_toggled)
1879 self.localhost_radio_button.connect("toggled", self.on_radio_button_toggled)
1881 def update_sensitivity(self):
1882 server_required = not self.localhost_radio_button.get_active()
1884 self.server_address_entry.set_sensitive(server_required)
1886 def get_server_address(self):
1887 return self.server_address_entry.get_text().strip()
1889 def get_transport_type(self):
1890 if self.rpc_smb_tcpip_radio_button.get_active():
1892 elif self.rpc_tcpip_radio_button.get_active():
1894 elif self.localhost_radio_button.get_active():
1899 def get_username(self):
1900 return self.username_entry.get_text().strip()
1902 def get_password(self):
1903 return self.password_entry.get_text()
1905 def on_radio_button_toggled(self, widget):
1906 self.update_sensitivity()