mirror of
				https://github.com/sqlmapproject/sqlmap.git
				synced 2025-11-04 09:57:38 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			285 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			285 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/usr/bin/env python
 | 
						|
 | 
						|
"""
 | 
						|
Copyright (c) 2006-2022 sqlmap developers (https://sqlmap.org/)
 | 
						|
See the file 'LICENSE' for copying permission
 | 
						|
"""
 | 
						|
 | 
						|
import os
 | 
						|
import re
 | 
						|
import socket
 | 
						|
import subprocess
 | 
						|
import sys
 | 
						|
import tempfile
 | 
						|
import threading
 | 
						|
import webbrowser
 | 
						|
 | 
						|
from lib.core.common import getSafeExString
 | 
						|
from lib.core.common import saveConfig
 | 
						|
from lib.core.data import paths
 | 
						|
from lib.core.defaults import defaults
 | 
						|
from lib.core.enums import MKSTEMP_PREFIX
 | 
						|
from lib.core.exception import SqlmapMissingDependence
 | 
						|
from lib.core.exception import SqlmapSystemException
 | 
						|
from lib.core.settings import DEV_EMAIL_ADDRESS
 | 
						|
from lib.core.settings import IS_WIN
 | 
						|
from lib.core.settings import ISSUES_PAGE
 | 
						|
from lib.core.settings import GIT_PAGE
 | 
						|
from lib.core.settings import SITE
 | 
						|
from lib.core.settings import VERSION_STRING
 | 
						|
from lib.core.settings import WIKI_PAGE
 | 
						|
from thirdparty.six.moves import queue as _queue
 | 
						|
 | 
						|
alive = None
 | 
						|
line = ""
 | 
						|
process = None
 | 
						|
queue = None
 | 
						|
 | 
						|
