
    5iR7                        d Z ddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
mZ ddlmZmZ ddlmZmZ  G d d          Z G d d	e          Z	 	 	 ddZ	 	 	 ddZd Zedk    r e             dS dS )a  
File Download Server Example

This example demonstrates how to create a secure file download server using the 
HTTPServerHandler class. The server allows:
- Listing files in a specified directory
- Downloading individual files
- Protection against directory traversal attacks

Usage:
    python fileserver.py [directory_path] [host] [port]

Example:
    python fileserver.py ./downloads 127.0.0.1 8080
    N)Path)	UniTargetUniProto)HTTPServerHandler
HTTPServerc                   n    e Zd ZdZ	 	 ddZddZd	 Zd
 Zd Zd Z	d Z
d Zd Zd Zd Zd Zd Zd ZdS )MultipartStreamProcessorz
    Memory-efficient multipart form data processor that handles boundary detection
    across chunk boundaries and streams file data directly to disk.
         @Nd   c                    || _         || _        || _        || _        || _        || _        d| _        d| _        d | _        d | _	        g | _
        g | _        d| _        d| j         z   | _        | j         dz   | _        || _        d S )N    looking_for_boundaryr      
s   --)boundary_bytestarget_pathmax_buffer_sizemax_file_sizeallowed_extensionsmax_files_per_requestbufferstatecurrent_file_infocurrent_file_handle
temp_filescompleted_files
file_countboundary_with_crlfend_boundaryprint_cb)selfr   r   r   r   r   r   r    s           R/home/kali/Ninja/venv/lib/python3.11/site-packages/asysocks/examples/fileserver.py__init__z!MultipartStreamProcessor.__init__%   s    ,&.*"4%:" +
!%#' ! #*D,?"? /%7 r    c                 R   K   | j         d S |                      |           d {V  d S Nr    r!   msgs     r"   printzMultipartStreamProcessor.print<   =      = FmmC           r   c                   K   | xj         |z  c_         g }t          | j                   | j        k    rk| j        dk    r|                                  d{V  nEt          | j                   | j        dz  k    r%t          dt          | j                    d          	 | j        dk    r:|                    |                                  d{V            | j        dk    rnqno| j        dk    r|                                  d{V snJnH| j        dk    r=| 	                                 d{V }|r|
                    |           | j        dk    rn|S )	z
        Process a chunk of data, returning any completed file info.
        
        Args:
            chunk (bytes): Raw chunk data
            
        Returns:
            list: List of completed file info dictionaries
        reading_file_dataN   zBuffer size exceeded:  bytesTr   reading_headers)r   lenr   r   _flush_file_data
ValueErrorextend_process_boundary_search_process_headers_process_file_dataappend)r!   chunkr   	file_infos       r"   process_chunkz&MultipartStreamProcessor.process_chunkA   s      	u t{d222z000++----------T[!!D$81$<<< !R#dk:J:J!R!R!RSSS	z333&&T-J-J-L-L'L'L'L'L'L'LMMM:!777 8 000!2244444444  222"&"9"9";";;;;;;;	 6#**9555:!444	" r   c                   K   g }| j                             | j                  }|dk    r[t          | j                   t          | j                  dz  k    r,t          | j                  dz   }| j         | d         | _         |S | j         ||t          | j                  z            | j        k    rD|                                  d{V  | j        r!|                    | j                   d| _        |S |t          | j                  z   }| j         |d         | _         | j                             d          r| j         dd         | _         n.| j                             d          r| j         dd         | _         d| _	        |S )	z*Search for boundary markers in the buffer.r.   
   Nr      
   r0   )
r   findr   r1   r   _finalize_current_filer   r8   
startswithr   )r!   r   boundary_pos	keep_sizeboundary_ends        r"   r5   z1MultipartStreamProcessor._process_boundary_searchi   s      {''(;<<2 4;#d&9":":Q">>> 344r9	"k9*++6"" ;|L3t7H3I3I$IIJdN___--/////////% .&&t'=>>>)-&"" $c$*=&>&>>k,--0 ;!!'** 	*+abb/DKK[##E** 	*+abb/DK&
r   c                 :  K   | j                             d          }|dk    rp| j                             d          }|dk    r)t          | j                   dk    rt          d          dS | j         d|         }| j         |dz   d         | _         n&| j         d|         }| j         |d	z   d         | _         t          |          d
k    rt          d          	 |                    dd          }n$# t
          $ r}t          d|           d}~ww xY w|                     |          }|re| j        r|                                  d{V  | 	                    |          }|st          d|           | 
                    |           d{V  d| _        dS )zProcess multipart headers.s   

r=   s   

i    zCMultipart headers too long or malformed (missing header terminator)FNr.      i   zMultipart part headers too longutf-8strict)errorszInvalid header encoding: zInvalid or unsafe filename: r-   T)r   rA   r1   r3   decodeUnicodeDecodeError_extract_filename_from_headersr   rB   _sanitize_upload_filename_start_new_filer   )r!   
header_endheader_sectionheaders_textefilenamesafe_filenames          r"   r6   z)MultipartStreamProcessor._process_headers   s      [%%k22
))'22JRt{##d**$%jkkku![*5N+j1noo6DKK![*5N+j1noo6DK ~%%>???	>)000JJLL! 	> 	> 	><<<===	> 66|DD 		6% 411333333333 !::8DDM  L !J!J!JKKK&&}555555555(
ts   C4 4
D>DDc                 d  K   | j         s	d| _        dS | j                            | j                  }|dk    rt          | j                  t          | j                  dz   k    rjt          | j                  t          | j                  z
  dz
  }| j        d|         }| j        |d         | _        |                     |           d{V  dS | j        d|         }| j        |d         | _        |                     |           d{V  |                                  d{V }d| _        |S )z1Process file data, looking for the next boundary.r   Nr=   r>   )r   r   r   rA   r   r1   _write_file_datarB   )r!   next_boundary_pos
write_sizedata_to_writer:   s        r"   r7   z+MultipartStreamProcessor._process_file_data   s[     ' 	/DJ4 !K,,T-DEE"" 4;#d&=">">"CCC --D4K0L0LLrQ
 $KZK 8"k*++6++M:::::::::4 !K(:):(:;M+&7&8&89DK''666666666"99;;;;;;;;I/DJr   c                    |                     d          D ]}|                                }|                                                    d          rrt	          j        d|t          j                  }|r|                    d          c S t	          j        d|t          j                  }|r|                    d          c S dS )z1Extract filename from Content-Disposition header.
