Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ Depends: ${misc:Depends},
gir1.2-glib-2.0,
gir1.2-gtk-3.0,
gir1.2-notify-0.7,
gir1.2-pango-1.0
gir1.2-pango-1.0,
python3-paramiko
Recommends: gvfs-fuse,
libglib2.0-bin
Description: My Computer, shows general information about your computer.
Expand Down
1 change: 1 addition & 0 deletions po/files
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
ui/MainWindow.glade
src/MainWindow.py
src/UserSettings.py
src/Scansftp.py
12 changes: 12 additions & 0 deletions po/tr.po
Original file line number Diff line number Diff line change
Expand Up @@ -512,3 +512,15 @@ msgstr "# not: görünmesini sağlamak için kare işareti kaldırın"

#~ msgid "Website"
#~ msgstr "Website"

#: ui/MainWindow.glade:2248
msgid "Find the servers connected to the network:"
msgstr "Ağa bağlı sunucuları bulun:"

#: ui/MainWindow.glade:2248
msgid "Scanning the SFTP servers on the network..."
msgstr "Ağdaki SFTP sunucuları taranıyor..."

#: ui/MainWindow.glade:2344
msgid "Scan"
msgstr "Tara"
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def create_mo_files():
"src/DiskManager.py",
"src/Unmount.py",
"src/UserSettings.py",
"src/Scansftp.py",
"src/__version__"
]),
("/usr/share/pardus/pardus-mycomputer/ui",
Expand Down
56 changes: 56 additions & 0 deletions src/MainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

from UserSettings import UserSettings

import threading
import Scansftp # sftp scan function library

import locale
from locale import gettext as _

Expand Down Expand Up @@ -213,6 +216,10 @@ def UI(str):
self.box_user_domain_pass = UI("box_user_domain_pass")
self.box_anonym = UI("box_anonym")
self.btn_mount_connect = UI("btn_mount_connect")
self.btn_sftp_scan = UI("btn_sftp_scan") # sftp scan button
self.sftp_listbox = UI("sftp_listbox") # sftp list box
self.sftp_stack = UI("sftp_stack") # sftp stack panel
self.scrolledwindow = UI("scrolledwindow")
self.mount_password_options = UI("mount_password_options")
self.mount_anonym_options = UI("mount_anonym_options")
self.popover_connect = UI("popover_connect")
Expand Down Expand Up @@ -2103,6 +2110,55 @@ def remove_from_recent_clicked(self, button):

self.UserSettings.removeRecentServer(button.name)



# sftp scan function
def on_sftp_scan(self, button):
self.sftp_stack.set_visible_child_name('page1')
self.btn_sftp_scan.set_sensitive(False)
# Start background thread
threading.Thread(target=self.scan_process, daemon=True).start()

def scan_process(self):
try:
netaddress = Scansftp.get_local_network()
scanned_devices = Scansftp.scan_devices(netaddress)
except Exception as e:
return
GLib.idle_add(self.sftp_listboxadd, scanned_devices)

def sftp_listboxadd(self, scanned_devices):
# Update the list
self.sftp_listbox.foreach(lambda w: self.sftp_listbox.remove(w))
self.sftp_listbox.set_hexpand(True)
self.sftp_listbox.set_vexpand(True)
for d in scanned_devices:
row = self.make_sftp_listbox_button(d, on_clicked=self.server_entry_settext)
self.sftp_listbox.add(row)

self.sftp_stack.set_visible_child_name('page0')
self.sftp_listbox.show_all()
self.btn_sftp_scan.set_sensitive(True)

def make_sftp_listbox_button(self, label_text, on_clicked=None):
# Create row
row = Gtk.ListBoxRow()

# Create a button. You can edit it using align/halign
btn = Gtk.Button(label=label_text)
btn.set_hexpand(True)
btn.set_halign(Gtk.Align.FILL)

if on_clicked is not None:
btn.connect("clicked", on_clicked)
row.add(btn)
return row

def server_entry_settext(self, button):
ip = button.get_label().strip()
self.entry_addr.set_text("sftp://"+ip)


def on_btn_mount_connect_clicked(self, button, from_saved=False, saved_uri="", from_places=False):
def get_uri_name(source_object):
try:
Expand Down
102 changes: 102 additions & 0 deletions src/Scansftp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import subprocess
import socket
import ipaddress
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import paramiko
import netifaces

# a function that retrieves the network address of the connected interface
def get_local_network():
# Find the interface used by the default gateway
gateway_info = netifaces.gateways()
interface = gateway_info['default'][netifaces.AF_INET][1]

# Interface IP and netmask information
addr_info = netifaces.ifaddresses(interface)[netifaces.AF_INET][0]

ip_addr = addr_info['addr']
netmask = addr_info['netmask']

# Create a network address
network = ipaddress.IPv4Network(f"{ip_addr}/{netmask}", strict=False)

return str(network)


def get_ip_neigh():
ips = set()
try:
out = subprocess.check_output(["ip", "neigh"]).decode()
for line in out.splitlines():
parts = line.split()
if len(parts) > 0:
ip = parts[0]
if ip.count(".") == 3: # IPv4 basic filter
ips.add(ip)
except Exception as e:
print("ip neigh error:", e)

return ips


def check_ssh_sftp(host, port=22, timeout=3):
# Checking if the SSH port is open
try:
sock = socket.create_connection((host, port), timeout=timeout)
sock.close()
except (socket.timeout, ConnectionRefusedError, OSError):
return False

# Sending a fake credential results in an AuthenticationException → This means SFTP exists
transport = paramiko.Transport((host, port))
transport.banner_timeout = timeout

try:
transport.connect(
username='__probe__',
password='__probe__'
)
return True

except paramiko.AuthenticationException:
return True # an authentication error means the SFTP service is active

except paramiko.SSHException:
return False # SSH handshake failed

except Exception:
return False

# scan devices
def scan_devices(network, max_threads=30, delay=0.02):
net = ipaddress.ip_network(network, strict=False)
results = []

def worker(ip):
ip = str(ip)
if check_ssh_sftp(ip): # this address is being checked to see if it is an SSH server
return ip
return None

with ThreadPoolExecutor(max_workers=max_threads) as executor:
futures = []

for ip in net.hosts():
futures.append(executor.submit(worker, ip))
time.sleep(delay)

for f in as_completed(futures):
res = f.result()
if res:
results.append(res)

print(results)
return results


#netaddress = get_local_network()
#hosts = scan(netaddress)
#for h in hosts:
# print(h)

138 changes: 138 additions & 0 deletions ui/MainWindow.glade
Original file line number Diff line number Diff line change
Expand Up @@ -2223,6 +2223,144 @@ Fatih Altun &lt;[email protected]&gt;</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkBox" id="sftp_scanner_box">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-top">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-bottom">13</property>
<property name="label" translatable="yes">Find the servers connected to the network:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkStack" id="sftp_stack">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkBox" id="page0">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkScrolledWindow" id="scrolled_window">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="margin-bottom">3</property>
<property name="shadow-type">in</property>
<property name="propagate-natural-width">True</property>
<property name="propagate-natural-height">True</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkListBox" id="sftp_listbox">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="name">page0</property>
<property name="title" translatable="yes">page0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="page1">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkSpinner">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="active">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Scanning the SFTP servers on the network...</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="name">page1</property>
<property name="title" translatable="yes">page1</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btn_sftp_scan">
<property name="label" translatable="yes">Scan</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="margin-top">16</property>
<signal name="clicked" handler="on_sftp_scan" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
Expand Down