diff --git a/.gitignore b/.gitignore index 894a44c..70d6172 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,69 @@ venv.bak/ # mypy .mypy_cache/ +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser diff --git a/MainPresenter.py b/MainPresenter.py index 3003e97..43fef43 100644 --- a/MainPresenter.py +++ b/MainPresenter.py @@ -33,18 +33,32 @@ class MainPresenter: thread.exit_signal.connect(self.on_thread_exit) thread.start() - def on_thread_exit(self, thread): - self.threads.pop(self.threads.index(thread[0])) - self.setCurrentThreadsLabel(len(self.threads)) - if len(self.threads) == 0: + def on_thread_exit(self, is_last): + if is_last == True: self.isScanEnabled = False self.ui.startButton.setText("Start") + return + count = 0 + for thr in self.threads: + if thr.is_running == True: + count = count + 1 + self.setCurrentThreadsLabel(count) def stopScan(self): self.isScanEnabled = False for thread in self.threads: - thread.exit_signal.emit(self.threads.index(thread)) thread.exit() + thread.is_running = False + count = 0 + is_last_thread = False + for i in self.threads: + if i.is_running != True: + count += 1 + if count == len(self.threads): + is_last_thread = True + thread.exit_signal.emit(is_last_thread) + self.threads.clear() + self.ui.currentThreadsLabel.setText("0") self.queue = queue.Queue() def setLogText(self, string): @@ -57,7 +71,7 @@ class MainPresenter: class ScanThread(QThread): signal = pyqtSignal(str) - exit_signal = pyqtSignal(list) # This signal for correct pop'ing from thread list + exit_signal = pyqtSignal(bool) def __init__(self, scanQueue, ports, timeout, presenter, parent=None): QThread.__init__(self, parent) @@ -67,17 +81,24 @@ class ScanThread(QThread): self._stop_event = threading.Event() self.timeout = timeout self.presenter = presenter + self.is_running = True def run(self): while True: if self.scanQueue.empty(): - self.exit_signal.emit([self]) + self.is_running = False + count = 0 + is_last_thread = False + for i in self.presenter.threads: + if i.isRunning() != True: + count += 1 + if count == len(self.presenter.threads): + is_last_thread = True + self.exit_signal.emit(is_last_thread) self.exit(1) hostObject = self.scanQueue.get() open_ports = self.coreModel.scanIP(str(hostObject), self.ports) - signalStr = ''.join(str(x) for x in open_ports) - if(signalStr == ''): - self.signal.emit(str(hostObject) + ' has no open ports!') - else: + signalStr = ', '.join(open_ports) + if signalStr != '': self.signal.emit(str(hostObject) + ' has open ports: ' + signalStr) self.scanQueue.task_done() diff --git a/main.py b/main.py index 0015859..b16c9af 100644 --- a/main.py +++ b/main.py @@ -19,7 +19,7 @@ class MyWin(QtWidgets.QMainWindow): self.isScanActive = False def startButtonClicked(self): - if self.isScanActive == False: + if self.presenter.isScanEnabled == False: self.presenter.isScanEnabled = True self.ui.startButton.setText("Stop") self.presenter.startScan(self.ui.ipLine.text(), self.ui.portsLine.text(), self.ui.threadsLine.text(),