zcontent-disposition:zfilename="([^"]*)"r@   zfilename=([^;\s]+)N)splitstriplowerrC   research
IGNORECASEgroup)r!   rS   linefilename_matchs       r"   rN   z7MultipartStreamProcessor._extract_filename_from_headers   s     &&t,, 
	3 
	3D::<<Dzz||&&'=>> 3!#+@$!V!V! 3)//22222!#+@$!V!V! 3)//22222tr   c                    |sdS t           j                            |          }t          j        dd|          }t          j        dd|          }t          j        dd|          }|                    d          }|r|dv rdS t          |          d	k    r7t           j                            |          \  }}|dd
         |dd         z   }|S )z^
        Sanitize uploaded filename to prevent directory traversal and other attacks.
        Nz	[<>:"|?*]_z
[^\w\-_\.]z\.\.+.z._)ri   ..         )ospathbasenamera   subr_   r1   splitext)r!   rU   	safe_name	name_partext_parts        r"   rO   z2MultipartStreamProcessor._sanitize_upload_filename   s      	4 G$$X..	 F<i88	F=#y99	F8S)44	OOD))	  	I444 y>>C"$'"2"29"="=Ix!$3$(2A2,6Ir   c                   K   | j         | j        k    rt          d| j         d          | j        rmt          j                            |          d                                         }|| j        vr-t          d| dd                    | j                             t          j                            | j	        |          }|dz   }	 t          |d          | _        | j                            |           nI# t          $ r}t          d	| d
|           d}~wt          $ r}t          d| d
|           d}~ww xY w|||dd| _        | xj         dz  c_         dS )zStart writing a new file.zToo many files in upload (max: )r@   zFile extension 'z' not allowed. Allowed: , z
.uploadingwbzCannot create upload file '': Nz(Permission denied creating upload file 'r   )rU   	temp_path
final_pathsize)r   r   r3   r   rn   ro   rr   r`   joinr   openr   r   r8   OSErrorPermissionErrorr   )r!   rU   file_ext	file_pathtemp_file_pathrT   s         r"   rP   z(MultipartStreamProcessor._start_new_file  s      ?d888\t?Y\\\]]] " 	|w''11!4::<<Ht666 !zH!z!zVZV_V_`d`wVxVx!z!z{{{GLL!18<<	 #\1	]'+ND'A'AD$O"">2222 	P 	P 	PNNN1NNOOO 	] 	] 	][^[[XY[[\\\	] !'#	"
 "
 	1s$   
/C: :
E DE &D;;E c           	        K   | j         r|r| j        d         t          |          z   }|| j        k    r)t	          d| j        d          d| d| j         d          	 | j                             |           | j        dxx         t          |          z  cc<   d	S # t          $ r%}t          d| j        d          d|           d	}~wt          $ r%}t          d
| j        d          d|           d	}~ww xY wd	S d	S )zWrite data to current file.r}   zFile 'rU   z' exceeds size limit:  bytes (max: rw   zError writing to file 'rz   NzUnexpected error writing file ')r   r   r1   r   r3   writer   	Exception)r!   datanew_sizerT   s       r"   rX   z)MultipartStreamProcessor._write_file_data"  s     # 	l 	l-f5D		AH$,,,   "Q$*@*L  "Q  "Qdl  "Q  "Q{  |N  "Q  "Q  "Q  R  R  Rl(..t444&v...#d));..... d d db8Nz8Zbb_`bbccc l l lj@VWa@bjjghjjkkkl	l 	l 	l 	ls$   <B 
C8& CC8 C33C8c                 N   K   | j         r| j                                          dS dS )z'Flush file data to reduce memory usage.N)r   flush)r!   s    r"   r2   z)MultipartStreamProcessor._flush_file_data2  s6      # 	-$**,,,,,	- 	-r   c                   K   | j         sdS | j        rY| j                                         d| _        | j         d         }| j         d         }	 t          j        ||           || j        v r| j                            |           | j         d         | j         d         |d}|                     d|d          d|d         d	d
           d{V  | j        	                    |           d| _         |S # t          $ rk}|                     d| d|            d{V  	 t          j        |           || j        v r| j                            |           n#  Y nxY wY d}~nd}~ww xY wd| _         dS )z.Finalize the current file and return its info.Nr{   r|   rU   r}   )rU   r}   ro   z[UPLOAD-SUCCESS] Uploaded: z (, bytes)z%[UPLOAD-ERROR] Error finalizing file : )r   r   closern   renamer   remover*   r   r8   r   unlink)r!   r{   r|   r:   rT   s        r"   rB   z/MultipartStreamProcessor._finalize_current_file7  s     % 	4# !	$**,,,'+D$ .{;I/=J	)Z000//O**9555 !% 6z B 26:& 	 jj!ty?T!t!tXabhXi!t!t!t!tuuuuuuuuu$++I666)-&     jj!Z!Z!ZWX!Z!Z[[[[[[[[[Ii((( DO33..y999D "&ts1   B%C5 5
E*?!E%!7EE%EE%%E*c                   K   g }| j         r| j        dk    r| j        dk    r|                                  d{V snnr| j        dk    rg| j        r.| j         r'|                     | j                    d{V  d| _         |                                  d{V }|r|                    |           n| j         r| j        dk    |S )zFinalize any remaining data.r   r0   Nr-   r   )r   r   r6   r   rX   rB   r8   )r!   r   r:   s      r"   finalizez!MultipartStreamProcessor.finalizeb  s      k 	dj,BBBz...!2244444444 222+ & &//<<<<<<<<<"%DK"&"="="?"???????	 6#**9555 k 	dj,BBB r   c                   K   | j         r)	 | j                                          n#  Y nxY wd| _         | j        D ]}	 t          j                            |          r2t          j        |           |                     d|            d{V  U# t          $ r+}|                     d| d|            d{V  Y d}~d}~ww xY w| j        	                                 dS )zClean up any temporary files.Nz$[UPLOAD-CLEANUP] Removed temp file: z*[UPLOAD-CLEANUP] Error removing temp file r   )
r   r   r   rn   ro   existsr   r*   r   clear)r!   r{   rT   s      r"   cleanupz MultipartStreamProcessor.cleanupw  s6     # 	,(..0000'+D$ 	` 	`I`7>>),, YIi(((**%WI%W%WXXXXXXXXX ` ` `jj!^i!^!^[\!^!^______________` 	s    % )AB
C!B??C)r
   r   Nr   Nr$   )__name__
__module____qualname____doc__r#   r*   r;   r5   r6   r7   rN   rO   rP   rX   r2   rB   r   r    r   r"   r	   r	      s        
 ENmq! ! ! !.! ! ! !
& & &P# # #J* * *X  <    6  @l l l - - -
) ) )V  *         r   r	   c                        e Zd ZdZ	 	 d fd	ZddZd	 Zdd
Zd Zd Z	d Z
d ZddZd Zd Zd Zd ZddZddZd Z xZS )FileDownloadHandlera0  
    HTTP server handler that provides secure file download functionality.
    
    Features:
    - File listing for GET requests without parameters
    - File download for GET requests with 'file' parameter
    - Directory traversal protection
    - MIME type detection
    - HTML directory listing
    N        r   r   c                    t                                                       || _        || _        || _        || _        || _        || _        | j        rt          j	        
                    | j                  | _        t          j	                            | j                  st          d| j                   t          j	                            | j                  st          d| j                   dS dS )a  
        Initialize the file download handler.
        
        Args:
            download_directory (str): Directory to serve files from
            max_upload_size (int): Maximum total upload size per request in bytes (default: 2GB)
            max_file_size (int): Maximum individual file size in bytes (default: 500MB)
            allowed_extensions (set): Set of allowed file extensions (None = allow all)
            max_files_per_request (int): Maximum number of files per upload request (default: 100)
        z#Download directory does not exist: z"Download path is not a directory: N)superr#   download_directorymax_upload_sizer   r   r   r    rn   ro   abspathr   r3   isdir)r!   r   r   r   r   r   r    	__class__s          r"   r#   zFileDownloadHandler.__init__  s     	"4.*"4%:" " 	a&(good6M&N&ND#7>>$"9:: b !`tG^!`!`aaa7==!899 a !_dF]!_!_```	a 	a
a ar   r$   c                 R   K   | j         d S |                      |           d {V  d S r&   r'   r(   s     r"   r*   zFileDownloadHandler.print  r+   r   c                 n   | j         sdS |s| j         S |                    dd          }g }|                    d          D ]Y                                rdk    rdk    r&t	          fddD                       r dS |                               Z|s| j         S | j         }|D ]"t          j                            |          }#t          j        	                    |          }	 t          j        
                    || j         g          }|| j         k    rdS n# t          $ r Y dS w xY w|S )aW  
        Sanitize the requested path to prevent directory traversal attacks while allowing
        safe navigation within the allowed directory tree.
        
        Args:
            path_request (str): The requested file or directory path
            
        Returns:
            str or None: Safe absolute path or None if invalid
        N\/ri   rj   c              3       K   | ]}|v V  	d S r&   r   ).0char	components     r"   	<genexpr>z5FileDownloadHandler._sanitize_path.<locals>.<genexpr>  s(      UU49$UUUUUUr   ):*?"<>|)r   replacer^   r_   anyr8   rn   ro   r~   r   
commonpathr3   )r!   path_requestnormalized_pathpath_components	safe_pathcommon_pathr   s         @r"   _sanitize_pathz"FileDownloadHandler._sanitize_path  s    & 	4 	+** '..tS99 (..s33 	. 	.I!))I 	S 0 0D  UUUU1TUUUUU tt""9----  	+**+	( 	; 	;IY	::IIGOOI..		',,i9P-QRRKd555t 6 	 	 	44	 s   01D$ $
D21D2c                 >	   | j         sdS || j         }	 || j         k    rd}d}nHdt          j                            || j                                       t          j        d          z   }|}g }g }t          j        |          D ]}t          j                            ||          }t          j                            |          r7t          j        	                    |          }|
                    ||f           xt          j                            |          r|
                    |           |                                 |                                 t          j        |          }	t          j        |          }
