
    hIV                         S r SSKrSSKrSSKrSSKJr  SSKJr  SSK	J
r  S rS rS rS	 rS
 rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS r S r!S r"S r#S r$S r%S  r&g)!z?
Custom validators for enhanced input validation and security.
    N)ValidationError)URLValidator)gettext_lazyc                    [        5       n U" U 5        [        R                  R                  U 5      nUR                  S;  a  [        [        S5      5      eUR                  (       a`  UR                  R                  5       S;   a  OAUR                  R                  S5      (       d   UR                  R                  S5      (       a   U R                  S5      (       d*  U R                  S5      (       d  [        [        S	5      5      e/ S
QnU HA  n[        R                  " X@[        R                  5      (       d  M/  [        [        S5      5      e   g! [         a    [        [        S5      5      ef = f)z
Validate HLS stream URL format and security.

Args:
    value (str): URL to validate
    
Raises:
    ValidationError: If URL is invalid or insecure
zInvalid URL format.)httphttpsz*Only HTTP and HTTPS protocols are allowed.)	localhostz	127.0.0.1z0.0.0.0z192.168.z10.z.m3u8z.m3uz7URL must point to an HLS playlist file (.m3u8 or .m3u).)z[<>"\']zjavascript:zdata:zfile:z+URL contains potentially malicious content.N)r   r   _urllibparseurlparseschemehostnamelower
startswithendswithresearch
IGNORECASE)valueurl_validatorparsedsuspicious_patternspatterns        @C:\Users\brahi\OneDrive\Desktop\Code\src\apps\core\validators.pyvalidate_hls_urlr      s)    !NM8e
 \\""5)F }}--a LMNN ??  "&KK__''
33v7Q7QRW7X7X NN7##u~~f'='=a YZ[[ '99WR]]33!!$Q"RSS '?  8a 56778s   E E3c                   ^  T (       d  [        [        S5      5      eST ;   a  [        [        S5      5      eT R                  S5      (       a2  / SQn[        U 4S jU 5       5      (       d  [        [        S5      5      e/ SQn[        U 4S	 jU 5       5      (       a  [        [        S
5      5      e[	        T 5      S:  a  [        [        S5      5      eg)z
Validate file path for security and format.

Args:
    value (str): File path to validate
    
Raises:
    ValidationError: If path is invalid or insecure
zFile path cannot be empty.z..z(Path traversal attempts are not allowed./)z/tmp/z	/var/tmp/z/opt/streams/z/data/streams/z/app/media/c              3   F   >#    U  H  nTR                  U5      v   M     g 7fN)r   ).0prefixr   s     r   	<genexpr>%validate_file_path.<locals>.<genexpr>Z   s!     K:J5##F++:Js   !z.Absolute paths must be in allowed directories.)	<>"'&|;`$c              3   ,   >#    U  H	  oT;   v   M     g 7fr     )r!   charr   s     r   r#   r$   _   s     
6%5T5=%5s   z&File path contains invalid characters.i  z+File path is too long (max 500 characters).N)r   r
   r   anylen)r   allowed_prefixessuspicious_charss   `  r   validate_file_pathr5   ?   s     a <=>> u}a JKLL
 K:JKKK!!$T"UVV E

6%5
666a HIJJ 5zCa MNOO     c                     [        U 5        U R                  S5      (       a  U R                  S5      n S[        R                  R                  U 5      ;   a  [        [        S5      5      eg)z
Validate directory path for security and format.

Args:
    value (str): Directory path to validate
    
Raises:
    ValidationError: If path is invalid or insecure
r   .z+Path appears to be a file, not a directory.N)r5   r   rstripospathbasenamer   r
   r   s    r   validate_directory_pathr>   g   sZ     u ~~cS! bggu%%a MNOO &r6   c                 x   ^ [        U [        5      (       d  [        [        S5      5      eSU4S jjmT" U 5        g)z
Validate JSON configuration for notification channels.

Args:
    value (dict): Configuration dictionary to validate
    
Raises:
    ValidationError: If configuration is invalid
z*Configuration must be a valid JSON object.c                   > [        U [        5      (       aZ  U R                  5        HE  u  p#[        R                  " SU5      (       d  [        [        SU 35      5      eT" X1 SU 35        MG     g [        U [        5      (       av  [        R                  " SU [        R                  5      (       a  [        [        SU 35      5      e[        R                  " SU 5      (       a  [        [        SU 35      5      eg g )N^[a-zA-Z_][a-zA-Z0-9_]*$zInvalid configuration key: r8   <script|javascript:|data:|file:z%Suspicious content in configuration: [;&|`$]z%Potentially dangerous characters in: )

