-- Leo's gemini proxy
-- Connecting to typed-hole.org:1965...
-- Connected
-- Sending request
-- Meta line: 20 text/gemini
commit 8e9e2aee5568d6fe79576a7e21862aea738faa8f
Author: Julien Blanchard <julien@sideburns.eu>
Date: Tue Jul 30 18:32:03 2019 +0200
Extract some functionality in modules
diff --git a/src/content.rs b/src/content.rs
new file mode 100644
index 0000000..fc183c3
--- /dev/null
+++ b/src/content.rs
@@ -0,0 +1,35 @@
+use std::io::{Read, Write};
+
+use native_tls::TlsConnector;
+use std::net::TcpStream;
+
+pub fn get_data(url: url::Url) -> Result<String, String> {
+ let host = url.host_str().unwrap();
+ let path = url.path();
+ let urlf = format!("{}:1965", host);
+
+ let mut builder = TlsConnector::builder();
+ builder.danger_accept_invalid_hostnames(true);
+ builder.danger_accept_invalid_certs(true);
+ let connector = builder.build().unwrap();
+
+ let stream = TcpStream::connect(&urlf);
+
+ match stream {
+ Ok(stream) => {
+ let mstream = connector.connect(&host, stream);
+
+ match mstream {
+ Ok(mut stream) => {
+ let url_with_path = format!("{}\r\n", path);
+ stream.write_all(url_with_path.as_bytes()).unwrap();
+ let mut res = vec![];
+ stream.read_to_end(&mut res).unwrap();
+ Ok(String::from_utf8_lossy(&res).to_string())
+ }
+ Err(e) => Err(format!("Could not connect to {}\n{}", urlf, e)),
+ }
+ }
+ Err(e) => Err(format!("Could not connect to {}\n{}", urlf, e)),
+ }
+}
diff --git a/src/header.rs b/src/header.rs
new file mode 100644
index 0000000..f57293c
--- /dev/null
+++ b/src/header.rs
@@ -0,0 +1,37 @@
+extern crate regex;
+use regex::Regex;
+
+use std::str::FromStr;
+
+#[derive(Debug)]
+pub struct Header {
+ code: i16,
+ meta: String,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct ParseError;
+
+const HEADER_REGEX: &str = r"^(\d{1,3})[ \t](.*)$";
+
+impl FromStr for Header {
+ type Err = ParseError;
+
+ // Parses a &str into an instance of 'Header'
+ fn from_str(line: &str) -> Result<Self, Self::Err> {
+ let header_regexp = Regex::new(HEADER_REGEX).unwrap();
+
+ match header_regexp.captures(&line) {
+ Some(caps) => {
+ let code_str = caps.get(1).map_or("", |m| m.as_str());
+ let meta_str = caps.get(2).map_or("", |m| m.as_str());
+
+ let code: i16 = code_str.parse().expect("2");
+ let meta = meta_str.to_string();
+
+ Ok(Header { code, meta })
+ }
+ None => Err(ParseError),
+ }
+ }
+}
diff --git a/src/history.rs b/src/history.rs
new file mode 100644
index 0000000..1b71119
--- /dev/null
+++ b/src/history.rs
@@ -0,0 +1,57 @@
+use std::fs::File;
+use std::io::{Read,Write};
+use std::fs::OpenOptions;
+
+use url::Url;
+
+
+pub fn create_history_file() {
+ File::create("/tmp/asuka_history").expect("unable to create file");
+}
+
+pub fn append(url: &str) {
+ let mut file = OpenOptions::new()
+ .read(true)
+ .create(true)
+ .write(true)
+ .append(true)
+ .open("/tmp/asuka_history")
+ .expect("file not found");
+
+ let line = format!("{}\n", url);
+ file.write_all(line.as_bytes())
+ .expect("Unable to write file");
+}
+
+pub fn get_last_host() -> Option<String> {
+ let mut file = File::open("/tmp/asuka_history").expect("file not found");
+ let mut content = String::new();
+ file.read_to_string(&mut content)
+ .expect("Unable to read file");
+ let last_url = content.lines().last();
+ match last_url {
+ Some(url) => {
+ let urlp = Url::parse(url).expect("not an URL");
+ Some(urlp.host_str().unwrap().to_owned())
+ }
+ None => None,
+ }
+}
+
+pub fn get_previous_url() -> Option<String> {
+ let mut file = OpenOptions::new()
+ .read(true)
+ .open("/tmp/asuka_history")
+ .expect("file not found");
+ let mut content = String::new();
+ file.read_to_string(&mut content)
+ .expect("Unable to read file");
+ let lines_count = content.lines().count();
+
+ if lines_count > 1 {
+ // Return before last line
+ Some(content.lines().nth(lines_count - 2).unwrap().to_owned())
+ } else {
+ None
+ }
+}
diff --git a/src/link.rs b/src/link.rs
new file mode 100644
index 0000000..2e976dd
--- /dev/null
+++ b/src/link.rs
@@ -0,0 +1,41 @@
+extern crate regex;
+use regex::Regex;
+
+use std::str::FromStr;
+
+#[derive(Debug)]
+pub struct Link {
+ pub url: String,
+ pub label: String,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct ParseError;
+
+const LINK_REGEX: &str = r"^=>\s(\S*)\s*(.*)?$";
+
+impl FromStr for Link {
+ type Err = ParseError;
+
+ // Parses a &str into an instance of 'Link'
+ fn from_str(line: &str) -> Result<Self, Self::Err> {
+ let link_regexp = Regex::new(LINK_REGEX).unwrap();
+
+ match link_regexp.captures(&line) {
+ Some(caps) => {
+ let url_str = caps.get(1).map_or("", |m| m.as_str());
+ let label_str = caps.get(2).map_or("", |m| m.as_str());
+
+ let url = url_str.to_string();
+ let label = if label_str.is_empty() {
+ url_str.to_string()
+ } else {
+ label_str.to_string()
+ };
+
+ Ok(Link { url, label })
+ }
+ None => Err(ParseError),
+ }
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index d5d5741..c12d776 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,6 @@
+extern crate native_tls;
+extern crate regex;
+
use cursive::align::HAlign;
use cursive::theme::Effect;
use cursive::traits::*;
@@ -6,86 +9,17 @@ use cursive::view::Scrollable;
use cursive::views::{Dialog, EditView, Panel, SelectView};
use cursive::Cursive;
-extern crate native_tls;
-extern crate regex;
-
-use native_tls::TlsConnector;
-use regex::Regex;
-
-use std::io::{Read, Write};
-use std::net::TcpStream;
-
-use std::fs::File;
-use std::fs::OpenOptions;
-use std::str;
use std::str::FromStr;
use url::Url;
-#[derive(Debug)]
-struct Header {
- code: i16,
- meta: String,
-}
-
-#[derive(Debug)]
-struct Link {
- url: String,
- label: String,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-struct ParseError;
-
-const HEADER_REGEX: &str = r"^(\d{1,3})[ \t](.*)$";
-const LINK_REGEX: &str = r"^=>\s(\S*)\s*(.*)?$";
+mod header;
+use header::Header;
-impl FromStr for Header {
- type Err = ParseError;
+mod link;
+use link::Link;
- // Parses a &str into an instance of 'Header'
- fn from_str(line: &str) -> Result<Self, Self::Err> {
- let header_regexp = Regex::new(HEADER_REGEX).unwrap();
-
- match header_regexp.captures(&line) {
- Some(caps) => {
- let code_str = caps.get(1).map_or("", |m| m.as_str());
- let meta_str = caps.get(2).map_or("", |m| m.as_str());
-
- let code: i16 = code_str.parse().expect("2");
- let meta = meta_str.to_string();
-
- Ok(Header { code, meta })
- }
- None => Err(ParseError),
- }
- }
-}
-
-impl FromStr for Link {
- type Err = ParseError;
-
- // Parses a &str into an instance of 'Link'
- fn from_str(line: &str) -> Result<Self, Self::Err> {
- let link_regexp = Regex::new(LINK_REGEX).unwrap();
-
- match link_regexp.captures(&line) {
- Some(caps) => {
- let url_str = caps.get(1).map_or("", |m| m.as_str());
- let label_str = caps.get(2).map_or("", |m| m.as_str());
-
- let url = url_str.to_string();
- let label = if label_str.is_empty() {
- url_str.to_string()
- } else {
- label_str.to_string()
- };
-
- Ok(Link { url, label })
- }
- None => Err(ParseError),
- }
- }
-}
+mod content;
+mod history;
const HELP: &'static str = "
Welcome to Asuka Gemini browser!
@@ -96,7 +30,7 @@ Press q to exit
";
fn main() {
- File::create("/tmp/asuka_history").expect("unable to create file");
+ history::create_history_file();
let mut siv = Cursive::default();
@@ -154,8 +88,9 @@ fn visit_url(s: &mut Cursive, url_s: &str) {
}
match parse_link(url_s) {
- Ok(url) => match get_data(url) {
+ Ok(url) => match content::get_data(url) {
Ok(new_content) => {
+ history::append(url_s);
draw_content(s, url_s, new_content);
}
Err(msg) => {
@@ -170,7 +105,7 @@ fn visit_url(s: &mut Cursive, url_s: &str) {
fn parse_link(url: &str) -> Result<url::Url, url::ParseError> {
// Creates an absolute link if needed
- match get_last_host() {
+ match history::get_last_host() {
Some(host) => {
let url_s = if url.starts_with("gemini://") {
url.to_owned()
@@ -234,89 +169,9 @@ fn follow_link(s: &mut Cursive, line: &str) {
}
}
-fn get_data(url: url::Url) -> Result<String, String> {
- let host = url.host_str().unwrap();
- let path = url.path();
- let urlf = format!("{}:1965", host);
-
- let mut builder = TlsConnector::builder();
- builder.danger_accept_invalid_hostnames(true);
- builder.danger_accept_invalid_certs(true);
- let connector = builder.build().unwrap();
-
- let stream = TcpStream::connect(&urlf);
-
- match stream {
- Ok(stream) => {
- let mstream = connector.connect(&host, stream);
-
- match mstream {
- Ok(mut stream) => {
- append_history(url.as_str());
-
- let url_with_path = format!("{}\r\n", path);
- stream.write_all(url_with_path.as_bytes()).unwrap();
- let mut res = vec![];
- stream.read_to_end(&mut res).unwrap();
- Ok(String::from_utf8_lossy(&res).to_string())
- }
- Err(e) => Err(format!("Could not connect to {}\n{}", urlf, e)),
- }
- }
- Err(e) => Err(format!("Could not connect to {}\n{}", urlf, e)),
- }
-}
-
fn go_back(s: &mut Cursive) {
- match get_previous_url() {
+ match history::get_previous_url() {
Some(url) => visit_url(s, &url),
None => (),
}
}
-
-fn get_last_host() -> Option<String> {
- let mut file = File::open("/tmp/asuka_history").expect("file not found");
- let mut content = String::new();
- file.read_to_string(&mut content)
- .expect("Unable to read file");
- let last_url = content.lines().last();
- match last_url {
- Some(url) => {
- let urlp = Url::parse(url).expect("not an URL");
- Some(urlp.host_str().unwrap().to_owned())
- }
- None => None,
- }
-}
-
-fn get_previous_url() -> Option<String> {
- let mut file = OpenOptions::new()
- .read(true)
- .open("/tmp/asuka_history")
- .expect("file not found");
- let mut content = String::new();
- file.read_to_string(&mut content)
- .expect("Unable to read file");
- let lines_count = content.lines().count();
-
- if lines_count > 1 {
- // Return before last line
- Some(content.lines().nth(lines_count - 2).unwrap().to_owned())
- } else {
- None
- }
-}
-
-fn append_history(url: &str) {
- let mut file = OpenOptions::new()
- .read(true)
- .create(true)
- .write(true)
- .append(true)
- .open("/tmp/asuka_history")
- .expect("file not found");
-
- let line = format!("{}\n", url);
- file.write_all(line.as_bytes())
- .expect("Unable to write file");
-}
---
Served by Pollux Gemini Server.
-- Response ended
-- Page fetched on Sun May 19 10:18:21 2024