|                     |          }d|z   dz   }|| j         k    rdt          j                            |                    d                    }|dk    rd}t$          j                            |          }|d|z   d	z   z  }|dk    r2t$          j                            |                    d                    nd}|rd
| nd}d}|d| dz  }|D ]h}t          j        |          }|dk    r|}n|                    d          dz   |z   }t$          j                            |          }|d| d| d| dz  }i|D ]\  }}t          j        |          }|dk    r|}n|                    d          dz   |z   }t$          j                            |          }|                     |          }t          j                            |          d                                         }|dv rd}n%|dv rd}n|dv rd}n|dv rd}n|dv rd}n	|dv rd}nd}|d| d | d!| d"| d#| d$z  }t3          |          t3          |          z   }|d                    g d%t3          |           d&t3          |           d'| d(|
 d)| d| d*| d| d+| d| d,| d| d-| d| d.| d| d/| d| d0          z  }|S # t4          $ r1}t7          |          }d1t          j        |           d2cY d}~S d}~ww xY w)3z
        Generate an HTML page listing files and directories.
        
        Args:
            current_path (str): The current directory path to list
            
        Returns:
            str: HTML content
        zV<html><body><h1>File Server</h1><p>No download directory configured.</p></body></html>Nr   zRoot Directoryu$  <!DOCTYPE html>
<html>
<head>
    <title>📁 File Server - Directory Browser</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        :root {
            --primary: #2563eb;
            --primary-dark: #1d4ed8;
            --primary-light: #3b82f6;
            --secondary: #64748b;
            --secondary-light: #94a3b8;
            --success: #059669;
            --success-light: #10b981;
            --warning: #d97706;
            --warning-light: #f59e0b;
            --background: #f8fafc;
            --surface: #ffffff;
            --surface-2: #f1f5f9;
            --text: #1e293b;
            --text-muted: #64748b;
            --border: #e2e8f0;
            --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
        }
        
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: 'Inter', 'Segoe UI', system-ui, sans-serif;
            background: var(--background);
            color: var(--text);
            min-height: 100vh;
            padding: 20px;
            line-height: 1.6;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: var(--surface);
            border-radius: 12px;
            box-shadow: var(--shadow);
            overflow: hidden;
            animation: slideIn 0.5s ease-out;
        }
        @keyframes slideIn {
            from { opacity: 0; transform: translateY(20px); }
            to { opacity: 1; transform: translateY(0); }
        }
        .header {
            background: var(--primary);
            color: white;
            padding: 32px;
            text-align: center;
        }
        .header h1 {
            font-size: 2.5rem;
            font-weight: 700;
            margin-bottom: 8px;
        }
        .header p {
            opacity: 0.9;
            font-size: 1.1rem;
        }
        .breadcrumb {
            background: var(--surface-2);
            padding: 16px 32px;
            border-bottom: 1px solid var(--border);
            font-size: 1rem;
            font-weight: 500;
        }
        .content {
            padding: 32px;
        }
        .section {
            margin-bottom: 32px;
            padding: 24px;
            border-radius: 8px;
            border: 1px solid var(--border);
            background: var(--surface);
        }
        .upload-section {
            background: #f0fdf4;
            border: 2px dashed var(--success);
            transition: all 0.3s ease;
        }
        .upload-section:hover {
            background: #ecfdf5;
            border-color: var(--success-light);
        }
        .commands-section {
            background: #fefce8;
            border: 1px solid var(--warning);
        }
        .section h3 {
            color: var(--text);
            margin-bottom: 16px;
            font-weight: 600;
            font-size: 1.25rem;
        }
        .btn {
            background: var(--primary);
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: all 0.2s ease;
            text-decoration: none;
            display: inline-block;
        }
        .btn:hover {
            background: var(--primary-dark);
            transform: translateY(-1px);
            box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
        }
        .btn-upload {
            background: var(--success);
            font-size: 16px;
            padding: 16px 32px;
            border-radius: 8px;
        }
        .btn-upload:hover {
            background: var(--success-light);
            box-shadow: 0 4px 12px rgba(5, 150, 105, 0.3);
        }
        .file-input {
            padding: 12px;
            border: 2px solid var(--border);
            border-radius: 6px;
            width: 100%;
            margin-bottom: 16px;
            transition: border-color 0.2s ease;
            font-size: 14px;
        }
        .file-input:focus {
            border-color: var(--primary);
            outline: none;
            box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
        }
        .progress-container {
            display: none;
            margin-top: 16px;
            background: var(--surface-2);
            border-radius: 8px;
            padding: 16px;
        }
        .progress-bar {
            width: 100%;
            height: 8px;
            background: var(--border);
            border-radius: 4px;
            overflow: hidden;
            margin-bottom: 8px;
        }
        .progress-fill {
            height: 100%;
            background: var(--primary);
            width: 0%;
            transition: width 0.3s ease;
            border-radius: 4px;
        }
        .command-box {
            background: #0f172a;
            color: #e2e8f0;
            padding: 16px;
            border-radius: 6px;
            font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
            font-size: 13px;
            margin: 12px 0;
            position: relative;
            overflow-x: auto;
            border: 1px solid #334155;
        }
        .command-box pre {
            margin: 0;
            padding: 0;
            background: transparent;
            color: inherit;
            font-family: inherit;
            font-size: inherit;
            line-height: 1.5;
            white-space: pre-wrap;
            word-wrap: break-word;
        }
        .copy-btn {
            position: absolute;
            top: 12px;
            right: 12px;
            background: var(--secondary);
            color: white;
            border: none;
            padding: 6px 12px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 11px;
            transition: background 0.2s;
        }
        .copy-btn:hover { 
            background: var(--secondary-light); 
        }
        .table-container {
            overflow-x: auto;
            border-radius: 8px;
            border: 1px solid var(--border);
        }
        table {
            width: 100%;
            border-collapse: collapse;
            background: var(--surface);
        }
        th {
            background: var(--surface-2);
            color: var(--text);
            padding: 16px;
            text-align: left;
            font-weight: 600;
            font-size: 14px;
            border-bottom: 1px solid var(--border);
        }
        td {
            padding: 12px 16px;
            border-bottom: 1px solid var(--border);
            transition: background-color 0.2s ease;
        }
        tr:hover td {
            background-color: var(--surface-2);
        }
        .file-link {
            color: var(--primary);
            text-decoration: none;
            font-weight: 500;
            transition: color 0.2s ease;
        }
        .file-link:hover {
            color: var(--primary-dark);
        }
        .stats {
            background: var(--surface-2);
            padding: 24px;
            border-radius: 8px;
            text-align: center;
            margin-top: 24px;
            border: 1px solid var(--border);
        }
        .stats h3 {
            color: var(--text);
            margin-bottom: 20px;
        }
        .stat-item {
            text-align: center;
            margin: 12px;
        }
        .stat-number {
            font-size: 2rem;
            font-weight: 700;
            margin-bottom: 4px;
        }
        .stat-label {
            font-size: 14px;
            color: var(--text-muted);
            font-weight: 500;
        }
        .tab-container {
            margin-bottom: 20px;
        }
        .tab-buttons {
            display: flex;
            background: var(--surface-2);
            border-radius: 6px;
            padding: 4px;
            margin-bottom: 16px;
        }
        .tab-btn {
            flex: 1;
            padding: 10px 16px;
            border: none;
            background: transparent;
            cursor: pointer;
            border-radius: 4px;
            transition: all 0.2s ease;
            font-weight: 500;
            font-size: 14px;
            color: var(--text-muted);
        }
        .tab-btn.active {
            background: var(--surface);
            color: var(--text);
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
        }
        .tab-content {
            display: none;
        }
        .tab-content.active {
            display: block;
        }
        .badge {
            padding: 4px 8px;
            border-radius: 12px;
            font-size: 12px;
            font-weight: 500;
        }
        .badge-directory {
            background: #dbeafe;
            color: #1e40af;
        }
        .badge-file {
            background: #f3e8ff;
            color: #7c3aed;
        }
        @media (max-width: 768px) {
            .container { margin: 10px; }
            .content { padding: 20px; }
            .header { padding: 24px; }
            .header h1 { font-size: 2rem; }
            .stats > div { flex-direction: column; }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="breadcrumb">
            <strong>📍 Current Location:</strong> z.
        </div>
        <div class="content">
r$   z@            <div class="section">
                <a href="?dir=u   " class="btn" style="text-decoration: none; display: inline-block;">
                    ⬆️ Back to Parent Directory
                </a>
            </div>
z?dir=zhttp://YOUR_SERVER_IP:8080u   
            <div class="section upload-section">
                <h3>📤 Upload Files</h3>
                <form id="uploadForm" method="post" enctype="multipart/form-data" action="u;  ">
                    <input type="file" name="files" multiple accept="*/*" class="file-input" id="fileInput">
                    <button type="submit" class="btn btn-upload">🚀 Upload Files</button>
                    <div class="progress-container" id="progressContainer">
                        <div class="progress-bar">
                            <div class="progress-fill" id="progressFill"></div>
                        </div>
                        <div id="progressText">Uploading... 0%</div>
                    </div>
                </form>
                <div style="margin-top: 15px; font-size: 14px; color: #2d5a27;">
                    💡 Drag and drop files or click to browse. Multiple files supported. Large files streamed efficiently.
                </div>
            </div>

            <div class="section">
                <h3>📂 Directory Contents</h3>
                <div class="table-container">
                    <table>
                        <thead>
                            <tr>
                                <th>📋 Name</th>
                                <th>📁 Type</th>
                                <th>📏 Size</th>
                                <th>🕒 Actions</th>
                            </tr>
                        </thead>
                        <tbody>
zS                            <tr>
                                <td><a href="?dir=u   " class="file-link">📁 z</a></td>
                                <td><span class="badge badge-directory">Directory</span></td>
                                <td style="text-align: right;">-</td>
                                <td><a href="?dir=z" class="btn" style="padding: 6px 12px; font-size: 12px; text-decoration: none;">Browse</a></td>
                            </tr>
r@   )z.jpgz.jpegz.pngz.gifz.bmpu   🖼️)z.mp4z.aviz.mkvz.movu   🎬)z.mp3z.wavz.flacz.oggu   🎵)z.pdfu   📕)z.txtz.mdu   📄)z.zipz.rarz.7zz.tarz.gzu   📦zT                            <tr>
                                <td><a href="?file=z" class="file-link"> z</a></td>
                                <td><span class="badge badge-file">File</span></td>
                                <td style="text-align: right;">z9</td>
                                <td><a href="?file=z" class="btn" style="padding: 6px 12px; font-size: 12px; text-decoration: none;">Download</a></td>
                            </tr>
