
    ;i-                         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m	Z	m
Z
 ddlZddlZddlZddlmZmZmZ ddlmZ  ej(                  e      Z G d d      Z G d	 d
e
      Z G d de	      Zy)a  
OpenDrop: an open source AirDrop implementation
Copyright (C) 2018  Milan Stute
Copyright (C) 2018  Alexander Heinrich

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
    N)BaseHTTPRequestHandler
HTTPServer)	IPVersionServiceInfoZeroconf   )AirDropUtilc                   :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)
AirDropServerzJ
    Announces an HTTPS AirDrop server in the local network via mDNS.
    c                    || _         d| j                   j                  f| _        t        | _        d| j                  _        t        j                  | j                   j                  d      | _	        | j                  _| j                   j                  dk(  r#t        d| j                   j                   d      t        d| j                   j                   d      t        | _        | j                   | j                  _         t        t        | j                        gt        j                   t#        j$                         d	k(  
      | _        | j)                         | _        | j-                         | _        y )Nz::FT)ipv6awdl0z
Interface z@ does not have an IPv6 address. Make sure that `owl` is running.z does not have an IPv6 addressDarwin)
interfaces
ip_version	apple_p2p)configportserveraddressHTTPServerV6ServerClassallow_reuse_addressr	   get_ip_for_interface	interfaceip_addrRuntimeErrorAirDropServerHandlerHandlerr   strr   V6Onlyplatformsystemzeroconf_init_serverhttp_server_init_serviceservice_info)selfr   s     B/home/ubuntu/myenv/lib/python3.12/site-packages/opendrop/server.py__init__zAirDropServer.__init__+   s3    #DKK$4$45'/4,"77KK!!
 <<{{$$/" !6!6 77wx  # !6!6 77UV  ,"kk DLL)* ''oo'83
  ,,. ..0    c                     | j                         }| j                  j                  dz   }| j                  j                  dz   }t	        d|| j                  j
                  ||| j                  j                  g      }|S )Nz.local.z._airdrop._tcp.local.z_airdrop._tcp.local.)r   
propertiesserver	addresses)get_propertiesr   	host_name
service_idr   r   r   packed)r(   r-   r.   service_nameinfos        r)   r&   zAirDropServer._init_serviceL   ss    ((*
&&2{{--0GG"!!!||**+
 r+   c                     t         j                  d| j                  j                   d| j                   d| j                  j
                          | j                  j                  | j                         y )NzAnnouncing service: host z
, address z, port )	loggerr5   r   r1   r   r   r#   register_servicer'   r(   s    r)   start_servicezAirDropServer.start_serviceZ   s\    '(=(='>jV]^b^i^i^n^n]op	
 	&&t'8'89r+   c                    	 | j                  | j                  | j                        }| j                  j                  dk(  rBt        j                         dk(  r+|j                  j                  t        j                  dd       | j                  j                         j                  |j                  d      |_	        |S # t        $ r| | j                  j
                  dz   | j                  _        | j                  d   | j                  j
                  f| _        | j                  | j                  | j                        }Y w xY w)Nr   r   r   r   i  T)sockserver_side)r   r   r   OSErrorr   r   r   r!   r"   socket
