Merged server and client code into single repo
This commit is contained in:
		
							
								
								
									
										11
									
								
								client/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								client/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="cs">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta charset="UTF-8">
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
				
			||||||
 | 
					    <title>Infinitum</title>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										43
									
								
								client/login/login.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								client/login/login.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="cs">
 | 
				
			||||||
 | 
					  <head>
 | 
				
			||||||
 | 
					    <meta charset="UTF-8" />
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="style.css">
 | 
				
			||||||
 | 
					    <title>Přihlášení | Infinitum</title>
 | 
				
			||||||
 | 
					  </head>
 | 
				
			||||||
 | 
					  <body>
 | 
				
			||||||
 | 
					    <form action="http://10.69.13.199:8000/" method="post">
 | 
				
			||||||
 | 
					      <div class="most_outer_form_border">
 | 
				
			||||||
 | 
					          <div class="outer_form_border">
 | 
				
			||||||
 | 
					              <div class="form_border">
 | 
				
			||||||
 | 
					                  <h1>Přihlášení</h1>
 | 
				
			||||||
 | 
					                  <br>
 | 
				
			||||||
 | 
					                  <label for="username">Uživatelské jméno</label>
 | 
				
			||||||
 | 
					                  <br>
 | 
				
			||||||
 | 
					                  <input type="text" name="username" id="username" autofocus required minlength="3" maxlength="25"/>
 | 
				
			||||||
 | 
					                  <br>
 | 
				
			||||||
 | 
					                  <label for="password">Heslo</label>
 | 
				
			||||||
 | 
					                  <br>
 | 
				
			||||||
 | 
					                  <input type="password" name="password" id="password" required minlength="8" maxlength="40" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*]).{8,}$"/>
 | 
				
			||||||
 | 
					                  <br>
 | 
				
			||||||
 | 
					                  <button type="submit">Přihlásit se</button>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </form>
 | 
				
			||||||
 | 
					    <script>
 | 
				
			||||||
 | 
					        const form = document.querySelector("form");
 | 
				
			||||||
 | 
					        form.addEventListener("submit", function (e) {
 | 
				
			||||||
 | 
					            e.preventDefault();
 | 
				
			||||||
 | 
					            const passwordInput = this.querySelector("input[type=password]");
 | 
				
			||||||
 | 
					            crypto.subtle.digest("SHA-512", new TextEncoder().encode(passwordInput.value)).then(function (hashBuffer) {
 | 
				
			||||||
 | 
					                const hashArray = Array.from(new Uint8Array(hashBuffer));
 | 
				
			||||||
 | 
					                const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
 | 
				
			||||||
 | 
					                passwordInput.value = hashHex;
 | 
				
			||||||
 | 
					                form.submit();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					  </body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										66
									
								
								client/login/style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								client/login/style.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					@import url('https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,200&family=Source+Code+Pro:wght@300&display=swap');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					body {
 | 
				
			||||||
 | 
					    background-image: linear-gradient(120deg, #fccb90 0%, #d57eeb 100%);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form_border {
 | 
				
			||||||
 | 
					    border: 1px solid rgb(92, 92, 92);
 | 
				
			||||||
 | 
					    border-radius: 7px;
 | 
				
			||||||
 | 
					    background-color: rgb(160, 161, 182);
 | 
				
			||||||
 | 
					    width: 350px;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    height: 400px;
 | 
				
			||||||
 | 
					    justify-content: space-around;
 | 
				
			||||||
 | 
					    line-height: 200%;
 | 
				
			||||||
 | 
					    font-family: 'DM Sans', sans-serif;
 | 
				
			||||||
 | 
					    font-size: larger;
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form_border > input {
 | 
				
			||||||
 | 
					    width: 95%;
 | 
				
			||||||
 | 
					    font-family: 'Source Code Pro', monospace;
 | 
				
			||||||
 | 
					    outline: none;
 | 
				
			||||||
 | 
					    font-size: larger;
 | 
				
			||||||
 | 
					    border-radius: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form_border > input:focus {
 | 
				
			||||||
 | 
					    background-color: rgb(235, 235, 235);
 | 
				
			||||||
 | 
					    outline: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form_border > label {
 | 
				
			||||||
 | 
					    width: 97%;
 | 
				
			||||||
 | 
					    display: inline-block;
 | 
				
			||||||
 | 
					    line-height: 200%;
 | 
				
			||||||
 | 
					    text-align: left;
 | 
				
			||||||
 | 
					}  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.form_border > button {
 | 
				
			||||||
 | 
					    font-family: 'DM Sans', sans-serif;
 | 
				
			||||||
 | 
					    font-size: larger;
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    bottom: 10px;
 | 
				
			||||||
 | 
					    /*left: 117px;*/
 | 
				
			||||||
 | 
					    left: 0;
 | 
				
			||||||
 | 
					    background-color: rgba(255, 190, 78, 0.7);
 | 
				
			||||||
 | 
					    height: 12%;
 | 
				
			||||||
 | 
					    font-weight: bold;
 | 
				
			||||||
 | 
					    border: none;
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.most_outer_form_border {
 | 
				
			||||||
 | 
					    position: fixed;
 | 
				
			||||||
 | 
					    left: 0;
 | 
				
			||||||
 | 
					    top: 0;
 | 
				
			||||||
 | 
					    width: 100vw;
 | 
				
			||||||
 | 
					    height: 100vh;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.outer_form_border {
 | 
				
			||||||
 | 
					    margin: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								client/main/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								client/main/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="cs">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					    <meta charset="UTF-8">
 | 
				
			||||||
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="style.css">
 | 
				
			||||||
 | 
					    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
 | 
				
			||||||
 | 
					    <title>Infinitum</title>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					    <div class="cosiRandomCentered">
 | 
				
			||||||
 | 
					        <div class="chatHier">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="inputHier">
 | 
				
			||||||
 | 
					            <textarea id="textInput" autofocus name="textInput" rows="2" wrap="soft" >
 | 
				
			||||||
 | 
					            </textarea>
 | 
				
			||||||
 | 
					            <button type="button">Odeslat!</button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <script src="script.js"></script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										76
									
								
								client/main/script.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								client/main/script.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
				
			|||||||
 | 
					messages = [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    messageid: 98568,
 | 
				
			||||||
 | 
					    timestamp: 1630000000000,
 | 
				
			||||||
 | 
					    author: {
 | 
				
			||||||
 | 
					      name: "Velecísař Empy",
 | 
				
			||||||
 | 
					      id: 1,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    content: "Test message 01",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    messageid: 98868,
 | 
				
			||||||
 | 
					    timestamp: 1640000000000,
 | 
				
			||||||
 | 
					    author: {
 | 
				
			||||||
 | 
					      name: "Velecísař Empy 2",
 | 
				
			||||||
 | 
					      id: 2,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    content: "Test message 02",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    messageid: 96666,
 | 
				
			||||||
 | 
					    timestamp: 1650000000000,
 | 
				
			||||||
 | 
					    author: {
 | 
				
			||||||
 | 
					      name: "Velecísař Empy",
 | 
				
			||||||
 | 
					      id: 1,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    content: "Test message 03\n\n\n\n\nPokračování\ntest\na\na\n\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n\na\na\na\na\na\na\na\na\na\n\na\na\na\na\na\na\na\na\na\n\na\na\na\na\na\na\na\na\na\n",
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const messagesDescending = messages.sort((a, b) => a.timestamp - b.timestamp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let htmlString = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const currentUser = {
 | 
				
			||||||
 | 
					  name: "Velecísař Empy",
 | 
				
			||||||
 | 
					  id: 1,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					messagesDescending.forEach((obj) => {
 | 
				
			||||||
 | 
					  var meAuthor = obj.author.id == currentUser.id;
 | 
				
			||||||
 | 
					  var tempString = "";
 | 
				
			||||||
 | 
					  if (meAuthor) {
 | 
				
			||||||
 | 
					    tempString = '<div class="message left">';
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    tempString = '<div class="message right">';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tempString += "<div class=\"firstLine\">"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // console.log(event.toLocaleString('cs-CZ', { weekday: "long", year: "numeric", month:"long", day: "numeric", era: "long", hour: "numeric", minute: "numeric", second: "numeric"}));
 | 
				
			||||||
 | 
					  const locale = "cs-CZ";
 | 
				
			||||||
 | 
					  const options = {
 | 
				
			||||||
 | 
					    weekday: "long",
 | 
				
			||||||
 | 
					    year: "numeric",
 | 
				
			||||||
 | 
					    month: "long",
 | 
				
			||||||
 | 
					    day: "numeric",
 | 
				
			||||||
 | 
					    hour: "numeric",
 | 
				
			||||||
 | 
					    minute: "numeric",
 | 
				
			||||||
 | 
					    second: "numeric",
 | 
				
			||||||
 | 
					    era: "long"
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tempString += `<p class=\"author\">${ obj.author.name}</p>`;
 | 
				
			||||||
 | 
					  tempString += "<p class=\"spacer\"></p>"
 | 
				
			||||||
 | 
					  tempString += `<p class=\"time\">${ new Date(obj.timestamp).toLocaleString(locale, options)}</p>`;
 | 
				
			||||||
 | 
					  tempString += "</div>"
 | 
				
			||||||
 | 
					  //htmlString += `<p>ID: ${obj.messageid}, Timestamp: ${obj.timestamp}, Author Name: ${obj.author.name}, Author ID: ${obj.author.id}, Content: ${obj.content}</p>`;
 | 
				
			||||||
 | 
					  tempString += `<p class=\"content\">${obj.content.replaceAll("\n", "<br/>")}</p>`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tempString += "</div>";
 | 
				
			||||||
 | 
					  htmlString += tempString;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(".chatHier").html(htmlString);
 | 
				
			||||||
							
								
								
									
										94
									
								
								client/main/style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								client/main/style.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					@import url("https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,200&family=Source+Code+Pro:wght@300&display=swap");
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					font-family: 'Source Code Pro', monospace;
 | 
				
			||||||
 | 
					font-family: 'DM Sans', sans-serif;
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					body,
 | 
				
			||||||
 | 
					html {
 | 
				
			||||||
 | 
					  font-family: "Source Code Pro", monospace;
 | 
				
			||||||
 | 
					  background-image: linear-gradient(120deg, #fccb90 0%, #d57eeb 100%);
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  margin: 0;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.cosiRandomCentered {
 | 
				
			||||||
 | 
					  height: 100vh;
 | 
				
			||||||
 | 
					  width: 60vw;
 | 
				
			||||||
 | 
					  background-color: rgba(240, 240, 240, 0.55);
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.inputHier {
 | 
				
			||||||
 | 
					  margin-top: auto;
 | 
				
			||||||
 | 
					  background-color: #f0f0f0; /* Optional: Set a background color for better visibility */
 | 
				
			||||||
 | 
					  padding: 10px; /* Optional: Adjust padding as needed */
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  box-sizing: border-box;
 | 
				
			||||||
 | 
					  /*grid-template-columns: 2fr 1fr;*/
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.inputHier > textarea {
 | 
				
			||||||
 | 
					  font-family: "Source Code Pro", monospace;
 | 
				
			||||||
 | 
					  font-size: large;
 | 
				
			||||||
 | 
					  /*width: 1024px;*/
 | 
				
			||||||
 | 
					  width: 90%;
 | 
				
			||||||
 | 
					  box-sizing: border-box;
 | 
				
			||||||
 | 
					  resize: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.inputHier > button {
 | 
				
			||||||
 | 
					  font-family: "Source Code Pro", monospace;
 | 
				
			||||||
 | 
					  font-size: larger;
 | 
				
			||||||
 | 
					  font-weight: 700;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  box-sizing: border-box;
 | 
				
			||||||
 | 
					  margin-left: 10px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.chatHier {
 | 
				
			||||||
 | 
					    overflow: scroll;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.message {
 | 
				
			||||||
 | 
					  border: #d57eeb solid 5px;
 | 
				
			||||||
 | 
					  border-radius: 20px;
 | 
				
			||||||
 | 
					  width: max-content;
 | 
				
			||||||
 | 
					  padding: 5px;
 | 
				
			||||||
 | 
					  margin: 3px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.time {
 | 
				
			||||||
 | 
					  font-size: x-small;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.author {
 | 
				
			||||||
 | 
					  font-size: x-small;
 | 
				
			||||||
 | 
					  font-weight: 600;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.firstLine {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.spacer {
 | 
				
			||||||
 | 
					    width: 50px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.left {
 | 
				
			||||||
 | 
					    color:  darkslategray;
 | 
				
			||||||
 | 
					    background-color: rgba(30, 215, 250, 0.8);
 | 
				
			||||||
 | 
					    margin-right: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.right {
 | 
				
			||||||
 | 
					    color:  darkslategray;
 | 
				
			||||||
 | 
					    background-color: rgba(250, 65, 30, 0.8);
 | 
				
			||||||
 | 
					    margin-left: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								server/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								server/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					all: server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					clean:
 | 
				
			||||||
 | 
					        rm -rf *.o
 | 
				
			||||||
 | 
					        @rm -rf server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					server: main.o httpd.o
 | 
				
			||||||
 | 
					        gcc -o server $^ -lssl -lcrypto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main.o: main.c httpd.h
 | 
				
			||||||
 | 
					        gcc -c -o main.o main.c -lssl -lcrypto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					httpd.o: httpd.c httpd.h
 | 
				
			||||||
 | 
					        gcc -c -o httpd.o httpd.c
 | 
				
			||||||
							
								
								
									
										231
									
								
								server/httpd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								server/httpd.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,231 @@
 | 
				
			|||||||
 | 
					#include "httpd.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include <netdb.h>
 | 
				
			||||||
 | 
					#include <signal.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <sys/mman.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_CONNECTIONS 1000
 | 
				
			||||||
 | 
					#define BUF_SIZE 65535
 | 
				
			||||||
 | 
					#define QUEUE_SIZE 1000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int listenfd;
 | 
				
			||||||
 | 
					int *clients;
 | 
				
			||||||
 | 
					static void start_server(const char *);
 | 
				
			||||||
 | 
					static void respond(int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char *buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Client request
 | 
				
			||||||
 | 
					char *method, // "GET" or "POST"
 | 
				
			||||||
 | 
					    *uri,     // "/index.html" things before '?'
 | 
				
			||||||
 | 
					    *qs,      // "a=1&b=2" things after  '?'
 | 
				
			||||||
 | 
					    *prot,    // "HTTP/1.1"
 | 
				
			||||||
 | 
					    *payload; // for POST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int payload_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void serve_forever(const char *PORT) {
 | 
				
			||||||
 | 
					  struct sockaddr_in clientaddr;
 | 
				
			||||||
 | 
					  socklen_t addrlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int slot = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  printf("Server started %shttp://127.0.0.1:%s%s\n", "\033[92m", PORT,
 | 
				
			||||||
 | 
					         "\033[0m");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // create shared memory for client slot array
 | 
				
			||||||
 | 
					  clients = mmap(NULL, sizeof(*clients) * MAX_CONNECTIONS,
 | 
				
			||||||
 | 
					                 PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Setting all elements to -1: signifies there is no client connected
 | 
				
			||||||
 | 
					  int i;
 | 
				
			||||||
 | 
					  for (i = 0; i < MAX_CONNECTIONS; i++)
 | 
				
			||||||
 | 
					    clients[i] = -1;
 | 
				
			||||||
 | 
					  start_server(PORT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Ignore SIGCHLD to avoid zombie threads
 | 
				
			||||||
 | 
					  signal(SIGCHLD, SIG_IGN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // ACCEPT connections
 | 
				
			||||||
 | 
					  while (1) {
 | 
				
			||||||
 | 
					    addrlen = sizeof(clientaddr);
 | 
				
			||||||
 | 
					    clients[slot] = accept(listenfd, (struct sockaddr *)&clientaddr, &addrlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (clients[slot] < 0) {
 | 
				
			||||||
 | 
					      perror("accept() error");
 | 
				
			||||||
 | 
					      exit(1);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      if (fork() == 0) {
 | 
				
			||||||
 | 
					        close(listenfd);
 | 
				
			||||||
 | 
					        respond(slot);
 | 
				
			||||||
 | 
					        close(clients[slot]);
 | 
				
			||||||
 | 
					        clients[slot] = -1;
 | 
				
			||||||
 | 
					        exit(0);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        close(clients[slot]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (clients[slot] != -1)
 | 
				
			||||||
 | 
					      slot = (slot + 1) % MAX_CONNECTIONS;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// start server
 | 
				
			||||||
 | 
					void start_server(const char *port) {
 | 
				
			||||||
 | 
					  struct addrinfo hints, *res, *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // getaddrinfo for host
 | 
				
			||||||
 | 
					  memset(&hints, 0, sizeof(hints));
 | 
				
			||||||
 | 
					  hints.ai_family = AF_INET;
 | 
				
			||||||
 | 
					  hints.ai_socktype = SOCK_STREAM;
 | 
				
			||||||
 | 
					  hints.ai_flags = AI_PASSIVE;
 | 
				
			||||||
 | 
					  if (getaddrinfo(NULL, port, &hints, &res) != 0) {
 | 
				
			||||||
 | 
					    perror("getaddrinfo() error");
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // socket and bind
 | 
				
			||||||
 | 
					  for (p = res; p != NULL; p = p->ai_next) {
 | 
				
			||||||
 | 
					    int option = 1;
 | 
				
			||||||
 | 
					    listenfd = socket(p->ai_family, p->ai_socktype, 0);
 | 
				
			||||||
 | 
					    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
 | 
				
			||||||
 | 
					    if (listenfd == -1)
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0)
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (p == NULL) {
 | 
				
			||||||
 | 
					    perror("socket() or bind()");
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  freeaddrinfo(res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // listen for incoming connections
 | 
				
			||||||
 | 
					  if (listen(listenfd, QUEUE_SIZE) != 0) {
 | 
				
			||||||
 | 
					    perror("listen() error");
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// get request header by name
 | 
				
			||||||
 | 
					char *request_header(const char *name) {
 | 
				
			||||||
 | 
					  header_t *h = reqhdr;
 | 
				
			||||||
 | 
					  while (h->name) {
 | 
				
			||||||
 | 
					    if (strcmp(h->name, name) == 0)
 | 
				
			||||||
 | 
					      return h->value;
 | 
				
			||||||
 | 
					    h++;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// get all request headers
 | 
				
			||||||
 | 
					header_t *request_headers(void) { return reqhdr; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Handle escape characters (%xx)
 | 
				
			||||||
 | 
					static void uri_unescape(char *uri) {
 | 
				
			||||||
 | 
					  char chr = 0;
 | 
				
			||||||
 | 
					  char *src = uri;
 | 
				
			||||||
 | 
					  char *dst = uri;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Skip inital non encoded character
 | 
				
			||||||
 | 
					  while (*src && !isspace((int)(*src)) && (*src != '%'))
 | 
				
			||||||
 | 
					    src++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Replace encoded characters with corresponding code.
 | 
				
			||||||
 | 
					  dst = src;
 | 
				
			||||||
 | 
					  while (*src && !isspace((int)(*src))) {
 | 
				
			||||||
 | 
					    if (*src == '+')
 | 
				
			||||||
 | 
					      chr = ' ';
 | 
				
			||||||
 | 
					    else if ((*src == '%') && src[1] && src[2]) {
 | 
				
			||||||
 | 
					      src++;
 | 
				
			||||||
 | 
					      chr = ((*src & 0x0F) + 9 * (*src > '9')) * 16;
 | 
				
			||||||
 | 
					      src++;
 | 
				
			||||||
 | 
					      chr += ((*src & 0x0F) + 9 * (*src > '9'));
 | 
				
			||||||
 | 
					    } else
 | 
				
			||||||
 | 
					      chr = *src;
 | 
				
			||||||
 | 
					    *dst++ = chr;
 | 
				
			||||||
 | 
					    src++;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  *dst = '\0';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// client connection
 | 
				
			||||||
 | 
					void respond(int slot) {
 | 
				
			||||||
 | 
					  int rcvd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  buf = malloc(BUF_SIZE);
 | 
				
			||||||
 | 
					  rcvd = recv(clients[slot], buf, BUF_SIZE, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (rcvd < 0) // receive error
 | 
				
			||||||
 | 
					    fprintf(stderr, ("recv() error\n"));
 | 
				
			||||||
 | 
					  else if (rcvd == 0) // receive socket closed
 | 
				
			||||||
 | 
					    fprintf(stderr, "Client disconnected upexpectedly.\n");
 | 
				
			||||||
 | 
					  else // message received
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    buf[rcvd] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    method = strtok(buf, " \t\r\n");
 | 
				
			||||||
 | 
					    uri = strtok(NULL, " \t");
 | 
				
			||||||
 | 
					    prot = strtok(NULL, " \t\r\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uri_unescape(uri);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fprintf(stderr, "\x1b[32m + [%s] %s\x1b[0m\n", method, uri);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qs = strchr(uri, '?');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (qs)
 | 
				
			||||||
 | 
					      *qs++ = '\0'; // split URI
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      qs = uri - 1; // use an empty string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    header_t *h = reqhdr;
 | 
				
			||||||
 | 
					    char *t, *t2;
 | 
				
			||||||
 | 
					    while (h < reqhdr + 16) {
 | 
				
			||||||
 | 
					      char *key, *val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      key = strtok(NULL, "\r\n: \t");
 | 
				
			||||||
 | 
					      if (!key)
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      val = strtok(NULL, "\r\n");
 | 
				
			||||||
 | 
					      while (*val && *val == ' ')
 | 
				
			||||||
 | 
					        val++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      h->name = key;
 | 
				
			||||||
 | 
					      h->value = val;
 | 
				
			||||||
 | 
					      h++;
 | 
				
			||||||
 | 
					      fprintf(stderr, "[H] %s: %s\n", key, val);
 | 
				
			||||||
 | 
					      t = val + 1 + strlen(val);
 | 
				
			||||||
 | 
					      if (t[1] == '\r' && t[2] == '\n')
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    t = strtok(NULL, "\r\n");
 | 
				
			||||||
 | 
					    t2 = request_header("Content-Length"); // and the related header if there is
 | 
				
			||||||
 | 
					    payload = t;
 | 
				
			||||||
 | 
					    payload_size = t2 ? atol(t2) : (rcvd - (t - buf));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // bind clientfd to stdout, making it easier to write
 | 
				
			||||||
 | 
					    int clientfd = clients[slot];
 | 
				
			||||||
 | 
					    dup2(clientfd, STDOUT_FILENO);
 | 
				
			||||||
 | 
					    close(clientfd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // call router
 | 
				
			||||||
 | 
					    route();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // tidy up
 | 
				
			||||||
 | 
					    fflush(stdout);
 | 
				
			||||||
 | 
					    shutdown(STDOUT_FILENO, SHUT_WR);
 | 
				
			||||||
 | 
					    close(STDOUT_FILENO);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  free(buf);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								server/httpd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								server/httpd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					#ifndef _HTTPD_H___
 | 
				
			||||||
 | 
					#define _HTTPD_H___
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Client request
 | 
				
			||||||
 | 
					extern char *method, // "GET" or "POST"
 | 
				
			||||||
 | 
					    *uri,            // "/index.html" things before '?'
 | 
				
			||||||
 | 
					    *qs,             // "a=1&b=2" things after  '?'
 | 
				
			||||||
 | 
					    *prot,           // "HTTP/1.1"
 | 
				
			||||||
 | 
					    *payload;        // for POST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int payload_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Server control functions
 | 
				
			||||||
 | 
					void serve_forever(const char *PORT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *request_header(const char *name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					  char *name, *value;
 | 
				
			||||||
 | 
					} header_t;
 | 
				
			||||||
 | 
					static header_t reqhdr[17] = {{"\0", "\0"}};
 | 
				
			||||||
 | 
					header_t *request_headers(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// user shall implement this function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void route();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Response
 | 
				
			||||||
 | 
					#define RESPONSE_PROTOCOL "HTTP/1.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define HTTP_200 printf("%s 200 OK\n\n", RESPONSE_PROTOCOL)
 | 
				
			||||||
 | 
					#define HTTP_201 printf("%s 201 Created\n\n", RESPONSE_PROTOCOL)
 | 
				
			||||||
 | 
					#define HTTP_404 printf("%s 404 Not found\n\n", RESPONSE_PROTOCOL)
 | 
				
			||||||
 | 
					#define HTTP_500 printf("%s 500 Internal Server Error\n\n", RESPONSE_PROTOCOL)
 | 
				
			||||||
 | 
					#define HTTP_301 printf("%s 301 Moved Permanently\n\n", RESPONSE_PROTOCOL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// some interesting macro for `route()`
 | 
				
			||||||
 | 
					#define ROUTE_START() if (0) {
 | 
				
			||||||
 | 
					#define ROUTE(METHOD, URI)                                                     \
 | 
				
			||||||
 | 
					  }                                                                            \
 | 
				
			||||||
 | 
					  else if (strcmp(URI, uri) == 0 && strcmp(METHOD, method) == 0) {
 | 
				
			||||||
 | 
					#define GET(URI) ROUTE("GET", URI)
 | 
				
			||||||
 | 
					#define POST(URI) ROUTE("POST", URI)
 | 
				
			||||||
 | 
					#define ROUTE_END()                                                            \
 | 
				
			||||||
 | 
					  }                                                                            \
 | 
				
			||||||
 | 
					  else HTTP_500;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										176
									
								
								server/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								server/main.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,176 @@
 | 
				
			|||||||
 | 
					#include "httpd.h"
 | 
				
			||||||
 | 
					#include <sys/stat.h>
 | 
				
			||||||
 | 
					#include <openssl/evp.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CHUNK_SIZE 1024 // read 1024 bytes at a time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Public directory settings
 | 
				
			||||||
 | 
					#define PUBLIC_DIR "./public"
 | 
				
			||||||
 | 
					#define INDEX_HTML "/index.html"
 | 
				
			||||||
 | 
					#define NOT_FOUND_HTML "/404.html"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					   char *key;
 | 
				
			||||||
 | 
					   char *value;
 | 
				
			||||||
 | 
					} KeyValuePair;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Function to create key-value pair
 | 
				
			||||||
 | 
					KeyValuePair* createKeyValuePair(const char *key, const char *value) {
 | 
				
			||||||
 | 
					    KeyValuePair *pair = malloc(sizeof(KeyValuePair));
 | 
				
			||||||
 | 
					    if (pair != NULL) {
 | 
				
			||||||
 | 
					        pair->key = strdup(key);
 | 
				
			||||||
 | 
					        pair->value = strdup(value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return pair;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Function to free memory occupied by a key-value pair
 | 
				
			||||||
 | 
					void freeKeyValuePair(KeyValuePair *pair) {
 | 
				
			||||||
 | 
					    if (pair != NULL) {
 | 
				
			||||||
 | 
					        free(pair->key);
 | 
				
			||||||
 | 
					        free(pair->value);
 | 
				
			||||||
 | 
					        free(pair);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sha512_hash_string(const char *input, char outputBuffer[129]) {
 | 
				
			||||||
 | 
					    EVP_MD_CTX *mdctx;
 | 
				
			||||||
 | 
					    const EVP_MD *md;
 | 
				
			||||||
 | 
					    unsigned char hash[EVP_MAX_MD_SIZE];
 | 
				
			||||||
 | 
					    unsigned int hashLen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    md = EVP_sha512();
 | 
				
			||||||
 | 
					    mdctx = EVP_MD_CTX_new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    EVP_DigestInit_ex(mdctx, md, NULL);
 | 
				
			||||||
 | 
					    EVP_DigestUpdate(mdctx, input, strlen(input));
 | 
				
			||||||
 | 
					    EVP_DigestFinal_ex(mdctx, hash, &hashLen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    EVP_MD_CTX_free(mdctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < hashLen; i++) {
 | 
				
			||||||
 | 
					        sprintf(&outputBuffer[i * 2], "%02x", hash[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    outputBuffer[hashLen * 2] = '\0';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void parsePasswordPostData(const char *postData) {
 | 
				
			||||||
 | 
					    char *dataCopy = strdup(postData);  // Make a copy to avoid modifying the original string
 | 
				
			||||||
 | 
					    char *token = strtok(dataCopy, "&");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (token != NULL) {
 | 
				
			||||||
 | 
					        char *keyValuePair = strdup(token);
 | 
				
			||||||
 | 
					        char *key = strtok(keyValuePair, "=");
 | 
				
			||||||
 | 
					        char *value = strtok(NULL, "=");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (key != NULL && value != NULL) {
 | 
				
			||||||
 | 
					            //printf("Key: %s, Value: %s\n", key, value);
 | 
				
			||||||
 | 
					            // Here, you can store or process the key and value as needed
 | 
				
			||||||
 | 
					            if(*key == 'p') {
 | 
				
			||||||
 | 
					                char localHashOutput[129];
 | 
				
			||||||
 | 
					                sha512_hash_string(value, localHashOutput);
 | 
				
			||||||
 | 
					                //printf("Hashed");
 | 
				
			||||||
 | 
					                printf("Input password is: %s\nHashed password is: %s\n", value, localHashOutput);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        free(keyValuePair);
 | 
				
			||||||
 | 
					        token = strtok(NULL, "&");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free(dataCopy);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int c, char **v) {
 | 
				
			||||||
 | 
					  char *port = c == 1 ? "8000" : v[1];
 | 
				
			||||||
 | 
					  serve_forever(port);
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int file_exists(const char *file_name) {
 | 
				
			||||||
 | 
					  struct stat buffer;
 | 
				
			||||||
 | 
					  int exists;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  exists = (stat(file_name, &buffer) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return exists;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int read_file(const char *file_name) {
 | 
				
			||||||
 | 
					  char buf[CHUNK_SIZE];
 | 
				
			||||||
 | 
					  FILE *file;
 | 
				
			||||||
 | 
					  size_t nread;
 | 
				
			||||||
 | 
					  int err = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  file = fopen(file_name, "r");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (file) {
 | 
				
			||||||
 | 
					    while ((nread = fread(buf, 1, sizeof buf, file)) > 0)
 | 
				
			||||||
 | 
					      fwrite(buf, 1, nread, stdout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    err = ferror(file);
 | 
				
			||||||
 | 
					    fclose(file);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void route() {
 | 
				
			||||||
 | 
					  ROUTE_START()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GET("/") {
 | 
				
			||||||
 | 
					    char index_html[20];
 | 
				
			||||||
 | 
					    sprintf(index_html, "%s%s", PUBLIC_DIR, INDEX_HTML);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    HTTP_200;
 | 
				
			||||||
 | 
					    if (file_exists(index_html)) {
 | 
				
			||||||
 | 
					      read_file(index_html);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      printf("Hello! You are using %s\n\n", request_header("User-Agent"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  POST("/hash") {
 | 
				
			||||||
 | 
					        HTTP_201;
 | 
				
			||||||
 | 
					        if(payload_size > 0){
 | 
				
			||||||
 | 
					           parsePasswordPostData(payload);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GET("/test") {
 | 
				
			||||||
 | 
					    HTTP_200;
 | 
				
			||||||
 | 
					    printf("List of request headers:\n\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    header_t *h = request_headers();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (h->name) {
 | 
				
			||||||
 | 
					      printf("%s: %s\n", h->name, h->value);
 | 
				
			||||||
 | 
					      h++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  POST("/") {
 | 
				
			||||||
 | 
					    HTTP_201;
 | 
				
			||||||
 | 
					    printf("Wow, seems that you POSTed %d bytes.\n", payload_size);
 | 
				
			||||||
 | 
					    printf("Fetch the data using `payload` variable.\n");
 | 
				
			||||||
 | 
					    if (payload_size > 0)
 | 
				
			||||||
 | 
					      printf("Request body: %s", payload);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GET(uri) {
 | 
				
			||||||
 | 
					    char file_name[255];
 | 
				
			||||||
 | 
					    sprintf(file_name, "%s%s", PUBLIC_DIR, uri);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (file_exists(file_name)) {
 | 
				
			||||||
 | 
					      HTTP_200;
 | 
				
			||||||
 | 
					      read_file(file_name);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      HTTP_404;
 | 
				
			||||||
 | 
					      sprintf(file_name, "%s%s", PUBLIC_DIR, NOT_FOUND_HTML);
 | 
				
			||||||
 | 
					      if (file_exists(file_name))
 | 
				
			||||||
 | 
					        read_file(file_name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ROUTE_END()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										61
									
								
								server/public/404.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								server/public/404.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					<!doctype html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					  <meta charset="utf-8">
 | 
				
			||||||
 | 
					  <title>Page Not Found</title>
 | 
				
			||||||
 | 
					  <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
				
			||||||
 | 
					  <style>
 | 
				
			||||||
 | 
					    * {
 | 
				
			||||||
 | 
					      line-height: 1.2;
 | 
				
			||||||
 | 
					      margin: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    html {
 | 
				
			||||||
 | 
					      color: #888;
 | 
				
			||||||
 | 
					      display: table;
 | 
				
			||||||
 | 
					      font-family: sans-serif;
 | 
				
			||||||
 | 
					      height: 100%;
 | 
				
			||||||
 | 
					      text-align: center;
 | 
				
			||||||
 | 
					      width: 100%;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    body {
 | 
				
			||||||
 | 
					      display: table-cell;
 | 
				
			||||||
 | 
					      vertical-align: middle;
 | 
				
			||||||
 | 
					      margin: 2em auto;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    h1 {
 | 
				
			||||||
 | 
					      color: #555;
 | 
				
			||||||
 | 
					      font-size: 2em;
 | 
				
			||||||
 | 
					      font-weight: 400;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    p {
 | 
				
			||||||
 | 
					      margin: 0 auto;
 | 
				
			||||||
 | 
					      width: 280px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @media only screen and (max-width: 280px) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      body,
 | 
				
			||||||
 | 
					      p {
 | 
				
			||||||
 | 
					        width: 95%;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      h1 {
 | 
				
			||||||
 | 
					        font-size: 1.5em;
 | 
				
			||||||
 | 
					        margin: 0 0 0.3em;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  </style>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					  <h1>Page Not Found</h1>
 | 
				
			||||||
 | 
					  <p>Sorry, but the page you were trying to view does not exist.</p>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										16
									
								
								server/public/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								server/public/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					<!doctype html>
 | 
				
			||||||
 | 
					<html lang="">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					  <meta charset="utf-8">
 | 
				
			||||||
 | 
					  <title>Pico HTTP server</title>
 | 
				
			||||||
 | 
					  <meta name="description" content="This is a very simple HTTP server for Unix, using fork(). It's very easy to use.">
 | 
				
			||||||
 | 
					  <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					  <h1>Hello world!</h1>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										5
									
								
								server/public/robots.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								server/public/robots.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					# www.robotstxt.org/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Allow crawling of all content
 | 
				
			||||||
 | 
					User-agent: *
 | 
				
			||||||
 | 
					Disallow:
 | 
				
			||||||
		Reference in New Issue
	
	Block a user