<s> import hashlib <EOL> import hmac <EOL> import os <EOL> import tempfile <EOL> from . decorator import StoreDecorator <EOL> class _HMACFileReader ( object ) : <EOL> def __init__ ( self , hm , source ) : <EOL> self . hm = hm <EOL> self . source = source <EOL> self . buffer = source . read ( self . hm . digest_size ) <EOL> if not len ( self . buffer ) == self . hm . digest_size : <EOL> raise VerificationException ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> def read ( self , n = None ) : <EOL> if '<STR_LIT>' == self . buffer or <NUM_LIT:0> == n : <EOL> return '<STR_LIT>' <EOL> new_read = self . source . read ( n ) if None != n else self . source . read ( ) <EOL> finished = ( None == n or len ( new_read ) != n ) <EOL> self . buffer += new_read <EOL> if None != n : <EOL> offset = min ( n , len ( self . buffer ) - self . hm . digest_size ) <EOL> else : <EOL> offset = len ( self . buffer ) - self . hm . digest_size <EOL> rv , self . buffer = self . buffer [ : offset ] , self . buffer [ offset : ] <EOL> self . hm . update ( rv ) <EOL> if finished : <EOL> if not self . buffer == self . hm . digest ( ) : <EOL> raise VerificationException ( '<STR_LIT>' ) <EOL> return rv <EOL> def close ( self ) : <EOL> self . source . close ( ) <EOL> def __enter__ ( self ) : <EOL> return self <EOL> def __exit__ ( self , * args ) : <EOL> self . close ( ) <EOL> class VerificationException ( Exception ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> class HMACDecorator ( StoreDecorator ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , secret_key , decorated_store , hashfunc = hashlib . sha256 ) : <EOL> super ( HMACDecorator , self ) . __init__ ( decorated_store ) <EOL> self . __hashfunc = hashfunc <EOL> self . __secret_key = bytes ( secret_key ) <EOL> @ property <EOL> def hmac_digestsize ( self ) : <EOL> return self . hmac_mixin_hashfunc ( ) . digestsize <EOL> def __new_hmac ( self , key , msg = None ) : <EOL> if not msg : <EOL> msg = b'<STR_LIT>' <EOL> hm = hmac . HMAC ( <EOL> key = key . encode ( '<STR_LIT:ascii>' ) + self . __secret_key , <EOL> msg = msg , <EOL> digestmod = self . __hashfunc ) <EOL> return hm <EOL> def get ( self , key ) : <EOL> buf = self . _dstore . get ( key ) <EOL> hm = self . __new_hmac ( key ) <EOL> hash = buf [ - hm . digest_size : ] <EOL> buf = buf [ : - hm . digest_size ] <EOL> hm . update ( buf ) <EOL> if not hm . digest ( ) == hash : <EOL> raise VerificationException ( '<STR_LIT>' % key ) <EOL> return buf <EOL> def get_file ( self , key , file ) : <EOL> if isinstance ( file , str ) : <EOL> try : <EOL> f = open ( file , '<STR_LIT:wb>' ) <EOL> except OSError as e : <EOL> raise IOError ( '<STR_LIT>' % ( <EOL> file , e <EOL> ) ) <EOL> try : <EOL> self . get_file ( key , f ) <EOL> finally : <EOL> f . close ( ) <EOL> else : <EOL> source = self . open ( key ) <EOL> bufsize = <NUM_LIT> * <NUM_LIT> <EOL> while True : <EOL> buf = source . read ( bufsize ) <EOL> file . write ( buf ) <EOL> if len ( buf ) != bufsize : <EOL> break <EOL> def open ( self , key ) : <EOL> source = self . _dstore . open ( key ) <EOL> return _HMACFileReader ( self . __new_hmac ( key ) , source ) <EOL> def put ( self , key , value , * args , ** kwargs ) : <EOL> data = value + self . __new_hmac ( key , value ) . digest ( ) <EOL> return self . _dstore . put ( key , data , * args , ** kwargs ) <EOL> def put_file ( self , key , file , * args , ** kwargs ) : <EOL> hm = self . __new_hmac ( key ) <EOL> bufsize = <NUM_LIT> * <NUM_LIT> <EOL> if isinstance ( file , str ) : <EOL> with open ( file , '<STR_LIT>' ) as source : <EOL> while True : <EOL> buf = source . read ( bufsize ) <EOL> hm . update ( buf ) <EOL> if len ( buf ) < bufsize : <EOL> break <EOL> source . write ( hm . digest ( ) ) <EOL> return self . _dstore . put_file ( key , file , * args , ** kwargs ) <EOL> else : <EOL> tmpfile = tempfile . NamedTemporaryFile ( delete = False ) <EOL> try : <EOL> while True : <EOL> buf = file . read ( bufsize ) <EOL> hm . update ( buf ) <EOL> tmpfile . write ( buf ) <EOL> if len ( buf ) < bufsize : <EOL> break <EOL> tmpfile . write ( hm . digest ( ) ) <EOL> tmpfile . close ( ) <EOL> return self . _dstore . put_file ( <EOL> key , tmpfile . name , * args , ** kwargs <EOL> ) <EOL> finally : <EOL> os . unlink ( tmpfile . name ) </s>
