o
    b>r                     @   s|   d Z ddlZddlZddlmZ ddlmZmZmZm	Z	 ddl
mZmZ ddlmZ ddlmZmZ d	ZG d
d deZdS )z,Implements the MySQL Client/Server protocol
    N)Decimal   )	FieldFlag	ServerCmd	FieldType
ClientFlag)errorsutils)get_auth_plugin)DatabaseErrorget_exception
   c                   @   s$  e Zd ZdZdd Zdd Z			
	dFddZdd Z			dGddZdHddZ	dIddZ
			dJddZdd Zdd Zdd ZdKdd Zd!d" ZdLd$d%ZdId&d'Zd(d) Zd*d+ Zd,d- Zd.d/ ZdKd0d1ZdMd2d3Zd4d5 Zd6d7 Zd8d9 Zd:d; Zd<d= Z	>	?dNd@dAZdBdC ZdDdE Z dS )OMySQLProtocolzRImplements MySQL client/server protocol

    Create and parses MySQL packets.
    c                 C   s    |t j@ r|r|dd S dS )z.Prepare database string for handshake responseutf8    )r   ZCONNECT_WITH_DBencode)selfclient_flagsdatabase r   W/var/www/secure340b-portal/env/lib/python3.10/site-packages/mysql/connector/protocol.py_connect_with_db4   s   zMySQLProtocol._connect_with_dbc              
   C   s   |sdS zt ||||||d}| }	W n ttjfy. }
 z
tdt|
d}
~
ww |tj@ rBt	|	}t
d||	 }|S |	d }|S )z#Prepare the authentication responser   )usernamepasswordr   ssl_enabledzFailed authentication: {0}N<B)r
   auth_response	TypeErrorr   InterfaceErrorformatstrr   SECURE_CONNECTIONlenstructpack)r   r   r   r   r   auth_plugin	auth_datar   authZplugin_auth_responseexcZresplenr   r   r   r   _auth_response:   s*   
zMySQLProtocol._auth_responseN-   r      @Fc              
   C   s   z|d }|	p
|d }	W n t tfy" } ztd|d}~ww |s'd}z|d}W n ty9   |}Y nw tdjdt	|d	||||}|| 
|||||	||7 }|| ||7 }|tj@ rm||	dd
 7 }|tj@ r}|
dur}|| |
7 }|S )z"Make a MySQL Authentication packetr&   r%   *Handshake misses authentication info ({0})N    r   z<IIH{filler}{usrlen}sxZxxxxxxxxxxxxxxxxxxxxxx)Zfillerusrlenr   )r   KeyErrorr   ProgrammingErrorr   r   AttributeErrorr#   r$   r"   r)   r   r   PLUGIN_AUTHCONNECT_ARGSmake_conn_attrs)r   	handshaker   r   r   charsetr   max_allowed_packetr   r%   
conn_attrsr&   r(   username_bytespacketr   r   r   	make_authQ   sB   
zMySQLProtocol.make_authc                    s    D ]} | du rd |< qt  fdd D t   t   }td|} D ](}|tdt|7 }||d7 }|tdt | 7 }| | d7 }q.|S )z Encode the connection attributesN c                    s    g | ]}t |t  |  qS r   )r"   ).0xr8   r   r   
<listcomp>   s     z1MySQLProtocol.make_conn_attrs.<locals>.<listcomp>r   r   )sumr"   keysvaluesr#   r$   r   )r   r8   	attr_nameZconn_attrs_lenZconn_attrs_packetr   r?   r   r4   y   s"   

zMySQLProtocol.make_conn_attrsc                 C   s"   t |t | t | d S )z Make a SSL authentication packets                         r	   	int4store	int2store)r   r6   r   r7   r   r   r   make_auth_ssl   s   zMySQLProtocol.make_auth_sslc                 C   s   t |}|dur||7 }|S )z(Make a MySQL packet containing a commandN)r	   	int1store)r   commandargumentdatar   r   r   make_command   s   
zMySQLProtocol.make_commandr   c                 C   s   t |t | S )z0Make a MySQL packet with Fetch Statement command)r	   rF   )r   statement_idrowsr   r   r   make_stmt_fetch   s   zMySQLProtocol.make_stmt_fetchc
              
   C   s
  z|d }
|p
|d }W n t tfy" } ztd|d}~ww |s'd}z|d}W n ty9   |}Y nw tdjt	|dt
j|}|| ||||||
|7 }|| ||7 }|td	|7 }|tj@ rs||dd
 7 }|tj@ r|	dur|| |	7 }|S )z0Make a MySQL packet with the Change User commandr&   r%   r,   Nr-   r   z<B{usrlen}sx)r.   <Hr   )r   r/   r   r0   r   r   r1   r#   r$   r"   r   ZCHANGE_USERr)   r   r   r2   r3   r4   )r   r5   r   r   r   r6   r   r   r%   r8   r&   r(   r9   r:   r   r   r   make_change_user   s>   
