
^c           @  s  d  Z  d d l m Z d Z d d d d d d	 d
 g Z d d l Z d d l m Z m Z d d l	 m
 Z
 d d l Z d d l m Z m Z d Z d Z e d e Z e d e d Z e d e d Z e j d e  Z d e   Z i d d 6d d 6d d 6d d 6Z i d d 6d d 6d d 6d d 6Z d d d d  g Z i  Z x e D] Z e e e <qLWd!   Z d" Z e j e  Z  d#   Z! d$ f  d%     YZ" e d& d'  Z# d( f  d)     YZ$ d* e$ f d+     YZ% d, e$ f d-     YZ& e d d.  Z' d S(/   uc   
ldif - generate and parse LDIF data (see RFC 2849)

See https://www.python-ldap.org/ for details.
i(   t   unicode_literalsu   3.3.1u   ldif_patternu
   CreateLDIFu	   ParseLDIFu
   LDIFWriteru
   LDIFParseru   LDIFRecordListu   LDIFCopyN(   t	   b64encodet	   b64decode(   t   StringIO(   t   urlparset   urlopenu   [\w;.-]+(;[\w_-]+)*u   (([^,]|\\,)+|".*?")u	   [ ]*=[ ]*u   ([ ]*\+[ ]*u   )*[ ]*u
   ([ ]*,[ ]*u   ^%s$u>   ^((dn(:|::) %(dn_pattern)s)|(%(attrtype_pattern)s(:|::) .*)$)+i    u   addi   u   deletei   u   replacei   u	   incrementu   modifyu   modrdnc         C  s>   |  d k r d St  j |   } | d k o= | j d  |  k S(   u!   
  returns 1 if s is a LDAP DN
  u    i   i    N(   t   dn_regext   matcht   Nonet   group(   t   st   rm(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   is_dn8   s    s    (^( |
|| |:|<)|[ 
-]+|[ ]+$)c         C  s   d   |  D S(   uN   
  return a dictionary with all items of l being the keys of the dictionary
  c         S  s   i  |  ] } d  |  q S(   N(   R   (   t   .0t   i(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pys
   <dictcomp>I   s   	 (    (   t   l(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt	   list_dictE   s    t
   LDIFWriterc           B  sV   e  Z d  Z d
 d d d  Z d   Z d   Z d   Z d   Z d   Z	 d	   Z
 RS(   u   
  Write LDIF entry or change records to file object
  Copy LDIF input to a file output object containing all data retrieved
  via URLs
  iL   u   
c         C  sV   | |  _  t g  | p g  D] } | j   ^ q  |  _ | |  _ | |  _ d |  _ d S(   uB  
    output_file
        file object for output; should be opened in *text* mode
    base64_attrs
        list of attribute types to be base64-encoded in any case
    cols
        Specifies how many columns a line may have before it's
        folded into many lines.
    line_sep
        String used as line separator
    i    N(   t   _output_fileR   t   lowert   _base64_attrst   _colst   _last_line_sept   records_written(   t   selft   output_filet   base64_attrst   colst   line_sept   a(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   __init__S   s
    	.		c         C  s   t  |  } | |  j k rA |  j j |  |  j j |  j  n |  j } |  j j | d t | |  j  ! |  j j |  j  xo | | k  r |  j j d  |  j j | | t | | |  j d  ! |  j j |  j  | |  j d } q Wd S(   u7   
    Write string line as one or more folded lines
    i    u    i   N(   t   lenR   R   t   writeR   t   min(   R   t   linet   line_lent   pos(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   _unfold_linese   s    	#+c         C  s(   | j    |  j k p' t j |  d k	 S(   u   
    returns 1 if attr_value has to be base-64 encoded because
    of special chars or because attr_type is in self._base64_attrs
    N(   R   R   t   safe_string_ret   searchR   (   R   t	   attr_typet
   attr_value(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   _needs_base64_encodingz   s    c         C  s   |  j  | |  rX t |  j d  } | j d d  } |  j d j | | g   n% |  j d j | | j d  g   d S(   u   
    Write a single attribute type/value pair

    attr_type
          attribute type (text)
    attr_value
          attribute value (bytes)
    u   asciiu   
u    u   :: u   : N(   R*   R   t   decodet   replaceR%   t   join(   R   R(   R)   t   encoded(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   _unparseAttrTypeandValue   s    	%c         C  sH   xA t  | j    D]- \ } } x | D] } |  j | |  q& Wq Wd S(   u3   
    entry
        dictionary holding an entry
    N(   t   sortedt   itemsR/   (   R   t   entryR(   t   valuesR)   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   _unparseEntryRecord   s    c   	      C  s*  t  | d  } | d k r% d } n% | d k r: d } n t d |   |  j d | j d   x | D] } | d k r | \ } } nG | d k r | \ } } } |  j t | | j d   n t d	   | r x! | D] } |  j | |  q Wn  | d k rj |  j j d
 |  j  qj qj Wd S(   uP   
    modlist
        list of additions (2-tuple) or modifications (3-tuple)
    i    i   u   addi   u   modifyu    modlist item of wrong length: %du
   changetypeu   asciiu'   Subsequent modlist item of wrong lengthu   -N(   R   t
   ValueErrorR/   t   encodet
   MOD_OP_STRR   R    R   (	   R   t   modlistt   mod_lent
   changetypet   modt   mod_typet   mod_valst   mod_opt   mod_val(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   _unparseChangeRecord   s(    		c         C  s   | j  d  } |  j d |  t | t  r> |  j |  n5 t | t  r] |  j |  n t d t |    |  j	 j
 |  j  |  j d |  _ d S(   u   
    dn
          string-representation of distinguished name
    record
          Either a dictionary holding the LDAP entry {attrtype:record}
          or a list with a modify list like for LDAPObject.modify().
    u   utf-8u   dnu8   Argument record must be dictionary or list instead of %si   N(   R6   R/   t
   isinstancet   dictR4   t   listR@   R5   t   reprR   R    R   R   (   R   t   dnt   record(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   unparse   s    	N(   t   __name__t
   __module__t   __doc__R   R   R%   R*   R/   R4   R@   RG   (    (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyR   L   s   						iL   c         C  sa   t  j d d t d d t   } t | | | d  } | j |  |  | j   } | j   | S(   u  
  Create LDIF single formatted record including trailing empty line.
  This is a compatibility function.

  dn
        string-representation of distinguished name
  record
        Either a dictionary holding the LDAP entry {attrtype:record}
        or a list with a modify list like for LDAPObject.modify().
  base64_attrs
        list of attribute types to be base64-encoded in any case
  cols
        Specifies how many columns a line may have before it's
        folded into many lines.
  uh   ldif.CreateLDIF() is deprecated. Use LDIFWriter.unparse() instead. It will be removed in python-ldap 3.1t   categoryt
   stackleveli   u   
(   t   warningst   warnt   DeprecationWarningR   R   RG   t   getvaluet   close(   RE   RF   R   R   t   ft   ldif_writerR
   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt
   CreateLDIF   s    	
t
   LDIFParserc           B  sw   e  Z d  Z d d d d d  Z d   Z d   Z d   Z d   Z d   Z	 d	   Z
 d
   Z d d  Z d   Z RS(   u   
  Base class for a LDIF parser. Applications should sub-class this
  class and override method handle() to implement something meaningful.

  Public class attributes:

  records_read
        Counter for records processed so far
  i    u   
c         C  s  | |  _  t |  j  j d  t  |  _ | |  _ t g  | p? g  D] } | j   ^ q@  |  _ t g  | pm g  D] } | j   ^ qn  |  _	 | |  _
 d |  _ d |  _ d |  _ d |  _ i  j t d  |  _ t |  _ y |  j   |  _ Wn t k
 rd |  _ n Xd S(   u  
    Parameters:
    input_file
        File-object to read the LDIF input from
    ignored_attr_types
        Attributes with these attribute type names will be ignored.
    max_entries
        If non-zero specifies the maximum number of entries to be
        read from f.
    process_url_schemes
        List containing strings with URLs schemes to process with urllib.
        An empty list turns off all URL processing and the attribute
        is ignored completely.
    line_sep
        String used as line separator
    i    u    N(   t   _input_fileRA   t   readt   bytest   _file_sends_bytest   _max_entriesR   R   t   _process_url_schemest   _ignored_attr_typesR   R   t   versiont   line_countert   byte_countert   records_readt   fromkeyst   CHANGE_TYPESt   changetype_counterR   t
   _b64decodet	   _readlinet
   _last_linet   EOFError(   R   t
   input_filet   ignored_attr_typest   max_entriest   process_url_schemesR   R
   R   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyR      s     		..						c         C  s   d S(   uw   
    Process a single content LDIF record. This method should be
    implemented by applications using LDIFParser.
    N(    (   R   RE   R2   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   handle(  s    c         C  s   |  j  j   } |  j r* | j d  } n  |  j d |  _ |  j t |  |  _ | sZ d  S| d d k rr | d  S| d d k r | d  S| Sd  S(   Nu   utf-8i   iu   
iu   
(   RV   t   readlineRY   R+   R^   R_   R   R   (   R   R
   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyRe   /  s    	c         C  s   |  j  d k r. t d |  j |  j f   n  |  j  g } |  j   } x7 | r | d d k r | j | d  |  j   } qI W| |  _  d j |  S(   uG   
    Unfold several folded lines with trailing space into one line
    u%   EOF reached after %d lines (%d bytes)i    u    i   u    N(   Rf   R   Rg   R^   R_   Re   t   appendR-   (   R   t   unfolded_linest	   next_line(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyR%   @  s    	c   	      C  s  |  j    } x& | r4 | d d k r4 |  j    } q W| s? d S| d k rO d Sy | j d  } Wn) t k
 r } t d t |    n X| d | !} | | | d !} | d k r | | d j   } | j d  } n | d	 k r| | d } | j d
  } |  j |  } n | d k r| | d j   } d } |  j	 rt
 |  } | d |  j	 k rt |  j   } qqn | | d j d  } | | f S(   u   
    Parse a single attribute type and value pair from one or
    more lines of LDIF data

    Returns attr_type (text) and attr_value (bytes)
    i    u   #u   -u   :u   no value-spec in %si   u   : u   utf-8u   ::u   asciiu   :<i   N(   NN(   u   -N(   R%   R   t   indexR5   RD   t   lstripR6   Rd   t   stripR[   R   R   RW   (	   R   t   unfolded_linet	   colon_post   eR(   t
   value_specR)   t   urlt   u(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   _next_key_and_valueQ  s:    	c         C  st   |  j  } yA |   \ } } x+ | d k rH | d k rH |   \ } } q WWn t k
 ri d \ } } n X| | f S(   u   
    Consume empty lines until first non-empty line.
    Must only be used between full records!

    Returns non-empty key-value-tuple.
    N(   NN(   Rz   R   Rg   (   R   t   next_key_and_valuet   kt   v(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   _consume_empty_lines  s    	c         C  s  |  j  } yO |  j   \ } } | d k rW t | j d   |  _ |  j   \ } } n  Wn t k
 rl d SXxx| d k r|  j s |  j |  j k  r| d k r t	 d |  j
 t |  f   n  | j d  } t |  st	 d |  j
 t |  f   n  | } i  } |   \ } } x | d k r| j   |  j k r{y | | j |  Wq{t k
 rw| g | | <q{Xn  y |   \ } } Wq!t k
 rd	 \ } } q!Xq!W|  j | |  |  j d |  _ |  j   \ } } qp Wd S(
   u8   
    Continuously read and parse LDIF entry records
    u   versionu   asciiNu   dnu;   Line %d: First line of record does not start with "dn:": %su   utf-8u6   Line %d: Not a valid string-representation for dn: %s.i   (   NN(   Rz   R~   t   intR+   R]   Rg   R   RZ   R`   R5   R^   RD   R   R   R\   Rn   t   KeyErrorRl   (   R   R{   R|   R}   RE   R2   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   parse_entry_records  s@    	""c         C  s
   |  j    S(   uM   
    Invokes LDIFParser.parse_entry_records() for backward compatibility
    (   R   (   R   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   parse  s    c         C  s   g  p	 d } d S(   u   
    Process a single LDIF record representing a single modify operation.
    This method should be implemented by applications using LDIFParser.
    N(   R   (   R   RE   t   modopst   controls(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   handle_modify  s    c         C  s  |  j  } |  j   \ } } | d k rK t |  |  _ |  j   \ } } n  x| d  k r|  j sv |  j |  j k  r| d k r t d |  j t	 |  f   n  | j
 d  } t |  s t d |  j t	 |  f   n  | } |   \ } } g  } x | d  k r| d k r| j
 d  } y | j d d  \ } } } Wn/ t k
 rvd  } | j d d	  \ } } n X| j | | | f  |   \ } } q Wd  }	 | d
 k r| j
 d  } | t k rt d t	 |    n  | }	 |   \ } } n  |	 d k rg  }
 yBx;| d  k rPy t | } Wn0 t k
 rbt d |  j t	 |  f   n X| j
 d  } | } g  } y |   \ } } Wn t k
 rd \ } } n XxP | | k r| j |  y |   \ } } Wqt k
 rd \ } } qXqW|
 j | | | pd  f  |   \ } } | d k r|   \ } } qqWWn t k
 rqd \ } } n X|
 r|  j | |
 |  qn" x | d  k r|   \ } } qW|  j   \ } } y |  j |	 d	 |  j |	 <Wn t k
 rd	 |  j |	 <n X|  j d	 |  _ qN Wd  S(   Nu   versionu   dnu;   Line %d: First line of record does not start with "dn:": %su   utf-8u6   Line %d: Not a valid string-representation for dn: %s.u   controlu    i   i   u
   changetypeu   Invalid changetype: %su   modifyu"   Line %d: Invalid mod-op string: %su   -(   NN(   NN(   NN(   Rz   R~   R   R]   R   RZ   R`   R5   R^   RD   R+   R   t   splitRn   t   valid_changetype_dictt   MOD_OP_INTEGERR   Rg   R   Rc   (   R   R{   R|   R}   RE   R   t   control_typet   criticalityt   control_valueR:   R   t   modopt   modattrt	   modvalues(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   parse_change_records  s    	""#N(   RH   RI   RJ   R   R   Rl   Re   R%   Rz   R~   R   R   R   R   (    (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyRU      s   	'				0		6	t   LDIFRecordListc           B  s5   e  Z d  Z d d d d  Z d   Z d d  Z RS(   u   
  Collect all records of a LDIF file. It can be a memory hog!

  Records are stored in :attr:`.all_records` as a single list
  of 2-tuples (dn, entry), after calling :meth:`.parse`.
  i    c         C  s/   t  j |  | | | |  g  |  _ g  |  _ d  S(   N(   RU   R   t   all_recordst   all_modify_changes(   R   Rh   Ri   Rj   Rk   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyR   J  s    	c         C  s   |  j  j | | f  d S(   uS   
    Append a single record to the list of all records (:attr:`.all_records`).
    N(   R   Rn   (   R   RE   R2   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyRl   U  s    c         C  s)   g  p	 d } |  j j | | | f  d S(   u   
    Process a single LDIF record representing a single modify operation.
    This method should be implemented by applications using LDIFParser.
    N(   R   R   Rn   (   R   RE   R   R   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyR   [  s    N(   RH   RI   RJ   R   R   Rl   R   (    (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyR   B  s   	t   LDIFCopyc           B  s2   e  Z d  Z d d d d d d d  Z d   Z RS(   uM   
  Copy LDIF input to LDIF output containing all data retrieved
  via URLs
  i    iL   u   
c	   	      C  s5   t  j |  | | | |  t | | | |  |  _ d S(   u=   
    See LDIFParser.__init__() and LDIFWriter.__init__()
    N(   RU   R   R   t   _output_ldif(	   R   Rh   R   Ri   Rj   Rk   R   R   R   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyR   j  s    	c         C  s   |  j  j | |  d S(   u2   
    Write single LDIF record to output file.
    N(   R   RG   (   R   RE   R2   (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyRl   v  s    N(   RH   RI   RJ   R   R   Rl   (    (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyR   d  s   	c         C  sH   t  j d d t d d t |  d | d | d d } | j   | j S(	   uL   
  Parse LDIF records read from file.
  This is a compatibility function.
  ui   ldif.ParseLDIF() is deprecated. Use LDIFRecordList.parse() instead. It will be removed in python-ldap 3.1RK   RL   i   Ri   Rj   Rk   i    (   RM   RN   RO   R   R   R   (   RR   t   ignore_attrst
   maxentriest   ldif_parser(    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt	   ParseLDIF}  s    
((   RJ   t
   __future__R    t   __version__t   __all__t   ret   base64R   R   t   ioR   RM   t   ldap.compatR   R   t   attrtype_patternt   attrvalue_patternt   attrtypeandvalue_patternt   rdn_patternt
   dn_patternt   compileR   t   varst   ldif_patternR   R7   Rb   R   t   cR   R   t   SAFE_STRING_PATTERNR&   R   R   RT   RU   R   R   R   (    (    (    s*   /opt/osstech/lib/mailman/pythonlib/ldif.pyt   <module>   sT   	
	
	 S"