
    uj(                        d Z ddlm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
mZ ddlmZmZ ddlmZmZmZ ddlZeegdf   Zeegdf   Zeg ef   ZdddZdd	Zdd
Zdddddd	 	 	 	 	 	 	 	 	 	 	 ddZy)u  yjm_file_transfer.py

viewer.html <-> host 파일전송 HTTP 보조 모듈.

현재 단계(v2.5):
- viewer 브라우저에서 선택한 파일을 host PC의 ./recv_files 폴더로 업로드한다.
- 단일 파일은 압축하지 않고 원본 그대로 저장한다.
- 저장 중에는 .part로 쓰고, 완료 후 원래 파일명으로 rename한다.
- token / host 파일전송 허용 체크가 모두 맞아야 저장한다.
- 진행 상황은 host 오버레이와 viewer toast로 알린다.

주의:
- 아직 FTP가 아니다.
- 아직 host -> viewer 임의 파일 다운로드 선택 UI는 넣지 않았다.
- 폴더/여러 파일은 viewer에서 여러 POST로 순차 업로드하면 된다.
    )annotationsN)SimpleHTTPRequestHandler)PathPurePosixPathPureWindowsPath)CallableOptional)parse_qsunquoteurlparsec                    t        |       }|j                  d|       t        j                  |d      j	                  d      S )NstatusF)ensure_asciizutf-8)dict
setdefaultjsondumpsencode)objr   datas      (D:\_St\RTC8790_8791\yjm_file_transfer.py_json_bytesr   $   s5    9DOOHf%::d/66w??    c                r   t        | xs d      j                  dd      }g }t        |      j                  D ]m  }|j	                         j	                  d      }|r|dv r)t        j                  d|      r@t        j                  dd|      }|sZ|j                  |d	d
        o |sdg}|dd	 }t        | S )uc   브라우저가 보낸 파일명/상대경로를 recv_files 내부 상대경로로만 정리한다.
upload.bin\/z. )r   z..z^[A-Za-z]:$z[<>:"|?*\x00-\x1f]_Nx   i)
r   replacer   partsstriprematchsubappendr   )raw_namenamer!   parts       r   _safe_rel_pathr*   *   s    8+|,44T3?DEd#))zz|!!$'t{*88ND)vv+S$7LLds$ * "#JE<r   c                   | |z  j                         }| j                         }||j                  vr
||k7  r|dz  }|j                  j                  dd       |j	                         s.|j                  |j                  dz         j	                         s|S |j                  xs d}|j                  }|j                  }t        dd      D ]P  }|| d|d	| z  }|j	                         r!|j                  |j                  dz         j	                         rN|c S  || dt        t        j                                | z  S )
Nr   Tparentsexist_ok.partupload   i'  r   03d)resolver-   parentmkdirexistswith_suffixsuffixstemrangeinttime)	base_dirrel_pathtargetbase_resolvedr9   r8   r4   idxcands	            r   _unique_target_pathrC   @   s$   !**,F$$&MFNN*v/F-
MMt4==?6#5#5fmmg6M#N#U#U#W;;"(D]]F]]FQ4&#c6(33{{}T%5%5dkkG6K%L%S%S%UK  tfAc$))+./x888r    )tokenis_enabled_callbackstatus_callbackweb_notify_callbackloggerc           	         	 t               j                          t              j                         j                  dd       xs d dfdd	fd	 G  	fddt              }|S )
u<   ThreadingHTTPServer에 넣을 Handler class를 생성한다.Tr,   c                      y)NF rL   r   r   <lambda>z,make_file_transfer_handler.<locals>.<lambda>a   s    %r   c                <    r
	  |        y y # t         $ r Y y w xY wN	Exception)textrG   s    r   host_statusz/make_file_transfer_handler.<locals>.host_statusc   s,    %       	c                <    r
	  |        y y # t         $ r Y y w xY wrO   rP   )payloadrH   s    r   