isinstancedictitemsr   matchr   r
   strr   r   )objr;   keyvalcheck_suspicious_contents       r   rL   =validate_json_configuration.<locals>.check_suspicious_content   s    c4  IIKxx ;SAA)!.I#,O*PQQ(auo> ( S!!yy;S"--PP%a*OPTv(V&WXX yyS))%a*OPTv(V&WXX * "r6   N )rD   rE   r   r
   )r   rL   s    @r   validate_json_configurationrP   }   s3     eT""a LMNNY$ U#r6   c                 ~   SS/nU H@  nX ;  a  [        [        SU 35      5      eX   (       a  M*  [        [        SU S35      5      e   U S   n[        R                  " SU5      (       d  [        [        S5      5      e[	        U S   5      n[        R                  " SU5      (       d  [        [        S	5      5      eg
)z
Validate Telegram notification configuration.

Args:
    config (dict): Telegram configuration
    
Raises:
    ValidationError: If configuration is invalid
	bot_tokenchat_idMissing required field: Field  cannot be emptyz^\d+:[A-Za-z0-9_-]+$z"Invalid Telegram bot token format.z^-?\d+$z Invalid Telegram chat ID format.N)r   r
   r   rG   rH   )configrequired_fieldsfieldrR   rS   s        r   validate_telegram_configrZ      s     #I.O !!&>ug$F"GHH}}!!fUG3C$D"EFF ! {#I88+Y77a DEFF &#$G88J((a BCDD )r6   c                 .   / SQnU H@  nX ;  a  [        [        SU 35      5      eX   (       a  M*  [        [        SU S35      5      e   U S   n[        R                  " SU5      (       d  [        [        S5      5      e [	        U S   5      nS	Us=::  a  S