zMySQLProtocol.make_change_userc           
   	   C   s  i }t d|dd d |d< |d tkr td|d ttj|dd dd\}|d	< t d
|dd \|d< }}|d< |d< }}|d	  |d	< |dd }t|| }d}|t	j
@ r|rktd|d nd}	|d|	 }||	d }|d dkr|dd }|t	j@ rd|vr|d	 drd|}|d< ntj|dd\}|d< |d d|d< nd|d< || |d< ||d< |S )zParse a MySQL Handshake-packet<xxxxBr      protocolz;Protocol mismatch; server version = {}, client version = {}Nr   endZserver_version_originalz<I8sx2sBH2sBxxxxxxxxxx   Zserver_threadidr6   Zserver_statusr-         z5.5.8r%   utf-8Zmysql_native_passwordr&   capabilities)r#   unpackPROTOCOL_VERSIONr   r   r	   read_stringdecodeZintreadr   r!   minr2   
startswith)
r   r:   resZ
auth_data1Zcapabilities1Zcapabilities2Zauth_data_lengthr]   Z
auth_data2sizer   r   r   parse_handshake   sT   


zMySQLProtocol.parse_handshakec                 C   s   |d dkst di }zTtd|dd d |d< t|dd \}|d< t|\}|d	< td
|dd \|d< |d< |dd }|r_t|\}|d< |d d|d< W |S W |S  tym   t dw )zParse a MySQL OK-packet   r   z#Failed parsing OK packet (invalid).rS   rT   Zfield_countNZaffected_rowsZ	insert_idz<HHstatus_flagwarning_countZinfo_msgr\   zFailed parsing OK packet.)	r   r   r#   r^   r	   read_lc_intread_lc_stringra   
ValueError)r   r:   Z	ok_packetr   r   r   parse_ok   s(   

zMySQLProtocol.parse_okc              	   C   s<   zt |dd d }|W S  tjtfy   tdw )z=Parse a MySQL packet with the number of columns in result setrg   Nr   zFailed parsing column count)r	   rj   r#   errorrl   r   r   )r   r:   countr   r   r   parse_column_count  s   
z MySQLProtocol.parse_column_countr\   c              	   C   s   t |dd \}}t |\}}t |\}}t |\}}t |\}}t |\}}ztd|\}}}}}W n tjyH   tdw |||dddd| tj	@ ||f	S )zParse a MySQL column-packetrg   Nz	<xHIBHBxxz!Failed parsing column information)
r	   rk   r#   r^   rn   r   r   ra   r   ZNOT_NULL)r   r:   encoding_namer6   Zcolumn_typeflagsr   r   r   parse_column  s6   


zMySQLProtocol.parse_columnc                 C   s   |d dkr|  |S d}i }ztd|}W n tjy$   t|w |d dkr1t|dks6t||d |d	< |d
 |d< |S )zParse a MySQL EOF-packetrg   r   zFailed parsing EOF packet.z<xxxBBHHr      	      ri      rh   )rm   r#   r^   rn   r   r   r"   )r   r:   err_msgrd   unpackedr   r   r   	parse_eof0  s   


zMySQLProtocol.parse_eofTc           	      C   s   d}i }|r|dd  d}n| d}|D ]E}zdd | ddD \}}W n   t||d	}zt|||< W q   zt|d	||< W n   td
|||Y q|S )zParse the statistics packetz)Failed getting COM_STATISTICS informationrg   Ns     c                 S   s   g | ]}|  qS r   )strip)r=   vr   r   r   r@   O      z2MySQLProtocol.parse_statistics.<locals>.<listcomp>   :rx   r\   z{0} ({1}:{2}).)splitr   r   ra   intr   r   )	r   r:   Zwith_headererrmsgrd   pairspairZlblvalr   r   r   parse_statisticsD  s,   


zMySQLProtocol.parse_statisticsc           
      C   s"  g }d}d}d}	 |s||kr	 ||fS |  }|drS|dd g}	|  }|dr?|	|dd  |  }|ds-|	|dd  ttd|	}n|d dkrg|d dk rg| |}d}nd}t|dd }|du r|dur|| n|du r|du rt||d	7 }q	)
zRead MySQL text result

        Reads all or given number of rows from the socket.

        Returns a tuple with 2 elements: a list with all rows and
        the EOF packet.
        Nr   Ts   rg   r-   rv      r   )	recvrc   appendr	   Zread_lc_string_list	bytearrayjoinr|   r   )
r   sockversionro   rO   eofZrowdatair:   Zdatasr   r   r   read_text_result_  s:   



