diff options
author | Markus Krogh <markus@nordu.net> | 2017-06-02 13:19:30 +0200 |
---|---|---|
committer | Markus Krogh <markus@nordu.net> | 2017-06-02 13:19:30 +0200 |
commit | 934702f61f1cbdbf001ebb598c22c75efa247645 (patch) | |
tree | b0c6725a8c8a682b421aa35eea9662d7fff31bd6 | |
parent | 41afbaae97384968df6312cbe570305208b2216e (diff) |
Django 1.11 compatible and cleaned up
52 files changed, 1916 insertions, 10 deletions
diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d30e8af --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +*.db +*~ +*.pyc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ce88364 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Django stuff: +*.log +local_settings.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ @@ -1,18 +1,21 @@ -FROM python:2 +FROM python:2-slim ENV PYTHONUNBUFFERED 1 EXPOSE 8000 -RUN mkdir /sso -WORKDIR /sso +RUN mkdir /app && mkdir -p /opt/pwman +WORKDIR /app -ADD requirements.txt /sso/ -ADD start.sh /sso/ +ADD requirements.txt /app/ RUN apt-get update && \ - apt-get install -y build-essential libldap-dev libsasl2-dev && \ + echo "krb5-config krb5-config/default_realm string NORDU.NET" | debconf-set-selections && \ + apt-get install -y build-essential libldap-dev libsasl2-dev heimdal-clients libheimdal-kadm5-perl && \ pip install -r requirements.txt && \ apt-get remove --purge -y build-essential && \ apt-get autoremove -y && \ apt-get clean -CMD [ "./start.sh" ] +ADD src /app +ADD start.sh / + +ENTRYPOINT [ "/start.sh" ] diff --git a/README.md b/README.md new file mode 100644 index 0000000..2714a2a --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ + +## Installing + +``` +docker build --no-cache=true -t ndn-pwman . +``` + +Migrate db if necessary. + +``` +docker run --rm -ti ndn-pwman migrate +``` + +Then run a collect static: + +``` +docker run --rm --ti ndn-pwman -v /opt/pwman-statics:/opt/statics collectstatic +``` + +You need a useradmin keytab file, and the admin password for our ldap. + +## Running pwman + +``` + docker run --rm -ti --name pwman -e LDAP_PASSWORD="1234secrets" -v useradmin.keytab:/etc/useradmin.keytab ndn-pwman server +``` + + +## Debugging + +You can run the image with the argument shell. + +``` +docker run --rm -ti ndn-pwman shell +``` + +## Environement variables + +- LDAP_URL +- LDAP_USER +- LDAP_PASSWORD +- KERBEROS_SCRIPT +- DEBUG_MODE +- SECRET_KEY_FILE +- SECRET_KEY +- DATA_DIR - defaults to `/opt/pwman` diff --git a/nginx-test/pwman.dev.conf b/nginx-test/pwman.dev.conf new file mode 100644 index 0000000..12af816 --- /dev/null +++ b/nginx-test/pwman.dev.conf @@ -0,0 +1,29 @@ + +server { + listen 80; + server_name pwman.dev; + + + location /sso/ { + proxy_pass http://pwman:8000; + proxy_set_header SCRIPT_NAME /sso; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Port $server_port; + } + + location /sso/accounts/login-federated/ { + proxy_pass http://pwman:8000; + proxy_set_header SCRIPT_NAME /sso; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Port $server_port; + proxy_set_header X-Remote-User 'markus@nordu.net'; + proxy_set_header GIVENNAME 'Markus'; + proxy_set_header SN 'Krogh'; + proxy_set_header MAIL 'markus@nordu.net'; + proxy_set_header AFFILIATION 'employee@nordu.net'; + } +} diff --git a/requirements.txt b/requirements.txt index 402c64d..de0f057 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ uwsgi -Django==1.4 +Django==1.11 python-ldap pexpect diff --git a/src/apps/__init__.py b/src/apps/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/apps/__init__.py diff --git a/src/apps/changepw/__init__.py b/src/apps/changepw/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/apps/changepw/__init__.py diff --git a/src/apps/changepw/eduroam.mobileconfig b/src/apps/changepw/eduroam.mobileconfig new file mode 100644 index 0000000..952c924 --- /dev/null +++ b/src/apps/changepw/eduroam.mobileconfig @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>PayloadContent</key> + <array> + <dict> + <key>EAPClientConfiguration</key> + <dict> + <key>AcceptEAPTypes</key> + <array> + <integer>25</integer> + </array> + <key>EAPFASTProvisionPAC</key> + <false/> + <key>EAPFASTProvisionPACAnonymously</key> + <false/> + <key>EAPFASTUsePAC</key> + <false/> + <key>OuterIdentity</key> + <string>nordu-user@nordu.net</string> + <key>TLSAllowTrustExceptions</key> + <true/> + <key>TLSTrustedServerNames</key> + <array> + <string>eduroam1.nordu.net</string> + </array> + <key>UserName</key> + <string>eduroam-user</string> + </dict> + <key>EncryptionType</key> + <string>WPA</string> + <key>HIDDEN_NETWORK</key> + <false/> + <key>PayloadDescription</key> + <string>Configures wireless connectivity settings.</string> + <key>PayloadDisplayName</key> + <string>Wi-Fi (eduroam)</string> + <key>PayloadIdentifier</key> + <string>net.nordu.iphone.profile.wifi</string> + <key>PayloadOrganization</key> + <string>NORDUnet</string> + <key>PayloadType</key> + <string>com.apple.wifi.managed</string> + <key>PayloadUUID</key> + <string>63622959-0DCB-413A-9C3C-515833E38891</string> + <key>PayloadVersion</key> + <integer>1</integer> + <key>SSID_STR</key> + <string>eduroam</string> + </dict> + </array> + <key>PayloadDescription</key> + <string>Configuration for eduroam at NORDUnet</string> + <key>PayloadDisplayName</key> + <string>Eduroam Profile</string> + <key>PayloadIdentifier</key> + <string>net.nordu.iphone.profile</string> + <key>PayloadOrganization</key> + <string>NORDUnet</string> + <key>PayloadType</key> + <string>Configuration</string> + <key>PayloadUUID</key> + <string>4AD09534-1BC6-41CA-BC88-56149799781B</string> + <key>PayloadVersion</key> + <integer>1</integer> +</dict> +</plist> diff --git a/src/apps/changepw/models.py b/src/apps/changepw/models.py new file mode 100644 index 0000000..24e0bec --- /dev/null +++ b/src/apps/changepw/models.py @@ -0,0 +1,34 @@ +from django import forms +import re + +class ChangePasswordForm(forms.Form): + new_password = forms.CharField(widget=forms.PasswordInput) + new_password_again = forms.CharField(widget=forms.PasswordInput) + + def clean(self): + ''' + Validate the password submitted. + ''' + cleaned_data = self.cleaned_data + # The two submitted strings need to match. + new_password = cleaned_data.get('new_password') + new_password_again = cleaned_data.get('new_password_again') + if new_password != new_password_again: + raise forms.ValidationError('The typed passwords do not \ +match.') + # Check that the length is at least 10 characters. + if not len(new_password) >= 10: + raise forms.ValidationError('Your password needs to be at \ +least 10 characters long. Currently %d characters.' % len(new_password)) + # The password needs to contain at least one upper and one lower case + # letter and three numbers or special characters. + if not re.search('[a-z]', new_password) or not re.search( + '[A-Z]', new_password): + raise forms.ValidationError('You need at least one upper \ +case letter and one lower case letter in your password.') + numbers = re.findall('\d', new_password) + specials = re.findall('[,.\[\]!@#$%^&*?_\(\)-]', new_password) + if (len(numbers)+len(specials)) < 3: + raise forms.ValidationError('You need at least three numbers or \ +special characters i.e. 1234567890,.][!@#$%^&*?_()-') + return cleaned_data diff --git a/src/apps/changepw/nordunet_change_password.py b/src/apps/changepw/nordunet_change_password.py new file mode 100644 index 0000000..8149483 --- /dev/null +++ b/src/apps/changepw/nordunet_change_password.py @@ -0,0 +1,277 @@ +# -*- coding: utf-8 -*- +""" +Created on Mon May 9 14:20:31 2011 + +@author: lundberg +Used in django-changepw (http://git.nordu.net/?p=django-changepw.git;a=summary). +""" + +from subprocess import call, Popen, PIPE +import pexpect +import ldap +from django.conf import settings + +SUFFIXES = ['', '/ppp', '/net', '/vpn'] + + +def _normalize_whitespace(s): + """ + Removes leading and ending whitespace from a string. + """ + return ' '.join(s.split()) + + +def check_kerberos_password(username, password): + """ + Tries to kinit with the username and password. + Returns True and kdestroys the ticket if the kinit succeded and returns + False otherwise. + """ + child = pexpect.spawn('kinit %s' % username) + result = child.expect(['Password', 'not found']) + if result is 0: + child.sendline(password) + result = child.expect([ + 'kinit: Password incorrect', + 'kinit: krb5_get_init_creds: salt type 3 not supported', # Missmatch of kerberos version between client and server + 'unknown', + pexpect.EOF]) + if result == 3: + call('kdestroy') + return True + return False + + +def duplicated_kerberos_password(suffix, _username, password): + """ + Checks all suffixes except the one provided, if the password can unlock + any pricipal True is returned else False. + """ + kerberos_uid = _username.split('@') + kerberos_uid[1] = kerberos_uid[1].upper() + suffixes = list(SUFFIXES) + suffixes.remove(suffix) + for suff in suffixes: + username = '%s@' % suff + if check_kerberos_password(username.join(kerberos_uid), password): + return True + return False + + +def change_nordunet_sso_pw(user, new_password): + """ + Changes the Kerberos and LDAP password for the user. + """ + ret = _change_kerberos_pw('', user.username, new_password) + if not ret: + ret = set_nordunet_ldap_pw_sasl(user) + return ret + + +def set_nordunet_ldap_pw_sasl(user): + """ + Sets the users ldap password to a pointer to a Kerberos principal. + """ + username = user.username.split('@')[0] + ldap_dn = 'uid=%s,ou=People,dc=nordu,dc=net' % username + l = _connect_ldap(user=settings.LDAP_USER, password=settings.LDAP_PASSWORD) + if l: + try: + mod_attrs = [(ldap.MOD_REPLACE, 'userPassword', str('{SASL}%s@NORDU.NET' % username))] + l.modify_s(ldap_dn, mod_attrs) + except ldap.LDAPError, e: + l.unbind() + return e.message + l.unbind() + else: + return 'Invalid LDAP credentials in settings.' + return 0 + + +def change_nordunet_ppp_pw(user, new_password): + """ + Uses a third party script to change a Kerberos password. + Returns the return value from the third party script. + + User needs to be employee at NORDUnet to run this. User has + affiliation employee@nordu.net. + """ + if user.is_staff: + return _change_kerberos_pw('/ppp', user.username, new_password) + else: + return 'You need to be a NORDUnet employee or member to use this.' + + +def change_nordunet_net_pw(user, new_password): + """ + Uses a third party script to change a Kerberos password. + Returns the return value from the third party script. + + User needs to be employee at NORDUnet to run this. If user has + affiliation employee@nordu.net is_staff flag is True. + """ + if user.is_staff: + return _change_kerberos_pw('/net', user.username, new_password) + else: + return 'You need to be a NORDUnet employee to use this.' + + +def change_nordunet_vpn_pw(user, new_password): + """ + Uses a third party script to change a Kerberos password. + Returns the return value from the third party script. + + User needs to be employee at NORDUnet to run this. If user has + affiliation employee@nordu.net is_staff flag is True. + """ + if user.is_staff: + return _change_kerberos_pw('/vpn', user.username, new_password) + else: + return 'You need to be a NORDUnet employee to use this.' + + +def _change_kerberos_pw(suffix, username, new_password): + kerberos_uid = username.split('@') + kerberos_uid[1] = kerberos_uid[1].upper() + if not duplicated_kerberos_password(suffix, username, new_password): + kerberos_uid = '%s%s@%s' % (kerberos_uid[0], suffix, kerberos_uid[1]) + p = Popen([settings.KERBEROS_SCRIPT], stdin=PIPE) + p.communicate('%s %s' % (kerberos_uid, new_password)) + return p.wait() + return 'You can\'t set the same password as your %s password.' % _pretty_suffixes(without=suffix) + + +def _pretty_suffixes(without=None): + if without is None: + suffixes = [s for s in SUFFIXES if s is not without] + else: + suffixes = list(SUFFIXES) + if '' in suffixes: + suffixes.remove('') + suffixes.append('SSO') + return ', '.join([s.upper().replace('/', '') for s in suffixes]) + + +def _validate_ssh_key(s): + """ + Tries to validate a string against the public ssh key format as in + RFC4253 and RFC4716. + + Checks that the string is in three parts separated by whitespace and that + the first part is in public_key_formats and the second part is a base64 + encoded string. + + Returns True if the string validates. + """ + import base64 + public_key_formats = ['ssh-dss', 'ssh-rsa', 'pgp-sign-rsa', 'pgp-sign-dss', 'ssh-ed25519'] + three_parts = s.split() + if three_parts[0] in public_key_formats and len(three_parts) in [2,3]: + try: + base64.b64decode(three_parts[1]) + except TypeError: + return False + else: + return False + return True + + +def _connect_ldap(server=None, user=None, password=None): + """ + Connects to an ldap server and binds with supplied user and password. + """ + _server = server or settings.LDAP_URL + l = ldap.initialize(_server) + if not _server.startswith("ldaps"): + l.start_tls_s() + try: + if user is None: + l.simple_bind_s() + else: + l.bind_s(user, password) + except ldap.INVALID_CREDENTIALS: + return False + return l + + +def set_public_ssh_key(user, ssh_keys): + """ + Sets the provided string(s) as the sshPublicKey attribute for the user. + User need to have affiliation employee@nordu.net to use this function. + """ + if user.is_staff: + valid_keys = [] + for ssh_key in ssh_keys.split('\n'): + ssh_key = _normalize_whitespace(ssh_key) + if ssh_key: + if _validate_ssh_key(ssh_key): + valid_keys.append(ssh_key) + else: + return '%s is not a valid SSH key.' % ssh_key + if valid_keys: + ldap_dn = user.username.split('@') + ldap_dn = 'uid=%s,ou=People,dc=nordu,dc=net' % ldap_dn[0] + l = _connect_ldap(user=settings.LDAP_USER, password=settings.LDAP_PASSWORD) + if l: + try: + # Ensure that objectClass ldapPublicKey is added to the user + mod_attrs = [(ldap.MOD_ADD, 'objectClass', 'ldapPublicKey')] + l.modify_s(ldap_dn, mod_attrs) + except ldap.TYPE_OR_VALUE_EXISTS: + pass + try: + # Add the new ssh keys + for key in valid_keys: + mod_attrs = [(ldap.MOD_ADD, 'sshPublicKey', str(key))] + l.modify_s(ldap_dn, mod_attrs) + except ldap.LDAPError, e: + l.unbind() + return e.message + l.unbind() + else: + return 'Invalid LDAP credentials in settings.' + else: + return 'You need to be a NORDUnet employee to use this.' + return 0 + + +def get_public_ssh_keys(user): + l = _connect_ldap() + if l: + uid = user.username.split('@')[0] + dn = "uid=%s,ou=People,dc=nordu,dc=net" % uid + try: + res = l.search_s(dn, ldap.SCOPE_SUBTREE, "(objectClass=person)")[0][1] + return res.get('sshPublicKey') + except (ldap.LDAPError, TypeError): + pass + return None + + +def del_public_ssh_key(user, ssh_key): + """ + Sets the provided string(s) as the sshPublicKey attribute for the user. + User need to have affiliation employee@nordu.net to use this function. + """ + if user.is_staff: + ldap_dn = user.username.split('@') + ldap_dn = 'uid=%s,ou=People,dc=nordu,dc=net' % ldap_dn[0] + l = _connect_ldap(user=settings.LDAP_USER, + password=settings.LDAP_PASSWORD) + if l: + try: + # Remove all previous ssh keys + try: + mod_attrs = [(ldap.MOD_DELETE, 'sshPublicKey', ssh_key)] + l.modify_s(ldap_dn, mod_attrs) + except ldap.NO_SUCH_ATTRIBUTE: + pass + except ldap.LDAPError, e: + l.unbind() + return e.message + l.unbind() + else: + return 'Invalid LDAP credentials in settings.' + else: + return 'You need to be a NORDUnet employee to use this.' + return 0 diff --git a/src/apps/changepw/templates/changepw/change_other.html b/src/apps/changepw/templates/changepw/change_other.html new file mode 100644 index 0000000..0979e84 --- /dev/null +++ b/src/apps/changepw/templates/changepw/change_other.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} +{% block js %} +{% endblock %} +{% block title %}Update public SSH keys{% endblock %} +{% block content %} +<h2>Update your public SSH keys</h2> +{% if return_value == None %} + <form action="{% url changeother %}" method="post" autocomplete="off">{% csrf_token %} + <p>When pasting multiple ssh public keys remember to use new line or a blank line between keys.</p> + <table> + <tr> + <td class="formlabel">Paste your SSH public keys:</td> + </tr> + <tr> + <td class="formfield"> + <textarea name="ssh_key" cols="50" rows="10"></textarea> + </td> + </tr> + <tr> + <td class="formbutton"><input type="submit" value="Submit" /></td> + </tr> + </table> + </form> +{% else %} + {% if return_value == 0 %} + <p>Your public SSH keys was updated successfully.</p> + {% else %} + <p>Something went wrong. Please contact an administrator.</p> + <p>Return code: {{ return_value }}</p> + {% endif %} +{% endif %} +<p> + <a href="{% url index %}">Back</a><br /> + <a href="{% url logout %}">Log out</a> +</p> +{% endblock %} + diff --git a/src/apps/changepw/templates/changepw/change_password.html b/src/apps/changepw/templates/changepw/change_password.html new file mode 100644 index 0000000..5017b4c --- /dev/null +++ b/src/apps/changepw/templates/changepw/change_password.html @@ -0,0 +1,54 @@ +{% extends "base.html" %} +{% load static %} +{% block js %} + <script type="text/javascript" src="{% static 'js/jquery/jquery-1.4.4.min.js' %}"></script> + <script type="text/javascript" src="{% static 'js/jquery/password_strength.js' %}"></script> +{% endblock %} +{% block title %}Change {{ pwtype }} password{% endblock %} +{% block content %} +<h2>Change {{ pwtype }} password</h2> +{% if form %} +<p>When thinking of a new password you need to remember to use:</p> +<ul> + <li>no fewer than ten characters</li> + <li>at least one upper case and one lower case letter</li> + <li>three or more numbers or special characters</li> +</ul> + + <p class="error"> + {{ form.non_field_errors }} + </p> + <form action="{% url 'changepw' pwtype %}" method="post" autocomplete="off">{% csrf_token %} + <table> + <tr> + <th class="formlabel">Username:</th><td>{{ username }}{% if pwtype == "ppp" %}/ppp{% endif %}</td> + </tr> + {% for field in form %} + <tr> + <td class="fielderrors">{{ field.errors }}</td> + </tr> + <tr> + <th class="formlabel">{{ field.label_tag }}:</th><td class="formfield">{{ field }}</td><td><span class="password_strength"></span></td> + </tr> + {% endfor %} + </table> + <input type="submit" value="Submit" /> + </form> + <script type="text/javascript"> + $('form').attr('autocomplete', 'off'); + $('#id_new_password').password_strength(); + $('#id_new_password_again').password_strength(); + </script> +{% else %} + {% if return_value == 0 %} + <p>Your {{ pwtype }} password was changed successfully.</p> + {% else %} + <p>Something went wrong. Please contact an administrator.</p> + <p>Return code: {{ return_value }}</p> + {% endif %} +{% endif %} +<p> + <a href="{% url 'index' %}">Back</a><br /> + <a href="{% url 'logout' %}">Log out</a> +</p> +{% endblock %} diff --git a/src/apps/changepw/templates/changepw/change_public_ssh_key.html b/src/apps/changepw/templates/changepw/change_public_ssh_key.html new file mode 100644 index 0000000..0ad6533 --- /dev/null +++ b/src/apps/changepw/templates/changepw/change_public_ssh_key.html @@ -0,0 +1,45 @@ +{% extends "base.html" %} +{% block js %} +{% endblock %} +{% block title %}Update public SSH keys{% endblock %} +{% block content %} + +{% if return_value == 0 or return_value == None %} + {% if return_value == 0 %} + <p>Your public SSH keys where updated successfully.</p> + {% endif %} + + <h2>Your existing public SSH keys</h2> + <table border="1px"> + {% for key in ssh_keys %} + <tr> + <td><div style="width:500px;word-wrap:break-word;">{{ key }}</div></td> + <td><a href="{% url 'deletepublicsshkey' key_number=forloop.counter0 %}">Delete</a></td> + </tr> + {% endfor %} + </table> + <h2>Update your public SSH keys</h2> + <form action="{% url 'changepublicsshkeys' %}" method="post" autocomplete="off">{% csrf_token %} + <table> + <tr> + <td class="formlabel">Paste your SSH public keys (one key per line):</td> + </tr> + <tr> + <td class="formfield"> + <textarea name="ssh_key" cols="70" rows="10"></textarea> + </td> + </tr> + <tr> + <td class="formbutton"><input type="submit" value="Submit" /></td> + </tr> + </table> + </form> +{% else %} + <p>Something went wrong. Please contact an administrator.</p> + <p>Return code: {{ return_value }}</p> +{% endif %} +<p> + <a href="{% url 'index' %}">Back</a><br /> + <a href="{% url 'logout' %}">Log out</a> +</p> +{% endblock %} diff --git a/src/apps/changepw/templates/changepw/index.html b/src/apps/changepw/templates/changepw/index.html new file mode 100644 index 0000000..12df371 --- /dev/null +++ b/src/apps/changepw/templates/changepw/index.html @@ -0,0 +1,41 @@ +{% extends "base.html" %} +{% block js %} +{% endblock %} +{% block title %}SSO Password Manager{% endblock %} +{% block content %} +<h2>SSO Password Manager</h2> +<p> + Hello {{ full_name|capfirst }},<br /> + Welcome to the single sign on password manager site. +</p> + +<table> + <tr> + <th>Your usernames</th><th></th> + </tr> + <tr> + <td>SSO username:</td><td>{{ username }}</td> + </tr> + <tr> + <td><!-- VPN and -->eduroam username:</td><td>{{ username }}/ppp</td> + </tr> +</table> + +<p> +Available actions:<br /> +<a href="{% url 'changepw' "sso" %}">Change single sign on (SSO) password</a><br /> +{% if user.is_staff %} + <a href="{% url 'changepw' "net" %}">Change TACACS password</a><br /> +{% endif %} +{% if user.is_active or user.is_staff %} + <a href="{% url 'changepw' "ppp" %}">Change <!-- VPN and -->eduroam password</a><br /> +{% endif %} +{% if user.is_staff %} + <a href="{% url 'changepublicsshkeys' %}">Update your public SSH keys</a><br /> + <a href="{% url 'ideviceconf' %}" rel="external">Configure eduroam on your iDevice</a> +{% endif %} +</p> + +<p><a href="{% url 'logout' %}">Log out</a></p> +{% endblock %} + diff --git a/src/apps/changepw/templates/changepw/reset_password.html b/src/apps/changepw/templates/changepw/reset_password.html new file mode 100644 index 0000000..c56b920 --- /dev/null +++ b/src/apps/changepw/templates/changepw/reset_password.html @@ -0,0 +1,44 @@ +{% extends "base.html" %} +{% block js %} +{% endblock %} +{% block title %}Reset <!--VPN and -->eduroam password{% endblock %} +{% block content %} +<h2>Reset <!--VPN and -->eduroam password</h2> +{% if not return_value %} + <table> + <tr> + <th>Username:</th><td>{{ username }}/ppp</td> + </tr> + {% if new_password %} + <tr> + <th>Password:</th><td>{{ new_password }}</td> + </tr> + {% else %} + <tr> + <th>Password:</th> + <td> + <form action="{% url resetpw %}" method="post"> + {% csrf_token %} + <input type="submit" value="Reset" /> + </form> + </td> + </tr> + {% endif %} + </table> + <p> +<!-- + <a href="https://portal.nordu.net/display/nordunet/VPN+Access" target="_blank">Guide to VPN setup</a><br /> +--> + <a href="https://portal.nordu.net/display/nordunet/Wireless+roaming+via+eduroam" target="_blank">Guide to eduroam setup</a> + </p> +{% else %} + <p>Something went wrong. Please contact an administrator.</p> + <p>Return code: {{ return_value }}</p> +{% endif %} + +<p> + <a href="{% url index %}">Back</a><br /> + <a href="{% url logout %}">Log out</a> +</p> +{% endblock %} + diff --git a/src/apps/changepw/tests.py b/src/apps/changepw/tests.py new file mode 100644 index 0000000..2247054 --- /dev/null +++ b/src/apps/changepw/tests.py @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff --git a/src/apps/changepw/urls.py b/src/apps/changepw/urls.py new file mode 100644 index 0000000..8983950 --- /dev/null +++ b/src/apps/changepw/urls.py @@ -0,0 +1,13 @@ +# This also imports the include function +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url(r'^$', views.index, name='index'), + url(r'^changepw/(?P<pwtype>[-\w]+)$', views.change_password, name='changepw'), + url(r'^changeother$', views.change_other, name='changeother'), + url(r'^ideviceconf$', views.ideviceconf, name='ideviceconf'), + url(r'^changepublicsshkeys$', views.change_public_ssh_keys, name='changepublicsshkeys'), + url(r'^changepublicsshkeys/deletekey/(?P<key_number>\d+)$', views.delete_public_ssh_key, name='deletepublicsshkey'), +] diff --git a/src/apps/changepw/views.py b/src/apps/changepw/views.py new file mode 100644 index 0000000..c3fb090 --- /dev/null +++ b/src/apps/changepw/views.py @@ -0,0 +1,183 @@ +from django.contrib.auth.decorators import login_required +from apps.changepw.models import ChangePasswordForm +from django.http import HttpResponse +from django.shortcuts import render +import random +import nordunet_change_password as pw + + +def _change_password(pwtype, user, new_password): + ''' + Use this to call your change password function. + ''' + if pwtype == 'sso': + ret = pw.change_nordunet_sso_pw(user, new_password) + elif pwtype == 'ppp': + ret = pw.change_nordunet_ppp_pw(user, new_password) + elif pwtype == 'net': + ret = pw.change_nordunet_net_pw(user, new_password) + elif pwtype == 'vpn': + ret = pw.change_nordunet_vpn_pw(user, new_password) + else: + ret = 'Could not change that password type.' + return ret + + +def _change_other(request, *args): + ''' + Use this to call your change function. + ''' + user = request.user + ssh_key = request.POST.get('ssh_key', None) + if ssh_key: + ret = pw.set_public_ssh_key(user, ssh_key) + else: + return 1 + return ret + + +def _get_username(request): + ''' + Returns the actual username from the Shibboleth uid. + request.user.username == username@domain.com + ''' + return request.user.username.split('@')[0] + + +def _generate_password(n, z=3): + ''' + Returns a psudo random string of lenght n in accordance to the NORDUnet + security standard. z is the number of non-letters to include. + ''' + letters = 'abcdefghijklmnopqrstuvwxyz' + others = '1234567890!#%&?+*-_.<>' + pw = [] + for i in range(0, n//2): + pw.append(random.choice(letters)) + pw.append(random.choice(letters.upper())) + random.shuffle(pw) + pw = pw[:n] + for i in random.sample(range(0, n-1), z): + pw[i] = random.choice(others) + return ''.join(pw) + + +@login_required() +def index(request): + ''' + Greets the user and presents the choices available. + ''' + username = _get_username(request) + try: + full_name = request.user.get_full_name() + except AttributeError: + full_name = username + return render(request, + 'changepw/index.html', + {'full_name': full_name, 'username': username}) + + +@login_required() +def change_password(request, pwtype): + ''' + If the user is authenticated and the form is valid the password + changing script will be run with the username and new password. + The function that changes the password has to be provided as func. + ''' + username = _get_username(request) + form = ChangePasswordForm(request.POST or None) + return_value = -1 + if request.method == 'POST': + if form.is_valid(): + new_password = form.cleaned_data['new_password'] + return_value = _change_password(pwtype, request.user, new_password) + form = None + return render(request, + 'changepw/change_password.html', + {'form': form, + 'username': username, + 'pwtype': pwtype, + 'return_value': return_value}) + + +@login_required() +def change_other(request, *args): + ''' + Just passes along the request so that something can be done for that user. + ''' + username = _get_username(request) + return_value = None + if request.method == 'POST': + return_value = _change_other(request, *args) + return render(request, + 'changepw/change_other.html', + {'username': username, 'return_value': return_value}) + + +@login_required() +def change_public_ssh_keys(request): + """ + Lets the user remove or add public SSH keys. + """ + if request.POST: + ssh_key = request.POST.get('ssh_key', None) + if ssh_key: + ret = pw.set_public_ssh_key(request.user, ssh_key) + else: + ret = 'No SSH key to add.' + ssh_keys = pw.get_public_ssh_keys(request.user) + return render(request, + 'changepw/change_public_ssh_key.html', + {'username': request.user.username, + 'ssh_keys': ssh_keys, + 'return_value': ret}) + else: + ssh_keys = pw.get_public_ssh_keys(request.user) + return render(request, + 'changepw/change_public_ssh_key.html', + {'username': request.user.username, + 'ssh_keys': ssh_keys, + 'return_value': None}) + + +@login_required() +def delete_public_ssh_key(request, key_number): + """ + Delete a public SSH key. + """ + ssh_keys = pw.get_public_ssh_keys(request.user) + ret = pw.del_public_ssh_key(request.user, ssh_keys[int(key_number)]) + ssh_keys = pw.get_public_ssh_keys(request.user) + return render(request, + 'changepw/change_public_ssh_key.html', + { + 'username': request.user.username, + 'ssh_keys': ssh_keys, + 'return_value': ret}) + +def _create_ieduroam_conf(user): + """ + Creates an xml config (http://www.apple.com/DTDs/PropertyList-1.0.dtd) for + iPhone, iPod Touch or Ipad that can be set by surfing to the URL. + + Should ultimately returned with + HttpResponse(conf, mimetype='application/x-apple-aspen-config') + """ + try: + f = open('/var/lib/django/sso/apps/changepw/eduroam.mobileconfig') + except IOError: + return 'Could not open boilerplate configuration.' + uid = user.username.split('@')[0] + s = ''.join(f.readlines()) + s = s.replace('nordu-user', '%s-pwman' % uid) + conf = s.replace('eduroam-user', '%s/ppp' % uid) + return conf + + +def ideviceconf(request): + """ + HACK + """ + user = request.user + conf = _create_ieduroam_conf(user) + return HttpResponse(conf, content_type='application/x-apple-aspen-config') diff --git a/src/apps/fedlogin/__init__.py b/src/apps/fedlogin/__init__.py new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/src/apps/fedlogin/__init__.py diff --git a/src/apps/fedlogin/middleware.py b/src/apps/fedlogin/middleware.py new file mode 100644 index 0000000..00f5ba4 --- /dev/null +++ b/src/apps/fedlogin/middleware.py @@ -0,0 +1,6 @@ +#MK: 2017-04-27 hack to make it work double proxied... +from django.contrib.auth.middleware import PersistentRemoteUserMiddleware + +class CustomHeaderMiddleware(PersistentRemoteUserMiddleware): + header = 'HTTP_X_REMOTE_USER' +#END MK hack diff --git a/src/apps/fedlogin/models.py b/src/apps/fedlogin/models.py new file mode 100755 index 0000000..137941f --- /dev/null +++ b/src/apps/fedlogin/models.py @@ -0,0 +1 @@ +from django.db import models diff --git a/src/apps/fedlogin/tests.py b/src/apps/fedlogin/tests.py new file mode 100755 index 0000000..2247054 --- /dev/null +++ b/src/apps/fedlogin/tests.py @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff --git a/src/apps/fedlogin/views.py b/src/apps/fedlogin/views.py new file mode 100755 index 0000000..f122ccd --- /dev/null +++ b/src/apps/fedlogin/views.py @@ -0,0 +1,40 @@ +from django.contrib.auth import logout +from django.http import HttpResponseRedirect +from django.conf import settings +from django.core.urlresolvers import reverse +from django.contrib.auth.views import login + + +def fedlogin(request): + user = request.user + + if user.is_authenticated(): + + first_name = request.META.get('HTTP_GIVENNAME') + last_name = request.META.get('HTTP_SN') + email = request.META.get('HTTP_MAIL') + affiliations = request.META.get('HTTP_AFFILIATION', '').split(';') + + if first_name: + user.first_name = first_name + if last_name: + user.last_name = last_name + if email: + user.email = email + user.is_staff = 'employee@nordu.net' in affiliations + user.is_active = 'employee@nordu.net' in affiliations or 'member@nordu.net' in affiliations + if user.password == "": + user.password = "(not used for federated logins)" + user.save() + + _next = request.GET.get('next') + if _next: + return HttpResponseRedirect(_next) + else: + return HttpResponseRedirect(reverse(login)) + + +def fedlogout(request): + logout(request) + url = getattr(settings, 'FEDERATE_LOGOUT_URL', '/Shibboleth.sso/Logout') + return HttpResponseRedirect(url) diff --git a/src/database.db b/src/database.db Binary files differnew file mode 100644 index 0000000..4c4a210 --- /dev/null +++ b/src/database.db diff --git a/src/manage.py b/src/manage.py new file mode 100644 index 0000000..4015a97 --- /dev/null +++ b/src/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pwman.settings") + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise + execute_from_command_line(sys.argv) diff --git a/src/pwman/__init__.py b/src/pwman/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/pwman/__init__.py diff --git a/src/pwman/settings.py b/src/pwman/settings.py new file mode 100644 index 0000000..cf7bb69 --- /dev/null +++ b/src/pwman/settings.py @@ -0,0 +1,137 @@ +from os.path import abspath, dirname, join, normpath, isfile +from os import environ +# Django settings for sso project. + +DEBUG = environ.get('DEBUG_MODE', False) + +BASE_DIR = dirname(dirname(abspath(__file__))) +DATA_DIR = environ.get('DATA_DIR', '/opt/pwman') + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ + + +ALLOWED_HOSTS = ['crowd.nordu.net', 'pwman.nordu.net', 'localhost'] + +INSTALLED_APPS = [ + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + # Uncomment the next line to enable the admin: + # 'django.contrib.admin', + 'apps.changepw', + 'apps.fedlogin', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + #'django.contrib.auth.middleware.RemoteUserMiddleware', + 'django.contrib.auth.middleware.PersistentRemoteUserMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'apps.fedlogin.middleware.CustomHeaderMiddleware', + +] + +AUTHENTICATION_BACKENDS = ( + 'django.contrib.auth.backends.RemoteUserBackend', +) + +ROOT_URLCONF = 'pwman.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + normpath(join(BASE_DIR, 'templates')), + ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + + +WSGI_APPLICATION = 'pwman.wsgi.application' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': join(DATA_DIR, 'database.db'), + } +} + +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# On Unix systems, a value of None will cause Django to use the same +# timezone as the operating system. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'Europe/Stockholm' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale +USE_L10N = True + +STATIC_URL = '/sso/static/' + +STATICFILES_DIRS = [ + join(BASE_DIR, "static"), +] + +STATIC_ROOT = join(DATA_DIR, "static") + +LOGIN_URL = '/sso/accounts/login-federated/' + +# secrets +LDAP_USER = environ.get('LDAP_USER', 'cn=admin,dc=nordu,dc=net') +LDAP_PASSWORD = environ.get('LDAP_PASSWORD', '') +LDAP_URL = environ.get('LDAP_URL', 'ldaps://ldap.nordu.net') +KERBEROS_SCRIPT = environ.get('KERBEROS_SCRIPT', join(BASE_DIR, 'scripts/create-kdc-principal.pl')) + +# SECURITY WARNING: keep the secret key used in production secret! +_path = environ.get('SECRET_KEY_FILE', join(DATA_DIR, 'secret.txt')) +if isfile(_path): + with open(_path) as f: + SECRET_KEY = f.read().strip() +else: + SECRET_KEY = environ.get('SECRET_KEY') diff --git a/src/pwman/urls.py b/src/pwman/urls.py new file mode 100644 index 0000000..b98b75f --- /dev/null +++ b/src/pwman/urls.py @@ -0,0 +1,36 @@ +"""pwman URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.11/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url, include +from django.contrib.auth.views import login +from apps.fedlogin.views import fedlogout, fedlogin + +# Uncomment the next two lines to enable the admin: +# from django.contrib import admin +# admin.autodiscover() + +urlpatterns = [ + + #Fedlogin + url(r'^sso/accounts/login/$', login, {'template_name': 'login.html'}, 'login'), + url(r'^sso/accounts/logout/$', fedlogout, name='logout'), + url(r'^sso/accounts/login-federated/$', fedlogin, name='loginfed'), + url(r'^sso/pwman', include('apps.changepw.urls')), + # Uncomment the admin/doc line below to enable admin documentation: + # (r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + # (r'^admin/', include(admin.site.urls)), +] diff --git a/src/pwman/wsgi.py b/src/pwman/wsgi.py new file mode 100644 index 0000000..3719d7f --- /dev/null +++ b/src/pwman/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for pwman project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pwman.settings") + +application = get_wsgi_application() diff --git a/src/scripts/create-kdc-principal.pl b/src/scripts/create-kdc-principal.pl new file mode 100755 index 0000000..ec541da --- /dev/null +++ b/src/scripts/create-kdc-principal.pl @@ -0,0 +1,18 @@ +#!/usr/bin/env perl + +use Heimdal::Kadm5 qw(/KADM5_/); + +$client = Heimdal::Kadm5::Client->new('RaiseErrors'=>1,'Principal'=>'shibboleth-idp@NORDU.NET',Keytab=>'/etc/useradmin.keytab'); +my $line = <STDIN>; +my ($user,$pass) = split('\s+',$line); +die "Missing parameters on stdin\n" unless ($user and $pass); +my ($local,$domain) = split('\@',$user); + +my $pn = "$local\@NORDU.NET"; +my $p = $client->getPrincipal($pn); +unless ($p) { + $p = $client->makePrincipal($pn); + $client->createPrincipal($p,$pass); +} else { + $client->changePassword($pn,$pass); +} diff --git a/src/static/css/NORDUnet.css b/src/static/css/NORDUnet.css new file mode 100644 index 0000000..6af9baa --- /dev/null +++ b/src/static/css/NORDUnet.css @@ -0,0 +1,321 @@ +html { + +} + +body { + margin: 0; + padding: 0; + +} + +#container { + width: 100%; + font-family: Arial, Helvetica, sans-serif; + font-size: 12px; + color: #000; + background: #fff url('../img/pipes_back.jpg') repeat-y top left; +} + +#top { + display: block; + width: 100%; + background: #00B2E4 url('../img/top_back.gif') repeat-x bottom left; + overflow: hidden; + +} +#top_table { + margin:0; + padding:0; + margin-top: 33px; + width: 900px; + border-collapse: collapse; + margin-bottom: -1px; + + +} + +#top_table td { + vertical-align:bottom; +} + +#top_table td img { + margin-bottom: 20px; + display: block; + padding-right:10px; + +} + +#main_nav { + margin:0; + padding:0; + list-style:none; + color: #fff; + height: 40px; + display: block; + +} + +#main_nav li { + display: block; + float: left; + background: url('../img/main_nav_left.gif') no-repeat bottom left; + padding: 0 0 0 11px; + +} +#main_nav li#selectedPage { + background: url('../img/main_nav_left_selected.gif') no-repeat bottom left; +} +#main_nav li a { + display: block; + float: left; + padding: 0 11px 0 0; + height: 40px; + color: #fff; + text-decoration: none; + outline: 0; + background: url('../img/main_nav_back.gif') no-repeat bottom right; +} + +#main_nav li#selectedPage a { + background: url('../img/main_nav_back_selected.jpg') no-repeat bottom right; + color: #000; + +} +#main_nav li a span { + vertical-align: middle; + display: block; + padding-top: 10px; + +} + +#left { + clear: both; + background: #fff url('../img/left_back.gif') repeat-y top left; + width: 200px; + float: left; +} + +#search_form { + padding-left: 8px; + width: 200px; + margin: 10px 0 20px 0; +} + +#search_form .input_image { + + vertical-align: middle; +} + +#nav { + + width: 200px; + font-size: 12px; + clear: both; +} + +#nav #intro { + width: 179px; + background: #fff url('../img/intro_top.jpg') no-repeat top left; + padding: 15px 10px 1px 10px; +} + +#nav #intro_footer { + width: 199px; + height:27px; + background: #fff url('../img/intro_bottom.jpg') no-repeat top left; +} + + +#nav ul.site_tree, +#nav ul.site_tree ul, +#nav ul.site_tree li { + margin: 0; + padding: 0; + list-style: none; + +} +#nav ul.site_tree { + background: transparent url('../img/subnavback.gif') no-repeat bottom left; + padding-bottom:2px; +} + +#nav ul.site_tree a { + color: #4F4E4E; + text-decoration: none; + display: block; +} + +#nav ul.site_tree a:hover { + text-decoration: none; +} + +#nav ul.site_tree strong.level1 { + color: #000; + display: block; + background-color: #59BAE7; +} + +#nav ul.site_tree li.level2 { + background: transparent url('../img/subnavback.gif') no-repeat top left; +} + + +#nav ul.site_tree a.level1, +#nav ul.site_tree strong.level1 { + padding:5px 0 5px 10px; + +} + +#nav ul.site_tree li.level2 { + display:block; + padding: 5px 0 2px 15px; +} + +#nav ul.site_tree a.level2 { + +} + +#nav #nav_pic { + display: block; + margin: 0; + padding: 0; +} + + +h1 { + font-size: 20px; + color: #004788; +} + +h2 { + font-size: 18px; + color: #004788; +} + +h3 { + font-size: 16px; + color: #004788; +} + +h4 { + font-size: 14px; + color: #004788; +} + +h5 { + font-size: 12px; + color: #004788; +} + +p { + font-size: 12px; + color: #004788; + +} + +ul { + font-size: 12px; + color: #004788; + +} + +#content { + margin-left: 200px; + padding: 20px; + width: auto; + line-height: 1.5em; +} + +#content table { + border-collapse: collapse; +} + +#content th { + background-color: #f0f0f0; + padding: 5px; + color: #036; +} + +#content td { + vertical-align: middle; + padding: 5px; +} + +*html #content table { width:99%; } + +#footer { + clear: both; + width: 100%; + height: 35px; + background-color: #D8D8D8; + border-top: 1px solid #989898; + border-bottom: 1px solid #989898; +} + +#footer p { + vertical-align: middle; + margin: 12px 10px 10px 200px; + font-size: 10px; + color: #848484; +} + +#footer img { + float: left; + margin: 0px 0px 0px 2px; +} + +hr { + border: 0; + color: #696969; + background-color:#696969; + height: 1px; +} + + +#intro img{ + padding-top: 5px; + border: none; +} + +/* Open trouble tickets */ +#opentickets { + margin-left: 200px; + padding: 0 20px 20px 20px; + width: auto; +} + +.blue { +background:#004788 none repeat scroll 0 0; +} + +.text { + font-size: 12px; + color: #004788; +} + +.group_heading { +color:#004788; +font-size:12px; +font-weight:bolder; +} + +.list_info { +background-color:#D9EFFA; +color:#004788; +padding:0.6em; +} + +.whitebold { +color:#FFFFFF; +font-size:12px; +font-weight:bold; +} + +/* Password change styles */ +ul.errorlist { +font-weight:bold; +list-style:none; +} +th.formlabel { +text-align:right; +} diff --git a/src/static/css/style.css b/src/static/css/style.css new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/static/css/style.css diff --git a/src/static/img/NORDUnet2.jpg b/src/static/img/NORDUnet2.jpg Binary files differnew file mode 100644 index 0000000..ed5b9bf --- /dev/null +++ b/src/static/img/NORDUnet2.jpg diff --git a/src/static/img/intro_bottom.jpg b/src/static/img/intro_bottom.jpg Binary files differnew file mode 100644 index 0000000..f1f01b5 --- /dev/null +++ b/src/static/img/intro_bottom.jpg diff --git a/src/static/img/intro_top.jpg b/src/static/img/intro_top.jpg Binary files differnew file mode 100644 index 0000000..4579323 --- /dev/null +++ b/src/static/img/intro_top.jpg diff --git a/src/static/img/left_back.gif b/src/static/img/left_back.gif Binary files differnew file mode 100644 index 0000000..bffe2f0 --- /dev/null +++ b/src/static/img/left_back.gif diff --git a/src/static/img/main_nav_back.gif b/src/static/img/main_nav_back.gif Binary files differnew file mode 100644 index 0000000..c6ad535 --- /dev/null +++ b/src/static/img/main_nav_back.gif diff --git a/src/static/img/main_nav_back_selected.jpg b/src/static/img/main_nav_back_selected.jpg Binary files differnew file mode 100644 index 0000000..8492215 --- /dev/null +++ b/src/static/img/main_nav_back_selected.jpg diff --git a/src/static/img/main_nav_left.gif b/src/static/img/main_nav_left.gif Binary files differnew file mode 100644 index 0000000..122e91b --- /dev/null +++ b/src/static/img/main_nav_left.gif diff --git a/src/static/img/main_nav_left_selected.gif b/src/static/img/main_nav_left_selected.gif Binary files differnew file mode 100644 index 0000000..1e8a0c0 --- /dev/null +++ b/src/static/img/main_nav_left_selected.gif diff --git a/src/static/img/pipes_back.jpg b/src/static/img/pipes_back.jpg Binary files differnew file mode 100644 index 0000000..d492675 --- /dev/null +++ b/src/static/img/pipes_back.jpg diff --git a/src/static/img/subnavback.gif b/src/static/img/subnavback.gif Binary files differnew file mode 100644 index 0000000..799b35f --- /dev/null +++ b/src/static/img/subnavback.gif diff --git a/src/static/img/top_back.gif b/src/static/img/top_back.gif Binary files differnew file mode 100644 index 0000000..40ae535 --- /dev/null +++ b/src/static/img/top_back.gif diff --git a/src/static/js/jquery/jquery-1.4.4.min.js b/src/static/js/jquery/jquery-1.4.4.min.js new file mode 100644 index 0000000..8f3ca2e --- /dev/null +++ b/src/static/js/jquery/jquery-1.4.4.min.js @@ -0,0 +1,167 @@ +/*! + * jQuery JavaScript Library v1.4.4 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Nov 11 19:04:53 2010 -0500 + */ +(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h= +h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;k<J.length;k++){h=J[k];h.origType.replace(X,"")===a.type?f.push(h.selector):J.splice(k--,1)}f=c(a.target).closest(f,a.currentTarget);o=0;for(x=f.length;o<x;o++){r=f[o];for(k=0;k<J.length;k++){h=J[k];if(r.selector===h.selector&&(!A||A.test(h.namespace))){l=r.elem;e=null;if(h.preType==="mouseenter"|| +h.preType==="mouseleave"){a.type=h.preType;e=c(a.relatedTarget).closest(h.selector)[0]}if(!e||e!==l)C.push({elem:l,handleObj:h,level:r.level})}}}o=0;for(x=C.length;o<x;o++){f=C[o];if(d&&f.level>d)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La, +"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this, +e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a, +"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+ +a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/, +C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j, +s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this, +j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length}, +toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j=== +-1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false; +if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K<Q;K++)if((j=arguments[K])!=null)for(s in j){v=G[s];z=j[s];if(G!==z)if(ga&&z&&(b.isPlainObject(z)||(H=b.isArray(z)))){if(H){H=false;v=v&&b.isArray(v)?v:[]}else v=v&&b.isPlainObject(v)?v:{};G[s]=b.extend(ga,v,z)}else if(z!==B)G[s]=z}return G};b.extend({noConflict:function(j){E.$=e;if(j)E.jQuery=d;return b},isReady:false,readyWait:1,ready:function(j){j===true&&b.readyWait--; +if(!b.readyWait||j!==true&&!b.isReady){if(!t.body)return setTimeout(b.ready,1);b.isReady=true;if(!(j!==true&&--b.readyWait>0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload", +b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&& +!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&& +l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H<G;){if(s.apply(j[H++],v)===false)break}else if(K)for(z in j){if(s.call(j[z], +z,j[z])===false)break}else for(v=j[0];H<G&&s.call(v,H,v)!==false;v=j[++H]);return j},trim:O?function(j){return j==null?"":O.call(j)}:function(j){return j==null?"":j.toString().replace(k,"").replace(o,"")},makeArray:function(j,s){var v=s||[];if(j!=null){var z=b.type(j);j.length==null||z==="string"||z==="function"||z==="regexp"||b.isWindow(j)?M.call(v,j):b.merge(v,j)}return v},inArray:function(j,s){if(s.indexOf)return s.indexOf(j);for(var v=0,z=s.length;v<z;v++)if(s[v]===j)return v;return-1},merge:function(j, +s){var v=j.length,z=0;if(typeof s.length==="number")for(var H=s.length;z<H;z++)j[v++]=s[z];else for(;s[z]!==B;)j[v++]=s[z++];j.length=v;return j},grep:function(j,s,v){var z=[],H;v=!!v;for(var G=0,K=j.length;G<K;G++){H=!!s(j[G],G);v!==H&&z.push(j[G])}return z},map:function(j,s,v){for(var z=[],H,G=0,K=j.length;G<K;G++){H=s(j[G],G,v);if(H!=null)z[z.length]=H}return z.concat.apply([],z)},guid:1,proxy:function(j,s,v){if(arguments.length===2)if(typeof s==="string"){v=j;j=v[s];s=B}else if(s&&!b.isFunction(s)){v= +s;s=B}if(!s&&j)s=function(){return j.apply(v||this,arguments)};if(j)s.guid=j.guid=j.guid||s.guid||b.guid++;return s},access:function(j,s,v,z,H,G){var K=j.length;if(typeof s==="object"){for(var Q in s)b.access(j,Q,s[Q],z,H,v);return j}if(v!==B){z=!G&&z&&b.isFunction(v);for(Q=0;Q<K;Q++)H(j[Q],s,z?v.call(j[Q],Q,H(j[Q],s)):v,G);return j}return K?H(j[0],s):B},now:function(){return(new Date).getTime()},uaMatch:function(j){j=j.toLowerCase();j=L.exec(j)||g.exec(j)||i.exec(j)||j.indexOf("compatible")<0&&n.exec(j)|| +[];return{browser:j[1]||"",version:j[2]||"0"}},browser:{}});b.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(j,s){R["[object "+s+"]"]=s.toLowerCase()});m=b.uaMatch(m);if(m.browser){b.browser[m.browser]=true;b.browser.version=m.version}if(b.browser.webkit)b.browser.safari=true;if(D)b.inArray=function(j,s){return D.call(s,j)};if(!/\s/.test("\u00a0")){k=/^[\s\xA0]+/;o=/[\s\xA0]+$/}f=b(t);if(t.addEventListener)u=function(){t.removeEventListener("DOMContentLoaded",u, +false);b.ready()};else if(t.attachEvent)u=function(){if(t.readyState==="complete"){t.detachEvent("onreadystatechange",u);b.ready()}};return E.jQuery=E.$=b}();(function(){c.support={};var a=t.documentElement,b=t.createElement("script"),d=t.createElement("div"),e="script"+c.now();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"), +k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false, +scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent= +false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom= +1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="<div style='width:4px;'></div>";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display= +"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h= +c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando); +else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h<l;h++){f=e[h].name;if(f.indexOf("data-")===0){f=f.substr(5);ka(this[0],f,d[f])}}}return d}else if(typeof a==="object")return this.each(function(){c.data(this, +a)});var k=a.split(".");k[1]=k[1]?"."+k[1]:"";if(b===B){d=this.triggerHandler("getData"+k[1]+"!",[k[0]]);if(d===B&&this.length){d=c.data(this[0],a);d=ka(this[0],a,d)}return d===B&&k[1]?this.data(k[0]):d}else return this.each(function(){var o=c(this),x=[k[0],b];o.triggerHandler("setData"+k[1]+"!",x);c.data(this,a,b);o.triggerHandler("changeData"+k[1]+"!",x)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var e= +c.data(a,b);if(!d)return e||[];if(!e||c.isArray(d))e=c.data(a,b,c.makeArray(d));else e.push(d);return e}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),e=d.shift();if(e==="inprogress")e=d.shift();if(e){b==="fx"&&d.unshift("inprogress");e.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===B)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this, +a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var sa=/[\n\t]/g,ha=/\s+/,Sa=/\r/g,Ta=/^(?:href|src|style)$/,Ua=/^(?:button|input)$/i,Va=/^(?:button|input|object|select|textarea)$/i,Wa=/^a(?:rea)?$/i,ta=/^(?:radio|checkbox)$/i;c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan", +colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};c.fn.extend({attr:function(a,b){return c.access(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(x){var r=c(this);r.addClass(a.call(this,x,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType=== +1)if(f.className){for(var h=" "+f.className+" ",l=f.className,k=0,o=b.length;k<o;k++)if(h.indexOf(" "+b[k]+" ")<0)l+=" "+b[k];f.className=c.trim(l)}else f.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var x=c(this);x.removeClass(a.call(this,o,x.attr("class")))});if(a&&typeof a==="string"||a===B)for(var b=(a||"").split(ha),d=0,e=this.length;d<e;d++){var f=this[d];if(f.nodeType===1&&f.className)if(a){for(var h=(" "+f.className+" ").replace(sa," "), +l=0,k=b.length;l<k;l++)h=h.replace(" "+b[l]+" "," ");f.className=c.trim(h)}else f.className=""}return this},toggleClass:function(a,b){var d=typeof a,e=typeof b==="boolean";if(c.isFunction(a))return this.each(function(f){var h=c(this);h.toggleClass(a.call(this,f,h.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var f,h=0,l=c(this),k=b,o=a.split(ha);f=o[h++];){k=e?k:!l.hasClass(f);l[k?"addClass":"removeClass"](f)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this, +"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(sa," ").indexOf(a)>-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one"; +if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h<e;h++){var l=f[h];if(l.selected&&(c.support.optDisabled?!l.disabled:l.getAttribute("disabled")===null)&&(!l.parentNode.disabled||!c.nodeName(l.parentNode,"optgroup"))){a=c(l).val();if(b)return a;d.push(a)}}return d}if(ta.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Sa,"")}return B}var k=c.isFunction(a);return this.each(function(o){var x=c(this),r=a;if(this.nodeType===1){if(k)r= +a.call(this,o,x.val());if(r==null)r="";else if(typeof r==="number")r+="";else if(c.isArray(r))r=c.map(r,function(C){return C==null?"":C+""});if(c.isArray(r)&&ta.test(this.type))this.checked=c.inArray(x.val(),r)>=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true}, +attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&& +b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0}; +c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem, +arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid= +d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+ +c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h<A.length;h++){C=A[h];if(d.guid===C.guid){if(k||x.test(C.namespace)){e==null&&A.splice(h--,1);r.remove&&r.remove.call(a,C)}if(e!=null)break}}if(A.length===0||e!=null&&A.length===1){if(!r.teardown||r.teardown.call(a,o)===false)c.removeEvent(a,f,w.handle);delete I[f]}}else for(h=0;h<A.length;h++){C=A[h];if(k||x.test(C.namespace)){c.event.remove(a,r,C.handler,h);A.splice(h--,1)}}}if(c.isEmptyObject(I)){if(b= +w.handle)b.elem=null;delete w.events;delete w.handle;if(typeof w==="function")c.removeData(a,J);else c.isEmptyObject(w)&&c.removeData(a)}}}}},trigger:function(a,b,d,e){var f=a.type||a;if(!e){a=typeof a==="object"?a[c.expando]?a:c.extend(c.Event(f),a):c.Event(f);if(f.indexOf("!")>=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType=== +8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k=== +"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+ +d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f<l;f++){var k=d[f];if(b||e.test(k.namespace)){a.handler=k.handler;a.data=k.data;a.handleObj=k;k=k.handler.apply(this,h);if(k!==B){a.result=k;if(k===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), +fix:function(a){if(a[c.expando])return a;var b=a;a=c.Event(b);for(var d=this.props.length,e;d;){e=this.props[--d];a[e]=b[e]}if(!a.target)a.target=a.srcElement||t;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=t.documentElement;d=t.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop|| +d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(a.which==null&&(a.charCode!=null||a.keyCode!=null))a.which=a.charCode!=null?a.charCode:a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==B)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,Y(a.origType,a.selector),c.extend({},a,{handler:Ka,guid:a.handler.guid}))},remove:function(a){c.event.remove(this, +Y(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,d){if(c.isWindow(this))this.onbeforeunload=d},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.removeEvent=t.removeEventListener?function(a,b,d){a.removeEventListener&&a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent&&a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp= +c.now();this[c.expando]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ca;var a=this.originalEvent;if(a)if(a.preventDefault)a.preventDefault();else a.returnValue=false},stopPropagation:function(){this.isPropagationStopped=ca;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ca;this.stopPropagation()},isDefaultPrevented:U,isPropagationStopped:U,isImmediatePropagationStopped:U}; +var va=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},wa=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?wa:va,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?wa:va)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(){if(this.nodeName.toLowerCase()!== +"form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length){a.liveFired=B;return la("submit",this,arguments)}});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13){a.liveFired=B;return la("submit",this,arguments)}})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};if(!c.support.changeBubbles){var V, +xa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired= +B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type=== +"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]=== +0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h<k;h++)c.event.add(this[h],d,l,e)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault)for(var d in a)this.unbind(d, +a[d]);else{d=0;for(var e=this.length;d<e;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,e){return this.live(b,d,e,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){var d=c.Event(a);d.preventDefault();d.stopPropagation();c.event.trigger(d,b,this[0]);return d.result}},toggle:function(a){for(var b=arguments,d= +1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(e){var f=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,f+1);e.preventDefault();return b[f].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var ya={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,e,f,h){var l,k=0,o,x,r=h||this.selector;h=h?this:c(this.context);if(typeof d=== +"object"&&!d.preventDefault){for(l in d)h[b](l,e,d[l],r);return this}if(c.isFunction(e)){f=e;e=B}for(d=(d||"").split(" ");(l=d[k++])!=null;){o=X.exec(l);x="";if(o){x=o[0];l=l.replace(X,"")}if(l==="hover")d.push("mouseenter"+x,"mouseleave"+x);else{o=l;if(l==="focus"||l==="blur"){d.push(ya[l]+x);l+=x}else l=(ya[l]||l)+x;if(b==="live"){x=0;for(var A=h.length;x<A;x++)c.event.add(h[x],"live."+Y(l,r),{data:e,selector:r,handler:f,origType:l,origHandler:f,preType:o})}else h.unbind("live."+Y(l,r),f)}}return this}}); +c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d,e){if(e==null){e=d;d=null}return arguments.length>0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}}); +(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1&&!q){y.sizcache=n;y.sizset=p}if(y.nodeName.toLowerCase()===i){F=y;break}y=y[g]}m[p]=F}}}function b(g,i,n,m,p,q){p=0;for(var u=m.length;p<u;p++){var y=m[p];if(y){var F=false;for(y=y[g];y;){if(y.sizcache===n){F=m[y.sizset];break}if(y.nodeType===1){if(!q){y.sizcache=n;y.sizset=p}if(typeof i!=="string"){if(y===i){F=true;break}}else if(k.filter(i, +[y]).length>0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3]; +break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr, +q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h= +l;g.sort(w);if(h)for(var i=1;i<g.length;i++)g[i]===g[i-1]&&g.splice(i--,1)}return g};k.matches=function(g,i){return k(g,null,null,i)};k.matchesSelector=function(g,i){return k(i,null,null,[g]).length>0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p<q;p++){var u,y=o.order[p];if(u=o.leftMatch[y].exec(g)){var F=u[1];u.splice(1,1);if(F.substr(F.length-1)!=="\\"){u[1]=(u[1]||"").replace(/\\/g,"");m=o.find[y](u,i,n);if(m!=null){g=g.replace(o.match[y],"");break}}}}m||(m=i.getElementsByTagName("*")); +return{set:m,expr:g}};k.filter=function(g,i,n,m){for(var p,q,u=g,y=[],F=i,M=i&&i[0]&&k.isXML(i[0]);g&&i.length;){for(var N in o.filter)if((p=o.leftMatch[N].exec(g))!=null&&p[2]){var O,D,R=o.filter[N];D=p[1];q=false;p.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(F===y)y=[];if(o.preFilter[N])if(p=o.preFilter[N](p,F,n,y,m,M)){if(p===true)continue}else q=O=true;if(p)for(var j=0;(D=F[j])!=null;j++)if(D){O=R(D,p,j,F);var s=m^!!O;if(n&&O!=null)if(s)q=true;else F[j]=false;else if(s){y.push(D);q=true}}if(O!== +B){n||(F=y);g=g.replace(o.match[N],"");if(!q)return[];break}}}if(g===u)if(q==null)k.error(g);else break;u=g}return F};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var o=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/, +POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,i){var n=typeof i==="string",m=n&&!/\W/.test(i);n=n&&!m;if(m)i=i.toLowerCase();m=0;for(var p=g.length,q;m<p;m++)if(q=g[m]){for(;(q=q.previousSibling)&&q.nodeType!==1;);g[m]=n||q&&q.nodeName.toLowerCase()=== +i?q||false:q===i}n&&k.filter(i,g,true)},">":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p<q;p++){if(n=g[p]){n=n.parentNode;g[p]=n.nodeName.toLowerCase()===i?n:false}}else{for(;p<q;p++)if(n=g[p])g[p]=m?n.parentNode:n.parentNode===i;m&&k.filter(i,g,true)}},"":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m=i=i.toLowerCase();q=a}q("parentNode",i,p,g,m,n)},"~":function(g,i,n){var m,p=e++,q=b;if(typeof i==="string"&&!/\W/.test(i)){m= +i=i.toLowerCase();q=a}q("previousSibling",i,p,g,m,n)}},find:{ID:function(g,i,n){if(typeof i.getElementById!=="undefined"&&!n)return(g=i.getElementById(g[1]))&&g.parentNode?[g]:[]},NAME:function(g,i){if(typeof i.getElementsByName!=="undefined"){for(var n=[],m=i.getElementsByName(g[1]),p=0,q=m.length;p<q;p++)m[p].getAttribute("name")===g[1]&&n.push(m[p]);return n.length===0?null:n}},TAG:function(g,i){return i.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,i,n,m,p,q){g=" "+g[1].replace(/\\/g, +"")+" ";if(q)return g;q=0;for(var u;(u=i[q])!=null;q++)if(u)if(p^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n, +m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled=== +true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"=== +g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return i<n[3]-0},gt:function(g,i,n){return i>n[3]-0},nth:function(g,i,n){return n[3]- +0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n<m;n++)if(i[n]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+p)},CHILD:function(g,i){var n=i[1],m=g;switch(n){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(n=== +"first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":n=i[2];var p=i[3];if(n===1&&p===0)return true;var q=i[0],u=g.parentNode;if(u&&(u.sizcache!==q||!g.nodeIndex)){var y=0;for(m=u.firstChild;m;m=m.nextSibling)if(m.nodeType===1)m.nodeIndex=++y;u.sizcache=q}m=g.nodeIndex-p;return n===0?m===0:m%n===0&&m/n>=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()=== +i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]]; +if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m, +g);else if(typeof g.length==="number")for(var p=g.length;n<p;n++)m.push(g[n]);else for(;g[n];n++)m.push(g[n]);return m}}var w,I;if(t.documentElement.compareDocumentPosition)w=function(g,i){if(g===i){h=true;return 0}if(!g.compareDocumentPosition||!i.compareDocumentPosition)return g.compareDocumentPosition?-1:1;return g.compareDocumentPosition(i)&4?-1:1};else{w=function(g,i){var n,m,p=[],q=[];n=g.parentNode;m=i.parentNode;var u=n;if(g===i){h=true;return 0}else if(n===m)return I(g,i);else if(n){if(!m)return 1}else return-1; +for(;u;){p.unshift(u);u=u.parentNode}for(u=m;u;){q.unshift(u);u=u.parentNode}n=p.length;m=q.length;for(u=0;u<n&&u<m;u++)if(p[u]!==q[u])return I(p[u],q[u]);return u===n?I(g,q[u],-1):I(p[u],i,1)};I=function(g,i,n){if(g===i)return n;for(g=g.nextSibling;g;){if(g===i)return-1;g=g.nextSibling}return 1}}k.getText=function(g){for(var i="",n,m=0;g[m];m++){n=g[m];if(n.nodeType===3||n.nodeType===4)i+=n.nodeValue;else if(n.nodeType!==8)i+=k.getText(n.childNodes)}return i};(function(){var g=t.createElement("div"), +i="script"+(new Date).getTime(),n=t.documentElement;g.innerHTML="<a name='"+i+"'/>";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g); +n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&& +function(){var g=k,i=t.createElement("div");i.innerHTML="<p class='TEST'></p>";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F|| +p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g= +t.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition? +function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n<u;n++)k(g,q[n],m);return k.filter(p,m)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=k.getText;c.isXMLDoc=k.isXML; +c.contains=k.contains})();var Za=/Until$/,$a=/^(?:parents|prevUntil|prevAll)/,ab=/,/,Na=/^.[^:#\[\.,]*$/,bb=Array.prototype.slice,cb=c.expr.match.POS;c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,e=0,f=this.length;e<f;e++){d=b.length;c.find(a,this[e],b);if(e>0)for(var h=d;h<b.length;h++)for(var l=0;l<d;l++)if(b[l]===b[h]){b.splice(h--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,e=b.length;d<e;d++)if(c.contains(this,b[d]))return true})}, +not:function(a){return this.pushStack(ma(this,a,false),"not",a)},filter:function(a){return this.pushStack(ma(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e<f;e++){l=a[e];k[l]||(k[l]=c.expr.match.POS.test(l)?c(l,b||this.context):l)}for(;h&&h.ownerDocument&&h!==b;){for(l in k){e=k[l];if(e.jquery?e.index(h)>-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h= +h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e<f;e++)for(h=this[e];h;)if(l?l.index(h)>-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context): +c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a, +2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a, +b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&& +e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/<tbody/i,eb=/<|&#?\w+;/,Ca=/<(?:script|object|embed|option|style)/i,Da=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/\=([^="'>\s]+\/)>/g,P={option:[1, +"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null; +else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1></$2>");try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(e){this.empty().append(a)}}else c.isFunction(a)?this.each(function(f){var h=c(this);h.html(a.call(this,f,h.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d= +c(this),e=d.html();d.replaceWith(a.call(this,b,e))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){var e,f,h,l=a[0],k=[];if(!c.support.checkClone&&arguments.length===3&&typeof l==="string"&&Da.test(l))return this.each(function(){c(this).domManip(a, +b,d,true)});if(c.isFunction(l))return this.each(function(x){var r=c(this);a[0]=l.call(this,x,b?r.html():B);r.domManip(a,b,d)});if(this[0]){e=l&&l.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:c.buildFragment(a,this,k);h=e.fragment;if(f=h.childNodes.length===1?h=h.firstChild:h.firstChild){b=b&&c.nodeName(f,"tr");f=0;for(var o=this.length;f<o;f++)d.call(b?c.nodeName(this[f],"table")?this[f].getElementsByTagName("tbody")[0]||this[f].appendChild(this[f].ownerDocument.createElement("tbody")): +this[f]:this[f],f>0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append", +prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f<h;f++){var l=(f>0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument|| +b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1></$2>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]==="<table>"&&!x?r.childNodes:[];for(o=k.length- +1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script")))); +d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i, +jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true, +zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b), +h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b); +if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f= +d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left; +e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, +ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b=== +"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("<div>").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&& +!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})}, +getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html", +script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data|| +!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache= +false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset; +A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type", +b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&& +c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d|| +c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]= +encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess", +[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"), +e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}}); +if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show", +3),a,b,d);else{d=0;for(var e=this.length;d<e;d++){a=this[d];b=a.style.display;if(!c.data(a,"olddisplay")&&b==="none")b=a.style.display="";b===""&&c.css(a,"display")==="none"&&c.data(a,"olddisplay",qa(a.nodeName))}for(d=0;d<e;d++){a=this[d];b=a.style.display;if(b===""||b==="none")a.style.display=c.data(a,"olddisplay")||""}return this}},hide:function(a,b,d){if(a||a===0)return this.animate(S("hide",3),a,b,d);else{a=0;for(b=this.length;a<b;a++){d=c.css(this[a],"display");d!=="none"&&c.data(this[a],"olddisplay", +d)}for(a=0;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b,d){var e=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||e?this.each(function(){var f=e?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(S("toggle",3),a,b,d);return this},fadeTo:function(a,b,d,e){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d,e)},animate:function(a,b,d,e){var f=c.speed(b, +d,e);if(c.isEmptyObject(a))return this.each(f.complete);return this[f.queue===false?"each":"queue"](function(){var h=c.extend({},f),l,k=this.nodeType===1,o=k&&c(this).is(":hidden"),x=this;for(l in a){var r=c.camelCase(l);if(l!==r){a[r]=a[l];delete a[l];l=r}if(a[l]==="hide"&&o||a[l]==="show"&&!o)return h.complete.call(this);if(k&&(l==="height"||l==="width")){h.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY];if(c.css(this,"display")==="inline"&&c.css(this,"float")==="none")if(c.support.inlineBlockNeedsLayout)if(qa(this.nodeName)=== +"inline")this.style.display="inline-block";else{this.style.display="inline";this.style.zoom=1}else this.style.display="inline-block"}if(c.isArray(a[l])){(h.specialEasing=h.specialEasing||{})[l]=a[l][1];a[l]=a[l][0]}}if(h.overflow!=null)this.style.overflow="hidden";h.curAnim=c.extend({},a);c.each(a,function(A,C){var J=new c.fx(x,h,A);if(vb.test(C))J[C==="toggle"?o?"show":"hide":C](a);else{var w=wb.exec(C),I=J.cur()||0;if(w){var L=parseFloat(w[2]),g=w[3]||"px";if(g!=="px"){c.style(x,A,(L||1)+g);I=(L|| +1)/J.cur()*I;c.style(x,A,I+g)}if(w[1])L=(w[1]==="-="?-1:1)*L+I;J.custom(I,L,g)}else J.custom(I,C,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var e=d.length-1;e>=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b, +d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a* +Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)} +var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true; +this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide|| +this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a= +c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},interval:13,stop:function(){clearInterval(ba);ba=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a=== +b.elem}).length};var xb=/^t(?:able|d|h)$/i,Ia=/^(?:body|html)$/i;c.fn.offset="getBoundingClientRect"in t.documentElement?function(a){var b=this[0],d;if(a)return this.each(function(l){c.offset.setOffset(this,a,l)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);try{d=b.getBoundingClientRect()}catch(e){}var f=b.ownerDocument,h=f.documentElement;if(!d||!c.contains(h,b))return d||{top:0,left:0};b=f.body;f=fa(f);return{top:d.top+(f.pageYOffset||c.support.boxModel&& +h.scrollTop||b.scrollTop)-(h.clientTop||b.clientTop||0),left:d.left+(f.pageXOffset||c.support.boxModel&&h.scrollLeft||b.scrollLeft)-(h.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(x){c.offset.setOffset(this,a,x)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d,e=b.offsetParent,f=b.ownerDocument,h=f.documentElement,l=f.body;d=(f=f.defaultView)?f.getComputedStyle(b,null):b.currentStyle; +for(var k=b.offsetTop,o=b.offsetLeft;(b=b.parentNode)&&b!==l&&b!==h;){if(c.offset.supportsFixedPosition&&d.position==="fixed")break;d=f?f.getComputedStyle(b,null):b.currentStyle;k-=b.scrollTop;o-=b.scrollLeft;if(b===e){k+=b.offsetTop;o+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&xb.test(b.nodeName))){k+=parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}e=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"){k+= +parseFloat(d.borderTopWidth)||0;o+=parseFloat(d.borderLeftWidth)||0}d=d}if(d.position==="relative"||d.position==="static"){k+=l.offsetTop;o+=l.offsetLeft}if(c.offset.supportsFixedPosition&&d.position==="fixed"){k+=Math.max(h.scrollTop,l.scrollTop);o+=Math.max(h.scrollLeft,l.scrollLeft)}return{top:k,left:o}};c.offset={initialize:function(){var a=t.body,b=t.createElement("div"),d,e,f,h=parseFloat(c.css(a,"marginTop"))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px", +height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);d=b.firstChild;e=d.firstChild;f=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=e.offsetTop!==5;this.doesAddBorderForTableAndCells= +f.offsetTop===5;e.style.position="fixed";e.style.top="20px";this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15;e.style.position=e.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==h;a.removeChild(b);c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.css(a, +"marginTop"))||0;d+=parseFloat(c.css(a,"marginLeft"))||0}return{top:b,left:d}},setOffset:function(a,b,d){var e=c.css(a,"position");if(e==="static")a.style.position="relative";var f=c(a),h=f.offset(),l=c.css(a,"top"),k=c.css(a,"left"),o=e==="absolute"&&c.inArray("auto",[l,k])>-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a, +e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&& +c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase(); +c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+ +b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window); diff --git a/src/static/js/jquery/password_strength.js b/src/static/js/jquery/password_strength.js new file mode 100644 index 0000000..24e1dad --- /dev/null +++ b/src/static/js/jquery/password_strength.js @@ -0,0 +1,136 @@ +/* + * Password Strength (0.1.1) + * by Sagie Maoz (n0nick.net) + * n0nick@php.net + * + * This plugin will check the value of a password field and evaluate the + * strength of the typed password. This is done by checking for + * the diversity of character types: numbers, lowercase and uppercase + * letters and special characters. + * + * Copyright (c) 2010 Sagie Maoz <n0nick@php.net> + * Licensed under the GPL license, see http://www.gnu.org/licenses/gpl-3.0.html + * + * + * NOTE: This script requires jQuery to work. Download jQuery at www.jquery.com + * + */ + +(function($){ + +var passwordStrength = new function() +{ + this.countRegexp = function(val, rex) + { + var match = val.match(rex); + return match ? match.length : 0; + } + + this.getStrength = function(val, minLength) + { + var len = val.length; + + // too short =( + if (len < minLength) + { + return 0; + } + + var nums = this.countRegexp(val, /\d/g), + lowers = this.countRegexp(val, /[a-z]/g), + uppers = this.countRegexp(val, /[A-Z]/g), + specials = len - nums - lowers - uppers, + others = nums + specials; + + // upper case, lower case and three nums or specials used + if (lowers == 0 || uppers == 0 || others < 3) + { + return 0; + } + + var strength = len; + /* + if (nums) { strength+= 2; } + if (lowers) { strength+= uppers? 4 : 3; } + if (uppers) { strength+= lowers? 4 : 3; } + if (specials) { strength+= 5; } + if (len > 10) { strength+= 1; } + */ + + return strength; + } + + this.getStrengthLevel = function(val, minLength) + { + var strength = this.getStrength(val, minLength); + switch (true) + { + case (strength <= 0): + return 1; + break; + case (strength > 0 && strength <= 8): + return 2; + break; + case (strength > 10 && strength <= 12): + return 3; + break; + case (strength > 12 && strength <= 15): + return 4; + break; + case (strength > 15): + return 5; + break; + } + + return 1; + } +} + +$.fn.password_strength = function(options) +{ + var settings = $.extend({ + 'container' : null, + 'minLength' : 10, + 'texts' : { + 1 : 'Too weak', + 2 : 'Weak password', + 3 : 'Normal strength', + 4 : 'Strong password', + 5 : 'Very strong password' + } + }, options); + + return this.each(function() + { + if (settings.container) + { + var container = $(settings.container); + } + else + { + var container = $('<span/>').attr('class', 'password_strength'); + $(this).after(container); + } + + $(this).keyup(function() + { + var val = $(this).val(); + if (val.length > 0) + { + var level = passwordStrength.getStrengthLevel(val, settings.minLength); + var _class = 'password_strength_' + level; + + if (!container.hasClass(_class) && level in settings.texts) + { + container.text(settings.texts[level]).attr('class', 'password_strength ' + _class); + } + } + else + { + container.text('').attr('class', 'password_strength'); + } + }); + }); +}; + +})(jQuery); diff --git a/src/templates/404.html b/src/templates/404.html new file mode 100644 index 0000000..d74f8ca --- /dev/null +++ b/src/templates/404.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} + +{% block content %} +<p> +404 -- page not found +</p> +{% endblock %} diff --git a/src/templates/500.html b/src/templates/500.html new file mode 100644 index 0000000..57bed1c --- /dev/null +++ b/src/templates/500.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} + +{% block content %} +<p> +500 -- server error +</p> +{% endblock %} diff --git a/src/templates/base.html b/src/templates/base.html new file mode 100644 index 0000000..840024d --- /dev/null +++ b/src/templates/base.html @@ -0,0 +1,28 @@ +{% load static %}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <link rel="stylesheet" href="{% static 'css/NORDUnet.css' %}" type="text/css" media="screen" title="NORDUnet" charset="utf-8" />
+ <title>{% block title %}{% endblock %}</title>
+ {% block js %}
+ {% endblock %}
+</head>
+<body>
+ <div id="container">
+ <div id="top">
+ <table id="top_table">
+ <tr>
+ <td><img src="{% static 'img/NORDUnet2.jpg' %}" width="203" height="46" alt="" /></td>
+ </tr>
+ </table>
+ </div>
+ <div id="content">
+ {% block content %}{% endblock %}
+ </div>
+ <div id="footer">
+ <p>NORDUnet A/S | Kastruplundgade 22 | DK-2770 Kastrup | DENMARK | Phone +45 32 46 25 00 | Fax +45 45 76 23 66 | info@nordu.net</p>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/src/templates/login.html b/src/templates/login.html new file mode 100644 index 0000000..99aad5d --- /dev/null +++ b/src/templates/login.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} +{% block title %}Log in via your IdP{% endblock %} + +{% block content %} +<p> +<a href="https://crowd.nordu.net/Shibboleth.sso/Login/idp.nordu.net?target=https://crowd.nordu.net{% url 'loginfed' %}?next={% url 'index' %}">Click here to login via your Identity Provider</a> +</p> +{% endblock %} @@ -0,0 +1 @@ +Shaimet4ahW2 @@ -1,3 +1,20 @@ #!/bin/sh -yes no | python manage.py syncdb -python manage.py runserver 0.0.0.0:8000 + + +case "$*" in + dev) + export SECRET_KEY="+qYGOYFD(Pc;--S]X%Xnu&j4c+~5As6)yRTY;CHl4bRW;" + export DEBUG_MODE=True + yes no | python manage.py migrate + python manage.py runserver 0.0.0.0:8000 + ;; + server) + # uwsgi start! + + ;; + shell) + /bin/bash + ;; + *) + python manage.py "$@" +esac |