Merge Stable Changesto Master #9
							
								
								
									
										104
									
								
								plugins/searcher/ipc_server.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								plugins/searcher/ipc_server.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,104 @@
 | 
				
			|||||||
 | 
					# Python imports
 | 
				
			||||||
 | 
					import os, threading, time, pickle
 | 
				
			||||||
 | 
					from multiprocessing.connection import Listener, Client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Lib imports
 | 
				
			||||||
 | 
					import gi
 | 
				
			||||||
 | 
					gi.require_version('Gtk', '3.0')
 | 
				
			||||||
 | 
					from gi.repository import Gtk, GLib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Application imports
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class IPCServer:
 | 
				
			||||||
 | 
					    """ Create a listener so that other SolarFM instances send requests back to existing instance. """
 | 
				
			||||||
 | 
					    def __init__(self, ipc_address: str = '127.0.0.1', conn_type: str = "socket"):
 | 
				
			||||||
 | 
					        self.is_ipc_alive     = False
 | 
				
			||||||
 | 
					        self._ipc_port        = 4848
 | 
				
			||||||
 | 
					        self._ipc_address     = ipc_address
 | 
				
			||||||
 | 
					        self._conn_type       = conn_type
 | 
				
			||||||
 | 
					        self._ipc_authkey     = b'' + bytes(f'solarfm-search_grep-ipc', 'utf-8')
 | 
				
			||||||
 | 
					        self._ipc_timeout     = 15.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if conn_type == "socket":
 | 
				
			||||||
 | 
					            self._ipc_address = f'/tmp/solarfm-search_grep-ipc.sock'
 | 
				
			||||||
 | 
					        elif conn_type == "full_network":
 | 
				
			||||||
 | 
					            self._ipc_address = '0.0.0.0'
 | 
				
			||||||
 | 
					        elif conn_type == "full_network_unsecured":
 | 
				
			||||||
 | 
					            self._ipc_authkey = None
 | 
				
			||||||
 | 
					            self._ipc_address = '0.0.0.0'
 | 
				
			||||||
 | 
					        elif conn_type == "local_network_unsecured":
 | 
				
			||||||
 | 
					            self._ipc_authkey = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @daemon_threaded
 | 
				
			||||||
 | 
					    def create_ipc_listener(self) -> None:
 | 
				
			||||||
 | 
					        if self._conn_type == "socket":
 | 
				
			||||||
 | 
					            if os.path.exists(self._ipc_address):
 | 
				
			||||||
 | 
					                os.unlink(self._ipc_address)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            listener = Listener(address=self._ipc_address, family="AF_UNIX", authkey=self._ipc_authkey)
 | 
				
			||||||
 | 
					        elif "unsecured" not in self._conn_type:
 | 
				
			||||||
 | 
					            listener = Listener((self._ipc_address, self._ipc_port), authkey=self._ipc_authkey)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            listener = Listener((self._ipc_address, self._ipc_port))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.is_ipc_alive = True
 | 
				
			||||||
 | 
					        while True:
 | 
				
			||||||
 | 
					            conn       = listener.accept()
 | 
				
			||||||
 | 
					            start_time = time.perf_counter()
 | 
				
			||||||
 | 
					            self.handle_message(conn, start_time)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        listener.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle_message(self, conn, start_time) -> None:
 | 
				
			||||||
 | 
					        while True:
 | 
				
			||||||
 | 
					            msg  = conn.recv()
 | 
				
			||||||
 | 
					            data = msg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if "SEARCH|" in msg:
 | 
				
			||||||
 | 
					                file = msg.split("SEARCH|")[1].strip()
 | 
				
			||||||
 | 
					                if file:
 | 
				
			||||||
 | 
					                    GLib.idle_add(self._load_file_ui, file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                conn.close()
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if "GREP|" in msg:
 | 
				
			||||||
 | 
					                data = msg.split("GREP|")[1].strip()
 | 
				
			||||||
 | 
					                if data:
 | 
				
			||||||
 | 
					                    GLib.idle_add(self._load_grep_ui, data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                conn.close()
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if msg in ['close connection', 'close server']:
 | 
				
			||||||
 | 
					                conn.close()
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # NOTE: Not perfect but insures we don't lock up the connection for too long.
 | 
				
			||||||
 | 
					            end_time = time.perf_counter()
 | 
				
			||||||
 | 
					            if (end_time - start_time) > self._ipc_timeout:
 | 
				
			||||||
 | 
					                conn.close()
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def send_ipc_message(self, message: str = "Empty Data...") -> None:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            if self._conn_type == "socket":
 | 
				
			||||||
 | 
					                conn = Client(address=self._ipc_address, family="AF_UNIX", authkey=self._ipc_authkey)
 | 
				
			||||||
 | 
					            elif "unsecured" not in self._conn_type:
 | 
				
			||||||
 | 
					                conn = Client((self._ipc_address, self._ipc_port), authkey=self._ipc_authkey)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                conn = Client((self._ipc_address, self._ipc_port))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            conn.send(message)
 | 
				
			||||||
 | 
					            conn.close()
 | 
				
			||||||
 | 
					        except ConnectionRefusedError as e:
 | 
				
			||||||
 | 
					            print("Connection refused...")
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            print(repr(e))
 | 
				
			||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
# Python imports
 | 
					# Python imports
 | 
				
			||||||
import os, threading, subprocess, inspect, time, json, base64, shlex, select, signal, pickle
 | 
					import os, threading, subprocess, inspect, time, json, base64, shlex, select, signal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Lib imports
 | 
					# Lib imports
 | 
				
			||||||
import gi
 | 
					import gi
 | 
				
			||||||
@@ -8,7 +8,7 @@ from gi.repository import Gtk, GLib
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Application imports
 | 
					# Application imports
 | 
				
			||||||
from plugins.plugin_base import PluginBase
 | 
					from plugins.plugin_base import PluginBase
 | 
				
			||||||
 | 
					from .ipc_server import IPCServer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -74,7 +74,7 @@ class GrepPreviewWidget(Gtk.Box):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pause_fifo_update = False
 | 
					pause_fifo_update = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Plugin(PluginBase):
 | 
					class Plugin(IPCServer, PluginBase):
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
        super().__init__()
 | 
					        super().__init__()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -83,9 +83,6 @@ class Plugin(PluginBase):
 | 
				
			|||||||
                                           #       where self.name should not be needed for message comms
 | 
					                                           #       where self.name should not be needed for message comms
 | 
				
			||||||
        self._GLADE_FILE       = f"{self.path}/search_dialog.glade"
 | 
					        self._GLADE_FILE       = f"{self.path}/search_dialog.glade"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._files_fifo_file  = f"/tmp/search_files_fifo"
 | 
					 | 
				
			||||||
        self._grep_fifo_file   = f"/tmp/grep_files_fifo"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self._search_dialog    = None
 | 
					        self._search_dialog    = None
 | 
				
			||||||
        self._active_path      = None
 | 
					        self._active_path      = None
 | 
				
			||||||
        self._file_list        = None
 | 
					        self._file_list        = None
 | 
				
			||||||
@@ -123,30 +120,7 @@ class Plugin(PluginBase):
 | 
				
			|||||||
        self._event_system.subscribe("update-file-ui", self._load_file_ui)
 | 
					        self._event_system.subscribe("update-file-ui", self._load_file_ui)
 | 
				
			||||||
        self._event_system.subscribe("update-grep-ui", self._load_grep_ui)
 | 
					        self._event_system.subscribe("update-grep-ui", self._load_grep_ui)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not os.path.exists(self._files_fifo_file):
 | 
					        self.create_ipc_listener()
 | 
				
			||||||
            os.mkfifo(self._files_fifo_file, 0o777)
 | 
					 | 
				
			||||||
        if not os.path.exists(self._grep_fifo_file):
 | 
					 | 
				
			||||||
            os.mkfifo(self._grep_fifo_file, 0o777)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.run_files_fifo_thread()
 | 
					 | 
				
			||||||
        self.run_grep_fifo_thread()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @daemon_threaded
 | 
					 | 
				
			||||||
    def run_files_fifo_thread(self):
 | 
					 | 
				
			||||||
        with open(self._files_fifo_file) as fifo:
 | 
					 | 
				
			||||||
            while True:
 | 
					 | 
				
			||||||
                select.select([fifo],[],[fifo])
 | 
					 | 
				
			||||||
                data = fifo.read()
 | 
					 | 
				
			||||||
                GLib.idle_add(self._load_file_ui, data)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @daemon_threaded
 | 
					 | 
				
			||||||
    def run_grep_fifo_thread(self):
 | 
					 | 
				
			||||||
        with open(self._grep_fifo_file) as fifo:
 | 
					 | 
				
			||||||
            while True:
 | 
					 | 
				
			||||||
                select.select([fifo],[],[fifo])
 | 
					 | 
				
			||||||
                data = fifo.read()
 | 
					 | 
				
			||||||
                GLib.idle_add(self._load_grep_ui, data)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _show_grep_list_page(self, widget=None, eve=None):
 | 
					    def _show_grep_list_page(self, widget=None, eve=None):
 | 
				
			||||||
@@ -166,9 +140,7 @@ class Plugin(PluginBase):
 | 
				
			|||||||
        query = widget.get_text()
 | 
					        query = widget.get_text()
 | 
				
			||||||
        if not query in ("", None):
 | 
					        if not query in ("", None):
 | 
				
			||||||
            target_dir = shlex.quote( self._fm_state.tab.get_current_directory() )
 | 
					            target_dir = shlex.quote( self._fm_state.tab.get_current_directory() )
 | 
				
			||||||
            # command = [f"{self.path}/search.sh", "-t", "file_search", "-d", f"{target_dir}", "-q", f"{query}"]
 | 
					 | 
				
			||||||
            command = ["python", f"{self.path}/search.py", "-t", "file_search", "-d", f"{target_dir}", "-q", f"{query}"]
 | 
					            command = ["python", f"{self.path}/search.py", "-t", "file_search", "-d", f"{target_dir}", "-q", f"{query}"]
 | 
				
			||||||
 | 
					 | 
				
			||||||
            process = subprocess.Popen(command, cwd=self.path, stdin=None, stdout=None, stderr=None)
 | 
					            process = subprocess.Popen(command, cwd=self.path, stdin=None, stdout=None, stderr=None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _stop_find_file_query(self, widget=None, eve=None):
 | 
					    def _stop_find_file_query(self, widget=None, eve=None):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Python imports
 | 
					# Python imports
 | 
				
			||||||
import os, traceback, argparse, time, json, base64
 | 
					import os, traceback, argparse, json, base64
 | 
				
			||||||
from setproctitle import setproctitle
 | 
					from setproctitle import setproctitle
 | 
				
			||||||
 | 
					from multiprocessing.connection import Client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Lib imports
 | 
					# Lib imports
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -11,8 +12,9 @@ from setproctitle import setproctitle
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_files_fifo_file  = f"/tmp/search_files_fifo"
 | 
					
 | 
				
			||||||
_grep_fifo_file   = f"/tmp/grep_files_fifo"
 | 
					_ipc_address = f'/tmp/solarfm-search_grep-ipc.sock'
 | 
				
			||||||
 | 
					_ipc_authkey = b'' + bytes(f'solarfm-search_grep-ipc', 'utf-8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
filter = (".mkv", ".mp4", ".webm", ".avi", ".mov", ".m4v", ".mpg", ".mpeg", ".wmv", ".flv") + \
 | 
					filter = (".mkv", ".mp4", ".webm", ".avi", ".mov", ".m4v", ".mpg", ".mpeg", ".wmv", ".flv") + \
 | 
				
			||||||
            (".png", ".jpg", ".jpeg", ".gif", ".ico", ".tga", ".webp") + \
 | 
					            (".png", ".jpg", ".jpeg", ".gif", ".ico", ".tga", ".webp") + \
 | 
				
			||||||
@@ -21,24 +23,33 @@ filter = (".mkv", ".mp4", ".webm", ".avi", ".mov", ".m4v", ".mpg", ".mpeg", ".wm
 | 
				
			|||||||
file_result_set = []
 | 
					file_result_set = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def file_search(fifo, path, query):
 | 
					def send_ipc_message(message) -> None:
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        conn = Client(address=_ipc_address, family="AF_UNIX", authkey=_ipc_authkey)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        conn.send(message)
 | 
				
			||||||
 | 
					        conn.close()
 | 
				
			||||||
 | 
					    except ConnectionRefusedError as e:
 | 
				
			||||||
 | 
					        print("Connection refused...")
 | 
				
			||||||
 | 
					    except Exception as e:
 | 
				
			||||||
 | 
					        print(repr(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def file_search(path, query):
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        for file in os.listdir(path):
 | 
					        for file in os.listdir(path):
 | 
				
			||||||
            target = os.path.join(path, file)
 | 
					            target = os.path.join(path, file)
 | 
				
			||||||
            if os.path.isdir(target):
 | 
					            if os.path.isdir(target):
 | 
				
			||||||
                file_search(fifo, target, query)
 | 
					                file_search(target, query)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                if query.lower() in file.lower():
 | 
					                if query.lower() in file.lower():
 | 
				
			||||||
                    # file_result_set.append([target, file])
 | 
					                    data = f"SEARCH|{json.dumps([target, file])}"
 | 
				
			||||||
                    data = json.dumps([target, file])
 | 
					                    send_ipc_message(data)
 | 
				
			||||||
                    fifo.write(data)
 | 
					 | 
				
			||||||
                    time.sleep(0.01)
 | 
					 | 
				
			||||||
    except Exception as e:
 | 
					    except Exception as e:
 | 
				
			||||||
        print("Couldn't traverse to path. Might be permissions related...")
 | 
					        print("Couldn't traverse to path. Might be permissions related...")
 | 
				
			||||||
        traceback.print_exc()
 | 
					        traceback.print_exc()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _search_for_string(file, query):
 | 
					def _search_for_string(file, query):
 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
    b64_file = base64.urlsafe_b64encode(file.encode('utf-8')).decode('utf-8')
 | 
					    b64_file = base64.urlsafe_b64encode(file.encode('utf-8')).decode('utf-8')
 | 
				
			||||||
    grep_result_set = {}
 | 
					    grep_result_set = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -53,14 +64,8 @@ def _search_for_string(file, query):
 | 
				
			|||||||
                    grep_result_set[f"{b64_file}"] = {}
 | 
					                    grep_result_set[f"{b64_file}"] = {}
 | 
				
			||||||
                    grep_result_set[f"{b64_file}"] = {f"{i+1}": b64_line}
 | 
					                    grep_result_set[f"{b64_file}"] = {f"{i+1}": b64_line}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # NOTE: Push to fifo here after loop
 | 
					        data = f"GREP|{json.dumps(grep_result_set)}"
 | 
				
			||||||
        with open(_grep_fifo_file, 'w') as fifo:
 | 
					        send_ipc_message(data)
 | 
				
			||||||
            data = json.dumps(grep_result_set)
 | 
					 | 
				
			||||||
            fifo.write(data)
 | 
					 | 
				
			||||||
            time.sleep(0.05)
 | 
					 | 
				
			||||||
    except Exception as e:
 | 
					 | 
				
			||||||
        print("Couldn't read file. Might be binary or other cause...")
 | 
					 | 
				
			||||||
        traceback.print_exc()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def grep_search(path, query):
 | 
					def grep_search(path, query):
 | 
				
			||||||
@@ -78,8 +83,7 @@ def grep_search(path, query):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def search(args):
 | 
					def search(args):
 | 
				
			||||||
    if args.type == "file_search":
 | 
					    if args.type == "file_search":
 | 
				
			||||||
       with open(_files_fifo_file, 'w') as fifo:
 | 
					        file_search(args.dir, args.query)
 | 
				
			||||||
           file_search(fifo, args.dir, args.query)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if args.type == "grep_search":
 | 
					    if args.type == "grep_search":
 | 
				
			||||||
        grep_search(args.dir, args.query)
 | 
					        grep_search(args.dir, args.query)
 | 
				
			||||||
@@ -98,6 +102,5 @@ if __name__ == "__main__":
 | 
				
			|||||||
        # Read arguments (If any...)
 | 
					        # Read arguments (If any...)
 | 
				
			||||||
        args = parser.parse_args()
 | 
					        args = parser.parse_args()
 | 
				
			||||||
        search(args)
 | 
					        search(args)
 | 
				
			||||||
 | 
					 | 
				
			||||||
    except Exception as e:
 | 
					    except Exception as e:
 | 
				
			||||||
        traceback.print_exc()
 | 
					        traceback.print_exc()
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user