zMySQLProtocol.read_text_resultc                 C   s   |d t jkrd}d}n&|d t jkrd}d}n|d t jt jfv r'd}d}n|d t jkr2d}d}|d	 tj@ r=| }||d
 t	
||d| d fS )z%Parse an integer from a binary packetr   <b<hrx   <irg   <qrZ   r   Nr   )r   TINYSHORTINT24LONGLONGLONGr   ZUNSIGNEDupperr#   r^   )r   r:   fieldformat_lengthr   r   r   _parse_binary_integer  s   $z#MySQLProtocol._parse_binary_integerc                 C   sD   |d t jkrd}d}nd}d}||d t||d| d fS )z)Parse a float/double from a binary packetr   rZ   <drg   z<fNr   )r   DOUBLEr#   r^   )r   r:   r   r   r   r   r   r   _parse_binary_float  s   $z!MySQLProtocol._parse_binary_floatc              	   C   s   |d }d}|dkr!t jtd|dd d |d |d d}n8|dkrYd}|d	kr9td
|d|d  d }t j td|dd d |d |d |d |d |d |d}||d d |fS )z&Parse a timestamp from a binary packetr   Nrg   rQ   r   ry   )yearmonthdayr      <IrZ   rT      )r   r   r   hourminutesecondmicrosecond)datetimedater#   r^   )r   r:   r   r   valuemcsr   r   r   _parse_binary_timestamp  s,   	z%MySQLProtocol._parse_binary_timestampc                 C   s   |d }|d|d  }d}|dkrt d|dd d }t d|dd d }|d dkr4|d9 }tj||d ||d	 |d d
}||d d |fS )z'Parse a time value from a binary packetr   r   rZ   r   NrT   r[   r   r   )dayssecondsmicrosecondsminuteshours)r#   r^   r   	timedelta)r   r:   r   r   rL   r   r   tmpr   r   r   _parse_binary_time  s   z MySQLProtocol._parse_binary_timec           
      C   sl  t |d d d }dd |d| D }||d }g }t|D ]\}}|t|d d  d|d d > @ r=|d q!|d tjtjtjtjtj	fv r[| 
||\}}	||	 q!|d tjtjfv rs| ||\}}	||	 q!|d tjtjtjfv r| ||\}}	||	 q!|d tjkr| ||\}}	||	 q!t|\}}	||	| q!t|S )	z(Parse values from a binary result packetr   rx   rZ   c                 S   s   g | ]}t |qS r   )r   )r=   r   r   r   r   r@     r   z6MySQLProtocol._parse_binary_values.<locals>.<listcomp>r   Nr   )r"   	enumerater   r   r   r   r   r   r   r   r   r   FLOATr   DATETIMEDATE	TIMESTAMPr   TIMEr   r	   rk   ra   tuple)
r   fieldsr:   r6   Znull_bitmap_lengthnull_bitmaprC   posr   r   r   r   r   _parse_binary_values  s8   $
z"MySQLProtocol._parse_binary_valuesc           
      C   s   g }d}d}d}	 |dur	 ||fS ||kr	 ||fS |  }	|	d dkr-| |	}d}n|	d dkr@d}| ||	dd |}|du rN|durN|| n|du rZ|du rZt|	|d7 }q	)zwRead MySQL binary protocol result

        Reads all or given number of binary resultset rows from the socket.
        Nr   Trg   rv   rT   r   )r   r|   r   r   r   )
r   r   columnsro   r6   rO   r   rC   r   r:   r   r   r   read_binary_result  s0   
z MySQLProtocol.read_binary_resultc                 C   s   |d dkst di }z5t|dd d\}|d< t|d\}|d< t|d\}|d	< |d
d }t|d\}|d< W |S  tyN   t dw )z'Parse a MySQL Binary Protocol OK packetrg   r   zFailed parsing Binary OK packetrT   NrN   rx   Znum_columnsZ
num_paramsr   ri   )r   r   r	   Zread_intrl   )r   r:   Zok_pktr   r   r   parse_binary_prepare_ok	  s   

z%MySQLProtocol.parse_binary_prepare_okc                 C   s   d}d}|dk r,|dkrd}t j}n?|dkrd}t j}n5|dkr&d}t j}n+d	}t j}n%d
}|dkr8d}t j}n|dkrBd}t j}n|dkrLd}t j}nt j}d}t||||fS )z0Prepare an integer for the MySQL binary protocolNr   ir   i r   i   r   r         r   i  rQ   l    r   z<Q)r   r   r   r   r   r#   r$   )r   r   
field_typert   r   r   r   r   _prepare_binary_integer  s6   z%MySQLProtocol._prepare_binary_integerc                 C   s   t |tjr
tj}nt |tjrtj}ntdt|j	t
|j t
|j }t |tjrQ|t
|j t
|j t
|j }|jdkrQ|t|j7 }t
t|| }||fS )a  Prepare a timestamp object for the MySQL binary protocol

        This method prepares a timestamp of type datetime.datetime or
        datetime.date for sending over the MySQL binary protocol.
        A tuple is returned with the prepared value and field type
        as elements.

        Raises ValueError when the argument value is of invalid type.

        Returns a tuple.
        z2Argument must a datetime.datetime or datetime.dater   )
