
    G/ja                     t   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
m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 d dlmZ d dlmZ d d	lmZmZ d d
lmZ  G d de      Z G d de      Z  G d de!      Z" G d d      Z#	 	 	 	 	 	 	 	 	 	 d"dee$e
e
e$e%f   ee$e
e$e%f   f   f   f   de
de$f   de
dee$f   de
dee$e
e$e&f   f   f   de$de'de
de(f   de&de'de
dee$e
e$e&e(f   f   f   de
dejR                  f   de
e$ej:                  f   fdZ*	 	 	 	 	 	 	 	 	 	 d"dee$e
e
e$e%f   ee$e
e$e%f   f   f   f   de
de$f   de
dee$f   de
dee$e
e$e&f   f   f   de$de'de
de(f   de&de'de
dee$e
e$e&e(f   f   f   d e
dejV                  f   de
e$ejX                  f   fd!Z-y# e$ r
 d dlmZ Y w xY w)#    N)deepcopy)castUnionDict)urlparse)default_backend)ec)serialization)partial)VapidVapid01)Responsec                   &    e Zd ZdZdddZdefdZy)WebPushExceptionzCWeb Push failure.

    This may contain the requests.Response

    Nreturnc                      || _         || _        y N)messageresponse)selfr   r   s      P/var/www/html/maxservice/venv/lib/python3.12/site-packages/pywebpush/__init__.py__init__zWebPushException.__init__%   s         c                     d}| j                   &	 dj                  | j                   j                        }d| j                   | S # t        $ r d| j                    }Y +w xY w)N z, Response {}z, Response zWebPushException: )r   formattextAttributeErrorr   )r   extras     r   __str__zWebPushException.__str__)   sk    ==$6'..MM&&
 $DLL>%99 " 6%dmm_56s   %A A! A!r   r   N)__name__
__module____qualname____doc__r   strr     r   r   r   r      s    !	: 	:r   r   c                       e Zd ZdZy)NoDataz0Message contained No Data, no encoding required.N)r"   r#   r$   r%   r'   r   r   r)   r)   5   s    :r   r)   c                   J    e Zd ZdZi fddZdefdZd Zd Zd Z	dd	Z
dd
Zy)CaseInsensitiveDictz+A dictionary that has case-insensitive keysr   Nc                     |D ]*  }t         j                  | |j                         ||          , | j                  |       y r   )dict__setitem__lowerupdate)r   datakwargskeys       r   r   zCaseInsensitiveDict.__init__<   s9     	;CT399;S	:	;Fr   c                 J    t         j                  | |j                               S r   )r-   __contains__r/   r   r3   s     r   r5   z CaseInsensitiveDict.__contains__A   s      syy{33r   c                 N    t         j                  | |j                         |       y r   )r-   r.   r/   )r   r3   values      r   r.   zCaseInsensitiveDict.__setitem__D   s    syy{E2r   c                 J    t         j                  | |j                               S r   )r-   __getitem__r/   r6   s     r   r:   zCaseInsensitiveDict.__getitem__G   s    ciik22r   c                 L    t         j                  | |j                                y r   )r-   __delitem__r/   r6   s     r   r<   zCaseInsensitiveDict.__delitem__J   s    syy{+r   c                 H    	 | j                  |      S # t        $ r |cY S w xY wr   )r:   KeyError)r   r3   defaults      r   getzCaseInsensitiveDict.getM   s,    	##C(( 	N	s    !!c                 <    |D ]  }| j                  |||           y r   )r.   )r   r1   r3   s      r   r0   zCaseInsensitiveDict.updateS   s%     	-CS$s),	-r   r!   r   )r"   r#   r$   r%   r   boolr5   r.   r:   r<   r@   r0   r'   r   r   r+   r+   9   s2    5 
44 433,-r   r+   c                      e Zd ZdZi ZddgZdZ	 	 	 ddeee	e	ee
f   eee	ee
f   f   f   f   de	dej                  f   de	dej                  j                  f   d	ed
df
dZded
dfdZde
d
e
fdZ	 dde
ded
efdZdede
deeef   d
efdZ	 	 	 	 dde	de
f   de	deeef   f   deded
ef
dZd
e	eef   fdZd
e	ej8                  ef   fdZy)	WebPushera=  WebPusher encrypts a data block using HTTP Encrypted Content Encoding
    for WebPush.

    See https://tools.ietf.org/html/draft-ietf-webpush-protocol-04
    for the current specification, and
    https://developer.mozilla.org/en-US/docs/Web/API/Push_API for an
    overview of Web Push.

    Example of use:

    The javascript promise handler for PushManager.subscribe()
    receives a subscription_info object. subscription_info.getJSON()
    will return a JSON representation.
    (e.g.
    .. code-block:: javascript
        subscription_info.getJSON() ==
        {"endpoint": "https://push.server.com/...",
         "keys":{"auth": "...", "p256dh": "..."}
        }
    )

    This subscription_info block can be stored.

    To send a subscription update:

    .. code-block:: python
        # Optional
        # headers = py_vapid.sign({"aud": "https://push.server.com/",
                                   "sub": "mailto:your_admin@your.site.com"})
        data = "Mary had a little lamb, with a nice mint jelly"
        WebPusher(subscription_info).send(data, headers)

    aesgcm	aes128gcmFNsubscription_inforequests_sessionaiohttp_sessionverboser   c           	         || _         |t        | _        n|| _        || _        d|vrt	        d      t        |      | _        dx| _        | _        d|v r7t        t        t        t        t        t        f   f   | j                  d         }dD ]c  }|j                  |      t	        d|       t        ||   t              s6t        t        t        ||         j!                  d            ||<   e t#        j$                  | j'                  t        t        |d                     }t)        |      d	k7  r|d
   dk7  rt	        d      || _        t#        j$                  | j'                  t        t        |d                     | _        yy)a-  Initialize using the info provided by the client PushSubscription
        object (See
        https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe)

        :param subscription_info: a dict containing the subscription_info from
            the client.
        :type subscription_info: dict

        :param requests_session: a requests.Session object to optimize requests
            to the same client.
        :type requests_session: requests.Session

        :param verbose: provide verbose feedback
        :type verbose: bool

        Nendpointz&subscription_info missing endpoint URLkeys)p256dhauthzMissing keys value: utf8rN   A   r   zInvalid p256dh key specifiedrO   )rJ   requestsrequests_methodrI   r   r   rG   auth_keyreceiver_keyr   r   r&   r   bytesr@   
