Ejemplo n.º 1
0
def decodestring(cookiestring, userdir):
    """Given a username/password encoded into a string - decode it and check it's validity.
    It checks the username against the one stored in the user file..
    """
# try decoding the string, if it's badly formed then it may raise an excpetion - in which case we just return False
    try:
        instring, daynumber, timestamp = pass_dec(cookiestring)
    except:
        return False
# check it's not a really old (or copied) cookie
    if not unexpired(daynumber, timestamp, AGETEST):
        return False
# we've extracted the timestamped string from the cookie string.
# Let's pull out the username and password hash
    try:
        username, pwd_hash = instring.split('||')
    except ValueError:
        return False
# Now we need to check it's a valid username and check the password
    if username in RESERVEDNAMES or not os.path.isfile(userdir+username+'.ini'):
        return False
    user = ConfigObj(userdir+username+'.ini')
    stamped_pwd_hash = user['password']
    maxage = user['max-age']
    cookiepath = ConfigObj(userdir+'config.ini')['cookiepath']
# the password is time stamped - so we need to decode it 
    try:
        stored_pwd_hash, _, _= pass_dec(stamped_pwd_hash)
    except:
        return False
    if pwd_hash != stored_pwd_hash:
        return False
    return user, pwd_hash, cookiepath
Ejemplo n.º 2
0
def validatelogin(formdict, userdir, thisscript, action):
    name = formdict['username']
    tempstore = ConfigObj(userdir + 'temp.ini')
    pendinglist = tempstore.get('pending', [])
    if os.path.isfile(userdir+name+'.ini') or name in pendinglist or name.lower() in RESERVEDNAMES:
        invalidentry('Username already exists.', formdict, userdir, thisscript, action)
    for char in name.lower():
        if not char in validchars:
            invalidentry('Username contains invalid characters.', formdict, userdir, thisscript, action)
    return name
Ejemplo n.º 3
0
def validatelogin(formdict, userdir, thisscript, action):
    name = formdict['username']
    tempstore = ConfigObj(userdir + 'temp.ini')
    pendinglist = tempstore.get('pending', [])
    if os.path.isfile(
            userdir + name +
            '.ini') or name in pendinglist or name.lower() in RESERVEDNAMES:
        invalidentry('Username already exists.', formdict, userdir, thisscript,
                     action)
    for char in name.lower():
        if not char in validchars:
            invalidentry('Username contains invalid characters.', formdict,
                         userdir, thisscript, action)
    return name
Ejemplo n.º 4
0
def doeditconfig(theform, userdir, thisscript, userconfig, action, newcookie):
    """Receives the submission from the edit config page."""
    config = ConfigObj(userdir + 'config.ini')
    default = ConfigObj(userdir + 'default.ini')

    loginlink = theform.getfirst('loginlink', '')
    adminmail = theform.getfirst('adminmail', '')
    emailsubj = theform.getfirst('emailsubject', '')
    emailmsg = theform.getfirst('emailmsg', '')
    maxage = theform.getfirst('maxage', '')
    editable = theform.getfirst('editable', '')

    if adminmail and not validemail(adminmail):
        editconfig(theform, userdir, thisscript, userconfig, action, newcookie, "The adminmail doesn't appear to be a valid address.")
    if not maxage.isdigit():
        editconfig(theform, userdir, thisscript, userconfig, action, newcookie, "maxage must be a number.")
    if int(maxage) and int(maxage) < MINMAXAGE:
        editconfig(theform, userdir, thisscript, userconfig, action, newcookie, "maxage must be greater than %s." % MINMAXAGE)

    if loginlink:
        config['newloginlink'] = 'Yes'
    else:
        config['newloginlink'] = 'No'
    config['adminmail'] = adminmail
    config['email_subject'] = emailsubj
    config['email_message'] = emailmsg
    config.write()
    default['max-age'] = maxage
    if editable:
        default['editable'] = 'Yes'
    else:
        default['editable'] = 'No'
    default.write()

    displaymenu(theform, userdir, thisscript, userconfig, action, newcookie)            # XXXX should we send a msg here 'COnfig File Edited' ?
Ejemplo n.º 5
0
def createuser(userdir, realname, username, email, password, adminlev):
    """Create a new user."""
    from time import time
    from modules.dataenc import pass_enc
    from modules.configobj import ConfigObj

    user = ConfigObj(userdir + 'default.ini')
    user.filename = userdir + username + '.ini'  # XXXX  this does no checkign htat the name is valid and doesn't already exist !!
    user['username'] = username
    user['realname'] = realname
    user['email'] = email
    user['admin'] = adminlev
    user['password'] = pass_enc(password, timestamp=True, daynumber=True)
    user['created'] = str(time())
    user.write()
Ejemplo n.º 6
0
def createuser(userdir, realname, username, email, password, adminlev):
    """Create a new user."""
    from time import time
    from modules.dataenc import pass_enc
    from modules.configobj import ConfigObj
    
    user = ConfigObj(userdir+'default.ini')
    user.filename = userdir + username + '.ini'         # XXXX  this does no checkign htat the name is valid and doesn't already exist !!
    user['username'] = username
    user['realname'] = realname
    user['email'] = email
    user['admin'] = adminlev
    user['password'] = pass_enc(password, timestamp=True, daynumber=True)
    user['created'] = str(time())
    user.write()
Ejemplo n.º 7
0
def confirm(theform, userdir, thisscript):
    """Confirm a login.
    Either from an invite or from a user who has registered."""
    from modules.dataenc import pass_dec, pass_enc
    from login import encodestring
    fail = False
    try:
        theval, daynumber, timestamp = pass_dec(theform['id'].value)
    except:
        # FIXME: bare except....
        newloginfail()
    tempstore = ConfigObj(userdir + 'temp.ini')
    if not tempstore.has_key(theval):
        newloginfail()
    uservals = tempstore[theval]
    del tempstore[theval]
    username = uservals['username']
    if username in tempstore['pending']:
        tempstore['pending'].remove(username)
    tempstore.write()
    #
    newconfig = ConfigObj(userdir + 'default.ini')
    newpath = userdir + username + '.ini'
    if os.path.isfile(newpath):
        newloginfail()
    newconfig.filename = newpath
    # FIXME: should this be '' ?
    action = None
    for entry in uservals:
        if entry == 'action':
            action = uservals[entry]
        elif entry == 'password':
            password = uservals[entry]
            newconfig[entry] = pass_enc(password, timestamp=True, daynumber=True)
        else:
            newconfig[entry] = uservals[entry]
    newconfig.write()
    #
    # next we need to create the cookie header to return it 
    from Cookie import SimpleCookie
    thecookie = SimpleCookie()
    thecookie['userid'] = encodestring(newconfig['username'], password)
    config = ConfigObj(userdir + 'config.ini')
    maxage = newconfig['max-age'] 
    cookiepath = config['cookiepath']
    if maxage and int(maxage):            # possible cause of error here if the maxage value in a users file isn't an integer !!
        thecookie['userid']['max-age'] = int(maxage) 
    if cookiepath:
        thecookie['userid']['path'] = cookiepath 
    if config['adminmail']:
        msg = 'A new user has created a login - "%s".\n\n' % thisscript
        for entry in newconfig:
            if entry != 'password':
                msg += entry + '   :   ' + newconfig[entry] + '\n'
        # FIXME: should be mailme
        sendmailme(config['adminmail'], msg, config['email_subject'],
                config['adminmail'], html=False)
    return action, newconfig, thecookie.output()
Ejemplo n.º 8
0
def displaylogin(userdir, thisscript=None, action=None, failed=False):
    """This function will display the login page and then exit.
    Usually called if the user has no cookie or an expired/forged cookie.
    """
    if thisscript == None:
        thisscript = THISSCRIPT
    config = ConfigObj(userdir + 'config.ini')
    templatedir = userdir + ".." + os.sep + config['templatedir'].replace("/",os.sep)


    loginform = readfile(templatedir+form_nojs)
    loginform = loginform.replace('**script**', thisscript)

    loginpage = readfile(templatedir+logintemplate)  
    loginpage = loginpage.replace('**login form**', loginform)

    if failed:
        loginpage = loginpage.replace('**login failed**', '<b style="color:red">Wrong user name or password</b>')
    else:
        loginpage = loginpage.replace('**login failed**', '')

    if istrue(config['newloginlink']):
        loginpage = loginpage.replace('<!-- **commstart**', '')
        loginpage = loginpage.replace('**commend** -->', '')
        loginpage = loginpage.replace('**new login link**', thisscript+'?login=newlogin')

    if action:
        loginpage = loginpage.replace('<!-- **action** -->', actionline % action)
    print(serverline)
    print('\r')
    print(loginpage)
    
    sys.exit()
Ejemplo n.º 9
0
def checknewlogin(userdir):
    """Check that new logins are enabled on this setup.
    Return or display the error message and quit."""
    config = ConfigObj(userdir + 'config.ini')
    if istrue(config['newloginlink']):
        return
    error('Sorry, New Logins are Disabled on this System.')
Ejemplo n.º 10
0
def doinvite(theform, userdir, thisscript, userconfig, action, newcookie):
    """Receives the submission from the invite/create new user page."""
    config = ConfigObj(userdir + 'config.ini')
    default = ConfigObj(userdir + 'default.ini')

    create = theform.getfirst('create', '')
    realname = theform.getfirst('realname', '')
    username = theform.getfirst('username', '')
    email = validemail(theform.getfirst('email', ''))
    pass1 = theform.getfirst('pass1', '')
    pass2 = theform.getfirst('pass2', '')
    adminlev = theform.getfirst('adminlev', '')
    
    maxadminlev = min(int(userconfig['admin']), MAXADMINLEV)
    
    if not email:
        invite(theform, userdir, thisscript, userconfig, action, newcookie, 'The email address appears to be invalid.')
    if pass1 != pass2:
        invite(theform, userdir, thisscript, userconfig, action, newcookie, "The two passwords don't match.")
    if len(pass1) < 5:    
        invite(theform, userdir, thisscript, userconfig, action, newcookie, "The password must be at least five characters long.")
    if not realname:
        invite(theform, userdir, thisscript, userconfig, action, newcookie, 'You must supply a realname.')
    if not username:
        invite(theform, userdir, thisscript, userconfig, action, newcookie, 'You must supply a username.')
    if not adminlev.isdigit():
        invite(theform, userdir, thisscript, userconfig, action, newcookie, 'Admin level must be a number.')
    if int(adminlev) > maxadminlev:
        invite(theform, userdir, thisscript, userconfig, action, newcookie, 'Admin level is greater than the maximum allowed (%s).' % maxadminlev)

# now we need to check if the username already exists
    tempstore = ConfigObj(userdir + 'temp.ini')
    pendinglist = tempstore.get('pending', [])
    if os.path.isfile(userdir+username+'.ini') or username in pendinglist or username.lower() in RESERVEDNAMES:
        invite(theform, userdir, thisscript, userconfig, action, newcookie, 'username already exists.')
    for char in username.lower():
        if not char in validchars:
            invite(theform, userdir, thisscript, userconfig, action, newcookie, 'username contains invalid characters.')
# now we have verified the values - we *either* need to create a new username *or* send an invitiation
    
    if create == 'create':
        createuser(userdir, realname, username, email, pass1, adminlev)
        msg = 'New User Created'
    else:
        inviteuser(userdir, realname, username, email, pass1, thisscript, adminlev)
        msg = 'New User Invited'
    invite(theform, userdir, thisscript, userconfig, action, newcookie, msg, True)
Ejemplo n.º 11
0
def donewlogin(theform, userdir, thisscript, action=None):
    """Process the results from new login form submissions."""
    loginaction = theform['login'].value
    if not loginaction == 'donewloginnojs':
        # only type of newlogin supported so far
        sys.exit()
    # check that new logins are enabled on this setup
    checknewlogin(userdir)
    allentries = theform.keys()
    vallist = allentries + [
        entry for entry in newloginformkeys if entry not in allentries
    ]
    formdict = getform(vallist, theform, nolist=True)
    for entry in newloginformkeys:
        if not formdict[entry]:
            invalidentry(
                'Required field missing : "%s"' % newloginformkeys[entry],
                formdict, userdir, thisscript, action)
    # missingentry should redisplay the form, with values filled in, and then exit
    email = validateemail(formdict)
    if not email:
        invalidentry('Email address appears to be invalid.', formdict, userdir,
                     thisscript, action)
    # if the address is invalid it should behave like missingentry
    # also max one login per email address ?
    login = validatelogin(formdict, userdir, thisscript, action)
    # if login name already exists or is invalid
    password = validatepass(formdict, userdir, thisscript, action)
    # if passwords don't match or are too short
    realname = formdict['realname']
    # If we've got this far we've got a valid new login and need to save the
    # details, send the email and print a mesage
    #
    config = ConfigObj(userdir + 'config.ini')
    link_url = savedetails(
        userdir, formdict,
        action)  # this includes any 'extra' keys, not just the ones we require
    msg = config['email_message'] + '\n'
    msg = msg + SCRIPTLOC + thisscript + '?login=confirm&id=' + link_url
    writefile('log.txt', msg)
    mailme(email,
           msg,
           config['email_subject'],
           config['mail_server_address'],
           config['mail_server_host'],
           config['mail_server_port'],
           config['mail_server_user'],
           config['mail_server_password'],
           html=False)
    #
    templatedir = config['templatedir']
    logindonepage = readfile(templatedir + logindone)
    logindonepage = logindonepage.replace('**this script**', thisscript)
    #
    print serverline
    print '\r'
    print logindonepage
    #
    sys.exit()
Ejemplo n.º 12
0
def doeditaccount(theform, userconfig, userdir, thisscript, action, newcookie):
    """Process the results from edit account form submissions."""
    from modules.dataenc import pass_enc, pass_dec
    loginaction = theform['login'].value
    if not loginaction == 'doeditaccountnojs':  # only type of newlogin supported so far
        sys.exit()
    allentries = theform.keys()
    vallist = allentries + [
        entry for entry in edacckeys if entry not in allentries
    ]
    formdict = getform(vallist, theform, nolist=True)
    #
    oldpass_hash = pwd_context.hash(formdict['pass0'], salt="")
    storedpass_hash = pass_dec(userconfig['password'])[0]
    pass1 = formdict['pass1']
    pass2 = formdict['pass2']
    #
    email = validateemail(formdict)
    oldemail = userconfig['email']
    if not email:
        msg = 'The email address you supplied appears to be invalid.'
        display_edit(formdict, userdir, thisscript, msg, action, newcookie,
                     userconfig)
    if email != oldemail and (not oldpass_hash
                              or oldpass_hash != storedpass_hash):
        msg = 'You must correctly enter your password to change your email address.'
        display_edit(formdict, userdir, thisscript, msg, action, newcookie,
                     userconfig)
    userconfig['email'] = email
    if not formdict['realname']:
        msg = 'You need to enter a name for us to use.'
        display_edit(formdict, userdir, thisscript, msg, action, newcookie,
                     userconfig)
    userconfig['realname'] = formdict['realname']
    if pass1 or pass2:
        if pass1 != pass2:
            msg = "The two passwords don't match."
            display_edit(formdict, userdir, thisscript, msg, action, newcookie,
                         userconfig)
        if len(pass1) < 5:
            msg = "The password must be longer than 5 characters."
            display_edit(formdict, userdir, thisscript, msg, action, newcookie,
                         userconfig)
        if not oldpass_hash or oldpass_hash != storedpass_hash:
            msg = 'You must correctly enter your current password to change it.'
            display_edit(formdict, userdir, thisscript, msg, action, newcookie,
                         userconfig)
        pass1_hash = pwd_context.hash(pass1, salt="")
        userconfig['password'] = pass_enc(pass1_hash,
                                          daynumber=True,
                                          timestamp=True)
        newcookie = makecookie(userconfig, pass1_hash,
                               ConfigObj(userdir + 'config.ini')['cookiepath'])
    for entry in formdict:
        if entry not in edacckeys:
            userconfig[entry] = formdict[entry]
    userconfig.write()
    return action, userconfig, newcookie  # XXXXX display values changed page
