summaryrefslogtreecommitdiff
path: root/src/console.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/console.rs')
-rw-r--r--src/console.rs264
1 files changed, 0 insertions, 264 deletions
diff --git a/src/console.rs b/src/console.rs
deleted file mode 100644
index 16bf4a3..0000000
--- a/src/console.rs
+++ /dev/null
@@ -1,264 +0,0 @@
-use axum::{
- http::{Method, Uri},
- response::Response,
-};
-use lazy_static::lazy_static;
-use serde::Serialize;
-use serde_json::{ser::Formatter, Value};
-use std::{collections::VecDeque, io, net::IpAddr};
-use tokio::sync::Mutex;
-
-use crate::types::http::ResponseCode;
-
-struct LogMessage {
- ip: IpAddr,
- method: Method,
- uri: Uri,
- path: String,
- body: String,
-}
-
-impl ToString for LogMessage {
- fn to_string(&self) -> String {
- let mut ip = self.ip.to_string();
- if ip.contains("::ffff:") {
- ip = ip.as_str()[7..].to_string();
- }
- let color = match self.method {
- Method::GET => "#3fe04f",
- Method::POST => "#853fe0",
- Method::PATCH => "#e0773f",
- Method::PUT => "#e0cb3f",
- Method::HEAD => "#3f75e0",
- Method::DELETE => "#e04c3f",
- Method::CONNECT => "#3fe0ad",
- Method::TRACE => "#e03fc5",
- Method::OPTIONS => "#423fe0",
- _ => "white",
- };
- format!("<div class='msg'><span class='ip'>{}</span> <span class='method' style='color: {};'>{}</span> <span class='path'>{}{}</span> <span class='body'>{}</span></div>",
- ip, color, self.method, self.path, sanatize(&self.uri.to_string()), self.body)
- }
-}
-
-lazy_static! {
- static ref LOG: Mutex<VecDeque<LogMessage>> = Mutex::new(VecDeque::with_capacity(200));
-}
-
-pub async fn log(ip: IpAddr, method: Method, uri: Uri, path: Option<String>, body: Option<String>) {
- let path = path.unwrap_or_default();
- let body = body.unwrap_or_default();
-
- if path == "/api/admin" {
- return;
- }
-
- tracing::info!("{} {} {}{} {}", &ip, &method, &path, &uri, &body);
-
- let message = LogMessage {
- ip,
- method,
- uri,
- path,
- body: beautify(&body),
- };
-
- let mut lock = LOG.lock().await;
- if lock.len() > 200 {
- lock.pop_back();
- }
- lock.push_front(message);
-}
-
-struct HtmlFormatter;
-impl Formatter for HtmlFormatter {
- fn write_null<W>(&mut self, writer: &mut W) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- writer.write_all(b"<span class='null'>null</span>")
- }
-
- fn write_bool<W>(&mut self, writer: &mut W, value: bool) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- let s = if value {
- b"<span class='bool'>true</span>" as &[u8]
- } else {
- b"<span class='bool'>false</span>" as &[u8]
- };
- writer.write_all(s)
- }
-
- fn write_i8<W>(&mut self, writer: &mut W, value: i8) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- let buff = format!("<span class='number'>{value}</span>");
- writer.write_all(buff.as_bytes())
- }
-
- fn write_i16<W>(&mut self, writer: &mut W, value: i16) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- let buff = format!("<span class='number'>{value}</span>");
- writer.write_all(buff.as_bytes())
- }
-
- fn write_i32<W>(&mut self, writer: &mut W, value: i32) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- let buff = format!("<span class='number'>{value}</span>");
- writer.write_all(buff.as_bytes())
- }
-
- fn write_i64<W>(&mut self, writer: &mut W, value: i64) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- let buff = format!("<span class='number'>{value}</span>");
- writer.write_all(buff.as_bytes())
- }
-
- fn write_u8<W>(&mut self, writer: &mut W, value: u8) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- let buff = format!("<span class='number'>{value}</span>");
- writer.write_all(buff.as_bytes())
- }
-
- fn write_u16<W>(&mut self, writer: &mut W, value: u16) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- let buff = format!("<span class='number'>{value}</span>");
- writer.write_all(buff.as_bytes())
- }
-
- fn write_u32<W>(&mut self, writer: &mut W, value: u32) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- let buff = format!("<span class='number'>{value}</span>");
- writer.write_all(buff.as_bytes())
- }
-
- fn write_u64<W>(&mut self, writer: &mut W, value: u64) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- let buff = format!("<span class='number'>{value}</span>");
- writer.write_all(buff.as_bytes())
- }
-
- fn write_f32<W>(&mut self, writer: &mut W, value: f32) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- let buff = format!("<span class='number'>{value}</span>");
- writer.write_all(buff.as_bytes())
- }
-
- fn write_f64<W>(&mut self, writer: &mut W, value: f64) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- let buff = format!("<span class='number'>{value}</span>");
- writer.write_all(buff.as_bytes())
- }
-
- fn begin_string<W>(&mut self, writer: &mut W) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- writer.write_all(b"<span class='string'>\"")
- }
-
- fn end_string<W>(&mut self, writer: &mut W) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- writer.write_all(b"\"</span>")
- }
-
- fn begin_object_key<W>(&mut self, writer: &mut W, first: bool) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- if first {
- writer.write_all(b"<span class='key'>")
- } else {
- writer.write_all(b"<span class='key'>,")
- }
- }
-
- fn end_object_key<W>(&mut self, writer: &mut W) -> io::Result<()>
- where
- W: ?Sized + io::Write,
- {
- writer.write_all(b"</span>")
- }
-}
-
-pub fn sanatize(input: &str) -> String {
- input
- .replace('&', "&amp;")
- .replace('<', "&lt;")
- .replace('>', "&gt;")
-}
-
-pub fn beautify(body: &str) -> String {
- let body = sanatize(body);
-
- if body.is_empty() {
- return String::new();
- }
- let Ok(mut json) = serde_json::from_str::<Value>(&body) else {
- return body
- };
- if json["password"].is_string() {
- json["password"] = Value::String("********".to_owned());
- }
- let mut writer: Vec<u8> = Vec::with_capacity(128);
- let mut serializer = serde_json::Serializer::with_formatter(&mut writer, HtmlFormatter);
- if json.serialize(&mut serializer).is_err() {
- return body;
- }
- String::from_utf8_lossy(&writer).to_string()
-}
-
-pub async fn generate() -> Response {
- let lock = LOG.lock().await;
-
- let mut html = r#"<!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="refresh" content="5">
- <link rel="stylesheet" href="/css/main.css">
- <link rel="stylesheet" href="/css/header.css">
- <link rel="stylesheet" href="/css/admin.css">
- <link rel="stylesheet" href="/css/console.css">
- <title>XSSBook - Console</title>
- </head>
- <body>
- <div id="header">
- <span class="logo"><a href="/">xssbook</a></span>
- <span class="gtext desc" style="margin-left: 6em; font-size: 2em; color: #606770">Console</span>
- </div>
- <div style="margin-bottom: 3.5em"></div>
- "#
- .to_string();
-
- for message in lock.iter() {
- html.push_str(&message.to_string());
- }
-
- html.push_str("</body></html>");
-
- ResponseCode::Success.html(&html)
-}