u                          </tbody>
                    </table>
                </div>
            </div>
            
            <div class="stats">
                <h3>📊 Directory Statistics</h3>
                <div style="display: flex; justify-content: space-around; flex-wrap: wrap; margin-top: 16px;">
                    <div class="stat-item">
                        <div class="stat-number" style="color: var(--success);">u   </div>
                        <div class="stat-label">📁 Directories</div>
                    </div>
                    <div class="stat-item">
                        <div class="stat-number" style="color: var(--primary);">u   </div>
                        <div class="stat-label">📄 Files</div>
                    </div>
                    <div class="stat-item">
                        <div class="stat-number" style="color: var(--secondary);">ue  </div>
                        <div class="stat-label">📋 Total Items</div>
                    </div>
                </div>
                <div style="margin-top: 16px; font-size: 14px; color: var(--text-muted);">
                    💾 Current path: <code style="background: var(--surface-2); padding: 2px 6px; border-radius: 4px; font-size: 13px;">u  </code>
                </div>
            </div>

            <div class="section commands-section">
                <h3>💻 Command Line Upload Examples</h3>
                <p style="margin-bottom: 20px; color: var(--text-muted);">Use these commands to upload files from your terminal or scripts.</p>
                <div class="tab-container">
                    <div class="tab-buttons">
                        <button class="tab-btn active" onclick="showTab('curl')">🌐 cURL</button>
                        <button class="tab-btn" onclick="showTab('wget')">📥 wget</button>
                        <button class="tab-btn" onclick="showTab('powershell')">⚡ PowerShell</button>
                        <button class="tab-btn" onclick="showTab('python')">🐍 Python</button>
                    </div>
                    
                    <div id="curl" class="tab-content active">
                        <div class="command-box">
                            <button class="copy-btn" onclick="copyToClipboard('curlCmd')">📋 Copy</button>
                            <pre id="curlCmd"># Upload a single file
curl -X POST -F "files=@/path/to/your/file.txt" "z{"

# Upload multiple files
curl -X POST \
  -F "files=@file1.txt" \
  -F "files=@file2.jpg" \
  -F "files=@file3.pdf" \
  "uV  "</pre>
                        </div>
                        <p><strong>Usage:</strong> Replace <code>/path/to/your/file.txt</code> with your actual file path. Use <code>-F "files=@filename"</code> for each file.</p>
                    </div>
                    
                    <div id="wget" class="tab-content">
                        <div class="command-box">
                            <button class="copy-btn" onclick="copyToClipboard('wgetCmd')">📋 Copy</button>
                            <pre id="wgetCmd"># Create multipart form data (limited support)
echo -e "--boundary123\r\nContent-Disposition: form-data; name=\"files\"; filename=\"test.txt\"\r\nContent-Type: text/plain\r\n\r\nfile content here\r\n--boundary123--\r\n" | \
wget --post-data=@- \
     --header="Content-Type: multipart/form-data; boundary=boundary123" \
     "u  " -O -</pre>
                        </div>
                        <p><strong>Note:</strong> wget has limited multipart support. <strong>Recommended:</strong> Use cURL for better compatibility and easier syntax.</p>
                    </div>
                    
                    <div id="powershell" class="tab-content">
                        <div class="command-box">
                            <button class="copy-btn" onclick="copyToClipboard('psCmd')">📋 Copy</button>
                            <pre id="psCmd"># Upload a single file
$file = Get-Item "C:\path\to\your\file.txt"
$form = @{'files' = $file}
$response = Invoke-RestMethod -Uri "z" -Method Post -Form $form
Write-Output $response

# Upload multiple files
$files = Get-ChildItem "C:\path\to\files\*" -Include *.txt,*.jpg,*.pdf
$form = @{}
foreach ($file in $files) {
    $form.Add("files", $file)
}
$response = Invoke-RestMethod -Uri "u  " -Method Post -Form $form
Write-Output $response</pre>
                        </div>
                        <p><strong>Usage:</strong> Replace the file paths with your actual Windows file paths. Works with PowerShell 3.0+.</p>
                    </div>
                    
                    <div id="python" class="tab-content">
                        <div class="command-box">
                            <button class="copy-btn" onclick="copyToClipboard('pythonCmd')">📋 Copy</button>
                            <pre id="pythonCmd">#!/usr/bin/env python3
import requests
import os

# Upload a single file
def upload_single_file(file_path):
    url = "a7  "
    with open(file_path, 'rb') as f:
        files = {'files': f}
        response = requests.post(url, files=files)
        print(f"Status: {response.status_code}")
        print(f"Response: {response.text}")
        return response

# Upload multiple files
def upload_multiple_files(file_paths):
    url = "u  "
    files = []
    try:
        for file_path in file_paths:
            files.append(('files', open(file_path, 'rb')))
        
        response = requests.post(url, files=files)
        print(f"Status: {response.status_code}")
        print(f"Response: {response.text}")
        return response
    finally:
        # Close all file handles
        for _, file_handle in files:
            file_handle.close()

