PageRenderTime 146ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/snappy/backend/configmanagers/fileconfigmanager.py

https://github.com/donaldharvey/snappy
Python | 135 lines | 133 code | 0 blank | 2 comment | 1 complexity | f9f18d90ee567e7beb052e352a8ab102 MD5 | raw file
Possible License(s): GPL-3.0
  1. from configmanager import ConfigManager, ConfigDict
  2. from ConfigParser import SafeConfigParser, NoSectionError
  3. import sys
  4. import os
  5. from Crypto.Cipher import Blowfish #for password storage
  6. from hashlib import sha1
  7. from random import randrange
  8. from base64 import encodestring as b64enc, decodestring as b64dec
  9. def app_data_dir(appname='snappy'):
  10. '''
  11. Returns (and creates if it does not exist) the application's data directory for all 3 major platforms.
  12. Based on http://[stackoverflow url].
  13. '''
  14. if sys.platform == 'darwin':
  15. from AppKit import NSSearchPathForDirectoriesInDomains
  16. # http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSearchPathForDirectoriesInDomains
  17. # NSApplicationSupportDirectory = 14
  18. # NSUserDomainMask = 1
  19. # True for expanding the tilde into a fully qualified path
  20. appdata = os.path.join(NSSearchPathForDirectoriesInDomains(14, 1, True)[0], appname)
  21. elif sys.platform == 'win32':
  22. appdata = os.path.join(environ['APPDATA'], appname)
  23. else:
  24. appdata = os.path.expanduser(os.path.join("~", "." + appname))
  25. if not os.access(appdata, os.F_OK):
  26. os.mkdir(appdata)
  27. return appdata
  28. class FileConfigManager(ConfigManager):
  29. def __init__(self):
  30. super(FileConfigManager, self).__init__()
  31. self.settings = FileConfigDict()
  32. def _pad_pass(self, password):
  33. pad_bytes = 8 - (len(password) % 8)
  34. for i in range(pad_bytes - 1):
  35. password += chr(randrange(0, 256))
  36. # final padding byte; % by 8 to get the number of padding bytes
  37. bflag = randrange(6, 248)
  38. bflag -= bflag % 8 - pad_bytes
  39. password += chr(bflag)
  40. return password
  41. def _depad_pass(self, password):
  42. pad_bytes = ord(password[-1]) % 8
  43. if not pad_bytes:
  44. pad_bytes = 8
  45. return password[:-pad_bytes]
  46. def set_password(self, key, password):
  47. cryptkey = sha1(key).hexdigest()
  48. bf = Blowfish.new(cryptkey, Blowfish.MODE_ECB)
  49. encrypted_pass = bf.encrypt(self._pad_pass(password))
  50. del password
  51. self[cryptkey] = b64enc(encrypted_pass)
  52. def get_password(self, key):
  53. cryptkey = sha1(key).hexdigest()
  54. bf = Blowfish.new(cryptkey, Blowfish.MODE_ECB)
  55. try:
  56. encrypted_pass = b64dec(self[cryptkey])
  57. except Exception:
  58. return ''
  59. try:
  60. decrypted_pass = self._depad_pass(bf.decrypt(encrypted_pass))
  61. return decrypted_pass
  62. except Exception:
  63. return ''
  64. class FileConfigDict(ConfigDict):
  65. def __init__(self):
  66. super(FileConfigDict, self).__init__()
  67. self.filename = os.path.join(app_data_dir(), 'settings.cfg')
  68. if not os.path.exists(self.filename):
  69. open(self.filename, 'w').close()
  70. self.parser = SafeConfigParser()
  71. f = open(self.filename, 'r+')
  72. self.parser.readfp(f)
  73. f.close()
  74. self.defaults = {}
  75. def __getitem__(self, key):
  76. try:
  77. section, option = key.split('.', 1)
  78. except ValueError:
  79. section, option = 'misc', key
  80. if option == '*':
  81. opts_dict = {}
  82. for key in self.defaults.keys():
  83. if key.startswith(section):
  84. opts_dict[key.split('.', 1)[1]] = self.defaults[key]
  85. try:
  86. opt_names = self.parser.options(section)
  87. except NoSectionError:
  88. pass
  89. else:
  90. for opt_name in opt_names:
  91. opts_dict[opt_name] = self.parser.get(section, opt_name)
  92. return opts_dict
  93. try:
  94. result = self.parser.get(section, option)
  95. except Exception:
  96. result = self.defaults.get(key)
  97. if result == None:
  98. return ''
  99. else:
  100. return result
  101. def __setitem__(self, key, value):
  102. try:
  103. section, option = key.split('.', 1)
  104. except ValueError:
  105. section, option = 'misc', key
  106. if not self.parser.has_section(section):
  107. self.parser.add_section(section)
  108. self.parser.set(section, option, value)
  109. f = open(self.filename, 'w')
  110. self.parser.write(f)
  111. f.close()
  112. def __delitem__(self, key):
  113. try:
  114. section, option = key.split('.', 1)
  115. except ValueError:
  116. section, option = 'misc', key
  117. self.parser.remove_option(section, option)
  118. def keys(self):
  119. keys = list()
  120. for section in self.parser.sections():
  121. for option in self.parser.items(section):
  122. keys.append(section + '.' + option[0])
  123. return keys