Ejemplo n.º 13
0
def invite(theform, userdir, thisscript, userconfig, action, newcookie, msg=None, success=None):
    """Display the screen to create or invite a new user."""
    config = ConfigObj(userdir + 'config.ini')
    templatedir = config['templatedir']
    
    adminpage = readfile(templatedir+adminpage_file)
    adminpage = adminpage.replace('**this script**', thisscript + '?action=' + action)
    adminpage = adminpage.replace('**admin menu**', thisscript+'?login=admin'+'&action='+action)

# Values to be filled in are :
# **create1** and **create2** - the one switched on should be 'checked', the other should be ''

    if msg:
        adminpage = adminpage.replace('<br><!- message --> ', '<h2>'+msg+'</h2>')
    if msg and not success:
        create = theform.getfirst('create', '')
        if create == 'create':
            create1 = 'checked'
            create2 = ''
        else:
            create2 = 'checked'
            create1 = ''
        realname = theform.getfirst('realname', '')
        username = theform.getfirst('username', '')
        email = theform.getfirst('email', '')
        pass1 = theform.getfirst('pass1', '')
        pass2 = theform.getfirst('pass2', '')
        adminlev = theform.getfirst('adminlev', '')
    else:
        create2 = 'checked'
        create1 = ''
        realname = ''
        username = ''
        email = ''
        pass1 = randomstring(8)
        pass2 = pass1
        adminlev = '0'
        
    invitemenu = readfile(templatedir+admininvite_file)
    invitemenu = invitemenu.replace('**create1**', create1)
    invitemenu = invitemenu.replace('**create2**', create2)
    invitemenu = invitemenu.replace('**realname**', realname)
    invitemenu = invitemenu.replace('**username**', username)
    invitemenu = invitemenu.replace('**email**', email)
    invitemenu = invitemenu.replace('**pass1**', pass1)
    invitemenu = invitemenu.replace('**pass2**', pass2)
    invitemenu = invitemenu.replace('**adminlev**', adminlev)

    invitemenu = invitemenu.replace('**thisscript**', thisscript)
    invitemenu = invitemenu.replace('**action**', action)

    adminpage = adminpage.replace('**admin**', invitemenu)
    print newcookie
    print serverline
    print
    print adminpage
    sys.exit()
Ejemplo n.º 14
0
def checkpass(username, password, userdir, thisscript, action):
    """Check the password from a new login."""
# XXXX log failed login attempts
    if username in RESERVEDNAMES:
        return False
    if not os.path.isfile(userdir+username+'.ini'):
        return False
    user = ConfigObj(userdir+username+'.ini')
    stampedpass = user['password']
    cookiepath = ConfigObj(userdir+'config.ini')['cookiepath']
# we need to un-time stamp the password
    realpass, daynumber, timestamp = pass_dec(stampedpass)
    if realpass != password:
        return False

    #open('xxxtest.txt', 'w').write(str(user))
# if we've got this far then the login was successful and we need to return a cookie
    thecookie = makecookie(user, password, cookiepath)
    return action, user, thecookie
Ejemplo n.º 15
0
def savedetails(userdir, formdict, action=None):
    """
    Given the form from a validated new login, it saves the details to the 
    temporary store.
    
    It also cleans up any out of date ones that haven't been used.
    """
    from modules.dateutils import returndate, daycount
    from modules.dataenc import pass_enc
    #
    tempstore = ConfigObj(userdir + 'temp.ini')
    if action: 
        formdict['action'] = action
    year, month, day = returndate()
    today = daycount(year, month, day)
    #
    for section in tempstore:
        if section[4:].isdigit():
            if int(section[4:]) > today + 30:
                name = tempstore[section]['username']
                tempstore['pending'].remove(name)
                del tempstore[section]
    #
    ran = randomstring(4)
    while tempstore.has_key(ran+str(today)):
        ran = randomstring(4)
    key = ran+str(today)
    tempstore[key] = {}
    store = tempstore[key]
    for entry in formdict:
        if entry == 'pass1' or entry == 'pass2':
            store['password'] = formdict[entry]
        elif entry == 'login':
            pass
        else:
            store[entry] = formdict[entry]
    if not tempstore.has_key('pending'):
        tempstore['pending'] = []
    tempstore['pending'].append(formdict['username'])
    tempstore.write()
    return pass_enc(key, timestamp=True, daynumber=True)
Ejemplo n.º 16
0
def update_git_info(user,
                    new_git_username,
                    new_git_password,
                    new_git_2fa=False):
    o = ConfigObj(prefix + 'users' + os.sep + user + '.ini')
    o['git_username'] = new_git_username
    o['git_2fa'] = str(new_git_2fa).lower()

    try:
        note = project + ", " + time.ctime()
        auth = github3.authorize(new_git_username, new_git_password, ['repo'],
                                 note, "")
        o['git_token'] = auth.token
        o['git_id'] = auth.id
        if 'git_password' in o:
            del o['git_password']
        o.write()
    except:
        # fail silently--would want to display an error ideally, but
        # users will know to try again if the credentials are wrong
        pass
Ejemplo n.º 17
0
def inviteuser(userdir, realname, username, email, password, thisscript, adminlev):
    """Invite a new user."""
    from newlogin import savedetails
    from configobj import ConfigObj
    formdict = {'username' : username, 'pass1' : password, 'admin' : adminlev,
                'realname' : realname, 'email' : email, 'action' : '' }
    thekey = savedetails(userdir, formdict)
    config = ConfigObj(userdir + 'config.ini') 
    msg = config['email_message'] + '\n'
    msg = msg + SCRIPTLOC + thisscript + '?login=confirm&id=' + thekey + (pass_msg % (username, password))
    writefile('log.txt', msg)
    sendmailme(email, msg, config['email_subject'], email, html=False)
Ejemplo n.º 18
0
def get_menu():
    config = ConfigObj(prefix + "users" + os.sep + "config.ini")

    if "banner" not in config:
        return ""
    banner = config["banner"]

    if banner.startswith("http"):  # Web resource
        resp = requests.get(banner)
        return resp.text
    else:  # File name in templates/ dir
        banner = config["banner"]
        banner = open(prefix + "templates" + os.sep + banner).read()
        return banner
Ejemplo n.º 19
0
def display_edit(formdict,
                 userdir,
                 thisscript,
                 msg,
                 action,
                 newcookie,
                 userconfig=None):
    """
    Display the form for editing account details.
    This is a different form to creating a new account as it requires
    confirmation of the old password before doing certain things, like 
    changing email address and password.
    """
    from time import ctime
    print newcookie
    config = ConfigObj(userdir + 'config.ini')
    templatedir = config['templatedir']
    # if we are sending the userconfig as the formdict, we needn't explicitly
    # pass it in
    if not userconfig:
        userconfig = formdict
    #
    edaccform = unicode(readfile(templatedir + editform_nojs))
    edaccform = edaccform.replace('**script**', thisscript)
    #
    edaccpage = readfile(templatedir + edacctemplate)
    edaccpage = edaccpage.replace('**edit account form**', edaccform)
    edaccpage = filltemplate(edaccpage, formdict)
    if msg:
        edaccpage = edaccpage.replace('<!-- **message** -->',
                                      '<h2>' + msg + '</h2><br>')
    edaccpage = edaccpage.replace('**created on**',
                                  ctime(float(userconfig['created'])))
    edaccpage = edaccpage.replace('**num logins**', userconfig['numlogins'])
    edaccpage = edaccpage.replace('**last used**',
                                  ctime(float(userconfig['lastused'])))
    edaccpage = edaccpage.replace('**num used**', userconfig['numused'])
    edaccpage = edaccpage.replace('**this script**',
                                  thisscript + '?action=' + action)
    #
    if action:
        edaccpage = edaccpage.replace('<!-- **action** -->',
                                      actionline % action)
    print serverline
    print '\r'
    print edaccpage
    #
    sys.exit()
Ejemplo n.º 20
0
def get_git_credentials(user, admin, code):
    global code_2fa
    code_2fa = code
    if admin == 0:
        return

    scriptpath = os.path.dirname(
        os.path.realpath(__file__)) + os.sep + ".." + os.sep
    userdir = scriptpath + "users" + os.sep
    user_dict = ConfigObj(userdir + user + '.ini')

    git_username = user_dict[
        'git_username'] if "git_username" in user_dict else "_"
    git_token = user_dict['git_token'] if "git_token" in user_dict else "_"
    git_use2fa = user_dict['git_2fa'] if "git_2fa" in user_dict else "false"
    return git_username, git_token, git_use2fa
Ejemplo n.º 21
0
def getReleaseNotes():
    """return release notes fir the given version string
  (major.minor.build, EXAMPLE: "2.3.1")
  if no release notes are found, return None
  """
    # release notes aren't displayed on each start
    # (eq if the user marked the current notes as
    # read or disabled release notes altogether)
    # so import configobj only when needed
    versionNumbers = None
    try:
        from modules.configobj import ConfigObj
        releaseNotes = ConfigObj(RELEASE_NOTES_FILE_PATH)
        versionNumbers = releaseNotes['release_notes_section'].keys()
    except Exception, e:
        print('info: loading release notes failed')
        print(e)
Ejemplo n.º 22
0
def displaymenu(theform, userdir, thisscript, userconfig, action, newcookie):
    """Display the admin menu page."""
    config = ConfigObj(userdir + 'config.ini')
    templatedir = config['templatedir']
    
    adminpage = readfile(templatedir+adminpage_file)
    adminpage = adminpage.replace('**this script**', thisscript + '?action=' + action)
    
    url = '?login=admin&admin=%s&action=' + action 
    adminmenu = readfile(templatedir+adminmenu_file)
    adminmenu = adminmenu.replace('**edit config**', thisscript+url % 'editconfig')
    adminmenu = adminmenu.replace('**edit users**', thisscript+url % 'edituser')
    adminmenu = adminmenu.replace('**invite**', thisscript+url % 'invite')

    adminpage = adminpage.replace('**admin**', adminmenu)
    adminpage = adminpage.replace('**admin menu**', thisscript+'?login=admin'+'&action='+action)
        
    print newcookie
    print serverline
    print
    print adminpage
    sys.exit()
Ejemplo n.º 23
0
def invalidentry(msg, formdict, userdir, thisscript, action=None):
    """Display the newlogin form."""
    config = ConfigObj(userdir + 'config.ini')
    templatedir = config['templatedir']
    #
    newloginform = readfile(templatedir + newform_nojs)
    newloginform = newloginform.replace('**script**', thisscript)
    #
    newloginpage = readfile(templatedir + newlogintemplate)
    newloginpage = newloginpage.replace('**new login form**', newloginform)
    newloginpage = filltemplate(newloginpage, formdict)
    newloginpage = newloginpage.replace('<!-- **message** -->',
                                        '<h2>' + msg + '</h2><br>')
    #
    if action:
        newloginpage = newloginpage.replace('<!-- **action** -->',
                                            actionline % action)
    print serverline
    print '\r'
    print newloginpage
    #
    sys.exit()
Ejemplo n.º 24
0
def newlogin(userdir, thisscript, action=None):
    """Display the newlogin form."""
    config = ConfigObj(userdir + 'config.ini')
    templatedir = userdir + ".." + os.sep + config['templatedir'].replace(
        "/", os.sep)
    # check that new logins are enabled on this setup
    checknewlogin(userdir)
    #
    newloginform = readfile(templatedir + newform_nojs)
    newloginform = newloginform.replace('**script**', thisscript)
    #
    newloginpage = readfile(templatedir + newlogintemplate)
    newloginpage = newloginpage.replace('**new login form**', newloginform)
    newloginpage = filltemplate(newloginpage)
    #
    if action:
        newloginpage = newloginpage.replace('<!-- **action** -->',
                                            actionline % action)
    print serverline
    print '\r'
    print newloginpage
    #
    sys.exit()
Ejemplo n.º 25
0
def savedetails(userdir, formdict, action=None):
    """
    Given the form from a validated new login, it saves the details to the 
    temporary store.
    
    It also cleans up any out of date ones that haven't been used.
    """
    from modules.dateutils import returndate, daycount
    from modules.dataenc import pass_enc
    #
    tempstore = ConfigObj(userdir + 'temp.ini')
    if action:
        formdict['action'] = action
    year, month, day = returndate()
    today = daycount(year, month, day)
    #
    for section in tempstore:
        if section[4:].isdigit():
            if int(section[4:]) > today + 30:
                name = tempstore[section]['username']
                tempstore['pending'].remove(name)
                del tempstore[section]
    #
    ran = randomstring(4)
    while tempstore.has_key(ran + str(today)):
        ran = randomstring(4)
    key = ran + str(today)
    tempstore[key] = {}
    store = tempstore[key]
    for entry in formdict:
        if entry == 'pass1' or entry == 'pass2':
            store['password'] = pwd_context.hash(formdict[entry], salt="")
        elif entry == 'login':
            pass
        else:
            store[entry] = formdict[entry]
    if not tempstore.has_key('pending'):
        tempstore['pending'] = []
    tempstore['pending'].append(formdict['username'])
    tempstore.write()
    return pass_enc(key, timestamp=True, daynumber=True)