# Example usage
if __name__ == "__main__":
    # Single file upload
    upload_single_file("/path/to/your/file.txt")
    
    # Multiple files upload
    file_list = [
        "/path/to/file1.txt",
        "/path/to/file2.jpg",
        "/path/to/file3.pdf"
    ]
    upload_multiple_files(file_list)</pre>
                        </div>
                        <p><strong>Installation:</strong> <code>pip install requests</code><br>
                        <strong>Usage:</strong> Replace file paths with your actual file paths. The script includes proper error handling and file cleanup.</p>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // Tab switching functionality
        function showTab(tabName) {
            const contents = document.querySelectorAll('.tab-content');
            contents.forEach(content => content.classList.remove('active'));
            
            const buttons = document.querySelectorAll('.tab-btn');
            buttons.forEach(btn => btn.classList.remove('active'));
            
            document.getElementById(tabName).classList.add('active');
            event.target.classList.add('active');
        }
        
        // Copy to clipboard functionality
        function copyToClipboard(elementId) {
            const element = document.getElementById(elementId);
            const text = element.textContent;
            
            if (navigator.clipboard) {
                navigator.clipboard.writeText(text).then(() => {
                    showCopyFeedback(event.target);
                });
            } else {
                const textArea = document.createElement('textarea');
                textArea.value = text;
                document.body.appendChild(textArea);
                textArea.select();
                document.execCommand('copy');
                document.body.removeChild(textArea);
                showCopyFeedback(event.target);
            }
        }
        
        function showCopyFeedback(button) {
            const originalText = button.textContent;
            button.textContent = '✅ Copied!';
            button.style.background = '#28a745';
            setTimeout(() => {
                button.textContent = originalText;
                button.style.background = '#4a5568';
            }, 2000);
        }
        
        // Upload progress functionality
        document.getElementById('uploadForm').addEventListener('submit', function(e) {
            e.preventDefault();
            
            const fileInput = document.getElementById('fileInput');
            const files = fileInput.files;
            
            if (files.length === 0) {
                alert('Please select files to upload');
                return;
            }
            
            const formData = new FormData();
            for (let i = 0; i < files.length; i++) {
                formData.append('files', files[i]);
            }
            
            const progressContainer = document.getElementById('progressContainer');
            const progressFill = document.getElementById('progressFill');
            const progressText = document.getElementById('progressText');
            
            progressContainer.style.display = 'block';
            
            const xhr = new XMLHttpRequest();
            
            xhr.upload.addEventListener('progress', function(e) {
                if (e.lengthComputable) {
                    const percentComplete = (e.loaded / e.total) * 100;
                    progressFill.style.width = percentComplete + '%';
                    progressText.textContent = `Uploading... ${Math.round(percentComplete)}% (${formatBytes(e.loaded)} / ${formatBytes(e.total)})`;
                }
            });
            
            xhr.addEventListener('load', function() {
                if (xhr.status === 200) {
                    progressText.textContent = 'Upload complete! Redirecting...';
                    setTimeout(() => {
                        location.reload();
                    }, 1500);
                } else {
                    progressText.textContent = 'Upload failed!';
                    progressFill.style.background = '#ef4444';
                }
            });
            
            xhr.addEventListener('error', function() {
                progressText.textContent = 'Upload error!';
                progressFill.style.background = '#ef4444';
            });
            
            xhr.open('POST', this.action);
            xhr.send(formData);
        });
        
        function formatBytes(bytes) {
            if (bytes === 0) return '0 Bytes';
            const k = 1024;
            const sizes = ['Bytes', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }
        
        // Drag and drop functionality
        const fileInput = document.getElementById('fileInput');
        const uploadSection = document.querySelector('.upload-section');
        
        ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
            uploadSection.addEventListener(eventName, preventDefaults, false);
        });
        
        function preventDefaults(e) {
            e.preventDefault();
            e.stopPropagation();
        }
        
        ['dragenter', 'dragover'].forEach(eventName => {
            uploadSection.addEventListener(eventName, highlight, false);
        });
        
        ['dragleave', 'drop'].forEach(eventName => {
            uploadSection.addEventListener(eventName, unhighlight, false);
        });
        
        function highlight(e) {
            uploadSection.style.background = '#ecfdf5';
            uploadSection.style.borderColor = 'var(--success-light)';
            uploadSection.style.transform = 'scale(1.02)';
        }
        
        function unhighlight(e) {
            uploadSection.style.background = '#f0fdf4';
            uploadSection.style.borderColor = 'var(--success)';
            uploadSection.style.transform = 'scale(1)';
        }
        
        uploadSection.addEventListener('drop', handleDrop, false);
        
        function handleDrop(e) {
            const dt = e.dataTransfer;
            const files = dt.files;
            fileInput.files = files;
            
            if (files.length > 0) {
                const fileCount = files.length;
                const totalSize = Array.from(files).reduce((sum, file) => sum + file.size, 0);
                alert(`Ready to upload ${fileCount} file(s) (${formatBytes(totalSize)} total)`);
            }
        }
    </script>
</body>
</html>z7<html><body><h1>Error</h1><p>Failed to list directory: </p></body></html>)r   rn   ro   relpathr   seplistdirr~   isfilegetsizer8   r   sorthtmlescape_generate_breadcrumbsdirnamerstripurllibparsequotelstrip_format_file_sizerr   r`   r1   r   str) r!   current_pathrelative_pathdisplay_pathfilesdirectoriesitem	item_pathr}   escaped_directoryescaped_display_pathbreadcrumbshtml_contentparent_relativeencoded_parentcurrent_dir_encodedcurrent_dir_param
server_urlr   escaped_dirnamedir_pathencoded_dirnamerU   escaped_filenamer   encoded_filenamesize_strr   icontotal_itemsrT   	error_msgs                                    r"   _generate_directory_list_htmlz1FileDownloadHandler._generate_directory_list_html  s    & 	lkk 2L	xt666 #/ #bgoolDD[&\&\&d&degekmp&q&q q, EK
<00 - -GLLt<<	7>>),, -7??955DLL$....W]]9-- -&&t,,, JJLLL $L 9 9#';|#<#<  44]CCKC8F
 ;FG
CFF
IG
FLR
 t666"$'//-2F2Fs2K2K"L"L"c))&(O!'!3!3O!D!D !"$2!36!  TadgSgSg&,"4"4]5I5I#5N5N"O"O"OmoAT \ =(; = = =Z\5J  \m   LD '  "&+g"6"6 C''&HH,33C883>HH"(,"4"4X">"> !3B! !]l! ! 4C	! ! !  #( # #$#';x#8#8  C'' (II - 4 4S 9 9C ?( JI#)<#5#5i#@#@   11$77 7++H55a8>>@@HHH$DD!AAA!DD!BBB!DD))!DD00!DD!GGG!DD!D !4D! !Z^! !aq! ! AI! ! 5E	! ! !  k**SZZ7K f f f f f f RUU`QaQaf f f f RUUZQ[Q[f f f f" T_#f f f f, L`-f f f fR 3=Sf f f fR @QSf f f f` af f f f` #af f f fx yf f f fx &yf f f fN &0Of f f fN 3DOf f f f` &0af f f f` 3Daf f f f~ f f f f~ +f f f fR Sf f f fR +Sf f f f f f fLP	   	x 	x 	xAIwT[YbMcMcwwwwwwwww	xs   QQ! !
R+&RRRc                    |dk    rdS dg}|                     d                              d          }d}t          |          D ]\  }}|s||rd|z   n|z  }t          j                            |          }t          j        |          }|t          |          dz
  k    r|	                    d| d           w|	                    d| d| d	           d

                    |          S )z
        Generate breadcrumb navigation HTML.
        
        Args:
            relative_path (str): The current relative path
            
        Returns:
            str: HTML breadcrumb navigation
        r   uH   <a href="?" style="text-decoration: none; color: #0066cc;">🏠 Root</a>r$   r@   u    <span style="color: #333;">📁 z</span>z<a href="?dir=u6   " style="text-decoration: none; color: #0066cc;">📁 z</a>u'    <span style="color: #999;">→</span> )r_   r^   	enumerater   r   r   r   r   r1   r8   r~   )	r!   r   r   partsr   ipartencoded_pathescaped_parts	            r"   r   z)FileDownloadHandler._generate_breadcrumbs  sD    C]]ab ##C((..s33 '' 	L 	LGAt ,@C$JJD@L!<--l;;L;t,,LCJJN""""#[l#[#[#[\\\\ ""  $KL  $K  $K  yE  $K  $K  $K  L  L  L  L8==kJJJr   c                 8    t          j        |          \  }}|pdS )z
        Get the MIME type for a file.
        
        Args:
            filepath (str): Path to the file
            
        Returns:
            str: MIME type
        zapplication/octet-stream)	mimetypes
guess_type)r!   filepath	mime_typerh   s       r"   _get_mime_typez"FileDownloadHandler._get_mime_type%  s$     !+H55	1666r   c                 x  K   	 t           j                            |j                            d                    }t           j                            |j                  }d|v r9|d         r1|d         d         }|                     ||j                   d{V  dS d|v r;|d         d         r|d         d         nd}| 	                    |           d{V  dS | 	                    d           d{V  dS # t          $ r7}|                     ddt          |                      d{V  Y d}~dS d}~ww xY w)	z
        Handle GET requests for file listing, directory browsing, and downloads.
        
        Args:
            event: The HTTP request event
        asciifiler   Ndirr$     zInternal Server Error: )r   r   urlparsetargetrL   parse_qsquery_serve_fileheaders_serve_directory_listr   _serve_errorr   )r!   event	url_partsquery_paramsr   r   rT   s          r"   do_GETzFileDownloadHandler.do_GET2  s     	M--el.A.A'.J.JKKI!<00AAL %%,v*>%(03	&&y%-@@@@@@@@@@@,&&5A%5H5KS<.q11QS00::::::::::: 0044444444444 	M 	M 	M##C)K3q66)K)KLLLLLLLLLLLLLLL	Ms$   BC8 =C8 C8 8
