添加了账号的设置
This commit is contained in:
parent
699cb26587
commit
db336184c3
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -552,6 +552,7 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
|||||||
name = "ftphack"
|
name = "ftphack"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
"gtk",
|
"gtk",
|
||||||
"libunftp",
|
"libunftp",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -8,3 +8,4 @@ gtk = "0.18.2"
|
|||||||
libunftp = "0.21.0"
|
libunftp = "0.21.0"
|
||||||
tokio = { version = "1.47.1", features = ["rt-multi-thread"] }
|
tokio = { version = "1.47.1", features = ["rt-multi-thread"] }
|
||||||
unftp-sbe-fs = "0.3.0"
|
unftp-sbe-fs = "0.3.0"
|
||||||
|
async-trait = "0.1.50"
|
||||||
|
@ -28,6 +28,8 @@ fn main() {
|
|||||||
let ip = ui_clone.ip_entry.text();
|
let ip = ui_clone.ip_entry.text();
|
||||||
let port: u16 = ui_clone.port_entry.text().parse().unwrap_or(2121);
|
let port: u16 = ui_clone.port_entry.text().parse().unwrap_or(2121);
|
||||||
let dir = ui_clone.dir_entry.text();
|
let dir = ui_clone.dir_entry.text();
|
||||||
|
let username = ui_clone.username_entry.text();
|
||||||
|
let password = ui_clone.password_entry.text();
|
||||||
|
|
||||||
// Validate directory
|
// Validate directory
|
||||||
let dir_path = PathBuf::from(&dir);
|
let dir_path = PathBuf::from(&dir);
|
||||||
@ -40,7 +42,7 @@ fn main() {
|
|||||||
let addr: SocketAddr = format!("{}:{}", ip, port).parse().unwrap();
|
let addr: SocketAddr = format!("{}:{}", ip, port).parse().unwrap();
|
||||||
|
|
||||||
// Create and start server
|
// Create and start server
|
||||||
match server::FtpServer::new(addr, dir_path) {
|
match server::FtpServer::new(addr, dir_path, username.to_string(), password.to_string()) {
|
||||||
Ok(mut srv) => {
|
Ok(mut srv) => {
|
||||||
// First start the server (initialize it)
|
// First start the server (initialize it)
|
||||||
if let Err(e) = srv.start() {
|
if let Err(e) = srv.start() {
|
||||||
|
@ -2,18 +2,39 @@ use std::net::SocketAddr;
|
|||||||
use libunftp::{Server, ServerBuilder};
|
use libunftp::{Server, ServerBuilder};
|
||||||
use unftp_sbe_fs::Filesystem;
|
use unftp_sbe_fs::Filesystem;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use libunftp::auth::{AnonymousAuthenticator, DefaultUser};
|
use libunftp::auth::{DefaultUser, Authenticator, Credentials, AuthenticationError};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
pub struct FtpServer {
|
pub struct FtpServer {
|
||||||
server: Option<Server<Filesystem, DefaultUser>>,
|
server: Option<Server<Filesystem, DefaultUser>>,
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
root_dir: std::path::PathBuf,
|
root_dir: std::path::PathBuf,
|
||||||
shutdown_flag: Arc<AtomicBool>,
|
shutdown_flag: Arc<AtomicBool>,
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct CustomAuthenticator {
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Authenticator<DefaultUser> for CustomAuthenticator {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
async fn authenticate(&self, username: &str, creds: &Credentials) -> Result<DefaultUser, AuthenticationError> {
|
||||||
|
if username == self.username && creds.password.as_ref().map_or(false, |p| p == &self.password) {
|
||||||
|
Ok(DefaultUser {})
|
||||||
|
} else {
|
||||||
|
Err(AuthenticationError::BadPassword)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FtpServer {
|
impl FtpServer {
|
||||||
pub fn new(addr: SocketAddr, root_dir: std::path::PathBuf) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
|
pub fn new(addr: SocketAddr, root_dir: std::path::PathBuf, username: String, password: String) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
if !root_dir.exists() {
|
if !root_dir.exists() {
|
||||||
return Err(format!("Directory does not exist: {:?}", root_dir).into());
|
return Err(format!("Directory does not exist: {:?}", root_dir).into());
|
||||||
}
|
}
|
||||||
@ -22,15 +43,21 @@ impl FtpServer {
|
|||||||
addr,
|
addr,
|
||||||
root_dir,
|
root_dir,
|
||||||
shutdown_flag: Arc::new(AtomicBool::new(false)),
|
shutdown_flag: Arc::new(AtomicBool::new(false)),
|
||||||
|
username,
|
||||||
|
password,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
pub fn start(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let root_dir = self.root_dir.clone();
|
let root_dir = self.root_dir.clone();
|
||||||
|
let username = self.username.clone();
|
||||||
|
let password = self.password.clone();
|
||||||
|
let authenticator = CustomAuthenticator { username, password };
|
||||||
|
|
||||||
let server = ServerBuilder::new(Box::new(move || -> Filesystem { Filesystem::new(&root_dir).unwrap() }))
|
let server = ServerBuilder::new(Box::new(move || -> Filesystem { Filesystem::new(&root_dir).unwrap() }))
|
||||||
.greeting("Welcome to FTP server")
|
.greeting("Welcome to FTP server")
|
||||||
.passive_ports(50000..=60000)
|
.passive_ports(50000..=60000)
|
||||||
.authenticator(Arc::new(AnonymousAuthenticator))
|
.authenticator(Arc::new(authenticator))
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ pub struct FtpUi {
|
|||||||
pub port_entry: gtk::Entry,
|
pub port_entry: gtk::Entry,
|
||||||
pub dir_entry: gtk::Entry,
|
pub dir_entry: gtk::Entry,
|
||||||
pub dir_button: gtk::Button,
|
pub dir_button: gtk::Button,
|
||||||
|
pub username_entry: gtk::Entry,
|
||||||
|
pub password_entry: gtk::Entry,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FtpUi {
|
impl FtpUi {
|
||||||
@ -55,6 +57,19 @@ impl FtpUi {
|
|||||||
.build();
|
.build();
|
||||||
let dir_button = gtk::Button::with_label("浏览");
|
let dir_button = gtk::Button::with_label("浏览");
|
||||||
|
|
||||||
|
// Username
|
||||||
|
let username_label = gtk::Label::new(Some("用户名:"));
|
||||||
|
let username_entry = gtk::Entry::builder()
|
||||||
|
.text("admin")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Password
|
||||||
|
let password_label = gtk::Label::new(Some("密码:"));
|
||||||
|
let password_entry = gtk::Entry::builder()
|
||||||
|
.text("password")
|
||||||
|
.visibility(false) // Hide password input
|
||||||
|
.build();
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
let status_label = gtk::Label::new(Some("Status: Stopped"));
|
let status_label = gtk::Label::new(Some("Status: Stopped"));
|
||||||
|
|
||||||
@ -74,10 +89,16 @@ impl FtpUi {
|
|||||||
grid.attach(&dir_entry, 1, 2, 1, 1);
|
grid.attach(&dir_entry, 1, 2, 1, 1);
|
||||||
grid.attach(&dir_button, 2, 2, 1, 1);
|
grid.attach(&dir_button, 2, 2, 1, 1);
|
||||||
|
|
||||||
grid.attach(&status_label, 0, 3, 3, 1);
|
grid.attach(&username_label, 0, 3, 1, 1);
|
||||||
|
grid.attach(&username_entry, 1, 3, 1, 1);
|
||||||
|
|
||||||
grid.attach(&start_button, 0, 4, 1, 1);
|
grid.attach(&password_label, 0, 4, 1, 1);
|
||||||
grid.attach(&stop_button, 1, 4, 1, 1);
|
grid.attach(&password_entry, 1, 4, 1, 1);
|
||||||
|
|
||||||
|
grid.attach(&status_label, 0, 5, 3, 1);
|
||||||
|
|
||||||
|
grid.attach(&start_button, 0, 6, 1, 1);
|
||||||
|
grid.attach(&stop_button, 1, 6, 1, 1);
|
||||||
|
|
||||||
window.add(&grid);
|
window.add(&grid);
|
||||||
|
|
||||||
@ -90,6 +111,8 @@ impl FtpUi {
|
|||||||
port_entry,
|
port_entry,
|
||||||
dir_entry,
|
dir_entry,
|
||||||
dir_button,
|
dir_button,
|
||||||
|
username_entry,
|
||||||
|
password_entry,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user