Ejemplo n.º 26
0
	'''
	if mode != "server":
		cpout = cpout.replace(".py","")
	return cpout

# Main script when running from Apache
def structure_main_server():
	thisscript = os.environ.get('SCRIPT_NAME', '')
	action = None
	theform = cgi.FieldStorage()
	scriptpath = os.path.dirname(os.path.realpath(__file__)) + os.sep
	userdir = scriptpath + "users" + os.sep
	action, userconfig = login(theform, userdir, thisscript, action)
	user = userconfig["username"]
	admin = userconfig["admin"]
	kwargs={}
	for key in theform:
		kwargs[key] = theform[key].value
	print structure_main(user, admin, 'server', **kwargs)


scriptpath = os.path.dirname(os.path.realpath(__file__)) + os.sep
userdir = scriptpath + "users" + os.sep
config = ConfigObj(userdir + 'config.ini')
if "/" in os.environ.get('SCRIPT_NAME', ''):
	mode = "server"
else:
	mode = "local"

if mode == "server":
	structure_main_server()
Ejemplo n.º 27
0
def structure_main(user, admin, mode, **kwargs):

    scriptpath = os.path.dirname(os.path.realpath(__file__)) + os.sep
    userdir = scriptpath + "users" + os.sep
    theform = kwargs

    cgitb.enable()

    ###GRAPHICAL PARAMETERS###
    top_spacing = 20
    layer_spacing = 60

    config = ConfigObj(userdir + 'config.ini')
    templatedir = scriptpath + config['controltemplates'].replace("/", os.sep)

    template = "main_header.html"
    header = readfile(templatedir + template)
    header = header.replace("**page_title**", "Structure editor")
    header = header.replace("**user**", user)

    cpout = ""
    if mode == "server":
        cpout += "Content-Type: text/html\n\n\n"
        header = header.replace("**logout_control**",
                                '(<a href="logout.py">log out</a>)')
    else:
        header = header.replace("**logout_control**", '')
    cpout += header

    if "current_doc" in theform:
        current_doc = theform["current_doc"]
        current_project = theform["current_project"]
        current_guidelines = get_guidelines_url(current_project)
    else:
        current_doc = ""
        current_project = ""
        current_guidelines = ""

    UTF8Writer = codecs.getwriter('utf8')
    sys.stdout = UTF8Writer(sys.stdout)

    edit_bar = "edit_bar.html"
    edit_bar = readfile(templatedir + edit_bar)
    edit_bar = edit_bar.replace("**doc**", current_doc)
    edit_bar = edit_bar.replace("**project**", current_project)
    edit_bar = edit_bar.replace("**structure_disabled**",
                                'disabled="disabled"')
    edit_bar = edit_bar.replace("**segment_disabled**", '')
    edit_bar = edit_bar.replace("**relations_disabled**", '')
    edit_bar = edit_bar.replace("**screenshot_disabled**", '')
    edit_bar = edit_bar.replace("**quickexp_disabled**", '')
    edit_bar = edit_bar.replace("**current_guidelines**", current_guidelines)
    if mode == "server":
        edit_bar = edit_bar.replace("**submit_target**", 'structure.py')
    else:
        edit_bar = edit_bar.replace("**submit_target**", 'structure')
    edit_bar = edit_bar.replace("**action_type**", 'action')
    edit_bar = edit_bar.replace("**serve_mode**", mode)
    edit_bar = edit_bar.replace("**open_disabled**", '')
    edit_bar = edit_bar.replace(
        'id="nav_edit" class="nav_button"',
        'id="nav_edit" class="nav_button nav_button_inset"')

    if admin == "3":
        edit_bar = edit_bar.replace("**admin_disabled**", '')
    else:
        edit_bar = edit_bar.replace("**admin_disabled**",
                                    'disabled="disabled"')

    cpout += edit_bar

    help = "help.html"
    help = readfile(templatedir + help)
    help_match = re.search(r'(<div id="help_edit".*?</div>)', help,
                           re.MULTILINE | re.DOTALL)
    help = help_match.group(1)
    if sys.version_info[0] == 2:
        cpout += help.decode("utf-8")
    else:
        cpout += help

    about = "about.html"
    about = readfile(templatedir + about)
    about = about.replace("**version**", _version.__version__)
    cpout += about

    if current_guidelines != "":
        cpout += '<script>enable_guidelines();</script>'

    if current_doc == "":
        cpout += '<p class="warn">No file found - please select a file to open</p>'
        return cpout

    cpout += '''
          <div id="container" class="container">
            <button id="show-all-signals">
              Show All Signal Tokens
            </button>
            <div class="signal-drawer">
              <div id="signal-list"> </div>

			  <div class="signal-drawer__row">
			    <button id="new-signal" class="signal-drawer__create-new-button">
  			      <i class="fa fa-plus" title="New Signal"> </i>
			      New Signal
			    </button>
			  </div>
			  <div class="signal-drawer__row" style="text-align: center;padding-top:20px;">
  		        <button id="save-signals" class="signal-drawer__save-button">
  		          <i class="fa fa-check"> </i>
  		          Save Changes
  		        </button>
  		        <button id="cancel-signals" class="signal-drawer__cancel-button">
  		          <i class="fa fa-ban"> </i>
  		          Cancel
  		        </button>
  		      </div>
            </div>
    '''

    cpout += '''<div id="canvas" class="canvas">'''
    cpout += '\t<p id="document_name">Document: <b>' + current_doc + '</b> (project: <i>' + current_project + '</i>)</p>'
    cpout += '''<div id="inner_canvas">'''
    cpout += '<script src="./script/structure.js"></script>'

    # Remove floating non-terminal nodes if found
    # (e.g. due to browsing back and re-submitting old actions or other data corruption)
    clean_floating_nodes(current_doc, current_project, user)

    rels = get_rst_rels(current_doc, current_project)
    def_multirel = get_def_rel("multinuc", current_doc, current_project)
    def_rstrel = get_def_rel("rst", current_doc, current_project)
    multi_options = ""
    rst_options = ""
    rel_kinds = {}
    for rel in rels:
        if rel[1] == "multinuc":
            multi_options += "<option value='" + rel[0] + "'>" + rel[
                0].replace("_m", "") + '</option>\n'
            rel_kinds[rel[0]] = "multinuc"
        else:
            rst_options += "<option value='" + rel[0] + "'>" + rel[0].replace(
                "_r", "") + '</option>\n'
            rel_kinds[rel[0]] = "rst"
    multi_options += "<option value='" + def_rstrel + "'>(satellite...)</option>\n"

    timestamp = ""
    if "timestamp" in theform:
        if len(theform["timestamp"]) > 1:
            timestamp = theform["timestamp"]

    refresh = check_refresh(user, timestamp)

    if "action" in theform and not refresh:
        if len(theform["action"]) > 1:
            action_log = theform["action"]
            if len(action_log) > 0:
                actions = action_log.split(";")
                set_timestamp(user, timestamp)
                for action in actions:
                    action_type = action.split(":")[0]
                    action_params = action.split(":")[1] if len(
                        action.split(":")) > 1 else ""
                    params = action_params.split(",")
                    if action_type == "up":
                        update_parent(params[0], params[1], current_doc,
                                      current_project, user)
                    elif action_type == "sp":
                        insert_parent(params[0], "span", "span", current_doc,
                                      current_project, user)
                    elif action_type == "mn":
                        insert_parent(params[0], def_multirel, "multinuc",
                                      current_doc, current_project, user)
                    elif action_type == "rl":
                        update_rel(params[0], params[1], current_doc,
                                   current_project, user)
                    elif action_type == "sg":
                        update_signals(
                            action.split(":")[1:], current_doc,
                            current_project, user)
                    else:
                        cpout += '<script>alert("the action was: " + theform["action"]);</script>\n'

    if "logging" in theform and not refresh:
        if len(theform["logging"]) > 1:
            if get_setting("logging") == "on":
                logging = theform["logging"]
                if len(logging) > 0:
                    update_log(current_doc, current_project, user, logging,
                               "structure", str(datetime.datetime.now()))

    if "reset" in theform or user == "demo":
        if len(theform["reset"]) > 1 or user == "demo":
            reset_rst_doc(current_doc, current_project, user)

    nodes = {}
    rows = get_rst_doc(current_doc, current_project, user)
    for row in rows:
        if row[7] in rel_kinds:
            relkind = rel_kinds[row[7]]
        else:
            relkind = "span"
        if row[5] == "edu":
            nodes[row[0]] = NODE(row[0], row[1], row[2], row[3], row[4],
                                 row[5], row[6], row[7], relkind)
        else:
            nodes[row[0]] = NODE(row[0], 0, 0, row[3], row[4], row[5], row[6],
                                 row[7], relkind)

    for key in nodes:
        node = nodes[key]
        get_depth(node, node, nodes)

    for key in nodes:
        if nodes[key].kind == "edu":
            get_left_right(key, nodes, 0, 0, rel_kinds)

    signals = {}

    for signal in get_signals(current_doc, current_project, user):
        s_id, s_type, subtype, tokens = signal
        if s_id not in signals:
            signals[s_id] = list()
        if tokens:
            tokens = list(map(int, tokens.split(",")))
        else:
            tokens = []
        signals[s_id].append({
            'type': s_type,
            'subtype': subtype,
            'tokens': tokens
        })
    cpout += '<script>'
    cpout += 'window.rstWebSignals = ' + json.dumps(signals) + ';'
    cpout += 'window.rstWebSignalTypes = ' + json.dumps(get_signal_types_dict(
        current_doc, current_project),
                                                        sort_keys=True) + ';'
    cpout += 'window.rstWebDefaultSignalType = Object.keys(window.rstWebSignalTypes)[0];'
    cpout += 'window.rstWebDefaultSignalSubtype = window.rstWebSignalTypes[window.rstWebDefaultSignalType][0];'
    cpout += '</script>'

    anchors = {}
    pix_anchors = {}

    dbpath = os.path.dirname(os.path.realpath(__file__)) + os.sep + "rstweb.db"
    conn = sqlite3.connect(dbpath)
    cur = conn.cursor()

    # Calculate anchor points for nodes
    # First get proportional position for anchor

    nodes_data = get_multinuc_nodes_data(cur, current_doc, current_project,
                                         user)

    node_to_lr = {}

    for node in nodes_data:
        if not node[1] in node_to_lr:
            node_to_lr[node[1]] = {'left': {}, 'right': {}}
        if not node[2] in node_to_lr[node[1]]['left']:
            node_to_lr[node[1]]['left'][node[2]] = node[0]
        if not node[3] in node_to_lr[node[1]]['right']:
            node_to_lr[node[1]]['right'][node[3]] = node[0]

    for key in sorted(nodes, key=lambda id: nodes[id].depth, reverse=True):
        node = nodes[key]
        if node.kind == "edu":
            anchors[node.id] = "0.5"
        if node.parent != "0":
            parent = nodes[node.parent]
            parent_wid = (parent.right - parent.left + 1) * 100 - 4
            child_wid = (node.right - node.left + 1) * 100 - 4
            if node.relname == "span":
                if node.id in anchors:
                    anchors[parent.id] = str((
                        (node.left - parent.left) * 100) / parent_wid +
                                             float(anchors[node.id]) *
                                             float(child_wid / parent_wid))
                else:
                    anchors[parent.id] = str((
                        (node.left - parent.left) * 100) / parent_wid +
                                             (0.5 * child_wid) / parent_wid)
            elif node.relkind == "multinuc" and parent.kind == "multinuc":
                # For multinucs, the anchor is in the middle between leftmost and rightmost of the multinuc children
                # (not including other rst children)
                node_lr = node_to_lr[node.parent]
                lr = [
                    min(node_lr['left'].keys()),
                    max(node_lr['right'].keys())
                ]

                lr_wid = (lr[0] + lr[1]) / 2
                lr_ids = (node_to_lr[node.parent]['left'][lr[0]],
                          node_to_lr[node.parent]['right'][lr[1]])

                left_child = lr_ids[0]
                right_child = lr_ids[1]
                if left_child == right_child:
                    anchors[parent.id] = "0.5"
                else:
                    if left_child in anchors and right_child in anchors:  #both leftmost and rightmost multinuc children have been found
                        len_left = nodes[left_child].right - nodes[
                            left_child].left + 1
                        len_right = nodes[right_child].right - nodes[
                            right_child].left + 1
                        anchors[parent.id] = str(
                            ((float(anchors[left_child]) * len_left * 100 +
                              float(anchors[right_child]) * len_right * 100 +
                              (nodes[right_child].left - parent.left) * 100) /
                             2) / parent_wid)
                    else:
                        anchors[parent.id] = str(
                            (lr_wid - parent.left + 1) /
                            (parent.right - parent.left + 1))

            else:
                if not parent.id in anchors:
                    anchors[parent.id] = "0.5"

    # Place anchor element to center on proportional position relative to parent
    for key in nodes:
        node = nodes[key]
        pix_anchors[node.id] = str(
            int(3 + node.left * 100 - 100 - 39 + float(anchors[node.id]) *
                ((node.right - node.left + 1) * 100 - 4)))

    # Check that span and multinuc buttons should be used (if the interface is not used for RST, they may be disabled)
    if int(get_schema()) > 2:
        use_span_buttons = True if get_setting(
            "use_span_buttons") == "True" else False
        use_multinuc_buttons = True if get_setting(
            "use_multinuc_buttons") == "True" else False
    else:
        use_span_buttons = True
        use_multinuc_buttons = True

    if sys.version_info[0] == 2:
        lambda_button = "Λ".decode("utf-8")
    else:
        lambda_button = "Λ"

    tok_count = 0
    for key in sorted(nodes.keys(), key=int):
        node = nodes[key]
        if node.kind != "edu":
            g_wid = str(int((node.right - node.left + 1) * 100 - 4))
            cpout += '<div id="lg' + node.id + '" class="group" style="left: ' + str(
                int(node.left * 100 - 100)
            ) + '; width: ' + g_wid + '; top:' + str(
                int(top_spacing + layer_spacing + node.depth * layer_spacing)
            ) + 'px; z-index:1"><div id="wsk' + node.id + '" class="whisker" style="width:' + g_wid + ';"></div></div>'
            cpout += '<div id="g' + node.id + '" class="num_cont" style="position: absolute; left:' + pix_anchors[
                node.id] + 'px; top:' + str(
                    int(4 + top_spacing + layer_spacing +
                        node.depth * layer_spacing)
                ) + 'px; z-index:' + str(
                    int(200 - (node.right - node.left))
                ) + '"><table class="btn_tb"><tr><td rowspan="2"><button id="unlink_' + node.id + '"  title="unlink this node" class="minibtn" onclick="act(' + "'up:" + node.id + ",0'" + ');">X</button></td><td rowspan="2"><span class="num_id">' + str(
                    int(node.left)) + "-" + str(int(
                        node.right)) + '</span></td>'
            if use_span_buttons:
                cpout += '<td><button id="aspan_' + node.id + '" title="add span above" class="minibtn" onclick="act(' + "'sp:" + node.id + "'" + ');">T</button></td>'
            cpout += '</tr>'
            if use_multinuc_buttons:
                cpout += '<tr><td><button id="amulti_' + node.id + '" title="add multinuc above" class="minibtn" onclick="act(' + "'mn:" + node.id + "'" + ');">' + lambda_button + '</button></td></tr>'
            cpout += '</table></div><br/>'

        elif node.kind == "edu":
            cpout += '<div id="edu' + str(
                node.id) + '" class="edu" title="' + str(
                    node.id) + '" style="left:' + str(
                        int(node.id) * 100 - 100) + '; top:' + str(
                            int(top_spacing + layer_spacing + node.depth *
                                layer_spacing)) + '; width: 96px">'
            cpout += '<div id="wsk' + node.id + '" class="whisker" style="width:96px;"></div><div class="edu_num_cont"><table class="btn_tb"><tr><td rowspan="2"><button id="unlink_' + node.id + '" title="unlink this node" class="minibtn" onclick="act(' + "'up:" + node.id + ",0'" + ');">X</button></td><td rowspan="2"><span class="num_id">&nbsp;' + str(
                int(node.left)) + '&nbsp;</span></td>'
            if use_span_buttons:
                cpout += '<td><button id="aspan_' + node.id + '" title="add span above" class="minibtn" onclick="act(' + "'sp:" + node.id + "'" + ');">T</button></td>'
            cpout += '</tr>'
            if use_multinuc_buttons:
                cpout += '<tr><td><button id="amulti_' + node.id + '" title="add multinuc above" class="minibtn" onclick="act(' + "'mn:" + node.id + "'" + ');">' + lambda_button + '</button></td></tr>'
            cpout += '</table></div>'

            for tok in node.text.split(" "):
                tok_count += 1
                cpout += '<span id="tok' + str(
                    tok_count) + '" class="tok">' + tok + '</span> '

            cpout += '</div>'

    max_right = get_max_right(current_doc, current_project, user)

    # Serialize data in hidden input for JavaScript
    cpout += '<input id="data" name="data" type="hidden" '
    hidden_val = ""

    doc_relname_to_reltype = get_doc_relname_to_reltype(
        cur, current_doc, current_project)
    for key in nodes:
        node = nodes[key]
        reltype = doc_relname_to_reltype.get(node.relname)

        if node.relname:
            safe_relname = node.relname
        else:
            safe_relname = "none"
        if node.kind == "edu":
            hidden_val += "n" + node.id + ",n" + node.parent + ",e," + str(
                int(node.left)) + "," + safe_relname + "," + reltype + ";"
        elif node.kind == "span":
            hidden_val += "n" + node.id + ",n" + node.parent + ",s,0," + safe_relname + "," + reltype + ";"
        else:
            hidden_val += "n" + node.id + ",n" + node.parent + ",m,0," + safe_relname + "," + reltype + ";"
    hidden_val = hidden_val[0:len(hidden_val) - 1]
    cpout += 'value="' + hidden_val + '"/>'

    cpout += '<input id="def_multi_rel" type="hidden" value="' + get_def_rel(
        "multinuc", current_doc, current_project) + '"/>\n'
    cpout += '<input id="def_rst_rel" type="hidden" value="' + get_def_rel(
        "rst", current_doc, current_project) + '"/>\n'
    cpout += '<input id="undo_log" type="hidden" value=""/>\n'
    cpout += '<input id="redo_log" type="hidden" value=""/>\n'
    cpout += '<input id="undo_state" type="hidden" value=""/>\n'
    cpout += '<input id="logging" type="hidden" value=""/>\n'
    cpout += '<input id="validations" type="hidden" value="' + get_project_validations(
        current_project) + '"/>\n'
    cpout += '<input id="use_span_buttons" type="hidden" value="' + str(
        use_span_buttons) + '"/>\n'
    cpout += '<input id="use_multinuc_buttons" type="hidden" value="' + str(
        use_multinuc_buttons) + '"/>\n'

    cpout += '''	<script src="./script/jquery.jsPlumb-1.7.5-min.js"></script>

			<script>
			'''

    cpout += 'function select_my_rel(options,my_rel){'
    cpout += 'var multi_options = `' + multi_options + '`;\n'
    cpout += 'var rst_options = `' + rst_options + '`;\n'
    cpout += 'if (options =="multi"){options = multi_options;} else {options=rst_options;}'
    cpout += '		return options.replace("<option value=' + "'" + '"' + '+my_rel+' + '"' + "'" + '","<option selected=' + "'" + 'selected' + "'" + ' value=' + "'" + '"' + '+my_rel+' + '"' + "'" + '");'
    cpout += '			}\n'
    cpout += '''function make_relchooser(id,option_type,rel){
	    var s = "<div id='seldiv"+id.replace("n","")+"' style='white-space:nowrap;'>";
	    s += make_signal_button(id);
	    s += "<select id='sel"+id.replace("n","")+"' class='rst_rel' onchange='crel(" + id.replace("n","") + ",this.options[this.selectedIndex].value);'>" + select_my_rel(option_type,rel) + "</select>";
	    return $(s);
	}'''
    # todo: make a flag that controls whether signals are on
    cpout += 'var signalsEnabled = ' + ('true;' if get_setting("signals")
                                        == "True" else 'false;')
    cpout += '''function make_signal_button(id) {
		if (signalsEnabled) {
			var text = window.rstWebSignals[id]
					? window.rstWebSignals[id].length
					: "S";
			var classes = window.rstWebSignals[id] && window.rstWebSignals[id].length > 0
					? "minibtn minibtn--with-signals"
					: "minibtn";
			return '<button title="add signals" class="' + classes + '" onclick="open_signal_drawer(\\'' + id.replace('n','') + '\\')">' + text + '</button>';
		} else {
			return '';
		}
	}'''
    cpout += '''
			jsPlumb.importDefaults({
			PaintStyle : {
				lineWidth:2,
				strokeStyle: 'rgba(0,0,0,0.5)'
			},
			Endpoints : [ [ "Dot", { radius:1 } ], [ "Dot", { radius:1 } ] ],
			  EndpointStyles : [{ fillStyle:"#000000" }, { fillStyle:"#000000" }],
			  Anchor:"Top",
	            Connector : [ "Bezier", { curviness:50 } ]
			})
			 jsPlumb.ready(function() {

	jsPlumb.setContainer(document.getElementById("inner_canvas"));
	'''

    cpout += "jsPlumb.setSuspendDrawing(true);"

    for key in nodes:
        node = nodes[key]
        if node.kind == "edu":
            node_id_str = "edu" + node.id
        else:
            node_id_str = "g" + node.id
        cpout += 'jsPlumb.makeSource("' + node_id_str + '", {anchor: "Top", filter: ".num_id", allowLoopback:false});'
        cpout += 'jsPlumb.makeTarget("' + node_id_str + '", {anchor: "Top", filter: ".num_id", allowLoopback:false});'

    # Connect nodes
    for key in nodes:
        node = nodes[key]
        if node.parent != "0":
            parent = nodes[node.parent]
            if node.kind == "edu":
                node_id_str = "edu" + node.id
            else:
                node_id_str = "g" + node.id
            if parent.kind == "edu":
                parent_id_str = "edu" + parent.id
            else:
                parent_id_str = "g" + parent.id

            if node.relname == "span":
                cpout += 'jsPlumb.connect({source:"' + node_id_str + '",target:"' + parent_id_str + '", connector:"Straight", anchors: ["Top","Bottom"]});'
            elif parent.kind == "multinuc" and node.relkind == "multinuc":
                cpout += 'jsPlumb.connect({source:"' + node_id_str + '",target:"' + parent_id_str + '", connector:"Straight", anchors: ["Top","Bottom"], overlays: [ ["Custom", {create:function(component) {return make_relchooser("' + node.id + '","multi","' + node.relname + '");},location:0.2,id:"customOverlay"}]]});'
            else:
                cpout += 'jsPlumb.connect({source:"' + node_id_str + '",target:"' + parent_id_str + '", overlays: [ ["Arrow" , { width:12, length:12, location:0.95 }],["Custom", {create:function(component) {return make_relchooser("' + node.id + '","rst","' + node.relname + '");},location:0.1,id:"customOverlay"}]]});'

    cpout += '''

		jsPlumb.setSuspendDrawing(false,true);


		jsPlumb.bind("connection", function(info) {
		   source = info.sourceId.replace(/edu|g/,"")
		   target = info.targetId.replace(/edu|g/g,"")
		});

		jsPlumb.bind("beforeDrop", function(info) {
		    $(".minibtn").prop("disabled",true);

	'''

    cpout += '''
			var node_id = "n"+info.sourceId.replace(/edu|g|lg/,"");
			var new_parent_id = "n"+info.targetId.replace(/edu|g|lg/,"");

			nodes = parse_data();
			new_parent = nodes[new_parent_id];
			relname = nodes[node_id].relname;
			new_parent_kind = new_parent.kind;
			if (nodes[node_id].parent != "n0"){
				old_parent_kind = nodes[nodes[node_id].parent].kind;
			}
			else
			{
				old_parent_kind ="none";
			}

			if (info.sourceId != info.targetId){
				if (!(is_ancestor(new_parent_id,node_id))){
					jsPlumb.select({source:info.sourceId}).detach();
					if (new_parent_kind == "multinuc"){
						relname = get_multirel(new_parent_id,node_id,nodes);
						jsPlumb.connect({source:info.sourceId, target:info.targetId, connector:"Straight", anchors: ["Top","Bottom"], overlays: [ ["Custom", {create:function(component) {return make_relchooser(node_id,"multi",relname);},location:0.2,id:"customOverlay"}]]});
					}
					else{
						jsPlumb.connect({source:info.sourceId, target:info.targetId, overlays: [ ["Arrow" , { width:12, length:12, location:0.95 }],["Custom", {create:function(component) {return make_relchooser(node_id,"rst",relname);},location:0.1,id:"customOverlay"}]]});
					}
					new_rel = document.getElementById("sel"+ node_id.replace("n","")).value;
				    act('up:' + node_id.replace("n","") + ',' + new_parent_id.replace("n",""));
					update_rel(node_id,new_rel,nodes);
					recalculate_depth(parse_data());
				}
			}

		    $(".minibtn").prop("disabled",false);

		});

	});
		nodes = parse_data();
		show_warnings(nodes);

			</script>

