<s> """<STR_LIT>""" <EOL> import sys <EOL> import socket <EOL> import asyncore <EOL> import asynchat <EOL> import logging <EOL> import os <EOL> import os . path <EOL> import pwd <EOL> import mailbox <EOL> import time <EOL> import errno <EOL> import random <EOL> import asimap <EOL> import asimap . parse <EOL> import asimap . mbox <EOL> import asimap . message_cache <EOL> from asimap . client import Authenticated <EOL> from asimap . db import Database <EOL> from asimap . exceptions import MailboxLock , MailboxInconsistency <EOL> module_logger = logging . getLogger ( "<STR_LIT>" % __name__ ) <EOL> BACKLOG = <NUM_LIT:5> <EOL> def set_user_server_program ( prg ) : <EOL> """<STR_LIT>""" <EOL> module = sys . modules [ __name__ ] <EOL> setattr ( module , "<STR_LIT>" , prg ) <EOL> return <EOL> class IMAPUserClientHandler ( asynchat . async_chat ) : <EOL> """<STR_LIT>""" <EOL> LINE_TERMINATOR = "<STR_LIT:\n>" <EOL> def __init__ ( self , sock , rem_address , port , server , options ) : <EOL> """<STR_LIT:U+0020>""" <EOL> asynchat . async_chat . __init__ ( self , sock = sock ) <EOL> self . log = logging . getLogger ( "<STR_LIT>" % ( __name__ , <EOL> self . __class__ . __name__ ) ) <EOL> self . reading_message = False <EOL> self . ibuffer = [ ] <EOL> self . set_terminator ( self . LINE_TERMINATOR ) <EOL> self . port = port <EOL> self . rem_addr = rem_address <EOL> self . server = server <EOL> self . options = options <EOL> self . cmd_processor = Authenticated ( self , self . server ) <EOL> return <EOL> def log_string ( self ) : <EOL> """<STR_LIT>""" <EOL> return "<STR_LIT>" % ( self . rem_addr , self . port ) <EOL> def log_info ( self , message , type = "<STR_LIT:info>" ) : <EOL> """<STR_LIT>""" <EOL> if type not in self . ignore_log_types : <EOL> if type == "<STR_LIT:info>" : <EOL> self . log . info ( message ) <EOL> elif type == "<STR_LIT:error>" : <EOL> self . log . error ( message ) <EOL> elif type == "<STR_LIT>" : <EOL> self . log . warning ( message ) <EOL> elif type == "<STR_LIT>" : <EOL> self . log . debug ( message ) <EOL> else : <EOL> self . log . info ( message ) <EOL> def collect_incoming_data ( self , data ) : <EOL> """<STR_LIT>""" <EOL> self . ibuffer . append ( data ) <EOL> return <EOL> def found_terminator ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . reading_message : <EOL> try : <EOL> msg_length = int ( "<STR_LIT>" . join ( self . ibuffer ) . strip ( ) ) <EOL> self . ibuffer = [ ] <EOL> self . reading_message = True <EOL> self . set_terminator ( msg_length ) <EOL> except ValueError , e : <EOL> self . log . error ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( self . log_string ( ) , <EOL> "<STR_LIT>" . join ( self . ibuffer ) ) ) <EOL> return <EOL> imap_msg = "<STR_LIT>" . join ( self . ibuffer ) <EOL> self . ibuffer = [ ] <EOL> self . reading_message = False <EOL> self . set_terminator ( self . LINE_TERMINATOR ) <EOL> if self . cmd_processor . idling : <EOL> if imap_msg . lower ( ) . strip ( ) != "<STR_LIT>" : <EOL> self . push ( "<STR_LIT>" % imap_msg ) <EOL> else : <EOL> self . cmd_processor . do_done ( None ) <EOL> return <EOL> try : <EOL> imap_cmd = asimap . parse . IMAPClientCommand ( imap_msg ) <EOL> imap_cmd . parse ( ) <EOL> except asimap . parse . BadCommand , e : <EOL> if imap_cmd . tag is not None : <EOL> self . push ( "<STR_LIT>" % ( imap_cmd . tag , str ( e ) ) ) <EOL> else : <EOL> self . push ( "<STR_LIT>" % str ( e ) ) <EOL> return <EOL> self . cmd_processor . command ( imap_cmd ) <EOL> if self . cmd_processor . state == "<STR_LIT>" : <EOL> self . log . info ( "<STR_LIT>" % self . log_string ( ) ) <EOL> self . cleanup ( ) <EOL> if self . socket is not None : <EOL> self . close ( ) <EOL> return <EOL> def handle_close ( self ) : <EOL> """<STR_LIT>""" <EOL> self . log . info ( "<STR_LIT>" ) <EOL> self . cleanup ( ) <EOL> if self . socket is not None : <EOL> self . close ( ) <EOL> return <EOL> def cleanup ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . port in self . server . clients : <EOL> del self . server . clients [ self . port ] <EOL> for mbox in self . server . active_mailboxes . itervalues ( ) : <EOL> mbox . unselected ( self . cmd_processor ) <EOL> if len ( self . server . clients ) == <NUM_LIT:0> : <EOL> self . log . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> self . expiry = time . time ( ) + <NUM_LIT> <EOL> return <EOL> class IMAPUserServer ( asyncore . dispatcher ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , options , maildir ) : <EOL> """<STR_LIT>""" <EOL> self . options = options <EOL> asyncore . dispatcher . __init__ ( self ) <EOL> self . log = logging . getLogger ( "<STR_LIT>" % ( __name__ , <EOL> self . __class__ . __name__ ) ) <EOL> if self . options . standalone_mode is False : <EOL> self . create_socket ( socket . AF_INET , socket . SOCK_STREAM ) <EOL> self . set_reuse_addr ( ) <EOL> self . bind ( ( "<STR_LIT:127.0.0.1>" , <NUM_LIT:0> ) ) <EOL> self . address = self . socket . getsockname ( ) <EOL> self . listen ( BACKLOG ) <EOL> self . maildir = maildir <EOL> self . mailbox = mailbox . MH ( self . maildir , create = True ) <EOL> self . uid_vv = <NUM_LIT:0> <EOL> self . db = Database ( maildir ) <EOL> self . active_mailboxes = { } <EOL> self . clients = { } <EOL> self . msg_cache = asimap . message_cache . MessageCache ( ) <EOL> self . expiry = time . time ( ) + <NUM_LIT> <EOL> self . _restore_from_db ( ) <EOL> return <EOL> def _restore_from_db ( self ) : <EOL> """<STR_LIT>""" <EOL> c = self . db . cursor ( ) <EOL> c . execute ( "<STR_LIT>" ) <EOL> results = c . fetchone ( ) <EOL> if results is None : <EOL> c . execute ( "<STR_LIT>" , <EOL> str ( self . uid_vv ) ) <EOL> c . close ( ) <EOL> self . db . commit ( ) <EOL> else : <EOL> self . uid_vv = int ( results [ <NUM_LIT:0> ] ) <EOL> c . close ( ) <EOL> return <EOL> def has_queued_commands ( self ) : <EOL> """<STR_LIT>""" <EOL> return any ( len ( x . command_queue ) > <NUM_LIT:0> <EOL> for x in self . active_mailboxes . itervalues ( ) ) <EOL> def process_queued_commands ( self , ) : <EOL> """<STR_LIT>""" <EOL> mboxes = [ x for x in self . active_mailboxes . values ( ) <EOL> if x . has_queued_commands ( ) ] <EOL> if len ( mboxes ) == <NUM_LIT:0> : <EOL> return <EOL> start_time = time . time ( ) <EOL> num_queued_cmds = sum ( len ( x . command_queue ) for x in mboxes ) <EOL> self . log . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" % num_queued_cmds ) <EOL> random . shuffle ( mboxes ) <EOL> for mbox in mboxes : <EOL> if len ( mbox . command_queue ) == <NUM_LIT:0> : <EOL> continue <EOL> self . log . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( mbox . name , <EOL> len ( mbox . command_queue ) ) ) <EOL> client , imap_cmd = mbox . command_queue . pop ( <NUM_LIT:0> ) <EOL> if not client . client . connected : <EOL> continue <EOL> try : <EOL> self . log . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( mbox . name , client . name , <EOL> str ( imap_cmd ) ) ) <EOL> client . command ( imap_cmd ) <EOL> except Exception : <EOL> nil , t , v , tbinfo = asyncore . compact_traceback ( ) <EOL> self . log . error ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( t , v , tbinfo ) ) <EOL> now = time . time ( ) <EOL> if now - start_time > <NUM_LIT:5> : <EOL> self . log . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> ( now - start_time ) ) <EOL> return <EOL> now = time . time ( ) <EOL> self . log . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( now - start_time ) ) <EOL> return <EOL> def get_next_uid_vv ( self ) : <EOL> """<STR_LIT>""" <EOL> self . uid_vv += <NUM_LIT:1> <EOL> c = self . db . cursor ( ) <EOL> c . execute ( "<STR_LIT>" , ( str ( self . uid_vv ) , ) ) <EOL> c . close ( ) <EOL> self . db . commit ( ) <EOL> return self . uid_vv <EOL> def log_info ( self , message , type = "<STR_LIT:info>" ) : <EOL> """<STR_LIT>""" <EOL> if type not in self . ignore_log_types : <EOL> if type == "<STR_LIT:info>" : <EOL> self . log . info ( message ) <EOL> elif type == "<STR_LIT:error>" : <EOL> self . log . error ( message ) <EOL> elif type == "<STR_LIT>" : <EOL> self . log . warning ( message ) <EOL> elif type == "<STR_LIT>" : <EOL> self . log . debug ( message ) <EOL> else : <EOL> self . log . info ( message ) <EOL> return <EOL> def get_mailbox ( self , name , expiry = <NUM_LIT> ) : <EOL> """<STR_LIT>""" <EOL> if name . lower ( ) == "<STR_LIT>" : <EOL> name = "<STR_LIT>" <EOL> if name in self . active_mailboxes : <EOL> return self . active_mailboxes [ name ] <EOL> mbox = asimap . mbox . Mailbox ( name , self , expiry = expiry ) <EOL> self . active_mailboxes [ name ] = mbox <EOL> return mbox <EOL> def check_all_active_folders ( self ) : <EOL> """<STR_LIT>""" <EOL> for name , mbox in self . active_mailboxes . iteritems ( ) : <EOL> if any ( x . idling for x in mbox . clients . itervalues ( ) ) : <EOL> try : <EOL> self . log . debug ( "<STR_LIT>" % name ) <EOL> mbox . resync ( ) <EOL> except ( MailboxLock , MailboxInconsistency ) , e : <EOL> self . log . warn ( "<STR_LIT>" <EOL> "<STR_LIT:%s>" % ( name , str ( e ) ) ) <EOL> return <EOL> def expire_inactive_folders ( self ) : <EOL> """<STR_LIT>""" <EOL> expired = [ ] <EOL> for mbox_name , mbox in self . active_mailboxes . iteritems ( ) : <EOL> if len ( mbox . clients ) == <NUM_LIT:0> and mbox . expiry is not None and mbox . expiry < time . time ( ) : <EOL> expired . append ( mbox_name ) <EOL> for mbox_name in expired : <EOL> self . active_mailboxes [ mbox_name ] . commit_to_db ( ) <EOL> del self . active_mailboxes [ mbox_name ] <EOL> self . msg_cache . clear_mbox ( mbox_name ) <EOL> if len ( expired ) > <NUM_LIT:0> : <EOL> self . log . debug ( "<STR_LIT>" % <EOL> len ( expired ) ) <EOL> return <EOL> def find_all_folders ( self ) : <EOL> """<STR_LIT>""" <EOL> start_time = time . time ( ) <EOL> self . log . debug ( "<STR_LIT>" ) <EOL> extant_mboxes = { } <EOL> mboxes_to_create = [ ] <EOL> c = self . db . cursor ( ) <EOL> c . execute ( "<STR_LIT>" ) <EOL> for row in c : <EOL> name , mtime = row <EOL> extant_mboxes [ name ] = mtime <EOL> c . close ( ) <EOL> for root , dirs , files in os . walk ( '<STR_LIT:.>' , followlinks = True ) : <EOL> for d in dirs : <EOL> dirname = os . path . normpath ( os . path . join ( root , d ) ) <EOL> if dirname not in extant_mboxes : <EOL> mboxes_to_create . append ( dirname ) <EOL> for mbox_name in mboxes_to_create : <EOL> self . log . debug ( "<STR_LIT>" % mbox_name ) <EOL> self . get_mailbox ( mbox_name , expiry = <NUM_LIT:0> ) <EOL> self . log . debug ( "<STR_LIT>" % <EOL> ( time . time ( ) - start_time ) ) <EOL> def check_all_folders ( self , force = False ) : <EOL> """<STR_LIT>""" <EOL> start_time = time . time ( ) <EOL> self . log . debug ( "<STR_LIT>" ) <EOL> mboxes = [ ] <EOL> c = self . db . cursor ( ) <EOL> c . execute ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> for row in c : <EOL> mboxes . append ( row ) <EOL> c . close ( ) <EOL> for mbox_name , mtime in mboxes : <EOL> if mbox_name in self . active_mailboxes and ( any ( x . idling for x in self . active_mailboxes [ mbox_name ] . clients . itervalues ( ) ) or len ( self . active_mailboxes [ mbox_name ] . command_queue ) > <NUM_LIT:0> ) : <EOL> continue <EOL> path = os . path . join ( self . mailbox . _path , mbox_name ) <EOL> seq_path = os . path . join ( path , "<STR_LIT>" ) <EOL> try : <EOL> fmtime = asimap . mbox . Mailbox . get_actual_mtime ( self . mailbox , <EOL> mbox_name ) <EOL> if ( fmtime > mtime ) or force : <EOL> self . log . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( mbox_name , mtime , fmtime ) ) <EOL> m = self . get_mailbox ( mbox_name , <NUM_LIT:30> ) <EOL> if ( m . mtime >= fmtime ) and not force : <EOL> m . commit_to_db ( ) <EOL> else : <EOL> m . resync ( force = force ) <EOL> except ( MailboxLock , MailboxInconsistency ) , e : <EOL> self . log . warn ( "<STR_LIT>" <EOL> "<STR_LIT:%s>" % ( mbox_name , str ( e ) ) ) <EOL> except ( OSError , IOError ) , e : <EOL> if e . errno == errno . ENOENT : <EOL> self . log . error ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( path , <EOL> seq_path ) ) <EOL> self . log . debug ( "<STR_LIT>" % ( time . time ( ) - start_time ) ) <EOL> return <EOL> def handle_accept ( self ) : <EOL> """<STR_LIT>""" <EOL> pair = self . accept ( ) <EOL> if pair is not None : <EOL> sock , addr = pair <EOL> self . log . info ( "<STR_LIT>" % addr ) <EOL> self . expiry = None <EOL> handler = IMAPUserClientHandler ( sock , addr [ <NUM_LIT:0> ] , addr [ <NUM_LIT:1> ] , self , <EOL> self . options ) <EOL> self . clients [ addr [ <NUM_LIT:1> ] ] = handler </s>
