diff --git a/authorization/authorization.py b/authorization/authorization.py
index c519abe..f1a26c8 100644
--- a/authorization/authorization.py
+++ b/authorization/authorization.py
@@ -16,6 +16,8 @@
from java.net import URL
import re
+from thread import start_new_thread
+
def tool_needs_to_be_ignored(self, toolFlag):
for i in range(0, self.IFList.getModel().getSize()):
if self.IFList.getModel().getElementAt(i).split(":")[0] == "Ignore spider requests":
@@ -41,7 +43,6 @@ def capture_last_authorization_header(self, messageInfo):
self.lastAuthorizationHeader = authorization
self.fetchAuthorizationHeaderButton.setEnabled(True)
-
def valid_tool(self, toolFlag):
return (toolFlag == self._callbacks.TOOL_PROXY or
(toolFlag == self._callbacks.TOOL_REPEATER and
@@ -190,25 +191,179 @@ def handle_message(self, toolFlag, messageIsRequest, messageInfo):
return
if no_filters_defined(self):
- checkAuthorization(self, messageInfo,
- self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),
- self.doUnauthorizedRequest.isSelected())
+ # checkAuthorization(self, messageInfo,
+ # self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),
+ # self.doUnauthorizedRequest.isSelected())
+ checkAuthorizationAllUsers(self, messageInfo, self.doUnauthorizedRequest.isSelected())
else:
if message_passed_interception_filters(self, messageInfo):
- checkAuthorization(self, messageInfo,self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())
+ # checkAuthorization(self, messageInfo,self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())
+ checkAuthorizationAllUsers(self, messageInfo, self.doUnauthorizedRequest.isSelected())
+
+def checkAuthorizationAllUsers(self, messageInfo, checkUnauthorized=True):
+ originalHeaders = self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders()
+
+ requestResponseUnauthorized = None
+ impressionUnauthorized = "Disabled"
+
+ if checkUnauthorized:
+ messageUnauthorized = makeMessage(self, messageInfo, True, False)
+ requestResponseUnauthorized = makeRequest(self, messageInfo, messageUnauthorized)
+ if requestResponseUnauthorized and requestResponseUnauthorized.getResponse():
+ unauthorizedResponse = requestResponseUnauthorized.getResponse()
+ analyzedResponseUnauthorized = self._helpers.analyzeResponse(unauthorizedResponse)
+ statusCodeUnauthorized = analyzedResponseUnauthorized.getHeaders()[0]
+ contentUnauthorized = getResponseBody(self, requestResponseUnauthorized)
+
+ message = makeMessage(self, messageInfo, True, True)
+ requestResponse = makeRequest(self, messageInfo, message)
+ newResponse = requestResponse.getResponse()
+ analyzedResponse = self._helpers.analyzeResponse(newResponse)
+
+ oldStatusCode = originalHeaders[0]
+ newStatusCode = analyzedResponse.getHeaders()[0]
+ oldContent = getResponseBody(self, messageInfo)
+ newContent = getResponseBody(self, requestResponse)
+
+ EDFiltersUnauth = self.EDModelUnauth.toArray()
+ impressionUnauthorized = checkBypass(self, oldStatusCode, statusCodeUnauthorized,
+ oldContent, contentUnauthorized,
+ EDFiltersUnauth, requestResponseUnauthorized,
+ self.AndOrTypeUnauth.getSelectedItem())
+
+ self._lock.acquire()
+
+ row = self._log.size()
+ method = self._helpers.analyzeRequest(messageInfo.getRequest()).getMethod()
+ original_url = self._helpers.analyzeRequest(messageInfo).getUrl()
+
+ logEntry = LogEntry(self.currentRequestNumber,
+ method,
+ original_url,
+ messageInfo,
+ requestResponseUnauthorized if checkUnauthorized else None,
+ impressionUnauthorized)
+
+ for user_id, user_data in self.userTab.user_tabs.items():
+ user_name = user_data['user_name']
+ ed_instance = user_data['ed_instance']
+ mr_instance = user_data['mr_instance']
+
+ message = makeUserMessage(self, messageInfo, True, True, mr_instance)
+ requestResponse = makeRequest(self, messageInfo, message)
+
+ if requestResponse and requestResponse.getResponse():
+ newResponse = requestResponse.getResponse()
+ analyzedResponse = self._helpers.analyzeResponse(newResponse)
+ newStatusCode = analyzedResponse.getHeaders()[0]
+ oldContent = getResponseBody(self, messageInfo)
+ newContent = getResponseBody(self, requestResponse)
+
+ EDFilters = ed_instance.EDModel.toArray()
+ impression = checkBypass(self, originalHeaders[0], newStatusCode, oldContent, newContent,
+ EDFilters, requestResponse, ed_instance.AndOrType.getSelectedItem())
+
+ savedRequestResponse = self._callbacks.saveBuffersToTempFiles(requestResponse)
+ logEntry.add_user_enforcement(user_id, savedRequestResponse, impression)
+
+ self._log.add(logEntry)
+ SwingUtilities.invokeLater(UpdateTableEDT(self,"insert",row,row))
+ self.currentRequestNumber = self.currentRequestNumber + 1
+ self._lock.release()
+
+def makeUserMessage(self, messageInfo, removeOrNot, authorizeOrNot, mr_instance):
+ requestInfo = self._helpers.analyzeRequest(messageInfo)
+ headers = list(requestInfo.getHeaders())
+
+ if removeOrNot:
+ if hasattr(self, 'replaceString') and self.replaceString.getText():
+ removeHeaders = self.replaceString.getText().split('\n')
+ removeHeaders = [header.split(':')[0].strip() + ':' for header in removeHeaders if ':' in header]
+
+ headers_to_remove = []
+ for header in headers[1:]:
+ for removeHeader in removeHeaders:
+ if header.lower().startswith(removeHeader.lower()):
+ headers_to_remove.append(header)
+
+ for header in headers_to_remove:
+ if header in headers:
+ headers.remove(header)
+
+ if authorizeOrNot:
+ for i in range(mr_instance.MRModel.getSize()):
+ rule_key = mr_instance.MRModel.getElementAt(i)
+ rule_data = mr_instance.badProgrammerMRModel.get(rule_key)
+
+ if rule_data:
+ rule_type = rule_data['type']
+ match_pattern = rule_data['match']
+ replace_pattern = rule_data['replace']
+ regex_match = rule_data.get('regexMatch')
+
+ if rule_type == "Headers (simple string):":
+ modifiedHeaders = [h.replace(match_pattern, replace_pattern) for h in headers[1:]]
+ headers = [headers[0]] + modifiedHeaders
+ elif rule_type == "Headers (regex):":
+ if regex_match:
+ modifiedHeaders = [regex_match.sub(replace_pattern, h) for h in headers[1:]]
+ headers = [headers[0]] + modifiedHeaders
+
+ if hasattr(self, 'replaceString') and self.replaceString.getText():
+ replaceStringLines = self.replaceString.getText().split("\n")
+ for h in replaceStringLines:
+ if h.strip() and ':' in h:
+ headers.append(h.strip())
+
+ msgBody = messageInfo.getRequest()[requestInfo.getBodyOffset():]
+
+ if authorizeOrNot and msgBody is not None:
+ msgBody_str = self._helpers.bytesToString(msgBody)
+
+ for i in range(mr_instance.MRModel.getSize()):
+ rule_key = mr_instance.MRModel.getElementAt(i)
+ rule_data = mr_instance.badProgrammerMRModel.get(rule_key)
+
+ if rule_data:
+ rule_type = rule_data['type']
+ match_pattern = rule_data['match']
+ replace_pattern = rule_data['replace']
+ regex_match = rule_data.get('regexMatch')
+
+ if rule_type == "Path (simple string):":
+ uriPath = headers[0].split(" ")[1]
+ if match_pattern in uriPath:
+ headers[0] = headers[0].replace(match_pattern, replace_pattern)
+ elif rule_type == "Path (regex):":
+ if regex_match:
+ uriPath = headers[0].split(" ")[1]
+ if regex_match.search(uriPath):
+ headers[0] = regex_match.sub(replace_pattern, headers[0])
+
+ elif rule_type == "Body (simple string):":
+ msgBody_str = msgBody_str.replace(match_pattern, replace_pattern)
+ elif rule_type == "Body (regex):":
+ if regex_match:
+ msgBody_str = regex_match.sub(replace_pattern, msgBody_str)
+
+ msgBody = self._helpers.stringToBytes(msgBody_str)
+
+ return self._helpers.buildHttpMessage(headers, msgBody)
def send_request_to_autorize(self, messageInfo):
if messageInfo.getResponse() is None:
message = makeMessage(self, messageInfo,False,False)
requestResponse = makeRequest(self, messageInfo, message)
- checkAuthorization(self, requestResponse,self._helpers.analyzeResponse(requestResponse.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())
+ # checkAuthorization(self, requestResponse,self._helpers.analyzeResponse(requestResponse.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())
+ checkAuthorizationAllUsers(self, requestResponse, self.doUnauthorizedRequest.isSelected())
else:
request = messageInfo.getRequest()
response = messageInfo.getResponse()
httpService = messageInfo.getHttpService()
newHttpRequestResponse = IHttpRequestResponseImplementation(httpService,request,response)
newHttpRequestResponsePersisted = self._callbacks.saveBuffersToTempFiles(newHttpRequestResponse)
- checkAuthorization(self, newHttpRequestResponsePersisted,self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())
+
+ checkAuthorizationAllUsers(self, newHttpRequestResponsePersisted, self.doUnauthorizedRequest.isSelected())
def auth_enforced_via_enforcement_detectors(self, filters, requestResponse, andOrEnforcement):
response = requestResponse.getResponse()
@@ -332,4 +487,4 @@ def retestAllRequests(self):
self.logTable.setAutoCreateRowSorter(True)
for i in range(self.tableModel.getRowCount()):
logEntry = self._log.get(self.logTable.convertRowIndexToModel(i))
- handle_message(self, "AUTORIZE", False, logEntry._originalrequestResponse)
+ start_new_thread(handle_message, (self, "AUTORIZE", False, logEntry._originalrequestResponse))
\ No newline at end of file
diff --git a/gui/configuration_tab.py b/gui/configuration_tab.py
index 295d292..521536d 100644
--- a/gui/configuration_tab.py
+++ b/gui/configuration_tab.py
@@ -90,10 +90,8 @@ def draw(self):
self._extender.filtersTabs = JTabbedPane()
self._extender.filtersTabs = self._extender.filtersTabs
- self._extender.filtersTabs.addTab("Enforcement Detector", self._extender.EDPnl)
self._extender.filtersTabs.addTab("Unauthentication Detector ", self._extender.EDPnlUnauth)
self._extender.filtersTabs.addTab("Interception Filters", self._extender.filtersPnl)
- self._extender.filtersTabs.addTab("Match/Replace", self._extender.MRPnl)
self._extender.filtersTabs.addTab("Table Filter", self._extender.filterPnl)
self._extender.filtersTabs.addTab("Save/Restore", self._extender.exportPnl)
@@ -386,5 +384,4 @@ def __init__(self, extender):
def actionPerformed(self, e):
selectedTitle = self._extender.savedHeadersTitlesCombo.getSelectedItem()
headers = [x for x in self._extender.savedHeaders if x['title'] == selectedTitle]
- self._extender.replaceString.setText(headers[0]['headers'])
-
+ self._extender.replaceString.setText(headers[0]['headers'])
\ No newline at end of file
diff --git a/gui/export.py b/gui/export.py
index 7a7f50b..e02ef5f 100644
--- a/gui/export.py
+++ b/gui/export.py
@@ -232,8 +232,6 @@ def draw(self):
)
)
)
-
-
def export(self, event):
if self.exportType.getSelectedItem() == "HTML":
@@ -247,6 +245,44 @@ def saveStateAction(self, event):
def restoreStateAction(self, event):
self.save_restore.restoreState()
+ def shouldIncludeRow(self, logEntry, enforcementStatusFilter):
+ should_include = False
+
+ if enforcementStatusFilter == "All Statuses":
+ should_include = True
+ elif enforcementStatusFilter == "As table filter":
+ if hasattr(self._extender, 'showBypassed') and hasattr(self._extender, 'showIsEnforced') and hasattr(self._extender, 'showEnforced'):
+ # Check unauthenticated status
+ unauth_status = logEntry._enfocementStatusUnauthorized
+ if ((self._extender.showBypassed.isSelected() and self.BYPASSSED_STR == unauth_status) or
+ (self._extender.showIsEnforced.isSelected() and self.IS_ENFORCED_STR == unauth_status) or
+ (self._extender.showEnforced.isSelected() and self.ENFORCED_STR == unauth_status) or
+ ("Disabled" == unauth_status)):
+ should_include = True
+
+ for user_id in logEntry.get_all_users():
+ user_data = logEntry.get_user_enforcement(user_id)
+ if user_data:
+ user_status = user_data['enforcementStatus']
+ if ((self._extender.showBypassed.isSelected() and self.BYPASSSED_STR == user_status) or
+ (self._extender.showIsEnforced.isSelected() and self.IS_ENFORCED_STR == user_status) or
+ (self._extender.showEnforced.isSelected() and self.ENFORCED_STR == user_status)):
+ should_include = True
+ break
+ else:
+ should_include = True
+ else:
+ if enforcementStatusFilter == logEntry._enfocementStatusUnauthorized:
+ should_include = True
+ else:
+ for user_id in logEntry.get_all_users():
+ user_data = logEntry.get_user_enforcement(user_id)
+ if user_data and enforcementStatusFilter == user_data['enforcementStatus']:
+ should_include = True
+ break
+
+ return should_include
+
def exportToHTML(self):
parentFrame = JFrame()
fileChooser = JFileChooser()
@@ -257,6 +293,16 @@ def exportToHTML(self):
fileToSave = fileChooser.getSelectedFile()
enforcementStatusFilter = self.exportES.getSelectedItem()
+
+ header_html = "| ID | Method | URL | Original length | Unauth length | Unauth Status | "
+
+ if hasattr(self._extender, 'userTab') and self._extender.userTab:
+ for user_id in sorted(self._extender.userTab.user_tabs.keys()):
+ user_name = self._extender.userTab.user_tabs[user_id]['user_name']
+ header_html += "{} Len | {} Status | ".format(user_name, user_name)
+
+ header_html += "
"
+
htmlContent = """
Autorize Report by Barak Tawily
Autorize Report
-
- | ID | Method | URL | Original length | Modified length | Unauthorized length | Authorization Enforcement Status | Authorization Unauthenticated Status |
+ """ + header_html + """
"""
- unique_HTML_lines = set() # set to keep track of unique values
- for i in range(0,self._log.size()):
+
+ unique_HTML_lines = set()
+ for i in range(0, self._log.size()):
+ logEntry = self._log.get(i)
+
if self.removeDuplicates.isSelected():
- # line data only looks for method, url, and authorized status. Does not factor in size of request during comparision
- lineData = "\t%s\t%s\t%s\t%s\n" % (self._log.get(i)._method, self._log.get(i)._url, self._log.get(i)._enfocementStatus,self._log.get(i)._enfocementStatusUnauthorized)
- if lineData in unique_HTML_lines: # Skip if line is already in set
+ user_statuses = []
+ for user_id in sorted(logEntry.get_all_users()):
+ user_data = logEntry.get_user_enforcement(user_id)
+ if user_data:
+ user_statuses.append(user_data['enforcementStatus'])
+
+ lineData = "\t%s\t%s\t%s\t%s" % (logEntry._method, logEntry._url,
+ logEntry._enfocementStatusUnauthorized,
+ "\t".join(user_statuses))
+ if lineData in unique_HTML_lines:
continue
- else: # Add line to set and continue with execution
+ else:
unique_HTML_lines.add(lineData)
- color_modified = ""
- if self._log.get(i)._enfocementStatus == self.BYPASSSED_STR:
- color_modified = "red"
- elif self._log.get(i)._enfocementStatus == self.IS_ENFORCED_STR:
- color_modified = "yellow"
- elif self._log.get(i)._enfocementStatus == self.ENFORCED_STR:
- color_modified = "LawnGreen"
-
- color_unauthorized = ""
- if self._log.get(i)._enfocementStatusUnauthorized == self.BYPASSSED_STR:
- color_unauthorized = "red"
- elif self._log.get(i)._enfocementStatusUnauthorized == self.IS_ENFORCED_STR:
- color_unauthorized = "yellow"
- elif self._log.get(i)._enfocementStatusUnauthorized == self.ENFORCED_STR:
- color_unauthorized = "LawnGreen"
-
- if enforcementStatusFilter == "All Statuses":
- htmlContent += "| %d | %s | %s | %d | %d | %d | %s | %s |
" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, color_modified, self._log.get(i)._enfocementStatus, color_unauthorized, self._log.get(i)._enfocementStatusUnauthorized)
- elif enforcementStatusFilter == "As table filter":
- if ((self._extender.showAuthBypassModified.isSelected() and self.BYPASSSED_STR == self._log.get(i)._enfocementStatus) or
- (self._extender.showAuthPotentiallyEnforcedModified.isSelected() and "Is enforced???" == self._log.get(i)._enfocementStatus) or
- (self._extender.showAuthEnforcedModified.isSelected() and self.ENFORCED_STR == self._log.get(i)._enfocementStatus) or
- (self._extender.showAuthBypassUnauthenticated.isSelected() and self.BYPASSSED_STR == self._log.get(i)._enfocementStatusUnauthorized) or
- (self._extender.showAuthPotentiallyEnforcedUnauthenticated.isSelected() and "Is enforced???" == self._log.get(i)._enfocementStatusUnauthorized) or
- (self._extender.showAuthEnforcedUnauthenticated.isSelected() and self.ENFORCED_STR == self._log.get(i)._enfocementStatusUnauthorized) or
- (self._extender.showDisabledUnauthenticated.isSelected() and "Disabled" == self._log.get(i)._enfocementStatusUnauthorized)):
- htmlContent += "| %d | %s | %s | %d | %d | %d | %s | %s |
" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, color_modified, self._log.get(i)._enfocementStatus, color_unauthorized, self._log.get(i)._enfocementStatusUnauthorized)
- else:
- if (enforcementStatusFilter == self._log.get(i)._enfocementStatus) or (enforcementStatusFilter == self._log.get(i)._enfocementStatusUnauthorized):
- htmlContent += "| %d | %s | %s | %d | %d | %d | %s | %s |
" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, color_modified, self._log.get(i)._enfocementStatus, color_unauthorized, self._log.get(i)._enfocementStatusUnauthorized)
+
+ if not self.shouldIncludeRow(logEntry, enforcementStatusFilter):
+ continue
+
+ row_html = "| %d | %s | %s | " % (
+ logEntry._id, logEntry._method, logEntry._url, logEntry._url)
+
+ orig_len = len(logEntry._originalrequestResponse.getResponse()) if logEntry._originalrequestResponse else 0
+ row_html += "%d | " % orig_len
+
+ unauth_len = 0
+ if logEntry._unauthorizedRequestResponse:
+ unauth_len = len(logEntry._unauthorizedRequestResponse.getResponse())
+
+ unauth_color = ""
+ if logEntry._enfocementStatusUnauthorized == self.BYPASSSED_STR:
+ unauth_color = "red"
+ elif logEntry._enfocementStatusUnauthorized == self.IS_ENFORCED_STR:
+ unauth_color = "yellow"
+ elif logEntry._enfocementStatusUnauthorized == self.ENFORCED_STR:
+ unauth_color = "LawnGreen"
+
+ row_html += "%d | %s | " % (unauth_len, unauth_color, logEntry._enfocementStatusUnauthorized)
+
+ # User data
+ if hasattr(self._extender, 'userTab') and self._extender.userTab:
+ for user_id in sorted(self._extender.userTab.user_tabs.keys()):
+ user_data = logEntry.get_user_enforcement(user_id)
+ if user_data and user_data['requestResponse']:
+ user_len = len(user_data['requestResponse'].getResponse())
+ user_status = user_data['enforcementStatus']
+
+ user_color = ""
+ if user_status == self.BYPASSSED_STR:
+ user_color = "red"
+ elif user_status == self.IS_ENFORCED_STR:
+ user_color = "yellow"
+ elif user_status == self.ENFORCED_STR:
+ user_color = "LawnGreen"
+
+ row_html += "%d | %s | " % (user_len, user_color, user_status)
+ else:
+ row_html += "0 | N/A | "
+
+ row_html += "
"
+ htmlContent += row_html
htmlContent += "
"
f = open(fileToSave.getAbsolutePath(), 'w')
f.writelines(htmlContent)
f.close()
-
+
def exportToCSV(self):
parentFrame = JFrame()
fileChooser = JFileChooser()
@@ -341,33 +412,60 @@ def exportToCSV(self):
fileToSave = fileChooser.getSelectedFile()
enforcementStatusFilter = self.exportES.getSelectedItem()
- csvContent = "id\tMethod\tURL\tOriginal length\tModified length\tUnauthorized length\tAuthorization Enforcement Status\tAuthorization Unauthenticated Status\n"
+
+ csvContent = "ID,Method,URL,Original Length,Unauth Length,Unauth Status"
+
+ if hasattr(self._extender, 'userTab') and self._extender.userTab:
+ for user_id in sorted(self._extender.userTab.user_tabs.keys()):
+ user_name = self._extender.userTab.user_tabs[user_id]['user_name']
+ csvContent += ",{} Length,{} Status".format(user_name, user_name)
+
+ csvContent += "\n"
- unique_CVS_lines = set()
+ unique_CSV_lines = set()
for i in range(0, self._log.size()):
+ logEntry = self._log.get(i)
+
if self.removeDuplicates.isSelected():
- # line data only looks for method, url, and authorized status. Does not factor in size of request during comparision
- lineData = "\t%s\t%s\t%s\t%s\n" % (self._log.get(i)._method, self._log.get(i)._url, self._log.get(i)._enfocementStatus,self._log.get(i)._enfocementStatusUnauthorized)
- if lineData in unique_CVS_lines: # Skip if line is already in set
+ user_statuses = []
+ for user_id in sorted(logEntry.get_all_users()):
+ user_data = logEntry.get_user_enforcement(user_id)
+ if user_data:
+ user_statuses.append(user_data['enforcementStatus'])
+
+ lineData = ",{},{},{},{}".format(logEntry._method, logEntry._url,
+ logEntry._enfocementStatusUnauthorized,
+ ",".join(user_statuses))
+ if lineData in unique_CSV_lines:
continue
- else: # Add line to set and continue with execution
- unique_CVS_lines.add(lineData)
- if enforcementStatusFilter == "All Statuses":
- csvContent += "%d\t%s\t%s\t%d\t%d\t%d\t%s\t%s\n" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, self._log.get(i)._enfocementStatus, self._log.get(i)._enfocementStatusUnauthorized)
- elif enforcementStatusFilter == "As table filter":
- if ((self._extender.showAuthBypassModified.isSelected() and self.BYPASSSED_STR == self._log.get(i)._enfocementStatus) or
- (self._extender.showAuthPotentiallyEnforcedModified.isSelected() and "Is enforced???" == self._log.get(i)._enfocementStatus) or
- (self._extender.showAuthEnforcedModified.isSelected() and self.ENFORCED_STR == self._log.get(i)._enfocementStatus) or
- (self._extender.showAuthBypassUnauthenticated.isSelected() and self.BYPASSSED_STR == self._log.get(i)._enfocementStatusUnauthorized) or
- (self._extender.showAuthPotentiallyEnforcedUnauthenticated.isSelected() and "Is enforced???" == self._log.get(i)._enfocementStatusUnauthorized) or
- (self._extender.showAuthEnforcedUnauthenticated.isSelected() and self.ENFORCED_STR == self._log.get(i)._enfocementStatusUnauthorized) or
- (self._extender.showDisabledUnauthenticated.isSelected() and "Disabled" == self._log.get(i)._enfocementStatusUnauthorized)):
- csvContent += "%d\t%s\t%s\t%d\t%d\t%d\t%s\t%s\n" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, self._log.get(i)._enfocementStatus, self._log.get(i)._enfocementStatusUnauthorized)
- else:
- if (enforcementStatusFilter == self._log.get(i)._enfocementStatus) or (enforcementStatusFilter == self._log.get(i)._enfocementStatusUnauthorized):
- csvContent += "%d\t%s\t%s\t%d\t%d\t%d\t%s\t%s\n" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, self._log.get(i)._enfocementStatus, self._log.get(i)._enfocementStatusUnauthorized)
-
+ else:
+ unique_CSV_lines.add(lineData)
+
+ if not self.shouldIncludeRow(logEntry, enforcementStatusFilter):
+ continue
+
+ orig_len = len(logEntry._originalrequestResponse.getResponse()) if logEntry._originalrequestResponse else 0
+ unauth_len = len(logEntry._unauthorizedRequestResponse.getResponse()) if logEntry._unauthorizedRequestResponse else 0
+
+ url_safe = '"{}"'.format(str(logEntry._url).replace('"', '""'))
+
+ csv_row = '{},{},{},{},{},"{}"'.format(
+ logEntry._id, logEntry._method, url_safe, orig_len, unauth_len, logEntry._enfocementStatusUnauthorized)
+
+ # User data
+ if hasattr(self._extender, 'userTab') and self._extender.userTab:
+ for user_id in sorted(self._extender.userTab.user_tabs.keys()):
+ user_data = logEntry.get_user_enforcement(user_id)
+ if user_data and user_data['requestResponse']:
+ user_len = len(user_data['requestResponse'].getResponse())
+ user_status = user_data['enforcementStatus']
+ csv_row += ',{},"{}"'.format(user_len, user_status)
+ else:
+ csv_row += ',0,"N/A"'
+
+ csv_row += "\n"
+ csvContent += csv_row
f = open(fileToSave.getAbsolutePath(), 'w')
f.writelines(csvContent)
- f.close()
+ f.close()
\ No newline at end of file
diff --git a/gui/save_restore.py b/gui/save_restore.py
index 55d2999..8c98cdb 100644
--- a/gui/save_restore.py
+++ b/gui/save_restore.py
@@ -32,13 +32,9 @@ def __init__(self, extender):
"interceptRequestsfromRepeater",
"doUnauthorizedRequest",
"replaceQueryParam",
- "showAuthBypassModified",
- "showAuthPotentiallyEnforcedModified",
- "showAuthEnforcedModified",
- "showAuthBypassUnauthenticated",
- "showAuthPotentiallyEnforcedUnauthenticated",
- "showAuthEnforcedUnauthenticated",
- "showDisabledUnauthenticated"
+ "showBypassed",
+ "showIsEnforced",
+ "showEnforced"
]
def saveState(self):
@@ -55,57 +51,56 @@ def saveState(self):
# Configuration
tempRow = ["ReplaceString", base64.b64encode(self._extender.replaceString.getText())]
csvwriter.writerow(tempRow)
-
- for EDFilter in self._extender.EDModel.toArray():
- tempRow = ["EDFilter", base64.b64encode(EDFilter)]
- csvwriter.writerow(tempRow)
-
- for EDFilterUnauth in self._extender.EDModelUnauth.toArray():
- tempRow = ["EDFilterUnauth", base64.b64encode(EDFilterUnauth)]
- csvwriter.writerow(tempRow)
-
- for IFFilter in self._extender.IFModel.toArray():
- tempRow = ["IFFilter", base64.b64encode(IFFilter)]
+
+ user_configs = []
+
+ for user_id, user_data in self._extender.userTab.user_tabs.items():
+ user_config = {
+ 'user_id': user_id,
+ 'user_name': user_data['user_name'],
+ 'ed_filters': list(user_data['ed_instance'].EDModel.toArray()),
+ 'ed_type': user_data['ed_instance'].EDType.getSelectedIndex(),
+ 'ed_text': user_data['ed_instance'].EDText.getText(),
+ 'andor_type': user_data['ed_instance'].AndOrType.getSelectedIndex(),
+ 'mr_rules': dict(user_data['mr_instance'].badProgrammerMRModel)
+ }
+
+ user_configs.append(user_config)
+
+ tempRow = ["UserConfigs", base64.b64encode(json.dumps(user_configs))]
csvwriter.writerow(tempRow)
- for t in ["AndOrType", "AndOrTypeUnauth"]:
- tempRow = [t, getattr(self._extender, t).getSelectedItem()]
- csvwriter.writerow(tempRow)
+ if hasattr(self._extender, 'EDModelUnauth'):
+ for EDFilterUnauth in self._extender.EDModelUnauth.toArray():
+ tempRow = ["EDFilterUnauth", base64.b64encode(EDFilterUnauth)]
+ csvwriter.writerow(tempRow)
- for key in self._extender.badProgrammerMRModel:
- d = dict(self._extender.badProgrammerMRModel[key])
- d["regexMatch"] = d["regexMatch"] is not None
- tempRow = ["MatchReplace", base64.b64encode(json.dumps(d))]
- csvwriter.writerow(tempRow)
+ if hasattr(self._extender, 'IFModel'):
+ for IFFilter in self._extender.IFModel.toArray():
+ tempRow = ["IFFilter", base64.b64encode(IFFilter)]
+ csvwriter.writerow(tempRow)
d = dict((c, getattr(self._extender, c).isSelected()) for c in self._checkBoxes)
- tempRow = ["CheckBoxes", json.dumps(d)]
- csvwriter.writerow(tempRow)
- isSelected = self._extender.exportPnl.getComponents()[-1].isSelected()
- tempRow = ["RemoveDuplicates", json.dumps(isSelected)]
+ tempRow = ["CheckBoxes", json.dumps(d)]
csvwriter.writerow(tempRow)
# Request/response list
- for i in range(0,self._extender._log.size()):
- tempRequestResponseHost = self._extender._log.get(i)._requestResponse.getHttpService().getHost()
- tempRequestResponsePort = self._extender._log.get(i)._requestResponse.getHttpService().getPort()
- tempRequestResponseProtocol = self._extender._log.get(i)._requestResponse.getHttpService().getProtocol()
- tempRequestResponseRequest = base64.b64encode(self._extender._log.get(i)._requestResponse.getRequest())
- tempRequestResponseResponse = base64.b64encode(self._extender._log.get(i)._requestResponse.getResponse())
-
- tempOriginalRequestResponseHost = self._extender._log.get(i)._originalrequestResponse.getHttpService().getHost()
- tempOriginalRequestResponsePort = self._extender._log.get(i)._originalrequestResponse.getHttpService().getPort()
- tempOriginalRequestResponseProtocol = self._extender._log.get(i)._originalrequestResponse.getHttpService().getProtocol()
- tempOriginalRequestResponseRequest = base64.b64encode(self._extender._log.get(i)._originalrequestResponse.getRequest())
- tempOriginalRequestResponseResponse = base64.b64encode(self._extender._log.get(i)._originalrequestResponse.getResponse())
-
- if self._extender._log.get(i)._unauthorizedRequestResponse is not None:
- tempUnauthorizedRequestResponseHost = self._extender._log.get(i)._unauthorizedRequestResponse.getHttpService().getHost()
- tempUnauthorizedRequestResponsePort = self._extender._log.get(i)._unauthorizedRequestResponse.getHttpService().getPort()
- tempUnauthorizedRequestResponseProtocol = self._extender._log.get(i)._unauthorizedRequestResponse.getHttpService().getProtocol()
- tempUnauthorizedRequestResponseRequest = base64.b64encode(self._extender._log.get(i)._unauthorizedRequestResponse.getRequest())
- tempUnauthorizedRequestResponseResponse = base64.b64encode(self._extender._log.get(i)._unauthorizedRequestResponse.getResponse())
+ for i in range(0, self._extender._log.size()):
+ logEntry = self._extender._log.get(i)
+
+ tempOriginalRequestResponseHost = logEntry._originalrequestResponse.getHttpService().getHost()
+ tempOriginalRequestResponsePort = logEntry._originalrequestResponse.getHttpService().getPort()
+ tempOriginalRequestResponseProtocol = logEntry._originalrequestResponse.getHttpService().getProtocol()
+ tempOriginalRequestResponseRequest = base64.b64encode(logEntry._originalrequestResponse.getRequest())
+ tempOriginalRequestResponseResponse = base64.b64encode(logEntry._originalrequestResponse.getResponse())
+
+ if logEntry._unauthorizedRequestResponse is not None:
+ tempUnauthorizedRequestResponseHost = logEntry._unauthorizedRequestResponse.getHttpService().getHost()
+ tempUnauthorizedRequestResponsePort = logEntry._unauthorizedRequestResponse.getHttpService().getPort()
+ tempUnauthorizedRequestResponseProtocol = logEntry._unauthorizedRequestResponse.getHttpService().getProtocol()
+ tempUnauthorizedRequestResponseRequest = base64.b64encode(logEntry._unauthorizedRequestResponse.getRequest())
+ tempUnauthorizedRequestResponseResponse = base64.b64encode(logEntry._unauthorizedRequestResponse.getResponse())
else:
tempUnauthorizedRequestResponseHost = None
tempUnauthorizedRequestResponsePort = None
@@ -113,13 +108,30 @@ def saveState(self):
tempUnauthorizedRequestResponseRequest = None
tempUnauthorizedRequestResponseResponse = None
- tempEnforcementStatus = self._extender._log.get(i)._enfocementStatus
- tempEnforcementStatusUnauthorized = self._extender._log.get(i)._enfocementStatusUnauthorized
-
- tempRow = [tempRequestResponseHost,tempRequestResponsePort,tempRequestResponseProtocol,tempRequestResponseRequest,tempRequestResponseResponse]
- tempRow.extend([tempOriginalRequestResponseHost,tempOriginalRequestResponsePort,tempOriginalRequestResponseProtocol,tempOriginalRequestResponseRequest,tempOriginalRequestResponseResponse])
- tempRow.extend([tempUnauthorizedRequestResponseHost,tempUnauthorizedRequestResponsePort,tempUnauthorizedRequestResponseProtocol,tempUnauthorizedRequestResponseRequest,tempUnauthorizedRequestResponseResponse])
- tempRow.extend([tempEnforcementStatus,tempEnforcementStatusUnauthorized])
+ tempEnforcementStatusUnauthorized = logEntry._enfocementStatusUnauthorized
+
+ user_data_json = {}
+
+ for user_id in logEntry.get_all_users():
+ user_enforcement = logEntry.get_user_enforcement(user_id)
+ if user_enforcement and user_enforcement['requestResponse']:
+ user_data_json[str(user_id)] = {
+ 'host': user_enforcement['requestResponse'].getHttpService().getHost(),
+ 'port': user_enforcement['requestResponse'].getHttpService().getPort(),
+ 'protocol': user_enforcement['requestResponse'].getHttpService().getProtocol(),
+ 'request': base64.b64encode(user_enforcement['requestResponse'].getRequest()),
+ 'response': base64.b64encode(user_enforcement['requestResponse'].getResponse()),
+ 'status': user_enforcement['enforcementStatus']
+ }
+
+ tempRow = [
+ tempOriginalRequestResponseHost, tempOriginalRequestResponsePort, tempOriginalRequestResponseProtocol,
+ tempOriginalRequestResponseRequest, tempOriginalRequestResponseResponse,
+ tempUnauthorizedRequestResponseHost, tempUnauthorizedRequestResponsePort, tempUnauthorizedRequestResponseProtocol,
+ tempUnauthorizedRequestResponseRequest, tempUnauthorizedRequestResponseResponse,
+ tempEnforcementStatusUnauthorized,
+ base64.b64encode(json.dumps(user_data_json))
+ ]
csvwriter.writerow(tempRow)
@@ -128,51 +140,69 @@ def restoreState(self):
fileChooser = JFileChooser()
fileChooser.setDialogTitle("State import file")
userSelection = fileChooser.showDialog(parentFrame, "Restore")
- modelMap = {
- "IFFilter": self._extender.IFModel,
- "EDFilter": self._extender.EDModel,
- "EDFilterUnauth": self._extender.EDModelUnauth
- }
if userSelection == JFileChooser.APPROVE_OPTION:
importFile = fileChooser.getSelectedFile()
+
+ self._extender._log.clear()
+ self._extender.tableModel.fireTableDataChanged()
+
+ if hasattr(self._extender, 'EDModelUnauth'):
+ self._extender.EDModelUnauth.clear()
+ if hasattr(self._extender, 'IFModel'):
+ self._extender.IFModel.clear()
with open(importFile.getAbsolutePath(), 'r') as csvfile:
csvreader = csv.reader(csvfile, delimiter='\t', quotechar='|')
+ user_configs = None
+
for row in csvreader:
# Configuration
if row[0] == "ReplaceString":
self._extender.replaceString.setText(base64.b64decode(row[1]))
continue
- if row[0] in modelMap:
- f = base64.b64decode(row[1])
- if f not in modelMap[row[0]].toArray():
- modelMap[row[0]].addElement(f)
+ if row[0] == "UserConfigs":
+ user_configs = json.loads(base64.b64decode(row[1]))
+
+ # Restore user configurations
+ if hasattr(self._extender, 'userTab') and self._extender.userTab:
+ self._extender.userTab.reset_user()
+
+ for i, config in enumerate(user_configs):
+ if i == 0:
+ user_data = list(self._extender.userTab.user_tabs.values())[0]
+ else:
+ self._extender.userTab.add_user()
+ user_data = list(self._extender.userTab.user_tabs.values())[-1]
+
+ user_data['ed_instance'].EDModel.clear()
+ for filter in config['ed_filters']:
+ user_data['ed_instance'].EDModel.addElement(filter)
+
+ user_data['ed_instance'].EDType.setSelectedIndex(config['ed_type'])
+ user_data['ed_instance'].EDText.setText(config['ed_text'])
+ user_data['ed_instance'].AndOrType.setSelectedIndex(config['andor_type'])
+
+ user_data['mr_instance'].badProgrammerMRModel.clear()
+ user_data['mr_instance'].MRModel.clear()
+ for key, value in config['mr_rules'].items():
+ user_data['mr_instance'].badProgrammerMRModel[key] = value
+ user_data['mr_instance'].MRModel.addElement(key)
continue
- if row[0] in {"AndOrType", "AndOrTypeUnauth"}:
- getattr(self._extender, row[0]).setSelectedItem(row[1])
+ if row[0] == "EDFilterUnauth":
+ if hasattr(self._extender, 'EDModelUnauth'):
+ self._extender.EDModelUnauth.addElement(base64.b64decode(row[1]))
continue
- if row[0] == "MatchReplace":
- d = json.loads(base64.b64decode(row[1]))
- key = d["type"] + " " + d["match"] + "->" + d["replace"]
- if key in self._extender.badProgrammerMRModel:
- continue
- regexMatch = None
- if d["regexMatch"]:
- try:
- d["regexMatch"] = re.compile(d["match"])
- except re.error:
- print("ERROR: Regex to restore is invalid:", d["match"])
- continue
- self._extender.badProgrammerMRModel[key] = d
- self._extender.MRModel.addElement(key)
+ if row[0] == "IFFilter":
+ if hasattr(self._extender, 'IFModel'):
+ self._extender.IFModel.addElement(base64.b64decode(row[1]))
continue
-
+
if row[0] == "CheckBoxes":
d = json.loads(row[1])
for k in d:
@@ -188,74 +218,56 @@ def restoreState(self):
continue
# Request/response list
- tempRequestResponseHost = row[0]
- tempRequestResponsePort = row[1]
- tempRequestResponseProtocol = row[2]
- tempRequestResponseRequest = base64.b64decode(row[3])
- tempRequestResponseResponse = base64.b64decode(row[4])
-
- tempRequestResponseHttpService = self._extender._helpers.buildHttpService(tempRequestResponseHost,int(tempRequestResponsePort),tempRequestResponseProtocol)
- tempRequestResponse = IHttpRequestResponseImplementation(tempRequestResponseHttpService,tempRequestResponseRequest,tempRequestResponseResponse)
-
- tempOriginalRequestResponseHost = row[5]
- tempOriginalRequestResponsePort = row[6]
- tempOriginalRequestResponseProtocol = row[7]
- tempOriginalRequestResponseRequest = base64.b64decode(row[8])
- tempOriginalRequestResponseResponse = base64.b64decode(row[9])
-
- tempOriginalRequestResponseHttpService = self._extender._helpers.buildHttpService(tempOriginalRequestResponseHost,int(tempOriginalRequestResponsePort),tempOriginalRequestResponseProtocol)
- tempOriginalRequestResponse = IHttpRequestResponseImplementation(tempOriginalRequestResponseHttpService,tempOriginalRequestResponseRequest,tempOriginalRequestResponseResponse)
-
- checkAuthentication = True
- if row[10] != '':
- tempUnauthorizedRequestResponseHost = row[10]
- tempUnauthorizedRequestResponsePort = row[11]
- tempUnauthorizedRequestResponseProtocol = row[12]
- tempUnauthorizedRequestResponseRequest = base64.b64decode(row[13])
- tempUnauthorizedRequestResponseResponse = base64.b64decode(row[14])
- tempUnauthorizedRequestResponseHttpService = self._extender._helpers.buildHttpService(tempUnauthorizedRequestResponseHost,int(tempUnauthorizedRequestResponsePort),tempUnauthorizedRequestResponseProtocol)
- tempUnauthorizedRequestResponse = IHttpRequestResponseImplementation(tempUnauthorizedRequestResponseHttpService,tempUnauthorizedRequestResponseRequest,tempUnauthorizedRequestResponseResponse)
- else:
- checkAuthentication = False
- tempUnauthorizedRequestResponse = None
-
- tempEnforcementStatus = row[15]
- tempEnforcementStatusUnauthorized = row[16]
-
- self._extender._lock.acquire()
-
- row = self._extender._log.size()
-
- if checkAuthentication:
- self._extender._log.add(
- LogEntry(self._extender.currentRequestNumber,
- self._extender._callbacks.saveBuffersToTempFiles(tempRequestResponse),
- self._extender._helpers.analyzeRequest(tempRequestResponse).getMethod(),
- self._extender._helpers.analyzeRequest(tempRequestResponse).getUrl(),
- self._extender._callbacks.saveBuffersToTempFiles(tempOriginalRequestResponse),
- tempEnforcementStatus,
- self._extender._callbacks.saveBuffersToTempFiles(tempUnauthorizedRequestResponse),
- tempEnforcementStatusUnauthorized))
- else:
- self._extender._log.add(
- LogEntry(self._extender.currentRequestNumber,
- self._extender._callbacks.saveBuffersToTempFiles(tempRequestResponse),
- self._extender._helpers.analyzeRequest(tempRequestResponse).getMethod(),
- self._extender._helpers.analyzeRequest(tempRequestResponse).getUrl(),
- self._extender._callbacks.saveBuffersToTempFiles(tempOriginalRequestResponse),
- tempEnforcementStatus,None,tempEnforcementStatusUnauthorized))
-
- SwingUtilities.invokeLater(UpdateTableEDT(self._extender,"insert",row,row))
- self._extender.currentRequestNumber = self._extender.currentRequestNumber + 1
- self._extender._lock.release()
-
- lastRow = self._extender._log.size()
- if lastRow > 0:
- cookiesHeader = get_cookie_header_from_message(self._extender, self._extender._log.get(lastRow - 1)._requestResponse)
- if cookiesHeader:
- self._extender.lastCookiesHeader = cookiesHeader
- self._extender.fetchCookiesHeaderButton.setEnabled(True)
- authorizationHeader = get_authorization_header_from_message(self._extender, self._extender._log.get(lastRow - 1)._requestResponse)
- if authorizationHeader:
- self._extender.lastAuthorizationHeader = authorizationHeader
- self._extender.fetchAuthorizationHeaderButton.setEnabled(True)
+
+ if len(row) >= 12:
+ tempOriginalRequestResponseHost = row[0]
+ tempOriginalRequestResponsePort = row[1]
+ tempOriginalRequestResponseProtocol = row[2]
+ tempOriginalRequestResponseRequest = base64.b64decode(row[3])
+ tempOriginalRequestResponseResponse = base64.b64decode(row[4])
+
+ tempOriginalRequestResponseHttpService = self._extender._helpers.buildHttpService(
+ tempOriginalRequestResponseHost, int(tempOriginalRequestResponsePort), tempOriginalRequestResponseProtocol)
+ tempOriginalRequestResponse = IHttpRequestResponseImplementation(
+ tempOriginalRequestResponseHttpService, tempOriginalRequestResponseRequest, tempOriginalRequestResponseResponse)
+
+ checkAuthentication = True
+ if row[5] != '':
+ tempUnauthorizedRequestResponseHost = row[5]
+ tempUnauthorizedRequestResponsePort = row[6]
+ tempUnauthorizedRequestResponseProtocol = row[7]
+ tempUnauthorizedRequestResponseRequest = base64.b64decode(row[8])
+ tempUnauthorizedRequestResponseResponse = base64.b64decode(row[9])
+ tempUnauthorizedRequestResponseHttpService = self._extender._helpers.buildHttpService(
+ tempUnauthorizedRequestResponseHost, int(tempUnauthorizedRequestResponsePort), tempUnauthorizedRequestResponseProtocol)
+ tempUnauthorizedRequestResponse = IHttpRequestResponseImplementation(
+ tempUnauthorizedRequestResponseHttpService, tempUnauthorizedRequestResponseRequest, tempUnauthorizedRequestResponseResponse)
+ else:
+ checkAuthentication = False
+ tempUnauthorizedRequestResponse = None
+
+ tempEnforcementStatusUnauthorized = row[10]
+
+ method = self._extender._helpers.analyzeRequest(tempOriginalRequestResponse).getMethod()
+ original_url = self._extender._helpers.analyzeRequest(tempOriginalRequestResponse).getUrl()
+
+ logEntry = LogEntry(self._extender.currentRequestNumber, method, original_url,
+ self._extender._callbacks.saveBuffersToTempFiles(tempOriginalRequestResponse),
+ self._extender._callbacks.saveBuffersToTempFiles(tempUnauthorizedRequestResponse) if checkAuthentication else None,
+ tempEnforcementStatusUnauthorized)
+
+ if len(row) > 11 and row[11]:
+ user_data_json = json.loads(base64.b64decode(row[11]))
+ for user_id_str, user_data in user_data_json.items():
+ user_id = int(user_id_str)
+ userHttpService = self._extender._helpers.buildHttpService(
+ user_data['host'], int(user_data['port']), user_data['protocol'])
+ userRequestResponse = IHttpRequestResponseImplementation(
+ userHttpService, base64.b64decode(user_data['request']), base64.b64decode(user_data['response']))
+ savedUserRequestResponse = self._extender._callbacks.saveBuffersToTempFiles(userRequestResponse)
+ logEntry.add_user_enforcement(user_id, savedUserRequestResponse, user_data['status'])
+
+ self._extender._log.add(logEntry)
+ self._extender.currentRequestNumber = self._extender.currentRequestNumber + 1
+
+ self._extender.tableModel.fireTableDataChanged()
\ No newline at end of file
diff --git a/gui/table.py b/gui/table.py
index a7ac4c2..9384e85 100644
--- a/gui/table.py
+++ b/gui/table.py
@@ -6,14 +6,13 @@
from java.lang import Integer
from java.lang import Runnable
from javax.swing import JTable
-from javax.swing import JLabel
from javax.swing import JPanel
from javax.swing import RowFilter
from javax.swing import JCheckBox
-from javax.swing import GroupLayout
from javax.swing import ListSelectionModel
from java.awt.event import MouseAdapter
from java.awt.event import ItemListener
+from java.awt import FlowLayout
from javax.swing.table import AbstractTableModel
from javax.swing.event import ListSelectionListener
@@ -27,187 +26,34 @@ def draw(self):
"""
init show tab
"""
+ self._extender.filterPnl = JPanel(FlowLayout(FlowLayout.LEFT))
- filterLModified = JLabel("Modified:")
- filterLModified.setBounds(10, 10, 100, 30)
-
- filterLUnauthenticated = JLabel("Unauthenticated:")
- filterLUnauthenticated.setBounds(250, 10, 100, 30)
-
- self._extender.showAuthBypassModified = JCheckBox(self._extender.BYPASSSED_STR)
- self._extender.showAuthBypassModified.setBounds(10, 35, 200, 30)
- self._extender.showAuthBypassModified.setSelected(True)
- self._extender.showAuthBypassModified.addItemListener(TabTableFilter(self._extender))
-
- self._extender.showAuthPotentiallyEnforcedModified = JCheckBox("Is enforced???")
- self._extender.showAuthPotentiallyEnforcedModified.setBounds(10, 60, 200, 30)
- self._extender.showAuthPotentiallyEnforcedModified.setSelected(True)
- self._extender.showAuthPotentiallyEnforcedModified.addItemListener(TabTableFilter(self._extender))
-
- self._extender.showAuthEnforcedModified = JCheckBox(self._extender.ENFORCED_STR)
- self._extender.showAuthEnforcedModified.setBounds(10, 85, 200, 30)
- self._extender.showAuthEnforcedModified.setSelected(True)
- self._extender.showAuthEnforcedModified.addItemListener(TabTableFilter(self._extender))
-
- self._extender.showAuthBypassUnauthenticated = JCheckBox(self._extender.BYPASSSED_STR)
- self._extender.showAuthBypassUnauthenticated.setBounds(250, 35, 200, 30)
- self._extender.showAuthBypassUnauthenticated.setSelected(True)
- self._extender.showAuthBypassUnauthenticated.addItemListener(TabTableFilter(self._extender))
-
- self._extender.showAuthPotentiallyEnforcedUnauthenticated = JCheckBox("Is enforced???")
- self._extender.showAuthPotentiallyEnforcedUnauthenticated.setBounds(250, 60, 200, 30)
- self._extender.showAuthPotentiallyEnforcedUnauthenticated.setSelected(True)
- self._extender.showAuthPotentiallyEnforcedUnauthenticated.addItemListener(TabTableFilter(self._extender))
-
- self._extender.showAuthEnforcedUnauthenticated = JCheckBox(self._extender.ENFORCED_STR)
- self._extender.showAuthEnforcedUnauthenticated.setBounds(250, 85, 200, 30)
- self._extender.showAuthEnforcedUnauthenticated.setSelected(True)
- self._extender.showAuthEnforcedUnauthenticated.addItemListener(TabTableFilter(self._extender))
-
- self._extender.showDisabledUnauthenticated = JCheckBox("Disabled")
- self._extender.showDisabledUnauthenticated.setBounds(250, 110, 200, 30)
- self._extender.showDisabledUnauthenticated.setSelected(True)
- self._extender.showDisabledUnauthenticated.addItemListener(TabTableFilter(self._extender))
-
- self._extender.filterPnl = JPanel()
- layout = GroupLayout(self._extender.filterPnl)
- self._extender.filterPnl.setLayout(layout)
- layout.setAutoCreateGaps(True)
- layout.setAutoCreateContainerGaps(True)
-
- layout.setHorizontalGroup(layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup()
- .addComponent(
- filterLModified,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showAuthBypassModified,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showAuthPotentiallyEnforcedModified,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showAuthEnforcedModified,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- )
- .addGroup(layout.createParallelGroup()
- .addComponent(
- filterLUnauthenticated,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showAuthBypassUnauthenticated,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showAuthPotentiallyEnforcedUnauthenticated,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showAuthEnforcedUnauthenticated,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showDisabledUnauthenticated,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- )
- )
-
-
- layout.setVerticalGroup(layout.createSequentialGroup()
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
- .addComponent(
- filterLModified,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- filterLUnauthenticated,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- )
- .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
- .addGroup(layout.createSequentialGroup()
- .addComponent(
- self._extender.showAuthBypassModified,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showAuthPotentiallyEnforcedModified,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showAuthEnforcedModified,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- )
- .addGroup(layout.createSequentialGroup()
- .addComponent(
- self._extender.showAuthBypassUnauthenticated,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showAuthPotentiallyEnforcedUnauthenticated,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showAuthEnforcedUnauthenticated,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- .addComponent(
- self._extender.showDisabledUnauthenticated,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- GroupLayout.PREFERRED_SIZE,
- )
- )
- )
- )
+ self._extender.showBypassed = JCheckBox(self._extender.BYPASSSED_STR)
+ self._extender.showBypassed.setSelected(True)
+ self._extender.showBypassed.addItemListener(TabTableFilter(self._extender))
+
+ self._extender.showIsEnforced = JCheckBox("Is enforced???")
+ self._extender.showIsEnforced.setSelected(True)
+ self._extender.showIsEnforced.addItemListener(TabTableFilter(self._extender))
+
+ self._extender.showEnforced = JCheckBox(self._extender.ENFORCED_STR)
+ self._extender.showEnforced.setSelected(True)
+ self._extender.showEnforced.addItemListener(TabTableFilter(self._extender))
+
+ self._extender.filterPnl.add(self._extender.showBypassed)
+ self._extender.filterPnl.add(self._extender.showIsEnforced)
+ self._extender.filterPnl.add(self._extender.showEnforced)
class TabTableFilter(ItemListener):
def __init__(self, extender):
self._extender = extender
def itemStateChanged(self, e):
- self._extender.tableSorter.sort()
+ if hasattr(self._extender, 'tableSorter'):
+ self._extender.tableSorter.sort()
+
+ if hasattr(self._extender, 'logTable'):
+ self._extender.logTable.repaint()
class TableModel(AbstractTableModel):
def __init__(self, extender):
@@ -226,48 +72,104 @@ def getRowCount(self):
return 0
def getColumnCount(self):
- return 8
+ base_columns = 6
+ user_count = len(self._extender.userTab.user_tabs) if hasattr(self._extender, 'userTab') and self._extender.userTab else 0
+ return base_columns + (user_count * 2)
def getColumnName(self, columnIndex):
- data = ['ID','Method', 'URL', 'Orig. Len', 'Modif. Len', "Unauth. Len",
- "Authz. Status", "Unauth. Status"]
+ base_columns = ['ID', 'Method', 'URL', 'Orig. Len', 'Unauth.len', 'Unauth. Status']
+
+ if columnIndex < len(base_columns):
+ return base_columns[columnIndex]
+
try:
- return data[columnIndex]
- except IndexError:
+ if hasattr(self._extender, 'userTab') and self._extender.userTab:
+ user_index = (columnIndex - len(base_columns)) // 2
+ col_type = (columnIndex - len(base_columns)) % 2
+
+ user_ids = sorted(self._extender.userTab.user_tabs.keys())
+
+ if user_index < len(user_ids):
+ user_id = user_ids[user_index]
+ user_name = self._extender.userTab.user_tabs[user_id]['user_name']
+
+ col_names = [
+ "{} Modif. Len".format(user_name),
+ "{} Authz. Status".format(user_name)
+ ]
+
+ return col_names[col_type]
+
+ return ""
+
+ except (IndexError, KeyError):
return ""
def getColumnClass(self, columnIndex):
- data = [Integer, String, String, Integer, Integer, Integer, String, String]
+ base_classes = [Integer, String, String, Integer, Integer, String]
+
+ if columnIndex < len(base_classes):
+ return base_classes[columnIndex]
+
try:
- return data[columnIndex]
+ col_type = (columnIndex - len(base_classes)) % 2
+ user_col_classes = [Integer, String]
+ return user_col_classes[col_type]
+
except IndexError:
return ""
def getValueAt(self, rowIndex, columnIndex):
logEntry = self._extender._log.get(rowIndex)
- if columnIndex == 0:
+
+ if columnIndex == 0: # ID
return logEntry._id
- if columnIndex == 1:
+ if columnIndex == 1: # METHOD
return logEntry._method
- if columnIndex == 2:
+ if columnIndex == 2: # URL
return logEntry._url.toString()
- if columnIndex == 3:
+ if columnIndex == 3: # Original Request Length
response = logEntry._originalrequestResponse.getResponse()
return len(logEntry._originalrequestResponse.getResponse()) - self._extender._helpers.analyzeResponse(response).getBodyOffset()
- if columnIndex == 4:
- response = logEntry._requestResponse.getResponse()
- return len(logEntry._requestResponse.getResponse()) - self._extender._helpers.analyzeResponse(response).getBodyOffset()
- if columnIndex == 5:
+ if columnIndex == 4: # Unauthorized Request Length
if logEntry._unauthorizedRequestResponse is not None:
response = logEntry._unauthorizedRequestResponse.getResponse()
return len(logEntry._unauthorizedRequestResponse.getResponse()) - self._extender._helpers.analyzeResponse(response).getBodyOffset()
else:
return 0
- if columnIndex == 6:
- return logEntry._enfocementStatus
- if columnIndex == 7:
- return logEntry._enfocementStatusUnauthorized
+ if columnIndex == 5:
+ return logEntry._enfocementStatusUnauthorized
+
+ # User columns
+ if hasattr(self._extender, 'userTab') and self._extender.userTab and columnIndex >= 6:
+ user_index = (columnIndex - 6) // 2
+ col_type = (columnIndex - 6) % 2
+
+ user_ids = sorted(self._extender.userTab.user_tabs.keys())
+ if user_index < len(user_ids):
+ user_id = user_ids[user_index]
+ user_name = self._extender.userTab.user_tabs[user_id]['user_name']
+
+ user_data = logEntry.get_user_enforcement(user_id)
+ if user_data:
+ if col_type == 0: # Modified Length
+ if user_data['requestResponse'] and user_data['requestResponse'].getResponse():
+ response = user_data['requestResponse'].getResponse()
+ return len(response) - self._extender._helpers.analyzeResponse(response).getBodyOffset()
+ return 0
+ elif col_type == 1: # Authorization Status
+ return user_data['enforcementStatus']
+
return ""
+
+class ColorConstants:
+ BLACK = Color.BLACK
+ WHITE = Color.WHITE
+ BYPASSED_BG = Color(255, 153, 153) # Light red
+ IS_ENFORCED_BG = Color(255, 204, 153) # Light orange
+ ENFORCED_BG = Color(204, 255, 153) # Light green
+ DISABLED_BG = Color(211, 211, 211) # Light gray
+ SELECTED_BG = Color(201, 215, 255)
class TableSelectionListener(ListSelectionListener):
"""Class Responsible for the multi-row deletion"""
@@ -284,40 +186,129 @@ def __init__(self, extender):
self._extender.tableModel = TableModel(extender)
self.setModel(self._extender.tableModel)
self.addMouseListener(Mouseclick(self._extender))
- self.getColumnModel().getColumn(0).setPreferredWidth(450)
self.setRowSelectionAllowed(True)
+
# Enables multi-row selection
self.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
+ self.updateColumnWidths()
+
+ def updateColumnWidths(self):
+ if self.getColumnCount() > 0:
+ column_model = self.getColumnModel()
+
+ widths = [50, 80, 300, 80, 80, 120]
+ for i, width in enumerate(widths):
+ column_model.getColumn(i).setPreferredWidth(width)
+
+ if hasattr(self._extender, 'userTab') and self._extender.userTab:
+ user_count = len(self._extender.userTab.user_tabs)
+ for i in range(6, 6 + (user_count << 1)): # Bit shift for multiply by 2
+ column_model.getColumn(i).setPreferredWidth(100)
def prepareRenderer(self, renderer, row, col):
comp = JTable.prepareRenderer(self, renderer, row, col)
- value = self._extender.tableModel.getValueAt(self._extender.logTable.convertRowIndexToModel(row), col)
- if col == 6 or col == 7:
- if value == self._extender.BYPASSSED_STR:
- comp.setBackground(Color(255, 153, 153))
- comp.setForeground(Color.BLACK)
- elif value == self._extender.IS_ENFORCED_STR:
- comp.setBackground(Color(255, 204, 153))
- comp.setForeground(Color.BLACK)
- elif value == self._extender.ENFORCED_STR:
- comp.setBackground(Color(204, 255, 153))
- comp.setForeground(Color.BLACK)
- else:
- comp.setForeground(Color.BLACK)
- comp.setBackground(Color.WHITE)
+
+ if col < 4:
+ comp.setForeground(ColorConstants.BLACK)
+ comp.setBackground(ColorConstants.WHITE)
+
+ selected_rows = self._extender.logTable.getSelectedRows()
+ if row in selected_rows:
+ comp.setBackground(ColorConstants.SELECTED_BG)
+
+ return comp
+
+ model_row = self._extender.logTable.convertRowIndexToModel(row)
+ value = self._extender.tableModel.getValueAt(model_row, col)
+
+ comp.setForeground(Color.BLACK)
+ comp.setBackground(Color.WHITE)
- selectedRows = self._extender.logTable.getSelectedRows()
- if row in selectedRows:
- comp.setBackground(Color(201, 215, 255))
- comp.setForeground(Color.BLACK)
+ should_mask = False
+
+ if col == 4: # Unauthenticated length
+ status_value = self._extender.tableModel.getValueAt(model_row, 5)
+ should_mask = not self.shouldShowStatus(status_value)
+ elif col == 5: # Unauthenticated status
+ should_mask = not self.shouldShowStatus(value)
+ elif col >= 6: # User columns
+ if col & 1:
+ should_mask = not self.shouldShowStatus(value)
+ else:
+ status_col = col + 1
+ if status_col < self._extender.tableModel.getColumnCount():
+ status_value = self._extender.tableModel.getValueAt(model_row, status_col)
+ should_mask = not self.shouldShowStatus(status_value)
+
+ if should_mask:
+ comp.setText("")
+ comp.setBackground(Color.WHITE)
+ comp.setForeground(Color.WHITE)
+ elif col >= 4:
+ if col == 5 or (col >= 6 and col & 1):
+ if value == self._extender.BYPASSSED_STR:
+ comp.setBackground(ColorConstants.BYPASSED_BG)
+ elif value == self._extender.IS_ENFORCED_STR:
+ comp.setBackground(ColorConstants.IS_ENFORCED_BG)
+ elif value == self._extender.ENFORCED_STR:
+ comp.setBackground(ColorConstants.ENFORCED_BG)
+ elif value == "Disabled":
+ comp.setBackground(ColorConstants.DISABLED_BG)
+
+ comp.setForeground(ColorConstants.BLACK)
+
+ selected_rows = self._extender.logTable.getSelectedRows()
+
+ if row in selected_rows and not should_mask:
+ comp.setBackground(ColorConstants.SELECTED_BG)
+ comp.setForeground(ColorConstants.BLACK)
return comp
+ def shouldShowStatus(self, status):
+ if not hasattr(self._extender, 'showBypassed'):
+ return True
+
+ if (self._extender.showBypassed.isSelected() and
+ self._extender.showIsEnforced.isSelected() and
+ self._extender.showEnforced.isSelected()):
+ return True
+
+ if status == "Disabled":
+ return True
+ elif self._extender.showBypassed.isSelected() and self._extender.BYPASSSED_STR == status:
+ return True
+ elif self._extender.showIsEnforced.isSelected() and self._extender.IS_ENFORCED_STR == status:
+ return True
+ elif self._extender.showEnforced.isSelected() and self._extender.ENFORCED_STR == status:
+ return True
+
+ return False
+
def changeSelection(self, row, col, toggle, extend):
- # show the log entry for the selected row
logEntry = self._extender._log.get(self._extender.logTable.convertRowIndexToModel(row))
- self._extender._requestViewer.setMessage(logEntry._requestResponse.getRequest(), True)
- self._extender._responseViewer.setMessage(logEntry._requestResponse.getResponse(), False)
+
+ current_user_name = "Original"
+ current_request_response = logEntry._originalrequestResponse
+
+ if col >= 6 and hasattr(self._extender, 'userTab') and self._extender.userTab:
+ user_index = (col - 6) >> 1
+ user_ids = sorted(self._extender.userTab.user_tabs.keys())
+ if user_index < len(user_ids):
+ user_id = user_ids[user_index]
+ user_name = self._extender.userTab.user_tabs[user_id]['user_name']
+ user_data = logEntry.get_user_enforcement(user_id)
+ if user_data and user_data['requestResponse']:
+ current_user_name = user_name
+ current_request_response = user_data['requestResponse']
+
+ if col >= 4 and col < 6: # Unauthenticated columns
+ current_request_response = logEntry._unauthorizedRequestResponse
+
+ current_user_name = "Unauthenticated"
+
+ self._extender._requestViewer.setMessage(current_request_response.getRequest(), True)
+ self._extender._responseViewer.setMessage(current_request_response.getResponse(), False)
self._extender._originalrequestViewer.setMessage(logEntry._originalrequestResponse.getRequest(), True)
self._extender._originalresponseViewer.setMessage(logEntry._originalrequestResponse.getResponse(), False)
@@ -330,37 +321,154 @@ def changeSelection(self, row, col, toggle, extend):
self._extender._currentlyDisplayedItem = logEntry
- if col == 3:
+ self.updateTabTitles(current_user_name)
+
+ if col == 2: # URL column
collapse(self._extender, self._extender.modified_requests_tabs)
collapse(self._extender, self._extender.unauthenticated_requests_tabs)
expand(self._extender, self._extender.original_requests_tabs)
- elif col == 4 or col == 6:
+ elif col >= 6: # User columns
collapse(self._extender, self._extender.original_requests_tabs)
collapse(self._extender, self._extender.unauthenticated_requests_tabs)
expand(self._extender, self._extender.modified_requests_tabs)
- elif col == 5 or col == 7:
+ elif col == 4 or col == 5: # Unauth Status
collapse(self._extender, self._extender.original_requests_tabs)
collapse(self._extender, self._extender.modified_requests_tabs)
expand(self._extender, self._extender.unauthenticated_requests_tabs)
- else:
- collapse(self._extender, self._extender.original_requests_tabs)
- collapse(self._extender, self._extender.modified_requests_tabs)
- collapse(self._extender, self._extender.unauthenticated_requests_tabs)
+
+ self.updateContextMenuText(col)
JTable.changeSelection(self, row, col, toggle, extend)
return
+ def updateContextMenuText(self, col):
+ modified_text = "Send Modified Request to Repeater"
+ comparer_text = "Send Responses to Comparer"
+
+ if col >= 6 and hasattr(self._extender, 'userTab') and self._extender.userTab:
+ user_index = (col - 6) // 2
+ user_ids = sorted(self._extender.userTab.user_tabs.keys())
+ if user_index < len(user_ids):
+ user_id = user_ids[user_index]
+ user_name = self._extender.userTab.user_tabs[user_id]['user_name']
+ modified_text = "Send {} Request to Repeater".format(user_name)
+ comparer_text = "Send {} Responses to Comparer".format(user_name)
+ elif col == 4 or col == 5:
+ modified_text = "Send Unauthenticated Request to Repeater"
+ comparer_text = "Send Unauthenticated Responses to Comparer"
+
+ if hasattr(self._extender, 'sendRequestMenu2'):
+ self._extender.sendRequestMenu2.setText(modified_text)
+ if hasattr(self._extender, 'sendResponseMenu'):
+ self._extender.sendResponseMenu.setText(comparer_text)
+
+ def updateTabTitles(self, user_name):
+ if hasattr(self._extender, 'modified_requests_tabs'):
+ self._extender.modified_requests_tabs.setTitleAt(0, "{} Modified Request".format(user_name))
+ self._extender.modified_requests_tabs.setTitleAt(1, "{} Modified Response".format(user_name))
+
+class TableExtension:
+ def prepareRenderer(self, renderer, row, col):
+ comp = JTable.prepareRenderer(self, renderer, row, col)
+
+ if col < 5:
+ comp.setForeground(ColorConstants.BLACK)
+ comp.setBackground(ColorConstants.WHITE)
+
+ selected_rows = self._extender.logTable.getSelectedRows()
+ if row in selected_rows:
+ comp.setBackground(ColorConstants.SELECTED_BG)
+ comp.setForeground(ColorConstants.BLACK)
+
+ return comp
+
+ model_row = self._extender.logTable.convertRowIndexToModel(row)
+ value = self._extender.tableModel.getValueAt(model_row, col)
+
+ comp.setForeground(ColorConstants.BLACK)
+ comp.setBackground(ColorConstants.WHITE)
+ should_mask = False
+
+ if col == 5:
+ should_mask = not self.shouldShowStatus(value)
+ elif col >= 6:
+ if col & 1: # Odd columns are status
+ should_mask = not self.shouldShowStatus(value)
+ else: # Even columns are length
+ status_col = col + 1
+ if status_col < self._extender.tableModel.getColumnCount():
+ status_value = self._extender.tableModel.getValueAt(model_row, status_col)
+ should_mask = not self.shouldShowStatus(status_value)
+
+ if should_mask:
+ comp.setText("")
+ comp.setBackground(ColorConstants.WHITE)
+ comp.setForeground(ColorConstants.WHITE)
+ else:
+ if col & 1 or col == 5: # Status columns
+ if value == self._extender.BYPASSSED_STR:
+ comp.setBackground(ColorConstants.BYPASSED_BG)
+ elif value == self._extender.IS_ENFORCED_STR:
+ comp.setBackground(ColorConstants.IS_ENFORCED_BG)
+ elif value == self._extender.ENFORCED_STR:
+ comp.setBackground(ColorConstants.ENFORCED_BG)
+ elif value == "Disabled":
+ comp.setBackground(ColorConstants.DISABLED_BG)
+
+ comp.setForeground(ColorConstants.BLACK)
+
+ selected_rows = self._extender.logTable.getSelectedRows()
+ if row in selected_rows and (not should_mask or col < 5):
+ comp.setBackground(ColorConstants.SELECTED_BG)
+ comp.setForeground(ColorConstants.BLACK)
+
+ return comp
+
+ def shouldShowStatus(self, status):
+ if not hasattr(self._extender, 'showBypassed'):
+ return True
+
+ if (self._extender.showBypassed.isSelected() and
+ self._extender.showIsEnforced.isSelected() and
+ self._extender.showEnforced.isSelected()):
+ return True
+
+ if status == "Disabled":
+ return True
+ elif self._extender.showBypassed.isSelected() and self._extender.BYPASSSED_STR == status:
+ return True
+ elif self._extender.showIsEnforced.isSelected() and self._extender.IS_ENFORCED_STR == status:
+ return True
+ elif self._extender.showEnforced.isSelected() and self._extender.ENFORCED_STR == status:
+ return True
+
+ return False
+
class LogEntry:
- def __init__(self, id, requestResponse, method, url, originalrequestResponse, enforcementStatus, unauthorizedRequestResponse, enforcementStatusUnauthorized):
+ def __init__(self, id, method, url, originalrequestResponse, unauthorizedRequestResponse, enforcementStatusUnauthorized):
self._id = id
- self._requestResponse = requestResponse
- self._originalrequestResponse = originalrequestResponse
self._method = method
self._url = url
- self._enfocementStatus = enforcementStatus
+ self._originalrequestResponse = originalrequestResponse
self._unauthorizedRequestResponse = unauthorizedRequestResponse
- self._enfocementStatusUnauthorized = enforcementStatusUnauthorized
- return
+ self._enfocementStatusUnauthorized = enforcementStatusUnauthorized
+
+ self._userEnforcements = {}
+
+ def add_user_enforcement(self, user_id, requestResponse, enforcementStatus):
+ self._userEnforcements[user_id] = {
+ 'requestResponse': requestResponse,
+ 'enforcementStatus': enforcementStatus
+ }
+
+ def get_user_enforcement(self, user_id):
+ return self._userEnforcements.get(user_id, None)
+
+ def get_all_users(self):
+ return list(self._userEnforcements.keys())
+
+ def has_user_data(self, user_id):
+ return user_id in self._userEnforcements
class Mouseclick(MouseAdapter):
def __init__(self, extender):
@@ -375,23 +483,45 @@ def __init__(self, extender):
self._extender = extender
def include(self, entry):
- if self._extender.showAuthBypassModified.isSelected() and self._extender.BYPASSSED_STR == entry.getValue(6):
+ if (hasattr(self._extender, 'showBypassed') and
+ self._extender.showBypassed.isSelected() and
+ self._extender.showIsEnforced.isSelected() and
+ self._extender.showEnforced.isSelected()):
return True
- elif self._extender.showAuthPotentiallyEnforcedModified.isSelected() and self._extender.IS_ENFORCED_STR == entry.getValue(6):
+
+ unauth_status = entry.getValue(5) if entry.getValueCount() > 5 else ""
+
+ if self.statusMatchesFilter(unauth_status):
return True
- elif self._extender.showAuthEnforcedModified.isSelected() and self._extender.ENFORCED_STR == entry.getValue(6):
+
+ if hasattr(self._extender, 'userTab') and self._extender.userTab:
+ user_count = len(self._extender.userTab.user_tabs)
+
+ for i in range(user_count):
+ status_col = 7 + (i << 1)
+
+ if status_col < entry.getValueCount():
+ user_status = entry.getValue(status_col)
+ if self.statusMatchesFilter(user_status):
+ return True
+
+ return False
+
+ def statusMatchesFilter(self, status):
+ if not hasattr(self._extender, 'showBypassed'):
return True
- elif self._extender.showAuthBypassUnauthenticated.isSelected() and self._extender.BYPASSSED_STR == entry.getValue(7):
+
+ if self._extender.showBypassed.isSelected() and self._extender.BYPASSSED_STR == status:
return True
- elif self._extender.showAuthPotentiallyEnforcedUnauthenticated.isSelected() and self._extender.IS_ENFORCED_STR == entry.getValue(7):
+ elif self._extender.showIsEnforced.isSelected() and self._extender.IS_ENFORCED_STR == status:
return True
- elif self._extender.showAuthEnforcedUnauthenticated.isSelected() and self._extender.ENFORCED_STR == entry.getValue(7):
+ elif self._extender.showEnforced.isSelected() and self._extender.ENFORCED_STR == status:
return True
- elif self._extender.showDisabledUnauthenticated.isSelected() and "Disabled" == entry.getValue(7):
+ elif status == "Disabled":
return True
- else:
- return False
-
+
+ return False
+
class UpdateTableEDT(Runnable):
def __init__(self,extender,action,firstRow,lastRow):
self._extender=extender
@@ -407,5 +537,4 @@ def run(self):
elif self._action == "delete":
self._extender.tableModel.fireTableRowsDeleted(self._firstRow, self._lastRow)
else:
- print("Invalid action in UpdateTableEDT")
-
+ print("Invalid action in UpdateTableEDT")
\ No newline at end of file
diff --git a/gui/tabs.py b/gui/tabs.py
index 2094497..8262943 100644
--- a/gui/tabs.py
+++ b/gui/tabs.py
@@ -52,16 +52,8 @@ def draw(self):
"""
self._extender.logTable = Table(self._extender)
-
- tableWidth = self._extender.logTable.getPreferredSize().width
- self._extender.logTable.getColumn("ID").setPreferredWidth(Math.round(tableWidth / 50 * 2))
- self._extender.logTable.getColumn("Method").setPreferredWidth(Math.round(tableWidth / 50 * 3))
- self._extender.logTable.getColumn("URL").setPreferredWidth(Math.round(tableWidth / 50 * 25))
- self._extender.logTable.getColumn("Orig. Len").setPreferredWidth(Math.round(tableWidth / 50 * 4))
- self._extender.logTable.getColumn("Modif. Len").setPreferredWidth(Math.round(tableWidth / 50 * 4))
- self._extender.logTable.getColumn("Unauth. Len").setPreferredWidth(Math.round(tableWidth / 50 * 4))
- self._extender.logTable.getColumn("Authz. Status").setPreferredWidth(Math.round(tableWidth / 50 * 4))
- self._extender.logTable.getColumn("Unauth. Status").setPreferredWidth(Math.round(tableWidth / 50 * 4))
+
+ self.setupDynamicColumns()
self._extender.tableSorter = TableRowSorter(self._extender.tableModel)
rowFilter = TableRowFilter(self._extender)
@@ -81,8 +73,8 @@ def draw(self):
sendRequestMenu = JMenuItem("Send Original Request to Repeater")
sendRequestMenu.addActionListener(SendRequestRepeater(self._extender, self._extender._callbacks, True))
- sendRequestMenu2 = JMenuItem("Send Modified Request to Repeater")
- sendRequestMenu2.addActionListener(SendRequestRepeater(self._extender, self._extender._callbacks, False))
+ self._extender.sendRequestMenu2 = JMenuItem("Send Modified Request to Repeater")
+ self._extender.sendRequestMenu2.addActionListener(SendRequestRepeater(self._extender, self._extender._callbacks, False))
# Define the key combination for the shortcut
try:
@@ -109,8 +101,8 @@ def draw(self):
actionMap.put("copyToClipBoard",
CopySelectedURLToClipBoard(self._extender, self._extender._callbacks))
- sendResponseMenu = JMenuItem("Send Responses to Comparer")
- sendResponseMenu.addActionListener(SendResponseComparer(self._extender, self._extender._callbacks))
+ self._extender.sendResponseMenu = JMenuItem("Send Responses to Comparer")
+ self._extender.sendResponseMenu.addActionListener(SendResponseComparer(self._extender, self._extender._callbacks))
retestSelecteditem = JMenuItem("Retest selected request")
retestSelecteditem.addActionListener(RetestSelectedRequest(self._extender))
@@ -123,8 +115,8 @@ def draw(self):
self._extender.menu = JPopupMenu("Popup")
self._extender.menu.add(sendRequestMenu)
- self._extender.menu.add(sendRequestMenu2)
- self._extender.menu.add(sendResponseMenu)
+ self._extender.menu.add(self._extender.sendRequestMenu2)
+ self._extender.menu.add(self._extender.sendResponseMenu)
self._extender.menu.add(copyURLitem)
self._extender.menu.add(retestSelecteditem)
self._extender.menu.add(retestAllitem)
@@ -132,6 +124,7 @@ def draw(self):
message_editor = MessageEditor(self._extender)
self._extender.tabs = JTabbedPane()
+
self._extender._requestViewer = self._extender._callbacks.createMessageEditor(message_editor, False)
self._extender._responseViewer = self._extender._callbacks.createMessageEditor(message_editor, False)
@@ -147,7 +140,7 @@ def draw(self):
self._extender.original_requests_tabs.addTab("Original Response", self._extender._originalresponseViewer.getComponent())
self._extender.original_requests_tabs.addTab("Expand", None)
self._extender.original_requests_tabs.setSelectedIndex(0)
-
+
self._extender.unauthenticated_requests_tabs = JTabbedPane()
self._extender.unauthenticated_requests_tabs.addMouseListener(Mouseclick(self._extender))
self._extender.unauthenticated_requests_tabs.addTab("Unauthenticated Request", self._extender._unauthorizedrequestViewer.getComponent())
@@ -174,6 +167,18 @@ def draw(self):
self._extender.tabs.setMinimumSize(Dimension(1,1))
self._extender._splitpane.setRightComponent(self._extender.tabs)
+ self._extender.tabs.addTab("User", self._extender.userPanel)
+
+ def setupDynamicColumns(self):
+ if hasattr(self._extender, 'tableModel'):
+ self._extender.tableModel.fireTableStructureChanged()
+ if hasattr(self._extender, 'logTable'):
+ self._extender.logTable.updateColumnWidths()
+
+ def refreshTable(self):
+ if hasattr(self._extender, 'tableModel'):
+ self._extender.tableModel.fireTableStructureChanged()
+ self.setupDynamicColumns()
class SendRequestRepeater(ActionListener):
def __init__(self, extender, callbacks, original):
@@ -199,13 +204,36 @@ def __init__(self, extender, callbacks):
self._callbacks = callbacks
def actionPerformed(self, e):
+ if not hasattr(self._extender, '_currentlyDisplayedItem') or not self._extender._currentlyDisplayedItem:
+ return
+
originalResponse = self._extender._currentlyDisplayedItem._originalrequestResponse
- modifiedResponse = self._extender._currentlyDisplayedItem._requestResponse
unauthorizedResponse = self._extender._currentlyDisplayedItem._unauthorizedRequestResponse
+ selected_col = self._extender.logTable.getSelectedColumn()
+
+ if selected_col >= 6 and hasattr(self._extender, 'userTab') and self._extender.userTab:
+ user_index = (selected_col - 6) >> 1
+ user_ids = sorted(self._extender.userTab.user_tabs.keys())
+ if user_index < len(user_ids):
+ user_id = user_ids[user_index]
+ user_data = self._extender._currentlyDisplayedItem.get_user_enforcement(user_id)
+ if user_data and user_data['requestResponse']:
+ modifiedResponse = user_data['requestResponse']
+ else:
+ modifiedResponse = originalResponse
+ else:
+ modifiedResponse = originalResponse
+ elif selected_col == 4 or selected_col == 5:
+ modifiedResponse = unauthorizedResponse or originalResponse
+ else:
+ modifiedResponse = originalResponse
+
self._callbacks.sendToComparer(originalResponse.getResponse())
- self._callbacks.sendToComparer(modifiedResponse.getResponse())
- self._callbacks.sendToComparer(unauthorizedResponse.getResponse())
+ if modifiedResponse:
+ self._callbacks.sendToComparer(modifiedResponse.getResponse())
+ if unauthorizedResponse:
+ self._callbacks.sendToComparer(unauthorizedResponse.getResponse())
class RetestSelectedRequest(ActionListener):
@@ -228,7 +256,6 @@ def __init__(self, extender):
self._extender = extender
def actionPerformed(self, e):
- # Its ready to delete multiple rows at a time once we can figure out how to select multiple row.
rows = self._extender.logTable.getSelectedRows()
if len(rows) != 0:
rows = [self._extender.logTable.convertRowIndexToModel(row) for row in rows]
@@ -239,9 +266,10 @@ def __init__(self, extender):
self._extender = extender
def actionPerformed(self, e):
- stringSelection = StringSelection(str(self._extender._helpers.analyzeRequest(self._extender._currentlyDisplayedItem._requestResponse).getUrl()))
- clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard()
- clpbrd.setContents(stringSelection, None)
+ if hasattr(self._extender, '_currentlyDisplayedItem') and self._extender._currentlyDisplayedItem:
+ stringSelection = StringSelection(str(self._extender._helpers.analyzeRequest(self._extender._currentlyDisplayedItem._originalrequestResponse).getUrl()))
+ clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard()
+ clpbrd.setContents(stringSelection, None)
class AutoScrollListener(AdjustmentListener):
def __init__(self, extender):
@@ -256,13 +284,21 @@ def __init__(self, extender):
self._extender = extender
def getHttpService(self):
- return self._extender._currentlyDisplayedItem.getHttpService()
+ return self._extender._currentlyDisplayedItem._originalrequestResponse.getHttpService()
def getRequest(self):
- return self._extender._currentlyDisplayedItem.getRequest()
+ if hasattr(self._extender, '_currentUserSelection'):
+ user_data = self._extender._currentlyDisplayedItem.get_user_enforcement(self._extender._currentUserSelection)
+ if user_data and user_data['requestResponse']:
+ return user_data['requestResponse'].getRequest()
+ return self._extender._currentlyDisplayedItem._originalrequestResponse.getRequest()
def getResponse(self):
- return self._extender._currentlyDisplayedItem.getResponse()
+ if hasattr(self._extender, '_currentUserSelection'):
+ user_data = self._extender._currentlyDisplayedItem.get_user_enforcement(self._extender._currentUserSelection)
+ if user_data and user_data['requestResponse']:
+ return user_data['requestResponse'].getResponse()
+ return self._extender._currentlyDisplayedItem._originalrequestResponse.getResponse()
class Mouseclick(MouseAdapter):
def __init__(self, extender):
@@ -275,21 +311,75 @@ def mouseReleased(self, evt):
else:
collapse(self._extender, evt.getComponent())
+class SendRequestRepeater(ActionListener):
+ def __init__(self, extender, callbacks, original):
+ self._extender = extender
+ self._callbacks = callbacks
+ self.original = original
+
+ def actionPerformed(self, e):
+ if not hasattr(self._extender, '_currentlyDisplayedItem') or not self._extender._currentlyDisplayedItem:
+ return
+
+ if self.original:
+ request = self._extender._currentlyDisplayedItem._originalrequestResponse
+ else:
+ selected_row = self._extender.logTable.getSelectedRow()
+ selected_col = self._extender.logTable.getSelectedColumn()
+
+ if selected_col >= 6 and hasattr(self._extender, 'userTab') and self._extender.userTab:
+ user_index = (selected_col - 6) >> 1
+ user_ids = sorted(self._extender.userTab.user_tabs.keys())
+ if user_index < len(user_ids):
+ user_id = user_ids[user_index]
+ user_data = self._extender._currentlyDisplayedItem.get_user_enforcement(user_id)
+ if user_data and user_data['requestResponse']:
+ request = user_data['requestResponse']
+ else:
+ request = self._extender._currentlyDisplayedItem._originalrequestResponse
+ else:
+ request = self._extender._currentlyDisplayedItem._originalrequestResponse
+ elif selected_col == 4 or selected_col == 5:
+ request = self._extender._currentlyDisplayedItem._unauthorizedRequestResponse or self._extender._currentlyDisplayedItem._originalrequestResponse
+ else:
+ request = self._extender._currentlyDisplayedItem._originalrequestResponse
+
+ host = request.getHttpService().getHost()
+ port = request.getHttpService().getPort()
+ proto = request.getHttpService().getProtocol()
+ secure = True if proto == "https" else False
+
+ self._callbacks.sendToRepeater(host, port, secure, request.getRequest(), "Autorize")
+
class SendRequestToRepeaterAction(AbstractAction):
def __init__(self, extender, callbacks):
self._extender = extender
self._callbacks = callbacks
def actionPerformed(self, e):
- # Get the selected row of the JTable
- row = self._extender.logTable.getSelectedRow()
-
- # Get the LogEntry object for the selected row
- rowModelIndex = self._extender.logTable.convertRowIndexToModel(row)
- entry = self._extender.tableModel.getValueAt(rowModelIndex, 0)
+ if not hasattr(self._extender, '_currentlyDisplayedItem') or not self._extender._currentlyDisplayedItem:
+ return
+
+ selected_col = self._extender.logTable.getSelectedColumn()
+
+ if selected_col >= 6 and hasattr(self._extender, 'userTab') and self._extender.userTab:
+ user_index = (selected_col - 6) >> 1
+ user_ids = sorted(self._extender.userTab.user_tabs.keys())
+ if user_index < len(user_ids):
+ user_id = user_ids[user_index]
+ user_data = self._extender._currentlyDisplayedItem.get_user_enforcement(user_id)
+ if user_data and user_data['requestResponse']:
+ request = user_data['requestResponse']
+ else:
+ request = self._extender._currentlyDisplayedItem._originalrequestResponse
+ else:
+ request = self._extender._currentlyDisplayedItem._originalrequestResponse
+ elif selected_col == 4 or selected_col == 5:
+ # Unauthenticated column
+ request = self._extender._currentlyDisplayedItem._unauthorizedRequestResponse or self._extender._currentlyDisplayedItem._originalrequestResponse
+ else:
+ request = self._extender._currentlyDisplayedItem._originalrequestResponse
- # Get the modified request
- request = self._extender._currentlyDisplayedItem._requestResponse
host = request.getHttpService().getHost()
port = request.getHttpService().getPort()
proto = request.getHttpService().getProtocol()
@@ -303,7 +393,7 @@ def __init__(self, extender, callbacks):
self._callbacks = callbacks
def actionPerformed(self, e):
- stringSelection = StringSelection(str(self._extender._helpers.analyzeRequest(
- self._extender._currentlyDisplayedItem._requestResponse).getUrl()))
- clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard()
- clpbrd.setContents(stringSelection, None)
\ No newline at end of file
+ if hasattr(self._extender, '_currentlyDisplayedItem') and self._extender._currentlyDisplayedItem:
+ stringSelection = StringSelection(str(self._extender._helpers.analyzeRequest(self._extender._currentlyDisplayedItem._originalrequestResponse).getUrl()))
+ clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard()
+ clpbrd.setContents(stringSelection, None)
\ No newline at end of file
diff --git a/gui/user_tab.py b/gui/user_tab.py
new file mode 100644
index 0000000..f17e5e9
--- /dev/null
+++ b/gui/user_tab.py
@@ -0,0 +1,289 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from javax.swing import JPanel
+from javax.swing import JLabel
+from javax.swing import JButton
+from javax.swing import JTabbedPane
+from javax.swing import JOptionPane
+from java.awt import BorderLayout
+from java.awt import FlowLayout
+from java.awt import Font
+from java.awt.event import ActionListener
+
+from gui.enforcement_detector import EnforcementDetectors
+from gui.match_replace import MatchReplace
+
+class UserTab():
+ def __init__(self, extender):
+ self._extender = extender
+ self.user_count = 0
+ self.user_tabs = {}
+ self.user_names = []
+
+ def draw(self):
+ self._extender.userPanel = JPanel(BorderLayout())
+
+ buttonPanel = JPanel(FlowLayout(FlowLayout.LEFT))
+
+ self.addUserBtn = JButton("Add User")
+ self.addUserBtn.addActionListener(AddUserAction(self))
+ buttonPanel.add(self.addUserBtn)
+
+ self.removeUserBtn = JButton("Remove User")
+ self.removeUserBtn.addActionListener(RemoveUserAction(self))
+ buttonPanel.add(self.removeUserBtn)
+
+ self.duplicateUserBtn = JButton("Duplicate User")
+ self.duplicateUserBtn.addActionListener(DuplicateUserAction(self))
+ buttonPanel.add(self.duplicateUserBtn)
+
+ self.renameUserBtn = JButton("Rename User")
+ self.renameUserBtn.addActionListener(RenameUserAction(self))
+ buttonPanel.add(self.renameUserBtn)
+
+ self.userTabs = JTabbedPane()
+
+ self.add_user()
+
+ self._extender.userPanel.add(buttonPanel, BorderLayout.NORTH)
+ self._extender.userPanel.add(self.userTabs, BorderLayout.CENTER)
+
+ def add_user(self):
+ self.user_count += 1
+ user_name = "User {}".format(self.user_count)
+ unique_user_name = self.get_unique_name(user_name)
+
+ self.user_names.append(unique_user_name)
+
+ userPanel = JPanel(BorderLayout())
+
+ headerPanel = JPanel(FlowLayout(FlowLayout.LEFT))
+ headerLabel = JLabel(unique_user_name)
+ headerLabel.setFont(Font("Tahoma", Font.BOLD, 12))
+ headerPanel.add(headerLabel)
+
+ userSubTabs = JTabbedPane()
+
+ user_ed = UserEnforcementDetector(self.user_count)
+ user_ed.draw()
+
+ user_mr = UserMatchReplace(self.user_count)
+ user_mr.draw()
+
+ userSubTabs.addTab("Enforcement Detector", user_ed.EDPnl)
+
+ userSubTabs.addTab("Match/Replace", user_mr.MRPnl)
+
+ userPanel.add(headerPanel, BorderLayout.NORTH)
+ userPanel.add(userSubTabs, BorderLayout.CENTER)
+
+ self.user_tabs[self.user_count] = {
+ 'user_id': self.user_count,
+ 'user_name': unique_user_name,
+ 'panel': userPanel,
+ 'subtabs': userSubTabs,
+ 'ed_instance': user_ed,
+ 'mr_instance': user_mr,
+ 'header_label': headerLabel
+ }
+
+ self.userTabs.addTab(unique_user_name, userPanel)
+
+ self.userTabs.setSelectedIndex(self.userTabs.getTabCount() - 1)
+
+ self.refreshTableStructure()
+
+ def remove_user(self):
+ if self.userTabs.getTabCount() <= 1:
+ JOptionPane.showMessageDialog(None, "Cannot remove the last user!", "Warning", JOptionPane.WARNING_MESSAGE)
+ return
+
+ selected_index = self.userTabs.getSelectedIndex()
+
+ if selected_index >= 0:
+ selected_panel = self.userTabs.getComponentAt(selected_index)
+
+ user_id_to_remove = None
+ user_name_to_remove = None
+
+ for user_id, user_data in self.user_tabs.items():
+ if user_data['panel'] == selected_panel:
+ user_id_to_remove = user_id
+ user_name_to_remove = user_data['user_name']
+ break
+
+ if user_id_to_remove and user_name_to_remove:
+ if user_name_to_remove in self.user_names:
+ self.user_names.remove(user_name_to_remove)
+
+ del self.user_tabs[user_id_to_remove]
+
+ self.userTabs.removeTabAt(selected_index)
+
+ self.refreshTableStructure()
+
+ def reset_user(self):
+ self.userTabs.removeAll()
+ self.user_tabs.clear()
+ del self.user_names[:]
+ self.user_count = 0
+ self.add_user()
+
+ def duplicate_user(self):
+ selected_index = self.userTabs.getSelectedIndex()
+
+ if selected_index >= 0:
+ selected_panel = self.userTabs.getComponentAt(selected_index)
+ source_user_data = None
+
+ for user_id, user_data in self.user_tabs.items():
+ if user_data['panel'] == selected_panel:
+ source_user_data = user_data
+ break
+
+ if source_user_data:
+ self.add_user()
+ new_user_id = self.user_count
+ new_user_data = self.user_tabs[new_user_id]
+
+ self.copy_ed_settings(source_user_data['ed_instance'], new_user_data['ed_instance'])
+ self.copy_mr_settings(source_user_data['mr_instance'], new_user_data['mr_instance'])
+
+ def copy_ed_settings(self, source_ed, target_ed):
+ target_ed.EDModel.clear()
+ for i in range(source_ed.EDModel.getSize()):
+ target_ed.EDModel.addElement(source_ed.EDModel.getElementAt(i))
+
+ target_ed.EDType.setSelectedIndex(source_ed.EDType.getSelectedIndex())
+ target_ed.EDText.setText(source_ed.EDText.getText())
+ target_ed.AndOrType.setSelectedIndex(source_ed.AndOrType.getSelectedIndex())
+
+ def copy_mr_settings(self, source_mr, target_mr):
+ target_mr.MRModel.clear()
+ for i in range(source_mr.MRModel.getSize()):
+ target_mr.MRModel.addElement(source_mr.MRModel.getElementAt(i))
+
+ target_mr.MRType.setSelectedIndex(source_mr.MRType.getSelectedIndex())
+ target_mr.MText.setText(source_mr.MText.getText())
+ target_mr.RText.setText(source_mr.RText.getText())
+
+ target_mr.badProgrammerMRModel.clear()
+ for key, value in source_mr.badProgrammerMRModel.items():
+ if hasattr(value, 'copy'):
+ target_mr.badProgrammerMRModel[key] = value.copy()
+ elif isinstance(value, dict):
+ target_mr.badProgrammerMRModel[key] = dict(value)
+ else:
+ target_mr.badProgrammerMRModel[key] = value
+
+ def rename_user(self):
+ selected_index = self.userTabs.getSelectedIndex()
+
+ if selected_index >= 0:
+ current_name = self.userTabs.getTitleAt(selected_index)
+ new_name = JOptionPane.showInputDialog(None, "Enter new name for user:", "Rename User", JOptionPane.QUESTION_MESSAGE, None, None, current_name)
+
+ if new_name and new_name.strip():
+ if current_name in self.user_names:
+ self.user_names.remove(current_name)
+
+ unique_name = self.get_unique_name(new_name.strip())
+ self.user_names.append(unique_name)
+
+ self.userTabs.setTitleAt(selected_index, unique_name)
+
+ selected_panel = self.userTabs.getComponentAt(selected_index)
+
+ for user_id, user_data in self.user_tabs.items():
+ if user_data['panel'] == selected_panel:
+ user_data['header_label'].setText(unique_name)
+ user_data['user_name'] = unique_name
+ break
+
+ self.refreshTableStructure()
+
+ def get_unique_name(self, name):
+ if name not in self.user_names:
+ return name
+
+ counter = 1
+ while True:
+ candidate_name = "{} Copy".format(name) if counter == 1 else "{} Copy {}".format(name, counter)
+
+ if candidate_name not in self.user_names:
+ return candidate_name
+
+ counter += 1
+
+ if counter > 100:
+ return "{} Copy {}".format(name, counter)
+
+ def refreshTableStructure(self):
+ if hasattr(self._extender, 'tableModel'):
+ self._extender.tableModel.fireTableStructureChanged()
+ if hasattr(self._extender, 'logTable'):
+ self._extender.logTable.updateColumnWidths()
+
+class UserEnforcementDetector(EnforcementDetectors):
+
+ def __init__(self, user_id):
+ self.isolated_extender = type('IsolatedExtender', (object,), {})()
+ self.user_id = user_id
+
+ EnforcementDetectors.__init__(self, self.isolated_extender)
+
+ def draw(self):
+ EnforcementDetectors.draw(self)
+ self.EDPnl = self.isolated_extender.EDPnl
+ self.EDType = self.isolated_extender.EDType
+ self.EDText = self.isolated_extender.EDText
+ self.EDModel = self.isolated_extender.EDModel
+ self.EDList = self.isolated_extender.EDList
+ self.AndOrType = self.isolated_extender.AndOrType
+
+class UserMatchReplace(MatchReplace):
+ def __init__(self, user_id):
+ self.isolated_extender = type('IsolatedExtender', (object,), {})()
+ self.user_id = user_id
+
+ MatchReplace.__init__(self, self.isolated_extender)
+
+ def draw(self):
+ MatchReplace.draw(self)
+
+ self.MRPnl = self.isolated_extender.MRPnl
+ self.MRType = self.isolated_extender.MRType
+ self.MText = self.isolated_extender.MText
+ self.RText = self.isolated_extender.RText
+ self.MRModel = self.isolated_extender.MRModel
+ self.MRList = self.isolated_extender.MRList
+ self.badProgrammerMRModel = self.isolated_extender.badProgrammerMRModel
+
+class AddUserAction(ActionListener):
+ def __init__(self, user_tab):
+ self.user_tab = user_tab
+
+ def actionPerformed(self, event):
+ self.user_tab.add_user()
+
+class RemoveUserAction(ActionListener):
+ def __init__(self, user_tab):
+ self.user_tab = user_tab
+
+ def actionPerformed(self, event):
+ self.user_tab.remove_user()
+
+class DuplicateUserAction(ActionListener):
+ def __init__(self, user_tab):
+ self.user_tab = user_tab
+
+ def actionPerformed(self, event):
+ self.user_tab.duplicate_user()
+
+class RenameUserAction(ActionListener):
+ def __init__(self, user_tab):
+ self.user_tab = user_tab
+
+ def actionPerformed(self, event):
+ self.user_tab.rename_user()
\ No newline at end of file
diff --git a/helpers/initiator.py b/helpers/initiator.py
index a4d0947..af99e29 100644
--- a/helpers/initiator.py
+++ b/helpers/initiator.py
@@ -9,6 +9,7 @@
from gui.table import TableFilter
from gui.export import Export
from gui.menu import MenuImpl
+from gui.user_tab import UserTab
from java.util import ArrayList
from threading import Lock
@@ -18,7 +19,7 @@ def __init__(self, extender):
self._extender = extender
def init_constants(self):
- self.contributors = ["Federico Dotta", "mgeeky", "Marcin Woloszyn", "jpginc", "Eric Harris", "Joao Teles"]
+ self.contributors = ["Federico Dotta", "mgeeky", "Marcin Woloszyn", "jpginc", "Eric Harris", "Joao Teles", "Roy Oswaldha"]
self._extender.version = 1.8
self._extender._log = ArrayList()
self._extender._lock = Lock()
@@ -54,6 +55,11 @@ def draw_all(self):
cfg_tab = ConfigurationTab(self._extender)
cfg_tab.draw()
+ user_tab = UserTab(self._extender)
+ user_tab.draw()
+
+ self._extender.userTab = user_tab
+
tabs = Tabs(self._extender)
tabs.draw()