D9,D44D9c                   K   	 t           j                            |j                            d                    }t           j                            |j                  }|                    ddg          d         }|                     ||           d{V  dS # t          $ r7}| 
                    ddt          |                      d{V  Y d}~dS d}~ww xY w)zy
        Handle POST requests for file uploads.
        
        Args:
            event: The HTTP request event
        r   r  r$   r   Nr  zUpload Error: )r   r   r  r  rL   r  r  get_handle_file_uploadr   r  r   )r!   r  r  r  
target_dirrT   s         r"   do_POSTzFileDownloadHandler.do_POSTN  s      	D--el.A.A'.J.JKKI!<00AAL &))%"66q9J**5*=========== 	D 	D 	D##C)B#a&&)B)BCCCCCCCCCCCCCCC	Ds   BB 
C$,CCc                 l  K   	 |                      |          }|rt          j                            |          s|                     dd           d{V  dS d}d}|j        D ]m\  }}|                                dk    r|                    d          }3|                                dk    r"t          |                    d                    }n|r|	                    d          s|                     dd           d{V  dS |s|                     dd	           d{V  dS t          j        d
|          }|s|                     dd           d{V  dS |                    d                              d          }	d|	                     d          }
d|	 d                    d          }|                     ||
||           d{V  dS # t           $ rU}|                     d|            d{V  |                     ddt%          |                      d{V  Y d}~dS d}~ww xY w)z
        Handle multipart file upload with memory-efficient streaming.
        
        Args:
            event: The HTTP request event
            target_dir (str): Target directory for upload (relative to download_directory)
          zInvalid target directoryNs   content-typer   s   content-lengthzmultipart/form-dataz.Only multipart/form-data uploads are supportedzContent-Length header requiredzboundary=([^;]+)z Missing boundary in Content-Typer@   r   z--z[UPLOAD-ERROR] r  zUpload processing error: )r   rn   ro   r   r  r	  r`   rL   intrC   ra   rb   rd   r_   encode_process_multipart_uploadr   r*   r   )r!   r  r  safe_target_pathcontent_typecontent_lengthnamevalueboundary_matchboundaryr   end_boundary_bytesrT   s                r"   r  z'FileDownloadHandler._handle_file_uploadb  s     '	O#22:>># 27==9I+J+J ''-GHHHHHHHHH  L!N$} @ @e::<<?22#(<<#8#8LLZZ\\%666%(g)>)>%?%?N |'>'>?T'U'U ''-]^^^^^^^^^! ''-MNNNNNNNNN  Y':LIIN! ''-OPPPPPPPPP%++A..44S99H,(__33G<<N!2h!2!2!2!9!9'!B!B 001A>Seguvvvvvvvvvvv 	O 	O 	O**2q22333333333##C)MSVV)M)MNNNNNNNNNNNNNNN	Os3   AG B,G G &3G A7G 
H3A
H..H3c           	      t  K   g }d}d}d}|| j         k    rt          d| d| j          d          t          |||| j        | j        | j        | j                  }		 ||k     r||z
  }
t          ||
          }|                     |           d{V }|sn|t          |          z  }|	
                    |           d{V }|                    |           |d	k    r9||z  d
z  }|dz  dk    r(|                     d|dd|dd|dd           d{V  ||k     |	                                 d{V }|                    |           |                     ||           d{V  dS # t          $ ro}|                     d|            d{V  |	                                 d{V  |                     ddt#          |                      d{V  Y d}~dS d}~wt$          $ r_}|                     d|            d{V  |	                                 d{V  |                     dd           d{V  Y d}~dS d}~wt&          $ ro}|                     d|            d{V  |	                                 d{V  |                     ddt#          |                      d{V  Y d}~dS d}~wt(          $ ro}|                     d|            d{V  |	                                 d{V  |                     ddt#          |                      d{V  Y d}~dS d}~ww xY w)aJ  
        Process multipart upload data with streaming to avoid memory issues.
        
        Args:
            target_path (str): Safe target directory path
            boundary_bytes (bytes): Multipart boundary
            end_boundary_bytes (bytes): End boundary
            content_length (int): Total content length
        r   i   r
   zUpload too large: r   rw   )r   r   r   r    N   r   z[UPLOAD-PROGRESS] .1f% (r   r   r   z[UPLOAD-VALIDATION] r  zUpload validation failed: z[UPLOAD-MEMORY] Out of memory: i  z&Upload too large - insufficient memoryz[UPLOAD-DISK] Disk error: i  zServer storage error: z![UPLOAD-ERROR] Unexpected error: r  zUpload processing failed: )r   r3   r	   r   r   r   r    min_read_upload_chunkr1   r;   r4   r*   r   _send_upload_success_responser   r  r   MemoryErrorr   r   )r!   r   r   r!  r  uploaded_filesbytes_processed
chunk_sizer   	processor	remaining	read_sizer9   
file_infosprogressfinal_filesrT   s                    r"   r  z-FileDownloadHandler._process_multipart_upload  s      
% D000f.fftOcfffggg -,#6"&"<}
 
 
	/	P!N22*_<	
I66	 #55i@@@@@@@@ 3u::- $-#:#:5#A#AAAAAAA
%%j111 "$444 /. @CGH&+6!;;"jj)|h)|)|)|)|)|)|cq)|)|)|)|}}}}}}}}}' "N22, !* 2 2 4 4444444K!!+... 44^[QQQQQQQQQQQ 	P 	P 	P**7A77888888888##%%%%%%%%%##C)Nc!ff)N)NOOOOOOOOOOOOOOO 	S 	S 	S**BqBBCCCCCCCCC##%%%%%%%%%##C)QRRRRRRRRRRRRRRR 	L 	L 	L**=!==>>>>>>>>>##%%%%%%%%%##C)J#a&&)J)JKKKKKKKKKKKKKKK 	P 	P 	P**DDDEEEEEEEEE##%%%%%%%%%##C)Nc!ff)N)NOOOOOOOOOOOOOOO	PsA   DE) )
L73A$GL7*AIL7A$J;;L7A$L22L7c                   K   	 t          j        | j                                        d           d{V }t	          |t
          j                  r|j        r|j        d|         ndS t	          |t
          j                  rdS | 	                    dt          |                      d{V  dS # t           j        $ r+ | 	                    d           d{V  t          d          t          $ r5}| 	                    d|            d{V  t          d	|           d}~wt          $ r5}| 	                    d
|            d{V  t          d|           d}~ww xY w)zQ
        Read a chunk of upload data from the HTTP request with timeout.
        g      >@)timeoutNr   z&[UPLOAD-ERROR] Unexpected event type: z*[UPLOAD-ERROR] Timeout reading upload dataz$Upload timeout - connection too slowz![UPLOAD-ERROR] Connection error: zUpload connection lost: z$[UPLOAD-ERROR] Error reading chunk: zError reading upload data: )asynciowait_for_wrapper
next_event
isinstanceh11Datar   EndOfMessager*   typeTimeoutErrorr   ConnectionErrorr   )r!   r}   r  rT   s       r"   r'  z&FileDownloadHandler._read_upload_chunk  s     	=!*4=+C+C+E+EtTTTTTTTTTE%** ,1J?uz%4%((C?E3#344 sjj!W$u++!W!WXXXXXXXXXs# 	B 	B 	B**IJJJJJJJJJ@AAA 	: 	: 	:**DDDEEEEEEEEE8Q88999 	= 	= 	=**GAGGHHHHHHHHH;;;<<<	=s1   A$B2 )B2 +B2 2AE&40D$$E&10E!!E&c           	        K   	 || j         k    rd}nCt          j                            || j                                       t          j        d          }dt          j                            |           dt          |           d}|D ]A}| 
                    |d                   }|dt          j        |d                    d	| d
z  }B|dt          j                            |          z   dz   z  }|                    d          }|                                 }|                    dd                    d          fdt!          t          |                                        d          fg           t#          j        d|          }	| j                            |	           d{V  | j                            t#          j        |                     d{V  | j                            t#          j                               d{V  dS # t.          $ r$}
|                     d|
            d{V   d}
~
ww xY w)z
        Send a success response after file upload.
        
        Args:
            uploaded_files (list): List of uploaded file info
            target_path (str): Target directory path
        r$   r   zv<!DOCTYPE html>
<html>
<head>
    <title>Upload Successful</title>
    <meta http-equiv="refresh" content="3;url=?dir=u   ">
</head>
<body style="font-family: Arial, sans-serif; margin: 40px;">
    <h1>✅ Upload Successful!</h1>
    <p>Successfully uploaded z file(s):</p>
    <ul>
r}   u           <li>📄 <strong>rU   z</strong> (z)</li>
z`    </ul>
    <p>Redirecting back to directory listing in 3 seconds...</p>
    <p><a href="?dir=zD">Click here if not redirected automatically</a></p>