'''

    cpout += '''
			</div>
			</div>
			</div>
			<div id="anim_catch" class="anim_catch">&nbsp;</div>
	</body>
	</html>

	'''
    if mode != "server":
        cpout = cpout.replace(".py", "")
    return cpout
Ejemplo n.º 28
0
def open_main(user, admin, mode, **kwargs):

    cpout = ""
    scriptpath = os.path.dirname(os.path.realpath(__file__)) + os.sep
    userdir = scriptpath + "users" + os.sep
    theform = kwargs

    cgitb.enable()

    config = ConfigObj(userdir + 'config.ini')
    templatedir = scriptpath + config['controltemplates'].replace("/", os.sep)
    template = "main_header.html"
    header = readfile(templatedir + template)
    header = header.replace("**page_title**", "Open a file for editing")
    header = header.replace("**user**", user)

    if mode == "server":
        cpout += "Content-Type: text/html\n\n\n"
        header = header.replace("**logout_control**",
                                '(<a href="logout.py">log out</a>)')
    else:
        header = header.replace("**logout_control**", '')
    cpout += header

    if "current_doc" in theform:
        current_doc = theform["current_doc"]
        current_project = theform["current_project"]
    else:
        current_doc = ""
        current_project = ""

    edit_bar = "edit_bar.html"
    edit_bar = readfile(templatedir + edit_bar)
    edit_bar = edit_bar.replace("**doc**", current_doc)
    edit_bar = edit_bar.replace("**project**", current_project)
    edit_bar = edit_bar.replace("**structure_disabled**", '')
    edit_bar = edit_bar.replace("**segment_disabled**", '')
    edit_bar = edit_bar.replace("**relations_disabled**", '')
    if mode == "server":
        edit_bar = edit_bar.replace("**submit_target**", 'structure.py')
    else:
        edit_bar = edit_bar.replace("**submit_target**", 'structure')
    edit_bar = edit_bar.replace("**action_type**", '')
    edit_bar = edit_bar.replace("**serve_mode**", mode)
    edit_bar = edit_bar.replace("**open_disabled**", 'disabled="disabled"')
    edit_bar = edit_bar.replace("**reset_disabled**", 'disabled="disabled"')
    edit_bar = edit_bar.replace("**save_disabled**", 'disabled="disabled"')
    edit_bar = edit_bar.replace("**undo_disabled**", 'disabled="disabled"')
    edit_bar = edit_bar.replace("**redo_disabled**", 'disabled="disabled"')
    edit_bar = edit_bar.replace(
        'id="nav_open" class="nav_button"',
        'id="nav_open" class="nav_button nav_button_inset"')

    if admin == "0":
        edit_bar = edit_bar.replace("**admin_disabled**",
                                    'disabled="disabled"')
    else:
        edit_bar = edit_bar.replace("**admin_disabled**", '')

    cpout += edit_bar
    help = "help.html"
    help = readfile(templatedir + help)
    help_match = re.search(r'(<div id="help_open".*?</div>)', help,
                           re.MULTILINE | re.DOTALL)
    help = help_match.group(1)
    cpout += help

    about = "about.html"
    about = readfile(templatedir + about)
    about = about.replace("**version**", _version.__version__)
    cpout += about

    cpout += "<h2>Current Documents</h2>"
    cpout += '<p>List of documents you are authorized to view:</p>'
    docs = get_docs_by_project(user)
    if not docs:
        cpout += "<p>No documents have been assigned for user name: <b>" + user + "</b></p>"
    else:
        cpout += '<select id="doclist" name="doclist" class="doclist" size="15">\n'
        project_group = ""
        for doc in docs:
            if project_group != doc[1]:
                if project_group != "":
                    cpout += '</optgroup>\n'
                project_group = doc[1]
                cpout += '<optgroup label="' + doc[1] + '">\n'
            cpout += '\t<option value="' + doc[1] + "/" + doc[0] + '">' + doc[
                0] + '</option>\n'

        cpout += '</optgroup>\n</select>\b<br/>'
        cpout += '''<button class="nav_button" onclick="do_open(document.getElementById('doclist').value);">Open file</button>'''

    cpout += '''
	</body>
	</html>
	'''
    if mode != "server":
        cpout = cpout.replace(".py", "")
    return cpout
Ejemplo n.º 29
0
import requests, os, platform
from modules.configobj import ConfigObj

# Support IIS site prefix on Windows
if platform.system() == "Windows":
    prefix = "transc\\"
else:
    prefix = ""

gitdox_root = os.path.dirname(os.path.realpath(__file__))

# to use password authentication, use a netrc file called .netrc in the project root
try:
    ether_url = ConfigObj(gitdox_root + os.sep + "users" + os.sep +
                          "config.ini")["ether_url"]
    if not ether_url.endswith(os.sep):
        ether_url += os.sep
except KeyError:
    ether_url = ""


def get_menu():
    config = ConfigObj(prefix + "users" + os.sep + "config.ini")

    if "banner" not in config:
        return ""
    banner = config["banner"]

    if banner.startswith("http"):  # Web resource
        resp = requests.get(banner)
        return resp.text
Ejemplo n.º 30
0
def get_nlp_credentials():
    config = ConfigObj("users" + os.sep + "config.ini")
    return config["nlp_user"], config["nlp_password"]
Ejemplo n.º 31
0
def segment_main(user, admin, mode, **kwargs):

	cpout = ""
	theform = kwargs

	scriptpath = os.path.dirname(os.path.realpath(__file__)) + os.sep
	userdir = scriptpath + "users" + os.sep

	UTF8Writer = codecs.getwriter('utf8')
	sys.stdout = UTF8Writer(sys.stdout)

	cgitb.enable()

	config = ConfigObj(userdir + 'config.ini')
	templatedir = scriptpath + config['controltemplates'].replace("/",os.sep)
	template = "main_header.html"
	header = readfile(templatedir+template)
	header = header.replace("**page_title**","Segmentation editor")
	header = header.replace("**user**",user)
	header = header.replace("**open_disabled**",'')


	if admin == "0":
		header = header.replace("**admin_disabled**",'disabled="disabled"')
	else:
		header = header.replace("**admin_disabled**",'')

	cpout = ""
	if mode == "server":
		cpout += "Content-Type: text/html\n\n\n"
		header = header.replace("**logout_control**",'(<a href="logout.py">log out</a>)')
	else:
		header = header.replace("**logout_control**",'')
	cpout += header


	if "current_doc" in theform:
		current_doc = theform["current_doc"]
		current_project = theform["current_project"]
		current_guidelines = get_guidelines_url(current_project)
	else:
		current_doc = ""
		current_project = ""
		current_guidelines = ""


	edit_bar = "edit_bar.html"
	edit_bar = readfile(templatedir+edit_bar)
	edit_bar = edit_bar.replace("**doc**",current_doc)
	edit_bar = edit_bar.replace("**project**",current_project)
	edit_bar = edit_bar.replace("**structure_disabled**",'')
	edit_bar = edit_bar.replace("**save_disabled**",'')
	edit_bar = edit_bar.replace("**reset_disabled**",'')
	edit_bar = edit_bar.replace("**segment_disabled**",'disabled="disabled"')
	edit_bar = edit_bar.replace("**submit_target**",'segment.py')
	edit_bar = edit_bar.replace("**action_type**",'seg_action')
	edit_bar = edit_bar.replace("**current_guidelines**",current_guidelines)
	edit_bar = edit_bar.replace("**serve_mode**",mode)
	edit_bar = edit_bar.replace("**open_disabled**",'')
	edit_bar = edit_bar.replace('id="nav_segment" class="nav_button"','id="nav_segment" class="nav_button nav_button_inset"')

	if admin == "0":
		edit_bar = edit_bar.replace("**admin_disabled**",'disabled="disabled"')
	else:
		edit_bar = edit_bar.replace("**admin_disabled**",'')

	cpout += edit_bar

	help = "help.html"
	help = readfile(templatedir+help)
	help_match = re.search(r'(<div.*?help_seg.*?</div>)',help,re.MULTILINE|re.DOTALL)
	help = help_match.group(1)
	cpout += help

	about = "about.html"
	about = readfile(templatedir+about)
	about = about.replace("**version**", _version.__version__)
	cpout += about

	if current_doc =="":
		cpout += '<p class="warn">No file found - please select a file to open</p>'
		return cpout

	cpout += '<input id="undo_log" type="hidden" value=""/>'
	cpout += '<input id="redo_log" type="hidden" value=""/>'
	cpout += '<input id="undo_state" type="hidden" value=""/>'

	cpout += '''<div class="canvas">
	<div id="inner_canvas">'''


	if "reset" in theform or user=="demo":
		if len(theform["reset"]) > 1 or user=="demo":
			reset_rst_doc(current_doc,current_project,user)

	if "logging" in theform:
		if len(theform["logging"]) > 1:
			logging = theform["logging"]
			if len(logging) > 0:
				update_log(current_doc,current_project,user,logging,"segment",str(datetime.datetime.now()))

	if "seg_action" in theform:
		if len(theform["seg_action"]) > 1:
			action_log = theform["seg_action"]
			if len(action_log) > 0:
				actions = action_log.split(";")
				for action in actions:
					action_type = action.split(":")[0]
					action_params = action.split(":")[1]
					if action_type =="ins":
						insert_seg(int(action_params.replace("tok","")),current_doc,current_project,user)
					elif action_type =="del":
						merge_seg_forward(int(action_params.replace("tok","")),current_doc,current_project,user)

	segs={}


	rows = get_rst_doc(current_doc,current_project,user)

	if current_guidelines != "":
		cpout += '<script>enable_guidelines();</script>'

	cpout += '\t<script src="script/segment.js"></script>'
	cpout += '<h2>Edit segmentation</h2>'
	cpout += '\t<div id="control">'
	cpout += '\t<p>Document: <b>'+current_doc+'</b> (project: <i>'+current_project+'</i>)</p>'
	cpout += '\t<div id="segment_canvas">'

	for row in rows:
		if row[5] =="edu":
			segs[int(row[0])] = SEGMENT(row[0],row[6])

	seg_counter=0
	tok_counter=0

	segs = collections.OrderedDict(sorted(segs.items()))
	first_seg = True
	for seg_id in segs:
		first_tok = True
		seg = segs[seg_id]
		seg_counter+=1
		if first_seg:
			first_seg = False
		else:
			cpout += '<div class="tok_space" id="tok'+str(tok_counter)+'" style="display:none" onclick="act('+"'ins:"+'tok'+str(tok_counter)+"'"+')">&nbsp;</div>'
			cpout += '\t\t\t<div id="segend_post_tok'+str(tok_counter)+'" class="seg_end" onclick="act('+"'del:"+'tok'+str(tok_counter)+"'"+')">||</div>'
			cpout += '\t\t</div>'
		cpout += '\t\t<div id="seg'+ str(seg_counter) +'" class="seg">'
		for token in seg.tokens:
			tok_counter+=1
			if first_tok:
				first_tok = False
			else:
				cpout += '<div class="tok_space" id="tok'+str(tok_counter-1)+'" onclick="act('+"'ins:"+'tok'+str(tok_counter-1)+"'"+')">&nbsp;</div>'
			cpout += '\t\t\t<div class="token" id="string_tok'+str(tok_counter)+'">' + token + '</div>'
	cpout += '\t\t</div>'
	cpout += '''\t</div></div>
	</body>
	</html>

	'''
	if mode != "server":
		cpout = cpout.replace(".py","")
	return cpout
Ejemplo n.º 32
0
def doedituser(theform, userdir, thisscript, userconfig, action, newcookie):
    """Receives form submissions from the 'edit user' page."""
# parameters to get :
# username, realname, email, adminlev, pass1, pass2
    username = theform.getfirst('username')         # the user we are editing
    loginname = theform.getfirst('loginname')       # the new user name (won't usually change I guess)
    realname = theform.getfirst('realname')
    email = theform.getfirst('email')
    adminlev = theform.getfirst('adminlev')
    pass1 = theform.getfirst('pass1')
    pass2 = theform.getfirst('pass2')
    maxage = theform.getfirst('maxage')
    editable = theform.getfirst('editable')
    
    maxadminlev = min(int(userconfig['admin']), MAXADMINLEV)

# check all the account values
# this could be turned into a generic 'account checker' function if we wanted.
    email = validemail(email)
    if not email:
        edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'The Email Address Appears to Be Invalid.')
    if not loginname:
        edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'You Must Supply a Login Name.')
    for char in loginname.lower():
        if not char in validchars:
            edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'Login Name Contains Invalid Characters')
    if not realname:
        edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'You Must Supply a Real Name')
    if (pass1 or pass2) and not (pass1 and pass2):
        edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'To Change the Password - Enter it Twice')
    if pass1 != pass2:
        edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'The Two Passwords Are Different')
    if pass1 and len(pass1) < 5:
        edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'Password Must Be at Least Five Characters')
    if not adminlev.isdigit():
        edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'The Admin Level Must Be a Number')
    if int(adminlev) > maxadminlev:
        edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'Admin Level is Higher than the Max (%s).' % maxadminlev)
    if not maxage.isdigit():
        edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'Cookie "max-age" Must Be a Number')
    if int(maxage) and int(maxage) < MINMAXAGE:
        edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'Cookie "max-age" Must Be Greater Than %s' % MINMAXAGE)
    if editable:
        editable = 'Yes'
    else:
        editable = 'No'
    # let's just check if the username has changed
    thisuser = ConfigObj(userdir+username+'.ini') 
    if loginname != username:
        pendinglist = ConfigObj(userdir + 'temp.ini').get('pending', [])
        if os.path.isfile(userdir+loginname+'.ini') or loginname in pendinglist or loginname.lower() in RESERVEDNAMES:
            edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'Login Name Chosen Already Exists')    
        thisuser.filename = userdir+loginname+'.ini'                # change to new name
        os.remove(userdir+username+'.ini')                          # free up the old name
    if pass1:
        from dataenc import pass_enc
        thisuser['password'] = pass_enc(pass1, daynumber=True, timestamp=True)
    #
    thisuser['realname'] = realname
    thisuser['email'] = email 
    thisuser['admin'] = adminlev 
    thisuser['max-age'] = maxage 
    thisuser['editable'] = editable
    thisuser.write()
    
#    edituser(theform, userdir, thisscript, userconfig, action, newcookie, '')
    edituser(theform, userdir, thisscript, userconfig, action, newcookie, 'Changes Made Successfully', True)
Ejemplo n.º 33
0
def confirm(theform, userdir, thisscript):
    """Confirm a login.
    Either from an invite or from a user who has registered."""
    from modules.dataenc import pass_dec, pass_enc
    from login import encodestring
    fail = False
    try:
        theval, daynumber, timestamp = pass_dec(theform['id'].value)
    except:
        # FIXME: bare except....
        newloginfail()
    tempstore = ConfigObj(userdir + 'temp.ini')
    if not tempstore.has_key(theval):
        newloginfail()
    uservals = tempstore[theval]
    del tempstore[theval]
    username = uservals['username']
    if username in tempstore['pending']:
        tempstore['pending'].remove(username)
    tempstore.write()
    #
    newconfig = ConfigObj(userdir + 'default.ini')
    newpath = userdir + username + '.ini'
    if os.path.isfile(newpath):
        newloginfail()
    newconfig.filename = newpath
    # FIXME: should this be '' ?
    action = None
    for entry in uservals:
        if entry == 'action':
            action = uservals[entry]
        elif entry == 'password':
            password = uservals[entry]
            pwd_hash = pwd_context.hash(password, salt="")
            newconfig[entry] = pass_enc(pwd_hash,
                                        timestamp=True,
                                        daynumber=True)
        else:
            newconfig[entry] = uservals[entry]
    newconfig.write()
    #
    # next we need to create the cookie header to return it
    from Cookie import SimpleCookie
    thecookie = SimpleCookie()
    pwd_hash = pwd_context.hash(password, salt="")
    thecookie['userid'] = encodestring(newconfig['username'], pwd_hash)
    config = ConfigObj(userdir + 'config.ini')
    maxage = newconfig['max-age']
    cookiepath = config['cookiepath']
    if maxage and int(
            maxage
    ):  # possible cause of error here if the maxage value in a users file isn't an integer !!
        thecookie['userid']['max-age'] = int(maxage)
    if cookiepath:
        thecookie['userid']['path'] = cookiepath
    if config['adminmail']:
        msg = 'A new user has created a login - "%s".\n\n' % thisscript
        for entry in newconfig:
            if entry != 'password':
                msg += entry + '   :   ' + newconfig[entry] + '\n'
        # FIXME: should be mailme
        sendmailme(config['adminmail'],
                   msg,
                   config['email_subject'],
                   config['adminmail'],
                   html=False)
    return action, newconfig, thecookie.output()
Ejemplo n.º 34
0
def admin_main(user, admin, mode, **kwargs):

    scriptpath = os.path.dirname(os.path.realpath(__file__)) + os.sep
    userdir = scriptpath + "users" + os.sep
    config = ConfigObj(userdir + 'config.ini')
    exportdir = scriptpath + config['exportdir'].replace("/", os.sep)

    theform = kwargs
    cgitb.enable()

    import re

    def is_email(email):
        pattern = '[\.\w]{1,}[@]\w+[.]\w+'
        if re.match(pattern, email):
            return True
        else:
            return False

    config = ConfigObj(userdir + 'config.ini')
    templatedir = scriptpath + config['controltemplates'].replace("/", os.sep)
    template = "main_header.html"
    header = readfile(templatedir + template)
    header = header.replace("**page_title**", "Administration")
    header = header.replace("**user**", user)

    importdir = scriptpath + config['importdir'].replace("/", os.sep)
    def_relfile = scriptpath + config['default_rels'].replace("/", os.sep)

    cpout = ""
    if mode == "server":
        cpout += "Content-Type: text/html\n\n\n"
        header = header.replace("**logout_control**",
                                '(<a href="logout.py">log out</a>)')
    else:
        header = header.replace("**logout_control**", '')
    cpout += header

    if "current_doc" in theform:
        current_doc = theform["current_doc"]
        current_project = theform["current_project"]
    else:
        current_doc = ""
        current_project = ""

    edit_bar = "edit_bar.html"
    edit_bar = readfile(templatedir + edit_bar)
    edit_bar = edit_bar.replace("**doc**", current_doc)
    edit_bar = edit_bar.replace("**project**", current_project)
    edit_bar = edit_bar.replace("**structure_disabled**", '')
    edit_bar = edit_bar.replace("**segment_disabled**", '')
    edit_bar = edit_bar.replace("**relations_disabled**", '')
    edit_bar = edit_bar.replace("**submit_target**", 'admin.py')
    edit_bar = edit_bar.replace("**action_type**", '')
    edit_bar = edit_bar.replace("**serve_mode**", mode)
    edit_bar = edit_bar.replace("**open_disabled**", '')
    edit_bar = edit_bar.replace("**reset_disabled**", 'disabled="disabled"')
    edit_bar = edit_bar.replace("**quickexp_disabled**", 'disabled="disabled"')
    edit_bar = edit_bar.replace("**screenshot_disabled**",
                                'disabled="disabled"')
    edit_bar = edit_bar.replace("**save_disabled**", 'disabled="disabled"')
    edit_bar = edit_bar.replace("**undo_disabled**", 'disabled="disabled"')
    edit_bar = edit_bar.replace("**redo_disabled**", 'disabled="disabled"')
    edit_bar = edit_bar.replace("**admin_disabled**", 'disabled="disabled"')
    edit_bar = edit_bar.replace(
        'id="nav_admin" class="nav_button"',
        'id="nav_admin" class="nav_button nav_button_inset"')

    if admin == "0":
        cpout += '<p class="warn">User ' + user + ' does not have administrator rights!</p></body></html>'
        return cpout
    else:
        edit_bar = edit_bar.replace("**admin_disabled**", '')

    cpout += edit_bar

    help = "help.html"
    help = readfile(templatedir + help)
    help_match = re.search(r'(<div id="help_admin".*?</div>)', help,
                           re.MULTILINE | re.DOTALL)
    help = help_match.group(1)
    cpout += help

    about = "about.html"
    about = readfile(templatedir + about)
    about = about.replace("**version**", _version.__version__)
    cpout += about

    if "wipe" in theform:
        if theform["wipe"] == "wipe":
            setup_db()

    if "create_project" in theform:
        new_project = theform["create_project"]
        if len(new_project) > 0:
            create_project(new_project)

    if "doclist" in theform:
        current_doc = theform["doclist"]
    else:
        current_doc = ""

    cpout += '''
	<div id="control">
	<form id="admin_form" name="id_form" action="admin.py" method="post" enctype="multipart/form-data">
		<input type="hidden" name="create_project" id="create_project" value=""/>
		<input type="hidden" name="sel_tab" id="sel_tab" value="project"/>
		<input type="hidden" name="delete" id="delete" value=""/>
		<input type="hidden" name="delete_user" id="delete_user" value=""/>
		<input type="hidden" name="export" id="export" value=""/>
		<input type="hidden" name="wipe" id="wipe" value=""/>
		<input type="hidden" name="switch_signals" id="switch_signals" value=""/>
		<input type="hidden" name="signals_file" id="signals_file" value=""/>
		<input type="hidden" name="switch_logging" id="switch_logging" value=""/>
		<input type="hidden" name="switch_span_buttons" id="switch_span_buttons" value=""/>
		<input type="hidden" name="switch_multinuc_buttons" id="switch_multinuc_buttons" value=""/>
		<input type="hidden" name="update_schema" id="update_schema" value=""/>
		<input type="hidden" name="imp_project" id="imp_project" value=""/>
		<input type="hidden" name="import_file_type" id="import_file_type" value=""/>
		<input type="hidden" name="do_tokenize" id="do_tokenize" value=""/>
		<input type="hidden" name="doclist" id="doclist" value="'''
    cpout += current_doc
    cpout += '''"/>
		<input type="hidden" name="userlist" id="userlist" value=""/>
		<input type="hidden" name="assign_doc" id="assign_doc" value=""/>
		<input type="hidden" name="assign_user" id="assign_user" value=""/>
		<input type="hidden" name="unassign_doc" id="unassign_doc" value=""/>
		<input type="hidden" name="unassign_user" id="unassign_user" value=""/>
		<input type="hidden" name="new_user_data" id="new_user_data" value=""/>
		<input type="hidden" name="edit_validation" id="edit_validation" value=""/>
		<input type="hidden" name="del_project" id="del_project" value=""/>
		<input type="hidden" name="guidelines_url" id="guidelines_url" value=""/>
		<input id="file" type="file" name="file" multiple="multiple"/>
	</form>
	<script src="./script/admin.js"></script>
	<script src="./script/jquery-1.11.3.min.js"></script>
	<script src="./script/jquery-ui.min.js"></script>
	'''

    cpout += '''
	<div class="tab_btn" id="project_btn" onclick="open_tab('project');">Projects</div><div id="project" class="tab">
	<h2>Manage Projects</h2>
	<p>Create a new project named: <input id="new_project"/></p>
	<button onclick="admin('create_project')">Create Project</button>
	'''
    #cpout += theform

    if "update_schema" in theform:
        if theform["update_schema"] == "update_schema":
            update_schema()

    if "del_project" in theform:
        projects_to_delete = theform["del_project"].split(";")
        if len(projects_to_delete) > 0:
            if isinstance(projects_to_delete, list):
                for project in projects_to_delete:
                    delete_project(project)
            else:
                delete_project(projects_to_delete)

    all_project_list = get_all_projects()

    url_message = ""
    if "guidelines_url" in theform:
        if "::" in theform["guidelines_url"]:
            project_list, guideline_url = theform["guidelines_url"].split("::")
            if len(project_list) > 0:
                schema = get_schema()
                if schema < 2:
                    update_schema()
                if isinstance(project_list, list):
                    for project in project_list:
                        set_guidelines_url(project, guideline_url)
                else:
                    set_guidelines_url(project_list, guideline_url)
                url_message = '<p class="warn">Added the URL ' + guideline_url + " to the selected projects</p>"

    cpout += '<p>Existing projects:</p>'
    if all_project_list:
        cpout += '<select class="doclist" id="project_select" size="5" multiple="multiple">\n'
        for project in all_project_list:
            cpout += '\t<option value="' + project[0] + '">' + project[
                0] + "</option>"
        cpout += '</select>\n'
    else:
        cpout += '<p class="warn">No projects found!</p>'

    cpout += '''<p>
		<p>Add guidelines URL to selected project:</p><p><input id="guidelines_url_input"/></p>
		<button onclick="admin('guidelines_url')">Add URL</button>
		''' + url_message

    cpout += '''

		<p>Delete selected projects:</p>

		<button onclick="admin('delete_project')">Delete Selected</button></p>
	'''

    # Handle validation settings
    validation_message = ""
    val_project = ""
    if "edit_validation" in theform:
        if "::" in theform["edit_validation"]:
            val_project, validations = theform["edit_validation"].split("::")
            schema = get_schema()
            if schema < 5:
                update_schema()
            set_project_validations(val_project, validations)
            validation_message = '<p class="warn">Updated validation settings for project ' + val_project

    cpout += '''<p>Change annotation warning settings for project:</p>'''

    if all_project_list:
        cpout += '''<select class="doclist" id="validate_project_select" onchange="toggle_validation_project();">\n'''
        if val_project == "":
            val_project = all_project_list[0][0]
        for project in all_project_list:
            if project[0] == val_project:
                sel_string = ' selected="selected"'
            else:
                sel_string = ""
            cpout += '\t<option value="' + project[
                0] + '"' + sel_string + '>' + project[0] + "</option>\n"
        cpout += '</select>\n'
        for project in all_project_list:
            vals = get_project_validations(project[0])
            cpout += '\t<input id="validations_' + project[
                0] + '" type="hidden" value="' + vals + '">'
    else:
        cpout += "<p>No projects found with permissions for user: "******"</p>"

    validations = get_project_validations(val_project)
    validation_list = validations.split(";")
    checked = ""
    if "validate_empty" in validation_list:
        checked = " checked"

    cpout += '''<br><br><label class="switch">
	  <input type="checkbox" id="check_empty_span" onclick="admin('toggle_validations');"''' + checked + '''>
	  <div class="slider round"></div>
		</label><div style="position: relative; top: -3px; left: 3px; display: inline-block">Warn on empty span
		<a class="tooltip" href="">
   <i class="fa fa-question-circle">&nbsp;</i>
   <span><img src="img/empty_span.png" height="100px">

    <i>Highlights spans with single span child</i>
   </span>
</a></div>
		'''
    checked = ""
    if "validate_flat" in validation_list:
        checked = " checked"
    cpout += '''<br><label class="switch">
	  <input type="checkbox" id="check_flat_rst" onclick="admin('toggle_validations');"''' + checked + '''>
	  <div class="slider round"></div>
		</label><div style="margin-top: 10px; position: relative; top: -3px; left: 3px; display: inline-block">Warn on multiple incoming flat RST relations
		<a class="tooltip" href="">
   <i class="fa fa-question-circle">&nbsp;</i>
   <span><img src="img/flat_rst.png" height="75px">

    <i>Highlights spans with multiple incoming satellites</i>
   </span>
</a></div>
'''
    checked = ""
    if "validate_mononuc" in validation_list:
        checked = " checked"
    cpout += '''<br><label class="switch">
		  <input type="checkbox" id="check_mononuc" onclick="admin('toggle_validations');"''' + checked + '''>
		  <div class="slider round"></div>
			</label><div style="margin-top: 10px; position: relative; top: -3px; left: 3px; display: inline-block">Warn on multinucs with single child
			<a class="tooltip" href="">
	   <i class="fa fa-question-circle">&nbsp;</i>
	   <span><img src="img/mononuc.png" height="75px">

	    <i>Highlights multinucs with a single child</i>
	   </span>
	</a></div>
		<script>
			selproj = document.getElementById("validate_project_select").value;
			validations = document.getElementById("validations_" + selproj).value;
			if (validations.indexOf("validate_flat")>0){
				document.getElementById("check_flat_rst").checked = true;
			}
			if (validations.indexOf("validate_empty")>0){
				document.getElementById("check_empty_span").checked = true;
			}
			if (validations.indexOf("validate_mononuc")>0){
				document.getElementById("check_mononuc").checked = true;
			}
		</script>'''
    cpout += validation_message

    cpout += '''
		</div>'''

    cpout += '''
	<div class="tab_btn" id="import_btn" onclick="open_tab('import');">Import</div><div id="import" class="tab">
	<h2>Import a Document</h2>
	<p>1. Upload .rs3 or plain text file(s): </p>
	<p>2. Choose file type: <select id="import_file_type_select" class="doclist"><option value="rs3">rs3</option><option value="plain">plain text (EDU per line)</option></select> </p>
	<p>3. Tokenize words automatically? <input type="checkbox" name="tokenize" id="tokenize"></p>
	<p>4. Import document(s) into this project:
	'''

    if all_project_list:
        cpout += '<select class="doclist" id="imp_project_select">\n'
        if isinstance(all_project_list, list):
            for project in all_project_list:
                cpout += '\t<option value="' + project[0] + '">' + project[
                    0] + "</option>"
        else:
            cpout += '\t<option value="' + all_project_list + '">' + all_project_list + "</option>"
        cpout += '</select>\n'
    else:
        cpout += "<p>No projects found with permissions for user: "******"</p>"
    cpout += '''
	</p>
	<p><button onclick="admin('upload')">Upload</button></p>

	'''

    fail = 0
    if "file" in theform and "imp_project" in theform:
        fileitem = theform['file']
        imp_project = theform["imp_project"]
        do_tokenize = theform["do_tokenize"] == "tokenize"
        if isinstance(fileitem, list):
            message = ""
            for filelist_item in fileitem:
                if filelist_item.filename and len(
                        imp_project
                ) > 0:  # Test if the file was uploaded and a project selection exists
                    #  strip leading path from file name to avoid directory traversal attacks
                    fn = os.path.basename(filelist_item.filename)
                    open(importdir + fn, 'wb').write(filelist_item.file.read())
                    message += 'The file "' + fn + '" was uploaded successfully<br/>'
                    if theform['import_file_type'] == "rs3":
                        fail = import_document(importdir + fn,
                                               imp_project,
                                               user,
                                               do_tokenize=do_tokenize)
                    elif theform['import_file_type'] == "plain":
                        if len(def_relfile) > 0:
                            rel_hash = read_relfile(def_relfile)
                        else:
                            rel_hash = {}
                        fail = import_plaintext(importdir + fn,
                                                imp_project,
                                                user,
                                                rel_hash,
                                                do_tokenize=do_tokenize)
                else:
                    message = 'No file was uploaded'
        else:
            if fileitem.filename and len(
                    imp_project
            ) > 0:  # Test if the file was uploaded and a project selection exists
                #  strip leading path from file name to avoid directory traversal attacks
                fn = os.path.basename(fileitem.filename)
                open(importdir + fn, 'wb').write(fileitem.file.read())
                message = 'The file "' + fn + '" was uploaded successfully'
                if theform['import_file_type'] == "rs3":
                    fail = import_document(importdir + fn,
                                           imp_project,
                                           user,
                                           do_tokenize=do_tokenize)
                elif theform['import_file_type'] == "plain":
                    if len(def_relfile) > 0:
                        rel_hash = read_relfile(def_relfile)
                    else:
                        rel_hash = {}
                    fail = import_plaintext(importdir + fn,
                                            imp_project,
                                            user,
                                            rel_hash,
                                            do_tokenize=do_tokenize)
            else:
                message = 'No file was uploaded'

        if isinstance(fail, basestring):
            message = fail
        cpout += """
		<p class="warn">%s</p>
		""" % (message, )

    cpout += '</div><div class="tab_btn" id="docs_btn" onclick="open_tab(' + "'" + "docs" + "'" + ');">Documents</div><div id="docs" class="tab">'
    cpout += "<h2>Current Documents</h2>"

    if "delete" in theform:  #execute delete documents before retrieving doclist
        doclist = theform["doclist"]
        if len(doclist) > 0 and theform["delete"] == "delete":
            docs_to_delete = doclist.split(";")

            if len(docs_to_delete) > 0:
                if isinstance(docs_to_delete, list):
                    for doc in docs_to_delete:
                        delete_document(doc.split("/")[1], doc.split("/")[0])
                else:
                    delete_document(
                        docs_to_delete.split("/")[1],
                        docs_to_delete.split("/")[0])
                cpout += '<p class="warn">Deletion complete</p>'

    cpout += '<p>List of documents in the database:</p>'
    docs = get_all_docs_by_project()
    if not docs:
        cpout += "<p>No documents found with permissions for user name: " + user + "</p>"
    else:
        cpout += '<select name="doclist_select" id="doclist_select" class="doclist" size="15" multiple="multiple">\n'
        project_group = ""
        for doc in docs:
            if project_group != doc[1]:
                if project_group != "":
                    cpout += '</optgroup>\n'
                project_group = doc[1]
                cpout += '<optgroup label="' + doc[1] + '">\n'
            cpout += '\t<option value="' + doc[1] + "/" + doc[0] + '">' + doc[
                0] + '</option>\n'

        cpout += '</optgroup>\n</select>\n'

    cpout += '''
	<p>Export selected document(s) to export folder as .rs3 file(s):</p>
	<button onclick="admin('export');">Export</button>
	<p>Delete selected document(s):</p>
	<button onclick="admin('delete_doc');">Delete</button>
	'''
    if "export" in theform:
        export_doc_list = theform["doclist"]
        if len(export_doc_list) > 0 and theform["export"] == "export":
            export_docs = export_doc_list.split(";")
            if isinstance(export_docs, list):
                for doc in export_docs:
                    export_document(
                        doc.split("/")[1],
                        doc.split("/")[0], exportdir)
            else:
                export_document(
                    export_docs.split("/")[1],
                    export_docs.split("/")[0], exportdir)
            cpout += '<p class="warn">Export complete</p>'

    # Handle user add and delete before showing user list
    if "delete_user" in theform:
        if len(theform["delete_user"]) > 0:
            users_to_delete = theform["userlist"]
            users = users_to_delete.split(";")
            if isinstance(users, list):
                for user in users:
                    try:
                        os.remove(userdir + user)
                        delete_docs_for_user(user)
                        user_del_message = '<p class="warn">Deleted users from selection</p>'
                    except OSError as e:
                        if e.errno == errno.ENOENT:
                            user_del_message = '<p class="warn">File to delete <i>' + user + '</i> not found!</p>'
                        else:
                            raise
            else:
                try:
                    os.remove(userdir + users_to_delete)
                    delete_docs_for_user(users_to_delete)
                    user_del_message = 'Deleted users from selection'
                except OSError as e:
                    if e.errno == errno.ENOENT:
                        user_del_message = '<p class="warn">File to delete <i>' + users_to_delete + '</i> not found!</p>'
                    else:
                        raise

    # Handle user document assignment
    if "assign_user" in theform:
        if len(theform["assign_user"]) > 0:
            users_to_assign = theform["assign_user"]
            docs_to_assign = theform["assign_doc"]
            users = users_to_assign.split(";") if ";" in users_to_assign else [
                users_to_assign
            ]
            docs = docs_to_assign.split(";") if ";" in docs_to_assign else [
                docs_to_assign
            ]
            for user in users:
                for doc in docs:
                    user = user.replace(".ini", "")
                    copy_doc_to_user(
                        doc.split("/")[1],
                        doc.split("/")[0], user)

    if "unassign_user" in theform:
        if len(theform["unassign_user"]) > 0:
            user_to_unassign = theform["unassign_user"]
            doc_to_unassign = theform["unassign_doc"]
            delete_doc_user_version(
                doc_to_unassign.split("/")[1],
                doc_to_unassign.split("/")[0], user_to_unassign)

    if "new_user_data" in theform:
        if len(theform["new_user_data"]) > 0:
            user_data = theform["new_user_data"].split("/")
            username = user_data[0]
            realname = user_data[1]
            email = user_data[2]
            RESERVEDNAMES = {
                'config': 1,
                'default': 1,
                'temp': 1,
                'emails': 1,
                'pending': 1,
                '_orig': 1
            }
            if username in RESERVEDNAMES:
                user_create_message = '<p class="warn">User name cannot be: "config", "default", "temp", "emails", or "pending"</p>'
            else:
                if len(realname) < 1:
                    user_create_message = '<p class="warn">The real name cannot be empty!</p>'
                else:
                    if not is_email(email):
                        user_create_message = '<p class="warn">Invalid e-mail address: <b>' + email + '</b></p>'
                    else:
                        password = user_data[3]
                        if len(password) < 5:
                            user_create_message = '<p class="warn">Password must be at least 5 characters long</p>'
                        else:
                            administrator = user_data[4]
                            if str(administrator) != "3" and str(
                                    administrator) != "0":
                                user_create_message = '<p class="warn">Invalid administrator setting value for new user</p>'
                            else:
                                createuser(userdir, realname, username, email,
                                           password, administrator)
                                user_create_message = '<p class="warn">Created the user ' + username + '</p>'

    if mode == "server":
        cpout += '</div><div class="tab_btn" id="users_btn" onclick="open_tab(' + "'" + "users" + "'" + ');">Users</div><div id="users" class="tab">'
    else:
        cpout += '''</div><div class="tab_btn disabled_tab" id="users_btn" onclick="alert('User management disabled in local mode');">Users</div><div id="users" class="tab">'''
    cpout += '''<h2>User Management</h2>
	<table id="doc_assign"><tr><td><p>Users:</p>
	<select id="userlist_select" multiple="multiple" size="10" class="doclist">
	'''

    userfiles = [f for f in listdir(userdir) if isfile(join(userdir, f))]
    for userfile in sorted(userfiles):
        if userfile != "config.ini" and userfile != "default.ini" and userfile != "admin.ini" and userfile.endswith(
                ".ini"):
            userfile = userfile.replace(".ini", "")
            cpout += '<option value="' + userfile + '.ini">' + userfile + '</option>'
    cpout += '''
	</select></td><td>
	<p>Documents to assign to:</p>'''
    docs = get_all_docs_by_project()
    if not docs:
        cpout += "<p class='warn'>No documents found with permissions for user name: " + user + "</p>"
    else:
        cpout += '<select name="doc_assign_select" id="doc_assign_select" class="doclist" size="10" multiple="multiple">\n'
        project_group = ""
        for doc in docs:
            if project_group != doc[1]:
                if project_group != "":
                    cpout += '</optgroup>\n'
                project_group = doc[1]
                cpout += '<optgroup label="' + doc[1] + '">\n'
            cpout += '\t<option value="' + doc[1] + "/" + doc[0] + '">' + doc[
                0] + '</option>\n'

        cpout += '</optgroup>\n</select>\n'
    cpout += '''
	</td></tr></table>
	<p>Delete selected user files: (annotations will not be deleted)</p>
	<button onclick="admin('delete_user')">Delete user(s)</button>
	'''
    if "delete_user" in theform:
        if len(theform["delete_user"]) > 0:
            cpout += user_del_message
    cpout += '''
	<p>Assign selected users to selected documents:</p>
	<button onclick="admin('assign_user')">Assign</button>
	<p>Delete assignments for user: (annotations will be deleted)</p>
	'''

    assigned_users = get_assigned_users()
    if len(assigned_users) > 0:
        cpout += '<select id="assigned_user_sel" name="assigned_user_sel" class="doclist" onchange="update_assignments()">'
        first_user = assigned_users[0][0]
        for user in assigned_users:
            assigned_docs = get_assignments(user[0])
            cpout += '<option value="'  # + user[0] +":"
            for doc in assigned_docs:
                cpout += doc[1] + "/" + doc[0] + ";"
            cpout += '">' + user[0] + '</option>'
        cpout += '</select>\n'
        assigned_docs = get_assignments(first_user)
        cpout += '<select id="assigned_doc_sel" name="assigned_doc_sel" class="doclist">'
        for doc in assigned_docs:
            cpout += '<option value="' + doc[1] + "/" + doc[0] + '">' + doc[
                1] + "/" + doc[0] + '</option>'
        cpout += '</select>'
        cpout += '''<p><button onclick="admin('unassign_user')">Delete assignment</button></p>'''
    else:
        cpout += '<p class="warn">No user assignments found</p>'

    cpout += '''<p>Create new user:</p>
	<table class="gray_tab">
	    <tr><td>User name:</td><td><input name="username" id="username"  type="text" value=""></td></tr>
	    <tr><td>Real name:</td><td><input name="realname" id="realname" type="text" value=""></td></tr>
	    <tr><td>Email address:</td><td><input name="email" id="email" type="text" value=""></td></tr>
	    <tr><td>Password:</td><td><input name="pass" id="pass" type="password">
	    <tr><td>Administrator:</td><td><input type="checkbox" id="chk_admin" name="chk_admin">&nbsp;&nbsp;&nbsp;&nbsp;<button onclick="admin('create_user')">Create user</button></td></tr>
	    </td></tr>
	</table>

	'''

    if "new_user_data" in theform:
        if len(theform["new_user_data"]) > 0:
            cpout += user_create_message

    ### database
    cpout += '</div><div class="tab_btn" id="database_btn" onclick="open_tab(' + "'" + "database" + "'" + ');">Database</div><div id="database" class="tab">'

    # signals
    cpout += '''<h2>Signals</h2>
	<p>Turn signal display and editing signals on/off.</p>'''

    try:
        signals_state = get_setting("signals")
    except IndexError:
        signals_state = "False"

    if "switch_signals" in theform:
        if theform["switch_signals"] == "switch_signals":

            if signals_state == "True":
                signals_state = "False"
            else:
                signals_state = "True"
            save_setting("signals", signals_state)

    if signals_state == "True":
        opposite_signals = "False"
    else:
        opposite_signals = "True"

    cpout += '''<button onclick="admin('switch_signals')">Turn ''' + (
        'on' if opposite_signals == "True" else 'off') + '''</button>'''

    if "signals_file" in theform and theform["signals_file"]:
        save_setting("signals_file", theform["signals_file"])

    cpout += '''<div>
	<br>
	<span>Signal types: </span>
	<select name="signals_file_select" id="signals_file_select" class="doclist"
	        onchange="admin('select_signals_file')">'''
    signals_files = [
        fname for fname in os.listdir('signals') if fname.endswith('.json')
    ]
    signals_file = get_setting("signals_file")
    for fname in signals_files:

        selected_string = (' selected="selected"'
                           if signals_file and signals_file == fname else '')
        cpout += '<option value="' + fname + '"' + selected_string + '>' + fname[:
                                                                                 -5] + '</option>'
    cpout += '''</select>
	</div>'''

    # logging
    cpout += '''<h2>Logging</h2>
	<p>Turn detailed action logging on/off.</p>'''

    try:
        logging_state = get_setting("logging")
    except IndexError:
        logging_state = "off"

    if "switch_logging" in theform:
        if theform["switch_logging"] == "switch_logging":

            if logging_state == "on":
                logging_state = "off"
            else:
                logging_state = "on"
            save_setting("logging", logging_state)

    if logging_state == "on":
        opposite_logging = "off"
    else:
        opposite_logging = "on"

    cpout += '''<button onclick="admin('switch_logging')">Turn ''' + opposite_logging + '''</button>'''

    # spans/multinucs
    cpout += '''<h2>Disable spans or multinucs</h2>
	<p>Turn on/off add span and multinuc buttons (for non-RST annotation).</p>'''

    try:
        span_state = get_setting("use_span_buttons")
        multinuc_state = get_setting("use_multinuc_buttons")
    except IndexError:
        span_state = "True"
        multinuc_state = "True"

    if "switch_span_buttons" in theform:
        if int(get_schema()) < 3:
            update_schema()
        if theform["switch_span_buttons"] == "switch_span_buttons":
            if span_state == "True":
                span_state = "False"
            else:
                span_state = "True"
            save_setting("use_span_buttons", span_state)
    if span_state == "True":
        opposite_span = "Disable"
    else:
        opposite_span = "Enable"
    if "switch_multinuc_buttons" in theform:
        if int(get_schema()) < 3:
            update_schema()
        if theform["switch_multinuc_buttons"] == "switch_multinuc_buttons":
            if multinuc_state == "True":
                multinuc_state = "False"
            else:
                multinuc_state = "True"
            save_setting("use_multinuc_buttons", multinuc_state)
    if multinuc_state == "True":
        opposite_multinuc = "Disable"
    else:
        opposite_multinuc = "Enable"

    cpout += '''<button onclick="admin('switch_span_buttons')">''' + opposite_span + ''' span buttons</button><br/><br/>'''
    cpout += '''<button onclick="admin('switch_multinuc_buttons')">''' + opposite_multinuc + ''' multinuc buttons</button>'''

    cpout += '''<h2>Update schema</h2>
	<p>Update the schema without losing data between major schema upgrades.</p>'''

    cpout += '''<button onclick="admin('update_schema')">Update</button>'''

    cpout += '''<h2>Initialize the Database</h2>
	<p>Wipe and restore database structure.</p>
	<p class="warn">Warning:</p> <p>this will delete all imported documents and all edits from the database.</p>
	<button onclick="admin('wipe')">Init DB</button>
	'''

    if "wipe" in theform:
        if theform["wipe"] == "wipe":
            cpout += '<p class="warn">Database has been re-initialized</p>'

    cpout += '''
	</div>
	<script>
		open_tab(document.getElementById("sel_tab").value);
	</script>'''

    if "sel_tab" in theform:
        sel_tab = theform['sel_tab']
        cpout += '<script>open_tab("' + sel_tab + '")</script>'

    cpout += '''
	</div>
	</body>
	</html>
	'''

    if mode != "server":
        cpout = cpout.replace(".py", "")
    return cpout