web_notifyz.make_file_transfer_handler.<locals>.web_notifyj   s,    #G,   rT   c                  p     e Zd ZdZ fdZd
dZd ZdfdZddZfdZ	 fdZ
fd	Z xZS )7make_file_transfer_handler.<locals>.FileTransferHandlerzYjmWin2RtcHTTP/0.2c                :    t        |   |dt              i| y )N	directory)super__init__str)selfargskwargs	__class__web_dirs      r   r]   z@make_file_transfer_handler.<locals>.FileTransferHandler.__init__t   s    GdEc'lEfEr   c                   t        |d|cxk  rdk  rn ndnd      }| j                  |       | j                  dd       | j                  dt        t	        |                   | j                  dd	       | j                  d
d       | j                  dd       | j                  dd       | j                          | j                  j                  |       y )N   i,  okerrorzContent-Typezapplication/json; charset=utf-8Content-LengthzCache-Controlzno-storeAccess-Control-Allow-Origin*Access-Control-Allow-MethodsGET, POST, OPTIONSAccess-Control-Allow-Headers7Content-Type, X-File-Name, X-Relative-Path, X-File-Size)r   send_responsesend_headerr^   lenend_headerswfilewrite)r_   coder   bodys       r   
_send_jsonzBmake_file_transfer_handler.<locals>.FileTransferHandler._send_jsonw   s    sC4,=#,=D7KDt$^-NO-s3t9~>_j9:C@;=QR;=vwJJT"r   c                    | j                  d       | j                  dd       | j                  dd       | j                  dd       | j                  dd	       | j                          y )
N   ri   rj   rk   rl   rm   rn   zAccess-Control-Max-Age600)ro   rp   rr   )r_   s    r   
do_OPTIONSzBmake_file_transfer_handler.<locals>.FileTransferHandler.do_OPTIONS   sb    s#:C@;=QR;=vw5u=r   c                    sy	 t        | j                        }t        |j                        j	                  ddg      d   }t        j                  t        |      t                    S # t        $ r Y yw xY w)NTrE   rD   r   F)	r   pathr
   querygetsecretscompare_digestr^   rQ   )r_   parsedgotrE   s      r   _check_tokenzDmake_file_transfer_handler.<locals>.FileTransferHandler._check_token   sk    !$)),v||,002$?B--c#hE
CC s   A%A, ,	A87A8c                ,    | j                  |d|i       y )Nmessage)rw   )r_   ru   r   s      r   _rejectz?make_file_transfer_handler.<locals>.FileTransferHandler._reject   s    OOD9g"67r   c           
        t        | j                        }|j                  dk7  r| j                  dd      S | j                         s| j                  dd      S 	 t	                      s| j                  dd      S 	 | j                  j                  d      xs | j                  j                  d      xs d	}t        |      j                  d
d      j                  d      d   xs d	}t        |      }t        |      }|j                  |j                  dz         }	 t        | j                  j                  dd            }|dk  r| j                  dd      S d}d}	 ddd|dd        d| d       	 |j!                  d      5 }
|}|dkD  r| j"                  j%                  t'        d|            }|sn|
j)                  |       |t+        |      z  }|t+        |      z  }t-        j,                         }||	z
  dk\  s||k(  r:|}	t        |dz  t/        d|      z        } ddd||d        d| d | d!       |dkD  rd d d        ||k7  rD	 |j1                  d"#        ddd$|d%d&        d'|        | j                  dd(| d|       S |j                  |        ddd)|dd        d*|j2                          rj5                  d+||       | j7                  d,d-|j2                  |t9        |      d.      S # t
        $ r | j                  dd      cY S w xY w# t
        $ r d}Y w xY w# 1 sw Y   xY w# t
        $ r Y w xY w# t
        $ r~}	 |j1                  d"#       n# t
        $ r Y nw xY w ddd$|t9        |      d&        d/|        rj;                  d0|       | j                  d1t9        |            cY d }~S d }~ww xY w)2Nz/uploadi  zunknown POST endpointi  zinvalid tokenzhost file transfer disabledzX-File-NamezX-Relative-Pathr   r   r   r/   rh   0r   i  zempty uploadg        notifyfilestart)typekindstatefilenamepercentu   원격: 파일 전송중