isinstanceencodebase64urlsafe_b64decode_repadlen)r   rG   rH   rI   rJ   rM   kreceiver_raws           r   r   zWebPusher.__init__   s|   4 ##+D #3D ..."#KLL!)*;!<,00)&&15S%U
++,d.D.DV.L2D ( G88A;&*-A!+EFFd1gs+#Dd1g$6$=$=f$EFDG	G
 "33DX78L < B&<?f+D&'EFF ,D"44DV56DM 'r   msgc                 h    | j                   r&t        j                   |j                  |i |       y y r   )rJ   logginginfor   )r   r`   argsr2   s       r   verbzWebPusher.verb   s*    <<LLT4V45 r   r1   c                 *    |ddt        |      dz   z   S )z6Add base64 padding to the end of a string, if requireds   ====N   )r]   )r   r1   s     r   r\   zWebPusher._repad   s    goD	A...r   content_encodingc           	         t               }|s| j                  d       t               | j                  r| j                  st        d      | j                  d       d}|| j                  vr+t        dt        j                  | j                        z         |dk(  r>| j                  d       t        j                  d      }t        j                  d	|        t        j                  t        j                         t!                     }|j#                         j%                  t&        j(                  j*                  t&        j,                  j.                  
      }t1        |t2              rt5        |j7                  d            }|dk(  rG| j                  d       t9        j:                  |||| j                  | j                  |      }||d<   |S | j                  d       t=        j>                  |      jA                  d      }t9        j:                  ||||jC                         | j                  | j                  |      }||d<   ||d<   |r't=        j>                  |      jA                  d      |d<   |S )a  Encrypt the data.

        :param data: A serialized block of byte data (String, JSON, bit array,
            etc.) Make sure that whatever you send, your client knows how
            to understand it.
        :type data: str
        :param content_encoding: The content_encoding type to use to encrypt
            the data. Defaults to RFC8188 "aes128gcm". The previous draft-01 is
            "aesgcm", however this format is now deprecated.
        :type content_encoding: enum("aesgcm", "aes128gcm")

        zNo data found...z&No keys specified in subscription infozEncoding data...Nz0Invalid content encoding specified. Select from rE   zGenerating salt for aesgcm...   zSalt: )encodingr   rP   rF   zEncrypting to aes128gcm...)saltprivate_keydhauth_secretversionbodyzEncrypting to aesgcm...   =)rl   rm   keyidrn   ro   rp   
crypto_keyrl   )"r+   re   r)   rU   rV   r   valid_encodingsjsondumpsosurandomrb   debugr	   generate_private_key	SECP256R1r   
public_keypublic_bytesr
   EncodingX962PublicFormatUncompressedPointrX   r&   rW   rY   http_eceencryptrZ   urlsafe_b64encodestripdecode)r   r1   rh   replyrl   
