downloading, kinda

pull/6/head
dvkt 5 years ago
parent ce0ef445b6
commit 9e4570fe78

@ -110,6 +110,43 @@ pub fn fetch(host: &str, port: &str, selector: &str) -> io::Result<String> {
})
}
// Downloads a binary to disk and returns the path it was saved to.
pub fn download_url(url: &str) -> io::Result<String> {
let (_, host, port, sel) = parse_url(url);
let sel = sel.replace('?', "\t"); // search queries
let filename = "./tmp-download".to_string();
let path = std::path::Path::new("./tmp-download");
format!("{}:{}", host, port)
.to_socket_addrs()
.and_then(|mut socks| {
socks
.next()
.ok_or_else(|| io_error("Can't create socket".to_string()))
.and_then(|sock| {
TcpStream::connect_timeout(&sock, TCP_TIMEOUT_DURATION)
.and_then(|mut stream| {
stream.write(format!("{}\r\n", sel).as_ref());
Ok(stream)
})
.and_then(|mut stream| {
stream.set_read_timeout(Some(TCP_TIMEOUT_DURATION));
std::fs::OpenOptions::new()
.write(true)
.create(true)
.open(path)
.and_then(|mut file| {
let mut buf = [0; 1024];
while let Ok(()) = stream.read_exact(&mut buf) {
file.write_all(&buf);
}
Ok(filename)
})
})
})
})
}
// url parsing states
enum Parsing {
Host,

@ -128,12 +128,64 @@ impl UI {
})
}
fn download(&mut self, url: &str) -> io::Result<Page> {
// request thread
let download_url = url.to_string();
let req = thread::spawn(move || match gopher::download_url(&download_url) {
Ok(res) => Ok(res),
Err(e) => Err(e),
});
// spinner thead
let download_url = url.to_string();
let (spintx, spinrx) = mpsc::channel();
thread::spawn(move || loop {
for i in 0..=3 {
if spinrx.try_recv().is_ok() {
return;
}
print!(
"\r{}Downloading {}{}{}{}",
termion::cursor::Hide,
color::Fg(color::LightBlack),
download_url,
".".repeat(i),
termion::clear::AfterCursor
);
stdout().flush();
thread::sleep(Duration::from_millis(350));
}
});
let work = req.join();
spintx.send(true); // stop spinner
self.dirty = true;
let res = match work {
Ok(opt) => match opt {
Ok(body) => body,
Err(e) => return Err(e),
},
Err(_) => return Err(io_error("Connection error".into())),
};
Ok(Box::new(Text::from(
url.into(),
format!("Download complete! {}", res),
)))
}
fn fetch(&mut self, url: &str) -> io::Result<Page> {
// on-line help
if url.starts_with("gopher://help/") {
return self.fetch_help(url);
}
// binary downloads
let (typ, _, _, _) = gopher::parse_url(url);
if typ.is_download() {
return self.download(url);
}
// request thread
let thread_url = url.to_string();
let req = thread::spawn(move || match gopher::fetch_url(&thread_url) {
@ -170,8 +222,6 @@ impl UI {
},
Err(_) => return Err(io_error("Connection error".into())),
};
let (typ, _, _, _) = gopher::parse_url(url);
match typ {
Type::Menu | Type::Search => Ok(Box::new(Menu::from(url.to_string(), res))),
Type::Text | Type::HTML => Ok(Box::new(Text::from(url.to_string(), res))),

Loading…
Cancel
Save