isinstancer   r   r   r   r   rl   r	   rG   r   rI   r   r   r   r   r   r   rF   r"   )r   r   r   packedr   r   r   _prepare_binary_timestamp;  s,   





z'MySQLProtocol._prepare_binary_timestampc           
      C   s  t |tjtjfstdtj}d}d}d}t |tjrO|jdk r#d}t|j	d\}}t|d\}}	|t
t|jt
| t
| t
|	 7 }|j}n|t
dt
|j t
|j t
|j 7 }|j}|rt|t
|7 }t
|| }t
t|| }||fS )a  Prepare a time object for the MySQL binary protocol

        This method prepares a time object of type datetime.timedelta or
        datetime.time for sending over the MySQL binary protocol.
        A tuple is returned with the prepared value and field type
        as elements.

        Raises ValueError when the argument value is of invalid type.

        Returns a tuple.
        z3Argument must a datetime.timedelta or datetime.timer   Nr-   r   i  <   )r   r   r   timerl   r   r   r   divmodr   r	   rF   absrI   r   r   r   r   r   r"   )
r   r   r   negativer   r   r   	remainderZminsZsecsr   r   r   _prepare_binary_time]  sD   




z"MySQLProtocol._prepare_binary_timec                 C   s   t |t | | }|S )zMPrepare long data for prepared statements

        Returns a string.
        rE   )r   Z	statementparamrL   r:   r   r   r   _prepare_stmt_send_long_data  s   z*MySQLProtocol._prepare_stmt_send_long_datar   r   c              	   C   s  d}dgt |d d  }g }	g }
d}|dkrd}|du ri }|r,|r,t |t |kr2td	t|D ]\}}|| }d}|du ra||d   d|d > O  < |
ttjt|  q6||v rs|| d rotj	}ntj
}nt|tr| |\}}}|	| nt|tr||}|	tt ||  tj}n~t|tr|	tt ||  tj	}nit|tr|	tt t||t||  tj}nJt|tr|	td
| tj}n8t|tjtjfr| |\}}|	| n"t|tjtjfr| |\}}|	| ntdj |j!j"d|
t|t|  q6t#|td t#| }t |dkrg|d$dd |D td 7 }|
D ]}||7 }qU|	D ]}||7 }q_|S )z6Make a MySQL packet with the Statement Execute commandr   r   r   rZ   r-   Zutf8mb4r   NzTFailed executing prepared statement: data values does not match number of parametersr   z:MySQL binary protocol can not handle '{classname}' objects)	classnamec                 S   s   g | ]}t d |qS )B)r#   r$   )r=   bitr   r   r   r@     s    z3MySQLProtocol.make_stmt_execute.<locals>.<listcomp>)%r"   r   r   r   r   r	   rI   r   ZNULLZBLOBSTRINGr   r   r   r    r   Zlc_intZVARCHARbytesr   ZDECIMALfloatr#   r$   r   r   r   r   r   r   r   r0   r   	__class____name__rF   r   )r   rN   rL   
parametersrt   Zlong_data_usedr6   Ziteration_countr   rC   typesr   r   rr   r   r   r:   a_typeZa_valuer   r   r   make_stmt_execute  s   





zMySQLProtocol.make_stmt_executec                 C   sZ   |d dkst dtj|dd dd\}}|r&|d d	kr&|dd }|d
|fS )z&Parse a MySQL AuthSwitchRequest-packetrg   rv   z'Failed parsing AuthSwitchRequest packetrT   Nr   rV   r[   r   r   )r   r   r	   r`   ra   )r   r:   Zplugin_namer   r   r   parse_auth_switch_request  s   z'MySQLProtocol.parse_auth_switch_requestc                 C   s"   |d dkst d|dd S )z!Parse a MySQL AuthMoreData-packetrg   r   z"Failed parsing AuthMoreData packetrT   N)r   r   )r   r:   r   r   r   parse_auth_more_data  s
   z"MySQLProtocol.parse_auth_more_data)	NNNr*   r   r+   FNN)r*   r   r+   )N)r   )NNNr*   r   FNN)r\   )T)r   r\   )r   r   r   Nr   )!r   
__module____qualname____doc__r   r)   r;   r4   rH   rM   rP   rR   rf   rm   rp   ru   r|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   .   sT    
(



'0
 

%

 !"-
Rr   )r   r#   r   decimalr   	constantsr   r   r   r   r<   r   r	   Zauthenticationr
   r   r   r_   objectr   r   r   r   r   <module>   s   