From db5920747ab710751f93477baabfb9793dfcc3bd Mon Sep 17 00:00:00 2001
From: Snorre Ettrup Altschul <snorre@altschul.dk>
Date: Thu, 6 Feb 2025 15:28:47 +0100
Subject: [PATCH] why didnt this get pushed yesterday? :skull_emoji:

---
 Cargo.lock  |   9 +++++
 Cargo.toml  |   3 ++
 src/main.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 116 insertions(+), 7 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 48aa698..356208c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,15 @@
 # It is not intended for manual editing.
 version = 4
 
+[[package]]
+name = "urlencoding"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
+
 [[package]]
 name = "webbisitey"
 version = "0.1.0"
+dependencies = [
+ "urlencoding",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 57dda76..deb0588 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,3 +2,6 @@
 name = "webbisitey"
 version = "0.1.0"
 edition = "2024"
+
+[dependencies]
+urlencoding = "2.1.3"
diff --git a/src/main.rs b/src/main.rs
index 2898c81..0f83418 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,8 @@
 use std::{
     env::current_dir,
     ffi::OsStr,
-    io::{BufRead, BufReader, Write},
+    fs::DirEntry,
+    io::{BufRead, BufReader, Read, Write},
     net::{TcpListener, TcpStream},
     path::PathBuf,
 };
@@ -59,7 +60,7 @@ impl Request {
         path.push("public");
 
         path.push(
-            PathBuf::from(self.path.as_ref().unwrap())
+              PathBuf::from(urlencoding::decode(self.path.as_ref().unwrap()).unwrap().to_string())
                 .strip_prefix("/")
                 .expect("Failed to strip prefix"),
         );
@@ -106,6 +107,101 @@ fn handle_connection(mut stream: TcpStream) {
 
     let req = Request::from(http_request.get(0).expect("Empty request"));
 
+    if req.path == Some("/posts/index".to_string()) {
+        stream
+            .write_all(
+                {
+                    match std::fs::read_dir("./public/posts/") {
+                        Ok(files) => {
+                            let mut entries = files
+                                .filter_map(|x| if x.is_ok() { Some(x.unwrap()) } else { None })
+                                .filter(|x| {
+                                    let file_name = x.file_name();
+                                    let y = file_name.to_str();
+                                    if y.is_some() {
+                                        if y.unwrap().ends_with(".md") {
+                                            true
+                                        } else {
+                                            false
+                                        }
+                                    } else {
+                                        false
+                                    }
+                                })
+                                .collect::<Vec<DirEntry>>();
+                            entries.sort_by(|a, b| {
+                                let mut a = if let Ok(a) = std::fs::File::open(a.path()) {
+                                    a
+                                } else {
+                                    return std::cmp::Ordering::Equal;
+                                };
+                                let mut b = if let Ok(b) = std::fs::File::open(b.path()) {
+                                    b
+                                } else {
+                                    return std::cmp::Ordering::Equal;
+                                };
+
+                                let mut buf: &mut [u8] = &mut [0; 16];
+                                let _ = a.read(&mut buf);
+
+                                let a = String::from_utf8_lossy(buf);
+
+                                let buf: &mut [u8] = &mut [0; 16];
+                                let _ = b.read(&mut *buf);
+                                let b = String::from_utf8_lossy(buf);
+
+                                let a = if let Ok(a) = a
+                                    .chars()
+                                    .take_while(|x| x != &'\n')
+                                    .collect::<String>()
+                                    .parse::<u32>()
+                                {
+                                    a
+                                } else {
+                                    return std::cmp::Ordering::Equal;
+                                };
+
+                                let b = if let Ok(b) = b
+                                    .chars()
+                                    .take_while(|x| x != &'\n')
+                                    .collect::<String>()
+                                    .parse::<u32>()
+                                {
+                                    b
+                                } else {
+                                    return std::cmp::Ordering::Equal;
+                                };
+
+                                return a.cmp(&b);
+                            });
+                            entries
+                                .into_iter()
+                                .filter_map(|x| {
+                                    if let Some(n) = x.file_name().to_str() {
+                                        if n.ends_with(".md") {
+                                            Some(n.to_owned().replace(".md",""))
+                                        } else {
+                                            None
+                                        }
+                                    } else {
+                                        None
+                                    }
+                                })
+                                .reduce(|a, b| format!("{}\n{}", b, a))
+                                .unwrap()
+                        }
+                        // .reduce(|i, x| format!("{}\n{}", i, x))
+                        // .unwrap()
+                        // .to_string(),
+                        Err(e) => format!("HTTP/1.1 500\r\n\r\n{}", e),
+                    }
+                }
+                .as_bytes(),
+            )
+            .unwrap();
+        return;
+    }
+
     println!("Requested file: {:#?}", req.file());
 
     let mut response_content = vec![];
@@ -116,11 +212,12 @@ fn handle_connection(mut stream: TcpStream) {
                 let len = &content.len();
                 response_content = content;
                 format!(
-                "HTTP/1.1 200 OK{0}Content-Type: {2}{0}Content-Length: {1}{0}{0}",
-                CLRF,
-                len,
-                get_mime_type(path.extension())
-            )},
+                    "HTTP/1.1 200 OK{0}Content-Type: {2}{0}Content-Length: {1}{0}{0}",
+                    CLRF,
+                    len,
+                    get_mime_type(path.extension())
+                )
+            }
             Err(e) => format!("HTTP/1.1 404{0}{0}{e}", CLRF),
         },
         None => format!("HTTP/1.1 404{0}{0}", CLRF),