diff --git a/src/gopher.rs b/src/gopher.rs index d81d30c..9c85418 100644 --- a/src/gopher.rs +++ b/src/gopher.rs @@ -41,15 +41,15 @@ pub const TCP_TIMEOUT_IN_SECS: u64 = 8; pub const TCP_TIMEOUT_DURATION: Duration = Duration::from_secs(TCP_TIMEOUT_IN_SECS); /// Fetches a gopher URL and returns a raw Gopher response. -pub fn fetch_url(url: &str) -> Result { +pub fn fetch_url(url: &str, try_tls: bool) -> Result { let (_, host, port, sel) = parse_url(url); - fetch(host, port, sel) + fetch(host, port, sel, try_tls) } /// Fetches a gopher URL by its component parts and returns a raw /// Gopher response. -pub fn fetch(host: &str, port: &str, selector: &str) -> Result { - let mut stream = request(host, port, selector)?; +pub fn fetch(host: &str, port: &str, selector: &str, try_tls: bool) -> Result { + let mut stream = request(host, port, selector, try_tls)?; let mut body = String::new(); stream.read_to_string(&mut body)?; Ok(body) @@ -57,7 +57,7 @@ pub fn fetch(host: &str, port: &str, selector: &str) -> Result { /// Downloads a binary to disk. Allows canceling with Ctrl-c. /// Returns the path it was saved to and the size in bytes. -pub fn download_url(url: &str) -> Result<(String, usize)> { +pub fn download_url(url: &str, try_tls: bool) -> Result<(String, usize)> { let (_, host, port, sel) = parse_url(url); let filename = sel .split_terminator('/') @@ -69,7 +69,7 @@ pub fn download_url(url: &str) -> Result<(String, usize)> { let stdin = termion::async_stdin(); let mut keys = stdin.keys(); - let mut stream = request(host, port, sel)?; + let mut stream = request(host, port, sel, try_tls)?; let mut file = std::fs::OpenOptions::new() .write(true) .create(true) @@ -95,21 +95,23 @@ pub fn download_url(url: &str) -> Result<(String, usize)> { /// Make a Gopher request and return a TcpStream ready to be read()'d. /// Will attempt a TLS connection first, then retry a regular /// connection if it fails. -pub fn request(host: &str, port: &str, selector: &str) -> Result { +pub fn request(host: &str, port: &str, selector: &str, try_tls: bool) -> Result { let selector = selector.replace('?', "\t"); // search queries let sock = format!("{}:{}", host, port) .to_socket_addrs() .and_then(|mut socks| socks.next().ok_or_else(|| error!("Can't create socket")))?; // attempt tls connection - if let Ok(connector) = TlsConnector::new() { - let stream = TcpStream::connect_timeout(&sock, TCP_TIMEOUT_DURATION)?; - stream.set_read_timeout(Some(TCP_TIMEOUT_DURATION))?; - if let Ok(mut stream) = connector.connect(host, stream) { - stream.write(format!("{}\r\n", selector).as_ref())?; - return Ok(Stream { - io: Box::new(stream), - }); + if try_tls { + if let Ok(connector) = TlsConnector::new() { + let stream = TcpStream::connect_timeout(&sock, TCP_TIMEOUT_DURATION)?; + stream.set_read_timeout(Some(TCP_TIMEOUT_DURATION))?; + if let Ok(mut stream) = connector.connect(host, stream) { + stream.write(format!("{}\r\n", selector).as_ref())?; + return Ok(Stream { + io: Box::new(stream), + }); + } } } diff --git a/src/main.rs b/src/main.rs index 52bd4ba..74f9d3c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ fn main() { fn run() -> i32 { let args: Vec = std::env::args().collect(); let mut url = "gopher://phetch/1/home"; + let mut praw = false; let mut tls = false; let mut iter = args.iter(); while let Some(arg) = iter.next() { @@ -22,9 +23,7 @@ fn run() -> i32 { } "-r" | "--raw" | "-raw" => { if args.len() > 2 { - let url = args.get(2).unwrap(); - print_raw(url); - return 0; + praw = true; } else { eprintln!("--raw needs gopher-url"); return 1; @@ -44,7 +43,12 @@ fn run() -> i32 { } } - let mut ui = UI::new(); + if praw { + print_raw(url, tls); + return 0; + } + + let mut ui = UI::new(tls); if let Err(e) = ui.open(url, url).and_then(|_| ui.run()) { eprintln!("{}", e); return 1; @@ -71,8 +75,8 @@ Once you've launched phetch, use `ctrl-h` to view the on-line help." ); } -fn print_raw(url: &str) { - match gopher::fetch_url(url) { +fn print_raw(url: &str, try_tls: bool) { + match gopher::fetch_url(url, try_tls) { Ok(response) => println!("{}", response), Err(e) => { eprintln!("{}", e); diff --git a/src/ui.rs b/src/ui.rs index 2136dcd..dcc819f 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -40,11 +40,12 @@ pub struct UI { running: bool, // main ui loop running? pub size: (usize, usize), // cols, rows status: String, // status message, if any + tls: bool, // tls mode? out: RefCell>>, } impl UI { - pub fn new() -> UI { + pub fn new(tls: bool) -> UI { UI { views: vec![], focused: 0, @@ -52,6 +53,7 @@ impl UI { running: true, size: (0, 0), status: String::new(), + tls, out: RefCell::new(AlternateScreen::from(stdout().into_raw_mode().unwrap())), } } @@ -141,8 +143,9 @@ impl UI { fn download(&mut self, url: &str) -> Result<()> { let url = url.to_string(); + let tls = self.tls; self.spinner(&format!("Downloading {}", url), move || { - gopher::download_url(&url) + gopher::download_url(&url, tls) }) .and_then(|res| res) .and_then(|(path, bytes)| { @@ -166,11 +169,12 @@ impl UI { thread::spawn(move || history::save(&hname, &hurl)); // request thread let thread_url = url.to_string(); + let try_tls = self.tls; // don't spin on first ever request let res = if self.views.is_empty() { - gopher::fetch_url(&thread_url)? + gopher::fetch_url(&thread_url, try_tls)? } else { - self.spinner("", move || gopher::fetch_url(&thread_url))?? + self.spinner("", move || gopher::fetch_url(&thread_url, try_tls))?? }; let (typ, _, _, _) = gopher::parse_url(&url); match typ { @@ -501,7 +505,7 @@ impl UI { impl Default for UI { fn default() -> Self { - UI::new() + UI::new(false) } }