def runGui(parser):
 | 
						|
    try:
 | 
						|
        from thirdparty.six.moves import tkinter as _tkinter
 | 
						|
        from thirdparty.six.moves import tkinter_scrolledtext as _tkinter_scrolledtext
 | 
						|
        from thirdparty.six.moves import tkinter_ttk as _tkinter_ttk
 | 
						|
        from thirdparty.six.moves import tkinter_messagebox as _tkinter_messagebox
 | 
						|
    except ImportError as ex:
 | 
						|
        raise SqlmapMissingDependence("missing dependence ('%s')" % getSafeExString(ex))
 | 
						|
 | 
						|
    # Reference: https://www.reddit.com/r/learnpython/comments/985umy/limit_user_input_to_only_int_with_tkinter/e4dj9k9?utm_source=share&utm_medium=web2x
 | 
						|
    class ConstrainedEntry(_tkinter.Entry):
 | 
						|
        def __init__(self, master=None, **kwargs):
 | 
						|
            self.var = _tkinter.StringVar()
 | 
						|
            self.regex = kwargs["regex"]
 | 
						|
            del kwargs["regex"]
 | 
						|
            _tkinter.Entry.__init__(self, master, textvariable=self.var, **kwargs)
 | 
						|
            self.old_value = ''
 | 
						|
            self.var.trace('w', self.check)
 | 
						|
            self.get, self.set = self.var.get, self.var.set
 | 
						|
 | 
						|
        def check(self, *args):
 | 
						|
            if re.search(self.regex, self.get()):
 | 
						|
                self.old_value = self.get()
 | 
						|
            else:
 | 
						|
                self.set(self.old_value)
 | 
						|
 | 
						|
    # Reference: https://code.activestate.com/recipes/580726-tkinter-notebook-that-fits-to-the-height-of-every-/
 | 
						|
    class AutoresizableNotebook(_tkinter_ttk.Notebook):
 | 
						|
        def __init__(self, master=None, **kw):
 | 
						|
            _tkinter_ttk.Notebook.__init__(self, master, **kw)
 | 
						|
            self.bind("<<NotebookTabChanged>>", self._on_tab_changed)
 | 
						|
 | 
						|
        def _on_tab_changed(self, event):
 | 
						|
            event.widget.update_idletasks()
 | 
						|
 | 
						|
            tab = event.widget.nametowidget(event.widget.select())
 | 
						|
            event.widget.configure(height=tab.winfo_reqheight())
 | 
						|
 | 
						|
    try:
 | 
						|
        window = _tkinter.Tk()
 | 
						|
    except Exception as ex:
 | 
						|
        errMsg = "unable to create GUI window ('%s')" % getSafeExString(ex)
 | 
						|
        raise SqlmapSystemException(errMsg)
 | 
						|
 | 
						|
    window.title(VERSION_STRING)
 | 
						|
 | 
						|
    # Reference: https://www.holadevs.com/pregunta/64750/change-selected-tab-color-in-ttknotebook
 | 
						|
    style = _tkinter_ttk.Style()
 | 
						|
    settings = {"TNotebook.Tab": {"configure": {"padding": [5, 1], "background": "#fdd57e"}, "map": {"background": [("selected", "#C70039"), ("active", "#fc9292")], "foreground": [("selected", "#ffffff"), ("active", "#000000")]}}}
 | 
						|
    style.theme_create("custom", parent="alt", settings=settings)
 | 
						|
    style.theme_use("custom")
 | 
						|
 | 
						|
    # Reference: https://stackoverflow.com/a/10018670
 | 
						|
    def center(window):
 | 
						|
        window.update_idletasks()
 | 
						|
        width = window.winfo_width()
 | 
						|
        frm_width = window.winfo_rootx() - window.winfo_x()
 | 
						|
        win_width = width + 2 * frm_width
 | 
						|
        height = window.winfo_height()
 | 
						|
        titlebar_height = window.winfo_rooty() - window.winfo_y()
 | 
						|
        win_height = height + titlebar_height + frm_width
 | 
						|
        x = window.winfo_screenwidth() // 2 - win_width // 2
 | 
						|
        y = window.winfo_screenheight() // 2 - win_height // 2
 | 
						|
        window.geometry('{}x{}+{}+{}'.format(width, height, x, y))
 | 
						|
        window.deiconify()
 | 
						|
 | 
						|
    def onKeyPress(event):
 | 
						|
        global line
 | 
						|
        global queue
 | 
						|
 | 
						|
        if process:
 | 
						|
            if event.char == '\b':
 | 
						|
                line = line[:-1]
 | 
						|
            else:
 | 
						|
                line += event.char
 | 
						|
 | 
						|
    def onReturnPress(event):
 | 
						|
        global line
 | 
						|
        global queue
 | 
						|
 | 
						|
        if process:
 | 
						|
            try:
 | 
						|
                process.stdin.write(("%s\n" % line.strip()).encode())
 | 
						|
                process.stdin.flush()
 | 
						|
            except socket.error:
 | 
						|
                line = ""
 | 
						|
                event.widget.master.master.destroy()
 | 
						|
                return "break"
 | 
						|
            except:
 | 
						|
                return
 | 
						|
 | 
						|
            event.widget.insert(_tkinter.END, "\n")
 | 
						|
 | 
						|
            return "break"
 | 
						|
 | 
						|
    def run():
 | 
						|
        global alive
 | 
						|
        global process
 | 
						|
        global queue
 | 
						|
 | 
						|
        config = {}
 | 
						|
 | 
						|
        for key in window._widgets:
 | 
						|
            dest, type = key
 | 
						|
            widget = window._widgets[key]
 | 
						|
 | 
						|
            if hasattr(widget, "get") and not widget.get():
 | 
						|
                value = None
 | 
						|
            elif type == "string":
 | 
						|
                value = widget.get()
 | 
						|
            elif type == "float":
 | 
						|
                value = float(widget.get())
 | 
						|
            elif type == "int":
 | 
						|
                value = int(widget.get())
 | 
						|
            else:
 | 
						|
                value = bool(widget.var.get())
 | 
						|
 | 
						|
            config[dest] = value
 | 
						|
 | 
						|
        for option in parser.option_list:
 | 
						|
            config[option.dest] = defaults.get(option.dest, None)
 | 
						|
 | 
						|
        handle, configFile = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.CONFIG, text=True)
 | 
						|
        os.close(handle)
 | 
						|
 | 
						|
        saveConfig(config, configFile)
 | 
						|
 | 
						|
        def enqueue(stream, queue):
 | 
						|
            global alive
 | 
						|
 | 
						|
            for line in iter(stream.readline, b''):
 | 
						|
                queue.put(line)
 | 
						|
 | 
						|
            alive = False
 | 
						|
            stream.close()
 | 
						|
 | 
						|
        alive = True
 | 
						|
 | 
						|
        process = subprocess.Popen([sys.executable or "python", os.path.join(paths.SQLMAP_ROOT_PATH, "sqlmap.py"), "-c", configFile], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, bufsize=1, close_fds=not IS_WIN)
 | 
						|
 | 
						|
        # Reference: https://stackoverflow.com/a/4896288
 | 
						|
        queue = _queue.Queue()
 | 
						|
        thread = threading.Thread(target=enqueue, args=(process.stdout, queue))
 | 
						|
        thread.daemon = True
 | 
						|
        thread.start()
 | 
						|
 | 
						|
        top = _tkinter.Toplevel()
 | 
						|
        top.title("Console")
 | 
						|
 | 
						|
        # Reference: https://stackoverflow.com/a/13833338
 | 
						|
        text = _tkinter_scrolledtext.ScrolledText(top, undo=True)
 | 
						|
        text.bind("<Key>", onKeyPress)
 | 
						|
        text.bind("<Return>", onReturnPress)
 | 
						|
        text.pack()
 | 
						|
        text.focus()
 | 
						|
 | 
						|
        center(top)
 | 
						|
 | 
						|
        while True:
 | 
						|
            line = ""
 | 
						|
            try:
 | 
						|
                # line = queue.get_nowait()
 | 
						|
                line = queue.get(timeout=.1)
 | 
						|
                text.insert(_tkinter.END, line)
 | 
						|
            except _queue.Empty:
 | 
						|
                text.see(_tkinter.END)
 | 
						|
                text.update_idletasks()
 | 
						|
 | 
						|
                if not alive:
 | 
						|
                    break
 | 
						|
 | 
						|
    menubar = _tkinter.Menu(window)
 | 
						|
 | 
						|
    filemenu = _tkinter.Menu(menubar, tearoff=0)
 | 
						|
    filemenu.add_command(label="Open", state=_tkinter.DISABLED)
 | 
						|
    filemenu.add_command(label="Save", state=_tkinter.DISABLED)
 | 
						|
    filemenu.add_separator()
 | 
						|
    filemenu.add_command(label="Exit", command=window.quit)
 | 
						|
    menubar.add_cascade(label="File", menu=filemenu)
 | 
						|
 | 
						|
    menubar.add_command(label="Run", command=run)
 | 
						|
 | 
						|
    helpmenu = _tkinter.Menu(menubar, tearoff=0)
 | 
						|
    helpmenu.add_command(label="Official site", command=lambda: webbrowser.open(SITE))
 | 
						|
    helpmenu.add_command(label="Github pages", command=lambda: webbrowser.open(GIT_PAGE))
 | 
						|
    helpmenu.add_command(label="Wiki pages", command=lambda: webbrowser.open(WIKI_PAGE))
 | 
						|
    helpmenu.add_command(label="Report issue", command=lambda: webbrowser.open(ISSUES_PAGE))
 | 
						|
    helpmenu.add_separator()
 | 
						|
    helpmenu.add_command(label="About", command=lambda: _tkinter_messagebox.showinfo("About", "Copyright (c) 2006-2022\n\n    (%s)" % DEV_EMAIL_ADDRESS))
 | 
						|
    menubar.add_cascade(label="Help", menu=helpmenu)
 | 
						|
 | 
						|
    window.config(menu=menubar)
 | 
						|
    window._widgets = {}
 | 
						|
 | 
						|
    notebook = AutoresizableNotebook(window)
 | 
						|
 | 
						|
    first = None
 | 
						|
    frames = {}
 | 
						|
 | 
						|
    for group in parser.option_groups:
 | 
						|
        frame = frames[group.title] = _tkinter.Frame(notebook, width=200, height=200)
 | 
						|
        notebook.add(frames[group.title], text=group.title)
 | 
						|
 | 
						|
        _tkinter.Label(frame).grid(column=0, row=0, sticky=_tkinter.W)
 | 
						|
 | 
						|
        row = 1
 | 
						|
        if group.get_description():
 | 
						|
            _tkinter.Label(frame, text="%s:" % group.get_description()).grid(column=0, row=1, columnspan=3, sticky=_tkinter.W)
 | 
						|
            _tkinter.Label(frame).grid(column=0, row=2, sticky=_tkinter.W)
 | 
						|
            row += 2
 | 
						|
 | 
						|
        for option in group.option_list:
 | 
						|
            _tkinter.Label(frame, text="%s " % parser.formatter._format_option_strings(option)).grid(column=0, row=row, sticky=_tkinter.W)
 | 
						|
 | 
						|
            if option.type == "string":
 | 
						|
                widget = _tkinter.Entry(frame)
 | 
						|
            elif option.type == "float":
 | 
						|
                widget = ConstrainedEntry(frame, regex=r"\A\d*\.?\d*\Z")
 | 
						|
            elif option.type == "int":
 | 
						|
                widget = ConstrainedEntry(frame, regex=r"\A\d*\Z")
 | 
						|
            else:
 | 
						|
                var = _tkinter.IntVar()
 | 
						|
                widget = _tkinter.Checkbutton(frame, variable=var)
 | 
						|
                widget.var = var
 | 
						|
 | 
						|
            first = first or widget
 | 
						|
            widget.grid(column=1, row=row, sticky=_tkinter.W)
 | 
						|
 | 
						|
            window._widgets[(option.dest, option.type)] = widget
 | 
						|
 | 
						|
            default = defaults.get(option.dest)
 | 
						|
            if default:
 | 
						|
                if hasattr(widget, "insert"):
 | 
						|
                    widget.insert(0, default)
 | 
						|
 | 
						|
            _tkinter.Label(frame, text=" %s" % option.help).grid(column=2, row=row, sticky=_tkinter.W)
 | 
						|
 | 
						|
            row += 1
 | 
						|
 | 
						|
        _tkinter.Label(frame).grid(column=0, row=row, sticky=_tkinter.W)
 | 
						|
 | 
						|
    notebook.pack(expand=1, fill="both")
 | 
						|
    notebook.enable_traversal()
 | 
						|
 | 
						|
    first.focus()
 | 
						|
 | 
						|
    window.mainloop()
 |