diff --git a/windows/amdicon.py b/windows/amdicon.py new file mode 100644 index 000000000..a26ca3c35 --- /dev/null +++ b/windows/amdicon.py @@ -0,0 +1,69 @@ +#---------------------------------------------------------------------- +# This file was generated by encode_icons.py +# +from wx import ImageFromStream, BitmapFromImage +from wx import EmptyIcon +import cStringIO + + +def getData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\ +\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x04\ +\x1aIDATX\x85\xad\x97MLTW\x14\xc7\xff\xef\xbd\x997|\x8c\x86\xb1\x888\x0c\x06\ +\x17\x80\x03\xa1\x8a\t\xa9\x8d5a\xd3t\xd3\xa4\xed\xae+\xe3\xa6\xe9\x02v\x8d\ +\xdd\xb8\xd2%D\xb1\x06\x02]\xd9.\xba\xd0\xa4iBqaHHM\xcbnbGZeH\x8d\x16\xad\ +\xed\x14\x91\xe1c\x98\xb9\xf7\xbdw\xcf\xe9\x02\x9c\xf2\xf1\xde\x9b7\xc8\x99L\ +2\x99{\xce\xb9\xbfs\xee\xb9\xe7\xde\xabi\xba\x81\xa0\x12\x1eN2\xd9!\x90\x1d\ +\xc2\xdb\x87\x92\xa8\xab\x8abY\xe41\xb34\x0b=\xec\xc00mX}\x19-\xb0C\x00\xd0t\ +#\xd0\xd7\xb8\xde\xcd-\xa3\x1f\xf3\xcd\x99\t\xce\x895\xde*9\xb1\xc67g&\xb8e\ +\xec#\x0e}u\x8a\x83\xfa\xd4t#\x18\x80q\xed4_\xb8s\x85\xcbIN\xac\xf1\x85;W\ +\xd8\xb8v:0D\xf9\xc9\x87\xba\xf9\xfc\xc4eV;>S\xf3)\x9e\x9aO\xf1\xfdlf\xd7\ +\xd8\xf9\x89\xcbl\\\xef\x0e\x06\xe1W\x03\xa1\x1b\x1d|&\xf6.\xee~:T\xfao\xe2\ +\x8fi\\\xfci\x04\x7f\x15\x9e\x03:\x03\xa4!Q\xd3\x8c\xc1\xde>|\xd8z\xb6\xa4w\ +\xe6\xdb\xcf\x90\x113\xb0\xfbg\xfdk\xa2\\\xea\xc7\x9fL\xf1\x92\xbd\xc8K\xf6"\ +\x8f\xa4o\xb16\xd8\xc3\x91\xd1\xcem\xd1EF;Y\x1b\xec\xe1\x91\xf4\xad\x92\xee\ +\xf8\x93\xa9@K\xa1\xfb\xc1\xc5\xab\xe2\xe8ij\x83$\x81\x97\xc5W\xb8to\x0cf\ +\xb4\xb0\xab\xd2\xad\xbe\x8cfF\x0b\xb8to\x0c/\x8b\xaf I\xa0\xa7\xa9\r\xf1\ +\xea\xb8\xff\x0e\x00\xbc\x01B7:\xf8\x9dD\x12\x92\x05$\x0b|\xf7p\x12y\xe4<\ +\xb7\x99\xd5\x97\xd1\xf2\xc8\xe1\xc7\xc7\xd3%\x9bd\xfd1\x84\x87\x93\xbc\'\ +\x00\x008z \x06I\x02\x92\x04rb\x15\x9a\xa1|\xa3\xd1\x0c\x85\xf9\x95l\xc9\xa6\ +\xbd>\x01&\xff\x12\x08\xf9\r:\xec@\x92(\xfd\x0e"\x95\xda\x94\x01\xb0\xb78\ +\xb3\x03\x02Tf\xe3\t\xa0\xa4\t\x87\x1d\x08*\x02\x00\xea\xa3Qt\x1e\xec\x00\ +\xbe\xe9\xf0]\xd3\xfah\xb4d\xe3\xb0\x03%M_\x00\xd7>\xa0\r\x9e\xe2/\xce~\x82\ +\x0f\xdaO\x96\x8d\xa0\x9c\xdc\x9d{\x80\xab\xd3?\x80/\xa6]\x8b\xc15\x03-\x07\ +\xe3\xe8mm/\xa5\xf2M\xa4\xb7\xb5\x1d\xdf\xff\x16\xc7S\xa4]\xc7]\x01\xaa\xcd\ +\xf0\xbeL\xbe\xd5\x9f\x97\xb8\x020\x13\xc4>\x020Se\x00\x04\x82do\x80\xb9\xec\ +\x02&\x1feP\xb0,\xd4\x98&\xde\xef8\x81\xf6\xc6\x06O}B\xa5\x00L\xa5J\xde)\x0f\ +\x9e\xfd\x83\xaf\x7f\xfe\x05\xe1\xda"\xec\xfeY-<\x9c\xe4\xfb\x93\x7f\xe2\xf3\ +s\xef\xe1\xe4\xb1\xa3\xee\x00{\xca\x80\xcb\x12,;K\xb8\x9dJo;\x0f\xec\xfeY\ +\xcd\x1c9\xc1\xb7S\xbf\xe2\xad\x06\x0bu\xa1\x18\xc2\xba\xb9\xcb\xdf\x1e\x00$\ +\x14;X\xb0\xb3\xf8\xd7z\x81U\xb5\x02b\x85e\xa1\x83\xbf\xdc}\x18\xd9\x03\xd5<\ +\x99\x1b\x07\x81P\xa5W\xe3p\xf8\x08\x8eW\xb5\xe1\x88\x19\xaf\x1c\x80\x99\xf0\ +B>\xc3\xbc|\x0c\x8b,\x10\x14\x14\x13\x88\x15\x98j\\\x1d1i\x90,A\xacP\xa0u,\ +\xda\x0bx\xb8\x9e\xc6a\xb3\x11k\x8ew}\xb8\x1eFy\xb5\x86\xb9\xe2\xef(\xa8\xf5\ +\xcd\x83E\xc2\xa2\x8d\x13\xae\xb1Y\xc0\x18\xea\xda\xd6\r\x8d\xa1.\x8e5\xadl\ +\xeaHX$7\xecX\xe2\xb9x\x8aU\xb5R\x19\xc0\xeb~.Y\xc2\xe2\xff\x9dY$\xd1p|\t\ +\xb5Q\xa7\x04a\x0cuq\xa4V\xa2\xae\xe5\xefM\x1d\x01\x8b$\x1c\xb672\x06\xdf\ +\xce\xed]\x03\x16I((\x10+\x106\xd2\xafX\x81\x0cB]3!\xff\xa8\x11\x00\xc0\xac\ +\xe1@"\x0bG/\x80\xc9\x7f\xb2\xe0\x00\xbc\xd1\x07\x88is\xfd\xb7C\xd8\xac\xef\ +\xd2/\x17iE\x00\xbc3\x03L\xdb\xb2\xe1\x90wk\xdd\x17\x00\x02C\x92\x00\x816\ +\xa3W`\xe6=GY9\x00\x13,\x96\xbe\xa9%+\x04m\xa0\x9b\xc9\xaa\xec%\x16\x08\x80\ +\xc1P\xec}\xff\x8b\xd4\xad"q.\xf5F\x13\xbf\x16\xd7mHN\xf0\x07k\x10\xf1\xf3\ +\xe7\n\xa0\xa4\x89\xe2bl_&/.\xc6\xa0D\xc4s\xdc\xf3i\xa6\rt\xb3Q%\xa1\x87\xfc\ +\xaf\xe2~B\x8e\x01%M\xcf\xeb\x18\x00\xfc\x07\x9aY\xdf_&\xed\xfd\xe8\x00\x00\ +\x00\x00IEND\xaeB`\x82' + +def getBitmap(): + return BitmapFromImage(getImage()) + +def getImage(): + stream = cStringIO.StringIO(getData()) + return ImageFromStream(stream) + +def getIcon(): + icon = EmptyIcon() + icon.CopyFromBitmap(getBitmap()) + return icon + + diff --git a/windows/confwiz.py b/windows/confwiz.py index f26484f2c..334c0d711 100644 --- a/windows/confwiz.py +++ b/windows/confwiz.py @@ -1,10 +1,22 @@ +BACKEND_URL = 'https://www-test.allmydata.com/native_client2.php' +REGISTER_PAGE = 'https://www-test.allmydata.com/register' +WINSVC_NAME = 'Tahoe' + +import os +import sys +import traceback import urllib2 from urllib import urlencode +import webbrowser +import wx from allmydata.util.assertutil import precondition from allmydata import uri +import amdicon + + class AuthError(Exception): pass @@ -12,6 +24,7 @@ def unicode_to_utf8(uobj): assert precondition(isinstance(uobj, unicode)) return uobj.encode('utf-8') + def post(url, args): argstr = urlencode(args) conn = urllib2.urlopen(url, argstr) @@ -34,12 +47,166 @@ def get_root_cap(url, user, passwd): def get_introducer_furl(url): return post(url, { 'action': 'getintroducerfurl' }) +def write_config_file(filename, contents): + if sys.platform == 'win32': + from allmydata.windows import registry + basedir = registry.get_base_dir_path() + else: + basedir = os.path.expanduser('~/.tahoe') + path = os.path.join(basedir, filename) + dirname = os.path.dirname(path) + if not os.path.exists(dirname): + os.makedirs(dirname) + iff = file(path, 'wb') + iff.write(contents) + iff.close() + + +def DisplayTraceback(message): + xc = traceback.format_exception(*sys.exc_info()) + wx.MessageBox(u"%s\n (%s)"%(message,''.join(xc)), 'Error') + +class ConfWizApp(wx.App): + def __init__(self): + wx.App.__init__(self, 0) + + def OnInit(self): + try: + wx.InitAllImageHandlers() + + self.frame = ConfWizFrame(self) + self.frame.CenterOnScreen() + self.SetTopWindow(self.frame) + self.SetExitOnFrameDelete(True) + self.frame.Show(True) + + return True + except: + DisplayTraceback('config wizard init threw an exception') + +class ConfWizFrame(wx.Frame): + def __init__(self, app): + title = 'Allmydata Tahoe Config Wizard' + wx.Frame.__init__(self, None, -1, title) + self.app = app + self.SetSizeHints(100, 100, 600, 800) + self.SetIcon(amdicon.getIcon()) + self.Bind(wx.EVT_CLOSE, self.close) + + background = wx.Panel(self, -1) + background.parent = self + self.login_panel = LoginPanel(background) + self.register_panel = RegisterPanel(background) + sizer = wx.BoxSizer(wx.VERTICAL) + background_sizer = wx.BoxSizer(wx.VERTICAL) + background_sizer.Add(self.login_panel, 1, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 26) + background_sizer.Add(self.register_panel, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 26) + background.SetSizer(background_sizer) + sizer.Add(background, 0, wx.EXPAND | wx.ALL, 0) + self.SetSizer(sizer) + self.SetAutoLayout(True) + self.Fit() + self.Layout() + + def close(self, event): + sys.exit() + +class LoginPanel(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent, -1) + self.parent = parent + + self.sizer = wx.BoxSizer(wx.VERTICAL) + + self.user_label = wx.StaticText(self, -1, 'Email') + self.pass_label = wx.StaticText(self, -1, 'Password') + self.user_field = wx.TextCtrl(self, -1, u'', size=(260,-1)) + self.pass_field = wx.TextCtrl(self, -1, u'', size=(260,-1), style=wx.TE_PASSWORD) + self.login_button = wx.Button(self, -1, 'Sign In') + self.warning_label = wx.StaticText(self, -1, '') + self.warning_label.SetOwnForegroundColour(wx.RED) + wx.EVT_CHAR(self.user_field, self.on_user_entry) + wx.EVT_CHAR(self.pass_field, self.on_pass_entry) + self.Bind(wx.EVT_BUTTON, self.on_login, self.login_button) + login_sizer = wx.FlexGridSizer(3, 2, 5, 4) + login_sizer.Add(self.user_label, 0, wx.ALIGN_RIGHT | wx.ALL, 2) + login_sizer.Add(self.user_field, 0, wx.EXPAND | wx.ALL, 2) + login_sizer.Add(self.pass_label, 0, wx.ALIGN_RIGHT | wx.ALL, 2) + login_sizer.Add(self.pass_field, 0, wx.EXPAND | wx.ALL, 2) + login_sizer.Add(wx.Size(2,2), 0, wx.ALIGN_RIGHT | wx.ALL, 2) + login_sizer.Add(self.login_button, 0, wx.ALIGN_RIGHT | wx.ALL, 2) + self.sizer.Add(login_sizer, 1, wx.EXPAND | wx.ALL, 2) + #self.sizer.Add(self.warning_label, 0, wx.EXPAND | wx.ALL, 2) + self.sizer.Add(self.warning_label, 0, wx.CENTER | wx.ALL, 2) + self.SetSizer(self.sizer) + self.SetAutoLayout(True) + + def on_user_entry(self, event): + if event.GetKeyCode() == wx.WXK_RETURN: + self.pass_field.SetFocus() + else: + event.Skip() + + def on_pass_entry(self, event): + if event.GetKeyCode() == wx.WXK_RETURN: + self.on_login(event) + else: + event.Skip() + + def on_login(self, event): + user = self.user_field.GetValue() + passwd = self.pass_field.GetValue() + self.warning_label.SetLabel('') + + try: + root_cap = get_root_cap(BACKEND_URL, user, passwd) + write_config_file('private/root_dir.cap', root_cap+'\n') + except AuthError: + self.warning_label.SetLabel('Your email and/or password is incorrect') + self.user_field.SetFocus() + self.Layout() + return + + # fetch the introducer furl + ifurl = get_introducer_furl(BACKEND_URL) + write_config_file('introducer.furl', ifurl+'\n') + + # start service etc. + if sys.platform == 'win32': + try: + import win32service + import win32serviceutil as wsu + if wsu.QueryServiceStatus(WINSVC_NAME)[1] != win32service.SERVICE_RUNNING: + wsu.StartService(WINSVC_NAME) + except: + DisplayTraceback('Failed to start windows service') + + # exit + self.parent.parent.Close() + +class RegisterPanel(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent, -1) + self.parent = parent + + self.sizer = wx.BoxSizer(wx.VERTICAL) + + self.reg_label = wx.StaticText(self, -1, "Don't have an account?") + self.reg_button = wx.Button(self, -1, 'Create Account') + self.Bind(wx.EVT_BUTTON, self.on_reg_button, self.reg_button) + reg_sizer = wx.FlexGridSizer(1, 2, 5, 4) + reg_sizer.Add(self.reg_label, 0, wx.ALIGN_RIGHT | wx.ALL, 2) + reg_sizer.Add(self.reg_button, 0, wx.ALIGN_RIGHT | wx.ALL, 2) + self.sizer.Add(reg_sizer, 1, wx.EXPAND | wx.ALL, 2) + self.SetSizer(self.sizer) + self.SetAutoLayout(True) + + def on_reg_button(self, event): + webbrowser.open(REGISTER_PAGE) + def main(): - - URL = 'https://www-test.allmydata.com/native_client2.php' - - print get_introducer_furl(URL) - print get_root_cap(URL, u'user', u'pass') + app = ConfWizApp() + app.MainLoop() if __name__ == '__main__':