-- 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