]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
cleanup mac and windows build code
authorrobk-tahoe <robk-tahoe@allmydata.com>
Thu, 24 Jan 2008 04:06:41 +0000 (21:06 -0700)
committerrobk-tahoe <robk-tahoe@allmydata.com>
Thu, 24 Jan 2008 04:06:41 +0000 (21:06 -0700)
this moves some of the code common to both windows and mac builds into the
allmydata module hierarchy, and cleans up the windows and mac build directories
to import the code from there.

14 files changed:
mac/allmydata_tahoe.py
mac/amdicon.py [deleted file]
mac/confwiz.py [deleted file]
mac/pkgreshook.py [deleted file]
src/allmydata/gui/__init__.py [new file with mode: 0644]
src/allmydata/gui/amdicon.py [new file with mode: 0644]
src/allmydata/gui/confwiz.py [new file with mode: 0644]
src/allmydata/gui/macapp.py [new file with mode: 0644]
src/allmydata/util/pkgresutil.py [new file with mode: 0644]
windows/amdicon.py [deleted file]
windows/confwiz.py
windows/pkgreshook.py [deleted file]
windows/tahoe.py
windows/tahoesvc.py

index 3e29238ac1fcc7b9c4d2648b5b38923ebbf2f3e9..b87d5cd8f0a84aefd80a4ec41a95d3bdec5a3c3d 100644 (file)
-import pkgreshook # override the pkg_resources zip provider for py2app deployment
-pkgreshook.install() # this is done before nevow is imported by depends
+from allmydata.util import pkgresutil # override the pkg_resources zip provider for py2app deployment
+pkgresutil.install() # this is done before nevow is imported by depends
 import depends # import dependencies so that py2exe finds them
 _junk = depends # appease pyflakes
 
 import sys
-import os
-import stat
-import traceback
-
-TRY_TO_INSTALL_TAHOE_SCRIPT = True
-TAHOE_SCRIPT = '''#!/bin/bash
-if [ "x${@}x" == "xx" ]
-then
-    %(exe)s --help
-else
-    %(exe)s "${@}"
-fi
-'''
-
-def run_default_node():
-    import operator
-
-    basedir = os.path.expanduser('~/.tahoe')
-    if not os.path.isdir(basedir):
-        app_supp = os.path.expanduser('~/Library/Application Support/Allmydata Tahoe/')
-        if not os.path.isdir(app_supp):
-            os.makedirs(app_supp)
-        os.symlink(app_supp, basedir)
-
-    if not os.path.exists(os.path.join(basedir, 'webport')):
-        f = file(os.path.join(basedir, 'webport'), 'wb')
-        f.write('8123')
-        f.close()
-
-    def files_exist(file_list):
-        extant_conf = [ os.path.exists(os.path.join(basedir, f)) for f in file_list ]
-        return reduce(operator.__and__, extant_conf)
-
-    def is_config_incomplete():
-        necessary_conf_files = ['introducer.furl', 'private/root_dir.cap']
-        need_config = not files_exist(necessary_conf_files)
-        if need_config:
-            print 'some config is missing from basedir (%s): %s' % (basedir, necessary_conf_files)
-        return need_config
-
-    if is_config_incomplete():
-        #import wx
-        from confwiz import ConfWizApp
-        app = ConfWizApp()
-        app.MainLoop()
-
-    if is_config_incomplete():
-        print 'config still incomplete; confwiz cancelled, exiting'
-        return 1
-
-    from twisted.internet import reactor
-    from twisted.python import log, logfile
-    from allmydata import client
-    # set up twisted logging. this will become part of the node rsn.
-    logdir = os.path.join(basedir, 'logs')
-    if not os.path.exists(logdir):
-        os.makedirs(logdir)
-    lf = logfile.LogFile('tahoesvc.log', logdir)
-    log.startLogging(lf)
-
-    def webopen():
-        if files_exist(['node.url', 'private/root_dir.cap']):
-            def read_file(f):
-                fh = file(f, 'rb')
-                contents = fh.read().strip()
-                fh.close()
-                return contents
-            import urllib, webbrowser
-            nodeurl = read_file(os.path.join(basedir, 'node.url'))
-            if nodeurl[-1] != "/":
-                nodeurl += "/"
-            root_dir = read_file(os.path.join(basedir, 'private/root_dir.cap'))
-            url = nodeurl + "uri/%s/" % urllib.quote(root_dir)
-            webbrowser.open(url)
-        else:
-            print 'files missing, not opening initial webish root page'
-
-    def maybe_install_tahoe_script():
-        path_candidates = ['/usr/local/bin', '~/bin', '~/Library/bin']
-        env_path = map(os.path.expanduser, os.environ['PATH'].split(':'))
-        if not sys.executable.endswith('/python'):
-            print 'not installing tahoe script: unexpected sys.exe "%s"' % (sys.executable,)
-            return
-        for path_candidate in map(os.path.expanduser, env_path):
-            tahoe_path = path_candidate + '/tahoe'
-            if os.path.exists(tahoe_path):
-                print 'not installing "tahoe": it already exists at "%s"' % (tahoe_path,)
-                return
-        for path_candidate in map(os.path.expanduser, path_candidates):
-            if path_candidate not in env_path:
-                print path_candidate, 'not in', env_path
-                continue
-            tahoe_path = path_candidate + '/tahoe'
-            try:
-                print 'trying to install "%s"' % (tahoe_path,)
-                bin_path = (sys.executable[:-6] + 'Allmydata Tahoe').replace(' ', '\\ ')
-                script = TAHOE_SCRIPT % { 'exe': bin_path }
-                f = file(tahoe_path, 'wb')
-                f.write(script)
-                f.close()
-                mode = stat.S_IRUSR|stat.S_IXUSR|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH
-                os.chmod(tahoe_path, mode)
-                print 'installed "%s"' % (tahoe_path,)
-                return
-            except:
-                print 'unable to write %s' % (tahoe_path,)
-                traceback.print_exc()
-        else:
-            print 'no remaining candidate paths for installation of tahoe script'
-
-    if TRY_TO_INSTALL_TAHOE_SCRIPT:
-        maybe_install_tahoe_script()
-
-    # run the node itself
-    os.chdir(basedir)
-    c = client.Client(basedir)
-    reactor.callLater(0, c.startService) # after reactor startup
-    reactor.callLater(4, webopen) # give node a chance to connect before loading root dir
-    reactor.run()
-
-    return 0
-
-
 
 def main(argv):
     if len(argv) == 1:
         # then we were given no args; do default mac node startup
-        sys.exit(run_default_node())
+        from allmydata.gui.macapp import run_macapp
+        sys.exit(run_macapp())
     else:
         # given any cmd line args, do 'tahoe' cli behaviour
         from allmydata.scripts import runner
diff --git a/mac/amdicon.py b/mac/amdicon.py
deleted file mode 100644 (file)
index a26ca3c..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#----------------------------------------------------------------------
-# 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/mac/confwiz.py b/mac/confwiz.py
deleted file mode 100644 (file)
index 6860df5..0000000
+++ /dev/null
@@ -1,407 +0,0 @@
-
-BACKEND_URL = 'https://www-test.allmydata.com/native_client.php'
-#REGISTER_PAGE = 'https://www-test.allmydata.com/register'
-TAHOESVC_NAME = 'Tahoe'
-WINFUSESVC_NAME = 'Allmydata Tahoe SMB'
-
-import os
-import sys
-#import time
-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
-
-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)
-    return conn.read()
-
-def get_root_cap(url, user, passwd):
-    args = {
-        'action': 'authenticate',
-        'email': unicode_to_utf8(user),
-        'passwd': unicode_to_utf8(passwd),
-        }
-    root_cap = post(url, args)
-    if root_cap == '0':
-        raise AuthError()
-    elif not uri.is_uri(root_cap):
-        raise ValueError('%r is not a URI' % (root_cap,))
-    else:
-        return root_cap
-
-def create_account(url, user, passwd, subscribe):
-    args = {
-        'action': 'create_account',
-        'email': unicode_to_utf8(user),
-        'passwd': unicode_to_utf8(passwd),
-        'subscribe': subscribe and 'true' or 'false',
-        }
-    result_code = post(url, args)
-    return result_code
-
-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.login_frame = LoginFrame(self)
-            self.login_frame.CenterOnScreen()
-            self.SetTopWindow(self.login_frame)
-            #self.SetExitOnFrameDelete(True)
-            self.login_frame.Show(True)
-
-            return True
-        except:
-            DisplayTraceback('config wizard init threw an exception')
-
-    def swap_to_register_frame(self):
-        try:
-            self.login_frame.Show(False)
-            self.regiser_frame = RegisterFrame(self)
-            self.regiser_frame.CenterOnScreen()
-            self.SetTopWindow(self.regiser_frame)
-            self.SetExitOnFrameDelete(True)
-            self.regiser_frame.Show(True)
-        except:
-            DisplayTraceback('config wizard threw an exception')
-
-class LoginFrame(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.reg_btn_panel = RegisterButtonPanel(background, app)
-        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.reg_btn_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):
-        self.Show(False)
-        self.app.ExitMainLoop()
-
-class RegisterFrame(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.register_panel = RegisterPanel(background)
-        sizer = wx.BoxSizer(wx.VERTICAL)
-        background_sizer = wx.BoxSizer(wx.VERTICAL)
-        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):
-        self.Show(False)
-        self.app.ExitMainLoop()
-
-
-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.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('Connecting...')
-        self.Layout()
-        wx.Yield()
-
-        if passwd == '':
-            self.warning_label.SetLabel('You must enter a password')
-            self.pass_field.SetFocus()
-            self.Layout()
-            return
-
-        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':
-            self.start_windows_service(TAHOESVC_NAME)
-            self.start_windows_service(WINFUSESVC_NAME)
-
-        # exit
-        self.parent.parent.Close()
-
-    def start_windows_service(self, svc_name):
-        try:
-            import win32service
-            import win32serviceutil as wsu
-            if wsu.QueryServiceStatus(svc_name)[1] != win32service.SERVICE_RUNNING:
-                wsu.StartService(svc_name)
-        except:
-            DisplayTraceback('Failed to start windows service "%s"' % (svc_name,))
-
-class RegisterButtonPanel(wx.Panel):
-    def __init__(self, parent, app):
-        wx.Panel.__init__(self, parent, -1)
-        self.parent = parent
-        self.app = app
-
-        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)
-        self.app.swap_to_register_frame()
-
-class RegisterPanel(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.conf_label = wx.StaticText(self, -1, 'Confirm 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.conf_field = wx.TextCtrl(self, -1, u'', size=(260,-1), style=wx.TE_PASSWORD)
-        self.create_account_button = wx.Button(self, -1, 'Create Account')
-        self.subscribe_box = wx.CheckBox(self, -1, 'Sign up for our Newsletter')
-        self.subscribe_box.SetValue(True)
-        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)
-        wx.EVT_CHAR(self.conf_field, self.on_conf_entry)
-        self.Bind(wx.EVT_BUTTON, self.on_create_account, self.create_account_button)
-        login_sizer = wx.FlexGridSizer(4, 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(self.conf_label, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
-        login_sizer.Add(self.conf_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.create_account_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.CENTER | wx.ALL, 2)
-        self.sizer.Add(self.subscribe_box, 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.conf_field.SetFocus()
-        else:
-            event.Skip()
-
-    def on_conf_entry(self, event):
-        if event.GetKeyCode() == wx.WXK_RETURN:
-            self.on_create_account(event)
-        else:
-            event.Skip()
-
-    def on_create_account(self, event):
-        user = self.user_field.GetValue()
-        passwd = self.pass_field.GetValue()
-        pconf = self.conf_field.GetValue()
-        subscribe = self.subscribe_box.IsChecked()
-        self.warning_label.SetLabel('Connecting...')
-        self.Layout()
-        wx.Yield()
-
-        if passwd == '':
-            self.warning_label.SetLabel('You must enter a password')
-            self.pass_field.SetFocus()
-            self.Layout()
-            return
-
-        if passwd != pconf:
-            self.warning_label.SetLabel("Passwords don't match")
-            self.pass_field.SetValue('')
-            self.conf_field.SetValue('')
-            self.pass_field.SetFocus()
-            self.Layout()
-            return
-
-        #print 'calling create_account', time.asctime()
-        result_code = create_account(BACKEND_URL, user, passwd, subscribe)
-
-        if result_code == 'account_exists':
-            # try and log into it; if valid, use it anyway
-            try:
-                #print 'calling get_root_cap (ae)', time.asctime()
-                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('That email address is already registered')
-                self.user_field.SetFocus()
-                self.Layout()
-                return
-        elif result_code == 'error':
-            self.warning_label.SetLabel('an error occurred')
-            self.user_field.SetFocus()
-            self.Layout()
-            return
-        elif result_code == 'ok':
-            #print 'calling get_root_cap (ok)', time.asctime()
-            root_cap = get_root_cap(BACKEND_URL, user, passwd)
-            write_config_file('private/root_dir.cap', root_cap+'\n')
-        else:
-            self.warning_label.SetLabel('an unexpected error occurred ("%s")' % (result_code,))
-            self.user_field.SetFocus()
-            self.Layout()
-            return
-
-        # fetch the introducer furl
-        #print 'calling get_introducer_furl', time.asctime()
-        ifurl = get_introducer_furl(BACKEND_URL)
-        write_config_file('introducer.furl', ifurl+'\n')
-
-        # start service etc.
-        if sys.platform == 'win32':
-            self.start_windows_service(TAHOESVC_NAME)
-            self.start_windows_service(WINFUSESVC_NAME)
-
-        # exit
-        self.parent.parent.Close()
-
-    def start_windows_service(self, svc_name):
-        try:
-            import win32service
-            import win32serviceutil as wsu
-            if wsu.QueryServiceStatus(svc_name)[1] != win32service.SERVICE_RUNNING:
-                wsu.StartService(svc_name)
-        except:
-            DisplayTraceback('Failed to start windows service "%s"' % (svc_name,))
-
-
-def main():
-    app = ConfWizApp()
-    app.MainLoop()
-
-
-if __name__ == '__main__':
-    main()
diff --git a/mac/pkgreshook.py b/mac/pkgreshook.py
deleted file mode 100644 (file)
index bb1d985..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-
-def install():
-    """
-    This installs a hook into setuptools' pkg_resources infrastructure, so that resource
-    files can be found in files relative to the runnin executable, in addition to the
-    usual egg and source lookup mechanisms.  This overrides the ZipProvider, since that
-    is the lookup mechanism triggered within pkg_resources when running code out of a
-    py2exe or py2app build's library.zip.
-    """
-    import os, sys
-    import pkg_resources, zipimport
-
-    platform_libdirs = {
-        'darwin': '../Resources/pkg_resources',
-        }
-    exedir = os.path.dirname(sys.executable)
-    libdir = platform_libdirs.get(sys.platform, 'pkg_resources')
-
-    class Provider(pkg_resources.ZipProvider):
-
-        def __init__(self, module):
-            self._module_name = module.__name__
-            pkg_resources.ZipProvider.__init__(self, module)
-
-        def get_resource_filename(self, manager, resource_name):
-            #print 'get_resource_filename(%s, %s)' % (manager, resource_name)
-            path = [exedir, libdir] + self._module_name.split('.') + [resource_name]
-            localfile = os.path.join(*path)
-            #print '             checking(%s)' % (localfile,)
-            if os.path.exists(localfile):
-                #print 'found locally'
-                return localfile
-            else:
-                try:
-                    ret = pkg_resources.ZipProvider.get_resource_filename(self, manager, resource_name)
-                    #print 'returning %s' % (ret,)
-                    return ret
-                except NotImplementedError:
-                    #print 'get_resource_filename(%s,%s): not found' % (self._module_name, resource_name)
-                    #import traceback
-                    #traceback.print_exc()
-                    return ''
-
-    pkg_resources.register_loader_type(zipimport.zipimporter, Provider)
-
-
diff --git a/src/allmydata/gui/__init__.py b/src/allmydata/gui/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/allmydata/gui/amdicon.py b/src/allmydata/gui/amdicon.py
new file mode 100644 (file)
index 0000000..a26ca3c
--- /dev/null
@@ -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/src/allmydata/gui/confwiz.py b/src/allmydata/gui/confwiz.py
new file mode 100644 (file)
index 0000000..6860df5
--- /dev/null
@@ -0,0 +1,407 @@
+
+BACKEND_URL = 'https://www-test.allmydata.com/native_client.php'
+#REGISTER_PAGE = 'https://www-test.allmydata.com/register'
+TAHOESVC_NAME = 'Tahoe'
+WINFUSESVC_NAME = 'Allmydata Tahoe SMB'
+
+import os
+import sys
+#import time
+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
+
+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)
+    return conn.read()
+
+def get_root_cap(url, user, passwd):
+    args = {
+        'action': 'authenticate',
+        'email': unicode_to_utf8(user),
+        'passwd': unicode_to_utf8(passwd),
+        }
+    root_cap = post(url, args)
+    if root_cap == '0':
+        raise AuthError()
+    elif not uri.is_uri(root_cap):
+        raise ValueError('%r is not a URI' % (root_cap,))
+    else:
+        return root_cap
+
+def create_account(url, user, passwd, subscribe):
+    args = {
+        'action': 'create_account',
+        'email': unicode_to_utf8(user),
+        'passwd': unicode_to_utf8(passwd),
+        'subscribe': subscribe and 'true' or 'false',
+        }
+    result_code = post(url, args)
+    return result_code
+
+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.login_frame = LoginFrame(self)
+            self.login_frame.CenterOnScreen()
+            self.SetTopWindow(self.login_frame)
+            #self.SetExitOnFrameDelete(True)
+            self.login_frame.Show(True)
+
+            return True
+        except:
+            DisplayTraceback('config wizard init threw an exception')
+
+    def swap_to_register_frame(self):
+        try:
+            self.login_frame.Show(False)
+            self.regiser_frame = RegisterFrame(self)
+            self.regiser_frame.CenterOnScreen()
+            self.SetTopWindow(self.regiser_frame)
+            self.SetExitOnFrameDelete(True)
+            self.regiser_frame.Show(True)
+        except:
+            DisplayTraceback('config wizard threw an exception')
+
+class LoginFrame(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.reg_btn_panel = RegisterButtonPanel(background, app)
+        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.reg_btn_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):
+        self.Show(False)
+        self.app.ExitMainLoop()
+
+class RegisterFrame(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.register_panel = RegisterPanel(background)
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        background_sizer = wx.BoxSizer(wx.VERTICAL)
+        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):
+        self.Show(False)
+        self.app.ExitMainLoop()
+
+
+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.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('Connecting...')
+        self.Layout()
+        wx.Yield()
+
+        if passwd == '':
+            self.warning_label.SetLabel('You must enter a password')
+            self.pass_field.SetFocus()
+            self.Layout()
+            return
+
+        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':
+            self.start_windows_service(TAHOESVC_NAME)
+            self.start_windows_service(WINFUSESVC_NAME)
+
+        # exit
+        self.parent.parent.Close()
+
+    def start_windows_service(self, svc_name):
+        try:
+            import win32service
+            import win32serviceutil as wsu
+            if wsu.QueryServiceStatus(svc_name)[1] != win32service.SERVICE_RUNNING:
+                wsu.StartService(svc_name)
+        except:
+            DisplayTraceback('Failed to start windows service "%s"' % (svc_name,))
+
+class RegisterButtonPanel(wx.Panel):
+    def __init__(self, parent, app):
+        wx.Panel.__init__(self, parent, -1)
+        self.parent = parent
+        self.app = app
+
+        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)
+        self.app.swap_to_register_frame()
+
+class RegisterPanel(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.conf_label = wx.StaticText(self, -1, 'Confirm 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.conf_field = wx.TextCtrl(self, -1, u'', size=(260,-1), style=wx.TE_PASSWORD)
+        self.create_account_button = wx.Button(self, -1, 'Create Account')
+        self.subscribe_box = wx.CheckBox(self, -1, 'Sign up for our Newsletter')
+        self.subscribe_box.SetValue(True)
+        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)
+        wx.EVT_CHAR(self.conf_field, self.on_conf_entry)
+        self.Bind(wx.EVT_BUTTON, self.on_create_account, self.create_account_button)
+        login_sizer = wx.FlexGridSizer(4, 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(self.conf_label, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
+        login_sizer.Add(self.conf_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.create_account_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.CENTER | wx.ALL, 2)
+        self.sizer.Add(self.subscribe_box, 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.conf_field.SetFocus()
+        else:
+            event.Skip()
+
+    def on_conf_entry(self, event):
+        if event.GetKeyCode() == wx.WXK_RETURN:
+            self.on_create_account(event)
+        else:
+            event.Skip()
+
+    def on_create_account(self, event):
+        user = self.user_field.GetValue()
+        passwd = self.pass_field.GetValue()
+        pconf = self.conf_field.GetValue()
+        subscribe = self.subscribe_box.IsChecked()
+        self.warning_label.SetLabel('Connecting...')
+        self.Layout()
+        wx.Yield()
+
+        if passwd == '':
+            self.warning_label.SetLabel('You must enter a password')
+            self.pass_field.SetFocus()
+            self.Layout()
+            return
+
+        if passwd != pconf:
+            self.warning_label.SetLabel("Passwords don't match")
+            self.pass_field.SetValue('')
+            self.conf_field.SetValue('')
+            self.pass_field.SetFocus()
+            self.Layout()
+            return
+
+        #print 'calling create_account', time.asctime()
+        result_code = create_account(BACKEND_URL, user, passwd, subscribe)
+
+        if result_code == 'account_exists':
+            # try and log into it; if valid, use it anyway
+            try:
+                #print 'calling get_root_cap (ae)', time.asctime()
+                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('That email address is already registered')
+                self.user_field.SetFocus()
+                self.Layout()
+                return
+        elif result_code == 'error':
+            self.warning_label.SetLabel('an error occurred')
+            self.user_field.SetFocus()
+            self.Layout()
+            return
+        elif result_code == 'ok':
+            #print 'calling get_root_cap (ok)', time.asctime()
+            root_cap = get_root_cap(BACKEND_URL, user, passwd)
+            write_config_file('private/root_dir.cap', root_cap+'\n')
+        else:
+            self.warning_label.SetLabel('an unexpected error occurred ("%s")' % (result_code,))
+            self.user_field.SetFocus()
+            self.Layout()
+            return
+
+        # fetch the introducer furl
+        #print 'calling get_introducer_furl', time.asctime()
+        ifurl = get_introducer_furl(BACKEND_URL)
+        write_config_file('introducer.furl', ifurl+'\n')
+
+        # start service etc.
+        if sys.platform == 'win32':
+            self.start_windows_service(TAHOESVC_NAME)
+            self.start_windows_service(WINFUSESVC_NAME)
+
+        # exit
+        self.parent.parent.Close()
+
+    def start_windows_service(self, svc_name):
+        try:
+            import win32service
+            import win32serviceutil as wsu
+            if wsu.QueryServiceStatus(svc_name)[1] != win32service.SERVICE_RUNNING:
+                wsu.StartService(svc_name)
+        except:
+            DisplayTraceback('Failed to start windows service "%s"' % (svc_name,))
+
+
+def main():
+    app = ConfWizApp()
+    app.MainLoop()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/src/allmydata/gui/macapp.py b/src/allmydata/gui/macapp.py
new file mode 100644 (file)
index 0000000..d43cc82
--- /dev/null
@@ -0,0 +1,138 @@
+
+import sys
+import os
+import stat
+import traceback
+
+TRY_TO_INSTALL_TAHOE_SCRIPT = True
+TAHOE_SCRIPT = '''#!/bin/bash
+if [ "x${@}x" == "xx" ]
+then
+    %(exe)s --help
+else
+    %(exe)s "${@}"
+fi
+'''
+
+def run_macapp():
+    import operator
+
+    basedir = os.path.expanduser('~/.tahoe')
+    if not os.path.isdir(basedir):
+        app_supp = os.path.expanduser('~/Library/Application Support/Allmydata Tahoe/')
+        if not os.path.isdir(app_supp):
+            os.makedirs(app_supp)
+        os.symlink(app_supp, basedir)
+
+    if not os.path.exists(os.path.join(basedir, 'webport')):
+        f = file(os.path.join(basedir, 'webport'), 'wb')
+        f.write('8123')
+        f.close()
+
+    def files_exist(file_list):
+        extant_conf = [ os.path.exists(os.path.join(basedir, f)) for f in file_list ]
+        return reduce(operator.__and__, extant_conf)
+
+    def is_config_incomplete():
+        necessary_conf_files = ['introducer.furl', 'private/root_dir.cap']
+        need_config = not files_exist(necessary_conf_files)
+        if need_config:
+            print 'some config is missing from basedir (%s): %s' % (basedir, necessary_conf_files)
+        return need_config
+
+    if is_config_incomplete():
+        #import wx
+        from allmydata.gui.confwiz import ConfWizApp
+        app = ConfWizApp()
+        app.MainLoop()
+
+    if is_config_incomplete():
+        print 'config still incomplete; confwiz cancelled, exiting'
+        return 1
+
+    from twisted.internet import reactor
+    from twisted.python import log, logfile
+    from allmydata import client
+    # set up twisted logging. this will become part of the node rsn.
+    logdir = os.path.join(basedir, 'logs')
+    if not os.path.exists(logdir):
+        os.makedirs(logdir)
+    lf = logfile.LogFile('tahoesvc.log', logdir)
+    log.startLogging(lf)
+
+    def webopen():
+        if files_exist(['node.url', 'private/root_dir.cap']):
+            def read_file(f):
+                fh = file(f, 'rb')
+                contents = fh.read().strip()
+                fh.close()
+                return contents
+            import urllib, webbrowser
+            nodeurl = read_file(os.path.join(basedir, 'node.url'))
+            if nodeurl[-1] != "/":
+                nodeurl += "/"
+            root_dir = read_file(os.path.join(basedir, 'private/root_dir.cap'))
+            url = nodeurl + "uri/%s/" % urllib.quote(root_dir)
+            webbrowser.open(url)
+        else:
+            print 'files missing, not opening initial webish root page'
+
+    def maybe_install_tahoe_script():
+        path_candidates = ['/usr/local/bin', '~/bin', '~/Library/bin']
+        env_path = map(os.path.expanduser, os.environ['PATH'].split(':'))
+        if not sys.executable.endswith('/python'):
+            print 'not installing tahoe script: unexpected sys.exe "%s"' % (sys.executable,)
+            return
+        for path_candidate in map(os.path.expanduser, env_path):
+            tahoe_path = path_candidate + '/tahoe'
+            if os.path.exists(tahoe_path):
+                print 'not installing "tahoe": it already exists at "%s"' % (tahoe_path,)
+                return
+        for path_candidate in map(os.path.expanduser, path_candidates):
+            if path_candidate not in env_path:
+                print path_candidate, 'not in', env_path
+                continue
+            tahoe_path = path_candidate + '/tahoe'
+            try:
+                print 'trying to install "%s"' % (tahoe_path,)
+                bin_path = (sys.executable[:-6] + 'Allmydata Tahoe').replace(' ', '\\ ')
+                script = TAHOE_SCRIPT % { 'exe': bin_path }
+                f = file(tahoe_path, 'wb')
+                f.write(script)
+                f.close()
+                mode = stat.S_IRUSR|stat.S_IXUSR|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH
+                os.chmod(tahoe_path, mode)
+                print 'installed "%s"' % (tahoe_path,)
+                return
+            except:
+                print 'unable to write %s' % (tahoe_path,)
+                traceback.print_exc()
+        else:
+            print 'no remaining candidate paths for installation of tahoe script'
+
+    if TRY_TO_INSTALL_TAHOE_SCRIPT:
+        maybe_install_tahoe_script()
+
+    # run the node itself
+    os.chdir(basedir)
+    c = client.Client(basedir)
+    reactor.callLater(0, c.startService) # after reactor startup
+    reactor.callLater(4, webopen) # give node a chance to connect before loading root dir
+    reactor.run()
+
+    return 0
+
+
+
+def main(argv):
+    if len(argv) == 1:
+        # then we were given no args; do default mac node startup
+        sys.exit(run_macapp())
+    else:
+        # given any cmd line args, do 'tahoe' cli behaviour
+        from allmydata.scripts import runner
+        sys.exit(runner.runner(argv[1:], install_node_control=False))
+
+if __name__ == '__main__':
+    main(sys.argv)
+
diff --git a/src/allmydata/util/pkgresutil.py b/src/allmydata/util/pkgresutil.py
new file mode 100644 (file)
index 0000000..bb1d985
--- /dev/null
@@ -0,0 +1,46 @@
+
+def install():
+    """
+    This installs a hook into setuptools' pkg_resources infrastructure, so that resource
+    files can be found in files relative to the runnin executable, in addition to the
+    usual egg and source lookup mechanisms.  This overrides the ZipProvider, since that
+    is the lookup mechanism triggered within pkg_resources when running code out of a
+    py2exe or py2app build's library.zip.
+    """
+    import os, sys
+    import pkg_resources, zipimport
+
+    platform_libdirs = {
+        'darwin': '../Resources/pkg_resources',
+        }
+    exedir = os.path.dirname(sys.executable)
+    libdir = platform_libdirs.get(sys.platform, 'pkg_resources')
+
+    class Provider(pkg_resources.ZipProvider):
+
+        def __init__(self, module):
+            self._module_name = module.__name__
+            pkg_resources.ZipProvider.__init__(self, module)
+
+        def get_resource_filename(self, manager, resource_name):
+            #print 'get_resource_filename(%s, %s)' % (manager, resource_name)
+            path = [exedir, libdir] + self._module_name.split('.') + [resource_name]
+            localfile = os.path.join(*path)
+            #print '             checking(%s)' % (localfile,)
+            if os.path.exists(localfile):
+                #print 'found locally'
+                return localfile
+            else:
+                try:
+                    ret = pkg_resources.ZipProvider.get_resource_filename(self, manager, resource_name)
+                    #print 'returning %s' % (ret,)
+                    return ret
+                except NotImplementedError:
+                    #print 'get_resource_filename(%s,%s): not found' % (self._module_name, resource_name)
+                    #import traceback
+                    #traceback.print_exc()
+                    return ''
+
+    pkg_resources.register_loader_type(zipimport.zipimporter, Provider)
+
+
diff --git a/windows/amdicon.py b/windows/amdicon.py
deleted file mode 100644 (file)
index a26ca3c..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#----------------------------------------------------------------------
-# 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
-
-
index 65c93e74e6a97c9916f75264aca3eab7205ad04c..2a5e8cd6840fa23e26ebdbe134f86fb289258d7b 100644 (file)
@@ -1,405 +1,9 @@
 
-BACKEND_URL = 'https://www-test.allmydata.com/native_client.php'
-#REGISTER_PAGE = 'https://www-test.allmydata.com/register'
-TAHOESVC_NAME = 'Tahoe'
-WINFUSESVC_NAME = 'Allmydata Tahoe SMB'
-
-import os
-import sys
-#import time
-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
-
-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)
-    return conn.read()
-
-def get_root_cap(url, user, passwd):
-    args = {
-        'action': 'authenticate',
-        'email': unicode_to_utf8(user),
-        'passwd': unicode_to_utf8(passwd),
-        }
-    root_cap = post(url, args)
-    if root_cap == '0':
-        raise AuthError()
-    elif not uri.is_uri(root_cap):
-        raise ValueError('%r is not a URI' % (root_cap,))
-    else:
-        return root_cap
-
-def create_account(url, user, passwd, subscribe):
-    args = {
-        'action': 'create_account',
-        'email': unicode_to_utf8(user),
-        'passwd': unicode_to_utf8(passwd),
-        'subscribe': subscribe and 'true' or 'false',
-        }
-    result_code = post(url, args)
-    return result_code
-
-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.login_frame = LoginFrame(self)
-            self.login_frame.CenterOnScreen()
-            self.SetTopWindow(self.login_frame)
-            self.SetExitOnFrameDelete(True)
-            self.login_frame.Show(True)
-
-            return True
-        except:
-            DisplayTraceback('config wizard init threw an exception')
-
-    def swap_to_register_frame(self):
-        try:
-            self.login_frame.Show(False)
-            self.regiser_frame = RegisterFrame(self)
-            self.regiser_frame.CenterOnScreen()
-            self.SetTopWindow(self.regiser_frame)
-            self.SetExitOnFrameDelete(True)
-            self.regiser_frame.Show(True)
-        except:
-            DisplayTraceback('config wizard threw an exception')
-
-class LoginFrame(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.reg_btn_panel = RegisterButtonPanel(background, app)
-        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.reg_btn_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 RegisterFrame(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.register_panel = RegisterPanel(background)
-        sizer = wx.BoxSizer(wx.VERTICAL)
-        background_sizer = wx.BoxSizer(wx.VERTICAL)
-        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.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('Connecting...')
-        self.Layout()
-        wx.Yield()
-
-        if passwd == '':
-            self.warning_label.SetLabel('You must enter a password')
-            self.pass_field.SetFocus()
-            self.Layout()
-            return
-
-        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':
-            self.start_windows_service(TAHOESVC_NAME)
-            self.start_windows_service(WINFUSESVC_NAME)
-
-        # exit
-        self.parent.parent.Close()
-
-    def start_windows_service(self, svc_name):
-        try:
-            import win32service
-            import win32serviceutil as wsu
-            if wsu.QueryServiceStatus(svc_name)[1] != win32service.SERVICE_RUNNING:
-                wsu.StartService(svc_name)
-        except:
-            DisplayTraceback('Failed to start windows service "%s"' % (svc_name,))
-
-class RegisterButtonPanel(wx.Panel):
-    def __init__(self, parent, app):
-        wx.Panel.__init__(self, parent, -1)
-        self.parent = parent
-        self.app = app
-
-        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)
-        self.app.swap_to_register_frame()
-
-class RegisterPanel(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.conf_label = wx.StaticText(self, -1, 'Confirm 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.conf_field = wx.TextCtrl(self, -1, u'', size=(260,-1), style=wx.TE_PASSWORD)
-        self.create_account_button = wx.Button(self, -1, 'Create Account')
-        self.subscribe_box = wx.CheckBox(self, -1, 'Sign up for our Newsletter')
-        self.subscribe_box.SetValue(True)
-        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)
-        wx.EVT_CHAR(self.conf_field, self.on_conf_entry)
-        self.Bind(wx.EVT_BUTTON, self.on_create_account, self.create_account_button)
-        login_sizer = wx.FlexGridSizer(4, 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(self.conf_label, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
-        login_sizer.Add(self.conf_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.create_account_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.CENTER | wx.ALL, 2)
-        self.sizer.Add(self.subscribe_box, 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.conf_field.SetFocus()
-        else:
-            event.Skip()
-
-    def on_conf_entry(self, event):
-        if event.GetKeyCode() == wx.WXK_RETURN:
-            self.on_create_account(event)
-        else:
-            event.Skip()
-
-    def on_create_account(self, event):
-        user = self.user_field.GetValue()
-        passwd = self.pass_field.GetValue()
-        pconf = self.conf_field.GetValue()
-        subscribe = self.subscribe_box.IsChecked()
-        self.warning_label.SetLabel('Connecting...')
-        self.Layout()
-        wx.Yield()
-
-        if passwd == '':
-            self.warning_label.SetLabel('You must enter a password')
-            self.pass_field.SetFocus()
-            self.Layout()
-            return
-
-        if passwd != pconf:
-            self.warning_label.SetLabel("Passwords don't match")
-            self.pass_field.SetValue('')
-            self.conf_field.SetValue('')
-            self.pass_field.SetFocus()
-            self.Layout()
-            return
-
-        #print 'calling create_account', time.asctime()
-        result_code = create_account(BACKEND_URL, user, passwd, subscribe)
-
-        if result_code == 'account_exists':
-            # try and log into it; if valid, use it anyway
-            try:
-                #print 'calling get_root_cap (ae)', time.asctime()
-                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('That email address is already registered')
-                self.user_field.SetFocus()
-                self.Layout()
-                return
-        elif result_code == 'error':
-            self.warning_label.SetLabel('an error occurred')
-            self.user_field.SetFocus()
-            self.Layout()
-            return
-        elif result_code == 'ok':
-            #print 'calling get_root_cap (ok)', time.asctime()
-            root_cap = get_root_cap(BACKEND_URL, user, passwd)
-            write_config_file('private/root_dir.cap', root_cap+'\n')
-        else:
-            self.warning_label.SetLabel('an unexpected error occurred ("%s")' % (result_code,))
-            self.user_field.SetFocus()
-            self.Layout()
-            return
-
-        # fetch the introducer furl
-        #print 'calling get_introducer_furl', time.asctime()
-        ifurl = get_introducer_furl(BACKEND_URL)
-        write_config_file('introducer.furl', ifurl+'\n')
-
-        # start service etc.
-        if sys.platform == 'win32':
-            self.start_windows_service(TAHOESVC_NAME)
-            self.start_windows_service(WINFUSESVC_NAME)
-
-        # exit
-        self.parent.parent.Close()
-
-    def start_windows_service(self, svc_name):
-        try:
-            import win32service
-            import win32serviceutil as wsu
-            if wsu.QueryServiceStatus(svc_name)[1] != win32service.SERVICE_RUNNING:
-                wsu.StartService(svc_name)
-        except:
-            DisplayTraceback('Failed to start windows service "%s"' % (svc_name,))
-
+from allmydata.gui.confwiz import ConfWizApp
 
 def main():
     app = ConfWizApp()
     app.MainLoop()
 
-
 if __name__ == '__main__':
     main()
diff --git a/windows/pkgreshook.py b/windows/pkgreshook.py
deleted file mode 100644 (file)
index bb1d985..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-
-def install():
-    """
-    This installs a hook into setuptools' pkg_resources infrastructure, so that resource
-    files can be found in files relative to the runnin executable, in addition to the
-    usual egg and source lookup mechanisms.  This overrides the ZipProvider, since that
-    is the lookup mechanism triggered within pkg_resources when running code out of a
-    py2exe or py2app build's library.zip.
-    """
-    import os, sys
-    import pkg_resources, zipimport
-
-    platform_libdirs = {
-        'darwin': '../Resources/pkg_resources',
-        }
-    exedir = os.path.dirname(sys.executable)
-    libdir = platform_libdirs.get(sys.platform, 'pkg_resources')
-
-    class Provider(pkg_resources.ZipProvider):
-
-        def __init__(self, module):
-            self._module_name = module.__name__
-            pkg_resources.ZipProvider.__init__(self, module)
-
-        def get_resource_filename(self, manager, resource_name):
-            #print 'get_resource_filename(%s, %s)' % (manager, resource_name)
-            path = [exedir, libdir] + self._module_name.split('.') + [resource_name]
-            localfile = os.path.join(*path)
-            #print '             checking(%s)' % (localfile,)
-            if os.path.exists(localfile):
-                #print 'found locally'
-                return localfile
-            else:
-                try:
-                    ret = pkg_resources.ZipProvider.get_resource_filename(self, manager, resource_name)
-                    #print 'returning %s' % (ret,)
-                    return ret
-                except NotImplementedError:
-                    #print 'get_resource_filename(%s,%s): not found' % (self._module_name, resource_name)
-                    #import traceback
-                    #traceback.print_exc()
-                    return ''
-
-    pkg_resources.register_loader_type(zipimport.zipimporter, Provider)
-
-
index 50dd05c78fe91790d20e2a8dfa14695a52bbefaf..38dd1a7858685e1db2dbf8c17d430c69706bc8e8 100644 (file)
@@ -1,5 +1,5 @@
-import pkgreshook # override the pkg_resources zip provider for py2exe deployment
-pkgreshook.install() # this is done before nevow is imported by depends
+from allmydata.util import pkgresutil # override the pkg_resources zip provider for py2exe deployment
+pkgresutil.install() # this is done before nevow is imported by depends
 import depends # import dependencies so that py2exe finds them
 _junk = depends # appease pyflakes
 
index f5db9d236a1df0a7683a403c79fac388b437697d..a2b5392a42dae35cde4911d38b46a81bc8e27a78 100644 (file)
@@ -22,8 +22,8 @@ logmsg('service loaded')
 #
 # Now with some bootstrap util functions in place, let's try and init things:
 try:
-    import pkgreshook # override the pkg_resources zip provider for py2exe deployment
-    pkgreshook.install() # this is done before nevow is imported
+    from allmydata.util import pkgresutil # override pkg_resources zip provider for py2exe deployment
+    pkgresutil.install() # this is done before nevow is imported
 
     logmsg('loading base dir')
     from allmydata.windows import registry