
Gh\c           @   s   d  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 d d l	 Z	 d d l
 m Z m Z m Z m Z d d l m Z d d l m Z d d l m Z m Z d	 e f d
     YZ d e f d     YZ d S(   s    IMAP repository support iN(   t   exc_info(   t   Event(   t   foldert   imaputilt
   imapservert   OfflineImapError(   t   BaseRepository(   t   ExitNotifyThread(   t   get_os_sslcertfilet   get_os_sslcertfile_searchpatht   IMAPRepositoryc           B   s  e  Z d    Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z	 d   Z
 d	   Z d
   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z  d   Z! d    Z" d!   Z# d"   Z$ d#   Z% d$   Z& e' d%  Z( d&   Z) d'   Z* d(   Z+ d)   Z, d*   Z- d+   Z. RS(,   c         C   s   d  |  _ t j |  | |  d  |  _ d  |  _ t j |   |  _ d  |  _ d  |  _	 d  |  _
 d  |  _ |  j j |  j   d  r |  j j |  j d   |  _ n  |  j d d   r |  j j d |   n  d  S(   Nt   newmail_hookt   sepsO   The 'sep' setting is being ignored for IMAP repository '%s' (it's autodetected)(   t   Nonet   idlefoldersR   t   __init__t   _hostt   oauth2_request_urlR   t
   IMAPServert   folderst   copy_ignore_evalt   kaeventt   kathreadt   configt
   has_optiont
   getsectiont	   localevalt   evalt   getconfR   t   uit   info(   t   selft	   reposnamet   account(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR   #   s    								c         C   sz   |  j    } | s d  St   |  _ t d |  j j d d |  j   d | |  j f  |  _ |  j j d  |  j j	   d  S(   Nt   targett   names   Keep alive t   argsi   (
   t   getkeepaliveR   R   R   R   t	   keepalivet   getnameR   t	   setDaemont   start(   R   t   keepalivetime(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   startkeepalive:   s    c         C   s6   |  j  d  k r d  S|  j  j   d  |  _ d  |  _  d  S(   N(   R   R   t   setR   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   stopkeepaliveE   s
    	c         C   s   |  j    s |  j   n  d  S(   N(   t   getholdconnectionopent   dropconnections(   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   holdordropconnectionsM   s    c         C   s   |  j  j   d  S(   N(   R   t   close(   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR/   Q   s    c         C   sg   |  j  d k rZ |  j j |  j   d  rK |  j j |  j d   |  _  qZ d   |  _  n  |  j  |  S(   s6   Return a list of UIDs to not copy for this foldername.R   c         S   s   d  S(   N(   R   (   t   x(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   <lambda>]   t    N(   R   R   R   R   R   R   R   R   (   R   t
   foldername(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   get_copy_ignore_UIDsT   s    		c         C   s    |  j    r t S|  j d t  S(   Nt   holdconnectionopen(   t   getidlefolderst   Truet   getconfbooleant   False(   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR.   a   s    c         C   s2   |  j  d d  } | d k r. |  j   r. d S| S(   NR&   i    i   i<   i  (   t
   getconfintR8   (   R   t   num(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR%   f   s    c         C   s,   |  j  j d k s" t d |    |  j  j S(   s   Return the folder separator for the IMAP repository

        This requires that self.imapserver has been initialized with an
        acquireconnection() or it will still be `None`sW   '%s' repository called getsep() before the folder separator was queried from the serverN(   R   t   delimR   t   AssertionError(   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getsepl   s    
c         C   s   |  j  r |  j  S|  j j |  j   d  r |  j d  } y |  j j |  } WnF t k
 r } t j	 t
 t
 d |  | f t
 j j  t   d  n X| r | |  _  |  j  Sn  |  j d d  } | d k r | |  _  |  j  St
 d |  t
 j j   d S(   sf   Return the configured hostname to connect to

        :returns: hostname as string or throws Exceptiont   remotehostevals4   remotehosteval option for repository '%s' failed:
%si   t
   remotehosts-   No remote host for repository '%s' specified.N(   R   R   R   R   R   R   R   t	   Exceptiont   sixt   reraiseR   t   ERRORt   REPOR    R   (   R   t   hostt   e(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   gethostv   s,    		
	
	c         C   s7   |  j  d d d } | d k r3 | j d  } n  | S(   s   Remote identity is used for certain SASL mechanisms
        (currently -- PLAIN) to inform server about the ID
        we want to authorize as instead of our login name.t   remote_identityt   defaults   UTF-8N(   R   R   t   encode(   R   t   identity(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   get_remote_identity   s    c         C   s   d d d d d g } d d d d d g } |  j  d d |  } x> | D]6 } | | k rF t d |  d	 | t j j   qF qF W|  j j d
 d |  | S(   Nt   GSSAPIt   XOAUTH2s   CRAM-MD5t   PLAINt   LOGINt   auth_mechanismss   ,\s*s   Repository %s: s%   unknown authentication mechanism '%s't   imaps"   Using authentication mechanisms %s(   t   getconflistR   RF   RG   R   t   debug(   R   t	   supportedRL   t   mechst   m(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   get_auth_mechanisms   s    	
c         C   sa  d  } |  j } |  j j |  j   d  r^ |  j d  } | d  k r^ | j |  j d  Sn  |  j j |  j   d  r |  j d  } | d  k r | Sn  y t j   j	 |  j
    } Wn+ t k
 r } | j t j k r   q n X| r | d Sy" t j d  j	 |  j
    } Wn4 t k
 rN} | j t j t j f k r]  q]n X| r]| d Sd  S(   Nt   remoteuserevals   UTF-8t
   remoteuseri    s
   /etc/netrc(   R   R   R   R   R   R   R   RM   t   netrct   authenticatorsRJ   t   IOErrort   errnot   ENOENTt   EACCES(   R   t   userR   t
   netrcentryt   inst(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getuser   s0    	
"
c         C   s_   d  } |  j j |  j   d  r3 |  j d  } n  | d  k rO |  j j |  S|  j d d   S(   Nt   remoteportevalt
   remoteport(   R   R   R   R   R   R   R   R<   (   R   t   port(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getport   s    c         C   s   |  j  d d   S(   Nt   ipv6(   R:   R   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getipv6   s    c         C   s   |  j  d t  S(   Nt   ssl(   R:   R9   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getssl   s    c         C   s4   t  j j t  j j t  j j g } |  j d | d   S(   Nt   sslclientcert(   t   ost   patht
   expandusert
   expandvarst   abspatht   getconf_xformR   (   R   t   xforms(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getsslclientcert   s    !c         C   s4   t  j j t  j j t  j j g } |  j d | d   S(   Nt   sslclientkey(   Rq   Rr   Rs   Rt   Ru   Rv   R   (   R   Rw   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getsslclientkey   s    !c         C   s   t  j j t  j j t  j j g } |  j d | d  } |  j d d  d k r t   } | d k r t	   } | r d d j
 |  } n d } t | t j j   q n  | d k r d St  j j |  s d |  j | f } t | t j j   n  | S(   s  Determines CA bundle.

        Returns path to the CA bundle.  It is either explicitely specified
        or requested via "OS-DEFAULT" value (and we will search known
        locations for the current OS and distribution).

        If search via "OS-DEFAULT" route yields nothing, we will throw an
        exception to make our callers distinguish between not specified
        value and non-existent default CA bundle.

        It is also an error to specify non-existent file via configuration:
        it will error out later, but, perhaps, with less verbose explanation,
        so we will also throw an exception.  It is consistent with
        the above behaviour, so any explicitely-requested configuration
        that doesn't result in an existing file will give an exception.
        t   sslcacertfiles
   OS-DEFAULTsP   Default CA bundle was requested, but no existing locations available.  Tried %s.s   , sd   Default CA bundle was requested, but OfflineIMAP doesn't know any for your current operating system.sF   CA certfile for repository '%s' couldn't be found.  No such file: '%s'N(   Rq   Rr   Rs   Rt   Ru   Rv   R   R   R   R	   t   joinR   RF   RG   t   isfileR#   (   R   Rw   t
   cacertfilet
   searchpatht   reason(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getsslcacertfile   s$    !		c         C   s   |  j  d d  S(   Nt	   tls_levelt
   tls_compat(   R   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   gettlslevel  s    c         C   s   |  j  d d   S(   Nt   ssl_version(   R   R   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getsslversion  s    c         C   s   |  j  d t  S(   Nt   starttls(   R:   R9   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getstarttls  s    c         C   sP   |  j  d d  } g  | j d  D]* } | r" | j   j   j d d  ^ q" S(   s   Return array of possible certificate fingerprints.

        Configuration item cert_fingerprint can contain multiple
        comma-separated fingerprints in hex form.t   cert_fingerprintR4   t   ,t   :(   R   t   splitt   stript   lowert   replace(   R   t   valuet   f(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   get_ssl_fingerprint!  s    c         C   s   | |  _  d  S(   N(   R   (   R   t   url(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   setoauth2_request_url*  s    c         C   s6   |  j  d  k	 r |  j  S|  j |  j d d    |  j  S(   NR   (   R   R   R   R   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getoauth2_request_url-  s    c         C   sa   |  j  d d   } | d  k r] |  j j |  j  d d   } | d  k	 r] | j d  } q] n  | S(   Nt   oauth2_refresh_tokent   oauth2_refresh_token_evalR   s   
(   R   R   R   R   R   (   R   t   refresh_token(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getoauth2_refresh_token4  s    	c         C   sa   |  j  d d   } | d  k r] |  j j |  j  d d   } | d  k	 r] | j d  } q] n  | S(   Nt   oauth2_access_tokent   oauth2_access_token_evalR   s   
(   R   R   R   R   R   (   R   t   access_token(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getoauth2_access_token>  s    	c         C   sa   |  j  d d   } | d  k r] |  j j |  j  d d   } | d  k	 r] | j d  } q] n  | S(   Nt   oauth2_client_idt   oauth2_client_id_evalR   s   
(   R   R   R   R   R   (   R   t	   client_id(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getoauth2_client_idH  s    	c         C   sa   |  j  d d   } | d  k r] |  j j |  j  d d   } | d  k	 r] | j d  } q] n  | S(   Nt   oauth2_client_secrett   oauth2_client_secret_evalR   s   
(   R   R   R   R   R   (   R   t   client_secret(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getoauth2_client_secretR  s    	c         C   s   |  j  d d   S(   Nt   preauthtunnel(   R   R   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getpreauthtunnel\  s    c         C   s   |  j  d d   S(   Nt   transporttunnel(   R   R   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   gettransporttunnel_  s    c         C   s   |  j  d d  S(   Nt	   referenceR4   (   R   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getreferenceb  s    c         C   s   |  j  d t  S(   Nt   decodefoldernames(   R:   R;   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getdecodefoldernamese  s    c         C   s:   |  j  d  k r3 |  j j |  j d d   |  _  n  |  j  S(   NR   s   [](   R   R   R   R   R   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR8   h  s    	c         C   s1   t  |  j    } |  j d d  } t | |  S(   Nt   maxconnectionsi   (   t   lenR8   R<   t   max(   R   t   num1t   num2(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getmaxconnectionso  s    c         C   s   |  j  d t  S(   Nt   expunge(   R:   R9   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt
   getexpunget  s    c         C   s  |  j  d d	  } | d	 k	 r7 |  j j |  j d  S|  j  d d	  } | d	 k	 rY | S|  j  d d	  } | d	 k	 r t j t j j	 |  d d  } | j
   j   } | j   | j d  Sy t j   j |  j    } Wn+ t k
 r} | j t j k rG  qGn: X| rG|  j   } | d	 k s<| | d k rG| d Sn  y" t j d  j |  j    } Wn4 t k
 r} | j t j t j f k r  qn: X| r|  j   } | d	 k s| | d k r| d Sn  d	 S(
   s  Return the IMAP password for this repository.

        It tries to get passwords in the following order:

        1. evaluate Repository 'remotepasseval'
        2. read password from Repository 'remotepass'
        3. read password from file specified in Repository 'remotepassfile'
        4. read password from ~/.netrc
        5. read password from /etc/netrc

        On success we return the password.
        If all strategies fail we return None.t   remotepassevals   UTF-8t
   remotepasst   remotepassfilet   ri    i   s
   /etc/netrcN(   R   R   R   R   RM   t   codecst   openRq   Rr   Rs   t   readlineR   R1   R^   R_   RJ   R`   Ra   Rb   Rg   Rc   (   R   t   passwdt   passwordt   passfilet   fdRe   Rf   Rd   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   getpasswordw  s>    !

"
c         C   s   |  j    |  j | |  |  S(   s5   Return instance of OfflineIMAP representative folder.(   t   getfoldertypeR   (   R   R5   t   decode(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt	   getfolder  s    c         C   s
   t  j j S(   N(   R   t   IMAPt
   IMAPFolder(   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR     s    c         C   s#   |  j  j   } |  j  j |  d  S(   N(   R   t   acquireconnectiont   releaseconnection(   R   t   imapobj(    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   connect  s    c         C   s   d  |  _ d  S(   N(   R   R   (   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   forgetfolders  s    c         C   s  |  j  d k	 r |  j  Sg  } |  j j   } | j } |  j d t  rR | j } n  zY | d |  j j  \ } } | d k r t	 d |  j
 |  t |  f t	 j j   n  Wd |  j j |  Xx | D] } | d k s t | t  r | d k r q n  y t j |  \ } } }	 Wn( t k
 r?|  j j d |    n Xg  t j |  D] }
 |
 j   ^ qP} d | k rzq n  | j |  j   |  j |	 |    q Wt |  j  r|  j j   } z x |  j D] } y  | j t j |  d	 t WnN t	 k
 rA} | j t	 j j k r  n  |  j j | t   d
 d  qn X| j |  j   |  j | |  d t  qWWd |  j j |  Xn  |  j  d k r| j! d d    n" d   } | j! d | |  j    | |  _  |  j  S(   s@   Return a list of instances of OfflineIMAP representative folder.t   subscribedonlyt	   directoryt   OKsB   Could not list the folders for repository %s. Server responded: %sNR4   s2   could not correctly parse server response; got: %ss	   \noselectt   readonlyi   s   Invalid folderinclude:R   t   keyc         S   s   t  j |  j    S(   N(   t   strR   t   getvisiblename(   R2   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR3     R4   c            s    d t  f   f d     Y} | S(   sv   Converts a cmp= function into a key= function
                We need to keep cmp functions for backward compatibilityt   Kc              s    e  Z d    Z   f d   Z RS(   c         W   s   | |  _  d  S(   N(   t   obj(   R   R   R$   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR     s    c            s     |  j  j   | j  j    S(   N(   R   R   (   R   t   other(   t   mycmp(    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   __cmp__  s    (   t   __name__t
   __module__R   R   (    (   R   (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR     s   	(   t   object(   R   R   (    (   R   s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   cmp2key  s    ("   R   R   R   R   t   listR:   R;   t   lsubR   R   R#   R   RF   t   FOLDERR   t
   isinstanceR   t	   imapsplitt
   ValueErrorR   t   errort	   flagsplitR   t   appendR   R   t   folderincludest   selectt	   utf8_IMAPR9   t   severityR    t
   foldersortt   sort(   R   t   retvalR   t   listfunctiont   resultt
   listresultt   st   flagsR>   R#   R2   t   flaglistR5   RI   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt
   getfolders  sd    		( !			c         C   s   |  j  j r t j |  } n  |  j j   } zN | j |  } | d d k rz t d | |  t |  f t j	 j
   n  Wd |  j j |  Xd S(   s#   Delete a folder on the IMAP server.i    R   s:   Folder '%s'[%s] could not be deleted. Server responded: %sN(   R!   t   utf_8_supportR   R   R   R   t   deleteR   R   RF   R   R   (   R   R5   R   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   deletefolder  s    c         C   s  | d k r d S|  j    r9 |  j    |  j   | } n  | sN |  j   } n  |  j j |  |  |  j j rq d S|  j j   } zl |  j j r t	 j
 |  } n  | j |  } | d d k r t d | |  t |  f t j j   n  Wd |  j j |  Xd S(   s*  Create a folder on the IMAP server

        This will not update the list cached in :meth:`getfolders`. You
        will need to invoke :meth:`forgetfolders` to force new caching
        when you are done creating folders yourself.

        :param foldername: Full path of the folder to be created.R4   Ni    R   s:   Folder '%s'[%s] could not be created. Server responded: %s(   R   R@   R   t
   makefolderR!   t   dryrunR   R   R   R   R   t   createR   R   RF   R   R   (   R   R5   R   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR     s&    	(/   R   R   R   R+   R-   R0   R/   R6   R.   R%   R@   RJ   RO   R[   Rg   Rk   Rm   Ro   Rx   Rz   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R8   R   R   R   R9   R   R   R   R   R   R   R   (    (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR
   "   sX   									
	 	
		"	
					*								
	
	
	
								8				N	t   MappedIMAPRepositoryc           B   s   e  Z d    Z RS(   c         C   s
   t  j j S(   N(   R   t   UIDMapst   MappedIMAPFolder(   R   (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR   <  s    (   R   R   R   (    (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyR   ;  s   (   t   __doc__Rq   R^   Ra   R   t   sysR    t	   threadingR   RD   t   offlineimapR   R   R   R   t   offlineimap.repository.BaseR   t   offlineimap.threadutilR   t   offlineimap.utils.distroR   R	   R
   R   (    (    (    s5   /usr/share/offlineimap/offlineimap/repository/IMAP.pyt   <module>   s   "  