1# Copyright (c) 2012 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import json
6import logging
7import urlparse
8from sdk_update_common import Error
9
10SOURCE_WHITELIST = [
11  'http://localhost/',  # For testing.
12  'https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk',
13]
14
15def IsSourceValid(url):
16  # E1101: Instance of 'ParseResult' has no 'scheme' member
17  # pylint: disable=E1101
18
19  given = urlparse.urlparse(url)
20  for allowed_url in SOURCE_WHITELIST:
21    allowed = urlparse.urlparse(allowed_url)
22    if (given.scheme == allowed.scheme and
23        given.hostname == allowed.hostname and
24        given.path.startswith(allowed.path)):
25      return True
26  return False
27
28
29class Config(dict):
30  def __init__(self, data=None):
31    dict.__init__(self)
32    if data:
33      self.update(data)
34    else:
35      self.sources = []
36
37  def LoadJson(self, json_data):
38    try:
39      self.update(json.loads(json_data))
40    except Exception as e:
41      raise Error('Error reading json config:\n%s' % str(e))
42
43  def ToJson(self):
44    try:
45      return json.dumps(self, sort_keys=False, indent=2)
46    except Exception as e:
47      raise Error('Json encoding error writing config:\n%s' % e)
48
49  def __getattr__(self, name):
50    if name in self:
51      return self[name]
52    else:
53      raise AttributeError('Config does not contain: %s' % name)
54
55  def __setattr__(self, name, value):
56    self[name] = value
57
58  def AddSource(self, source):
59    if not IsSourceValid(source):
60      logging.warn('Only whitelisted sources are allowed. Ignoring \"%s\".' % (
61          source,))
62      return
63
64    if source in self.sources:
65      logging.info('Source \"%s\" already in Config.' % (source,))
66      return
67    self.sources.append(source)
68
69  def RemoveSource(self, source):
70    if source not in self.sources:
71      logging.warn('Source \"%s\" not in Config.' % (source,))
72      return
73    self.sources.remove(source)
74
75  def RemoveAllSources(self):
76    if not self.sources:
77      logging.info('No sources to remove.')
78      return
79    self.sources = []
80