</body>
</html>rI   Content-Typetext/html; charset=utf-8r   Content-Length   status_coder	  Nr   z/[UPLOAD-ERROR] Error sending success response: )r   rn   ro   r   r   r   r   r   r   r1   r   r   r   r  basic_headersr4   r   r:  Responser7  sendr;  r<  r   r*   )r!   r*  r   redirect_pathr   r:   r   bodyr	  responserT   s              r"   r(  z1FileDownloadHandler._send_upload_success_response  s     -	d555 " "T=T U U ] ]^`^dfi j j
 5;L4F4F}4U4U	
 
 ".11
 
 
L , ~ ~	11)F2CDD }DK	R\H]<^<^ } }ks } } }} !<--m<<=@ L  &&w//D((**GNN!;!B!B7!K!KL!3s4yy>>#8#8#A#AB   
 |WEEEH-$$X.........-$$SX4%8%8%8999999999-$$S%5%7%788888888888 	 	 	**RqRRSSSSSSSSS	s   HH 
IH==Ic                 f    |dk    r	|dz  ddS |dk    r	|dz  ddS |dk    r	|dz  ddS | dS )	z*Format file size in human-readable format.i   @r$  z GBr
    MB   z KBr/   r   )r!   r}   s     r"   r   z%FileDownloadHandler._format_file_size4  sr    $$$n-66666Ki(11111D[[Tk*****???"r   c           	      X  K   	 |                      |          }|s|                     dd           d{V  dS t          j                            |          s|                     dd           d{V  dS t          j                            |          s|                     dd           d{V  dS |                     |          }|                    d          }|                                 }|	                    dd	                    d
          fdt          t          |                                        d
          fg           t          j        d|          }| j                            |           d{V  | j                            t          j        |                     d{V  | j                            t          j                               d{V  dS # t$          $ r7}|                     ddt          |                      d{V  Y d}~dS d}~ww xY w)z
        Serve the HTML directory listing page.
        
        Args:
            dir_path (str): The directory path to list (relative to download_directory)
        r  zInvalid directory pathN  zDirectory not foundzNot a directoryrI   rA  rB  r   rC  rD  rE  rG  r  z!Error generating directory list: )r   r  rn   ro   r   r   r   r  rH  r4   r   r1   r:  rI  r7  rJ  r;  r<  r   )r!   r   r   r   rL  r	  rM  rT   s           r"   r
  z)FileDownloadHandler._serve_directory_list?  s     	W++H55I ''-EFFFFFFFFF7>>),, ''-BCCCCCCCCC7==++ ''->?????????==iHHL&&w//D((**GNN!;!B!B7!K!KL!3s4yy>>#8#8#A#AB   
 |WEEEH-$$X.........-$$SX4%8%8%8999999999-$$S%5%7%788888888888 	W 	W 	W##C)USQRVV)U)UVVVVVVVVVVVVVVV	Ws)   3G( ;G( 6;G( 3D3G( (
H)2,H$$H)c           
        K   |                      |          }|s|                     dd           d{V  dS t          j                            |          s|                     dd           d{V  dS t          j                            |          s|                     dd           d{V  dS 	 t          j                            |          }|                     |          }d}|r7|D ]4\  }}|                                dk    r|	                    d          } n5d	}	|d
z
  }
d}|ry|
                    d          rd	 |dd         }d|v r=|                    dd
          \  }}|rt          |          }	|rt          |          }
d}n# t          t          f$ r Y nw xY w|
|	z
  d
z   }|                                 }|                    d|                    d          fdt%          |                              d          fdddt          j                            |           d                    d          fg           |dk    r3|                    dd|	 d|
 d|                     d          f           t+          j        ||          }| j                            |           d{V  d}d	}|}t3          |d          5 }|	d	k    r|                    |	           |d	k    rt7          ||          }|                    |          }|sn	 | j                            t+          j        |                     d{V  |t=          |          z  }|t=          |          z  }|dk    r9|dz  d	k    r0||z  dz  }|                     d |d!d"|d#d|d#d$           d{V  n5# t@          $ r(}|                     d%|d#d&|            d{V   d}~ww xY w|d	k    ddd           n# 1 swxY w Y   | j                            t+          j!                               d{V  dS # t@          $ r7}|                     d'd(t%          |                      d{V  Y d}~dS d}~ww xY w))a  
        Serve a specific file for download with support for large files.
        
        Args:
            file_path (str): The requested file path (can include directories)
            request_headers (dict): HTTP request headers for range support
        r  zInvalid filenameNrR  zFile not foundz
Not a files   ranger   r   r@   rD  zbytes=   -   rA  rC  )zAccept-Rangess   byteszContent-Dispositionzattachment; filename="r   zContent-Rangezbytes r   rE  i   rbrG  i  @r#  r   z![FILE-SERVER] Download progress: r$  r%  r   r   z%[FILE-SERVER] Error sending chunk at z bytes: r  zError serving file: )"r   r  rn   ro   r   r   r   r   r`   rL   rC   r^   r  r3   
IndexErrorrH  r4   r  r   rp   r8   r:  rI  r7  rJ  r   seekr&  readr;  r1   r*   r   r<  )r!   r   request_headersr   	file_sizer   range_headerr  r  
start_byteend_byterF  
range_specstartendr  r	  rM  r,  
bytes_sentbytes_remainingfr/  r9   r1  rT   s                             r"   r  zFileDownloadHandler._serve_fileg  s)      ''	22	 	##C);<<<<<<<<<Fw~~i(( 	##C)9:::::::::Fw~~i(( 	##C666666666FU	J	22I++I66I  L #2  KD%zz||x//',||G'<'< 0 J 1}HK   7 7 A A !-abb!1Jj((%/%5%5c1%=%=
s  4),UJ 0'*3xxH&)"J/   D &
2Q6N ((**GNN!1!1'!:!:;!3~#6#6#=#=g#F#FG+&(_AQAQR[A\A\(_(_(_(f(fgn(o(op	    c!!1]*1]1]x1]1]R[1]1]1d1del1m1mnooo |WMMMH-$$X......... $JJ,Oi&& !>>FF:&&&%)) #J @ @IFF9--E  "m00u1E1E1EFFFFFFFFF"c%jj0
'3u::5 *,===*P`BaefBfBf(2^(Cs'JH"&**  .KQY  .K  .K  .Kbl  .K  .K  .Kq  .K  .K  .K  .K  #L  #L  L  L  L  L  L  L  L$   "jj)jQ[)j)j)jgh)j)jkkkkkkkkk% &))              6 -$$S%5%7%788888888888 	J 	J 	J##C)HA)H)HIIIIIIIIIIIIIII	Js   3BP4 AF P4 F# P4 "F##D*P4 A
O6BN/.O6/
O!9#OO!!	O6*P4 6O::P4 =O:>4P4 4
Q5>,Q00Q5c           	        K   	 d| dt          j        |           d                    d          }|                                 }|                    dd                    d          fdt          t          |                                        d          fg           t          j        ||	          }| j	        
                    |           d
{V  | j	        
                    t          j        |                     d
{V  | j	        
                    t          j                               d
{V  d
S # t          $ r)}|                     d|            d
{V  Y d
}~d
S d
}~ww xY w)z
        Serve an error response.
        
        Args:
            status_code (int): HTTP status code
            message (str): Error message
        z<html><body><h1>Error z</h1><p>r   rI   rA  rB  r   rC  rE  NrG  zError serving error response: )r   r   r  rH  r4   r   r1   r:  rI  r7  rJ  r;  r<  r   r*   )r!   rF  messagerL  r	  rM  rT   s          r"   r  z FileDownloadHandler._serve_error  s     	CiKiiWAUAUiiippqxyyD((**GNN!;!B!B7!K!KL!3s4yy>>#8#8#A#AB   
 |WMMMH-$$X.........-$$SX4%8%8%8999999999-$$S%5%7%788888888888 	C 	C 	C**AaAABBBBBBBBBBBBBBB	Cs   D7D= =
E0E++E0)Nr   r   Nr   Nr   r&   )r   r   r   r   r#   r*   r   r   r   r   r  r  r  r  r'  r(  r   r
  r  r  __classcell__)r   s   @r"   r   r     s       	 	 anPTa a a a a a8! ! ! !
