#NEWLINE# def parse_client_keys( stream ) : #NEWLINE# #INDENT# '\n    This parses a hidden-service "client_keys" file, either stealth or\n    basic (they\'re the same, except "stealth" includes a\n    "client-key"). Returns a list of HiddenServiceClientAuth() instances.\n\n    Note that the key does NOT include the "----BEGIN ---" markers,\n    nor *any* embedded whitespace. It is *just* the key blob.\n\n    ' #NEWLINE# def parse_error( data ) : #NEWLINE# #INDENT# raise RuntimeError ( ( 'Parse error at: ' + data ) ) #NEWLINE# #UNINDENT# class ParserState ( object ) : #NEWLINE# #INDENT# def __init__( self ) : #NEWLINE# #INDENT# self . keys = [ ] #NEWLINE# self . reset ( ) #NEWLINE# #UNINDENT# def reset( self ) : #NEWLINE# #INDENT# self . name = None #NEWLINE# self . cookie = None #NEWLINE# self . key = [ ] #NEWLINE# #UNINDENT# def create_key( self ) : #NEWLINE# #INDENT# if ( self . name is not None ) : #NEWLINE# #INDENT# self . keys . append ( HiddenServiceClientAuth ( self . name , self . cookie , self . key ) ) #NEWLINE# #UNINDENT# self . reset ( ) #NEWLINE# #UNINDENT# def set_name( self , name ) : #NEWLINE# #INDENT# self . create_key ( ) #NEWLINE# self . name = name . split ( ) [ 1 ] #NEWLINE# #UNINDENT# def set_cookie( self , cookie ) : #NEWLINE# #INDENT# self . cookie = cookie . split ( ) [ 1 ] #NEWLINE# if self . cookie . endswith ( '==' ) : #NEWLINE# #INDENT# self . cookie = self . cookie [ : ( - 2 ) ] #NEWLINE# #UNINDENT# #UNINDENT# def add_key_line( self , line ) : #NEWLINE# #INDENT# self . key . append ( line ) #NEWLINE# #UNINDENT# #UNINDENT# from txtorcon.spaghetti import FSM , State , Transition #NEWLINE# init = State ( 'init' ) #NEWLINE# got_name = State ( 'got_name' ) #NEWLINE# got_cookie = State ( 'got_cookie' ) #NEWLINE# reading_key = State ( 'got_key' ) #NEWLINE# parser_state = ParserState ( ) #NEWLINE# init . add_transitions ( [ Transition ( got_name , ( lambda line : line . startswith ( 'client-name ' ) ) , parser_state . set_name ) , Transition ( init , ( lambda line : ( not line . startswith ( 'client-name ' ) ) ) , parse_error ) ] ) #NEWLINE# got_name . add_transitions ( [ Transition ( got_cookie , ( lambda line : line . startswith ( 'descriptor-cookie ' ) ) , parser_state . set_cookie ) , Transition ( init , ( lambda line : ( not line . startswith ( 'descriptor-cookie ' ) ) ) , parse_error ) ] ) #NEWLINE# got_cookie . add_transitions ( [ Transition ( reading_key , ( lambda line : line . startswith ( 'client-key' ) ) , None ) , Transition ( got_name , ( lambda line : line . startswith ( 'client-name ' ) ) , parser_state . set_name ) ] ) #NEWLINE# reading_key . add_transitions ( [ Transition ( reading_key , ( lambda line : ( not line . startswith ( 'client-name' ) ) ) , parser_state . add_key_line ) , Transition ( got_name , ( lambda line : line . startswith ( 'client-name ' ) ) , parser_state . set_name ) ] ) #NEWLINE# fsm = FSM ( [ init , got_name , got_cookie , reading_key ] ) #NEWLINE# for line in stream . readlines ( ) : #NEWLINE# #INDENT# fsm . process ( line . strip ( ) ) #NEWLINE# #UNINDENT# parser_state . create_key ( ) #NEWLINE# return parser_state . keys