server_keyrt   	encrypteds           r   rY   zWebPusher.encode   s'    $%II()(N}}D$5$5"#KLL		$%4#7#77"!%D,@,@!AB  x'II56::b>DMMF4&/* ,,R\\^_=NO
**,99"++00 --?? : 


 dC V,-D{*II23 ((&$$ MM(I &E&M"  II/011*=CCDIJ ((& '')$$ MM(I #-E,%E&M & 8 8 > D DT Jfr   rL   encoded_dataheadersc           	         |j                         D cg c]  \  }}d|j                          d| d }}}d}|r(t        dd      5 }|j                  |       ddd       d}d	|vr/| j	                  d
       |j                  dt        |       d       dj                  |dj                  |      |      S c c}}w # 1 sw Y   gxY w)a  Return the send as a curl command.

        Useful for debugging. This will write out the encoded data to a local
        file named `encrypted.data`

        :param endpoint: Push service endpoint URL
        :type endpoint: basestring
        :param encoded_data: byte array of encoded data
        :type encoded_data: bytearray
        :param headers: Additional headers for the send
        :type headers: dict
        :returns string

        z-H "z: z" \ 
r   zencrypted.datawbNz--data-binary @encrypted.datazcontent-lengthz#Generating content-length header...z-H "content-length: z%curl -vX POST {url} \
{headers}{data})urlr   r1   )	itemsr/   openwritere   appendr]   r   join)	r   rL   r   r   r3   valheader_listr1   fs	            r   as_curlzWebPusher.as_curl  s      @G}}
3;3d399;-r#g.
 
 &- &%&2D7*II;<&s<'8&9A =CC"''+"6T D 
 	


& &s   !B:C  C	ttlc                 D   |
t               }t               }t        |      }|r| j                  ||      }d|v rF|j                  dd      }|r|dz  }|d|d   j	                  d      z   z  }|j                  d|i       d|v r(|j                  dd	|d   j	                  d      z   i       |j                  d
|i       |j                  d      }| j                  d   }d|vs|r#| j                  d       t        |xs d      |d<   | j                  d|||       |||dS )aX  Encode and send the data to the Push Service.

        :param data: A serialized block of data (see encode() ).
        :type data: str
        :param headers: A dictionary containing any additional HTTP headers.
        :type headers: dict
        :param ttl: The Time To Live in seconds for this message if the
            recipient is not online. (Defaults to "0", which discards the
            message immediately if the recipient is unavailable.)
        :type ttl: int
        :param content_encoding: ECE content encoding (defaults to "aes128gcm")
        :type content_encoding: str
        rt   z
crypto-keyr   ;zdh=rP   rl   
encryptionzsalt=zcontent-encodingrq   rL   r   zGenerating TTL of 0...r   z4
Sending request to
	host: {}
	headers: {}
	data: {})rL   r1   r   )	r-   r+   rY   r@   r   r0   rG   re   r&   )	r   r1   r   r   rh   encodedrt   r   rL   s	            r   _prepare_send_datazWebPusher._prepare_send_data-  sB   * ?fG%'%g.kk$(89Gw&$[[r:

 #%Jegl&;&B&B6&JJJ
j9: g8N8Nv8V.VWXNN&(8
 {{6*))*53II./ ]GEN 			L		
 %lwOOr   c                    |j                  dd      }|j                  dd      } | j                  |i |}|j                  d      }|r|d   }|d   }| j                  |||      S  | j                  j                  |fd|i|}	| j                  d	|	j                  |	j                  xs d
|	j                  xs d       |	S )z,Encode and send the data to the Push Servicetimeout'  curlFrL   r1   r   r   r   z+
Response:
	code: {}
	body: {}
	headers: {}EmptyNone)	popr   r   rT   postre   status_coder   r   )
r   rd   r2   r   r   paramsrL   r   r   resps
             r   sendzWebPusher.sendl  s    **Y.zz&%(((($9&9::j)!&>LY'G<<|W<UU(t##((

 

 			@II LL"F		
 r   c                   K   |j                  dd      }|j                  dd      } | j                  |i |}|j                  d      }|r|d   }|d   }| j                  |||      S | j                  r@ | j                  j                  |fd|i| d {   }	|	j                          d {   }
nbt        j                         4 d {   } |j                  |fd|i| d {   }	|	j                          d {   }
d d d       d {    | j                  d		j                  
xs d
       |	S 7 7 7 p7 U7 ?7 1# 1 d {  7  sw Y   AxY ww)Nr   r   r   FrL   r1   r   r   z
Response:
	code: {}
	body: {}
r   )
r   r   r   rI   r   r   aiohttpClientSessionre   status)r   rd   r2   r   r   r   rL   r   r   r   	resp_textsessions               r   
send_asynczWebPusher.send_async  sU    **Y.zz&%(((($9&9::j)!&>LY'G<<|W<UU2--228WWWPVWWD"iik)I,,. . .')W\\(NGNvNN"&))+-	. . 			3KK 	

  X).N-. . . .s   BED;E0D=1ED?EE+E,EEEEE(E=E?EEEEEEEE)NNF)rF   )NNr   rF   )r"   r#   r$   r%   rG   ru   rJ   r   r&   r   rW   rS   Sessionr   clientr   rB   r   re   r\   r+   rY   r   intr-   r   r   r   ClientResponser   r'   r   r   rD   rD   X   s    D  	O
 G ;?EI7uS%Z($sE#u*4E/E*FFGG
7
  h&6&6 677 tW^^%A%AAB7 7 
7r6 6 6/5 /U /
 4?FF-0F	FP
 
5 
4S> 
VY 
D $(/3 +=PD%K =P tT#s(^+,=P 	=P
 =P 
=P~uXs]'; 459O9OQT9T3U r   rD   rG   r1   vapid_private_keyvapid_claimsrh   r   r   r   rJ   r   rH   r   c                    |	t               }	n|	j                         }	d}|r|rt        j                  d       |j	                  d      sHt        t        t        | j	                  d                  }|j                   d|j                   }||d<   |j	                  d      r<t        |j	                  d      xs d      t        t        j                               k  rLt        t        j                               dz   |d<   |r't        j                  d	j                  |d                |st        d
      t        |t              r|rt        j                  d       |}n}t         j"                  j%                  |      r1|rt        j                  d|        t'        j(                  |      }n-|rt        j                  d       t'        j*                  |      }|rt        j                  d|        |j-                  |      }|rt        j                  d|        |	j/                  |       t1        | |
|      j3                  ||	||||      }|sit        t4        |      j6                  dkD  rLt        t4        |      }t        dj                  |j6                  |j8                  |j:                        |      |S )a  
        One call solution to endcode and send `data` to the endpoint
        contained in `subscription_info` using optional VAPID auth headers.

        in example:

        .. code-block:: python

        from pywebpush import python

        webpush(
            subscription_info={
                "endpoint": "https://push.example.com/v1/abcd",
                "keys": {"p256dh": "0123abcd...",
                         "auth": "001122..."}
                 },
            data="Mary had a little lamb, with a nice mint jelly",
            vapid_private_key="path/to/key.pem",
            vapid_claims={"sub": "YourNameHere@example.com"}
            )

        No additional method call is required. Any non-success will throw a
        `WebPushException`.

    :param subscription_info: Provided by the client call
    :type subscription_info: dict
    :param data: Serialized data to send
    :type data: str
    :param vapid_private_key: Vapid instance or path to vapid private key PEM                               or encoded str
    :type vapid_private_key: Union[Vapid, str]
    :param vapid_claims: Dictionary of claims ('sub' required)
    :type vapid_claims: dict
    :param content_encoding: Optional content type string
    :type content_encoding: str
    :param curl: Return as "curl" string instead of sending
    :type curl: bool
    :param timeout: POST requests timeout
    :type timeout: float
    :param ttl: Time To Live
    :type ttl: int
    :param verbose: Provide verbose feedback
    :type verbose: bool
    :return requests.Response or string
    :param headers: Dictionary of extra HTTP headers to include
    :type headers: dict

    NGenerating VAPID headers...audrL   ://expr     zSetting VAPID expry to {}... VAPID dict missing 'private_key',Looks like we already have a valid VAPID keyReading VAPID key from file private_key_file Reading VAPID key from argumentsrm   
	 claims: 	 headers: )rH   rJ   r   rh   r   r      #Push failed: {} {}
Response body:{}r   )r-   copyrb   rc   r@   r   r   r&   schemenetlocr   timer   r   rX   r   rx   pathisfiler   	from_filefrom_stringsignr0   rD   r   r   r   reasonr   )rG   r1   r   r   rh   r   r   r   rJ   r   rH   vapid_headersr   r   vvr   s                   r   webpushr     se   ~ & ,,.MLL67&4%6%:%::%FGHCZZLCJJ<0C"%L &#l.>.>u.E.J*KcIIKO
 +
 #&diik"2l"CL;BB<PUCVWX "#EFF'1KL"BWW^^-. ;<M;NOP2CDB?@""/@ABLL;|n56-LL<78}%,<g
d)    D8,883>(+299$$hoox}} 	
 	
 Or   rI   c                   K   |	t               }	n|	j                         }	d}|r|rt        j                  d       |j	                  d      sHt        t        t        | j	                  d                  }|j                   d|j                   }||d<   |j	                  d      r<t        |j	                  d      xs d      t        t        j                               k  rLt        t        j                               dz   |d<   |r't        j                  d	j                  |d                |st        d
      t        |t              r|rt        j                  d       |}n}t         j"                  j%                  |      r1|rt        j                  d|        t'        j(                  |      }n-|rt        j                  d       t'        j*                  |      }|rt        j                  d|        |j-                  |      }|rt        j                  d|        |	j/                  |       t1        | |
|      j3                  ||	||||       d{   }|st        t4        j6                  |      j8                  dkD  rdt        t4        j6                  |      }|j;                          d{   }t        dj                  |j8                  |j<                  |      |      |S 7 7 :w)a  
        Async version of webpush function. One call solution to encode and send 
        `data` to the endpoint contained in `subscription_info` using optional 
        VAPID auth headers.

        Example:

        .. code-block:: python

        from pywebpush import webpush_async
        import asyncio

        async def send_notification():
            response = await webpush_async(
                subscription_info={
                    "endpoint": "https://push.example.com/v1/abcd",
                    "keys": {"p256dh": "0123abcd...",
                             "auth": "001122..."}
                     },
                data="Mary had a little lamb, with a nice mint jelly",
                vapid_private_key="path/to/key.pem",
                vapid_claims={"sub": "YourNameHere@example.com"}
                )

        asyncio.run(send_notification())

        No additional method call is required. Any non-success will throw a
        `WebPushException`.

    :param subscription_info: Provided by the client call
    :type subscription_info: dict
    :param data: Serialized data to send
    :type data: str
    :param vapid_private_key: Vapid instance or path to vapid private key PEM                               or encoded str
    :type vapid_private_key: Union[Vapid, str]
    :param vapid_claims: Dictionary of claims ('sub' required)
    :type vapid_claims: dict
    :param content_encoding: Optional content type string
    :type content_encoding: str
    :param curl: Return as "curl" string instead of sending
    :type curl: bool
    :param timeout: POST requests timeout
    :type timeout: float
    :param ttl: Time To Live
    :type ttl: int
    :param verbose: Provide verbose feedback
    :type verbose: bool
    :param headers: Dictionary of extra HTTP headers to include
    :type headers: dict
    :param aiohttp_session: Optional aiohttp ClientSession for connection reuse
    :type aiohttp_session: aiohttp.ClientSession
    :return aiohttp.ClientResponse or string

    Nr   r   rL   r   r   r   r   zSetting VAPID expiry to {}...r   r   r   r   r   r   r   r   )rI   rJ   r   r   r   r   )r-   r   rb   rc   r@   r   r   r&   r   r   r   r   r   r   rX   r   rx   r   r   r   r   r   r   r0   rD   r   r   r   r   r   r   )rG   r1   r   r   rh   r   r   r   rJ   r   rI   r   r   r   r   r   response_texts                    r   webpush_asyncr   "  s    L & ,,.MLL67&4%6%:%::%FGHCZZLCJJ<0C"%L &#l.>.>u.E.J*KcIIKO
 +
 #&diik"2l"CL3::<;NO !"#EFF'1KL"BWW^^-. ;<M;NOP2CDB?@""/@ABLL;|n56-LL<78}%?Gj)  	H D//:AACG..9&mmo-299- 	
 	
 O'	 .s%   IK6K2AK69K4:9K64K6)
NNNrF   FNr   FNN).asynciorZ   rv   rx   r   rb   r   r   typingr   r   r   r   ImportErrorurllib.parser   r   rS   cryptography.hazmat.backendsr   )cryptography.hazmat.primitives.asymmetricr	   cryptography.hazmat.primitivesr
   	functoolsr   py_vapidr   r   r   	Exceptionr   r)   r-   r+   rD   r&   rW   r   rB   floatr   r   r   r   r   r'   r   r   <module>r      s9  
    	    $ $&!    8 8 8  # :y :.;Y ;-$ ->E EX
 "15<@'"&>B6:U5e$d3c5j0A+A&BBCC c	
	
 T5#-. d3c3h#7889   4; 
  4c5c5#99::; D("2"223 3!!!"L "15<@'"&>B:>IU5e$d3c5j0A+A&BBCCI c	
	I
 T5#-.I d3c3h#7889I I I 4;I 
I I 4c5c5#99::;I 4!6!667I 3&&&'Ie  &%%&s   F( (F76F7