::  d  O  [        [        S5      5      e SSKJn  U" 5       n U" U S   5        g! [
        [        4 a    [        [        S5      5      ef = f! [          a    [        [        S5      5      ef = f)z
Validate email notification configuration.

Args:
    config (dict): Email configuration
    
Raises:
    ValidationError: If configuration is invalid
)	smtp_host	smtp_portusernamepasswordrT   rU   rV   r\   z^[a-zA-Z0-9.-]+$zInvalid SMTP host format.r]      i  z&SMTP port must be between 1 and 65535.z"SMTP port must be a valid integer.r   )EmailValidatorr^   zInvalid email address format.N)	r   r
   r   rG   int
ValueError	TypeErrordjango.core.validatorsra   )rW   rX   rY   r\   portra   email_validators          r   validate_email_configrh      s&    IO !!&>ug$F"GHH}}!!fUG3C$D"EFF ! {#I88'33a ;<==G6+&'T"U"!!$L"MNN # 6$&OBz*+ 	" Ga DEFFG  Ba ?@AABs   1C C5 %C25Dc                    SS/nU H@  nX ;  a  [        [        SU 35      5      eX   (       a  M*  [        [        SU S35      5      e   [        5       n U" U S   5        / SQnU S   R                  5       U;  a&  [        [        SS	R	                  U5       35      5      eS
U ;   a  U S
   n[        U[        5      (       d  [        [        S5      5      eUR                  5        Ho  u  pg[        U[        5      (       a  [        U[        5      (       d  [        [        S5      5      eUR                  5       S;   d  MY  [        [        SU S35      5      e   gg! [          a    [        [        S5      5      ef = f)z
Validate webhook notification configuration.

Args:
    config (dict): Webhook configuration
    
Raises:
    ValidationError: If configuration is invalid
urlmethodrT   rU   rV   zInvalid webhook URL format.)GETPOSTPUTPATCHzHTTP method must be one of: , headersz$Headers must be a valid JSON object.z(Header names and values must be strings.)hostzcontent-lengthzHeader z is not allowed.N)
r   r
   r   upperjoinrD   rE   rF   rH   r   )rW   rX   rY   r   allowed_methodsrq   header_nameheader_values           r   validate_webhook_configrx      sx    h'O !!&>ug$F"GHH}}!!fUG3C$D"EFF ! !NM@fUm$
 6Oh6a">tyy?Y>Z [\]] F#'4((!!$J"KLL)0%Kk3//z,PS7T7T%a(R&STT   "&@@%a'+>N(O&PQQ *9   @a =>??@s   E E:c                 N   U (       a  U R                  5       (       d  [        [        S5      5      e[        R                  " SU [        R
                  5      (       a  [        [        S5      5      e[        R                  " SU 5      (       a  [        [        S5      5      e[        R                  " SU 5      nU HF  nUR                  5       n[        R                  " SU5      (       a  M1  [        [        SU 35      5      e   [        U 5      S	:  a  [        [        S
5      5      eg)z
Validate notification template content for security.

Args:
    value (str): Template content to validate
    
Raises:
    ValidationError: If template contains unsafe content
z!Template content cannot be empty.rB   z0Template contains potentially malicious content.rC   z3Template contains potentially dangerous characters.z\{\{([^}]+)\}\}rA   zInvalid template variable: i  z3Template content is too long (max 5000 characters).N)	stripr   r
   r   r   r   findallrG   r2   )r   template_varsvars      r   validate_template_contentr~     s     a CDEE 
yy3UBMMJJa RSTT 
yyU##a UVWW JJ159Miikxx3S99!!&A#$G"HII  5zDa UVWW r6   c                     [        U [        [        45      (       d  [        [	        S5      5      eSU s=::  a  S::  d  O  [        [	        S5      5      eg)z
Validate confidence score range.

Args:
    value (float): Confidence score to validate
    
Raises:
    ValidationError: If score is out of valid range
z"Confidence score must be a number.              ?z-Confidence score must be between 0.0 and 1.0.NrD   rb   floatr   r
   r=   s    r   validate_confidence_scorer   6  sI     ec5\**a DEFF5Ca OPQQ  r6   c                     [        U [        [        45      (       d  [        [	        S5      5      eSU s=::  a  S::  d  O  [        [	        S5      5      eg)z
Validate similarity threshold range.

Args:
    value (float): Similarity threshold to validate
    
Raises:
    ValidationError: If threshold is out of valid range
z&Similarity threshold must be a number.r   r   z1Similarity threshold must be between 0.0 and 1.0.Nr   r=   s    r   validate_similarity_thresholdr   G  sI     ec5\**a HIJJ5Ca STUU  r6   c                     [        U [        5      (       d  [        [        S5      5      eU S::  a  [        [        S5      5      eg)z
Validate positive integer values.

Args:
    value (int): Integer to validate
    
Raises:
    ValidationError: If value is not a positive integer
zValue must be an integer.r   z!Value must be a positive integer.NrD   rb   r   r
   r=   s    r   validate_positive_integerr   X  s?     eS!!a ;<==za CDEE r6   c                 `    [        U 5        SU s=::  a  S::  d  O  [        [        S5      5      eg)z
Validate HLS segment duration.

Args:
    value (int): Segment duration in seconds
    
Raises:
    ValidationError: If duration is invalid
r`   <   z2Segment duration must be between 1 and 60 seconds.Nr   r   r
   r=   s    r   validate_segment_durationr   i  s/     e$"a TUVV r6   c                 `    [        U 5        SU s=::  a  S::  d  O  [        [        S5      5      eg)z
Validate maximum segments count.

Args:
    value (int): Maximum segments count
    
Raises:
    ValidationError: If count is invalid
r`   d   z+Maximum segments must be between 1 and 100.Nr   r=   s    r   validate_max_segmentsr   y  s/     e$#a MNOO r6   c                 `    [        U 5        SU s=::  a  S::  d  O  [        [        S5      5      eg)z
Validate retry attempts count.

Args:
    value (int): Retry attempts count
    
Raises:
    ValidationError: If count is invalid
r`   
   z(Retry attempts must be between 1 and 10.Nr   r=   s    r   validate_retry_attemptsr     s/     e$"a JKLL r6   c           	      2   [        U 5        [        U5        Su  p#Su  pEX s=::  a  U::  d  O  [        [        SU SU S35      5      eXAs=::  a  U::  d  O  [        [        SU SU S35      5      eX-  nSUs=::  a  S::  d  O  [        [        S	5      5      eg
)z
Validate video dimensions.

Args:
    width (int): Video width
    height (int): Video height
    
Raises:
    ValidationError: If dimensions are invalid
)i@  i   )   i  zVideo width must be between  and z pixels.zVideo height must be between g      ?g      @z/Video aspect ratio must be between 0.5 and 4.0.Nr   )widthheight	min_width	max_width
min_height
max_heightaspect_ratios          r   validate_video_dimensionsr     s     e$f% %I&J+)+a">ykykYa bcdd.J.a"?
|5Q[P\\d efgg >L<&3&a QRSS 'r6   c           	      t    [        U 5        SnSnXs=::  a  U::  d  O  [        [        SU SU S35      5      eg)z~
Validate video bitrate.

Args:
    value (int): Video bitrate in bps
    
Raises:
    ValidationError: If bitrate is invalid
i izVideo bitrate must be between r    bps.Nr   r   min_bitratemax_bitrates      r   validate_video_bitrater     sK     e$ KK/K/a"@US^R__d efgg 0r6   c           	      t    [        U 5        SnSnXs=::  a  U::  d  O  [        [        SU SU S35      5      eg)z~
Validate audio bitrate.

Args:
    value (int): Audio bitrate in bps
    
Raises:
    ValidationError: If bitrate is invalid
i }  i  zAudio bitrate must be between r   r   Nr   r   s      r   validate_audio_bitrater     sK     e$ KK/K/a"@US^R__d efgg 0r6   c                     [        U 5        / SQnX;  a5  [        [        SSR                  [	        [
        U5      5       S35      5      eg)z
Validate audio sample rate.

Args:
    value (int): Sample rate in Hz
    
Raises:
    ValidationError: If sample rate is invalid
)i@  i+  i>  i"V  iD  i  i w i  zSample rate must be one of: rp   z Hz.N)r   r   r
   rt   maprH   )r   valid_ratess     r   validate_sample_rater     sL     e$ KKa">tyySR]I^?_>``d efgg  r6   c                 `    [        U 5        SU s=::  a  S::  d  O  [        [        S5      5      eg)z
Validate audio channel count.

Args:
    value (int): Number of audio channels
    
Raises:
    ValidationError: If channel count is invalid
r`      z'Audio channels must be between 1 and 8.Nr   r=   s    r   validate_audio_channelsr     s-     e$O!Oa IJKK r6   c                     [        U [        [        45      (       d  [        [	        S5      5      eSU s=::  a  S::  d  O  [        [	        S5      5      eg)z
Validate video framerate.

Args:
    value (float): Framerate in fps
    
Raises:
    ValidationError: If framerate is invalid
zFramerate must be a number.r   g      ^@z,Framerate must be between 1.0 and 120.0 fps.Nr   r=   s    r   validate_framerater     sI     ec5\**a =>??5!E!a NOPP "r6   c                    U (       d  [        [        S5      5      e[        R                  " SU 5      (       d  [        [        S5      5      eU R	                  S5      (       d  U R                  S5      (       a  [        [        S5      5      eSU ;   a  [        [        S5      5      eS[        U 5      s=::  a  S	::  d  O  [        [        S
5      5      eg)z
Validate slug format for URL safety.

Args:
    value (str): Slug to validate
    
Raises:
    ValidationError: If slug format is invalid
zSlug cannot be empty.z^[a-z0-9-]+$z>Slug can only contain lowercase letters, numbers, and hyphens.-z'Slug cannot start or end with a hyphen.z--z(Slug cannot contain consecutive hyphens.   2   z.Slug must be between 3 and 50 characters long.N)r   r
   r   rG   r   r   r2   r=   s    r   validate_slug_formatr     s     a 7899 88OU++a `abb s 3 3a IJKK u}a JKLL U!r!a PQRR "r6   c                    U (       a  U R                  5       (       d  [        [        S5      5      eU R                  5       n [        R                  " SU 5      (       a  [        [        S5      5      e[        R                  " SU 5      (       a  [        [        S5      5      eS[        U 5      s=::  a  S::  d  O  [        [        S5      5      eg	)
z
Validate name format for display purposes.

Args:
    value (str): Name to validate
    
Raises:
    ValidationError: If name format is invalid
zName cannot be empty.z[<>]zName cannot contain HTML tags.[\x00-\x1f\x7f]z'Name cannot contain control characters.   r   z/Name must be between 2 and 100 characters long.N)rz   r   r
   r   r   r2   r=   s    r   validate_name_formatr   1  s     a 7899KKME 
yy%  a @ABB 
yy#U++a IJKK U"s"a QRSS #r6   c                     [        U [        5      (       d  [        [        S5      5      eSU s=::  a  S::  d  O  [        [        S5      5      eg)zz
Validate priority value.

Args:
    value (int): Priority value
    
Raises:
    ValidationError: If priority is invalid
zPriority must be an integer.r`   r   z"Priority must be between 1 and 10.Nr   r=   s    r   validate_priorityr   M  sE     eS!!a >?@@"a DEFF r6   c                     U (       d  [        [        S5      5      e[        R                  " SU 5      (       d  [        [        S5      5      eS[	        U 5      s=::  a  S::  d  O  [        [        S5      5      eg)z
Validate event type format.

Args:
    value (str): Event type to validate
    
Raises:
    ValidationError: If event type is invalid
zEvent type cannot be empty.z^[a-z][a-z0-9_]*$zREvent type must be in snake_case format (lowercase letters, numbers, underscores).r   r   z4Event type must be between 3 and 50 characters long.N)r   r
   r   rG   r2   r=   s    r   validate_event_typer   ^  sf     a =>?? 88(%00a tuvv U!r!a VWXX "r6   c                     [        U 5        / SQn[        R                  R                  U 5      S   R	                  5       nX!;  a&  [        [        SSR                  U5       35      5      eg)z
Validate image file path and format.

Args:
    value (str): Image file path to validate
    
Raises:
    ValidationError: If path or format is invalid
)z.jpgz.jpegz.pngz.bmpz.tiffz.webpr`   z.Image file must have one of these extensions: rp   N)r5   r:   r;   splitextr   r   r
   rt   )r   valid_extensionsfile_exts      r   validate_image_file_pathr   t  sh     u Kww&q)//1H'a"PQUQZQZ[kQlPm nopp (r6   c                     [        U [        5      (       d  U $ [        R                  " SSU 5      n [        R                  " SSU 5      R	                  5       n SSKnUR                  U 5      n U $ )z
Sanitize user input for safe storage and display.

Args:
    value (str): Input to sanitize
    
Returns:
    str: Sanitized input
r   rO   z\s+ r   N)rD   rH   r   subrz   htmlescape)r   r   s     r   sanitize_user_inputr     s`     eS!! FF%r51E FF63&,,.E KKELr6   c                 l  ^ [        U [        5      (       d  [        [        S5      5      eSU4S jjmU R	                  5        H  u  pT" X5        M     SSKn UR                  U 5      n[        U5      S:  a  [        [        S5      5      eg! [        [        4 a    [        [        S5      5      ef = f)	z
Validate context data for templates and notifications.

Args:
    context (dict): Context data to validate
    
Raises:
    ValidationError: If context data is invalid
zContext must be a dictionary.c           	         > U(       a  U SU  3OU n[         R                  " SU 5      (       d  [        [        SU  35      5      e[	        U[
        5      (       ai  [        U5      S:  a  [        [        SU 35      5      e[         R                  " SU[         R                  5      (       a  [        [        SU 35      5      eg [	        U[        5      (       a#  UR                  5        H  u  pET" XEU5        M     g [	        U[        5      (       a>  [        U5       H.  u  pg[	        U[
        [        45      (       d  M"  T" SU 3Xs5        M0     g [	        U[        [        [        [!        S 5      45      (       d  [        [        S	U 35      5      eg )
Nr8   rA   zInvalid context key: i  zContext value too long: z<script|javascript:|data:zSuspicious content in context: item_zInvalid context value type: )r   rG   r   r
   rD   rH   r2   r   r   rE   rF   list	enumeraterb   r   booltype)	rJ   r   r;   current_path
nested_keynested_valueiitemvalidate_context_values	           r   r   5validate_context_data.<locals>.validate_context_value  sT   *.$qC xx3S99!!&;C5$A"BCC eS!!5zD %a*B<.(Q&RSS yy5ubmmLL%a*I,(X&YZZ M t$$,1KKM(
&zN -: t$$$U+dS$K00*U1#;K , ECd4j#ABB!!&B<.$Q"RSS Cr6   r   Ni'  z%Context data is too large (max 10KB).z'Context data must be JSON serializable.rN   )
rD   rE   r   r
   rF   jsondumpsr2   rd   rc   )contextrJ   r   r   context_jsonr   s        @r   validate_context_datar     s     gt$$a ?@AAT> mmo
s* & Lzz'*|u$!!$K"LMM %z" La IJKKLs   4B %B3)'__doc__r   r:   urllib.parser   django.core.exceptionsr   re   r   django.utils.translationr   r
   r   r5   r>   rP   rZ   rh   rx   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r/   r6   r   <module>r      s    
 	  2 / 6/Td%PPP, $FE<&BR+R\XBR"V"F"W P M T<h(h(h&L Q"S<T8G"Y,q(46Lr6   