mirror of
https://github.com/YGGverse/Yoda.git
synced 2025-03-13 06:01:21 +00:00
handle redirection feature
This commit is contained in:
parent
32d3c1b31a
commit
9cb3b47a92
@ -3,7 +3,7 @@ use crate::tool::now;
|
|||||||
use super::super::super::page::status::Status as PageStatus; // @TODO
|
use super::super::super::page::status::Status as PageStatus; // @TODO
|
||||||
|
|
||||||
use super::{Feature, Page};
|
use super::{Feature, Page};
|
||||||
use gtk::glib::GString;
|
use gtk::glib::{GString, UriFlags};
|
||||||
use gtk::prelude::{EditableExt, FileExt};
|
use gtk::prelude::{EditableExt, FileExt};
|
||||||
use gtk::{
|
use gtk::{
|
||||||
gdk::Texture,
|
gdk::Texture,
|
||||||
@ -12,12 +12,16 @@ use gtk::{
|
|||||||
glib::{Priority, Uri},
|
glib::{Priority, Uri},
|
||||||
prelude::{EntryExt, SocketClientExt},
|
prelude::{EntryExt, SocketClientExt},
|
||||||
};
|
};
|
||||||
use std::{path::MAIN_SEPARATOR, rc::Rc, time::Duration};
|
use std::{cell::Cell, path::MAIN_SEPARATOR, rc::Rc, time::Duration};
|
||||||
|
|
||||||
/// Multi-protocol client API for `Page` object
|
/// Multi-protocol client API for `Page` object
|
||||||
pub struct Gemini {
|
pub struct Gemini {
|
||||||
|
/// Should be initiated once
|
||||||
client: Rc<ggemini::Client>,
|
client: Rc<ggemini::Client>,
|
||||||
|
/// Handle target
|
||||||
page: Rc<Page>,
|
page: Rc<Page>,
|
||||||
|
/// Validate redirection count by Gemini protocol specification
|
||||||
|
redirects: Rc<Cell<usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gemini {
|
impl Gemini {
|
||||||
@ -55,6 +59,7 @@ impl Gemini {
|
|||||||
Self {
|
Self {
|
||||||
client,
|
client,
|
||||||
page: page.clone(),
|
page: page.clone(),
|
||||||
|
redirects: Rc::new(Cell::new(0)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +119,7 @@ impl Gemini {
|
|||||||
{
|
{
|
||||||
let uri = uri.clone();
|
let uri = uri.clone();
|
||||||
let page = self.page.clone();
|
let page = self.page.clone();
|
||||||
|
let redirects = self.redirects.clone();
|
||||||
move |result| match result {
|
move |result| match result {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
match response.meta.status {
|
match response.meta.status {
|
||||||
@ -357,15 +363,70 @@ impl Gemini {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// https://geminiprotocol.net/docs/protocol-specification.gmi#status-30-temporary-redirection
|
// https://geminiprotocol.net/docs/protocol-specification.gmi#status-30-temporary-redirection
|
||||||
Status::Redirect => todo!(),
|
|
||||||
// https://geminiprotocol.net/docs/protocol-specification.gmi#status-31-permanent-redirection
|
// https://geminiprotocol.net/docs/protocol-specification.gmi#status-31-permanent-redirection
|
||||||
Status::PermanentRedirect => {
|
Status::PermanentRedirect | Status::Redirect => {
|
||||||
page.navigation
|
// Expected target URL in response meta
|
||||||
.request
|
match response.meta.data {
|
||||||
.widget
|
Some(data) => {
|
||||||
.entry
|
match uri.parse_relative(data.as_str(), UriFlags::NONE) {
|
||||||
.set_text(&uri.to_string());
|
Ok(target) => {
|
||||||
todo!()
|
let total = redirects.take() + 1;
|
||||||
|
|
||||||
|
// Validate total redirects by protocol specification
|
||||||
|
if total > 5 {
|
||||||
|
let status = page.content.to_status_failure();
|
||||||
|
status.set_description(Some("Redirection limit reached"));
|
||||||
|
|
||||||
|
page.status.replace(PageStatus::Failure { time: now() });
|
||||||
|
page.title.replace(status.title());
|
||||||
|
page.browser_action.update.activate(Some(&page.id));
|
||||||
|
|
||||||
|
redirects.replace(0); // reset
|
||||||
|
|
||||||
|
// Disallow external redirection
|
||||||
|
} else if uri.scheme() != target.scheme()
|
||||||
|
|| uri.port() != target.port()
|
||||||
|
|| uri.host() != target.host() {
|
||||||
|
let status = page.content.to_status_failure();
|
||||||
|
status.set_description(Some("External redirects not allowed by protocol specification"));
|
||||||
|
|
||||||
|
page.status.replace(PageStatus::Failure { time: now() });
|
||||||
|
page.title.replace(status.title());
|
||||||
|
page.browser_action.update.activate(Some(&page.id));
|
||||||
|
|
||||||
|
redirects.replace(0); // reset
|
||||||
|
// Valid
|
||||||
|
} else {
|
||||||
|
if matches!(response.meta.status, Status::PermanentRedirect) {
|
||||||
|
page.navigation
|
||||||
|
.request
|
||||||
|
.widget
|
||||||
|
.entry
|
||||||
|
.set_text(&uri.to_string());
|
||||||
|
}
|
||||||
|
redirects.replace(total);
|
||||||
|
page.tab_action.load.activate(Some(""), is_history);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
let status = page.content.to_status_failure();
|
||||||
|
status.set_description(Some(&e.to_string()));
|
||||||
|
|
||||||
|
page.status.replace(PageStatus::Failure { time: now() });
|
||||||
|
page.title.replace(status.title());
|
||||||
|
page.browser_action.update.activate(Some(&page.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let status = page.content.to_status_failure();
|
||||||
|
status.set_description(Some("Redirection target not found"));
|
||||||
|
|
||||||
|
page.status.replace(PageStatus::Failure { time: now() });
|
||||||
|
page.title.replace(status.title());
|
||||||
|
page.browser_action.update.activate(Some(&page.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// https://geminiprotocol.net/docs/protocol-specification.gmi#status-60
|
// https://geminiprotocol.net/docs/protocol-specification.gmi#status-60
|
||||||
Status::CertificateRequest => {
|
Status::CertificateRequest => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user