Larger python qt pyqt example
This is my OLD blog. I've copied this post over to my NEW blog at:
http://www.saltycrane.com/blog/2006/12/larger-python-qt-pyqt-example/
You should be redirected in 2 seconds.
This script is used to parse Windows Event Viewer logs. It uses dumpel.exe. It colors significant events and presents results in a QT GUI.
"""windows_audit.py
"""
__author__ = "So Feng"
__version__ = "$Revision: 1.0 $"
__date__ = "$Date: 2006/10/17 $"
__license__ = "Python"
import re
import datetime
from datetime import date
import time
import glob
import os
import sys
from Qt import *
import StringIO
# constants
NCHARS_TO_WRAP = 30
EARLY_HOUR = 6
LATE_HOUR = 20
outfile = "audit_" + str(datetime.date.today()) + ".txt"
red_eventids = ["560","565","592","678"] orange_eventids = ["539","629","644","531","544","545","675","676"]
yellow_eventids = ["529","530","532","533","534","535","536","537","681",
"576","608","609","610","611","624","625","626","627",
"628","630","631","632","633","634","635","636","637",
"638","639","640","641","642","643","645","646","647",
"648","649","650","651","652","653","654","655","656",
"657","658","659","660","661","662","663","664","665",
"666","667","668","669","670","672"]
green_eventids = ["528", "538", "540", "680"] other_eventids = ["612", "617", "618", "619"] failure_list = ('529', '530', '531', '532', '533', '534', '535', '536', '537', '539', '544', '545', '546', '547', '616', '675', '676', '677', '679', '681', ) success_list = ('512', '513', '514', '515', '516', '517', '518', '528', '538', '540', '541', '542', '543', '560', '561', '562', '563', '564', '565', '566', '576', '577', '578', '592', '593', '594', '595', '608', '609', '610', '611', '612', '613', '614', '615', '617', '618', '619', '620', '624', '625', '626', '627', '628', '630', '631', '632', '633', '634', '635', '636', '637', '638', '639', '640', '641', '642', '643', '644', '645', '646', '647', '648', '649', '650', '651', '652', '653', '654', '655', '656', '657', '658', '659', '660', '661', '662', '663', '664', '665', '666', '667', '668', '669', '670', '672', '673', '674', '678', '680', '682', '683', ) event_desc = {
'512': 'Windows NT is starting up. ',
'513': 'Windows NT is shutting down.\n All logon sessions will be terminated by this shutdown. ',
'514': 'An authentication package has been loaded by the Local Security Authority.\n This authentication package will be used to authenticate logon attempts. ',
'515': 'A trusted logon process has registered with the Local Security Authority.\n This logon process will be trusted to submit logon requests. ',
'516': 'Internal resources allocated for the queuing of audit messages have been\n exhausted, leading to the loss of some audits. ',
'517': 'The audit log was cleared ',
'518': 'An notification package has been loaded by the Security Account Manager.\n This package will be notified of any account or password changes. ',
'528': 'Successful Logon: ',
'529': 'Logon Failure Unknown user name or bad password',
'530': 'Logon Failure Account logon time restriction violation',
'531': 'Logon Failure Account currently disabled',
'532': 'Logon Failure The specified user account has expired',
'533': 'Logon Failure User not allowed to logon at this computer',
'534': 'Logon Failure The user has not been granted the requested \n logon type at this machine',
'535': 'Logon Failure The specified account\'s password has expired',
'536': 'Logon Failure The NetLogon component is not active',
'537': 'Logon Failure An unexpected error occurred during logon',
'538': 'User Logoff ',
'539': 'Logon Failure Account locked out',
'540': 'Successful Network Logon ',
'541': 'IKE security association established. ',
'542': 'IKE security association ended. ',
'543': 'IKE security association ended. ',
'544': 'IKE security association establishment failed because peer could not\n authenticate. The certificate trust could not be established. ',
'545': 'IKE peer authentication failed. ',
'546': 'IKE security association establishment failed because peer\n sent invalid proposal. ',
'547': 'IKE security association negotiation failed. ',
'560': 'Object Open ',
'561': 'Handle Allocated ',
'562': 'Handle Closed ',
'563': 'Object Open for Delete ',
'564': 'Object Deleted ',
'565': 'Object Open ',
'566': 'Object Operation ',
'576': 'Special privileges assigned to new logon: ',
'577': 'Privileged Service Called ',
'578': 'Privileged object operation ',
'592': 'A new process has been created ',
'593': 'A process has exited ',
'594': 'A handle to an object has been duplicated ',
'595': 'Indirect access to an object has been obtained ',
'608': 'User Right Assigned ',
'609': 'User Right Removed ',
'610': 'New Trusted Domain ',
'611': 'Removing Trusted Domain ',
'612': 'Audit Policy Change ',
'613': 'IPSec policy agent started ',
'614': 'IPSec policy agent disabled ',
'615': 'IPSEC PolicyAgent Service: %1 ',
'616': 'IPSec policy agent encountered a potentially serious failure. ',
'617': 'Kerberos Policy Changed ',
'618': 'Encrypted Data Recovery Policy Changed ',
'619': 'Quality of Service Policy Changed ',
'620': 'Trusted Domain Information Modified: ',
'624': 'User Account Created ',
'625': 'User Account Type Change ',
'626': 'User Account Enabled ',
'627': 'Change Password Attempt ',
'628': 'User Account password set ',
'630': 'User Account Deleted: ',
'631': 'Security Enabled Global Group Created ',
'632': 'Security Enabled Global Group Member Added ',
'633': 'Security Enabled Global Group Member Removed ',
'634': 'Security Enabled Global Group Deleted ',
'635': 'Security Enabled Local Group Created ',
'636': 'Security Enabled Local Group Member Added ',
'637': 'Security Enabled Local Group Member Removed ',
'638': 'Security Enabled Local Group Deleted ',
'639': 'Security Enabled Local Group Changed ',
'640': 'General Account Database Change ',
'641': 'Security Enabled Global Group Changed ',
'642': 'User Account Changed ',
'643': 'Domain Policy Changed: %1 modified ',
'644': 'User Account Locked Out ',
'645': 'Computer Account Created ',
'646': 'Computer Account Changed ',
'647': 'Computer Account Deleted ',
'648': 'Security Disabled Local Group Created ',
'649': 'Security Disabled Local Group Changed ',
'650': 'Security Disabled Local Group Member Added ',
'651': 'Security Disabled Local Group Member Removed ',
'652': 'Security Disabled Local Group Deleted ',
'653': 'Security Disabled Global Group Created ',
'654': 'Security Disabled Global Group Changed ',
'655': 'Security Disabled Global Group Member Added ',
'656': 'Security Disabled Global Group Member Removed ',
'657': 'Security Disabled Global Group Deleted ',
'658': 'Security Enabled Universal Group Created ',
'659': 'Security Enabled Universal Group Changed ',
'660': 'Security Enabled Universal Group Member Added ',
'661': 'Security Enabled Universal Group Member Removed ',
'662': 'Security Enabled Universal Group Deleted ',
'663': 'Security Disabled Universal Group Created ',
'664': 'Security Disabled Universal Group Changed ',
'665': 'Security Disabled Universal Group Member Added ',
'666': 'Security Disabled Universal Group Member Removed ',
'667': 'Security Disabled Universal Group Deleted ',
'668': 'Group Type Changed ',
'669': 'Add SID History ',
'670': 'Add SID History ',
'672': 'Authentication Ticket Granted ',
'673': 'Service Ticket Granted ',
'674': 'Ticket Granted Renewed ',
'675': 'Pre-authentication failed ',
'676': 'Authentication Ticket Request Failed ',
'677': 'Authentication Ticket Request Failed ',
'678': 'Account Mapped for Logon by: %1 ',
'679': 'The name: %2 could not be mapped for logon by: %1 ',
'680': 'Account Used for Logon by: %1 ',
'681': 'The logon to account: %2 by: %1 from workstation: %3 failed. The error code was: %4 ',
'682': 'Session reconnected to winstation: ',
'683': 'Session disconnected from winstation: ',
}
#sys.stderr = StringIO.StringIO()
#sys.stdout = StringIO.StringIO()
################################################################
################################################################
def main():
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(True)
form = StartForm()
form.show()
report = ReportWindow()
app.connect(form, SIGNAL("okClicked"),
report.create)
sys.exit(app.exec_())
################################################################
################################################################
class StartForm(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# # directory tree
# label_file = QLabel()
# label_file.setText("Select file:")
# dirmodel = QDirModel()
# treeview = QTreeView(self)
# treeview.setModel(dirmodel)
# treeview.setRootIndex(dirmodel.index(QDir.currentPath()))
# treeview.hideColumn(1)
# treeview.hideColumn(2)
# treeview.hideColumn(3)
# treeview.header().hide()
# date box
self.label_date = QLabel()
self.label_date.setText("Set date of last audit:")
default = datetime.date.today() - datetime.timedelta(10)
self.datebox = QDateEdit(QDate(default.year, default.month, default.day))
# buttons
spacer = QSpacerItem(20,40,QSizePolicy.Minimum,QSizePolicy.Expanding)
self.button_ok = QPushButton()
self.button_ok.setText("OK")
self.button_ok.setDefault(True)
button_cancel = QPushButton()
button_cancel.setText("Cancel")
# layout
# layout_left = QVBoxLayout()
# layout_left.addWidget(label_file)
# layout_left.addWidget(treeview)
layout_right = QVBoxLayout(self)
layout_right.addWidget(self.label_date)
layout_right.addWidget(self.datebox)
layout_right.addItem(spacer)
layout_right.addWidget(self.button_ok)
layout_right.addWidget(button_cancel)
# layout = QHBoxLayout(self)
# layout.addLayout(layout_left)
# layout.addLayout(layout_right)
# connections
self.connect(button_cancel, SIGNAL("clicked()"),
self.close)
self.connect(self.button_ok, SIGNAL("clicked()"),
self.ok_clicked)
def ok_clicked(self):
self.label_date.setText("Getting eventlog data...")
year = self.datebox.date().year()
month = self.datebox.date().month()
day = self.datebox.date().day()
delta = datetime.date.today() - datetime.date(int(year),int(month),int(day))
self.emit(SIGNAL("okClicked"), delta.days)
self.close()
################################################################
################################################################
class ReportWindow(QMainWindow):
def __init__(self, *args):
QMainWindow.__init__(self, *args)
# self.cb = QCheckBox()
self.table = MyTable()
self.textbrowser = QTextBrowser()
self.textbrowser.setFontFamily("Courier")
self.textbrowser.setFontPointSize(10)
splitter = QSplitter(Qt.Vertical, self)
# splitter = QSplitter(Qt.Vertical)
splitter.addWidget(self.table)
splitter.addWidget(self.textbrowser)
# vlayout = QVBoxLayout(self)
# vlayout.addWidget(self.cb)
# vlayout.addWidget(splitter)
self.setGeometry(100,100,750,550)
self.setCentralWidget(splitter)
def create(self, date):
self.table.parse_event_log(date)
self.table.setdata()
fh = open(outfile, "r")
text = fh.read()
self.textbrowser.setPlainText(text)
self.show()
################################################################
################################################################
class MyTable(QTableWidget):
def __init__(self, *args):
QTableWidget.__init__(self, *args)
self.setSortingEnabled(True)
self.setSelectionMode(self.ContiguousSelection)
#self.setFixedWidth(750)
self.setGeometry(0,0,700,400)
self.data = []
def setdata(self):
if len(self.data) == 0:
self.setRowCount(1)
self.setColumnCount(1)
newitem = QTableWidgetItem("No data for this date range.")
self.setItem(0, 0, newitem)
self.resizeColumnsToContents()
else:
self.nrows = len(self.data)
self.ncols = len(self.data[0])
self.setRowCount(self.nrows)
self.setColumnCount(self.ncols)
self.setmydata_list()
self.resizeColumnsToContents()
self.setGridStyle(Qt.DotLine)
self.setShowGrid(False)
self.setColumnWidth(3, 250)
#self.resizeRowsToContents()
#self.setHorizontalHeaderLabels(['date','time','?','?','event','source','user','?','computer','data'])
self.setHorizontalHeaderLabels(['Date','Time','Type','Event','User','Computer','Data'])
def setmydata_list(self):
n = 0
date_prev = ''
for row in self.data:
# event processing
event = row[4]
try:
row[4] = event + ": " + event_desc[event]
except:
pass
color = QColor("white")
if event in red_eventids:
color = QColor("red")
elif event in orange_eventids:
color = QColor("orange")
elif event in yellow_eventids:
color = QColor("yellow")
elif event in green_eventids:
#color = QColor("green")
pass
elif event in other_eventids:
color = QColor("blue")
# success or failure processing
if row[2] == "8":
row[2] = "Success"
icon = QIcon("success.png")
elif row[2] == "16":
row[2] = "Failure"
icon = QIcon("failure.png")
else:
row[2] = "Unknown"
icon = QIcon("unknown.png")
# date processing
row[0] = format_datetime(row[0], row[1])
(date, thetime) = re.split(r"\n", row[0])
newday = False
if date != date_prev:
newday = True
date_prev = date
thetime = re.split(r":", thetime)
hour = int(thetime[0])
if hour <= EARLY_HOUR or hour >= LATE_HOUR:
colordate = QColor(0,0,102)
else:
colordate = QColor("white")
# user
(dom, user) = re.split(r"\\", row[6])
row[6] = user
if user in ("SYSTEM", "NETWORK SERVICE", "LOCAL SERVICE", "ANONYMOUS LOGON"):
textcolor = QColor("gray")
font = QFont("Arial", 8)
else:
textcolor = QColor("black")
font = QFont("Arial", 8)
font.setBold(True)
# insert line
if newday:
m = 0
for j in range(len(row)-3):
text = ""
if j == 0:
text = date
newitem = QTableWidgetItem(text)
newitem.setBackgroundColor(QColor("black"))
self.setItem(n, m, newitem)
m += 1
self.setRowHeight(n, 15)
n += 1
#for item in row:
m = 0
for j in range(len(row)):
# skip these columns
if j in (3,5,7):
continue
item = row[j]
if j == 1:
color2 = colordate
else:
color2 = color
newitem = QTableWidgetItem(item)
newitem.setBackgroundColor(color2)
newitem.setTextColor(textcolor)
newitem.setFont(font)
newitem.setTextAlignment(Qt.AlignTop)
newitem.setToolTip(item)
if j == 2:
newitem.setIcon(icon)
self.setItem(n, m, newitem)
m += 1
self.setRowHeight(n, 16)
n += 1
def parse_event_log(self, ndays):
"""Parses event log file.
Returns none.
"""
# run dumpel.exe
os.system("dumpel -f dumpel_results.txt -l security -d %s" % ndays)
fin = open("dumpel_results.txt")
lines = fin.readlines()
# open output files
#outfile = "audit_" + str(datetime.date.today()) + ".txt"
fout=open(outfile,'w')
# initialization
fout.write("LOGON/LOGOFFS:\n")
fout.write("--------------\n")
output = "%-13s %3s %11s %12s %12s\n" % ('user','day','date','logon','logoff')
fout.write(output)
event578_count = 0
user_logged_in = 0
red_events = []
orange_events = []
yellow_events = []
# loop on each line in the file
for line in lines:
items = re.split('\t', line)
self.data.append(items)
date = items[0]
time = items[1]
event = items[4]
(dom, user) = re.split(r"\\", items[6])
day = get_weekday(date)
if event in red_eventids:
red_events.append(line)
elif event in orange_eventids:
orange_events.append(line)
elif event in yellow_eventids:
yellow_events.append(line)
elif user != "SYSTEM":
#if (not user_logged_in) and (event == "528"):
if event == "528":
if user_logged_in:
output = "%-13s %3s %11s %12s %12s\n" % (user,day,logon_date,logon_time,'no logout')
fout.write(output)
logon_time = time
logon_user = user
logon_date = date
logout_backup = ""
user_logged_in = 1
elif user_logged_in and event == "578":
if user == logon_user:
if event578_count == 0:
event578_count = 1
elif event578_count == 1:
event578_count = 0
user_logged_in = 0
output = "%-13s %3s %11s %12s %12s\n" % (user,day,logon_date,logon_time,time)
fout.write(output)
# print red events
fout.write("\nRED EVENTS:\n")
fout.write("-----------\n")
if len(red_events) == 0:
fout.write("None.\n")
else:
for event in red_events:
fout.write(event)
# print orange events
fout.write("\nORANGE EVENTS:\n")
fout.write("--------------\n")
if len(orange_events) == 0:
fout.write("None.\n")
else:
for event in orange_events:
fout.write(event)
# print yellow events
fout.write("\nYELLOW EVENTS:\n")
fout.write("--------------\n")
if len(yellow_events) == 0:
fout.write("None.\n")
else:
for event in yellow_events:
fout.write(event)
# close files
fin.close()
fout.close()
# print message
print "Parse sucessful.\n"
return
################################################################
################################################################
def get_weekday(date):
(month,day,year) = re.split('/', date)
weekday = datetime.date(int(year),int(month),int(day)).weekday()
day_names = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']
return day_names[weekday]
################################################################
################################################################
def format_datetime(date, thetime):
(month,day,year) = re.split('/', date)
dateobj = datetime.date(int(year),int(month),int(day))
newdate = "%04d/%02d/%02d" % (dateobj.year, dateobj.month, dateobj.day)
timeobj = time.strptime(thetime, "%I:%M:%S %p")
newtime = time.strftime("%H:%M:%S", timeobj)
return newdate + "\n" + newtime
################################################################
################################################################
def get_dateobject(date):
(month,day,year) = re.split('/', date)
return datetime.date(int(year),int(month),int(day))
################################################################
################################################################
if __name__ == "__main__":
main()
1 comment:
Hello
Thanks for your postings.
What is the best way to deal with null dates in a QDateEdit? - ie the end date for a particular date range that hasn't ended yet? I want the user to set the date and not have a date equivalent of null displayed.
Post a Comment