15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import json 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import logging 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import urlparse 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from sdk_update_common import Error 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SOURCE_WHITELIST = [ 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'http://localhost/', # For testing. 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk', 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)] 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def IsSourceValid(url): 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # E1101: Instance of 'ParseResult' has no 'scheme' member 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # pylint: disable=E1101 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) given = urlparse.urlparse(url) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for allowed_url in SOURCE_WHITELIST: 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allowed = urlparse.urlparse(allowed_url) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (given.scheme == allowed.scheme and 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) given.hostname == allowed.hostname and 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) given.path.startswith(allowed.path)): 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return True 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return False 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Config(dict): 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, data=None): 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict.__init__(self) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if data: 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.update(data) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.sources = [] 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) def LoadJson(self, json_data): 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) try: 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) self.update(json.loads(json_data)) 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) except Exception as e: 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) raise Error('Error reading json config:\n%s' % str(e)) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ToJson(self): 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) try: 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return json.dumps(self, sort_keys=False, indent=2) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) except Exception as e: 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) raise Error('Json encoding error writing config:\n%s' % e) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __getattr__(self, name): 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if name in self: 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return self[name] 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else: 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) raise AttributeError('Config does not contain: %s' % name) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __setattr__(self, name, value): 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) self[name] = value 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def AddSource(self, source): 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not IsSourceValid(source): 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warn('Only whitelisted sources are allowed. Ignoring \"%s\".' % ( 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source,)) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if source in self.sources: 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info('Source \"%s\" already in Config.' % (source,)) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.sources.append(source) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def RemoveSource(self, source): 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if source not in self.sources: 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warn('Source \"%s\" not in Config.' % (source,)) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.sources.remove(source) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def RemoveAllSources(self): 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not self.sources: 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info('No sources to remove.') 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.sources = [] 80