Advertisement
Python253

localhost

May 16th, 2024 (edited)
1,354
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.06 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Filename: localhost.py
  4. # Version: 1.0.2
  5. # Author: Jeoi Reqi
  6.  
  7. """
  8. This script implements a simple HTTP server that serves files from the current directory and provides a directory listing API.
  9. It also includes functionality to terminate any process using a specified port, in this case, port 8080.
  10.  
  11. Functions:
  12.    - Serv(BaseHTTPRequestHandler):
  13.        Defines a custom handler for handling HTTP requests.
  14.    - list_files(self):
  15.        Lists all files in the current directory.
  16.    - do_GET(self):
  17.        Handles GET requests, serving files or providing a directory listing based on the requested path.
  18.    - line():
  19.        Prints a line of underscores for formatting.
  20.    - get_pid_on_port(port):
  21.        Retrieves the process ID (PID) of any process using a specified port.
  22.    - kill_process(pid):
  23.        Terminates a process with a specified PID.
  24.    - run_server():
  25.        Starts the HTTP server.
  26.    - shutdown_server(server_thread):
  27.        Shuts down the HTTP server.
  28.  
  29. Requirements:
  30.    - Python 3.x
  31.    - colorama library (for colored output)
  32.  
  33. Usage:
  34.    - Run the script. It will start an HTTP server listening on port 8080.
  35.    - Access http://localhost:8080/ in a web browser to view the directory listing.
  36.    - Access http://localhost:8080/api/directory to retrieve a JSON response containing the directory listing.
  37.    - Press Ctrl+C to interrupt the script and stop the server.
  38.    - After interrupting the script, it will attempt to terminate any process using port 8080.
  39.  
  40. Additional Notes:
  41.    - This script is intended for educational purposes and may require modifications for production use.
  42.    - Ensure that no other process is using port 8080 before running the script.
  43.    - Colorama library is used to print colored output for better visualization.
  44. """
  45.  
  46. # Get Essential Imports
  47. from http.server import HTTPServer, BaseHTTPRequestHandler
  48. import os
  49. import subprocess
  50. import json
  51. import re
  52. import sys
  53. import threading
  54. from colorama import Fore, Style # For Colored Terminal Output
  55.  
  56. # Print Header
  57. print("""
  58. █████╗  ██████╗  █████╗  ██████╗
  59. ██╔══██╗██╔═████╗██╔══██╗██╔═████╗
  60. ╚█████╔╝██║██╔██║╚█████╔╝██║██╔██║
  61. ██╔══██╗████╔╝██║██╔══██╗████╔╝██║
  62. ╚█████╔╝╚██████╔╝╚█████╔╝╚██████╔╝
  63. ╚════╝  ╚═════╝  ╚════╝  ╚═════╝
  64. """)
  65.  
  66. # Class for custom HTTP request handler
  67. class Serv(BaseHTTPRequestHandler):
  68.     """
  69.    Custom HTTP request handler.
  70.    """
  71.     def list_files(self):
  72.         """
  73.        Lists all files in the current directory.
  74.  
  75.        Returns:
  76.            list: A list of dictionaries containing file information.
  77.        """
  78.         files = os.listdir(".")
  79.         file_list = []
  80.         for file in files:
  81.             file_info = {}
  82.             if os.path.isfile(file):
  83.                 file_info["name"] = file
  84.                 file_info["path"] = file
  85.             elif os.path.isdir(file):
  86.                 file_info["name"] = file + "/"
  87.                 file_info["path"] = file + "/"
  88.             file_list.append(file_info)
  89.         return file_list
  90.  
  91.     def do_GET(self):
  92.         """
  93.        Handles GET requests.
  94.  
  95.        If the path is '/', it serves an HTML page with a directory listing.
  96.        If the path is '/api/directory', it provides a JSON response with the directory listing.
  97.        Otherwise, it attempts to serve the requested file.
  98.        """
  99.         print("Request received for:", self.path)
  100.         if self.path == "/":
  101.             index_html = """
  102.            <!DOCTYPE html>
  103.            <html lang="en">
  104.            <head>
  105.                <meta charset="UTF-8">
  106.                <meta name="viewport" content="width=device-width, initial-scale=1.0">
  107.                <title>Directory Listing</title>
  108.            </head>
  109.            <body>
  110.                <h1>Directory Listing</h1>
  111.                <ul id="fileList">
  112.                    <!-- File and directory list will be generated here -->
  113.                </ul>
  114.  
  115.                <script>
  116.                    // Fetch directory listing
  117.                    fetch('/api/directory')
  118.                        .then(response => response.json())
  119.                        .then(data => {
  120.                            const fileList = document.getElementById('fileList');
  121.                            data.forEach(item => {
  122.                                const listItem = document.createElement('li');
  123.                                const link = document.createElement('a');
  124.                                link.textContent = item.name;
  125.                                link.href = item.path;
  126.                                listItem.appendChild(link);
  127.                                fileList.appendChild(listItem);
  128.                            });
  129.                        })
  130.                        .catch(error => {
  131.                            console.error('Error fetching directory listing:', error);
  132.                        });
  133.                </script>
  134.            </body>
  135.            </html>
  136.            """
  137.             self.send_response(200)
  138.             self.send_header("Content-type", "text/html")
  139.             self.end_headers()
  140.             self.wfile.write(index_html.encode())
  141.         elif self.path == "/api/directory":
  142.             file_list = self.list_files()
  143.             self.send_response(200)
  144.             self.send_header("Content-type", "application/json")
  145.             self.end_headers()
  146.             self.wfile.write(json.dumps(file_list).encode())
  147.         else:
  148.             try:
  149.                 file_to_open = open(self.path[1:], "rb").read()
  150.                 self.send_response(200)
  151.                 self.end_headers()
  152.                 self.wfile.write(file_to_open)
  153.             except FileNotFoundError:
  154.                 file_to_open = b"File not found"
  155.                 self.send_response(404)
  156.                 self.end_headers()
  157.                 self.wfile.write(file_to_open)
  158.  
  159. # Function to draw divider lines
  160. def line():
  161.     print("_" * 70 + "\n")
  162.  
  163. # Function to get port PIDs
  164. def get_pid_on_port(port):
  165.     result = subprocess.run(["netstat", "-ano"], capture_output=True, text=True)
  166.     lines = result.stdout.splitlines()
  167.     port_re = re.compile(rf"TCP\s+\S+:{port}\s+\S+\s+LISTENING\s+(\d+)")
  168.     for line in lines:
  169.         match = port_re.search(line)
  170.         if match:
  171.             return match.group(1)
  172.     return None
  173.  
  174. # Function to kill all proceses on given port (8080)
  175. def kill_process(pid):
  176.     subprocess.run(["taskkill", "/F", "/PID", pid])
  177.  
  178. # Run the localhost:8080 server
  179. def run_server():
  180.     httpd = HTTPServer(("localhost", 8080), Serv)
  181.     print("Server started on http://localhost:8080/\n")
  182.     httpd.serve_forever()
  183.     httpd.server_close()
  184.  
  185. # Shut down the localhost:8080 server
  186. def shutdown_server(server_thread):
  187.     print("\n\t  Shutting down server... Server shutdown complete!")
  188.     server_thread.join()
  189.     sys.stdout.flush()
  190.  
  191. if __name__ == "__main__":
  192.     server_thread = threading.Thread(target=run_server)
  193.     server_thread.start()
  194.  
  195.     try:
  196.         while server_thread.is_alive():
  197.             server_thread.join(1)
  198.             sys.stdout.flush()
  199.     except KeyboardInterrupt:
  200.         line()
  201.         print("\t\t    Keyboard interrupt received!")
  202.         sys.stdout.flush()
  203.         shutdown_server(server_thread)
  204.  
  205.         # Ensure any process using port 8080 is terminated
  206.         pid = get_pid_on_port(8080)
  207.         if pid:
  208.             print(
  209.                 f"\n\t    - {Fore.RED}Terminating process {pid} using port 8080{Style.RESET_ALL} -\n\n\tVerify cleanup completed with the terminal command:\n\n\t\t   {Fore.GREEN}!netstat -ano | findstr :8080{Style.RESET_ALL}"
  210.             )
  211.             line()
  212.             sys.stdout.flush()
  213.             kill_process(pid)
  214.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement