Exemple #1
0
    def run(port, subnets):
        # Is a server already running? Check if a Twistd PID exists in
        # the given directory.
        pidfile = os.path.join(directory, 'twistd.pid')
        if platformType != 'win32':
            from twisted.scripts._twistd_unix import checkPID
            try:
                checkPID(pidfile)
            except SystemExit as e:
                pid = int(open(pidfile).read())

                if str(e).startswith('Another twistd server is running,'):
                    print 'Another Sage Notebook server is running, PID %d.' % pid
                    old_interface, old_port, old_secure = get_old_settings(conf)
                    if open_viewer and old_port:
                        old_interface = old_interface or 'localhost'

                        print 'Opening web browser at http%s://%s:%s/ ...' % (
                            's' if old_secure else '', old_interface, old_port)

                        from sagenb.misc.misc import open_page as browse_to
                        browse_to(old_interface, old_port, old_secure, '/')
                        return
                    print '\nPlease either stop the old server or run the new server in a different directory.'
                    return

        ## Create the config file
        if secure:
            if (not os.path.exists(private_pem) or
                not os.path.exists(public_pem)):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if (not os.path.exists(private_pem) or
                not os.path.exists(public_pem)):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = '%s:%s:interface=%s:privateKey=%s:certKey=%s' % (
                protocol, port, interface, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s' % (port, interface)

        notebook_opts = '"%s",interface="%s",port=%s,secure=%s' % (
            os.path.abspath(directory), interface, port, secure)

        if open_viewer:
            if require_login:
                start_path = "'/?startup_token=%s' % startup_token"
            else:
                start_path = "'/'"
            if interface:
                hostname = interface
            else:
                hostname = 'localhost'
            open_page = "from sagenb.misc.misc import open_page; open_page('%s', %s, %s, %s)" % (hostname, port, secure, start_path)
        else:
            open_page = ''

        config = open(conf, 'w')

        if subnets is None:
            factory = "factory = channel.HTTPFactory(site)"
        else:
            if not isinstance(subnets, (list, tuple)):
                subnets = [subnets]
            factory = """
# See http://stackoverflow.com/questions/1273297/python-twisted-restricting-access-by-ip-address
from sagenb.misc.ipaddr import IPNetwork
subnets = eval(r"%s")
if not any(s.startswith('127') for s in subnets):
    subnets.insert(0, '127.0.0.0/8')
subnets = [IPNetwork(x) for x in subnets]
class RestrictedIPFactory(channel.HTTPFactory):
    def buildProtocol(self, addr):
        a = str(addr.host)
        for X in subnets:
            if a in X:
                return channel.HTTPFactory.buildProtocol(self, addr)
        print 'Ignoring all requests from IP address '+str(addr.host)

factory = RestrictedIPFactory(site)
""" % tuple([subnets])

        config.write("""
####################################################################
# WARNING -- Do not edit this file!   It is autogenerated each time
# the notebook(...) command is executed.
####################################################################
from twisted.internet import reactor

# Now set things up and start the notebook
import sagenb.notebook.notebook
sagenb.notebook.notebook.JSMATH=True
import sagenb.notebook.notebook as notebook
import sagenb.notebook.twist as twist
twist.notebook = notebook.load_notebook(%s)
twist.SAGETEX_PATH = %r
twist.OPEN_MODE = %s
twist.SID_COOKIE = str(hash(%r))
twist.DIR = %r
twist.reactor = reactor
twist.init_updates()
import sagenb.notebook.worksheet as worksheet

import signal, sys, random
def save_notebook():
    from twisted.internet.error import ReactorNotRunning
    print "Quitting all running worksheets..."
    twist.notebook.quit()
    print "Saving notebook..."
    twist.notebook.save()
    print "Notebook cleanly saved."

def my_sigint(x, n):
    try:
        reactor.stop()
    except ReactorNotRunning:
        pass
    signal.signal(signal.SIGINT, signal.SIG_DFL)


signal.signal(signal.SIGINT, my_sigint)

## Disable client-side certificate request for gnutls
try:
    import gnutls.connection
    gnutls.connection.CERT_REQUEST = 0
except (OSError, ImportError):
    print "Note: GNUTLS not available."


## Authentication framework (ported from Knooboo)
from twisted.web2 import log, server, channel
from twisted.cred import portal, checkers, credentials
import sagenb.notebook.guard as guard
import sagenb.notebook.avatars as avatars

from twisted.cred import portal

realm = avatars.LoginSystem()
p = portal.Portal(realm)
startup_token = '%%x' %% random.randint(0, 2**128)
startup_checker = avatars.OneTimeTokenChecker()
startup_checker.token = startup_token
p.registerChecker(startup_checker)
password_checker = avatars.PasswordChecker()
p.registerChecker(password_checker)
p.registerChecker(checkers.AllowAnonymousAccess())
rsrc = guard.MySessionWrapper(p)
log.DefaultCommonAccessLoggingObserver().start()
site = server.Site(rsrc)
%s
from twisted.web2 import channel
from twisted.application import service, strports
application = service.Application("SAGE Notebook")
s = strports.service(%r, factory)
%s
s.setServiceParent(application)

reactor.addSystemEventTrigger('before', 'shutdown', save_notebook)

""" % (notebook_opts, sagetex_path, not require_login,
       os.path.abspath(directory), cwd, factory,
       strport, open_page))

        config.close()

        ## Start up twisted
        cmd = 'twistd --pidfile="%s" -ny "%s"' % (pidfile, conf)
        if not quiet:
            print_open_msg('localhost' if not interface else interface,
                           port, secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."

        if fork:
            import pexpect
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)

        os.chdir(cwd)
        if e == 256:
            raise socket.error

        return True
Exemple #2
0
def notebook_run(
    self,
    directory=None,
    port=8080,
    interface='localhost',
    port_tries=50,
    secure=False,
    reset=False,
    accounts=None,
    openid=None,
    server_pool=None,
    ulimit='',
    timeout=None,  # timeout for normal worksheets. This is the
    # same as idle_timeout in server_conf.py
    doc_timeout=None,  # timeout for documentation worksheets
    upload=None,
    automatic_login=True,
    start_path="",
    fork=False,
    quiet=False,
    server="twistd",
    profile=False,
    subnets=None,
    require_login=None,
    open_viewer=None,
    address=None,
):

    # Check whether pyOpenSSL is installed or not (see Sage trac #13385)
    if secure:
        try:
            import OpenSSL
        except ImportError:
            raise RuntimeError(
                "HTTPS cannot be used without pyOpenSSL"
                " installed. See the Sage README for more information.")

    # Turn it into a full path for later conversion to a file URL
    if upload:
        upload_abs = os.path.abspath(upload)
        if os.path.exists(upload_abs):
            upload = upload_abs
        else:
            # They might have expected ~ to be expanded to their user directory
            upload = os.path.expanduser(upload)
            if not os.path.exists(upload):
                raise ValueError("Unable to find the file %s to upload" %
                                 upload)

    if subnets is not None:
        raise ValueError(
            """The subnets parameter is no longer supported. Please use a firewall to block subnets, or even better, volunteer to write the code to implement subnets again."""
        )
    if require_login is not None or open_viewer is not None:
        raise ValueError(
            "The require_login and open_viewer parameters are no longer supported.  "
            "Please use automatic_login=True to automatically log in as admin, "
            "or use automatic_login=False to not automatically log in.")
    if address is not None:
        raise ValueError(
            "Use 'interface' instead of 'address' when calling notebook(...).")

    cwd = os.getcwd()

    if directory is None:
        directory = '%s/sage_notebook.sagenb' % DOT_SAGENB
    else:
        directory = directory.rstrip('/')
        if not directory.endswith('.sagenb'):
            directory += '.sagenb'

    # First change to the directory that contains the notebook directory
    wd = os.path.split(directory)
    if wd[0]:
        os.chdir(wd[0])
    directory = wd[1]
    pidfile = os.path.join(directory, 'sagenb.pid')

    port = int(port)

    if not secure and interface != 'localhost':
        print '*' * 70
        print "WARNING: Running the notebook insecurely not on localhost is dangerous"
        print "because its possible for people to sniff passwords and gain access to"
        print "your account. Make sure you know what you are doing."
        print '*' * 70

    # first use provided values, if none, use loaded values,
    # if none use defaults

    nb = notebook.load_notebook(directory)

    directory = nb._dir

    if not quiet:
        print "The notebook files are stored in:", nb._dir

    if timeout is not None:
        nb.conf()['idle_timeout'] = int(timeout)
    if doc_timeout is not None:
        nb.conf()['doc_timeout'] = int(doc_timeout)

    if openid is not None:
        nb.conf()['openid'] = openid
    elif not nb.conf()['openid']:
        # What is the purpose behind this elif?  It seems rather pointless.
        # all it appears to do is set the config to False if bool(config) is False
        nb.conf()['openid'] = False

    if accounts is not None:
        nb.user_manager().set_accounts(accounts)
    else:
        nb.user_manager().set_accounts(nb.conf()['accounts'])

    if nb.user_manager().user_exists(
            'root') and not nb.user_manager().user_exists('admin'):
        # This is here only for backward compatibility with one
        # version of the notebook.
        s = nb.create_user_with_same_password('admin', 'root')
        # It would be a security risk to leave an escalated account around.

    if not nb.user_manager().user_exists('admin'):
        reset = True

    if reset:
        passwd = get_admin_passwd()
        if nb.user_manager().user_exists('admin'):
            admin = nb.user_manager().user('admin')
            admin.set_password(passwd)
            print "Password changed for user 'admin'."
        else:
            nb.user_manager().create_default_users(passwd)
            print "User admin created with the password you specified."
            print "\n\n"
            print "*" * 70
            print "\n"
            if secure:
                print "Login to the Sage notebook as admin with the password you specified above."
        #nb.del_user('root')

    # For old notebooks, make sure that default users are always created.
    # This fixes issue #175 (https://github.com/sagemath/sagenb/issues/175)
    um = nb.user_manager()
    for user in ('_sage_', 'pub'):
        if not um.user_exists(user):
            um.add_user(user, '', '', account_type='user', force=True)
    if not um.user_exists('guest'):
        um.add_user('guest', '', '', account_type='guest', force=True)

    nb.set_server_pool(server_pool)
    nb.set_ulimit(ulimit)

    if os.path.exists('%s/nb-older-backup.sobj' % directory):
        nb._migrate_worksheets()
        os.unlink('%s/nb-older-backup.sobj' % directory)
        print "Updating to new format complete."

    nb.upgrade_model()
    nb.save()
    del nb

    if interface != 'localhost' and not secure:
        print "*" * 70
        print "WARNING: Insecure notebook server listening on external interface."
        print "Unless you are running this via ssh port forwarding, you are"
        print "**crazy**!  You should run the notebook with the option secure=True."
        print "*" * 70

    port = find_next_available_port(interface, port, port_tries)
    if automatic_login:
        "******"
    if secure:
        if (not os.path.exists(private_pem) or not os.path.exists(public_pem)):
            print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
            print "Now running notebook.setup()"
            notebook_setup()
        if (not os.path.exists(private_pem) or not os.path.exists(public_pem)):
            print "Failed to setup notebook.  Please try notebook.setup() again manually."

    kw = dict(port=port,
              automatic_login=automatic_login,
              secure=secure,
              private_pem=private_pem,
              public_pem=public_pem,
              interface=interface,
              directory=directory,
              pidfile=pidfile,
              cwd=cwd,
              profile=profile,
              upload=upload)
    cmd = command[server]().run_command(kw)
    if cmd is None:
        return

    if not quiet:
        print_open_msg('localhost' if not interface else interface,
                       port,
                       secure=secure)
    if secure and not quiet:
        print "There is an admin account.  If you do not remember the password,"
        print "quit the notebook and type notebook(reset=True)."
    print "Executing", cmd
    if fork:
        import pexpect
        return pexpect.spawn(cmd)
    else:
        e = os.system(cmd)

    os.chdir(cwd)
    if e == 256:
        raise socket.error
Exemple #3
0
def notebook_run(self,
             directory     = None,
             port          = 8080,
             interface     = 'localhost',
             port_tries    = 50,
             secure        = False,
             reset         = False,
             accounts      = None,
             openid        = None,

             server_pool   = None,
             ulimit        = '',

             timeout       = 0,

             upload        = None,
             automatic_login = True,

             start_path    = "",
             fork          = False,
             quiet         = False,

             server = "twistd",
             profile = False,

             subnets = None,
             require_login = None,
             open_viewer = None,
             address = None,
             ):

    # Check whether pyOpenSSL is installed or not (see Sage trac #13385)
    if secure:
        try:
            import OpenSSL
        except ImportError:
            raise RuntimeError("HTTPS cannot be used without pyOpenSSL"
                    " installed. See the Sage README for more information.")

    # Turn it into a full path for later conversion to a file URL
    if upload:
        upload_abs = os.path.abspath(upload)
        if os.path.exists(upload_abs):
            upload = upload_abs
        else:
            # They might have expected ~ to be expanded to their user directory
            upload = os.path.expanduser(upload)
            if not os.path.exists(upload):
                raise ValueError("Unable to find the file %s to upload" % upload)


    if subnets is not None:
        raise ValueError("""The subnets parameter is no longer supported. Please use a firewall to block subnets, or even better, volunteer to write the code to implement subnets again.""")
    if require_login is not None or open_viewer is not None:
        raise ValueError("The require_login and open_viewer parameters are no longer supported.  "
                         "Please use automatic_login=True to automatically log in as admin, "
                         "or use automatic_login=False to not automatically log in.")
    if address is not None:
        raise ValueError("Use 'interface' instead of 'address' when calling notebook(...).")

    cwd = os.getcwd()

    if directory is None:
        directory = '%s/sage_notebook.sagenb' % DOT_SAGENB
    else:
        directory = directory.rstrip('/')
        if not directory.endswith('.sagenb'):
            directory += '.sagenb'

    # First change to the directory that contains the notebook directory
    wd = os.path.split(directory)
    if wd[0]:
        os.chdir(wd[0])
    directory = wd[1]
    pidfile = os.path.join(directory, 'sagenb.pid')

    port = int(port)

    if not secure and interface != 'localhost':
        print '*' * 70
        print "WARNING: Running the notebook insecurely not on localhost is dangerous"
        print "because its possible for people to sniff passwords and gain access to"
        print "your account. Make sure you know what you are doing."
        print '*' * 70

    # first use provided values, if none, use loaded values,
    # if none use defaults

    nb = notebook.load_notebook(directory)

    directory = nb._dir

    if not quiet:
        print "The notebook files are stored in:", nb._dir

    nb.conf()['idle_timeout'] = int(timeout)

    if openid is not None:
        nb.conf()['openid'] = openid
    elif not nb.conf()['openid']:
        # What is the purpose behind this elif?  It seems rather pointless.
        # all it appears to do is set the config to False if bool(config) is False
        nb.conf()['openid'] = False

    if accounts is not None:
        nb.user_manager().set_accounts(accounts)
    else:
        nb.user_manager().set_accounts(nb.conf()['accounts'])

    if nb.user_manager().user_exists('root') and not nb.user_manager().user_exists('admin'):
        # This is here only for backward compatibility with one
        # version of the notebook.
        s = nb.create_user_with_same_password('admin', 'root')
        # It would be a security risk to leave an escalated account around.

    if not nb.user_manager().user_exists('admin'):
        reset = True

    if reset:
        passwd = get_admin_passwd()
        if nb.user_manager().user_exists('admin'):
            admin = nb.user_manager().user('admin')
            admin.set_password(passwd)
            print "Password changed for user 'admin'."
        else:
            nb.user_manager().create_default_users(passwd)
            print "User admin created with the password you specified."
            print "\n\n"
            print "*" * 70
            print "\n"
            if secure:
                print "Login to the Sage notebook as admin with the password you specified above."
        #nb.del_user('root')

    nb.set_server_pool(server_pool)
    nb.set_ulimit(ulimit)

    if os.path.exists('%s/nb-older-backup.sobj' % directory):
        nb._migrate_worksheets()
        os.unlink('%s/nb-older-backup.sobj' % directory)
        print "Updating to new format complete."


    nb.upgrade_model()
    nb.save()
    del nb

    if interface != 'localhost' and not secure:
            print "*" * 70
            print "WARNING: Insecure notebook server listening on external interface."
            print "Unless you are running this via ssh port forwarding, you are"
            print "**crazy**!  You should run the notebook with the option secure=True."
            print "*" * 70

    port = find_next_available_port(interface, port, port_tries)
    if automatic_login:
        "******"
    if secure:
        if (not os.path.exists(private_pem) or
            not os.path.exists(public_pem)):
            print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
            print "Now running notebook.setup()"
            notebook_setup()
        if (not os.path.exists(private_pem) or
            not os.path.exists(public_pem)):
            print "Failed to setup notebook.  Please try notebook.setup() again manually."

    kw = dict(port=port, automatic_login=automatic_login, secure=secure, private_pem=private_pem, public_pem=public_pem,
              interface=interface, directory=directory, pidfile=pidfile, cwd=cwd, profile=profile, upload = upload )
    cmd = command[server]().run_command(kw)
    if cmd is None:
        return

    if not quiet:
        print_open_msg('localhost' if not interface else interface,
        port, secure=secure)
    if secure and not quiet:
        print "There is an admin account.  If you do not remember the password,"
        print "quit the notebook and type notebook(reset=True)."
    print "Executing", cmd
    if fork:
        import pexpect
        return pexpect.spawn(cmd)
    else:
        e = os.system(cmd)

    os.chdir(cwd)
    if e == 256:
        raise socket.error
Exemple #4
0
    def run(port):
        # Is a server already running? Check if a Twistd PID exists in
        # the given directory.
        pidfile = os.path.join(directory, 'twistd.pid')
        if platformType != 'win32':
            from twisted.scripts._twistd_unix import checkPID
            try:
                checkPID(pidfile)
            except SystemExit as e:
                pid = int(open(pidfile).read())

                if str(e).startswith('Another twistd server is running,'):
                    print 'Another Sage Notebook server is running, PID %d.' % pid
                    old_interface, old_port, old_secure = get_old_settings(conf)
                    if open_viewer and old_port:
                        old_interface = old_interface or 'localhost'

                        print 'Opening web browser at http%s://%s:%s/ ...' % (
                            's' if old_secure else '', old_interface, old_port)

                        from sagenb.misc.misc import open_page as browse_to
                        browse_to(old_interface, old_port, old_secure, '/')
                        return
                    print '\nPlease either stop the old server or run the new server in a different directory.'
                    return

        ## Create the config file
        if secure:
            if (not os.path.exists(private_pem) or
                not os.path.exists(public_pem)):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if (not os.path.exists(private_pem) or
                not os.path.exists(public_pem)):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = '%s:%s:interface=%s:privateKey=%s:certKey=%s'%(
                protocol, port, interface, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s' % (port, interface)

        notebook_opts = '"%s",interface="%s",port=%s,secure=%s' % (
            os.path.abspath(directory), interface, port, secure)

        if open_viewer:
            start_path = "'/?startup_token=%s' % startup_token"
            if interface:
                hostname = interface
            else:
                hostname = 'localhost'
            open_page = "from sagenb.misc.misc import open_page; open_page('%s', %s, %s, %s)" % (hostname, port, secure, start_path)
        else:
            open_page = ''

        config = open(conf, 'w')

        config.write(FLASK_NOTEBOOK_CONFIG%{'notebook_opts': notebook_opts, 'sagetex_path': sagetex_path,
                                            'do_not_require_login': not require_login,
                                            'dir': os.path.abspath(directory), 'cwd':cwd, 
                                            'strport': strport,
                                            'open_page': open_page})


        config.close()                     

        ## Start up twisted
        cmd = 'twistd --pidfile="%s" -ny "%s"' % (pidfile, conf)
        if not quiet:
            print_open_msg('localhost' if not interface else interface,
            port, secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."

        if fork:
            import pexpect
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)

        os.chdir(cwd)
        if e == 256:
            raise socket.error

        return True
Exemple #5
0
    def run(port, subnets):
        ## Create the config file
        if secure:
            if not os.path.exists(private_pem) or not os.path.exists(public_pem):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if not os.path.exists(private_pem) or not os.path.exists(public_pem):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = '%s:%s:interface=%s:privateKey=%s:certKey=%s'%(protocol, port, interface, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s'%(port, interface)

        notebook_opts = '"%s",interface="%s",port=%s,secure=%s' % (os.path.abspath(directory),
                interface, port, secure)

        if open_viewer:
            start_path = "'/?startup_token=%s' % startup_token"
            if interface:
                hostname = interface
            else:
                hostname = 'localhost'
            open_page = "from sagenb.misc.misc import open_page; open_page('%s', %s, %s, %s)"%(hostname, port, secure, start_path)
        else:
            open_page = ''
        
        config = open(conf, 'w')

        if subnets is None:
            factory = "factory = channel.HTTPFactory(site)"
        else:
            if not isinstance(subnets, (list, tuple)):
                subnets = [subnets]
            factory = """
# See http://stackoverflow.com/questions/1273297/python-twisted-restricting-access-by-ip-address
from sagenb.misc.ipaddr import IPNetwork
subnets = eval(r"%s")
if not any(s.startswith('127') for s in subnets):
    subnets.insert(0, '127.0.0.0/8')
subnets = [IPNetwork(x) for x in subnets]
class RestrictedIPFactory(channel.HTTPFactory):
    def buildProtocol(self, addr):
        a = str(addr.host)
        for X in subnets:
            if a in X:
                return channel.HTTPFactory.buildProtocol(self, addr)
        print 'Ignoring all requests from IP address '+str(addr.host)
        
factory = RestrictedIPFactory(site)
"""%tuple([subnets])

        config.write(FLASK_NOTEBOOK_CONFIG%{'notebook_opts': notebook_opts, 'sagetex_path': sagetex_path,
                                            'do_not_require_login': not require_login,
                                            'dir': os.path.abspath(directory), 'cwd':cwd, 
                                            'factory': factory, 'strport': strport,
                                            'open_page': open_page})


        config.close()                     

        pidfile = os.path.join(directory, 'twistd.pid')
        cmd = 'twistd --pidfile="%s" -ny "%s"' % (pidfile, os.path.join(directory, 'twistedconf.tac'))

        # Check if a Twistd PID exists in the given directory
        if platformType != 'win32':
            from twisted.scripts._twistd_unix import checkPID
            try:
                checkPID(pidfile)
            except SystemExit as e:
                pid = int(open(pidfile).read())
                if str(e).startswith('Another twistd server is running,'):
                    sys.exit("""\
Another Sage Notebook server is running, PID %d.

Please either stop the old server or run the new server in a different directory.
""" % pid)
        ## Start up twisted
        if not quiet:
            print_open_msg('localhost' if not interface else interface, port, secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."

        if fork:
            import pexpect
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)

        os.chdir(cwd)
        if e == 256:
            raise socket.error

        return True
Exemple #6
0
    def run(port, subnets):
        ## Create the config file
        if secure:
            if not os.path.exists(private_pem) or not os.path.exists(
                    public_pem):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if not os.path.exists(private_pem) or not os.path.exists(
                    public_pem):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = '%s:%s:interface=%s:privateKey=%s:certKey=%s' % (
                protocol, port, interface, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s' % (port, interface)

        notebook_opts = '"%s",interface="%s",port=%s,secure=%s' % (
            os.path.abspath(directory), interface, port, secure)

        if open_viewer:
            start_path = "'/?startup_token=%s' % startup_token"
            if interface:
                hostname = interface
            else:
                hostname = 'localhost'
            open_page = "from sagenb.misc.misc import open_page; open_page('%s', %s, %s, %s)" % (
                hostname, port, secure, start_path)
        else:
            open_page = ''

        config = open(conf, 'w')

        if subnets is None:
            factory = "factory = channel.HTTPFactory(site)"
        else:
            if not isinstance(subnets, (list, tuple)):
                subnets = [subnets]
            factory = """
# See http://stackoverflow.com/questions/1273297/python-twisted-restricting-access-by-ip-address
from sagenb.misc.ipaddr import IPNetwork
subnets = eval(r"%s")
if not any(s.startswith('127') for s in subnets):
    subnets.insert(0, '127.0.0.0/8')
subnets = [IPNetwork(x) for x in subnets]
class RestrictedIPFactory(channel.HTTPFactory):
    def buildProtocol(self, addr):
        a = str(addr.host)
        for X in subnets:
            if a in X:
                return channel.HTTPFactory.buildProtocol(self, addr)
        print 'Ignoring all requests from IP address '+str(addr.host)
        
factory = RestrictedIPFactory(site)
""" % tuple([subnets])

        config.write(
            FLASK_NOTEBOOK_CONFIG % {
                'notebook_opts': notebook_opts,
                'sagetex_path': sagetex_path,
                'do_not_require_login': not require_login,
                'dir': os.path.abspath(directory),
                'cwd': cwd,
                'factory': factory,
                'strport': strport,
                'open_page': open_page
            })

        config.close()

        pidfile = os.path.join(directory, 'twistd.pid')
        cmd = 'twistd --pidfile="%s" -ny "%s"' % (
            pidfile, os.path.join(directory, 'twistedconf.tac'))

        # Check if a Twistd PID exists in the given directory
        if platformType != 'win32':
            from twisted.scripts._twistd_unix import checkPID
            try:
                checkPID(pidfile)
            except SystemExit as e:
                pid = int(open(pidfile).read())
                if str(e).startswith('Another twistd server is running,'):
                    sys.exit("""\
Another Sage Notebook server is running, PID %d.

Please either stop the old server or run the new server in a different directory.
""" % pid)
        ## Start up twisted
        if not quiet:
            print_open_msg('localhost' if not interface else interface,
                           port,
                           secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."

        if fork:
            import pexpect
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)

        os.chdir(cwd)
        if e == 256:
            raise socket.error

        return True
Exemple #7
0
    def run(port):
        # Is a server already running? Check if a Twistd PID exists in
        # the given directory.
        pidfile = os.path.join(directory, 'twistd.pid')
        if platformType != 'win32':
            from twisted.scripts._twistd_unix import checkPID
            try:
                checkPID(pidfile)
            except SystemExit as e:
                pid = int(open(pidfile).read())

                if str(e).startswith('Another twistd server is running,'):
                    print 'Another Sage Notebook server is running, PID %d.' % pid
                    old_interface, old_port, old_secure = get_old_settings(
                        conf)
                    if open_viewer and old_port:
                        old_interface = old_interface or 'localhost'

                        print 'Opening web browser at http%s://%s:%s/ ...' % (
                            's' if old_secure else '', old_interface, old_port)

                        from sagenb.misc.misc import open_page as browse_to
                        browse_to(old_interface, old_port, old_secure, '/')
                        return
                    print '\nPlease either stop the old server or run the new server in a different directory.'
                    return

        ## Create the config file
        if secure:
            if (not os.path.exists(private_pem)
                    or not os.path.exists(public_pem)):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if (not os.path.exists(private_pem)
                    or not os.path.exists(public_pem)):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = '%s:%s:interface=%s:privateKey=%s:certKey=%s' % (
                protocol, port, interface, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s' % (port, interface)

        notebook_opts = '"%s",interface="%s",port=%s,secure=%s' % (
            os.path.abspath(directory), interface, port, secure)

        if open_viewer:
            start_path = "'/?startup_token=%s' % startup_token"
            if interface:
                hostname = interface
            else:
                hostname = 'localhost'
            open_page = "from sagenb.misc.misc import open_page; open_page('%s', %s, %s, %s)" % (
                hostname, port, secure, start_path)
        else:
            open_page = ''

        config = open(conf, 'w')

        config.write(
            FLASK_NOTEBOOK_CONFIG % {
                'notebook_opts': notebook_opts,
                'sagetex_path': sagetex_path,
                'do_not_require_login': not require_login,
                'dir': os.path.abspath(directory),
                'cwd': cwd,
                'strport': strport,
                'open_page': open_page
            })

        config.close()

        ## Start up twisted
        cmd = 'twistd --pidfile="%s" -ny "%s"' % (pidfile, conf)
        if not quiet:
            print_open_msg('localhost' if not interface else interface,
                           port,
                           secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."

        if fork:
            import pexpect
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)

        os.chdir(cwd)
        if e == 256:
            raise socket.error

        return True
    def run(port):
        ## Create the config file
        if secure:
            if not os.path.exists(private_pem) or not os.path.exists(public_pem):
                print "In order to use an SECURE encrypted notebook, you must first run notebook.setup()."
                print "Now running notebook.setup()"
                notebook_setup()
            if not os.path.exists(private_pem) or not os.path.exists(public_pem):
                print "Failed to setup notebook.  Please try notebook.setup() again manually."
            strport = '%s:%s:interface=%s:privateKey=%s:certKey=%s'%(protocol, port, address, private_pem, public_pem)
        else:
            strport = 'tcp:%s:interface=%s'%(port, address)

        notebook_opts = '"%s",address="%s",port=%s,secure=%s' % (os.path.abspath(directory),
                address, port, secure)

        if open_viewer:
            if require_login:
                start_path = "'/?startup_token=%s' % startup_token"
            else:
                start_path = "'/'"
            open_page = "from sagenb.misc.misc import open_page; open_page('%s', %s, %s, %s)"%(address, port, secure, start_path)
        else:
            open_page = ''
        
        config = open(conf, 'w')

        config.write("""
####################################################################        
# WARNING -- Do not edit this file!   It is autogenerated each time
# the notebook(...) command is executed.
####################################################################
from twisted.internet import reactor

# Now set things up and start the notebook
import sagenb.notebook.notebook
sagenb.notebook.notebook.JSMATH=True
import sagenb.notebook.notebook as notebook
import sagenb.notebook.twist as twist
twist.notebook = notebook.load_notebook(%s)
twist.SAGETEX_PATH = "%s"
twist.OPEN_MODE = %s
twist.SID_COOKIE = str(hash("%s"))
twist.init_updates()
import sagenb.notebook.worksheet as worksheet

import signal, sys, random
def save_notebook():
    from twisted.internet.error import ReactorNotRunning
    print "Saving notebook..."
    twist.notebook.save()
    try:
        reactor.stop()
    except ReactorNotRunning:
        pass
    print "Notebook cleanly saved."
    
def my_sigint(x, n):
    save_notebook()
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    
    
signal.signal(signal.SIGINT, my_sigint)

## Disable client-side certificate request for gnutls
try:
    import gnutls.connection
    gnutls.connection.CERT_REQUEST = 0
except (OSError, ImportError):
    print "Note: GNUTLS not available."


## Authentication framework (ported from Knooboo)
from twisted.web2 import log, server, channel
from twisted.cred import portal, checkers, credentials
import sagenb.notebook.guard as guard
import sagenb.notebook.avatars as avatars

from twisted.cred import portal

realm = avatars.LoginSystem()
p = portal.Portal(realm)
startup_token = '%%x' %% random.randint(0, 2**128)
startup_checker = avatars.OneTimeTokenChecker()
startup_checker.token = startup_token
p.registerChecker(startup_checker)
password_checker = avatars.PasswordChecker()
p.registerChecker(password_checker)
p.registerChecker(checkers.AllowAnonymousAccess())
rsrc = guard.MySessionWrapper(p)
log.DefaultCommonAccessLoggingObserver().start()
site = server.Site(rsrc)
factory = channel.HTTPFactory(site)

from twisted.web2 import channel
from twisted.application import service, strports
application = service.Application("SAGE Notebook")
s = strports.service('%s', factory)
%s
s.setServiceParent(application)

reactor.addSystemEventTrigger('before', 'shutdown', save_notebook)

"""%(notebook_opts, sagetex_path, not require_login,
     os.path.abspath(directory), strport, open_page))


        config.close()                     

        ## Start up twisted
        if not quiet:
            print_open_msg('localhost' if not address else address, port, secure=secure)
        if secure and not quiet:
            print "There is an admin account.  If you do not remember the password,"
            print "quit the notebook and type notebook(reset=True)."
        cmd = 'twistd --pidfile="%s"/twistd.pid -ny "%s"/twistedconf.tac'%(directory, directory)
        if fork:
            import pexpect
            return pexpect.spawn(cmd)
        else:
            e = os.system(cmd)
        if e == 256:
            raise socket.error
        return True