setsockopt
SOL_SOCKETget_ssl_contextwrap_socket)r(   httpds     r)   r$   zAirDropServer._init_server`   s   	G$$T%7%7FE ;;  G+0AX0MLL##F$5$5vqA{{224@@4 A 
   	G#{{//!3DKK"&"4"4Q"79I9I!JD$$T%7%7FE		Gs   &B? ?BEEc                 b    t         j                  d       | j                  j                          y )NzStarting HTTPS server)r7   r5   r%   serve_foreverr9   s    r)   start_serverzAirDropServer.start_servers   s!    +,&&(r+   c                 l    | j                   j                          | j                  j                          y N)r#   unregister_all_servicesr%   shutdownr9   s    r)   stopzAirDropServer.stopw   s$    --/!!#r+   c                 f    dt        | j                  j                        j                  d      i}|S )Ns   flagsutf-8)r   r   flagsencode)r(   r-   s     r)   r0   zAirDropServer.get_properties{   s,    DKK$5$5 6 = =g FG
r+   N)__name__
__module____qualname____doc__r*   r&   r:   r$   rG   rL   r0    r+   r)   r   r   &   s+    1B:&)$r+   r   c                   $    e Zd Zej                  Zy)r   N)rQ   rR   rS   r?   AF_INET6address_familyrU   r+   r)   r   r      s    __Nr+   r   c                   H    e 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y)r   z=
    Server which responds to AirDrop HTTP POST requests
    zHTTP/1.1Nc                 j    | j                  d       | j                  d|       | j                          y)zF
        Setting the default values for a successful response
           Content-LengthNsend_responsesend_headerend_headers)r(   content_lengths     r)   _set_responsez"AirDropServerHandler._set_response   s/     	3)>:r+   c                 j    | j                  d       | j                  dd       | j                          y)z&
        Answer head requests
        r[   zContent-typez	text/htmlNr]   r9   s    r)   do_HEADzAirDropServerHandler.do_HEAD   s.     	35r+   c                     t         j                  d| j                          dj                  d      }| j	                  t        |             | j                  j                  |       y)z%
        Answer get requests
        zGET request at 
rN   N)r7   debugpathrP   rb   lenwfilewrite)r(   bodys     r)   do_GETzAirDropServerHandler.do_GET   sM     	tyyk23{{7#3t9%

r+   c                    t        | j                  d         }| j                  j                  |      }t	        j
                  | j                  |d       ddi}t        j                         j                  |      }|j                  d      }|| j                  j                  | j                  j                  d}| j                  j                  r| j                  j                  |d<   t        j                  |t        j                        }t	        j
                  | j                  |d	       | j!                  t#        |             | j$                  j'                  |       y )
Nr\   zreceive_discover_request.plistVersionr   rN   )ReceiverMediaCapabilitiesReceiverComputerNameReceiverModelNameReceiverRecordDatafmtzreceive_discover_response.plist)intheadersrfilereadr	   write_debugr   jsonJSONEncoderrP   computer_namecomputer_modelrecord_dataplistlibdumps
FMT_BINARYrb   ri   rj   rk   )r(   ra   	post_datamedia_capabilitiesmedia_capabilities_jsonmedia_capabilities_binarydiscover_answerdiscover_answer_binarys           r)   handle_discoverz$AirDropServerHandler.handle_discover   s'   T\\*:;<JJOON3	KK$D	
 q
8 #'"2"2"4";";<N"O$;$B$B7$K!)B$(KK$=$=!%!;!;

 ;;""48KK4K4KO01!)!4!4"
 	KK/1R	

 	3567

/0r+   c                    t        | j                  d         }| j                  j                  |      }t	        j
                  | j                  |d       | j                  j                  | j                  j                  d}t        j                  |t        j                        }t	        j
                  | j                  |d       | j                  t        |             | j                  j                  |       y )Nr\   zreceive_ask_request.plist)rr   rq   rt   zreceive_ask_response.plist)rv   rw   rx   ry   r	   rz   r   r~   r}   r   r   r   rb   ri   rj   rk   )r(   ra   r   ask_responseask_resp_binarys        r)   
handle_askzAirDropServerHandler.handle_ask   s    T\\*:;<JJOON3	Y8ST "&!;!;$(KK$=$=
 #..h11
 	KK*F	
 	3/0

)r+   c                 B   | j                   j                  dd      j                         dk7  rt        j	                  d| j                   j                  d              | j                  d       | j                  dd       | j                  dd       | j                  d	d
       | j                          y | j                   j                  dd      j                         dk(  r3| j                  d       | j                  dd       | j                          | j                   j                  dd      j                         dk7  rmt        j	                  d       | j                  d       | j                  dd       | j                  dd       | j                  d	d
       | j                          y  G d dt        j                        }dd}t        j                  d       t        j                         } || j                        } ||       |j                  dz  dz  }|t        j                         |z
  z  }t        j                  d|dd|dd       | j                  d       | j                  dd       | j                  d	d
       | j                          y )Nzcontent-type zapplication/x-cpiozUnsupported content-type: i  zContent-Typer\   r   
Connectioncloseexpectz100-continued   ztransfer-encodingchunkedz Expect chunked transfer encoding  zTransfer-EncodingChunkedc                   *     e Zd Z fdZd Zd Z xZS )=AirDropServerHandler.handle_upload.<locals>.HTTPChunkedReaderc                 N    t        |   |i | || _        d | _        d| _        y )Nr   )superr*   rx   chunktotal)r(   rx   argskwargs	__class__s       r)   r*   zFAirDropServerHandler.handle_upload.<locals>.HTTPChunkedReader.__init__  s*     $1&1"
!

r+   c                 &   | j                   t        | j                         dk(  rmt        | j                  j	                         j                         d      }| j                  j                  |      | _         | j                  j	                          y y )Nr      )r   ri   rv   rx   readlinerstripry   )r(   lengths     r)   _next_chunkzIAirDropServerHandler.handle_upload.<locals>.HTTPChunkedReader._next_chunk  sf    ::%TZZA)= !4!4!6!=!=!?DF!%!8DJJJ'') *>r+   c                     | j                          t        t        | j                        t        |            }| j                  d | |d | | j                  |d  | _        | xj                  |z  c_        |S rI   )r   minri   r   r   )r(   bufr   s      r)   readintozFAirDropServerHandler.handle_upload.<locals>.HTTPChunkedReader.readinto  sa      "S_c#h7#zz'62GV!ZZ0


f$
r+   )rQ   rR   rS   r*   r   r   __classcell__)r   s   @r)   HTTPChunkedReaderr     s    *r+   r   c                     t         j                  j                  |       5 }t         j                  j	                  ||       ddd       y# 1 sw Y   yxY w)zU
            Extracts an archive from memory into the current directory.
            N)
libarchivery   stream_readerextractextract_entries)streamrO   archives      r)   extract_streamz:AirDropServerHandler.handle_upload.<locals>.extract_stream%  sG    
 ..v6 C'""227EBC C Cs   !A

AzReceiving file(s) ...g      @zFile(s) received (size z.02fz MB, speed z MB/s)r[   )r   )rw   getlowerr7   warningr^   r_   r`   io	RawIOBaser5   timerx   r   )r(   r   r   startreadertransferredspeeds          r)   handle_uploadz"AirDropServerHandler.handle_upload   s8   <<NB/557;OONN,T\\-=-=n-M,NO s#^-AB-q1\73 <<Hb)//1^Cs#-q1<</4::<	INN=>s#0)<-q1\73	 	*	C 	+,		"4::.vllV+f4tyy{U23%k$%7{5,fU	
 	3)1-w/r+   c                    t         j                  d| j                          t         j                  d| j                          | j                  dk(  r| j	                          y	| j                  dk(  r| j                          y	| j                  dk(  r| j                          y	t         j                  d| j                          | j                  d       | j                  dd       | j                          y	)
z&
        Handle post requests
        zPOST request at zHeaders
z	/Discoverz/Askz/Uploadr   r\   r   N)
r7   rg   rh   rw   r   r   r   r^   r_   r`   r9   s    r)   do_POSTzAirDropServerHandler.do_POST=  s    
 	'		{34y/099#  "YY& OOYY)# LL+DII;78s#-q1r+   c                 z    t         j                  | j                  d    d| j                          d||z          y )Nr   z - - [z] )r7   rg   client_addresslog_date_time_string)r(   formatr   s      r)   log_messagez AirDropServerHandler.log_messageQ  s=    ""1%&fT-F-F-H,IFUYM?[	
r+   )rQ   rR   rS   rT   protocol_versionr   rb   rd   rm   r   r   r   r   r   rU   r+   r)   r   r      s?     "F91v**FP(
r+   r   )rT   r   r{   loggingr!   r   r?   r   http.serverr   r   r   libarchive.extractlibarchive.readr#   r   r   r   utilr	   	getLoggerrQ   r7   r   r   r   rU   r+   r)   <module>r      sp   $ 
       :    5 5 			8	$W Wt%: %Q
1 Q
r+   