z 0%wbi   g?d   r1   progress %T)
missing_okrg   
incomplete)r   r   r   r   r   u   원격: 파일 수신 실패
zincomplete upload: doneu   원격: 파일 수신 완료
zfile received: %s (%d bytes)re   uploaded)r   r   sizer}   u   원격: 파일 수신 오류
zupload error: %si  )r   r}   r   r   boolrQ   headersr   r   r    splitr*   rC   r7   r8   r;   openrfilereadminrt   rq   r<   maxunlinkr(   inforw   r^   rg   )r_   r   r'   display_namer>   r?   r)   totalreceivedlast_noticef	remainingchunknowr   excrS   rF   rI   recv_dirrW   s                   r   do_POSTz?make_file_transfer_handler.<locals>.FileTransferHandler.do_POST   s%   dii(F{{i'||C)@AA$$&||C99H/12<<-JKK 3
 ||''6m$,,:J:JK\:]mamH"8,44T3?EEcJ2N^R^L%h/H(8<F%%fmmg&=>DDLL,,-=sCD z||C88HK&7Xdqrst4\N#FG/3YYt_ %I#a- $

J	0J K$! CJ.!SZ/	"iik,4E8I*-K&)(S.3q%=*H&IG&(0(.)3,8+2(  (*D\NRST[S\\](^_% $a- %, u$t4 &7`l  zF   G  H"@ OP<</B8*AeW-UVVV$Hfv[gtwxy<V[[MJKKK >Qs
PVP[P[emwz  |B  xC  -D  E  Eu  H||C)FGGH   %_2 %   	3KK4K0  Hfw\huxy|u}~<\NKLLL!3S9||CS22	3s   !L !%L0 <M B=MM M +0M A2M L-,L-0L?>L?MM 	MM MM 	O$'M:9O:	NONAOO$O$c                    t        | j                        }|j                  dk(  r8| j                         }d}	 t                      }| j                  d||d      S t        |          S # t        $ r d}Y 0w xY w)Nz/transfer-statusFre   )token_okenabled)r   r}   r   r   rQ   rw   r\   do_GET)r_   r   ok_tokenr   rb   rF   s       r   r   z>make_file_transfer_handler.<locals>.FileTransferHandler.do_GET   s    dii(F{{00,,.$"#6#89G sg,VWW7>## ! $#G$s   A, ,A:9A:c                X    r	  j                   d|z   g|  y y # t        $ r Y y w xY w)NzHTTP: )debugrQ   )r_   fmtr`   rI   s      r   log_messagezCmake_file_transfer_handler.<locals>.FileTransferHandler.log_message   s;     FLLC7$7  ! s    	)))ru   r;   r   r   returnNone)r   r   )ru   r;   r   r^   r   r   )__name__
__module____qualname__server_versionr]   rw   r{   r   r   r   r   r   __classcell__)rb   rS   rF   rI   r   rE   rc   rW   s   @r   FileTransferHandlerrY   q   s>    -	F
	#			8M	3 M	3^
	$	 	r   r   )rR   r^   r   r   )rV   r   r   r   )r   r3   r5   r   )
rc   r   rE   rF   rG   rH   rI   r   rS   rW   s
   ``````` @@r   make_file_transfer_handlerr   R   sm     7m##%GH~%%'HNN4$N/-@-G G6 GR r   )rf   )r   r   r   r^   r   bytes)r'   r^   r   r   )r=   r   r>   r   r   r   )rc   
str | Pathr   r   rE   r^   rF   zOptional[EnabledCallback]rG   zOptional[StatusCallback]rH   zOptional[WebNotifyCallback])__doc__
__future__r   r   r#   r<   http.serverr   pathlibr   r   r   typingr   r	   urllib.parser
   r   r   r   r^   StatusCallbackr   WebNotifyCallbackr   EnabledCallbackr   r*   rC   r   rL   r   r   <module>r      s   " #  	  0 8 8 % 4 4  3%+&dVT\* 2t8$@,9, 59047;hh h 	h
 3h .h 5hr   