5 5 5nPx Px Px Pxd"K "K "KH7 7 7M M M8D D D(/O /O /O /ObMP MP MP^= = =65 5 5n	# 	# 	#&W &W &W &WPlJ lJ lJ lJ\C C C C C C Cr   r   r   r   r   c                    K   	 fd}t          || |          }|                                 d{V S # t          $ r}	d|	fcY d}	~	S d}	~	ww xY w)aD  
    Run the file download server from a target.
    
    Args:
        target: Server target configuration
        download_directory (str): Directory to serve files from
        log_callback: Logging callback function
        max_upload_size (int): Maximum total upload size per request in bytes (default: 2GB)
        max_file_size (int): Maximum individual file size in bytes (default: 500MB)
        allowed_extensions (set): Set of allowed file extensions (None = allow all)
        max_files_per_request (int): Maximum number of files per upload request (default: 100)
    c                  ,    t                     S )Nr   r   r   r   )r   )r   r   r   r   r   s   r"   <lambda>z-run_file_server_from_target.<locals>.<lambda>  s&    "5+'1"7#
 #
 #
 r   )log_callbackN)r   server   )
r  r   rm  r   r   r   r   handler_factoryserverrT   s
    ` ````   r"   run_file_server_from_targetrq    s      
 
 
 
 
 
 
 
 OV,OOO\\^^#######   Qws   4> 
AAAA	127.0.0.1  Fc           	        K   	 d}|rd }| rEt          d| d|            t          dt          j                            |                       nt          d| d| d           |rt          d           t	          ||t
          j                  }	t          |	| |||||           d{V \  }
}|t          d	|            |
 d{V  nC# t          $ r t          d
           Y n(t          $ r}t          d	|            Y d}~nd}~ww xY w|
|

                                 t          d           dS # |
|

                                 t          d           w xY w)aM  
    Run the file download server.
    
    Args:
        download_directory (str): Directory to serve files from
        host (str): Host to bind to
        port (int): Port to bind to
        debug (bool): Enable debug logging
        max_upload_size (int): Maximum total upload size per request in bytes (default: 2GB)
        max_file_size (int): Maximum individual file size in bytes (default: 500MB)
        allowed_extensions (set): Set of allowed file extensions (None = allow all)
        max_files_per_request (int): Maximum number of files per upload request (default: 100)
    Nc                 .   K   t          d|             d S )Nz[FILE-SERVER] )r*   )r)   s    r"   rm  z%run_file_server.<locals>.log_callback  s#      ,s,,-----r   zStarting file server on r   zServing files from: z (no download directory)z+Debug mode enabled - verbose logging active)r   rm  r   r   r   r   zServer error: 
Server stopped by userzServer stopped)r*   rn   ro   r   r   r   
SERVER_TCPrq  KeyboardInterruptr   cancel)r   hostportdebugr   r   r   r   rm  r  server_taskerrrT   s                r"   run_file_serverr  
  s      $  	.. . .  	T:T::D::;;;N9K)L)LNNOOOORTRRDRRRSSS 	A?@@@4x':;;!<1%+'1"7"
 "
 "
 
 
 
 
 
 
S ?(3(())) * * *())))) $ $ $"q""########$ "    "   s<   CC D: D)D: +	D4DD: DD: :'E!c                  j
   ddl } ddl}|                     d| j        d          }|                    ddd	           |                    d
ddd           |                    ddt
          dd           |                    dddd           |                    dt
          dd           |                    dt
          dd           |                    dt
          d d!           |                    d"t          d#$           |                    d%d&d'd()           |                                }|j        rt          j
                            |j                  s-t          d*|j         d+           |                    d,           t          j
                            |j                  s-t          d-|j         d.           |                    d,           |j        d,k     s|j        d/k    r,t          d0|j                    |                    d,           |j        d1k     r,t          d2|j                    |                    d,           |j        d1k     r,t          d3|j                    |                    d,           |j        d,k     r,t          d4|j                    |                    d,           d}|j        rt)                      }|j                            d5          D ]W}|                                }|                    d6          sd6|z   }|                    |                                           Xt          d7           t          d8           |j        r5t          d9t          j
                            |j                              nt          d:           t          d;|j         d<|j                    |j        rt          d=           t          d>|j        d?z  d@dA           t          dB|j        d?z  d@dA           t          dC|j                    |r3t          dDdE                    t=          |                                nt          dF           t          d8           	 t?          j         tC          |j        |j        |j        |j        |j        |j        ||j        G                     dS # tD          $ r t          dH           Y dS tF          $ r2}t          dI|            |                    d,           Y d}~dS d}~ww xY w)Jz/
    Main entry point for the file server.
    r   NzLAsysocks File Server - Secure file upload/download server with web interfaceu  
Examples:
  %(prog)s                                    # Start server on 127.0.0.1:8080 (no directory)
  %(prog)s /home/user/files                  # Serve files from directory
  %(prog)s /home/user/files --host 0.0.0.0  # Bind to all interfaces
  %(prog)s /home/user/files --port 9000      # Use custom port
  %(prog)s /home/user/files --debug          # Enable debug logging
  %(prog)s --help                           # Show this help message

Features:
  • Modern web interface with drag-and-drop uploads
  • Directory browsing with breadcrumb navigation
  • Real-time upload progress bars
  • Command-line examples (cURL, wget, PowerShell, Python)
  • Secure file handling with directory traversal protection
  • Large file streaming support
        )descriptionformatter_classepilog	directoryr   z(Directory to serve files from (optional))nargshelpz--hostz-Hrr  z$Host to bind to (default: 127.0.0.1))defaultr  z--portz-prs  zPort to bind to (default: 8080))r=  r  r  z--debugz-d
store_truez5Enable debug logging (shows detailed server activity))actionr  z--max-upload-sizer   z=Maximum total upload size per request in bytes (default: 2GB)z--max-file-sizer   z6Maximum individual file size in bytes (default: 500MB)z--max-filesr   z9Maximum number of files per upload request (default: 100)z--allowed-extensionszHComma-separated list of allowed file extensions (e.g., ".txt,.jpg,.pdf"))r=  r  z	--versionz-vversionzAsysocks File Server 1.0.0)r  r  zError: Directory 'z' does not existr@   zError: 'z' is not a directoryi  z-Error: Port must be between 1 and 65535, got rP  z8Error: max-upload-size must be at least 1024 bytes, got z6Error: max-file-size must be at least 1024 bytes, got z)Error: max-files must be at least 1, got r   ri   zAsysocks File Serverz2==================================================zDirectory: z"Directory: None (upload-only mode)zAddress: http://r   zDebug: EnabledzMax upload size: r
   z.0frO  zMax file size: zMax files per request: zAllowed extensions: rx   zAllowed extensions: Allrk  rv  zFailed to start server: )$argparsesysArgumentParserRawDescriptionHelpFormatteradd_argumentr  r   
parse_argsr  rn   ro   r   r*   exitr   r{  r   r   	max_filesr   setr^   r_   rC   addr`   r   rz  r|  r~   sortedr5  runr  rx  r   )r  r  parserargsr   extrT   s          r"   mainr  A  s    OOOJJJ $$b < %  F, 7    
 $3    
 $.	     4D    
  L	     E	     H	     W    
 T,     D ~ w~~dn-- 	Gt~GGGHHHHHQKKKw}}T^,, 	AT^AAABBBHHQKKK y1}}	E))IdiIIJJJ d""_I]__```D  [tGY[[\\\~J$.JJKKK  0 UU*0055 	0 	0C))++C>>#&&  Ci""399;;//// 

 !!!	(OOO~ 4=BGOODN;;==>>>>2333	
4TY
4
4
4
4555z  	
Id2i@
I
I
I
IJJJ	
ED.)<
E
E
E
EFFF	
4DN
4
4555 )LTYYv6H/I/I%J%JLLMMMM'(((	(OOOONIIJ 0,1"&.	
 	
 	
 		 		 		 		 		  * * *())))))   ,,,---s   AS T27	T2 'T--T2__main__)NNr   r   Nr   )Nrr  rs  Fr   r   Nr   )r   r5  rn   urllib.parser   r   r   r:  tempfilera   pathlibr   asysocks.unicomm.common.targetr   r   0asysocks.unicomm.protocol.server.http.httpserverr   r   r	   r   rq  r  r  r   r   r   r"   <module>r     s      				          



  				       > > > > > > > > Z Z Z Z Z Z Z Zi  i  i  i  i  i  i  i XaC aC aC aC aC+ aC aC aCF+ UYVcUX   8 W\JWIL4  4  4  4 n[ [ [| zDFFFFF r   