Ejemplo n.º 35
0
def structure_main(user, admin, mode, **kwargs):

	scriptpath = os.path.dirname(os.path.realpath(__file__)) + os.sep
	userdir = scriptpath + "users" + os.sep
	theform = kwargs

	UTF8Writer = codecs.getwriter('utf8')
	sys.stdout = UTF8Writer(sys.stdout)

	cgitb.enable()

	###GRAPHICAL PARAMETERS###
	top_spacing = 20
	layer_spacing = 60

	config = ConfigObj(userdir + 'config.ini')
	templatedir = scriptpath + config['controltemplates'].replace("/",os.sep)

	template = "main_header.html"
	header = readfile(templatedir+template)
	header = header.replace("**page_title**","Structure editor")
	header = header.replace("**user**",user)

	cpout = ""
	if mode == "server":
		cpout += "Content-Type: text/html\n\n\n"
		header = header.replace("**logout_control**",'(<a href="logout.py">log out</a>)')
	else:
		header = header.replace("**logout_control**",'')
	cpout += header

	if "current_doc" in theform:
		current_doc = theform["current_doc"]
		current_project = theform["current_project"]
		current_guidelines = get_guidelines_url(current_project)
	else:
		current_doc = ""
		current_project = ""
		current_guidelines = ""

	edit_bar = "edit_bar.html"
	edit_bar = readfile(templatedir+edit_bar)
	edit_bar = edit_bar.replace("**doc**",current_doc)
	edit_bar = edit_bar.replace("**project**",current_project)
	edit_bar = edit_bar.replace("**structure_disabled**",'disabled="disabled"')
	edit_bar = edit_bar.replace("**segment_disabled**",'')
	edit_bar = edit_bar.replace("**relations_disabled**",'')
	edit_bar = edit_bar.replace("**current_guidelines**",current_guidelines)
	if mode == "server":
		edit_bar = edit_bar.replace("**submit_target**",'structure.py')
	else:
		edit_bar = edit_bar.replace("**submit_target**",'structure')
	edit_bar = edit_bar.replace("**action_type**",'action')
	edit_bar = edit_bar.replace("**serve_mode**",mode)
	edit_bar = edit_bar.replace("**open_disabled**",'')
	edit_bar = edit_bar.replace('id="nav_edit" class="nav_button"','id="nav_edit" class="nav_button nav_button_inset"')

	if admin == "3":
		edit_bar = edit_bar.replace("**admin_disabled**",'')
	else:
		edit_bar = edit_bar.replace("**admin_disabled**",'disabled="disabled"')

	cpout += edit_bar

	help = "help.html"
	help = readfile(templatedir+help)
	help_match = re.search(r'(<div id="help_edit".*?</div>)',help,re.MULTILINE|re.DOTALL)
	help = help_match.group(1)
	cpout += help.decode("utf-8")

	about = "about.html"
	about = readfile(templatedir+about)
	about = about.replace("**version**", _version.__version__)
	cpout += about

	if current_guidelines != "":
		cpout += '<script>enable_guidelines();</script>'
	cpout += '<script src="./script/structure.js"></script>'

	if current_doc =="":
		cpout += '<p class="warn">No file found - please select a file to open</p>'
		return cpout

	cpout += '''<div class="canvas">'''
	cpout += '\t<p>Document: <b>'+current_doc+'</b> (project: <i>'+current_project+'</i>)</p>'
	cpout += '''<div id="inner_canvas">'''

	rels = get_rst_rels(current_doc, current_project)
	def_multirel = get_def_rel("multinuc",current_doc, current_project)
	def_rstrel = get_def_rel("rst",current_doc, current_project)
	multi_options =""
	rst_options =""
	rel_kinds = {}
	for rel in rels:
		if rel[1]=="multinuc":
			multi_options += "<option value='"+rel[0]+"'>"+rel[0].replace("_m","")+'</option>'
			rel_kinds[rel[0]] = "multinuc"
		else:
			rst_options += "<option value='"+rel[0]+"'>"+rel[0].replace("_r","")+'</option>'
			rel_kinds[rel[0]] = "rst"
	multi_options += "<option value='"+def_rstrel+"'>(satellite...)</option>"


	if "action" in theform:
		if len(theform["action"]) > 1:
			action_log = theform["action"]
			if len(action_log) > 0:
				actions = action_log.split(";")
				for action in actions:
					action_type = action.split(":")[0]
					action_params = action.split(":")[1]
					params = action_params.split(",")
					if action_type == "up":
						update_parent(params[0],params[1],current_doc,current_project,user)
					elif action_type == "sp":
						insert_parent(params[0],"span","span",current_doc,current_project,user)
					elif action_type == "mn":
						insert_parent(params[0],def_multirel,"multinuc",current_doc,current_project,user)
					elif action_type == "rl":
						update_rel(params[0],params[1],current_doc,current_project,user)
					else:
						cpout += '<script>alert("the action was: " + theform["action"]);</script>'

	if "logging" in theform:
		if len(theform["logging"]) > 1:
			if get_setting("logging") == "on":
				logging = theform["logging"]
				if len(logging) > 0:
					update_log(current_doc,current_project,user,logging,"structure",str(datetime.datetime.now()))

	if "reset" in theform or user == "demo":
		if len(theform["reset"]) > 1 or user == "demo":
			reset_rst_doc(current_doc,current_project,user)

	nodes={}
	rows = get_rst_doc(current_doc,current_project,user)
	for row in rows:
		if row[7] in rel_kinds:
			relkind = rel_kinds[row[7]]
		else:
			relkind = "span"
		if row[5] == "edu":
			nodes[row[0]] = NODE(row[0],row[1],row[2],row[3],row[4],row[5],row[6],row[7],relkind)
		else:
			nodes[row[0]] = NODE(row[0],0,0,row[3],row[4],row[5],row[6],row[7],relkind)

	for key in nodes:
		node = nodes[key]
		get_depth(node,node,nodes)

	for key in nodes:
		if nodes[key].kind == "edu":
			get_left_right(key, nodes,0,0,rel_kinds)

	anchors = {}
	pix_anchors = {}

	# Calculate anchor points for nodes
	# First get proportional position for anchor
	for key in sorted(nodes, key = lambda id: nodes[id].depth, reverse=True):
		node = nodes[key]
		if node.kind=="edu":
			anchors[node.id]= "0.5"
		if node.parent!="0":
			parent = nodes[node.parent]
			parent_wid = (parent.right- parent.left+1) * 100 - 4
			child_wid = (node.right- node.left+1) * 100 - 4
			if node.relname == "span":
				if node.id in anchors:
					anchors[parent.id] = str(((node.left - parent.left)*100)/parent_wid+float(anchors[node.id])*float(child_wid/parent_wid))
				else:
					anchors[parent.id] = str(((node.left - parent.left)*100)/parent_wid+(0.5*child_wid)/parent_wid)
			elif node.relkind=="multinuc" and parent.kind =="multinuc":
				# For multinucs, the anchor is in the middle between leftmost and rightmost of the multinuc children
				# (not including other rst children)
				lr = get_multinuc_children_lr(node.parent,current_doc,current_project,user)
				lr_wid = (lr[0] + lr[1]) /2
				lr_ids = get_multinuc_children_lr_ids(node.parent,lr[0],lr[1],current_doc,current_project,user)
				left_child = lr_ids[0]
				right_child = lr_ids[1]
				if left_child == right_child:
					anchors[parent.id] = "0.5"
				else:
					if left_child in anchors and right_child in anchors: #both leftmost and rightmost multinuc children have been found
						len_left = nodes[left_child].right-nodes[left_child].left+1
						len_right = nodes[right_child].right-nodes[right_child].left+1
						anchors[parent.id] = str(((float(anchors[left_child]) * len_left*100 + float(anchors[right_child]) * len_right * 100 + (nodes[right_child].left - parent.left) * 100)/2)/parent_wid)
					else:
						anchors[parent.id] = str((lr_wid - parent.left+1) / (parent.right - parent.left+1))

			else:
				if not parent.id in anchors:
					anchors[parent.id] = "0.5"

	# Place anchor element to center on proportional position relative to parent
	for key in nodes:
		node = nodes[key]
		pix_anchors[node.id] = str(int(3+node.left * 100 -100 - 39 + float(anchors[node.id])*((node.right- node.left+1) * 100 - 4)))

	# Check that span and multinuc buttons should be used (if the interface is not used for RST, they may be disabled)
	if int(get_schema()) > 2:
		use_span_buttons = True if get_setting("use_span_buttons") == "True" else False
		use_multinuc_buttons = True if get_setting("use_multinuc_buttons") == "True" else False
	else:
		use_span_buttons = True
		use_multinuc_buttons = True

	for key in nodes:
		node = nodes[key]
		if node.kind != "edu":
			g_wid = str(int((node.right- node.left+1) *100 -4 ))
			cpout += '<div id="lg'+ node.id +'" class="group" style="left: ' +str(int(node.left*100 - 100))+ '; width: ' + g_wid + '; top:'+ str(int(top_spacing + layer_spacing+node.depth*layer_spacing)) +'px; z-index:1"><div id="wsk'+node.id+'" class="whisker" style="width:'+g_wid+';"></div></div>'
			cpout += '<div id="g'+ node.id +'" class="num_cont" style="position: absolute; left:' + pix_anchors[node.id] +'px; top:'+ str(int(4+ top_spacing + layer_spacing+node.depth*layer_spacing))+'px; z-index:'+str(int(200-(node.right-node.left)))+'"><table class="btn_tb"><tr><td rowspan="2"><button id="unlink_'+ node.id+'"  title="unlink this node" class="minibtn" onclick="act('+"'up:"+node.id+",0'"+');">X</button></td><td rowspan="2"><span class="num_id">'+str(int(node.left))+"-"+str(int(node.right))+'</span></td>'
			if use_span_buttons:
				cpout += '<td><button id="aspan_'+ node.id+'" title="add span above" class="minibtn" onclick="act('+"'sp:"+node.id+"'"+');">T</button></td>'
			cpout += '</tr>'
			if use_multinuc_buttons:
				cpout += '<tr><td><button id="amulti_'+ node.id+'" title="add multinuc above" class="minibtn" onclick="act('+"'mn:"+node.id+"'"+');">' + "Λ".decode("utf-8") + '</button></td></tr>'
			cpout += '</table></div><br/>'

		elif node.kind=="edu":
			cpout += '<div id="edu'+str(node.id)+'" class="edu" title="'+str(node.id)+'" style="left:'+str(int(node.id)*100 - 100) +'; top:'+str(int(top_spacing +layer_spacing+node.depth*layer_spacing))+'; width: 96px">'
			cpout += '<div id="wsk'+node.id+'" class="whisker" style="width:96px;"></div><div class="edu_num_cont"><table class="btn_tb"><tr><td rowspan="2"><button id="unlink_'+ node.id+'" title="unlink this node" class="minibtn" onclick="act('+"'up:"+node.id+",0'"+');">X</button></td><td rowspan="2"><span class="num_id">&nbsp;'+str(int(node.left))+'&nbsp;</span></td>'
			if use_span_buttons:
				cpout += '<td><button id="aspan_'+ node.id+'" title="add span above" class="minibtn" onclick="act('+"'sp:"+node.id+"'"+');">T</button></td>'
			cpout += '</tr>'
			if use_multinuc_buttons:
				cpout += '<tr><td><button id="amulti_'+ node.id+'" title="add multinuc above" class="minibtn" onclick="act('+"'mn:"+node.id+"'"+');">' + "Λ".decode("utf-8") + '</button></td></tr>'
			cpout += '</table></div>'+node.text+'</div>'


	max_right = get_max_right(current_doc,current_project,user)

	# Serialize data in hidden input for JavaScript
	cpout += '<input id="data" name="data" type="hidden" '
	hidden_val=""
	for key in nodes:
		node = nodes[key]
		if node.relname:
			safe_relname = node.relname
		else:
			safe_relname = "none"
		if node.kind =="edu":
			hidden_val += "n" + node.id +",n" +node.parent+",e,"+ str(int(node.left)) + "," + safe_relname + "," + get_rel_type(node.relname,current_doc,current_project) + ";"
		elif node.kind =="span":
			hidden_val += "n" + node.id +",n" +node.parent+",s,0," + safe_relname + "," + get_rel_type(node.relname,current_doc,current_project) + ";"
		else:
			hidden_val += "n"+node.id +",n" +node.parent+",m,0," + safe_relname + "," + get_rel_type(node.relname,current_doc,current_project) + ";"
	hidden_val = hidden_val[0:len(hidden_val)-1]
	cpout += 'value="' + hidden_val + '"/>'


	cpout += '<input id="def_multi_rel" type="hidden" value="' + get_def_rel("multinuc",current_doc,current_project) +'"/>'
	cpout += '<input id="def_rst_rel" type="hidden" value="' + get_def_rel("rst",current_doc,current_project) +'"/>'
	cpout += '<input id="undo_log" type="hidden" value=""/>'
	cpout += '<input id="redo_log" type="hidden" value=""/>'
	cpout += '<input id="undo_state" type="hidden" value=""/>'
	cpout += '<input id="logging" type="hidden" value=""/>'
	cpout += '<input id="use_span_buttons" type="hidden" value="'+str(use_span_buttons)+'"/>'
	cpout += '<input id="use_multinuc_buttons" type="hidden" value="'+str(use_multinuc_buttons)+'"/>'

	cpout += '''	<script src="./script/jquery.jsPlumb-1.7.5-min.js"></script>

			<script>
			'''

	cpout += 'function select_my_rel(options,my_rel){'
	cpout += 'var multi_options = "' + multi_options +'";'
	cpout += 'var rst_options = "' + rst_options +'";'
	cpout += 'if (options =="multi"){options = multi_options;} else {options=rst_options;}'
	cpout += '		return options.replace("<option value='+"'" +'"' + '+my_rel+'+'"' +"'"+'","<option selected='+"'"+'selected'+"'"+' value='+"'" +'"'+ '+my_rel+'+'"' +"'"+'");'
	cpout += '			}\n'
	cpout += '''function make_relchooser(id,option_type,rel){
	    return $("<select class='rst_rel' id='sel"+id.replace("n","")+"' onchange='crel(" + id.replace("n","") + ",this.options[this.selectedIndex].value);'>" + select_my_rel(option_type,rel) + "</select>");
	}'''
	cpout += '''
			jsPlumb.importDefaults({
			PaintStyle : {
				lineWidth:2,
				strokeStyle: 'rgba(0,0,0,0.5)'
			},
			Endpoints : [ [ "Dot", { radius:1 } ], [ "Dot", { radius:1 } ] ],
			  EndpointStyles : [{ fillStyle:"#000000" }, { fillStyle:"#000000" }],
			  Anchor:"Top",
	            Connector : [ "Bezier", { curviness:50 } ]
			})
			 jsPlumb.ready(function() {

	jsPlumb.setContainer(document.getElementById("inner_canvas"));
	'''

	cpout += "jsPlumb.setSuspendDrawing(true);"


	for key in nodes:
		node = nodes[key]
		if node.kind == "edu":
			node_id_str = "edu" + node.id
		else:
			node_id_str = "g" + node.id
		cpout += 'jsPlumb.makeSource("'+node_id_str+'", {anchor: "Top", filter: ".num_id", allowLoopback:false});'
		cpout += 'jsPlumb.makeTarget("'+node_id_str+'", {anchor: "Top", filter: ".num_id", allowLoopback:false});'


	# Connect nodes
	for key in nodes:
		node = nodes[key]
		if node.parent!="0":
			parent = nodes[node.parent]
			if node.kind == "edu":
				node_id_str = "edu" + node.id
			else:
				node_id_str = "g" + node.id
			if parent.kind == "edu":
				parent_id_str = "edu" + parent.id
			else:
				parent_id_str = "g" + parent.id

			if node.relname == "span":
				cpout += 'jsPlumb.connect({source:"'+node_id_str+'",target:"'+parent_id_str+ '", connector:"Straight", anchors: ["Top","Bottom"]});'
			elif parent.kind == "multinuc" and node.relkind=="multinuc":
				cpout += 'jsPlumb.connect({source:"'+node_id_str+'",target:"'+parent_id_str+ '", connector:"Straight", anchors: ["Top","Bottom"], overlays: [ ["Custom", {create:function(component) {return make_relchooser("'+node.id+'","multi","'+node.relname+'");},location:0.2,id:"customOverlay"}]]});'
			else:
				cpout += 'jsPlumb.connect({source:"'+node_id_str+'",target:"'+parent_id_str+'", overlays: [ ["Arrow" , { width:12, length:12, location:0.95 }],["Custom", {create:function(component) {return make_relchooser("'+node.id+'","rst","'+node.relname+'");},location:0.1,id:"customOverlay"}]]});'


	cpout += '''

		jsPlumb.setSuspendDrawing(false,true);


		jsPlumb.bind("connection", function(info) {
		   source = info.sourceId.replace(/edu|g/,"")
		   target = info.targetId.replace(/edu|g/g,"")
		});

		jsPlumb.bind("beforeDrop", function(info) {
		    $(".minibtn").prop("disabled",true);

	'''

	cpout += '''
			var node_id = "n"+info.sourceId.replace(/edu|g|lg/,"");
			var new_parent_id = "n"+info.targetId.replace(/edu|g|lg/,"");

			nodes = parse_data();
			new_parent = nodes[new_parent_id];
			relname = nodes[node_id].relname;
			new_parent_kind = new_parent.kind;
			if (nodes[node_id].parent != "n0"){
				old_parent_kind = nodes[nodes[node_id].parent].kind;
			}
			else
			{
				old_parent_kind ="none";
			}

			if (info.sourceId != info.targetId){
				if (!(is_ancestor(new_parent_id,node_id))){
					jsPlumb.select({source:info.sourceId}).detach();
					if (new_parent_kind == "multinuc"){
						relname = get_multirel(new_parent_id,node_id,nodes);
						jsPlumb.connect({source:info.sourceId, target:info.targetId, connector:"Straight", anchors: ["Top","Bottom"], overlays: [ ["Custom", {create:function(component) {return make_relchooser(node_id,"multi",relname);},location:0.2,id:"customOverlay"}]]});
					}
					else{
						jsPlumb.connect({source:info.sourceId, target:info.targetId, overlays: [ ["Arrow" , { width:12, length:12, location:0.95 }],["Custom", {create:function(component) {return make_relchooser(node_id,"rst",relname);},location:0.1,id:"customOverlay"}]]});
					}
					new_rel = document.getElementById("sel"+ node_id.replace("n","")).value;
				    act('up:' + node_id.replace("n","") + ',' + new_parent_id.replace("n",""));
					update_rel(node_id,new_rel,nodes);
					recalculate_depth(parse_data());
				}
			}

		    $(".minibtn").prop("disabled",false);

		});

	});

			</script>
			</div>
			</div>
			<div id="anim_catch" class="anim_catch">&nbsp;</div>
	</body>
	</html>

	'''
	if mode != "server":
		cpout = cpout.replace(".py","")
	return cpout