Remove im app.
authorAntony Chazapis <chazapis@gmail.com>
Wed, 4 Jan 2012 16:59:40 +0000 (18:59 +0200)
committerAntony Chazapis <chazapis@gmail.com>
Wed, 4 Jan 2012 16:59:40 +0000 (18:59 +0200)
Refs #1761

71 files changed:
README
docs/source/adminguide.rst
other/invite.py [deleted file]
pithos/im/__init__.py [deleted file]
pithos/im/api.py [deleted file]
pithos/im/faults.py [deleted file]
pithos/im/fixtures/admin_user.json [deleted file]
pithos/im/fixtures/auth_test_data.json [deleted file]
pithos/im/forms.py [deleted file]
pithos/im/interface.py [deleted file]
pithos/im/migrations/0001_initial.py [deleted file]
pithos/im/migrations/0002_auto__add_field_user_is_verified.py [deleted file]
pithos/im/migrations/0003_auto__add_field_user_provider__add_field_user_openidurl__add_field_inv.py [deleted file]
pithos/im/migrations/__init__.py [deleted file]
pithos/im/models.py [deleted file]
pithos/im/static/banner.png [deleted file]
pithos/im/static/bootstrap.css [deleted file]
pithos/im/static/jquery.js [deleted file]
pithos/im/static/jquery.tablesorter.js [deleted file]
pithos/im/static/local.png [deleted file]
pithos/im/static/main.js [deleted file]
pithos/im/static/openid.png [deleted file]
pithos/im/static/shibboleth.png [deleted file]
pithos/im/static/twitter.png [deleted file]
pithos/im/target/__init__.py [deleted file]
pithos/im/target/dummy.py [deleted file]
pithos/im/target/local.py [deleted file]
pithos/im/target/oauth2/__init__.py [deleted file]
pithos/im/target/oauth2/_version.py [deleted file]
pithos/im/target/oauth2/clients/__init__.py [deleted file]
pithos/im/target/oauth2/clients/imap.py [deleted file]
pithos/im/target/oauth2/clients/smtp.py [deleted file]
pithos/im/target/shibboleth.py [deleted file]
pithos/im/target/twitter.py [deleted file]
pithos/im/target/util.py [deleted file]
pithos/im/templates/activation.txt [deleted file]
pithos/im/templates/admin.html [deleted file]
pithos/im/templates/admin_base.html [deleted file]
pithos/im/templates/base.html [deleted file]
pithos/im/templates/index.html [deleted file]
pithos/im/templates/invitation.txt [deleted file]
pithos/im/templates/invitations.html [deleted file]
pithos/im/templates/invitations_list.html [deleted file]
pithos/im/templates/local_create.html [deleted file]
pithos/im/templates/password.txt [deleted file]
pithos/im/templates/pending_users.html [deleted file]
pithos/im/templates/reclaim.html [deleted file]
pithos/im/templates/register.html [deleted file]
pithos/im/templates/reset.html [deleted file]
pithos/im/templates/signup.html [deleted file]
pithos/im/templates/users_create.html [deleted file]
pithos/im/templates/users_info.html [deleted file]
pithos/im/templates/users_list.html [deleted file]
pithos/im/templates/users_profile.html [deleted file]
pithos/im/templatetags/__init__.py [deleted file]
pithos/im/templatetags/formatters.py [deleted file]
pithos/im/urls.py [deleted file]
pithos/im/util.py [deleted file]
pithos/im/views.py [deleted file]
pithos/middleware/__init__.py
pithos/middleware/astakos.py [moved from pithos/im/target/invitation.py with 62% similarity]
pithos/middleware/auth.py [deleted file]
pithos/settings.d/00-apps.conf
pithos/settings.d/10-backend.conf
pithos/settings.d/20-api.conf [deleted file]
pithos/settings.d/20-im.conf [deleted file]
pithos/settings.d/20-ui.conf [new file with mode: 0644]
pithos/settings.d/20-users.conf [new file with mode: 0644]
pithos/settings.d/30-ui.conf [deleted file]
pithos/urls.py
setup.py

diff --git a/README b/README
index 81c0b1c..ddee9dd 100644 (file)
--- a/README
+++ b/README
@@ -13,7 +13,7 @@ All docs are in the docs/source directory. The .rst files are perfectly readable
 To build the documentation you need to have Sphinx (http://sphinx.pocoo.org/) installed.
 
 On a typical debian-based Linux system run:
-    apt-get install python-django python-django-south python-setuptools python-sphinx python-httplib2
+    apt-get install python-django python-setuptools python-sphinx
     apt-get install python-sqlalchemy python-mysqldb python-psycopg2
 
 Then run:
@@ -30,18 +30,13 @@ Running the server
 ------------------
 
 Make sure you have all required packages installed:
-    apt-get install python-django python-setuptools python-sphinx python-httplib2
+    apt-get install python-django python-setuptools python-sphinx
     apt-get install python-sqlalchemy python-mysqldb python-psycopg2
 
 Then run:
     python manage.py syncdb
-    python manage.py migrate im
-    python manage.py loaddata admin_user
     python manage.py runserver
 
-Go to:
-       http://127.0.0.1:8000/im/admin?user=admin&token=0000
-
 This server is useful during development, but should not be used for deployment.
 To deploy Pithos using Apache, take a look at the Administrator Guide in docs.
 
index a2f96d8..c6ed459 100644 (file)
@@ -8,7 +8,7 @@ Assuming a clean debian squeeze (stable) installation, use the following steps t
 
 Install packages::
 
-  apt-get install git python-django python-django-south python-setuptools python-sphinx python-httplib2
+  apt-get install git python-django python-setuptools python-sphinx
   apt-get install python-sqlalchemy python-mysqldb python-psycopg2
   apt-get install apache2 libapache2-mod-wsgi
 
@@ -21,7 +21,6 @@ Setup the files::
 
   cd /pithos/pithos
   python manage.py syncdb
-  python manage.py migrate im
   cd /pithos
   python setup.py build_sphinx
 
@@ -126,7 +125,7 @@ Configure and run apache::
 
 Useful alias to add in ``~/.bashrc``::
 
-  alias pithos-sync='cd /pithos && git pull && python setup.py build_sphinx && cd pithos && python manage.py migrate im && /etc/init.d/apache2 restart'
+  alias pithos-sync='cd /pithos && git pull && python setup.py build_sphinx && /etc/init.d/apache2 restart'
 
 Gunicorn Setup
 --------------
diff --git a/other/invite.py b/other/invite.py
deleted file mode 100755 (executable)
index 660e4cb..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-
-if len(sys.argv) != 4:
-       print "Usage: %s <inviter token> <invitee name> <invitee email>" % (sys.argv[0],)
-       sys.exit(-1)
-
-import httplib2
-http = httplib2.Http(disable_ssl_certificate_validation=True)
-
-url = 'https://pithos.dev.grnet.gr/im/invite'
-
-import urllib
-params = urllib.urlencode({
-       'uniq': sys.argv[3],
-       'realname': sys.argv[2]
-})
-
-response, content = http.request(url, 'POST', params,
-       headers={'Content-type': 'application/x-www-form-urlencoded', 'X-Auth-Token': sys.argv[1]}
-)
-
-if response['status'] == '200':
-       print 'OK'
-       sys.exit(0)
-else:
-       print response, content
-       sys.exit(-1)
diff --git a/pithos/im/__init__.py b/pithos/im/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/pithos/im/api.py b/pithos/im/api.py
deleted file mode 100644 (file)
index 3286324..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from traceback import format_exc
-from time import time, mktime
-from django.conf import settings
-from django.http import HttpResponse
-from django.utils import simplejson as json
-
-from pithos.im.faults import BadRequest, Unauthorized, ServiceUnavailable
-from pithos.im.models import User
-
-import datetime
-
-def render_fault(request, fault):
-    if settings.DEBUG or settings.TEST:
-        fault.details = format_exc(fault)
-    
-    request.serialization = 'text'
-    data = '\n'.join((fault.message, fault.details)) + '\n'
-    response = HttpResponse(data, status=fault.code)
-    return response
-
-def update_response_headers(response):
-    response['Content-Type'] = 'application/json; charset=UTF-8'
-    response['Content-Length'] = len(response.content)
-
-def authenticate(request):
-    # Normal Response Codes: 204
-    # Error Response Codes: serviceUnavailable (503)
-    #                       badRequest (400)
-    #                       unauthorised (401)
-    try:
-        if request.method != 'GET':
-            raise BadRequest('Method not allowed.')
-        x_auth_token = request.META.get('HTTP_X_AUTH_TOKEN')
-        if not x_auth_token:
-            return render_fault(request, BadRequest('Missing X-Auth-Token'))
-        
-        try:
-            user = User.objects.get(auth_token=x_auth_token)
-        except User.DoesNotExist, e:
-            return render_fault(request, Unauthorized('Invalid X-Auth-Token')) 
-        
-        # Check if the is active.
-        if user.state != 'ACTIVE':
-            return render_fault(request, Unauthorized('User inactive'))
-        
-        # Check if the token has expired.
-        if (time() - mktime(user.auth_token_expires.timetuple())) > 0:
-            return render_fault(request, Unauthorized('Authentication expired'))
-        
-        response = HttpResponse()
-        response.status=204
-        user_info = user.__dict__
-        for k,v in user_info.items():
-            if isinstance(v,  datetime.datetime):
-                user_info[k] = v.strftime('%a, %d-%b-%Y %H:%M:%S %Z')
-        user_info.pop('_state')
-        response.content = json.dumps(user_info)
-        update_response_headers(response)
-        return response
-    except BaseException, e:
-        fault = ServiceUnavailable('Unexpected error')
-        return render_fault(request, fault)
\ No newline at end of file
diff --git a/pithos/im/faults.py b/pithos/im/faults.py
deleted file mode 100644 (file)
index 1975468..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-def camelCase(s):
-    return s[0].lower() + s[1:]
-
-class Fault(Exception):
-    def __init__(self, message='', details='', name=''):
-        Exception.__init__(self, message, details, name)
-        self.message = message
-        self.details = details
-        self.name = name or camelCase(self.__class__.__name__)
-
-class BadRequest(Fault):
-    code = 400
-
-class Unauthorized(Fault):
-    code = 401
-
-class ServiceUnavailable(Fault):
-    code = 503
\ No newline at end of file
diff --git a/pithos/im/fixtures/admin_user.json b/pithos/im/fixtures/admin_user.json
deleted file mode 100644 (file)
index 362dcc3..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-[
-    {
-        "model": "im.User",
-        "pk": 1,
-        "fields": {
-            "uniq": "admin",
-            "level": 0,
-            "invitations": 10000,
-                       "is_admin": true,
-            "auth_token": "0000",
-            "auth_token_created": "2011-09-11 09:17:14",
-            "auth_token_expires": "2012-09-11 09:17:14",
-            "created": "2011-09-11",
-            "updated": "2011-09-11"
-           }
-    }
-]
diff --git a/pithos/im/fixtures/auth_test_data.json b/pithos/im/fixtures/auth_test_data.json
deleted file mode 100644 (file)
index 81235fa..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-[
-    {
-        "model": "im.User",
-        "pk": 1,
-        "fields": {
-            "uniq": "test",
-            "level": 0,
-            "invitations": 10000,
-            "auth_token": "0000",
-            "auth_token_created": "2011-04-07 09:17:14",
-            "auth_token_expires": "2015-04-07 09:17:14",
-            "created": "2011-02-06",
-            "updated": "2011-02-06"
-           }
-    },
-    {
-        "model": "im.User",
-        "pk": 2,
-        "fields": {
-            "uniq": "verigak",
-            "level": 1,
-            "invitations": 3,
-            "is_admin": 1,
-            "auth_token": "0001",
-            "auth_token_created": "2011-04-07 09:17:14",
-            "auth_token_expires": "2015-04-07 09:17:14",
-            "created": "2011-02-06",
-            "updated": "2011-02-06"
-           }
-    },
-    {
-        "model": "im.User",
-        "pk": 3,
-        "fields": {
-            "uniq": "chazapis",
-            "level": 1,
-            "invitations": 3,
-            "auth_token": "0002",
-            "auth_token_created": "2011-04-07 09:17:14",
-            "auth_token_expires": "2015-04-07 09:17:14",
-            "created": "2011-02-06",
-            "updated": "2011-02-06"
-           }
-    },
-    {
-        "model": "im.User",
-        "pk": 4,
-        "fields": {
-            "uniq": "gtsouk",
-            "level": 1,
-            "invitations": 3,
-            "auth_token": "0003",
-            "auth_token_created": "2011-04-07 09:17:14",
-            "auth_token_expires": "2015-04-07 09:17:14",
-            "created": "2011-02-06",
-            "updated": "2011-02-06"
-           }
-    },
-    {
-        "model": "im.User",
-        "pk": 5,
-        "fields": {
-            "uniq": "papagian",
-            "level": 1,
-            "invitations": 3,
-            "auth_token": "0004",
-            "auth_token_created": "2011-04-07 09:17:14",
-            "auth_token_expires": "2015-04-07 09:17:14",
-            "created": "2011-02-06",
-            "updated": "2011-02-06"
-           }
-    },
-    {
-        "model": "im.User",
-        "pk": 6,
-        "fields": {
-            "uniq": "louridas",
-            "level": 1,
-            "invitations": 3,
-            "auth_token": "0005",
-            "auth_token_created": "2011-04-07 09:17:14",
-            "auth_token_expires": "2015-04-07 09:17:14",
-            "created": "2011-02-06",
-            "updated": "2011-02-06"
-           }
-    },
-    {
-        "model": "im.User",
-        "pk": 7,
-        "fields": {
-            "uniq": "chstath",
-            "level": 1,
-            "invitations": 3,
-            "auth_token": "0006",
-            "auth_token_created": "2011-04-07 09:17:14",
-            "auth_token_expires": "2015-04-07 09:17:14",
-            "created": "2011-02-06",
-            "updated": "2011-02-06"
-           }
-    },
-    {
-        "model": "im.User",
-        "pk": 8,
-        "fields": {
-            "uniq": "pkanavos",
-            "level": 1,
-            "invitations": 3,
-            "auth_token": "0007",
-            "auth_token_created": "2011-04-07 09:17:14",
-            "auth_token_expires": "2015-04-07 09:17:14",
-            "created": "2011-02-06",
-            "updated": "2011-02-06"
-           }
-    },
-    {
-        "model": "im.User",
-        "pk": 9,
-        "fields": {
-            "uniq": "mvasilak",
-            "level": 1,
-            "invitations": 3,
-            "auth_token": "0008",
-            "auth_token_created": "2011-04-07 09:17:14",
-            "auth_token_expires": "2015-04-07 09:17:14",
-            "created": "2011-02-06",
-            "updated": "2011-02-06"
-           }
-    },
-    {
-        "model": "im.User",
-        "pk": 10,
-        "fields": {
-            "uniq": "διογένης",
-            "level": 2,
-            "invitations": 2,
-            "auth_token": "0009",
-            "auth_token_created": "2011-04-07 09:17:14",
-            "auth_token_expires": "2015-04-07 09:17:14",
-            "created": "2011-02-06",
-            "updated": "2011-02-06"
-           }
-    }
-]
diff --git a/pithos/im/forms.py b/pithos/im/forms.py
deleted file mode 100644 (file)
index 6682522..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from django import forms
-from django.utils.translation import ugettext as _
-from django.conf import settings
-
-from pithos.im.models import User
-
-openid_providers = (
-('Google','https://www.google.com/accounts/o8/id'),
-('Yahoo', 'http://yahoo.com/'),
-('AOL','http://openid.aol.com/%s/'),
-('OpenID', None),
-('MyOpenID','http://%s.myopenid.com/'),
-('LiveJournal', 'http://%s.livejournal.com/'),
-('Flickr', 'http://flickr.com/%s/'),
-('Technorati', 'http://technorati.com/people/technorati/%s/'),
-('Wordpress', 'http://%s.wordpress.com/'),
-('Blogger', 'http://%s.blogspot.com/'),
-('Verisign', 'http://%s.pip.verisignlabs.com/'),
-('Vidoop', 'http://%s.myvidoop.com/'),
-('ClaimID','http://claimid.com/%s')    
-)
-
-class RegisterForm(forms.Form):
-    uniq = forms.CharField(widget=forms.widgets.TextInput())
-    provider = forms.CharField(widget=forms.TextInput(),
-                                label=u'Identity Provider')
-    email = forms.EmailField(widget=forms.TextInput(),
-                             label=_('Email address'))
-    realname = forms.CharField(widget=forms.TextInput(),
-                                label=u'Real Name')
-    
-    def __init__(self, *args, **kwargs):
-        super(forms.Form, self).__init__(*args, **kwargs)
-        
-        #set readonly form fields
-        self.fields['provider'].widget.attrs['readonly'] = True
-    
-    def clean_uniq(self):
-        """
-        Validate that the uniq is alphanumeric and is not already
-        in use.
-        
-        """
-        try:
-            user = User.objects.get(uniq__iexact=self.cleaned_data['uniq'])
-        except User.DoesNotExist:
-            return self.cleaned_data['uniq']
-        raise forms.ValidationError(_("A user with that uniq already exists."))
-
-class ShibbolethRegisterForm(RegisterForm):
-    pass
-
-class TwitterRegisterForm(RegisterForm):
-    pass
-
-class OpenidRegisterForm(RegisterForm):
-    openidurl = forms.ChoiceField(widget=forms.Select,
-                                  choices=((url, l) for l, url in openid_providers))
-
-class LocalRegisterForm(RegisterForm):
-    """ local signup form"""
-    password = forms.CharField(widget=forms.PasswordInput(render_value=False),
-                                label=_('Password'))
-    password2 = forms.CharField(widget=forms.PasswordInput(render_value=False),
-                                label=_('Confirm Password'))
-    
-    def __init__(self, *args, **kwargs):
-        super(LocalRegisterForm, self).__init__(*args, **kwargs)
-    
-    def clean_uniq(self):
-        """
-        Validate that the uniq is alphanumeric and is not already
-        in use.
-        
-        """
-        try:
-            user = User.objects.get(uniq__iexact=self.cleaned_data['uniq'])
-        except User.DoesNotExist:
-            return self.cleaned_data['uniq']
-        raise forms.ValidationError(_("A user with that uniq already exists."))
-    
-    def clean(self):
-        """
-        Verifiy that the values entered into the two password fields
-        match. Note that an error here will end up in
-        ``non_field_errors()`` because it doesn't apply to a single
-        field.
-        
-        """
-        if 'password' in self.cleaned_data and 'password2' in self.cleaned_data:
-            if self.cleaned_data['password'] != self.cleaned_data['password2']:
-                raise forms.ValidationError(_("The two password fields didn't match."))
-        return self.cleaned_data
-
-class InvitedRegisterForm(RegisterForm):
-    inviter = forms.CharField(widget=forms.TextInput(),
-                                label=_('Inviter Real Name'))
-    
-    def __init__(self, *args, **kwargs):
-        super(RegisterForm, self).__init__(*args, **kwargs)
-        
-        #set readonly form fields
-        self.fields['uniq'].widget.attrs['readonly'] = True
-        self.fields['inviter'].widget.attrs['readonly'] = True
-        self.fields['provider'].widget.attrs['provider'] = True
-
-class InvitedLocalRegisterForm(LocalRegisterForm, InvitedRegisterForm):
-    pass
-
-class InvitedOpenidRegisterForm(OpenidRegisterForm, InvitedRegisterForm):
-    pass
-
-class InvitedTwitterRegisterForm(TwitterRegisterForm, InvitedRegisterForm):
-    pass
-
-class InvitedShibbolethRegisterForm(ShibbolethRegisterForm, InvitedRegisterForm):
-    pass
\ No newline at end of file
diff --git a/pithos/im/interface.py b/pithos/im/interface.py
deleted file mode 100644 (file)
index 6b3d029..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from pithos.backends import connect_backend
-
-def get_quota(user):
-    backend = connect_backend()
-    quota = backend.get_account_policy(user, user)['quota']
-    backend.close()
-    return quota
-
-def set_quota(user, quota):
-    backend = connect_backend()
-    backend.update_account_policy(user, user, {'quota': quota})
-    backend.close()
-    return quota
diff --git a/pithos/im/migrations/0001_initial.py b/pithos/im/migrations/0001_initial.py
deleted file mode 100644 (file)
index 4c0b4e0..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-# encoding: utf-8
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        
-        # Adding model 'User'
-        db.create_table('im_user', (
-            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('uniq', self.gf('django.db.models.fields.CharField')(max_length=255, null=True)),
-            ('realname', self.gf('django.db.models.fields.CharField')(default='', max_length=255)),
-            ('email', self.gf('django.db.models.fields.CharField')(default='', max_length=255)),
-            ('affiliation', self.gf('django.db.models.fields.CharField')(default='', max_length=255)),
-            ('state', self.gf('django.db.models.fields.CharField')(default='ACTIVE', max_length=16)),
-            ('level', self.gf('django.db.models.fields.IntegerField')(default=4)),
-            ('invitations', self.gf('django.db.models.fields.IntegerField')(default=0)),
-            ('password', self.gf('django.db.models.fields.CharField')(default='', max_length=255)),
-            ('is_admin', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('auth_token', self.gf('django.db.models.fields.CharField')(max_length=32, null=True, blank=True)),
-            ('auth_token_created', self.gf('django.db.models.fields.DateTimeField')(null=True)),
-            ('auth_token_expires', self.gf('django.db.models.fields.DateTimeField')(null=True)),
-            ('created', self.gf('django.db.models.fields.DateTimeField')()),
-            ('updated', self.gf('django.db.models.fields.DateTimeField')()),
-        ))
-        db.send_create_signal('im', ['User'])
-
-        # Adding model 'Invitation'
-        db.create_table('im_invitation', (
-            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('inviter', self.gf('django.db.models.fields.related.ForeignKey')(related_name='invitations_sent', null=True, to=orm['im.User'])),
-            ('realname', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('uniq', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('code', self.gf('django.db.models.fields.BigIntegerField')(db_index=True)),
-            ('is_accepted', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
-            ('accepted', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
-        ))
-        db.send_create_signal('im', ['Invitation'])
-
-
-    def backwards(self, orm):
-        
-        # Deleting model 'User'
-        db.delete_table('im_user')
-
-        # Deleting model 'Invitation'
-        db.delete_table('im_invitation')
-
-
-    models = {
-        'im.invitation': {
-            'Meta': {'object_name': 'Invitation'},
-            'accepted': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'code': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True'}),
-            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'inviter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'invitations_sent'", 'null': 'True', 'to': "orm['im.User']"}),
-            'is_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'realname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'uniq': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        'im.user': {
-            'Meta': {'object_name': 'User'},
-            'affiliation': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
-            'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
-            'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
-            'created': ('django.db.models.fields.DateTimeField', [], {}),
-            'email': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'invitations': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'level': ('django.db.models.fields.IntegerField', [], {'default': '4'}),
-            'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'realname': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'state': ('django.db.models.fields.CharField', [], {'default': "'ACTIVE'", 'max_length': '16'}),
-            'uniq': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
-            'updated': ('django.db.models.fields.DateTimeField', [], {})
-        }
-    }
-
-    complete_apps = ['im']
diff --git a/pithos/im/migrations/0002_auto__add_field_user_is_verified.py b/pithos/im/migrations/0002_auto__add_field_user_is_verified.py
deleted file mode 100644 (file)
index 648739f..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-# encoding: utf-8
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        
-        # Adding field 'User.is_verified'
-        db.add_column('im_user', 'is_verified', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False)
-
-
-    def backwards(self, orm):
-        
-        # Deleting field 'User.is_verified'
-        db.delete_column('im_user', 'is_verified')
-
-
-    models = {
-        'im.invitation': {
-            'Meta': {'object_name': 'Invitation'},
-            'accepted': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'code': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True'}),
-            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'inviter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'invitations_sent'", 'null': 'True', 'to': "orm['im.User']"}),
-            'is_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'realname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'uniq': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        'im.user': {
-            'Meta': {'object_name': 'User'},
-            'affiliation': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
-            'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
-            'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
-            'created': ('django.db.models.fields.DateTimeField', [], {}),
-            'email': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'invitations': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'is_verified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'level': ('django.db.models.fields.IntegerField', [], {'default': '4'}),
-            'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'realname': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'state': ('django.db.models.fields.CharField', [], {'default': "'ACTIVE'", 'max_length': '16'}),
-            'uniq': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
-            'updated': ('django.db.models.fields.DateTimeField', [], {})
-        }
-    }
-
-    complete_apps = ['im']
diff --git a/pithos/im/migrations/0003_auto__add_field_user_provider__add_field_user_openidurl__add_field_inv.py b/pithos/im/migrations/0003_auto__add_field_user_provider__add_field_user_openidurl__add_field_inv.py
deleted file mode 100644 (file)
index 3ca4cb0..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-# encoding: utf-8
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        
-        # Adding field 'User.provider'
-        db.add_column('im_user', 'provider', self.gf('django.db.models.fields.CharField')(default='', max_length=255), keep_default=False)
-
-        # Adding field 'User.openidurl'
-        db.add_column('im_user', 'openidurl', self.gf('django.db.models.fields.CharField')(default='', max_length=255), keep_default=False)
-
-        # Adding field 'Invitation.is_consumed'
-        db.add_column('im_invitation', 'is_consumed', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False)
-
-        # Adding field 'Invitation.consumed'
-        db.add_column('im_invitation', 'consumed', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True), keep_default=False)
-
-
-    def backwards(self, orm):
-        
-        # Deleting field 'User.provider'
-        db.delete_column('im_user', 'provider')
-
-        # Deleting field 'User.openidurl'
-        db.delete_column('im_user', 'openidurl')
-
-        # Deleting field 'Invitation.is_consumed'
-        db.delete_column('im_invitation', 'is_consumed')
-
-        # Deleting field 'Invitation.consumed'
-        db.delete_column('im_invitation', 'consumed')
-
-
-    models = {
-        'im.invitation': {
-            'Meta': {'object_name': 'Invitation'},
-            'accepted': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'code': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True'}),
-            'consumed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'inviter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'invitations_sent'", 'null': 'True', 'to': "orm['im.User']"}),
-            'is_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'is_consumed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'realname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'uniq': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        'im.user': {
-            'Meta': {'object_name': 'User'},
-            'affiliation': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
-            'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
-            'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
-            'created': ('django.db.models.fields.DateTimeField', [], {}),
-            'email': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'invitations': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'is_verified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'level': ('django.db.models.fields.IntegerField', [], {'default': '4'}),
-            'openidurl': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'provider': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'realname': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
-            'state': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '16'}),
-            'uniq': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
-            'updated': ('django.db.models.fields.DateTimeField', [], {})
-        }
-    }
-
-    complete_apps = ['im']
diff --git a/pithos/im/migrations/__init__.py b/pithos/im/migrations/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/pithos/im/models.py b/pithos/im/models.py
deleted file mode 100644 (file)
index 0fbac27..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-import logging
-import hashlib
-
-from time import asctime
-from datetime import datetime, timedelta
-from base64 import b64encode
-
-from django.conf import settings
-from django.db import models
-
-from pithos.im.interface import get_quota, set_quota
-
-from hashlib import new as newhasher
-
-class User(models.Model):
-    ACCOUNT_STATE = (
-        ('ACTIVE', 'Active'),
-        ('DELETED', 'Deleted'),
-        ('SUSPENDED', 'Suspended'),
-        ('UNVERIFIED', 'Unverified'),
-        ('PENDING', 'Pending')
-    )
-    
-    uniq = models.CharField('Unique ID', max_length=255, null=True)
-    
-    realname = models.CharField('Real Name', max_length=255, default='')
-    email = models.CharField('Email', max_length=255, default='')
-    affiliation = models.CharField('Affiliation', max_length=255, default='')
-    provider = models.CharField('Provider', max_length=255, default='')
-    state = models.CharField('Account state', choices=ACCOUNT_STATE,
-                                max_length=16, default='PENDING')
-    
-    #for invitations
-    level = models.IntegerField('Inviter level', default=4)
-    invitations = models.IntegerField('Invitations left', default=0)
-    
-    #for local
-    password = models.CharField('Password', max_length=255, default='')
-    
-    is_admin = models.BooleanField('Admin?', default=False)
-    
-    auth_token = models.CharField('Authentication Token', max_length=32,
-                                    null=True, blank=True)
-    auth_token_created = models.DateTimeField('Token creation date',
-                                                null=True)
-    auth_token_expires = models.DateTimeField('Token expiration date',
-                                                null=True)
-    
-    created = models.DateTimeField('Creation date')
-    updated = models.DateTimeField('Update date')
-    
-    is_verified = models.BooleanField('Verified?', default=False)
-    
-    openidurl = models.CharField('OpenID url', max_length=255, default='')
-    
-    @property
-    def quota(self):
-        return get_quota(self.uniq)
-
-    @quota.setter
-    def quota(self, value):
-        set_quota(self.uniq, value)
-    
-    @property
-    def invitation(self):
-        try:
-            return Invitation.objects.get(uniq=self.uniq)
-        except Invitation.DoesNotExist:
-            return None
-    
-    def save(self, update_timestamps=True, **kwargs):
-        if update_timestamps:
-            if not self.id:
-                self.created = datetime.now()
-            self.updated = datetime.now()
-        
-        super(User, self).save(**kwargs)
-        
-        #invitation consume
-        if self.invitation and not self.invitation.is_consumed:
-            self.invitation.consume()
-    
-    def renew_token(self):
-        md5 = hashlib.md5()
-        md5.update(self.uniq)
-        md5.update(self.realname.encode('ascii', 'ignore'))
-        md5.update(asctime())
-        
-        self.auth_token = b64encode(md5.digest())
-        self.auth_token_created = datetime.now()
-        self.auth_token_expires = self.auth_token_created + \
-                                  timedelta(hours=settings.AUTH_TOKEN_DURATION)
-    
-    def __unicode__(self):
-        return self.uniq
-
-class Invitation(models.Model):
-    inviter = models.ForeignKey(User, related_name='invitations_sent',
-                                null=True)
-    realname = models.CharField('Real name', max_length=255)
-    uniq = models.CharField('Unique ID', max_length=255)
-    code = models.BigIntegerField('Invitation code', db_index=True)
-    #obsolete: we keep it just for transfering the data
-    is_accepted = models.BooleanField('Accepted?', default=False)
-    is_consumed = models.BooleanField('Consumed?', default=False)
-    created = models.DateTimeField('Creation date', auto_now_add=True)
-    #obsolete: we keep it just for transfering the data
-    accepted = models.DateTimeField('Acceptance date', null=True, blank=True)
-    consumed = models.DateTimeField('Consumption date', null=True, blank=True)
-    
-    def consume(self):
-        self.is_consumed = True
-        self.consumed = datetime.now()
-        self.save()
-        
-    def __unicode__(self):
-        return '%s -> %s [%d]' % (self.inviter, self.uniq, self.code)
diff --git a/pithos/im/static/banner.png b/pithos/im/static/banner.png
deleted file mode 100644 (file)
index 92f537d..0000000
Binary files a/pithos/im/static/banner.png and /dev/null differ
diff --git a/pithos/im/static/bootstrap.css b/pithos/im/static/bootstrap.css
deleted file mode 100644 (file)
index f1a5cc7..0000000
+++ /dev/null
@@ -1,2362 +0,0 @@
-/*!
- * Bootstrap v1.3.0
- *
- * Copyright 2011 Twitter, Inc
- * Licensed under the Apache License v2.0
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Designed and built with all the love in the world @twitter by @mdo and @fat.
- * Date: Thu Sep 22 12:52:42 PDT 2011
- */
-/* Reset.less
- * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here      that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc).
- * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
-html, body {
-  margin: 0;
-  padding: 0;
-}
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-p,
-blockquote,
-pre,
-a,
-abbr,
-acronym,
-address,
-cite,
-code,
-del,
-dfn,
-em,
-img,
-q,
-s,
-samp,
-small,
-strike,
-strong,
-sub,
-sup,
-tt,
-var,
-dd,
-dl,
-dt,
-li,
-ol,
-ul,
-fieldset,
-form,
-label,
-legend,
-button,
-table,
-caption,
-tbody,
-tfoot,
-thead,
-tr,
-th,
-td {
-  margin: 0;
-  padding: 0;
-  border: 0;
-  font-weight: normal;
-  font-style: normal;
-  font-size: 100%;
-  line-height: 1;
-  font-family: inherit;
-}
-table {
-  border-collapse: collapse;
-  border-spacing: 0;
-}
-ol, ul {
-  list-style: none;
-}
-q:before,
-q:after,
-blockquote:before,
-blockquote:after {
-  content: "";
-}
-html {
-  overflow-y: scroll;
-  font-size: 100%;
-  -webkit-text-size-adjust: 100%;
-  -ms-text-size-adjust: 100%;
-}
-a:focus {
-  outline: thin dotted;
-}
-a:hover, a:active {
-  outline: 0;
-}
-article,
-aside,
-details,
-figcaption,
-figure,
-footer,
-header,
-hgroup,
-nav,
-section {
-  display: block;
-}
-audio, canvas, video {
-  display: inline-block;
-  *display: inline;
-  *zoom: 1;
-}
-audio:not([controls]) {
-  display: none;
-}
-sub, sup {
-  font-size: 75%;
-  line-height: 0;
-  position: relative;
-  vertical-align: baseline;
-}
-sup {
-  top: -0.5em;
-}
-sub {
-  bottom: -0.25em;
-}
-img {
-  border: 0;
-  -ms-interpolation-mode: bicubic;
-}
-button,
-input,
-select,
-textarea {
-  font-size: 100%;
-  margin: 0;
-  vertical-align: baseline;
-  *vertical-align: middle;
-}
-button, input {
-  line-height: normal;
-  *overflow: visible;
-}
-button::-moz-focus-inner, input::-moz-focus-inner {
-  border: 0;
-  padding: 0;
-}
-button,
-input[type="button"],
-input[type="reset"],
-input[type="submit"] {
-  cursor: pointer;
-  -webkit-appearance: button;
-}
-input[type="search"] {
-  -webkit-appearance: textfield;
-  -webkit-box-sizing: content-box;
-  -moz-box-sizing: content-box;
-  box-sizing: content-box;
-}
-input[type="search"]::-webkit-search-decoration {
-  -webkit-appearance: none;
-}
-textarea {
-  overflow: auto;
-  vertical-align: top;
-}
-/* Variables.less
- * Variables to customize the look and feel of Bootstrap
- * ----------------------------------------------------- */
-/* Variables.less
- * Snippets of reusable CSS to develop faster and keep code readable
- * ----------------------------------------------------------------- */
-/*
- * Scaffolding
- * Basic and global styles for generating a grid system, structural layout, and page templates
- * ------------------------------------------------------------------------------------------- */
-html, body {
-  background-color: #ffffff;
-}
-body {
-  margin: 0;
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-  font-size: 13px;
-  font-weight: normal;
-  line-height: 18px;
-  color: #404040;
-}
-.container {
-  width: 940px;
-  margin-left: auto;
-  margin-right: auto;
-  zoom: 1;
-}
-.container:before, .container:after {
-  display: table;
-  content: "";
-  zoom: 1;
-  *display: inline;
-}
-.container:after {
-  clear: both;
-}
-.container-fluid {
-  position: relative;
-  min-width: 940px;
-  padding-left: 20px;
-  padding-right: 20px;
-  zoom: 1;
-}
-.container-fluid:before, .container-fluid:after {
-  display: table;
-  content: "";
-  zoom: 1;
-  *display: inline;
-}
-.container-fluid:after {
-  clear: both;
-}
-.container-fluid > .sidebar {
-  float: left;
-  width: 220px;
-}
-.container-fluid > .content {
-  margin-left: 240px;
-}
-a {
-  color: #0069d6;
-  text-decoration: none;
-  line-height: inherit;
-  font-weight: inherit;
-}
-a:hover {
-  color: #00438a;
-  text-decoration: underline;
-}
-.pull-right {
-  float: right;
-}
-.pull-left {
-  float: left;
-}
-.hide {
-  display: none;
-}
-.show {
-  display: block;
-}
-.row {
-  zoom: 1;
-  margin-left: -20px;
-}
-.row:before, .row:after {
-  display: table;
-  content: "";
-  zoom: 1;
-  *display: inline;
-}
-.row:after {
-  clear: both;
-}
-[class*="span"] {
-  display: inline;
-  float: left;
-  margin-left: 20px;
-}
-.span1 {
-  width: 40px;
-}
-.span2 {
-  width: 100px;
-}
-.span3 {
-  width: 160px;
-}
-.span4 {
-  width: 220px;
-}
-.span5 {
-  width: 280px;
-}
-.span6 {
-  width: 340px;
-}
-.span7 {
-  width: 400px;
-}
-.span8 {
-  width: 460px;
-}
-.span9 {
-  width: 520px;
-}
-.span10 {
-  width: 580px;
-}
-.span11 {
-  width: 640px;
-}
-.span12 {
-  width: 700px;
-}
-.span13 {
-  width: 760px;
-}
-.span14 {
-  width: 820px;
-}
-.span15 {
-  width: 880px;
-}
-.span16 {
-  width: 940px;
-}
-.span17 {
-  width: 1000px;
-}
-.span18 {
-  width: 1060px;
-}
-.span19 {
-  width: 1120px;
-}
-.span20 {
-  width: 1180px;
-}
-.span21 {
-  width: 1240px;
-}
-.span22 {
-  width: 1300px;
-}
-.span23 {
-  width: 1360px;
-}
-.span24 {
-  width: 1420px;
-}
-.offset1 {
-  margin-left: 80px;
-}
-.offset2 {
-  margin-left: 140px;
-}
-.offset3 {
-  margin-left: 200px;
-}
-.offset4 {
-  margin-left: 260px;
-}
-.offset5 {
-  margin-left: 320px;
-}
-.offset6 {
-  margin-left: 380px;
-}
-.offset7 {
-  margin-left: 440px;
-}
-.offset8 {
-  margin-left: 500px;
-}
-.offset9 {
-  margin-left: 560px;
-}
-.offset10 {
-  margin-left: 620px;
-}
-.offset11 {
-  margin-left: 680px;
-}
-.offset12 {
-  margin-left: 740px;
-}
-.span-one-third {
-  width: 300px;
-}
-.span-two-thirds {
-  width: 620px;
-}
-.offset-one-third {
-  margin-left: 340px;
-}
-.offset-two-thirds {
-  margin-left: 660px;
-}
-/* Typography.less
- * Headings, body text, lists, code, and more for a versatile and durable typography system
- * ---------------------------------------------------------------------------------------- */
-p {
-  font-size: 13px;
-  font-weight: normal;
-  line-height: 18px;
-  margin-bottom: 9px;
-}
-p small {
-  font-size: 11px;
-  color: #bfbfbf;
-}
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
-  font-weight: bold;
-  color: #404040;
-}
-h1 small,
-h2 small,
-h3 small,
-h4 small,
-h5 small,
-h6 small {
-  color: #bfbfbf;
-}
-h1 {
-  margin-bottom: 18px;
-  font-size: 30px;
-  line-height: 36px;
-}
-h1 small {
-  font-size: 18px;
-}
-h2 {
-  font-size: 24px;
-  line-height: 36px;
-}
-h2 small {
-  font-size: 14px;
-}
-h3,
-h4,
-h5,
-h6 {
-  line-height: 36px;
-}
-h3 {
-  font-size: 18px;
-}
-h3 small {
-  font-size: 14px;
-}
-h4 {
-  font-size: 16px;
-}
-h4 small {
-  font-size: 12px;
-}
-h5 {
-  font-size: 14px;
-}
-h6 {
-  font-size: 13px;
-  color: #bfbfbf;
-  text-transform: uppercase;
-}
-ul, ol {
-  margin: 0 0 18px 25px;
-}
-ul ul,
-ul ol,
-ol ol,
-ol ul {
-  margin-bottom: 0;
-}
-ul {
-  list-style: disc;
-}
-ol {
-  list-style: decimal;
-}
-li {
-  line-height: 18px;
-  color: #808080;
-}
-ul.unstyled {
-  list-style: none;
-  margin-left: 0;
-}
-dl {
-  margin-bottom: 18px;
-}
-dl dt, dl dd {
-  line-height: 18px;
-}
-dl dt {
-  font-weight: bold;
-}
-dl dd {
-  margin-left: 9px;
-}
-hr {
-  margin: 20px 0 19px;
-  border: 0;
-  border-bottom: 1px solid #eee;
-}
-strong {
-  font-style: inherit;
-  font-weight: bold;
-}
-em {
-  font-style: italic;
-  font-weight: inherit;
-  line-height: inherit;
-}
-.muted {
-  color: #bfbfbf;
-}
-blockquote {
-  margin-bottom: 18px;
-  border-left: 5px solid #eee;
-  padding-left: 15px;
-}
-blockquote p {
-  font-size: 14px;
-  font-weight: 300;
-  line-height: 18px;
-  margin-bottom: 0;
-}
-blockquote small {
-  display: block;
-  font-size: 12px;
-  font-weight: 300;
-  line-height: 18px;
-  color: #bfbfbf;
-}
-blockquote small:before {
-  content: '\2014 \00A0';
-}
-address {
-  display: block;
-  line-height: 18px;
-  margin-bottom: 18px;
-}
-code, pre {
-  padding: 0 3px 2px;
-  font-family: Monaco, Andale Mono, Courier New, monospace;
-  font-size: 12px;
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
-}
-code {
-  background-color: #fee9cc;
-  color: rgba(0, 0, 0, 0.75);
-  padding: 1px 3px;
-}
-pre {
-  background-color: #f5f5f5;
-  display: block;
-  padding: 8.5px;
-  margin: 0 0 18px;
-  line-height: 18px;
-  font-size: 12px;
-  border: 1px solid #ccc;
-  border: 1px solid rgba(0, 0, 0, 0.15);
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
-  white-space: pre;
-  white-space: pre-wrap;
-  word-wrap: break-word;
-}
-/* Forms.less
- * Base styles for various input types, form layouts, and states
- * ------------------------------------------------------------- */
-form {
-  margin-bottom: 18px;
-}
-fieldset {
-  margin-bottom: 18px;
-  padding-top: 18px;
-}
-fieldset legend {
-  display: block;
-  padding-left: 150px;
-  font-size: 19.5px;
-  line-height: 1;
-  color: #404040;
-  *padding: 0 0 5px 145px;
-  /* IE6-7 */
-
-  *line-height: 1.5;
-  /* IE6-7 */
-
-}
-form .clearfix {
-  margin-bottom: 18px;
-  zoom: 1;
-}
-form .clearfix:before, form .clearfix:after {
-  display: table;
-  content: "";
-  zoom: 1;
-  *display: inline;
-}
-form .clearfix:after {
-  clear: both;
-}
-label,
-input,
-select,
-textarea {
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-  font-size: 13px;
-  font-weight: normal;
-  line-height: normal;
-}
-label {
-  padding-top: 6px;
-  font-size: 13px;
-  line-height: 18px;
-  float: left;
-  width: 130px;
-  text-align: right;
-  color: #404040;
-}
-form .input {
-  margin-left: 150px;
-}
-input[type=checkbox], input[type=radio] {
-  cursor: pointer;
-}
-input,
-textarea,
-select,
-.uneditable-input {
-  display: inline-block;
-  width: 210px;
-  height: 18px;
-  padding: 4px;
-  font-size: 13px;
-  line-height: 18px;
-  color: #808080;
-  border: 1px solid #ccc;
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
-}
-/* mini reset for non-html5 file types */
-input[type=checkbox], input[type=radio] {
-  width: auto;
-  height: auto;
-  padding: 0;
-  margin: 3px 0;
-  *margin-top: 0;
-  /* IE6-7 */
-
-  line-height: normal;
-  border: none;
-}
-input[type=file] {
-  background-color: #ffffff;
-  padding: initial;
-  border: initial;
-  line-height: initial;
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-}
-input[type=button], input[type=reset], input[type=submit] {
-  width: auto;
-  height: auto;
-}
-select, input[type=file] {
-  height: 27px;
-  line-height: 27px;
-  *margin-top: 4px;
-  /* For IE7, add top margin to align select with labels */
-
-}
-select[multiple] {
-  height: inherit;
-}
-textarea {
-  height: auto;
-}
-.uneditable-input {
-  background-color: #ffffff;
-  display: block;
-  border-color: #eee;
-  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
-  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
-  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
-  cursor: not-allowed;
-}
-:-moz-placeholder {
-  color: #bfbfbf;
-}
-::-webkit-input-placeholder {
-  color: #bfbfbf;
-}
-input, textarea {
-  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
-  -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
-  -ms-transition: border linear 0.2s, box-shadow linear 0.2s;
-  -o-transition: border linear 0.2s, box-shadow linear 0.2s;
-  transition: border linear 0.2s, box-shadow linear 0.2s;
-  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
-  -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
-  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
-}
-input:focus, textarea:focus {
-  outline: 0;
-  border-color: rgba(82, 168, 236, 0.8);
-  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
-  -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
-  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
-}
-input[type=file]:focus, input[type=checkbox]:focus, select:focus {
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-  outline: 1px dotted #666;
-}
-form div.clearfix.error {
-  background: #fae5e3;
-  padding: 10px 0;
-  margin: -10px 0 10px;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
-}
-form div.clearfix.error > label, form div.clearfix.error span.help-inline, form div.clearfix.error span.help-block {
-  color: #9d261d;
-}
-form div.clearfix.error input, form div.clearfix.error textarea {
-  border-color: #c87872;
-  -webkit-box-shadow: 0 0 3px rgba(171, 41, 32, 0.25);
-  -moz-box-shadow: 0 0 3px rgba(171, 41, 32, 0.25);
-  box-shadow: 0 0 3px rgba(171, 41, 32, 0.25);
-}
-form div.clearfix.error input:focus, form div.clearfix.error textarea:focus {
-  border-color: #b9554d;
-  -webkit-box-shadow: 0 0 6px rgba(171, 41, 32, 0.5);
-  -moz-box-shadow: 0 0 6px rgba(171, 41, 32, 0.5);
-  box-shadow: 0 0 6px rgba(171, 41, 32, 0.5);
-}
-form div.clearfix.error .input-prepend span.add-on, form div.clearfix.error .input-append span.add-on {
-  background: #f4c8c5;
-  border-color: #c87872;
-  color: #b9554d;
-}
-.input-mini,
-input.mini,
-textarea.mini,
-select.mini {
-  width: 60px;
-}
-.input-small,
-input.small,
-textarea.small,
-select.small {
-  width: 90px;
-}
-.input-medium,
-input.medium,
-textarea.medium,
-select.medium {
-  width: 150px;
-}
-.input-large,
-input.large,
-textarea.large,
-select.large {
-  width: 210px;
-}
-.input-xlarge,
-input.xlarge,
-textarea.xlarge,
-select.xlarge {
-  width: 270px;
-}
-.input-xxlarge,
-input.xxlarge,
-textarea.xxlarge,
-select.xxlarge {
-  width: 530px;
-}
-textarea.xxlarge {
-  overflow-y: auto;
-}
-input.span1, textarea.span1, select.span1 {
-  display: inline-block;
-  float: none;
-  width: 30px;
-  margin-left: 0;
-}
-input.span2, textarea.span2, select.span2 {
-  display: inline-block;
-  float: none;
-  width: 90px;
-  margin-left: 0;
-}
-input.span3, textarea.span3, select.span3 {
-  display: inline-block;
-  float: none;
-  width: 150px;
-  margin-left: 0;
-}
-input.span4, textarea.span4, select.span4 {
-  display: inline-block;
-  float: none;
-  width: 210px;
-  margin-left: 0;
-}
-input.span5, textarea.span5, select.span5 {
-  display: inline-block;
-  float: none;
-  width: 270px;
-  margin-left: 0;
-}
-input.span6, textarea.span6, select.span6 {
-  display: inline-block;
-  float: none;
-  width: 330px;
-  margin-left: 0;
-}
-input.span7, textarea.span7, select.span7 {
-  display: inline-block;
-  float: none;
-  width: 390px;
-  margin-left: 0;
-}
-input.span8, textarea.span8, select.span8 {
-  display: inline-block;
-  float: none;
-  width: 450px;
-  margin-left: 0;
-}
-input.span9, textarea.span9, select.span9 {
-  display: inline-block;
-  float: none;
-  width: 510px;
-  margin-left: 0;
-}
-input.span10, textarea.span10, select.span10 {
-  display: inline-block;
-  float: none;
-  width: 570px;
-  margin-left: 0;
-}
-input.span11, textarea.span11, select.span11 {
-  display: inline-block;
-  float: none;
-  width: 630px;
-  margin-left: 0;
-}
-input.span12, textarea.span12, select.span12 {
-  display: inline-block;
-  float: none;
-  width: 690px;
-  margin-left: 0;
-}
-input.span13, textarea.span13, select.span13 {
-  display: inline-block;
-  float: none;
-  width: 750px;
-  margin-left: 0;
-}
-input.span14, textarea.span14, select.span14 {
-  display: inline-block;
-  float: none;
-  width: 810px;
-  margin-left: 0;
-}
-input.span15, textarea.span15, select.span15 {
-  display: inline-block;
-  float: none;
-  width: 870px;
-  margin-left: 0;
-}
-input.span16, textarea.span16, select.span16 {
-  display: inline-block;
-  float: none;
-  width: 930px;
-  margin-left: 0;
-}
-input[disabled],
-select[disabled],
-textarea[disabled],
-input[readonly],
-select[readonly],
-textarea[readonly] {
-  background-color: #f5f5f5;
-  border-color: #ddd;
-  cursor: not-allowed;
-}
-.actions {
-  background: #f5f5f5;
-  margin-top: 18px;
-  margin-bottom: 18px;
-  padding: 17px 20px 18px 150px;
-  border-top: 1px solid #ddd;
-  -webkit-border-radius: 0 0 3px 3px;
-  -moz-border-radius: 0 0 3px 3px;
-  border-radius: 0 0 3px 3px;
-}
-.actions .secondary-action {
-  float: right;
-}
-.actions .secondary-action a {
-  line-height: 30px;
-}
-.actions .secondary-action a:hover {
-  text-decoration: underline;
-}
-.help-inline, .help-block {
-  font-size: 11px;
-  line-height: 18px;
-  color: #bfbfbf;
-}
-.help-inline {
-  padding-left: 5px;
-  *position: relative;
-  /* IE6-7 */
-
-  *top: -5px;
-  /* IE6-7 */
-
-}
-.help-block {
-  display: block;
-  max-width: 600px;
-}
-.inline-inputs {
-  color: #808080;
-}
-.inline-inputs span, .inline-inputs input {
-  display: inline-block;
-}
-.inline-inputs input.mini {
-  width: 60px;
-}
-.inline-inputs input.small {
-  width: 90px;
-}
-.inline-inputs span {
-  padding: 0 2px 0 1px;
-}
-.input-prepend input, .input-append input {
-  -webkit-border-radius: 0 3px 3px 0;
-  -moz-border-radius: 0 3px 3px 0;
-  border-radius: 0 3px 3px 0;
-}
-.input-prepend .add-on, .input-append .add-on {
-  position: relative;
-  background: #f5f5f5;
-  border: 1px solid #ccc;
-  z-index: 2;
-  float: left;
-  display: block;
-  width: auto;
-  min-width: 16px;
-  height: 18px;
-  padding: 4px 4px 4px 5px;
-  margin-right: -1px;
-  font-weight: normal;
-  line-height: 18px;
-  color: #bfbfbf;
-  text-align: center;
-  text-shadow: 0 1px 0 #ffffff;
-  -webkit-border-radius: 3px 0 0 3px;
-  -moz-border-radius: 3px 0 0 3px;
-  border-radius: 3px 0 0 3px;
-}
-.input-prepend .active, .input-append .active {
-  background: #a9dba9;
-  border-color: #46a546;
-}
-.input-prepend .add-on {
-  *margin-top: 1px;
-  /* IE6-7 */
-
-}
-.input-append input {
-  float: left;
-  -webkit-border-radius: 3px 0 0 3px;
-  -moz-border-radius: 3px 0 0 3px;
-  border-radius: 3px 0 0 3px;
-}
-.input-append .add-on {
-  -webkit-border-radius: 0 3px 3px 0;
-  -moz-border-radius: 0 3px 3px 0;
-  border-radius: 0 3px 3px 0;
-  margin-right: 0;
-  margin-left: -1px;
-}
-.inputs-list {
-  margin: 0 0 5px;
-  width: 100%;
-}
-.inputs-list li {
-  display: block;
-  padding: 0;
-  width: 100%;
-}
-.inputs-list label {
-  display: block;
-  float: none;
-  width: auto;
-  padding: 0;
-  line-height: 18px;
-  text-align: left;
-  white-space: normal;
-}
-.inputs-list label strong {
-  color: #808080;
-}
-.inputs-list label small {
-  font-size: 11px;
-  font-weight: normal;
-}
-.inputs-list .inputs-list {
-  margin-left: 25px;
-  margin-bottom: 10px;
-  padding-top: 0;
-}
-.inputs-list:first-child {
-  padding-top: 6px;
-}
-.inputs-list li + li {
-  padding-top: 2px;
-}
-.inputs-list input[type=radio], .inputs-list input[type=checkbox] {
-  margin-bottom: 0;
-}
-.form-stacked {
-  padding-left: 20px;
-}
-.form-stacked fieldset {
-  padding-top: 9px;
-}
-.form-stacked legend {
-  padding-left: 0;
-}
-.form-stacked label {
-  display: block;
-  float: none;
-  width: auto;
-  font-weight: bold;
-  text-align: left;
-  line-height: 20px;
-  padding-top: 0;
-}
-.form-stacked .clearfix {
-  margin-bottom: 9px;
-}
-.form-stacked .clearfix div.input {
-  margin-left: 0;
-}
-.form-stacked .inputs-list {
-  margin-bottom: 0;
-}
-.form-stacked .inputs-list li {
-  padding-top: 0;
-}
-.form-stacked .inputs-list li label {
-  font-weight: normal;
-  padding-top: 0;
-}
-.form-stacked div.clearfix.error {
-  padding-top: 10px;
-  padding-bottom: 10px;
-  padding-left: 10px;
-  margin-top: 0;
-  margin-left: -10px;
-}
-.form-stacked .actions {
-  margin-left: -20px;
-  padding-left: 20px;
-}
-/*
- * Tables.less
- * Tables for, you guessed it, tabular data
- * ---------------------------------------- */
-table {
-  width: 100%;
-  margin-bottom: 18px;
-  padding: 0;
-  border-collapse: separate;
-  *border-collapse: collapse;
-  /* IE7, collapse table to remove spacing */
-
-  font-size: 13px;
-  border: 1px solid #ddd;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
-}
-table th, table td {
-  padding: 10px 10px 9px;
-  line-height: 18px;
-  text-align: left;
-}
-table th {
-  padding-top: 9px;
-  font-weight: bold;
-  vertical-align: middle;
-  border-bottom: 1px solid #ddd;
-}
-table td {
-  vertical-align: top;
-}
-table th + th, table td + td {
-  border-left: 1px solid #ddd;
-}
-table tr + tr td {
-  border-top: 1px solid #ddd;
-}
-table tbody tr:first-child td:first-child {
-  -webkit-border-radius: 4px 0 0 0;
-  -moz-border-radius: 4px 0 0 0;
-  border-radius: 4px 0 0 0;
-}
-table tbody tr:first-child td:last-child {
-  -webkit-border-radius: 0 4px 0 0;
-  -moz-border-radius: 0 4px 0 0;
-  border-radius: 0 4px 0 0;
-}
-table tbody tr:last-child td:first-child {
-  -webkit-border-radius: 0 0 0 4px;
-  -moz-border-radius: 0 0 0 4px;
-  border-radius: 0 0 0 4px;
-}
-table tbody tr:last-child td:last-child {
-  -webkit-border-radius: 0 0 4px 0;
-  -moz-border-radius: 0 0 4px 0;
-  border-radius: 0 0 4px 0;
-}
-.zebra-striped tbody tr:nth-child(odd) td {
-  background-color: #f9f9f9;
-}
-.zebra-striped tbody tr:hover td {
-  background-color: #f5f5f5;
-}
-table .header {
-  cursor: pointer;
-}
-table .header:after {
-  content: "";
-  float: right;
-  margin-top: 7px;
-  border-width: 0 4px 4px;
-  border-style: solid;
-  border-color: #000 transparent;
-  visibility: hidden;
-}
-table .headerSortUp, table .headerSortDown {
-  background-color: rgba(141, 192, 219, 0.25);
-  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
-}
-table .header:hover:after {
-  visibility: visible;
-}
-table .headerSortDown:after, table .headerSortDown:hover:after {
-  visibility: visible;
-  filter: alpha(opacity=60);
-  -khtml-opacity: 0.6;
-  -moz-opacity: 0.6;
-  opacity: 0.6;
-}
-table .headerSortUp:after {
-  border-bottom: none;
-  border-left: 4px solid transparent;
-  border-right: 4px solid transparent;
-  border-top: 4px solid #000;
-  visibility: visible;
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-  filter: alpha(opacity=60);
-  -khtml-opacity: 0.6;
-  -moz-opacity: 0.6;
-  opacity: 0.6;
-}
-table .blue {
-  color: #049cdb;
-  border-bottom-color: #049cdb;
-}
-table .headerSortUp.blue, table .headerSortDown.blue {
-  background-color: #ade6fe;
-}
-table .green {
-  color: #46a546;
-  border-bottom-color: #46a546;
-}
-table .headerSortUp.green, table .headerSortDown.green {
-  background-color: #cdeacd;
-}
-table .red {
-  color: #9d261d;
-  border-bottom-color: #9d261d;
-}
-table .headerSortUp.red, table .headerSortDown.red {
-  background-color: #f4c8c5;
-}
-table .yellow {
-  color: #ffc40d;
-  border-bottom-color: #ffc40d;
-}
-table .headerSortUp.yellow, table .headerSortDown.yellow {
-  background-color: #fff6d9;
-}
-table .orange {
-  color: #f89406;
-  border-bottom-color: #f89406;
-}
-table .headerSortUp.orange, table .headerSortDown.orange {
-  background-color: #fee9cc;
-}
-table .purple {
-  color: #7a43b6;
-  border-bottom-color: #7a43b6;
-}
-table .headerSortUp.purple, table .headerSortDown.purple {
-  background-color: #e2d5f0;
-}
-/* Patterns.less
- * Repeatable UI elements outside the base styles provided from the scaffolding
- * ---------------------------------------------------------------------------- */
-.topbar {
-  height: 40px;
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  z-index: 10000;
-  overflow: visible;
-}
-.topbar a {
-  color: #bfbfbf;
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-}
-.topbar h3 a:hover, .topbar .brand a:hover, .topbar ul .active > a {
-  background-color: #333;
-  background-color: rgba(255, 255, 255, 0.05);
-  color: #ffffff;
-  text-decoration: none;
-}
-.topbar h3 {
-  position: relative;
-}
-.topbar h3 a, .topbar .brand {
-  float: left;
-  display: block;
-  padding: 8px 20px 12px;
-  margin-left: -20px;
-  color: #ffffff;
-  font-size: 20px;
-  font-weight: 200;
-  line-height: 1;
-}
-.topbar p {
-  margin: 0;
-  line-height: 40px;
-}
-.topbar p a:hover {
-  background-color: transparent;
-  color: #ffffff;
-}
-.topbar form {
-  float: left;
-  margin: 5px 0 0 0;
-  position: relative;
-  filter: alpha(opacity=100);
-  -khtml-opacity: 1;
-  -moz-opacity: 1;
-  opacity: 1;
-}
-.topbar form.pull-right {
-  float: right;
-}
-.topbar input {
-  background-color: #444;
-  background-color: rgba(255, 255, 255, 0.3);
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-  font-size: normal;
-  font-weight: 13px;
-  line-height: 1;
-  padding: 4px 9px;
-  color: #ffffff;
-  color: rgba(255, 255, 255, 0.75);
-  border: 1px solid #111;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
-  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
-  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
-  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
-  -webkit-transition: none;
-  -moz-transition: none;
-  -ms-transition: none;
-  -o-transition: none;
-  transition: none;
-}
-.topbar input:-moz-placeholder {
-  color: #e6e6e6;
-}
-.topbar input::-webkit-input-placeholder {
-  color: #e6e6e6;
-}
-.topbar input:hover {
-  background-color: #bfbfbf;
-  background-color: rgba(255, 255, 255, 0.5);
-  color: #ffffff;
-}
-.topbar input:focus, .topbar input.focused {
-  outline: 0;
-  background-color: #ffffff;
-  color: #404040;
-  text-shadow: 0 1px 0 #ffffff;
-  border: 0;
-  padding: 5px 10px;
-  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
-  -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
-  box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
-}
-.topbar-inner, .topbar .fill {
-  background-color: #222;
-  background-color: #222222;
-  background-repeat: repeat-x;
-  background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222));
-  background-image: -moz-linear-gradient(top, #333333, #222222);
-  background-image: -ms-linear-gradient(top, #333333, #222222);
-  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222));
-  background-image: -webkit-linear-gradient(top, #333333, #222222);
-  background-image: -o-linear-gradient(top, #333333, #222222);
-  background-image: linear-gradient(top, #333333, #222222);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);
-  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
-  -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
-  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
-}
-.topbar div > ul, .nav {
-  display: block;
-  float: left;
-  margin: 0 10px 0 0;
-  position: relative;
-  left: 0;
-}
-.topbar div > ul > li, .nav > li {
-  display: block;
-  float: left;
-}
-.topbar div > ul a, .nav a {
-  display: block;
-  float: none;
-  padding: 10px 10px 11px;
-  line-height: 19px;
-  text-decoration: none;
-}
-.topbar div > ul a:hover, .nav a:hover {
-  color: #ffffff;
-  text-decoration: none;
-}
-.topbar div > ul .active > a, .nav .active > a {
-  background-color: #222;
-  background-color: rgba(0, 0, 0, 0.5);
-}
-.topbar div > ul.secondary-nav, .nav.secondary-nav {
-  float: right;
-  margin-left: 10px;
-  margin-right: 0;
-}
-.topbar div > ul.secondary-nav .menu-dropdown,
-.nav.secondary-nav .menu-dropdown,
-.topbar div > ul.secondary-nav .dropdown-menu,
-.nav.secondary-nav .dropdown-menu {
-  right: 0;
-  border: 0;
-}
-.topbar div > ul a.menu:hover,
-.nav a.menu:hover,
-.topbar div > ul li.open .menu,
-.nav li.open .menu,
-.topbar div > ul .dropdown-toggle:hover,
-.nav .dropdown-toggle:hover,
-.topbar div > ul .dropdown.open .dropdown-toggle,
-.nav .dropdown.open .dropdown-toggle {
-  background: #444;
-  background: rgba(255, 255, 255, 0.05);
-}
-.topbar div > ul .menu-dropdown,
-.nav .menu-dropdown,
-.topbar div > ul .dropdown-menu,
-.nav .dropdown-menu {
-  background-color: #333;
-}
-.topbar div > ul .menu-dropdown a.menu,
-.nav .menu-dropdown a.menu,
-.topbar div > ul .dropdown-menu a.menu,
-.nav .dropdown-menu a.menu,
-.topbar div > ul .menu-dropdown .dropdown-toggle,
-.nav .menu-dropdown .dropdown-toggle,
-.topbar div > ul .dropdown-menu .dropdown-toggle,
-.nav .dropdown-menu .dropdown-toggle {
-  color: #ffffff;
-}
-.topbar div > ul .menu-dropdown a.menu.open,
-.nav .menu-dropdown a.menu.open,
-.topbar div > ul .dropdown-menu a.menu.open,
-.nav .dropdown-menu a.menu.open,
-.topbar div > ul .menu-dropdown .dropdown-toggle.open,
-.nav .menu-dropdown .dropdown-toggle.open,
-.topbar div > ul .dropdown-menu .dropdown-toggle.open,
-.nav .dropdown-menu .dropdown-toggle.open {
-  background: #444;
-  background: rgba(255, 255, 255, 0.05);
-}
-.topbar div > ul .menu-dropdown li a,
-.nav .menu-dropdown li a,
-.topbar div > ul .dropdown-menu li a,
-.nav .dropdown-menu li a {
-  color: #999;
-  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
-}
-.topbar div > ul .menu-dropdown li a:hover,
-.nav .menu-dropdown li a:hover,
-.topbar div > ul .dropdown-menu li a:hover,
-.nav .dropdown-menu li a:hover {
-  background-color: #191919;
-  background-repeat: repeat-x;
-  background-image: -khtml-gradient(linear, left top, left bottom, from(#292929), to(#191919));
-  background-image: -moz-linear-gradient(top, #292929, #191919);
-  background-image: -ms-linear-gradient(top, #292929, #191919);
-  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #292929), color-stop(100%, #191919));
-  background-image: -webkit-linear-gradient(top, #292929, #191919);
-  background-image: -o-linear-gradient(top, #292929, #191919);
-  background-image: linear-gradient(top, #292929, #191919);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#292929', endColorstr='#191919', GradientType=0);
-  color: #ffffff;
-}
-.topbar div > ul .menu-dropdown .active a,
-.nav .menu-dropdown .active a,
-.topbar div > ul .dropdown-menu .active a,
-.nav .dropdown-menu .active a {
-  color: #ffffff;
-}
-.topbar div > ul .menu-dropdown .divider,
-.nav .menu-dropdown .divider,
-.topbar div > ul .dropdown-menu .divider,
-.nav .dropdown-menu .divider {
-  background-color: #222;
-  border-color: #444;
-}
-.topbar ul .menu-dropdown li a, .topbar ul .dropdown-menu li a {
-  padding: 4px 15px;
-}
-li.menu, .dropdown {
-  position: relative;
-}
-a.menu:after, .dropdown-toggle:after {
-  width: 0;
-  height: 0;
-  display: inline-block;
-  content: "&darr;";
-  text-indent: -99999px;
-  vertical-align: top;
-  margin-top: 8px;
-  margin-left: 4px;
-  border-left: 4px solid transparent;
-  border-right: 4px solid transparent;
-  border-top: 4px solid #ffffff;
-  filter: alpha(opacity=50);
-  -khtml-opacity: 0.5;
-  -moz-opacity: 0.5;
-  opacity: 0.5;
-}
-.menu-dropdown, .dropdown-menu {
-  background-color: #ffffff;
-  float: left;
-  display: none;
-  position: absolute;
-  top: 40px;
-  z-index: 900;
-  min-width: 160px;
-  max-width: 220px;
-  _width: 160px;
-  margin-left: 0;
-  margin-right: 0;
-  padding: 6px 0;
-  zoom: 1;
-  border-color: #999;
-  border-color: rgba(0, 0, 0, 0.2);
-  border-style: solid;
-  border-width: 0 1px 1px;
-  -webkit-border-radius: 0 0 6px 6px;
-  -moz-border-radius: 0 0 6px 6px;
-  border-radius: 0 0 6px 6px;
-  -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
-  -moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
-  -webkit-background-clip: padding-box;
-  -moz-background-clip: padding-box;
-  background-clip: padding-box;
-}
-.menu-dropdown li, .dropdown-menu li {
-  float: none;
-  display: block;
-  background-color: none;
-}
-.menu-dropdown .divider, .dropdown-menu .divider {
-  height: 1px;
-  margin: 5px 0;
-  overflow: hidden;
-  background-color: #eee;
-  border-bottom: 1px solid #ffffff;
-}
-.topbar .dropdown-menu a, .dropdown-menu a {
-  display: block;
-  padding: 4px 15px;
-  clear: both;
-  font-weight: normal;
-  line-height: 18px;
-  color: #808080;
-  text-shadow: 0 1px 0 #ffffff;
-}
-.topbar .dropdown-menu a:hover, .dropdown-menu a:hover {
-  background-color: #dddddd;
-  background-repeat: repeat-x;
-  background-image: -khtml-gradient(linear, left top, left bottom, from(#eeeeee), to(#dddddd));
-  background-image: -moz-linear-gradient(top, #eeeeee, #dddddd);
-  background-image: -ms-linear-gradient(top, #eeeeee, #dddddd);
-  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #dddddd));
-  background-image: -webkit-linear-gradient(top, #eeeeee, #dddddd);
-  background-image: -o-linear-gradient(top, #eeeeee, #dddddd);
-  background-image: linear-gradient(top, #eeeeee, #dddddd);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#dddddd', GradientType=0);
-  color: #404040;
-  text-decoration: none;
-  -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025);
-  -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025);
-  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025);
-}
-.open .menu,
-.dropdown.open .menu,
-.open .dropdown-toggle,
-.dropdown.open .dropdown-toggle {
-  color: #ffffff;
-  background: #ccc;
-  background: rgba(0, 0, 0, 0.3);
-}
-.open .menu-dropdown,
-.dropdown.open .menu-dropdown,
-.open .dropdown-menu,
-.dropdown.open .dropdown-menu {
-  display: block;
-}
-.tabs, .pills {
-  margin: 0 0 20px;
-  padding: 0;
-  list-style: none;
-  zoom: 1;
-}
-.tabs:before,
-.pills:before,
-.tabs:after,
-.pills:after {
-  display: table;
-  content: "";
-  zoom: 1;
-  *display: inline;
-}
-.tabs:after, .pills:after {
-  clear: both;
-}
-.tabs > li, .pills > li {
-  float: left;
-}
-.tabs > li > a, .pills > li > a {
-  display: block;
-}
-.tabs {
-  float: left;
-  width: 100%;
-  border-bottom: 1px solid #ddd;
-}
-.tabs > li {
-  position: relative;
-  top: 1px;
-}
-.tabs > li > a {
-  padding: 0 15px;
-  margin-right: 2px;
-  line-height: 36px;
-  border: 1px solid transparent;
-  -webkit-border-radius: 4px 4px 0 0;
-  -moz-border-radius: 4px 4px 0 0;
-  border-radius: 4px 4px 0 0;
-}
-.tabs > li > a:hover {
-  text-decoration: none;
-  background-color: #eee;
-  border-color: #eee #eee #ddd;
-}
-.tabs > li.active > a {
-  color: #808080;
-  background-color: #ffffff;
-  border: 1px solid #ddd;
-  border-bottom-color: transparent;
-}
-.tabs .menu-dropdown, .tabs .dropdown-menu {
-  top: 35px;
-  border-width: 1px;
-  -webkit-border-radius: 0 6px 6px 6px;
-  -moz-border-radius: 0 6px 6px 6px;
-  border-radius: 0 6px 6px 6px;
-}
-.tabs a.menu:after, .tabs .dropdown-toggle:after {
-  border-top-color: #999;
-  margin-top: 15px;
-  margin-left: 5px;
-}
-.tabs li.open.menu .menu, .tabs .open.dropdown .dropdown-toggle {
-  border-color: #999;
-}
-.tabs li.open a.menu:after, .tabs .dropdown.open .dropdown-toggle:after {
-  border-top-color: #555;
-}
-.tab-content {
-  clear: both;
-}
-.pills a {
-  margin: 5px 3px 5px 0;
-  padding: 0 15px;
-  text-shadow: 0 1px 1px #ffffff;
-  line-height: 30px;
-  -webkit-border-radius: 15px;
-  -moz-border-radius: 15px;
-  border-radius: 15px;
-}
-.pills a:hover {
-  background: #00438a;
-  color: #ffffff;
-  text-decoration: none;
-  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
-}
-.pills .active a {
-  background: #0069d6;
-  color: #ffffff;
-  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
-}
-.tab-content > *, .pill-content > * {
-  display: none;
-}
-.tab-content > .active, .pill-content > .active {
-  display: block;
-}
-.breadcrumb {
-  margin: 0 0 18px;
-  padding: 7px 14px;
-  background-color: #f5f5f5;
-  background-repeat: repeat-x;
-  background-image: -khtml-gradient(linear, left top, left bottom, from(#ffffff), to(#f5f5f5));
-  background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5);
-  background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5);
-  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f5f5f5));
-  background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5);
-  background-image: -o-linear-gradient(top, #ffffff, #f5f5f5);
-  background-image: linear-gradient(top, #ffffff, #f5f5f5);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);
-  border: 1px solid #ddd;
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
-  -webkit-box-shadow: inset 0 1px 0 #ffffff;
-  -moz-box-shadow: inset 0 1px 0 #ffffff;
-  box-shadow: inset 0 1px 0 #ffffff;
-}
-.breadcrumb li {
-  display: inline;
-  text-shadow: 0 1px 0 #ffffff;
-}
-.breadcrumb .divider {
-  padding: 0 5px;
-  color: #bfbfbf;
-}
-.breadcrumb .active a {
-  color: #404040;
-}
-.hero-unit {
-  background-color: #f5f5f5;
-  margin-bottom: 30px;
-  padding: 60px;
-  -webkit-border-radius: 6px;
-  -moz-border-radius: 6px;
-  border-radius: 6px;
-}
-.hero-unit h1 {
-  margin-bottom: 0;
-  font-size: 60px;
-  line-height: 1;
-  letter-spacing: -1px;
-}
-.hero-unit p {
-  font-size: 18px;
-  font-weight: 200;
-  line-height: 27px;
-}
-footer {
-  margin-top: 17px;
-  padding-top: 17px;
-  border-top: 1px solid #eee;
-}
-.page-header {
-  margin-bottom: 17px;
-  border-bottom: 1px solid #ddd;
-  -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
-  -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
-  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
-}
-.page-header h1 {
-  margin-bottom: 8px;
-}
-.btn.danger,
-.alert-message.danger,
-.btn.danger:hover,
-.alert-message.danger:hover,
-.btn.error,
-.alert-message.error,
-.btn.error:hover,
-.alert-message.error:hover,
-.btn.success,
-.alert-message.success,
-.btn.success:hover,
-.alert-message.success:hover,
-.btn.info,
-.alert-message.info,
-.btn.info:hover,
-.alert-message.info:hover {
-  color: #ffffff;
-}
-.btn.danger,
-.alert-message.danger,
-.btn.error,
-.alert-message.error {
-  background-color: #c43c35;
-  background-repeat: repeat-x;
-  background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));
-  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
-  background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
-  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));
-  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
-  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
-  background-image: linear-gradient(top, #ee5f5b, #c43c35);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  border-color: #c43c35 #c43c35 #882a25;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-}
-.btn.success, .alert-message.success {
-  background-color: #57a957;
-  background-repeat: repeat-x;
-  background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));
-  background-image: -moz-linear-gradient(top, #62c462, #57a957);
-  background-image: -ms-linear-gradient(top, #62c462, #57a957);
-  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));
-  background-image: -webkit-linear-gradient(top, #62c462, #57a957);
-  background-image: -o-linear-gradient(top, #62c462, #57a957);
-  background-image: linear-gradient(top, #62c462, #57a957);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  border-color: #57a957 #57a957 #3d773d;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-}
-.btn.info, .alert-message.info {
-  background-color: #339bb9;
-  background-repeat: repeat-x;
-  background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9));
-  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
-  background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);
-  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));
-  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
-  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
-  background-image: linear-gradient(top, #5bc0de, #339bb9);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  border-color: #339bb9 #339bb9 #22697d;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-}
-.btn {
-  cursor: pointer;
-  display: inline-block;
-  background-color: #e6e6e6;
-  background-repeat: no-repeat;
-  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));
-  background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
-  background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);
-  background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
-  background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
-  background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);
-  padding: 5px 14px 6px;
-  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
-  color: #333;
-  font-size: 13px;
-  line-height: normal;
-  border: 1px solid #ccc;
-  border-bottom-color: #bbb;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
-  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-  -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-  -webkit-transition: 0.1s linear all;
-  -moz-transition: 0.1s linear all;
-  -ms-transition: 0.1s linear all;
-  -o-transition: 0.1s linear all;
-  transition: 0.1s linear all;
-}
-.btn:hover {
-  background-position: 0 -15px;
-  color: #333;
-  text-decoration: none;
-}
-.btn:focus {
-  outline: 1px dotted #666;
-}
-.btn.primary {
-  color: #ffffff;
-  background-color: #0064cd;
-  background-repeat: repeat-x;
-  background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
-  background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
-  background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
-  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
-  background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
-  background-image: -o-linear-gradient(top, #049cdb, #0064cd);
-  background-image: linear-gradient(top, #049cdb, #0064cd);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  border-color: #0064cd #0064cd #003f81;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-}
-.btn:active {
-  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
-  -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
-  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
-}
-.btn.disabled {
-  cursor: default;
-  background-image: none;
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-  filter: alpha(opacity=65);
-  -khtml-opacity: 0.65;
-  -moz-opacity: 0.65;
-  opacity: 0.65;
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-}
-.btn[disabled] {
-  cursor: default;
-  background-image: none;
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-  filter: alpha(opacity=65);
-  -khtml-opacity: 0.65;
-  -moz-opacity: 0.65;
-  opacity: 0.65;
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-}
-.btn.large {
-  font-size: 15px;
-  line-height: normal;
-  padding: 9px 14px 9px;
-  -webkit-border-radius: 6px;
-  -moz-border-radius: 6px;
-  border-radius: 6px;
-}
-.btn.small {
-  padding: 7px 9px 7px;
-  font-size: 11px;
-}
-:root .alert-message, :root .btn {
-  border-radius: 0 \0;
-}
-button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner {
-  padding: 0;
-  border: 0;
-}
-.close {
-  float: right;
-  color: #000000;
-  font-size: 20px;
-  font-weight: bold;
-  line-height: 13.5px;
-  text-shadow: 0 1px 0 #ffffff;
-  filter: alpha(opacity=20);
-  -khtml-opacity: 0.2;
-  -moz-opacity: 0.2;
-  opacity: 0.2;
-}
-.close:hover {
-  color: #000000;
-  text-decoration: none;
-  filter: alpha(opacity=40);
-  -khtml-opacity: 0.4;
-  -moz-opacity: 0.4;
-  opacity: 0.4;
-}
-.alert-message {
-  position: relative;
-  padding: 7px 15px;
-  margin-bottom: 18px;
-  color: #404040;
-  background-color: #eedc94;
-  background-repeat: repeat-x;
-  background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94));
-  background-image: -moz-linear-gradient(top, #fceec1, #eedc94);
-  background-image: -ms-linear-gradient(top, #fceec1, #eedc94);
-  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94));
-  background-image: -webkit-linear-gradient(top, #fceec1, #eedc94);
-  background-image: -o-linear-gradient(top, #fceec1, #eedc94);
-  background-image: linear-gradient(top, #fceec1, #eedc94);
-  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0);
-  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
-  border-color: #eedc94 #eedc94 #e4c652;
-  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
-  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
-  border-width: 1px;
-  border-style: solid;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
-  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
-  -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
-  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
-}
-.alert-message .close {
-  *margin-top: 3px;
-  /* IE7 spacing */
-
-}
-.alert-message h5 {
-  line-height: 18px;
-}
-.alert-message p {
-  margin-bottom: 0;
-}
-.alert-message div {
-  margin-top: 5px;
-  margin-bottom: 2px;
-  line-height: 28px;
-}
-.alert-message .btn {
-  -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
-  -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
-  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
-}
-.alert-message.block-message {
-  background-image: none;
-  background-color: #fdf5d9;
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-  padding: 14px;
-  border-color: #fceec1;
-  -webkit-box-shadow: none;
-  -moz-box-shadow: none;
-  box-shadow: none;
-}
-.alert-message.block-message ul, .alert-message.block-message p {
-  margin-right: 30px;
-}
-.alert-message.block-message ul {
-  margin-bottom: 0;
-}
-.alert-message.block-message li {
-  color: #404040;
-}
-.alert-message.block-message .alert-actions {
-  margin-top: 5px;
-}
-.alert-message.block-message.error, .alert-message.block-message.success, .alert-message.block-message.info {
-  color: #404040;
-  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
-}
-.alert-message.block-message.error {
-  background-color: #fddfde;
-  border-color: #fbc7c6;
-}
-.alert-message.block-message.success {
-  background-color: #d1eed1;
-  border-color: #bfe7bf;
-}
-.alert-message.block-message.info {
-  background-color: #ddf4fb;
-  border-color: #c6edf9;
-}
-.pagination {
-  height: 36px;
-  margin: 18px 0;
-}
-.pagination ul {
-  float: left;
-  margin: 0;
-  border: 1px solid #ddd;
-  border: 1px solid rgba(0, 0, 0, 0.15);
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
-  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
-  -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
-  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
-}
-.pagination li {
-  display: inline;
-}
-.pagination a {
-  float: left;
-  padding: 0 14px;
-  line-height: 34px;
-  border-right: 1px solid;
-  border-right-color: #ddd;
-  border-right-color: rgba(0, 0, 0, 0.15);
-  *border-right-color: #ddd;
-  /* IE6-7 */
-
-  text-decoration: none;
-}
-.pagination a:hover, .pagination .active a {
-  background-color: #c7eefe;
-}
-.pagination .disabled a, .pagination .disabled a:hover {
-  background-color: transparent;
-  color: #bfbfbf;
-}
-.pagination .next a {
-  border: 0;
-}
-.well {
-  background-color: #f5f5f5;
-  margin-bottom: 20px;
-  padding: 19px;
-  min-height: 20px;
-  border: 1px solid #eee;
-  border: 1px solid rgba(0, 0, 0, 0.05);
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
-  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
-  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
-}
-.well blockquote {
-  border-color: #ddd;
-  border-color: rgba(0, 0, 0, 0.15);
-}
-.modal-backdrop {
-  background-color: #000000;
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  z-index: 10000;
-}
-.modal-backdrop.fade {
-  opacity: 0;
-}
-.modal-backdrop, .modal-backdrop.fade.in {
-  filter: alpha(opacity=80);
-  -khtml-opacity: 0.8;
-  -moz-opacity: 0.8;
-  opacity: 0.8;
-}
-.modal {
-  position: fixed;
-  top: 50%;
-  left: 50%;
-  z-index: 11000;
-  width: 560px;
-  margin: -250px 0 0 -250px;
-  background-color: #ffffff;
-  border: 1px solid #999;
-  border: 1px solid rgba(0, 0, 0, 0.3);
-  *border: 1px solid #999;
-  /* IE6-7 */
-
-  -webkit-border-radius: 6px;
-  -moz-border-radius: 6px;
-  border-radius: 6px;
-  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
-  -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
-  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
-  -webkit-background-clip: padding-box;
-  -moz-background-clip: padding-box;
-  background-clip: padding-box;
-}
-.modal .close {
-  margin-top: 7px;
-}
-.modal.fade {
-  -webkit-transition: opacity .3s linear, top .3s ease-out;
-  -moz-transition: opacity .3s linear, top .3s ease-out;
-  -ms-transition: opacity .3s linear, top .3s ease-out;
-  -o-transition: opacity .3s linear, top .3s ease-out;
-  transition: opacity .3s linear, top .3s ease-out;
-  top: -25%;
-}
-.modal.fade.in {
-  top: 50%;
-}
-.modal-header {
-  border-bottom: 1px solid #eee;
-  padding: 5px 15px;
-}
-.modal-body {
-  padding: 15px;
-}
-.modal-footer {
-  background-color: #f5f5f5;
-  padding: 14px 15px 15px;
-  border-top: 1px solid #ddd;
-  -webkit-border-radius: 0 0 6px 6px;
-  -moz-border-radius: 0 0 6px 6px;
-  border-radius: 0 0 6px 6px;
-  -webkit-box-shadow: inset 0 1px 0 #ffffff;
-  -moz-box-shadow: inset 0 1px 0 #ffffff;
-  box-shadow: inset 0 1px 0 #ffffff;
-  zoom: 1;
-  margin-bottom: 0;
-}
-.modal-footer:before, .modal-footer:after {
-  display: table;
-  content: "";
-  zoom: 1;
-  *display: inline;
-}
-.modal-footer:after {
-  clear: both;
-}
-.modal-footer .btn {
-  float: right;
-  margin-left: 5px;
-}
-.twipsy {
-  display: block;
-  position: absolute;
-  visibility: visible;
-  padding: 5px;
-  font-size: 11px;
-  z-index: 1000;
-  filter: alpha(opacity=80);
-  -khtml-opacity: 0.8;
-  -moz-opacity: 0.8;
-  opacity: 0.8;
-}
-.twipsy.fade.in {
-  filter: alpha(opacity=80);
-  -khtml-opacity: 0.8;
-  -moz-opacity: 0.8;
-  opacity: 0.8;
-}
-.twipsy.above .twipsy-arrow {
-  bottom: 0;
-  left: 50%;
-  margin-left: -5px;
-  border-left: 5px solid transparent;
-  border-right: 5px solid transparent;
-  border-top: 5px solid #000000;
-}
-.twipsy.left .twipsy-arrow {
-  top: 50%;
-  right: 0;
-  margin-top: -5px;
-  border-top: 5px solid transparent;
-  border-bottom: 5px solid transparent;
-  border-left: 5px solid #000000;
-}
-.twipsy.below .twipsy-arrow {
-  top: 0;
-  left: 50%;
-  margin-left: -5px;
-  border-left: 5px solid transparent;
-  border-right: 5px solid transparent;
-  border-bottom: 5px solid #000000;
-}
-.twipsy.right .twipsy-arrow {
-  top: 50%;
-  left: 0;
-  margin-top: -5px;
-  border-top: 5px solid transparent;
-  border-bottom: 5px solid transparent;
-  border-right: 5px solid #000000;
-}
-.twipsy-inner {
-  padding: 3px 8px;
-  background-color: #000000;
-  color: white;
-  text-align: center;
-  max-width: 200px;
-  text-decoration: none;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
-}
-.twipsy-arrow {
-  position: absolute;
-  width: 0;
-  height: 0;
-}
-.popover {
-  position: absolute;
-  top: 0;
-  left: 0;
-  z-index: 1000;
-  padding: 5px;
-  display: none;
-}
-.popover.above .arrow {
-  bottom: 0;
-  left: 50%;
-  margin-left: -5px;
-  border-left: 5px solid transparent;
-  border-right: 5px solid transparent;
-  border-top: 5px solid #000000;
-}
-.popover.right .arrow {
-  top: 50%;
-  left: 0;
-  margin-top: -5px;
-  border-top: 5px solid transparent;
-  border-bottom: 5px solid transparent;
-  border-right: 5px solid #000000;
-}
-.popover.below .arrow {
-  top: 0;
-  left: 50%;
-  margin-left: -5px;
-  border-left: 5px solid transparent;
-  border-right: 5px solid transparent;
-  border-bottom: 5px solid #000000;
-}
-.popover.left .arrow {
-  top: 50%;
-  right: 0;
-  margin-top: -5px;
-  border-top: 5px solid transparent;
-  border-bottom: 5px solid transparent;
-  border-left: 5px solid #000000;
-}
-.popover .arrow {
-  position: absolute;
-  width: 0;
-  height: 0;
-}
-.popover .inner {
-  background-color: #000000;
-  background-color: rgba(0, 0, 0, 0.8);
-  padding: 3px;
-  overflow: hidden;
-  width: 280px;
-  -webkit-border-radius: 6px;
-  -moz-border-radius: 6px;
-  border-radius: 6px;
-  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
-  -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
-  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
-}
-.popover .title {
-  background-color: #f5f5f5;
-  padding: 9px 15px;
-  line-height: 1;
-  -webkit-border-radius: 3px 3px 0 0;
-  -moz-border-radius: 3px 3px 0 0;
-  border-radius: 3px 3px 0 0;
-  border-bottom: 1px solid #eee;
-}
-.popover .content {
-  background-color: #ffffff;
-  padding: 14px;
-  -webkit-border-radius: 0 0 3px 3px;
-  -moz-border-radius: 0 0 3px 3px;
-  border-radius: 0 0 3px 3px;
-  -webkit-background-clip: padding-box;
-  -moz-background-clip: padding-box;
-  background-clip: padding-box;
-}
-.popover .content p, .popover .content ul, .popover .content ol {
-  margin-bottom: 0;
-}
-.fade {
-  -webkit-transition: opacity 0.15s linear;
-  -moz-transition: opacity 0.15s linear;
-  -ms-transition: opacity 0.15s linear;
-  -o-transition: opacity 0.15s linear;
-  transition: opacity 0.15s linear;
-  opacity: 0;
-}
-.fade.in {
-  opacity: 1;
-}
-.label {
-  padding: 1px 3px 2px;
-  background-color: #bfbfbf;
-  font-size: 9.75px;
-  font-weight: bold;
-  color: #ffffff;
-  text-transform: uppercase;
-  -webkit-border-radius: 3px;
-  -moz-border-radius: 3px;
-  border-radius: 3px;
-}
-.label.important {
-  background-color: #c43c35;
-}
-.label.warning {
-  background-color: #f89406;
-}
-.label.success {
-  background-color: #46a546;
-}
-.label.notice {
-  background-color: #62cffc;
-}
-.media-grid {
-  margin-left: -20px;
-  margin-bottom: 0;
-  zoom: 1;
-}
-.media-grid:before, .media-grid:after {
-  display: table;
-  content: "";
-  zoom: 1;
-  *display: inline;
-}
-.media-grid:after {
-  clear: both;
-}
-.media-grid li {
-  display: inline;
-}
-.media-grid a {
-  float: left;
-  padding: 4px;
-  margin: 0 0 20px 20px;
-  border: 1px solid #ddd;
-  -webkit-border-radius: 4px;
-  -moz-border-radius: 4px;
-  border-radius: 4px;
-  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-  -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-.media-grid a img {
-  display: block;
-}
-.media-grid a:hover {
-  border-color: #0069d6;
-  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
-  -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
-  box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
-}
diff --git a/pithos/im/static/jquery.js b/pithos/im/static/jquery.js
deleted file mode 100644 (file)
index 48590ec..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.6.2
- * http://jquery.com/
- *
- * Copyright 2011, John Resig
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- * Copyright 2011, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- *
- * Date: Thu Jun 30 14:16:56 2011 -0400
- */
-(function(a,b){function cv(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cs(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bZ(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bY(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bC.test(a)?d(a,e):bY(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)bY(a+"["+e+"]",b[e],c,d);else d(a,b)}function bX(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bR,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bX(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bX(a,c,d,e,"*",g));return l}function bW(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bN),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bA(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bv:bw;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bg(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function W(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(R.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(x,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(H)return H.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g](h)}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u=/\:|^on/,v,w;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(o);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(o);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(n," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if((" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.
-shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.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[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!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:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,N(a.origType,a.selector),f.extend({},a,{handler:M,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,N(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?E:D):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=E;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=E;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=E,this.stopPropagation()},isDefaultPrevented:D,isPropagationStopped:D,isImmediatePropagationStopped:D};var F=function(a){var b=a.relatedTarget,c=!1,d=a.type;a.type=a.data,b!==this&&(b&&(c=f.contains(this,b)),c||(f.event.handle.apply(this,arguments),a.type=d))},G=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?G:F,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?G:F)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=b.type;(c==="submit"||c==="image")&&f(b).closest("form").length&&K("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=b.type;(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&K("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var H,I=function(a){var b=a.type,c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var L={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||D,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=x.exec(h),k="",j&&(k=j[0],h=h.replace(x,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,L[h]?(a.push(L[h]+k),h=h+k):h=(L[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+N(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+N(h,m),e)}return this}}),f.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){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=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|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var O=/Until$/,P=/^(?:parents|prevUntil|prevAll)/,Q=/,/,R=/^.[^:#\[\.,]*$/,S=Array.prototype.slice,T=f.expr.match.POS,U={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(W(this,a,!1),"not",a)},filter:function(a){return this.pushStack(W(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=T.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/<tbody/i,ba=/<|&#?\w+;/,bb=/<(?:script|object|embed|option|style)/i,bc=/checked\s*(?:[^=]|=\s*.checked.)/i,bd=/\/(java|ecma)script/i,be=/^\s*<!(?:\[CDATA\[|\-\-)/,bf={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,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(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,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bc.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bg(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bm)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i;b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!bb.test(a[0])&&(f.support.checkClone||!bc.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j
-)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1></$2>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bl(k[i]);else bl(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bd.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bn=/alpha\([^)]*\)/i,bo=/opacity=([^)]*)/,bp=/([A-Z]|^ms)/g,bq=/^-?\d+(?:px)?$/i,br=/^-?\d/,bs=/^[+\-]=/,bt=/[^+\-\.\de]+/g,bu={position:"absolute",visibility:"hidden",display:"block"},bv=["Left","Right"],bw=["Top","Bottom"],bx,by,bz;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bx(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d;if(h==="number"&&isNaN(d)||d==null)return;h==="string"&&bs.test(d)&&(d=+d.replace(bt,"")+parseFloat(f.css(a,c)),h="number"),h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bx)return bx(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bA(a,b,d);f.swap(a,bu,function(){e=bA(a,b,d)});return e}},set:function(a,b){if(!bq.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cs(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cr("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cr("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cs(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cj.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=ck.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cr("show",1),slideUp:cr("hide",1),slideToggle:cr("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.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,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function h(a){return d.step(a)}var d=this,e=f.fx,g;this.startTime=cn||cp(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,h.elem=this.elem,h()&&f.timers.push(h)&&!cl&&(co?(cl=!0,g=function(){cl&&(co(g),e.tick())},co(g)):cl=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cn||cp(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cl),cl=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){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:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var ct=/^t(?:able|d|h)$/i,cu=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cv(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!ct.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<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>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.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!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);
\ No newline at end of file
diff --git a/pithos/im/static/jquery.tablesorter.js b/pithos/im/static/jquery.tablesorter.js
deleted file mode 100644 (file)
index b8605df..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-
-(function($){$.extend({tablesorter:new
-function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",cssChildRow:"expand-child",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,sortLocaleCompare:true,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'/\.|\,/g',onRenderHeader:null,selectorHeaders:'thead th',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}if(table.tBodies.length==0)return;var rows=table.tBodies[0].rows;if(rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,rows,-1,i);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,rows,rowIndex,cellIndex){var l=parsers.length,node=false,nodeValue=false,keepLooking=true;while(nodeValue==''&&keepLooking){rowIndex++;if(rows[rowIndex]){node=getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex);nodeValue=trimAndGetNodeText(table.config,node);if(table.config.debug){log('Checking if value was empty on row:'+rowIndex);}}else{keepLooking=false;}}for(var i=1;i<l;i++){if(parsers[i].is(nodeValue,table,node)){return parsers[i];}}return parsers[0];}function getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex){return rows[rowIndex].cells[cellIndex];}function trimAndGetNodeText(config,node){return $.trim(getElementText(config,node));}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=$(table.tBodies[0].rows[i]),cols=[];if(c.hasClass(table.config.cssChildRow)){cache.row[cache.row.length-1]=cache.row[cache.row.length-1].add(c);continue;}cache.row.push(c);for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c[0].cells[j]),table,c[0].cells[j]));}cols.push(cache.normalized.length);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){var text="";if(!node)return"";if(!config.supportsTextContent)config.supportsTextContent=node.textContent||false;if(config.textExtraction=="simple"){if(config.supportsTextContent){text=node.textContent;}else{if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){text=node.childNodes[0].innerHTML;}else{text=node.innerHTML;}}}else{if(typeof(config.textExtraction)=="function"){text=config.textExtraction(node);}else{text=$(node).text();}}return text;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){var pos=n[i][checkCell];rows.push(r[pos]);if(!table.config.appender){var l=r[pos].length;for(var j=0;j<l;j++){tableBody[0].appendChild(r[pos][j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false;var header_index=computeTableHeaderCellIndexes(table);$tableHeaders=$(table.config.selectorHeaders,table).each(function(index){this.column=header_index[this.parentNode.rowIndex+"-"+this.cellIndex];this.order=formatSortingOrder(table.config.sortInitialOrder);this.count=this.order;if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(checkHeaderOptionsSortingLocked(table,index))this.order=this.lockedOrder=checkHeaderOptionsSortingLocked(table,index);if(!this.sortDisabled){var $th=$(this).addClass(table.config.cssHeader);if(table.config.onRenderHeader)table.config.onRenderHeader.apply($th);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function computeTableHeaderCellIndexes(t){var matrix=[];var lookup={};var thead=t.getElementsByTagName('THEAD')[0];var trs=thead.getElementsByTagName('TR');for(var i=0;i<trs.length;i++){var cells=trs[i].cells;for(var j=0;j<cells.length;j++){var c=cells[j];var rowIndex=c.parentNode.rowIndex;var cellId=rowIndex+"-"+c.cellIndex;var rowSpan=c.rowSpan||1;var colSpan=c.colSpan||1
-var firstAvailCol;if(typeof(matrix[rowIndex])=="undefined"){matrix[rowIndex]=[];}for(var k=0;k<matrix[rowIndex].length+1;k++){if(typeof(matrix[rowIndex][k])=="undefined"){firstAvailCol=k;break;}}lookup[cellId]=firstAvailCol;for(var k=rowIndex;k<rowIndex+rowSpan;k++){if(typeof(matrix[k])=="undefined"){matrix[k]=[];}var matrixrow=matrix[k];for(var l=firstAvailCol;l<firstAvailCol+colSpan;l++){matrixrow[l]="x";}}}}return lookup;}function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function checkHeaderOptionsSortingLocked(table,i){if((table.config.headers[i])&&(table.config.headers[i].lockedOrder))return table.config.headers[i].lockedOrder;return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){return(v.toLowerCase()=="desc")?1:0;}else{return(v==1)?1:0;}}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(table.config.parsers[c].type=="text")?((order==0)?makeSortFunction("text","asc",c):makeSortFunction("text","desc",c)):((order==0)?makeSortFunction("numeric","asc",c):makeSortFunction("numeric","desc",c));var e="e"+i;dynamicExp+="var "+e+" = "+s;dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";if(table.config.debug){benchmark("Evaling expression:"+dynamicExp,new Date());}eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function makeSortFunction(type,direction,index){var a="a["+index+"]",b="b["+index+"]";if(type=='text'&&direction=='asc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+a+" < "+b+") ? -1 : 1 )));";}else if(type=='text'&&direction=='desc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+b+" < "+a+") ? -1 : 1 )));";}else if(type=='numeric'&&direction=='asc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+a+" - "+b+"));";}else if(type=='numeric'&&direction=='desc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+b+" - "+a+"));";}};function makeSortText(i){return"((a["+i+"] < b["+i+"]) ? -1 : ((a["+i+"] > b["+i+"]) ? 1 : 0));";};function makeSortTextDesc(i){return"((b["+i+"] < a["+i+"]) ? -1 : ((b["+i+"] > a["+i+"]) ? 1 : 0));";};function makeSortNumeric(i){return"a["+i+"]-b["+i+"];";};function makeSortNumericDesc(i){return"b["+i+"]-a["+i+"];";};function sortText(a,b){if(table.config.sortLocaleCompare)return a.localeCompare(b);return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){if(table.config.sortLocaleCompare)return b.localeCompare(a);return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$.data(this,"tablesorter",config);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){$this.trigger("sortStart");var $cell=$(this);var i=this.column;this.order=this.count++%2;if(this.lockedOrder)this.order=this.lockedOrder;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){var me=this;setTimeout(function(){me.config.parsers=buildParserCache(me,$headers);cache=buildCache(me);},1);}).bind("updateCell",function(e,cell){var config=this.config;var pos=[(cell.parentNode.rowIndex-1),cell.cellIndex];cache.normalized[pos[0]][pos[1]]=config.parsers[pos[1]].format(getElementText(config,cell),cell);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){return/^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g,'')));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLocaleLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}var $tr,row=-1,odd;$("tr:visible",table.tBodies[0]).each(function(i){$tr=$(this);if(!$tr.hasClass(table.config.cssChildRow))row++;odd=(row%2==0);$tr.removeClass(table.config.widgetZebra.css[odd?0:1]).addClass(table.config.widgetZebra.css[odd?1:0])});if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery);
\ No newline at end of file
diff --git a/pithos/im/static/local.png b/pithos/im/static/local.png
deleted file mode 100644 (file)
index 5316a18..0000000
Binary files a/pithos/im/static/local.png and /dev/null differ
diff --git a/pithos/im/static/main.js b/pithos/im/static/main.js
deleted file mode 100644 (file)
index e40ab3f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-$(function() {
-       $('table.id-sorted').tablesorter({ sortList: [[0, 0]] });
-
-       $('tr.row-template').hide();
-       $('div.alert-message').hide();
-});
-
-$('.needs-confirm').live('click', function() {
-       $('div.alert-message').show('fast');
-       $('div.actions').hide('fast');
-       return false;
-});
-
-$('.alert-close').live('click', function() {
-       $('div.alert-message').hide('fast');
-       $('div.actions').show('fast');
-       return false;
-});
diff --git a/pithos/im/static/openid.png b/pithos/im/static/openid.png
deleted file mode 100644 (file)
index 241df20..0000000
Binary files a/pithos/im/static/openid.png and /dev/null differ
diff --git a/pithos/im/static/shibboleth.png b/pithos/im/static/shibboleth.png
deleted file mode 100644 (file)
index f596fb0..0000000
Binary files a/pithos/im/static/shibboleth.png and /dev/null differ
diff --git a/pithos/im/static/twitter.png b/pithos/im/static/twitter.png
deleted file mode 100644 (file)
index b0a33bb..0000000
Binary files a/pithos/im/static/twitter.png and /dev/null differ
diff --git a/pithos/im/target/__init__.py b/pithos/im/target/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/pithos/im/target/dummy.py b/pithos/im/target/dummy.py
deleted file mode 100644 (file)
index 8301edb..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-#
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-#
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from django.http import HttpResponseBadRequest
-
-from pithos.im.target.util import prepare_response
-
-
-def login(request):
-    next = request.GET.get('next')
-    if not next:
-        return HttpResponseBadRequest('No next step provided')
-    if not request.user:
-        return HttpResponseBadRequest('User not found')
-    
-    return prepare_response(request, request.user, next)
diff --git a/pithos/im/target/local.py b/pithos/im/target/local.py
deleted file mode 100644 (file)
index 2417338..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-#
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-#
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
-from django.conf import settings
-from django.template.loader import render_to_string
-
-from pithos.im.target.util import prepare_response
-from pithos.im.models import User
-
-from urllib import unquote
-
-from hashlib import new as newhasher
-
-def login(request):
-    username = request.POST.get('username')
-    password = request.POST.get('password')
-    
-    if not username:
-        return HttpResponseBadRequest('No user')
-    
-    if not password:
-        return HttpResponseBadRequest('No password')
-    
-    try:
-        user = User.objects.get(uniq=username)
-    except User.DoesNotExist:
-        return HttpResponseBadRequest('No such user')
-    
-    hasher = newhasher('sha256')
-    hasher.update(password)
-    password = hasher.hexdigest()
-    
-    if not password or user.password != password:
-        return HttpResponseBadRequest('Wrong password')
-    
-    if user.state == 'UNVERIFIED':
-        return HttpResponseBadRequest('Unverified account')
-    
-    next = request.POST.get('next')
-    return prepare_response(request, user, next)
-    
-def activate(request):
-    token = request.GET.get('auth')
-    next = request.GET.get('next')
-    try:
-        user = User.objects.get(auth_token=token)
-    except User.DoesNotExist:
-        return HttpResponseBadRequest('No such user')
-    
-    user.state = 'ACTIVE'
-    user.save()
-    return prepare_response(request, user, next, renew=True)
-
-def reset_password(request):
-    if request.method == 'GET':
-        cookie_value = unquote(request.COOKIES.get('_pithos2_a', ''))
-        if cookie_value and '|' in cookie_value:
-            token = cookie_value.split('|', 1)[1]
-        else:
-            token = request.GET.get('auth')
-        next = request.GET.get('next')
-        username = request.GET.get('username')
-        kwargs = {'auth': token,
-                  'next': next,
-                  'username' : username}
-        if not token:
-            kwargs.update({'status': 'error',
-                           'message': 'Missing token'})
-        html = render_to_string('reset.html', kwargs)
-        return HttpResponse(html)
-    elif request.method == 'POST':
-        token = request.POST.get('auth')
-        username = request.POST.get('username')
-        password = request.POST.get('password')
-        next = request.POST.get('next')
-        if not token:
-            status = 'error'
-            message = 'Bad Request: missing token'
-        try:
-            user = User.objects.get(auth_token=token)
-            if username != user.uniq:
-                status = 'error'
-                message = 'Bad Request: username mismatch'
-            else:
-                user.password = password
-                user.status = 'NORMAL'
-                user.save()
-                return prepare_response(request, user, next, renew=True)
-        except User.DoesNotExist:
-            status = 'error'
-            message = 'Bad Request: invalid token'
-            
-        html = render_to_string('reset.html', {
-                'status': status,
-                'message': message})
-        return HttpResponse(html)
\ No newline at end of file
diff --git a/pithos/im/target/oauth2/__init__.py b/pithos/im/target/oauth2/__init__.py
deleted file mode 100644 (file)
index 835270e..0000000
+++ /dev/null
@@ -1,860 +0,0 @@
-"""
-The MIT License
-
-Copyright (c) 2007-2010 Leah Culver, Joe Stump, Mark Paschal, Vic Fryzel
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-"""
-
-import base64
-import urllib
-import time
-import random
-import urlparse
-import hmac
-import binascii
-import httplib2
-
-try:
-    from urlparse import parse_qs
-    parse_qs # placate pyflakes
-except ImportError:
-    # fall back for Python 2.5
-    from cgi import parse_qs
-
-try:
-    from hashlib import sha1
-    sha = sha1
-except ImportError:
-    # hashlib was added in Python 2.5
-    import sha
-
-import _version
-
-__version__ = _version.__version__
-
-OAUTH_VERSION = '1.0'  # Hi Blaine!
-HTTP_METHOD = 'GET'
-SIGNATURE_METHOD = 'PLAINTEXT'
-
-
-class Error(RuntimeError):
-    """Generic exception class."""
-
-    def __init__(self, message='OAuth error occurred.'):
-        self._message = message
-
-    @property
-    def message(self):
-        """A hack to get around the deprecation errors in 2.6."""
-        return self._message
-
-    def __str__(self):
-        return self._message
-
-
-class MissingSignature(Error):
-    pass
-
-
-def build_authenticate_header(realm=''):
-    """Optional WWW-Authenticate header (401 error)"""
-    return {'WWW-Authenticate': 'OAuth realm="%s"' % realm}
-
-
-def build_xoauth_string(url, consumer, token=None):
-    """Build an XOAUTH string for use in SMTP/IMPA authentication."""
-    request = Request.from_consumer_and_token(consumer, token,
-        "GET", url)
-
-    signing_method = SignatureMethod_HMAC_SHA1()
-    request.sign_request(signing_method, consumer, token)
-
-    params = []
-    for k, v in sorted(request.iteritems()):
-        if v is not None:
-            params.append('%s="%s"' % (k, escape(v)))
-
-    return "%s %s %s" % ("GET", url, ','.join(params))
-
-
-def to_unicode(s):
-    """ Convert to unicode, raise exception with instructive error
-    message if s is not unicode, ascii, or utf-8. """
-    if not isinstance(s, unicode):
-        if not isinstance(s, str):
-            raise TypeError('You are required to pass either unicode or string here, not: %r (%s)' % (type(s), s))
-        try:
-            s = s.decode('utf-8')
-        except UnicodeDecodeError, le:
-            raise TypeError('You are required to pass either a unicode object or a utf-8 string here. You passed a Python string object which contained non-utf-8: %r. The UnicodeDecodeError that resulted from attempting to interpret it as utf-8 was: %s' % (s, le,))
-    return s
-
-def to_utf8(s):
-    return to_unicode(s).encode('utf-8')
-
-def to_unicode_if_string(s):
-    if isinstance(s, basestring):
-        return to_unicode(s)
-    else:
-        return s
-
-def to_utf8_if_string(s):
-    if isinstance(s, basestring):
-        return to_utf8(s)
-    else:
-        return s
-
-def to_unicode_optional_iterator(x):
-    """
-    Raise TypeError if x is a str containing non-utf8 bytes or if x is
-    an iterable which contains such a str.
-    """
-    if isinstance(x, basestring):
-        return to_unicode(x)
-
-    try:
-        l = list(x)
-    except TypeError, e:
-        assert 'is not iterable' in str(e)
-        return x
-    else:
-        return [ to_unicode(e) for e in l ]
-
-def to_utf8_optional_iterator(x):
-    """
-    Raise TypeError if x is a str or if x is an iterable which
-    contains a str.
-    """
-    if isinstance(x, basestring):
-        return to_utf8(x)
-
-    try:
-        l = list(x)
-    except TypeError, e:
-        assert 'is not iterable' in str(e)
-        return x
-    else:
-        return [ to_utf8_if_string(e) for e in l ]
-
-def escape(s):
-    """Escape a URL including any /."""
-    return urllib.quote(s.encode('utf-8'), safe='~')
-
-def generate_timestamp():
-    """Get seconds since epoch (UTC)."""
-    return int(time.time())
-
-
-def generate_nonce(length=8):
-    """Generate pseudorandom number."""
-    return ''.join([str(random.randint(0, 9)) for i in range(length)])
-
-
-def generate_verifier(length=8):
-    """Generate pseudorandom number."""
-    return ''.join([str(random.randint(0, 9)) for i in range(length)])
-
-
-class Consumer(object):
-    """A consumer of OAuth-protected services.
-    The OAuth consumer is a "third-party" service that wants to access
-    protected resources from an OAuth service provider on behalf of an end
-    user. It's kind of the OAuth client.
-    Usually a consumer must be registered with the service provider by the
-    developer of the consumer software. As part of that process, the service
-    provider gives the consumer a *key* and a *secret* with which the consumer
-    software can identify itself to the service. The consumer will include its
-    key in each request to identify itself, but will use its secret only when
-    signing requests, to prove that the request is from that particular
-    registered consumer.
-    Once registered, the consumer can then use its consumer credentials to ask
-    the service provider for a request token, kicking off the OAuth
-    authorization process.
-    """
-
-    key = None
-    secret = None
-
-    def __init__(self, key, secret):
-        self.key = key
-        self.secret = secret
-
-        if self.key is None or self.secret is None:
-            raise ValueError("Key and secret must be set.")
-
-    def __str__(self):
-        data = {'oauth_consumer_key': self.key,
-            'oauth_consumer_secret': self.secret}
-
-        return urllib.urlencode(data)
-
-
-class Token(object):
-    """An OAuth credential used to request authorization or a protected
-    resource.
-    Tokens in OAuth comprise a *key* and a *secret*. The key is included in
-    requests to identify the token being used, but the secret is used only in
-    the signature, to prove that the requester is who the server gave the
-    token to.
-    When first negotiating the authorization, the consumer asks for a *request
-    token* that the live user authorizes with the service provider. The
-    consumer then exchanges the request token for an *access token* that can
-    be used to access protected resources.
-    """
-
-    key = None
-    secret = None
-    callback = None
-    callback_confirmed = None
-    verifier = None
-
-    def __init__(self, key, secret):
-        self.key = key
-        self.secret = secret
-
-        if self.key is None or self.secret is None:
-            raise ValueError("Key and secret must be set.")
-
-    def set_callback(self, callback):
-        self.callback = callback
-        self.callback_confirmed = 'true'
-
-    def set_verifier(self, verifier=None):
-        if verifier is not None:
-            self.verifier = verifier
-        else:
-            self.verifier = generate_verifier()
-
-    def get_callback_url(self):
-        if self.callback and self.verifier:
-            # Append the oauth_verifier.
-            parts = urlparse.urlparse(self.callback)
-            scheme, netloc, path, params, query, fragment = parts[:6]
-            if query:
-                query = '%s&oauth_verifier=%s' % (query, self.verifier)
-            else:
-                query = 'oauth_verifier=%s' % self.verifier
-            return urlparse.urlunparse((scheme, netloc, path, params,
-                query, fragment))
-        return self.callback
-
-    def to_string(self):
-        """Returns this token as a plain string, suitable for storage.
-        The resulting string includes the token's secret, so you should never
-        send or store this string where a third party can read it.
-        """
-
-        data = {
-            'oauth_token': self.key,
-            'oauth_token_secret': self.secret,
-        }
-
-        if self.callback_confirmed is not None:
-            data['oauth_callback_confirmed'] = self.callback_confirmed
-        return urllib.urlencode(data)
-    @staticmethod
-    def from_string(s):
-        """Deserializes a token from a string like one returned by
-        `to_string()`."""
-
-        if not len(s):
-            raise ValueError("Invalid parameter string.")
-
-        params = parse_qs(s, keep_blank_values=False)
-        if not len(params):
-            raise ValueError("Invalid parameter string.")
-
-        try:
-            key = params['oauth_token'][0]
-        except Exception:
-            raise ValueError("'oauth_token' not found in OAuth request.")
-
-        try:
-            secret = params['oauth_token_secret'][0]
-        except Exception:
-            raise ValueError("'oauth_token_secret' not found in " 
-                "OAuth request.")
-
-        token = Token(key, secret)
-        try:
-            token.callback_confirmed = params['oauth_callback_confirmed'][0]
-        except KeyError:
-            pass  # 1.0, no callback confirmed.
-        return token
-
-    def __str__(self):
-        return self.to_string()
-
-
-def setter(attr):
-    name = attr.__name__
-    def getter(self):
-        try:
-            return self.__dict__[name]
-        except KeyError:
-            raise AttributeError(name)
-    def deleter(self):
-        del self.__dict__[name]
-    return property(getter, attr, deleter)
-
-
-class Request(dict):
-    """The parameters and information for an HTTP request, suitable for
-    authorizing with OAuth credentials.
-    When a consumer wants to access a service's protected resources, it does
-    so using a signed HTTP request identifying itself (the consumer) with its
-    key, and providing an access token authorized by the end user to access
-    those resources.
-    """
-    version = OAUTH_VERSION
-
-    def __init__(self, method=HTTP_METHOD, url=None, parameters=None,
-                 body='', is_form_encoded=False):
-        if url is not None:
-            self.url = to_unicode(url)
-        self.method = method
-        if parameters is not None:
-            for k, v in parameters.iteritems():
-                k = to_unicode(k)
-                v = to_unicode_optional_iterator(v)
-                self[k] = v
-        self.body = body
-        self.is_form_encoded = is_form_encoded
-
-
-    @setter
-    def url(self, value):
-        self.__dict__['url'] = value
-        if value is not None:
-            scheme, netloc, path, params, query, fragment = urlparse.urlparse(value)
-
-            # Exclude default port numbers.
-            if scheme == 'http' and netloc[-3:] == ':80':
-                netloc = netloc[:-3]
-            elif scheme == 'https' and netloc[-4:] == ':443':
-                netloc = netloc[:-4]
-            if scheme not in ('http', 'https'):
-                raise ValueError("Unsupported URL %s (%s)." % (value, scheme))
-
-            # Normalized URL excludes params, query, and fragment.
-            self.normalized_url = urlparse.urlunparse((scheme, netloc, path, None, None, None))
-        else:
-            self.normalized_url = None
-            self.__dict__['url'] = None
-    @setter
-    def method(self, value):
-        self.__dict__['method'] = value.upper()
-    def _get_timestamp_nonce(self):
-        return self['oauth_timestamp'], self['oauth_nonce']
-    def get_nonoauth_parameters(self):
-        """Get any non-OAuth parameters."""
-        return dict([(k, v) for k, v in self.iteritems() 
-                    if not k.startswith('oauth_')])
-    def to_header(self, realm=''):
-        """Serialize as a header for an HTTPAuth request."""
-        oauth_params = ((k, v) for k, v in self.items() 
-                            if k.startswith('oauth_'))
-        stringy_params = ((k, escape(str(v))) for k, v in oauth_params)
-        header_params = ('%s="%s"' % (k, v) for k, v in stringy_params)
-        params_header = ', '.join(header_params)
-        auth_header = 'OAuth realm="%s"' % realm
-        if params_header:
-            auth_header = "%s, %s" % (auth_header, params_header)
-        return {'Authorization': auth_header}
-    def to_postdata(self):
-        """Serialize as post data for a POST request."""
-        d = {}
-        for k, v in self.iteritems():
-            d[k.encode('utf-8')] = to_utf8_optional_iterator(v)
-
-        # tell urlencode to deal with sequence values and map them correctly
-        # to resulting querystring. for example self["k"] = ["v1", "v2"] will
-        # result in 'k=v1&k=v2' and not k=%5B%27v1%27%2C+%27v2%27%5D
-        return urllib.urlencode(d, True).replace('+', '%20')
-    def to_url(self):
-        """Serialize as a URL for a GET request."""
-        base_url = urlparse.urlparse(self.url)
-        try:
-            query = base_url.query
-        except AttributeError:
-            # must be python <2.5
-            query = base_url[4]
-        query = parse_qs(query)
-        for k, v in self.items():
-            query.setdefault(k, []).append(v)
-        
-        try:
-            scheme = base_url.scheme
-            netloc = base_url.netloc
-            path = base_url.path
-            params = base_url.params
-            fragment = base_url.fragment
-        except AttributeError:
-            # must be python <2.5
-            scheme = base_url[0]
-            netloc = base_url[1]
-            path = base_url[2]
-            params = base_url[3]
-            fragment = base_url[5]
-        
-        url = (scheme, netloc, path, params,
-               urllib.urlencode(query, True), fragment)
-        return urlparse.urlunparse(url)
-
-    def get_parameter(self, parameter):
-        ret = self.get(parameter)
-        if ret is None:
-            raise Error('Parameter not found: %s' % parameter)
-
-        return ret
-
-    def get_normalized_parameters(self):
-        """Return a string that contains the parameters that must be signed."""
-        items = []
-        for key, value in self.iteritems():
-            if key == 'oauth_signature':
-                continue
-            # 1.0a/9.1.1 states that kvp must be sorted by key, then by value,
-            # so we unpack sequence values into multiple items for sorting.
-            if isinstance(value, basestring):
-                items.append((to_utf8_if_string(key), to_utf8(value)))
-            else:
-                try:
-                    value = list(value)
-                except TypeError, e:
-                    assert 'is not iterable' in str(e)
-                    items.append((to_utf8_if_string(key), to_utf8_if_string(value)))
-                else:
-                    items.extend((to_utf8_if_string(key), to_utf8_if_string(item)) for item in value)
-
-        # Include any query string parameters from the provided URL
-        query = urlparse.urlparse(self.url)[4]
-
-        url_items = self._split_url_string(query).items()
-        url_items = [(to_utf8(k), to_utf8(v)) for k, v in url_items if k != 'oauth_signature' ]
-        items.extend(url_items)
-
-        items.sort()
-        encoded_str = urllib.urlencode(items)
-        # Encode signature parameters per Oauth Core 1.0 protocol
-        # spec draft 7, section 3.6
-        # (http://tools.ietf.org/html/draft-hammer-oauth-07#section-3.6)
-        # Spaces must be encoded with "%20" instead of "+"
-        return encoded_str.replace('+', '%20').replace('%7E', '~')
-
-    def sign_request(self, signature_method, consumer, token):
-        """Set the signature parameter to the result of sign."""
-
-        if not self.is_form_encoded:
-            # according to
-            # http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html
-            # section 4.1.1 "OAuth Consumers MUST NOT include an
-            # oauth_body_hash parameter on requests with form-encoded
-            # request bodies."
-            self['oauth_body_hash'] = base64.b64encode(sha(self.body).digest())
-
-        if 'oauth_consumer_key' not in self:
-            self['oauth_consumer_key'] = consumer.key
-
-        if token and 'oauth_token' not in self:
-            self['oauth_token'] = token.key
-
-        self['oauth_signature_method'] = signature_method.name
-        self['oauth_signature'] = signature_method.sign(self, consumer, token)
-    @classmethod
-    def make_timestamp(cls):
-        """Get seconds since epoch (UTC)."""
-        return str(int(time.time()))
-    @classmethod
-    def make_nonce(cls):
-        """Generate pseudorandom number."""
-        return str(random.randint(0, 100000000))
-    @classmethod
-    def from_request(cls, http_method, http_url, headers=None, parameters=None,
-            query_string=None):
-        """Combines multiple parameter sources."""
-        if parameters is None:
-            parameters = {}
-        # Headers
-        if headers and 'Authorization' in headers:
-            auth_header = headers['Authorization']
-            # Check that the authorization header is OAuth.
-            if auth_header[:6] == 'OAuth ':
-                auth_header = auth_header[6:]
-                try:
-                    # Get the parameters from the header.
-                    header_params = cls._split_header(auth_header)
-                    parameters.update(header_params)
-                except:
-                    raise Error('Unable to parse OAuth parameters from '
-                        'Authorization header.')
-        # GET or POST query string.
-        if query_string:
-            query_params = cls._split_url_string(query_string)
-            parameters.update(query_params)
-        # URL parameters.
-        param_str = urlparse.urlparse(http_url)[4] # query
-        url_params = cls._split_url_string(param_str)
-        parameters.update(url_params)
-        if parameters:
-            return cls(http_method, http_url, parameters)
-        return None
-    @classmethod
-    def from_consumer_and_token(cls, consumer, token=None,
-            http_method=HTTP_METHOD, http_url=None, parameters=None,
-            body='', is_form_encoded=False):
-        if not parameters:
-            parameters = {}
-        defaults = {
-            'oauth_consumer_key': consumer.key,
-            'oauth_timestamp': cls.make_timestamp(),
-            'oauth_nonce': cls.make_nonce(),
-            'oauth_version': cls.version,
-        }
-        defaults.update(parameters)
-        parameters = defaults
-        if token:
-            parameters['oauth_token'] = token.key
-            if token.verifier:
-                parameters['oauth_verifier'] = token.verifier
-        return Request(http_method, http_url, parameters, body=body, 
-                       is_form_encoded=is_form_encoded)
-    @classmethod
-    def from_token_and_callback(cls, token, callback=None, 
-        http_method=HTTP_METHOD, http_url=None, parameters=None):
-
-        if not parameters:
-            parameters = {}
-        parameters['oauth_token'] = token.key
-        if callback:
-            parameters['oauth_callback'] = callback
-        return cls(http_method, http_url, parameters)
-    @staticmethod
-    def _split_header(header):
-        """Turn Authorization: header into parameters."""
-        params = {}
-        parts = header.split(',')
-        for param in parts:
-            # Ignore realm parameter.
-            if param.find('realm') > -1:
-                continue
-            # Remove whitespace.
-            param = param.strip()
-            # Split key-value.
-            param_parts = param.split('=', 1)
-            # Remove quotes and unescape the value.
-            params[param_parts[0]] = urllib.unquote(param_parts[1].strip('\"'))
-        return params
-    @staticmethod
-    def _split_url_string(param_str):
-        """Turn URL string into parameters."""
-        parameters = parse_qs(param_str.encode('utf-8'), keep_blank_values=True)
-        for k, v in parameters.iteritems():
-            parameters[k] = urllib.unquote(v[0])
-        return parameters
-
-
-class Client(httplib2.Http):
-    """OAuthClient is a worker to attempt to execute a request."""
-
-    def __init__(self, consumer, token=None, cache=None, timeout=None,
-        proxy_info=None):
-
-        if consumer is not None and not isinstance(consumer, Consumer):
-            raise ValueError("Invalid consumer.")
-
-        if token is not None and not isinstance(token, Token):
-            raise ValueError("Invalid token.")
-
-        self.consumer = consumer
-        self.token = token
-        self.method = SignatureMethod_HMAC_SHA1()
-
-        httplib2.Http.__init__(self, cache=cache, timeout=timeout, proxy_info=proxy_info)
-
-    def set_signature_method(self, method):
-        if not isinstance(method, SignatureMethod):
-            raise ValueError("Invalid signature method.")
-
-        self.method = method
-
-    def request(self, uri, method="GET", body='', headers=None, 
-        redirections=httplib2.DEFAULT_MAX_REDIRECTS, connection_type=None):
-        DEFAULT_POST_CONTENT_TYPE = 'application/x-www-form-urlencoded'
-
-        if not isinstance(headers, dict):
-            headers = {}
-
-        if method == "POST":
-            headers['Content-Type'] = headers.get('Content-Type', 
-                DEFAULT_POST_CONTENT_TYPE)
-
-        is_form_encoded = \
-            headers.get('Content-Type') == 'application/x-www-form-urlencoded'
-
-        if is_form_encoded and body:
-            parameters = parse_qs(body)
-        else:
-            parameters = None
-
-        req = Request.from_consumer_and_token(self.consumer, 
-            token=self.token, http_method=method, http_url=uri, 
-            parameters=parameters, body=body, is_form_encoded=is_form_encoded)
-
-        req.sign_request(self.method, self.consumer, self.token)
-
-        schema, rest = urllib.splittype(uri)
-        if rest.startswith('//'):
-            hierpart = '//'
-        else:
-            hierpart = ''
-        host, rest = urllib.splithost(rest)
-
-        realm = schema + ':' + hierpart + host
-
-        if is_form_encoded:
-            body = req.to_postdata()
-        elif method == "GET":
-            uri = req.to_url()
-        else:
-            headers.update(req.to_header(realm=realm))
-
-        return httplib2.Http.request(self, uri, method=method, body=body,
-            headers=headers, redirections=redirections,
-            connection_type=connection_type)
-
-
-class Server(object):
-    """A skeletal implementation of a service provider, providing protected
-    resources to requests from authorized consumers.
-    This class implements the logic to check requests for authorization. You
-    can use it with your web server or web framework to protect certain
-    resources with OAuth.
-    """
-
-    timestamp_threshold = 300 # In seconds, five minutes.
-    version = OAUTH_VERSION
-    signature_methods = None
-
-    def __init__(self, signature_methods=None):
-        self.signature_methods = signature_methods or {}
-
-    def add_signature_method(self, signature_method):
-        self.signature_methods[signature_method.name] = signature_method
-        return self.signature_methods
-
-    def verify_request(self, request, consumer, token):
-        """Verifies an api call and checks all the parameters."""
-
-        self._check_version(request)
-        self._check_signature(request, consumer, token)
-        parameters = request.get_nonoauth_parameters()
-        return parameters
-
-    def build_authenticate_header(self, realm=''):
-        """Optional support for the authenticate header."""
-        return {'WWW-Authenticate': 'OAuth realm="%s"' % realm}
-
-    def _check_version(self, request):
-        """Verify the correct version of the request for this server."""
-        version = self._get_version(request)
-        if version and version != self.version:
-            raise Error('OAuth version %s not supported.' % str(version))
-
-    def _get_version(self, request):
-        """Return the version of the request for this server."""
-        try:
-            version = request.get_parameter('oauth_version')
-        except:
-            version = OAUTH_VERSION
-
-        return version
-
-    def _get_signature_method(self, request):
-        """Figure out the signature with some defaults."""
-        try:
-            signature_method = request.get_parameter('oauth_signature_method')
-        except:
-            signature_method = SIGNATURE_METHOD
-
-        try:
-            # Get the signature method object.
-            signature_method = self.signature_methods[signature_method]
-        except:
-            signature_method_names = ', '.join(self.signature_methods.keys())
-            raise Error('Signature method %s not supported try one of the following: %s' % (signature_method, signature_method_names))
-
-        return signature_method
-
-    def _get_verifier(self, request):
-        return request.get_parameter('oauth_verifier')
-
-    def _check_signature(self, request, consumer, token):
-        timestamp, nonce = request._get_timestamp_nonce()
-        self._check_timestamp(timestamp)
-        signature_method = self._get_signature_method(request)
-
-        try:
-            signature = request.get_parameter('oauth_signature')
-        except:
-            raise MissingSignature('Missing oauth_signature.')
-
-        # Validate the signature.
-        valid = signature_method.check(request, consumer, token, signature)
-
-        if not valid:
-            key, base = signature_method.signing_base(request, consumer, token)
-
-            raise Error('Invalid signature. Expected signature base ' 
-                'string: %s' % base)
-
-    def _check_timestamp(self, timestamp):
-        """Verify that timestamp is recentish."""
-        timestamp = int(timestamp)
-        now = int(time.time())
-        lapsed = now - timestamp
-        if lapsed > self.timestamp_threshold:
-            raise Error('Expired timestamp: given %d and now %s has a '
-                'greater difference than threshold %d' % (timestamp, now, 
-                    self.timestamp_threshold))
-
-
-class SignatureMethod(object):
-    """A way of signing requests.
-    The OAuth protocol lets consumers and service providers pick a way to sign
-    requests. This interface shows the methods expected by the other `oauth`
-    modules for signing requests. Subclass it and implement its methods to
-    provide a new way to sign requests.
-    """
-
-    def signing_base(self, request, consumer, token):
-        """Calculates the string that needs to be signed.
-
-        This method returns a 2-tuple containing the starting key for the
-        signing and the message to be signed. The latter may be used in error
-        messages to help clients debug their software.
-
-        """
-        raise NotImplementedError
-
-    def sign(self, request, consumer, token):
-        """Returns the signature for the given request, based on the consumer
-        and token also provided.
-
-        You should use your implementation of `signing_base()` to build the
-        message to sign. Otherwise it may be less useful for debugging.
-
-        """
-        raise NotImplementedError
-
-    def check(self, request, consumer, token, signature):
-        """Returns whether the given signature is the correct signature for
-        the given consumer and token signing the given request."""
-        built = self.sign(request, consumer, token)
-        return built == signature
-
-
-class SignatureMethod_HMAC_SHA1(SignatureMethod):
-    name = 'HMAC-SHA1'
-
-    def signing_base(self, request, consumer, token):
-        if not hasattr(request, 'normalized_url') or request.normalized_url is None:
-            raise ValueError("Base URL for request is not set.")
-
-        sig = (
-            escape(request.method),
-            escape(request.normalized_url),
-            escape(request.get_normalized_parameters()),
-        )
-
-        key = '%s&' % escape(consumer.secret)
-        if token:
-            key += escape(token.secret)
-        raw = '&'.join(sig)
-        return key, raw
-
-    def sign(self, request, consumer, token):
-        """Builds the base signature string."""
-        key, raw = self.signing_base(request, consumer, token)
-
-        hashed = hmac.new(key, raw, sha)
-
-        # Calculate the digest base 64.
-        return binascii.b2a_base64(hashed.digest())[:-1]
-
-
-class SignatureMethod_PLAINTEXT(SignatureMethod):
-
-    name = 'PLAINTEXT'
-
-    def signing_base(self, request, consumer, token):
-        """Concatenates the consumer key and secret with the token's
-        secret."""
-        sig = '%s&' % escape(consumer.secret)
-        if token:
-            sig = sig + escape(token.secret)
-        return sig, sig
-
-    def sign(self, request, consumer, token):
-        key, raw = self.signing_base(request, consumer, token)
-        return raw
diff --git a/pithos/im/target/oauth2/_version.py b/pithos/im/target/oauth2/_version.py
deleted file mode 100644 (file)
index 0d74e05..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-# This is the version of this source code.
-
-manual_verstr = "1.5"
-
-
-
-auto_build_num = "170"
-
-
-
-verstr = manual_verstr + "." + auto_build_num
-try:
-    from pyutil.version_class import Version as pyutil_Version
-    __version__ = pyutil_Version(verstr)
-except (ImportError, ValueError):
-    # Maybe there is no pyutil installed.
-    from distutils.version import LooseVersion as distutils_Version
-    __version__ = distutils_Version(verstr)
diff --git a/pithos/im/target/oauth2/clients/__init__.py b/pithos/im/target/oauth2/clients/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/pithos/im/target/oauth2/clients/imap.py b/pithos/im/target/oauth2/clients/imap.py
deleted file mode 100644 (file)
index 68b7cd8..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-"""
-The MIT License
-
-Copyright (c) 2007-2010 Leah Culver, Joe Stump, Mark Paschal, Vic Fryzel
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-"""
-
-import oauth2
-import imaplib
-
-
-class IMAP4_SSL(imaplib.IMAP4_SSL):
-    """IMAP wrapper for imaplib.IMAP4_SSL that implements XOAUTH."""
-
-    def authenticate(self, url, consumer, token):
-        if consumer is not None and not isinstance(consumer, oauth2.Consumer):
-            raise ValueError("Invalid consumer.")
-
-        if token is not None and not isinstance(token, oauth2.Token):
-            raise ValueError("Invalid token.")
-
-        imaplib.IMAP4_SSL.authenticate(self, 'XOAUTH',
-            lambda x: oauth2.build_xoauth_string(url, consumer, token))
diff --git a/pithos/im/target/oauth2/clients/smtp.py b/pithos/im/target/oauth2/clients/smtp.py
deleted file mode 100644 (file)
index 3e7bf0b..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-"""
-The MIT License
-
-Copyright (c) 2007-2010 Leah Culver, Joe Stump, Mark Paschal, Vic Fryzel
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-"""
-
-import oauth2
-import smtplib
-import base64
-
-
-class SMTP(smtplib.SMTP):
-    """SMTP wrapper for smtplib.SMTP that implements XOAUTH."""
-
-    def authenticate(self, url, consumer, token):
-        if consumer is not None and not isinstance(consumer, oauth2.Consumer):
-            raise ValueError("Invalid consumer.")
-
-        if token is not None and not isinstance(token, oauth2.Token):
-            raise ValueError("Invalid token.")
-
-        self.docmd('AUTH', 'XOAUTH %s' % \
-            base64.b64encode(oauth2.build_xoauth_string(url, consumer, token)))
diff --git a/pithos/im/target/shibboleth.py b/pithos/im/target/shibboleth.py
deleted file mode 100644 (file)
index 8dfc0e6..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from django.http import HttpResponseBadRequest
-from django.core.urlresolvers import reverse
-
-from pithos.im.target.util import get_or_create_user, prepare_response
-
-
-class Tokens:
-    # these are mapped by the Shibboleth SP software
-    SHIB_EPPN = "HTTP_EPPN" # eduPersonPrincipalName
-    SHIB_NAME = "HTTP_SHIB_INETORGPERSON_GIVENNAME"
-    SHIB_SURNAME = "HTTP_SHIB_PERSON_SURNAME"
-    SHIB_CN = "HTTP_SHIB_PERSON_COMMONNAME"
-    SHIB_DISPLAYNAME = "HTTP_SHIB_INETORGPERSON_DISPLAYNAME"
-    SHIB_EP_AFFILIATION = "HTTP_SHIB_EP_AFFILIATION"
-    SHIB_SESSION_ID = "HTTP_SHIB_SESSION_ID"
-
-
-def login(request):
-    tokens = request.META
-    
-    try:
-        eppn = tokens[Tokens.SHIB_EPPN]
-    except KeyError:
-        return HttpResponseBadRequest("Missing unique token in request")
-    
-    if Tokens.SHIB_DISPLAYNAME in tokens:
-        realname = tokens[Tokens.SHIB_DISPLAYNAME]
-    elif Tokens.SHIB_CN in tokens:
-        realname = tokens[Tokens.SHIB_CN]
-    elif Tokens.SHIB_NAME in tokens and Tokens.SHIB_SURNAME in tokens:
-        realname = tokens[Tokens.SHIB_NAME] + ' ' + tokens[Tokens.SHIB_SURNAME]
-    else:
-        return HttpResponseBadRequest("Missing user name in request")
-    
-    affiliation = tokens.get(Tokens.SHIB_EP_AFFILIATION, '')
-    
-    return prepare_response(request,
-                            get_or_create_user(eppn, realname, affiliation, 0),
-                            request.GET.get('next'),
-                            'renew' in request.GET)
diff --git a/pithos/im/target/twitter.py b/pithos/im/target/twitter.py
deleted file mode 100644 (file)
index 4831ab6..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-# This is based on the docs at: https://github.com/simplegeo/python-oauth2
-
-import oauth2 as oauth
-import urlparse
-
-from django.conf import settings
-from django.http import HttpResponse
-from django.utils import simplejson as json
-
-from pithos.im.target.util import get_or_create_user, prepare_response
-
-# It's probably a good idea to put your consumer's OAuth token and
-# OAuth secret into your project's settings. 
-consumer = oauth.Consumer(settings.TWITTER_KEY, settings.TWITTER_SECRET)
-client = oauth.Client(consumer)
-
-request_token_url = 'http://twitter.com/oauth/request_token'
-access_token_url = 'http://twitter.com/oauth/access_token'
-
-# This is the slightly different URL used to authenticate/authorize.
-authenticate_url = 'http://twitter.com/oauth/authenticate'
-
-def login(request):
-    # Step 1. Get a request token from Twitter.
-    resp, content = client.request(request_token_url, "GET")
-    if resp['status'] != '200':
-        raise Exception("Invalid response from Twitter.")
-    request_token = dict(urlparse.parse_qsl(content))
-    if request.GET.get('next'):
-        request_token['next'] = request.GET['next']
-    
-    # Step 2. Store the request token in a session for later use.
-    response = HttpResponse()
-    response.set_cookie('Twitter-Request-Token', value=json.dumps(request_token), max_age=300)
-    
-    # Step 3. Redirect the user to the authentication URL.
-    url = "%s?oauth_token=%s" % (authenticate_url, request_token['oauth_token'])
-    response['Location'] = url
-    response.status_code = 302
-    
-    return response
-
-def authenticated(request):
-    # Step 1. Use the request token in the session to build a new client.
-    data = request.COOKIES.get('Twitter-Request-Token', None)
-    if not data:
-        raise Exception("Request token cookie not found.")
-    request_token = json.loads(data)
-    if not hasattr(request_token, '__getitem__'):
-        raise BadRequest('Invalid data formating')
-    try:
-        token = oauth.Token(request_token['oauth_token'],
-                            request_token['oauth_token_secret'])
-    except:
-        raise BadRequest('Invalid request token cookie formatting')
-    client = oauth.Client(consumer, token)
-    
-    # Step 2. Request the authorized access token from Twitter.
-    resp, content = client.request(access_token_url, "GET")
-    if resp['status'] != '200':
-        raise Exception("Invalid response from Twitter.")
-    
-    """
-    This is what you'll get back from Twitter. Note that it includes the
-    user's user_id and screen_name.
-    {
-        'oauth_token_secret': 'IcJXPiJh8be3BjDWW50uCY31chyhsMHEhqJVsphC3M',
-        'user_id': '120889797', 
-        'oauth_token': '120889797-H5zNnM3qE0iFoTTpNEHIz3noL9FKzXiOxwtnyVOD',
-        'screen_name': 'heyismysiteup'
-    }
-    """
-    access_token = dict(urlparse.parse_qsl(content))
-    
-    # Step 3. Lookup the user or create them if they don't exist.
-    
-    # When creating the user I just use their screen_name@twitter.com
-    # for their email and the oauth_token_secret for their password.
-    # These two things will likely never be used. Alternatively, you 
-    # can prompt them for their email here. Either way, the password 
-    # should never be used.
-    uniq = '%s@twitter.com' % access_token['screen_name']
-    realname = access_token['user_id']
-    
-    return prepare_response(request,
-                            get_or_create_user(uniq, realname, 'Twitter', 0),
-                            request_token.get('next'))
diff --git a/pithos/im/target/util.py b/pithos/im/target/util.py
deleted file mode 100644 (file)
index a23fed4..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-import logging
-import datetime
-
-from urlparse import urlsplit, urlunsplit
-from urllib import quote
-
-from django.conf import settings
-from django.http import HttpResponse
-from django.utils.http import urlencode
-from django.core.urlresolvers import reverse
-
-from pithos.im.models import User
-
-def get_or_create_user(uniq, realname, affiliation, level):
-    """Find or register a user into the internal database
-       and issue a token for subsequent requests.
-    """
-    
-    user, created = User.objects.get_or_create(uniq=uniq,
-        defaults={
-            'realname': realname,
-            'affiliation': affiliation,
-            'level': level,
-            'invitations': settings.INVITATIONS_PER_LEVEL[level],
-            'state':'PENDING',
-        })
-    if created:
-        user.renew_token()
-        user.save()
-        logging.info('Created user %s', user)
-    
-    return user
-
-def prepare_response(request, user, next='', renew=False):
-    """Return the unique username and the token
-       as 'X-Auth-User' and 'X-Auth-Token' headers,
-       or redirect to the URL provided in 'next'
-       with the 'user' and 'token' as parameters.
-       
-       Reissue the token even if it has not yet
-       expired, if the 'renew' parameter is present.
-    """
-    
-    if renew or user.auth_token_expires < datetime.datetime.now():
-        user.renew_token()
-        user.save()
-        
-    if next:
-        # TODO: Avoid redirect loops.
-        parts = list(urlsplit(next))
-        # Do not pass on user and token if we are on the same server.
-        if parts[1] and request.get_host() != parts[1]:
-            parts[3] = urlencode({'user': user.uniq, 'token': user.auth_token})
-            next = urlunsplit(parts)
-    
-    if settings.FORCE_PROFILE_UPDATE and not user.is_verified:
-        params = ''
-        if next:
-            params = '?' + urlencode({'next': next})
-        next = reverse('pithos.im.views.users_profile') + params
-    
-    response = HttpResponse()
-    expire_fmt = user.auth_token_expires.strftime('%a, %d-%b-%Y %H:%M:%S %Z')
-    cookie_value = quote(user.uniq + '|' + user.auth_token)
-    response.set_cookie('_pithos2_a', value=cookie_value, expires=expire_fmt, path='/')
-
-    if not next:
-        response['X-Auth-User'] = user.uniq
-        response['X-Auth-Token'] = user.auth_token
-        response.content = user.uniq + '\n' + user.auth_token + '\n'
-        response.status_code = 200
-    else:
-        response['Location'] = next
-        response.status_code = 302
-    return response
diff --git a/pithos/im/templates/activation.txt b/pithos/im/templates/activation.txt
deleted file mode 100644 (file)
index 19f722a..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
---- A translation in English follows ---
-
-Αγαπητέ/η {{ user.realname }},
-
-Έπειτα από αίτημα σας έχει δημιουργηθεί ο λογαρισμός σας  
-για την υπηρεσία {{ service }} της ΕΔΕΤ κατά την Alpha (πιλοτική) φάση λειτουργίας της.
-
-Για να τον ενεργοποιήσετε, χρησιμοποιήστε τον παρακάτω σύνδεσμο:
-
-{{ url }}
-
-Σημείωση:
-
-Η υπηρεσία θα είναι για μερικές εβδομάδες σε φάση λειτουργίας Alpha. Αν
-και έχουμε κάνει ότι είναι δυνατό για να εξασφαλίσουμε την ποιότητα της
-υπηρεσίας, δεν αποκλείεται να εμφανιστούν προβλήματα στο λογισμικό
-διαχείρισης ή η υπηρεσία να μην είναι διαθέσιμη κατά διαστήματα. Για
-αυτό το λόγο, σας παρακαλούμε να μη μεταφέρετε ακόμη σημαντικά κομμάτια
-της δουλειάς σας στην υπηρεσία {{ service }}. Επίσης, παρακαλούμε να έχετε
-υπόψη σας ότι όλα τα δεδομένα, θα διαγραφούν κατά τη μετάβαση από την
-έκδοση Alpha στην έκδοση Beta. Θα υπάρξει έγκαιρη ειδοποίησή σας πριν
-από τη μετάβαση αυτή.
-
-Περισσότερα για την υπηρεσία θα βρείτε στο {{ baseurl }}, αφού
-έχετε ενεργοποιήσει την πρόσκλησή σας.
-
-Αναμένουμε τα σχόλια και τις παρατηρήσεις σας, για να βελτιώσουμε τη
-λειτουργικότητα και την αξιοπιστία της καινοτομικής αυτής υπηρεσίας.
-
-Για όποιες παρατηρήσεις ή προβλήματα στη λειτουργεία της υπηρεσίας μπορείτε να
-απευθυνθείτε στο {{ support }}.
-
-Σας ευχαριστούμε πολύ για τη συμμετοχή στην Alpha λειτουργία του {{ service }}.
-
-Με εκτίμηση,
-
-Εθνικό Δίκτυο Έρευνας και Τεχνολογίας (ΕΔΕΤ/GRNET)
-
---
-
-Dear {{ user.realname }},
-
-After your request a new account for GRNET's {{ service }} service has been created
-for its Alpha test phase.
-
-To activate the account, please use the following link:
-
-{{ url }}
-
-Please note:
-
-This service is, for a few weeks, in Alpha. Although every care has been
-taken to ensure high quality, it is possible there may still be software
-bugs, or periods of limited service availability. For this reason, we
-kindly request you do not transfer important parts of your work to
-{{ service }}, yet. Also, please bear in mind that all data, will be deleted
-when the service moves to Beta test. Before the transition, you will be
-notified in time.
-
-For more information, please visit {{ baseurl }}, after
-activating your invitation.
-
-We look forward to your feedback, to improve the functionality and
-reliability of this innovative service.
-
-For any remarks or problems you can contact {{ support }}.
-
-Thank you for participating in the Alpha test of {{ service }}.
-
-Greek Research and Technonogy Network - GRNET
diff --git a/pithos/im/templates/admin.html b/pithos/im/templates/admin.html
deleted file mode 100644 (file)
index 754e114..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{% extends "admin_base.html" %}
-
-{% block body %}
-<ul class="unstyled">
-  <li><strong>{{ stats.users }}</strong> User{{ stats.users|pluralize }} (<strong>{{ stats.pending }}</strong> pending)</li>
-  <li><strong>{{ stats.invitations }}</strong> Invitation{{ stats.invitations|pluralize }} sent (<strong>{{ stats.invitations_consumed }}</strong> consumed)</li>
-</ul>
-{% endblock body %}
diff --git a/pithos/im/templates/admin_base.html b/pithos/im/templates/admin_base.html
deleted file mode 100644 (file)
index a86c33f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends "base.html" %}
-    
-{% block tabs %}
-<ul class="tabs">
-  <li{% ifequal tab "home" %} class="active"{% endifequal %}>
-    <a href="{% url pithos.im.views.admin %}">Home</a>
-  </li>
-  <li{% ifequal tab "users" %} class="active"{% endifequal %}>
-    <a href="{% url pithos.im.views.users_list %}">Users</a>
-  </li>
-  <li{% ifequal tab "pending" %} class="active"{% endifequal %}>
-    <a href="{% url pithos.im.views.pending_users %}">Pending Users</a>
-  </li>
-  <li{% ifequal tab "invitations" %} class="active"{% endifequal %}>
-    <a href="{% url pithos.im.views.invitations_list %}">Invitations</a>
-  </li>
-</ul>
-{% endblock %}
-
-{% block body %}{% endblock %}
diff --git a/pithos/im/templates/base.html b/pithos/im/templates/base.html
deleted file mode 100644 (file)
index f43fbaf..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8" />
-  <title>{{ title|default:"User Admin" }}</title>
-  <link rel="stylesheet" href="/im/static/bootstrap.css">
-  <script src="/im/static/jquery.js"></script>
-  <script src="/im/static/jquery.tablesorter.js"></script>
-  <script src="/im/static/main.js"></script>
-  {% block head %}{% endblock %}
-</head>
-<body>
-  <div class="container">
-    <div style="padding: 5px 0px 0px 0px">
-      <img src="/im/static/banner.png" width="900" height="200">
-    </div>
-    {% block title %}{% endblock %}
-    
-    {% if message %}
-    <br />
-    <div class="alert-message.{{ status }}">
-      <p>{{ message }}</p>
-    </div>
-    {% endif %}
-
-    {% block tabs %}{% endblock %}
-
-    {% block body %}{% endblock %}
-  </div>
-</body>
-</html>
diff --git a/pithos/im/templates/index.html b/pithos/im/templates/index.html
deleted file mode 100644 (file)
index 7a76e1d..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-{% extends 'base.html'%}
-
-{% block title%}
-        <h2>Welcome</h2>
-        <p>Choose how to login. Or move on to <a href="admin">admin</a>.</p>
-{% endblock title%}
-    
-{% block body%}
-    <div class="row">
-    {% if "local" in im_modules %}
-      <div class="span4">
-        <h4>Local account</h4>
-        <form action="{% url pithos.im.target.local.login %}" method="post" class="form-stacked">
-          <fieldset>
-            <div class="clearfix">
-              <label for="username">Username:</label>
-              <div class="input">
-                <input class="span3" id="user-username" name="username" type="text" />
-              </div>
-            </div>
-            <div class="clearfix">
-              <label for="password">Password:</label>
-              <div class="input">
-                <input class="span3" id="user-password" name="password" type="password" />
-              </div>
-            </div>
-          </fieldset>
-         <div>
-            <a href="{% url pithos.im.views.register 'local' %}">Sign up</a>
-         </div>
-         <div>
-            <a href="{% url pithos.im.views.reclaim_password %}">Forgot your password?</a>
-         </div>
-         <br>
-          <div class="">
-            <input type="hidden" name="next" value="{{ next }}">
-            <button type="submit" class="btn primary">Go</button>
-          </div>
-        </form>
-      </div>
-    {% endif %}
-    {% if other_modules %}
-      <div class="span8">
-        <h4>Other provider</h4>
-        {% for o in other_modules %}
-            <a href="/im/login/{{ o }}{% ifnotequal next "" %}?next={{ next|urlencode }}{% endifnotequal %}" alt="{{ o|title }}"><img src="/im/static/{{ o }}.png" width="120" height="120"></a>
-        {% endfor %}
-      </div>
-    {% endif %}
-    </div>
-{% endblock body%}
diff --git a/pithos/im/templates/invitation.txt b/pithos/im/templates/invitation.txt
deleted file mode 100644 (file)
index 0204a0b..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
---- A translation in English follows ---
-
-Αγαπητέ/η {{ invitation.realname }},
-
-Ο/Η {{ invitation.inviter.realname }} ({{ invitation.inviter.email}}) σας έχει προσκαλέσει να χρησιμοποιήσετε
-την υπηρεσία {{ service }} της ΕΔΕΤ κατά την Alpha (πιλοτική) φάση λειτουργίας της.
-
-Για να αποκτήσετε πρόσβαση, χρησιμοποιήστε τον παρακάτω σύνδεσμο:
-
-{{ url }}
-
-Σημείωση:
-
-Η υπηρεσία θα είναι για μερικές εβδομάδες σε φάση λειτουργίας Alpha. Αν
-και έχουμε κάνει ότι είναι δυνατό για να εξασφαλίσουμε την ποιότητα της
-υπηρεσίας, δεν αποκλείεται να εμφανιστούν προβλήματα στο λογισμικό
-διαχείρισης ή η υπηρεσία να μην είναι διαθέσιμη κατά διαστήματα. Για
-αυτό το λόγο, σας παρακαλούμε να μη μεταφέρετε ακόμη σημαντικά κομμάτια
-της δουλειάς σας στην υπηρεσία {{ service }}. Επίσης, παρακαλούμε να έχετε
-υπόψη σας ότι όλα τα δεδομένα, θα διαγραφούν κατά τη μετάβαση από την
-έκδοση Alpha στην έκδοση Beta. Θα υπάρξει έγκαιρη ειδοποίησή σας πριν
-από τη μετάβαση αυτή.
-
-Διατηρήστε το παρόν mail στο mailbox σας, καθώς μέσω του συνδέσμου που
-περιέχει το mail αυτό μπορείτε να ξαναμπείτε, κάθε φορά που επιθυμείτε
-να χρησιμοποιήσετε την υπηρεσία από άλλο browser.
-
-Περισσότερα για την υπηρεσία θα βρείτε στο {{ baseurl }}, αφού
-έχετε ενεργοποιήσει την πρόσκλησή σας.
-
-Αναμένουμε τα σχόλια και τις παρατηρήσεις σας, για να βελτιώσουμε τη
-λειτουργικότητα και την αξιοπιστία της καινοτομικής αυτής υπηρεσίας.
-
-Για όποιες παρατηρήσεις ή προβλήματα στη λειτουργεία της υπηρεσίας μπορείτε να
-απευθυνθείτε στο {{ support }}.
-
-Σας ευχαριστούμε πολύ για τη συμμετοχή στην Alpha λειτουργία του {{ service }}.
-
-Με εκτίμηση,
-
-Εθνικό Δίκτυο Έρευνας και Τεχνολογίας (ΕΔΕΤ/GRNET)
-
---
-
-Dear {{ invitation.realname }},
-
-{{ invitation.inviter.realname }} has invited you to use GRNET's {{ service }} service
-during its Alpha test phase.
-
-To access the service, please use the following link:
-
-{{ url }}
-
-Please note:
-
-This service is, for a few weeks, in Alpha. Although every care has been
-taken to ensure high quality, it is possible there may still be software
-bugs, or periods of limited service availability. For this reason, we
-kindly request you do not transfer important parts of your work to
-{{ service }}, yet. Also, please bear in mind that all data, will be deleted
-when the service moves to Beta test. Before the transition, you will be
-notified in time.
-
-Please keep this mail in your mailbox, as you need the link above to
-re-enter the service, should you wish to login using a different browser.
-
-For more information, please visit {{ baseurl }}, after
-activating your invitation.
-
-We look forward to your feedback, to improve the functionality and
-reliability of this innovative service.
-
-For any remarks or problems you can contact {{ support }}.
-
-Thank you for participating in the Alpha test of {{ service }}.
-
-Greek Research and Technonogy Network - GRNET
diff --git a/pithos/im/templates/invitations.html b/pithos/im/templates/invitations.html
deleted file mode 100644 (file)
index d1eca50..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8" />
-  <title>Invitations</title>
-  <link rel="stylesheet" href="/im/static/bootstrap.css">
-</head>
-<body>
-<div class="container">
-  <h3>You have {{ user.invitations }} invitation{{ user.invitations|pluralize }} left.</h3>
-
-  {% if message %}
-  <br />
-  <div class="alert-message {{ status }}">
-    <p>{{ message }}</p>
-  </div>
-  {% endif %}
-
-  {% if user.invitations %}
-  <br />
-  <h4>Invite someone else:</h4>
-  <form method="post">
-    <div class="clearfix">
-      <label for="user-realname">Name</label>
-      <div class="input">
-        <input type="text" class="span4" id="user-realname" name="realname" />
-      </div>
-    </div>
-
-    <div class="clearfix">
-      <label for="user-uniq">Email</label>
-      <div class="input">
-        <input type="text" class="span4" id="user-uniq" name="uniq" />
-      </div>
-    </div>
-
-    <div class="actions">
-      <button type="reset" class="btn">Reset</button>
-      <button type="submit" class="btn primary">Invite</button>
-    </div>
-  </form>
-  {% endif %}
-</div>
-</body>
-</html>
diff --git a/pithos/im/templates/invitations_list.html b/pithos/im/templates/invitations_list.html
deleted file mode 100644 (file)
index e54b408..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-{% extends "admin_base.html" %}
-
-{% load formatters %}
-
-{% block body %}
-
-<div class="row">
-  <div class="offset10 span3">
-    <form method="get">
-      <div class="input">
-        <input class="span3" name="filter" type="search" placeholder="search" value="{{ filter }}">
-      </div>
-    </form>
-  </div>
-</div>
-
-<table class="zebra-striped id-sorted">
-  <thead>
-    <tr>
-      <th>ID</th>
-      <th>Uniq</th>
-      <th>Real Name</th>
-      <th>Code</th>
-      <th>Inviter Uniq</th>
-      <th>Inviter Real Name</th>
-      <th>Is consumed</th>
-      <th>Created</th>
-      <th>Consumed</th>
-    </tr>
-  </thead>
-  <tbody>
-    {% for inv in invitations %}
-    <tr>
-      <td>{{ inv.id }}</td>
-      <td>{{ inv.uniq }}</td>
-      <td>{{ inv.realname }}</td>
-      <td>{{ inv.code }}</td>
-      <td>{{ inv.inviter.uniq }}</td>
-      <td>{{ inv.inviter.realname }}</td>
-      <td>{{ inv.is_consumed }}</td>
-      <td>{{ inv.created }}</td>
-      <td>{{ inv.consumed }}</td>
-    </tr>
-    {% endfor %}
-  </tbody>
-</table>
-
-{% if pages|length > 1 %}
-<div class="pagination">
-  <ul>
-    {% if prev %}
-      <li class="prev"><a href="?page={{ prev }}{% if filter %}&filter={{ filter }}{% endif %}">&larr; Previous</a></li>
-    {% else %}
-      <li class="prev disabled"><a href="#">&larr; Previous</a></li>
-    {% endif %}
-
-    {% for p in pages %}
-      <li{% if page == p %} class="active"{% endif %}><a href="?page={{ p }}{% if filter %}&filter={{ filter }}{% endif %}">{{ p }}</a></li>
-    {% endfor %}
-
-    {% if next %}
-      <li class="next"><a href="?page={{ next }}{% if filter %}&filter={{ filter }}{% endif %}">&rarr; Next</a></li>
-    {% else %}
-      <li class="next disabled"><a href="#">&rarr; Next</a></li>
-    {% endif %}
-  </ul>
-</div>
-{% endif %}
-
-<a class="btn success" href="{% url pithos.im.views.invitations_export %}">Export</a>
-
-<br /><br />
-{% endblock body %}
diff --git a/pithos/im/templates/local_create.html b/pithos/im/templates/local_create.html
deleted file mode 100644 (file)
index 503711c..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-{% extends "base.html" %}
-
-{% block title%}
-        <h2>Sign up</h2>
-{% endblock title%}
-
-{% block body %}
-<form action="{% url pithos.im.views.local_create %}" method="post">
-{% if provider == 'local'%}
-  <div class="clearfix">
-    <label for="user-uniq">Username</label>
-    <div class="input">
-      <input class="span4" id="user-uniq" name="uniq" {%if inv %} value={{ inv.uniq }} {% endif %} type="text" />
-    </div>
-  </div>
-  
-  <div class="clearfix">
-    <label for="user-password">Password</label>
-    <div class="input">
-      <input class="span4" id="user-password" name="password" type="password" />
-    </div>
-  </div>
-  
-  <div class="clearfix">
-    <label for="user-password">Confirm Password</label>
-    <div class="input">
-      <input class="span4" id="user-retype-password" name="retype_password" type="password" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-realname">Real Name</label>
-    <div class="input">
-      <input class="span4" id="user-realname" name="realname" {%if inv %} value={{ inv.realname }} {% endif %} type="text" />
-    </div>
-  </div>
-  
-  <div class="clearfix">
-    <label for="user-email">Email</label>
-    <div class="input">
-      <input class="span4" id="user-email" name="email" type="text" />
-    </div>
-  </div>
-{% endif %}
-
-{% if provider == 'twitter' %}
-    <div class="clearfix">
-        <label for="user-uniq">Twitter </label>
-        <div class="input">
-            <input class="span4" id="user-uniq" name="uniq" {%if inv %} value={{ inv.uniq }} {% endif %} type="text" />
-        </div>
-    </div>
-{% endif %}
-
-  <div class="actions">
-    <button type="submit" class="btn primary">Create</button>
-    <button type="reset" class="btn">Reset</button>
-  </div>
-</form>
-{% endblock body %}
diff --git a/pithos/im/templates/password.txt b/pithos/im/templates/password.txt
deleted file mode 100644 (file)
index e3f4e32..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
---- A translation in English follows ---
-
-Αγαπητέ/η {{ user.realname }},
-
-Για να ανανεώσετε τον κωδικό πρόσβασης σας
-για την υπηρεσία {{ service }} της ΕΔΕΤ κατά την Alpha (πιλοτική) φάση λειτουργίας της,
-χρησιμοποιήστε τον παρακάτω σύνδεσμο:
-
-{{ url }}
-
-Σημείωση:
-
-Η υπηρεσία θα είναι για μερικές εβδομάδες σε φάση λειτουργίας Alpha. Αν
-και έχουμε κάνει ότι είναι δυνατό για να εξασφαλίσουμε την ποιότητα της
-υπηρεσίας, δεν αποκλείεται να εμφανιστούν προβλήματα στο λογισμικό
-διαχείρισης ή η υπηρεσία να μην είναι διαθέσιμη κατά διαστήματα. Για
-αυτό το λόγο, σας παρακαλούμε να μη μεταφέρετε ακόμη σημαντικά κομμάτια
-της δουλειάς σας στην υπηρεσία {{ service }}. Επίσης, παρακαλούμε να έχετε
-υπόψη σας ότι όλα τα δεδομένα, θα διαγραφούν κατά τη μετάβαση από την
-έκδοση Alpha στην έκδοση Beta. Θα υπάρξει έγκαιρη ειδοποίησή σας πριν
-από τη μετάβαση αυτή.
-
-Περισσότερα για την υπηρεσία θα βρείτε στο {{ baseurl }}, αφού
-έχετε ενεργοποιήσει την πρόσκλησή σας.
-
-Για όποιες παρατηρήσεις ή προβλήματα στη λειτουργεία της υπηρεσίας μπορείτε να
-
-Αναμένουμε τα σχόλια και τις παρατηρήσεις σας, για να βελτιώσουμε τη
-λειτουργικότητα και την αξιοπιστία της καινοτομικής αυτής υπηρεσίας.
-
-
-Σας ευχαριστούμε πολύ για τη συμμετοχή στην Alpha λειτουργία του {{ service }}.
-
-Με εκτίμηση,
-
-Εθνικό Δίκτυο Έρευνας και Τεχνολογίας (ΕΔΕΤ/GRNET)
-
---
-
-Dear {{ user.realname }},
-
-Yuu can use the following link:
-
-{{ url }}
-
-to reset your password for GRNET's {{ service }} service has been created
-for its Alpha test phase.
-
-To activate the account, please use the following link:
-
-
-Please note:
-
-This service is, for a few weeks, in Alpha. Although every care has been
-taken to ensure high quality, it is possible there may still be software
-bugs, or periods of limited service availability. For this reason, we
-kindly request you do not transfer important parts of your work to
-{{ service }}, yet. Also, please bear in mind that all data, will be deleted
-when the service moves to Beta test. Before the transition, you will be
-notified in time.
-
-For more information, please visit {{ baseurl }}, after
-activating your invitation.
-
-We look forward to your feedback, to improve the functionality and
-reliability of this innovative service.
-
-For any remarks or problems you can contact {{ support }}.
-
-Thank you for participating in the Alpha test of {{ service }}.
-
-Greek Research and Technonogy Network - GRNET
diff --git a/pithos/im/templates/pending_users.html b/pithos/im/templates/pending_users.html
deleted file mode 100644 (file)
index d5effb3..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-{% extends "admin_base.html" %}
-
-{% load formatters %}
-
-{% block body %}
-
-<div class="row">
-  <div class="offset10 span3">
-    <form method="get">
-      <div class="input">
-        <input class="span3" name="filter" type="search" placeholder="search" value="{{ filter }}">
-      </div>
-    </form>
-  </div>
-</div>
-
-<table class="zebra-striped id-sorted">
-  <thead>
-    <tr>
-      <th>ID</th>
-      <th>Uniq</th>
-      <th>Real Name</th>
-      <th>Affiliation</th>
-      <th>Email</th>
-      <th>Inviter</th>
-      <th>Action</th>
-    </tr>
-  </thead>
-  <tbody>
-    {% for user in users %}
-    <tr>
-      <td>{{ user.id }}</td>
-      <td>{{ user.uniq }}</td>
-      <td>{{ user.realname }}</td>
-      <td>{{ user.affiliation }}</td>
-      <td>{{ user.email }}</td>
-      <td>{{ user.inviter.realname }}</td>
-      <td>
-        <form action="{% url pithos.im.views.users_activate user.id %}" method="post">
-        <input type="hidden" name="page" value="{{ page }}">
-        <button type="submit" class="btn primary">Activate</button>
-        </form>
-    </tr>
-    {% endfor %}
-  </tbody>
-</table>
-
-{% if pages|length > 1 %}
-<div class="pagination">
-  <ul>
-    {% if prev %}
-      <li class="prev"><a href="?page={{ prev }}{% if filter %}&filter={{ filter }}{% endif %}">&larr; Previous</a></li>
-    {% else %}
-      <li class="prev disabled"><a href="#">&larr; Previous</a></li>
-    {% endif %}
-
-    {% for p in pages %}
-      <li{% if page == p %} class="active"{% endif %}><a href="?page={{ p }}{% if filter %}&filter={{ filter }}{% endif %}">{{ p }}</a></li>
-    {% endfor %}
-
-    {% if next %}
-      <li class="next"><a href="?page={{ next }}{% if filter %}&filter={{ filter }}{% endif %}">&rarr; Next</a></li>
-    {% else %}
-      <li class="next disabled"><a href="#">&rarr; Next</a></li>
-    {% endif %}
-  </ul>
-</div>
-{% endif %}
-
-<br /><br />
-{% endblock body %}
diff --git a/pithos/im/templates/reclaim.html b/pithos/im/templates/reclaim.html
deleted file mode 100644 (file)
index 5b9b20f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends "base.html" %}
-
-{% block title%}
-        <h2>Reclaim password</h2>
-{% endblock title%}
-
-{% block body %}
-<form action="{% url pithos.im.views.reclaim_password %}" method="post">
-  <div class="clearfix">
-    <label for="user-uniq">Username</label>
-    <div class="input">
-      <input class="span4" id="user-uniq" name="uniq" type="text" />
-    </div>
-  </div>
-  
-  <div class="actions">
-    <button type="submit" class="btn primary">Go</button>
-  </div>
-</form>
-{% endblock body %}
diff --git a/pithos/im/templates/register.html b/pithos/im/templates/register.html
deleted file mode 100644 (file)
index 9f591b5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{% extends "base.html" %}
-
-{% block title%}
-        <h1>Welcome</h1>{{provider}}
-{% endblock title%}
-
-{% block body %}
-<form action={%url pithos.im.views.register provider%} method="post">
-    {{ formset.as_p }}
-<div>
-    <button type="submit" class="btn primary">Register</button>
-</div>
-<input type="hidden" name="provider" value="{{ provider }}">
-<input type="hidden" name="code" value="{{ code }}">
-<input type="hidden" name="next" value="{{ next }}">
-
-</form>
-{% endblock body %}
\ No newline at end of file
diff --git a/pithos/im/templates/reset.html b/pithos/im/templates/reset.html
deleted file mode 100644 (file)
index a9a8116..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{% extends "base.html" %}
-
-{% block title%}
-        <h2>Reset password</h2>
-{% endblock title%}
-
-{% block body %}
-<form action="{% url pithos.im.target.local.reset_password %}" method="post">
-  <div class="clearfix">
-    <label for="user-uniq">password</label>
-    <div class="input">
-      <input class="span4" id="user-password" name="password" type="password" />
-    </div>
-  </div>
-  
-  <div class="actions">
-    <input type="hidden" name="auth" value="{{ auth }}">
-    <input type="hidden" name="next" value="{{ next }}">
-    <input type="hidden" name="username" value="{{ username }}">
-    <button type="submit" class="btn primary">Reset</button>
-  </div>
-</form>
-{% endblock body %}
diff --git a/pithos/im/templates/signup.html b/pithos/im/templates/signup.html
deleted file mode 100644 (file)
index c6ebebb..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{% extends "base.html" %}
-
-{% block title%}
-        <h1>Welcome</h1>
-{% endblock title%}
-
-{% block body %}
-<form action={%url pithos.im.views.signup %} method="post">
-    <p>Select an Identity Provider:</p>
-    {% for choice in im_modules%}
-    <div class="row">
-        <div class="span8">
-            <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice }}" />
-            <label for="choice{{ forloop.counter }}"><img src="/im/static/{{ choice }}.png" width="80"></label>
-        </div>
-    </div>
-    {% endfor %}
-<div>
-    {% if inv %}
-    <input type=hidden  name="code" value={{ inv.code }} />
-    {% endif %}
-    <button type="submit" class="btn primary">Signup</button>
-</div>
-<input type="hidden" name="provider" value="{{ provider }}">
-<input type="hidden" name="code" value="{{ code }}">
-<input type="hidden" name="next" value="{{ next }}">
-</form>
-{% endblock body %}
\ No newline at end of file
diff --git a/pithos/im/templates/users_create.html b/pithos/im/templates/users_create.html
deleted file mode 100644 (file)
index 8f5558d..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-{% extends "admin_base.html" %}
-
-{% block body %}
-
-<form action="{% url pithos.im.views.users_create %}" method="post">
-  <div class="clearfix">
-    <label for="user-uniq">Uniq</label>
-    <div class="input">
-      <input class="span4" id="user-uniq" name="uniq" type="text" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-realname">Real Name</label>
-    <div class="input">
-      <input class="span4" id="user-realname" name="realname" type="text" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-admin">Admin</label>
-    <div class="input">
-      <ul class="inputs-list">
-        <li>
-          <label>
-            <input type="checkbox" id="user-admin" name="admin">
-          </label>
-        </li>
-      </ul>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-affiliation">Affiliation</label>
-    <div class="input">
-      <input class="span4" id="user-affiliation" name="affiliation" type="text" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-quota">Quota</label>
-    <div class="input">
-      <div class="input-append">
-        <input class="span2" id="user-quota" name="quota" type="text" />
-        <span class="add-on">GiB</span>
-      </div>
-    </div>
-  </div>
-
-  <div class="actions">
-    <button type="submit" class="btn primary">Create</button>
-    <button type="reset" class="btn">Reset</button>
-  </div>
-</form>
-{% endblock body %}
diff --git a/pithos/im/templates/users_info.html b/pithos/im/templates/users_info.html
deleted file mode 100644 (file)
index 0d99d77..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-{% extends "admin_base.html" %}
-
-{% load formatters %}
-
-{% block body %}
-
-<form action="{% url pithos.im.views.users_modify user.id %}" method="post">
-  <div class="clearfix">
-    <label for="user-id">ID</label>
-    <div class="input">
-      <span class="uneditable-input" id="user-id">{{ user.id }}</span>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-uniq">Uniq</label>
-    <div class="input">
-      <input class="span4" id="user-uniq" name="uniq" value="{{ user.uniq }}" type="text" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-realname">Real Name</label>
-    <div class="input">
-      <input class="span4" id="user-realname" name="realname" value="{{ user.realname }}" type="text" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-admin">Admin</label>
-    <div class="input">
-      <ul class="inputs-list">
-        <li>
-          <label>
-            <input type="checkbox" id="user-admin" name="admin"{% if user.is_admin %} checked{% endif %}>
-          </label>
-        </li>
-      </ul>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-affiliation">Affiliation</label>
-    <div class="input">
-      <input class="span4" id="user-affiliation" name="affiliation" value="{{ user.affiliation }}" type="text" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-state">State</label>
-    <div class="input">
-      <select class="medium" id="user-state" name="state">
-        {% for state in states %}
-        <option{% ifequal state user.state %} selected{% endifequal %}>{{ state }}</option>
-        {% endfor %}
-      </select>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-invitations">Invitations</label>
-    <div class="input">
-      <input class="span2" id="user-invitations" name="invitations" value="{{ user.invitations }}" type="text" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-quota">Quota</label>
-    <div class="input">
-      <div class="input-append">
-        <input class="span2" id="user-quota" name="quota" value="{{ user.quota|GiB }}" type="text" />
-        <span class="add-on">GiB</span>
-      </div>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-token">Token</label>
-    <div class="input">
-      <input class="span4" id="user-token" name="auth_token" value="{{ user.auth_token }}" type="text" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="token-created">Token Created</label>
-    <div class="input">
-      <span class="uneditable-input" id="token-created">{{ user.auth_token_created }}</span>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="token-expires">Token Expires</label>
-    <div class="input">
-      <input type="datetime" class="span4" id="token-expires" name="auth_token_expires" value="{{ user.auth_token_expires|isoformat }}" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-created">Created</label>
-    <div class="input">
-      <span class="uneditable-input" id="user-created">{{ user.created }}</span>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-updated">Updated</label>
-    <div class="input">
-      <span class="uneditable-input" id="user-updated">{{ user.updated }}</span>
-    </div>
-  </div>
-
-  <div class="actions">
-    <button type="submit" class="btn primary">Save Changes</button>
-    <button type="reset" class="btn">Reset</button>
-        &nbsp;&nbsp;
-    <a class="btn danger needs-confirm" href="{% url pithos.im.views.users_delete user.id %}">Delete User</a>
-  </div>
-
-  <div class="alert-message block-message error">
-    <p><strong>WARNING:</strong> Are you sure you want to delete this user?</p>
-    <div class="alert-actions">
-      <a class="btn danger" href="{% url pithos.im.views.users_delete user.id %}">Delete</a>
-      <a class="btn alert-close">Cancel</a>
-    </div>
-  </div>
-</form>
-{% endblock body %}
diff --git a/pithos/im/templates/users_list.html b/pithos/im/templates/users_list.html
deleted file mode 100644 (file)
index c4e1900..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-{% extends "admin_base.html" %}
-
-{% load formatters %}
-
-{% block body %}
-
-<div class="row">
-  <div class="offset10 span3">
-    <form method="get">
-      <div class="input">
-        <input class="span3" name="filter" type="search" placeholder="search" value="{{ filter }}">
-      </div>
-    </form>
-  </div>
-</div>
-
-<table class="zebra-striped id-sorted">
-  <thead>
-    <tr>
-      <th>ID</th>
-      <th>Uniq</th>
-      <th>Real Name</th>
-      <th>Admin</th>
-      <th>Affiliation</th>
-      <th>State</th>
-      <th>Quota</th>
-      <th>Updated</th>
-    </tr>
-  </thead>
-  <tbody>
-    {% for user in users %}
-    <tr>
-      <td><a href="{% url pithos.im.views.users_info user.id %}">{{ user.id }}</a></td>
-      <td><a href="{% url pithos.im.views.users_info user.id %}">{{ user.uniq }}</a></td>
-      <td>{{ user.realname }}</td>
-      <td>{{ user.is_admin }}</td>
-      <td>{{ user.affiliation }}</td>
-      <td>{{ user.state }}</td>
-      <td>{{ user.quota|GiB }} GiB</td>
-      <td>{{ user.updated }}</td>
-    </tr>
-    {% endfor %}
-  </tbody>
-</table>
-
-{% if pages|length > 1 %}
-<div class="pagination">
-  <ul>
-    {% if prev %}
-      <li class="prev"><a href="?page={{ prev }}{% if filter %}&filter={{ filter }}{% endif %}">&larr; Previous</a></li>
-    {% else %}
-      <li class="prev disabled"><a href="#">&larr; Previous</a></li>
-    {% endif %}
-
-    {% for p in pages %}
-      <li{% if page == p %} class="active"{% endif %}><a href="?page={{ p }}{% if filter %}&filter={{ filter }}{% endif %}">{{ p }}</a></li>
-    {% endfor %}
-
-    {% if next %}
-      <li class="next"><a href="?page={{ next }}{% if filter %}&filter={{ filter }}{% endif %}">&rarr; Next</a></li>
-    {% else %}
-      <li class="next disabled"><a href="#">&rarr; Next</a></li>
-    {% endif %}
-  </ul>
-</div>
-{% endif %}
-
-<a class="btn success" href="{% url pithos.im.views.users_create %}">Create a user</a>
-<a class="btn success" href="{% url pithos.im.views.users_export %}">Export</a>
-
-<br /><br />
-{% endblock body %}
diff --git a/pithos/im/templates/users_profile.html b/pithos/im/templates/users_profile.html
deleted file mode 100644 (file)
index fbc73c3..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-{% extends "base.html" %}
-
-{% load formatters %}
-
-{% block title%}
-        <h2>User Profile</h2>
-{% endblock title%}
-
-{% block body %}
-
-<form action="{% url pithos.im.views.users_edit%}" method="post">
-  <div class="clearfix">
-    <label for="user-id">ID</label>
-    <div class="input">
-      <span class="uneditable-input" id="user-id">{{ user.id }}</span>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-uniq">Uniq</label>
-    <div class="input">
-        <span class="uneditable-input" id="user-uniq">{{ user.uniq }}</span>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-realname">Real Name</label>
-    <div class="input">
-      <input class="span4" id="user-realname" name="realname" value="{{ user.realname }}" type="text" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-admin">Admin</label>
-    <div class="input">
-      <ul class="inputs-list">
-        <li>
-          <label>
-            <input type="checkbox" id="user-admin" name="admin"{% if user.is_admin %} checked{% endif %} disabled="disabled">
-          </label>
-        </li>
-      </ul>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-affiliation">Affiliation</label>
-    <div class="input">
-      <input class="span4" id="user-affiliation" name="affiliation" value="{{ user.affiliation }}" type="text" />
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-state">State</label>
-    <div class="input">
-      <select class="medium" id="user-state" name="state" disabled="disabled">
-        {% for state in states %}
-        <option{% ifequal state user.state %} selected{% endifequal %}>{{ state }}</option>
-        {% endfor %}
-      </select>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-invitations">Invitations</label>
-    <div class="input">
-        <span class="uneditable-input" id="user-invitations">{{ user.invitations }}</span>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-quota">Quota</label>
-    <div class="input">
-      <div class="input-append">
-        <input class="span2" id="user-quota" name="quota" value="{{ user.quota|GiB }}" type="text" readonly="readonly"/>
-        <span class="add-on">GiB</span>
-      </div>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-token">Token</label>
-    <div class="input">
-        <span class="uneditable-input" id="user-token">{{ user.auth_token }}</span>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="token-created">Token Created</label>
-    <div class="input">
-      <span class="uneditable-input" id="token-created">{{ user.auth_token_created }}</span>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="token-expires">Token Expires</label>
-    <div class="input">
-      <span class="uneditable-input" id="token-expires">{{ user.auth_token_expires }}</span>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-created">Created</label>
-    <div class="input">
-      <span class="uneditable-input" id="user-created">{{ user.created }}</span>
-    </div>
-  </div>
-
-  <div class="clearfix">
-    <label for="user-updated">Updated</label>
-    <div class="input">
-      <span class="uneditable-input" id="user-updated">{{ user.updated }}</span>
-    </div>
-  </div>
-
-  <div class="actions">
-    <input type="hidden" name="next" value="{{ next }}">
-    <input type="hidden" name="auth" value="{{ user.auth_token }}">
-    <button type="submit" class="btn primary">Verify</button>
-  </div>
-
-</form>
-{% endblock body %}
diff --git a/pithos/im/templatetags/__init__.py b/pithos/im/templatetags/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/pithos/im/templatetags/formatters.py b/pithos/im/templatetags/formatters.py
deleted file mode 100644 (file)
index 8b76cc0..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-#
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-#
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from django import template
-
-
-register = template.Library()
-
-
-@register.filter
-def GiB(value):
-    try:
-        return int(value) / 1024 ** 3
-    except ValueError:
-        return 0
-
-
-@register.filter
-def isoformat(value):
-    return value.strftime('%Y-%m-%dT%H:%MZ')
diff --git a/pithos/im/urls.py b/pithos/im/urls.py
deleted file mode 100644 (file)
index f2d51e5..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from django.conf import settings
-from django.conf.urls.defaults import patterns, include
-
-urlpatterns = patterns('pithos.im.views',
-    (r'^$', 'index'),
-    (r'^login/?$', 'index'),
-    
-    (r'^admin/?$', 'admin'),
-    
-    (r'^admin/users/?$', 'users_list'),
-    (r'^admin/users/(\d+)/?$', 'users_info'),
-    (r'^admin/users/create$', 'users_create'),
-    (r'^admin/users/(\d+)/modify/?$', 'users_modify'),
-    (r'^admin/users/(\d+)/delete/?$', 'users_delete'),
-    (r'^admin/users/export/?$', 'users_export'),
-    (r'^admin/users/pending/?$', 'pending_users'),
-    (r'^admin/users/activate/(\d+)/?$', 'users_activate'),
-    
-    (r'^admin/invitations/?$', 'invitations_list'),
-    (r'^admin/invitations/export/?$', 'invitations_export'),
-    
-    (r'^profile/?$', 'users_profile'),
-    (r'^profile/edit/?$', 'users_edit'),
-    
-    (r'^signup/?$', 'signup'),
-    (r'^register/(\w+)?$', 'register'),
-    #(r'^signup/complete/?$', 'signup_complete'),
-    #(r'^local/create/?$', 'local_create'),
-)
-
-urlpatterns += patterns('pithos.im.target',
-    (r'^login/dummy/?$', 'dummy.login')
-)
-
-urlpatterns += patterns('',
-    (r'^static/(?P<path>.*)$', 'django.views.static.serve',
-                                {'document_root': settings.PROJECT_PATH + '/im/static'})
-)
-
-
-if 'local' in settings.IM_MODULES:
-    urlpatterns += patterns('pithos.im.views',
-#        (r'^local/create/?$', 'local_create'),
-        (r'^local/reclaim/?$', 'reclaim_password')
-    )
-    urlpatterns += patterns('pithos.im.target',
-        (r'^local/?$', 'local.login'),
-        (r'^local/activate/?$', 'local.activate'),
-        (r'^local/reset/?$', 'local.reset_password')
-    )
-
-if settings.INVITATIONS_ENABLED:
-    urlpatterns += patterns('pithos.im.views',
-        (r'^invite/?$', 'invite'),
-    )
-#    urlpatterns += patterns('pithos.im.target',
-#        (r'^login/invitation/?$', 'invitation.login')
-#    )
-
-if 'shibboleth' in settings.IM_MODULES:
-    urlpatterns += patterns('pithos.im.target',
-        (r'^login/shibboleth/?$', 'shibboleth.login')
-    )
-
-if 'twitter' in settings.IM_MODULES:
-    urlpatterns += patterns('pithos.im.target',
-        (r'^login/twitter/?$', 'twitter.login'),
-        (r'^login/twitter/authenticated/?$', 'twitter.authenticated')
-    )
-
-urlpatterns += patterns('pithos.im.api',
-    (r'^authenticate/?$', 'authenticate')
-)
-    
diff --git a/pithos/im/util.py b/pithos/im/util.py
deleted file mode 100644 (file)
index 4f06a06..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from datetime import tzinfo, timedelta
-
-
-class UTC(tzinfo):
-   def utcoffset(self, dt):
-       return timedelta(0)
-
-   def tzname(self, dt):
-       return 'UTC'
-
-   def dst(self, dt):
-       return timedelta(0)
-
-def isoformat(d):
-   """Return an ISO8601 date string that includes a timezone."""
-
-   return d.replace(tzinfo=UTC()).isoformat()
diff --git a/pithos/im/views.py b/pithos/im/views.py
deleted file mode 100644 (file)
index f41933b..0000000
+++ /dev/null
@@ -1,727 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-import json
-import logging
-import socket
-import csv
-import sys
-
-from datetime import datetime
-from functools import wraps
-from math import ceil
-from random import randint
-from smtplib import SMTPException
-
-from django.conf import settings
-from django.core.mail import send_mail
-from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
-from django.shortcuts import redirect
-from django.template.loader import render_to_string
-from django.shortcuts import render_to_response
-from django.utils.http import urlencode
-from django.utils.translation import ugettext as _
-from django.core.urlresolvers import reverse
-from django.forms import Form
-from django.forms.formsets import formset_factory
-from openid.consumer.consumer import Consumer, \
-    SUCCESS, CANCEL, FAILURE, SETUP_NEEDED
-
-from hashlib import new as newhasher
-
-from urllib import quote
-
-from pithos.im.openid_store import PithosOpenIDStore
-from pithos.im.models import User, Invitation
-from pithos.im.util import isoformat
-from pithos.im.forms import *
-
-def render_response(template, tab=None, status=200, **kwargs):
-    if tab is None:
-        tab = template.partition('_')[0]
-    kwargs.setdefault('tab', tab)
-    html = render_to_string(template, kwargs)
-    return HttpResponse(html, status=status)
-
-
-def requires_login(func):
-    @wraps(func)
-    def wrapper(request, *args):
-        if not settings.BYPASS_ADMIN_AUTH:
-            if not request.user:
-                next = urlencode({'next': request.build_absolute_uri()})
-                login_uri = reverse(index) + '?' + next
-                return HttpResponseRedirect(login_uri)
-        return func(request, *args)
-    return wrapper
-
-def requires_admin(func):
-    @wraps(func)
-    def wrapper(request, *args):
-        if not settings.BYPASS_ADMIN_AUTH:
-            if not request.user:
-                next = urlencode({'next': request.build_absolute_uri()})
-                login_uri = reverse(index) + '?' + next
-                return HttpResponseRedirect(login_uri)
-            if not request.user.is_admin:
-                return HttpResponse('Forbidden', status=403)
-        return func(request, *args)
-    return wrapper
-
-
-def index(request):
-    kwargs = {'im_modules':settings.IM_MODULES,
-              'other_modules':settings.IM_MODULES[1:]}
-    return render_response('index.html',
-                           next=request.GET.get('next', ''),
-                           **kwargs)
-
-
-@requires_admin
-def admin(request):
-    stats = {}
-    stats['users'] = User.objects.count()
-    stats['pending'] = User.objects.filter(state = 'PENDING').count()
-    
-    invitations = Invitation.objects.all()
-    stats['invitations'] = invitations.count()
-    stats['invitations_consumed'] = invitations.filter(is_consumed=True).count()
-    
-    return render_response('admin.html', tab='home', stats=stats)
-
-
-@requires_admin
-def users_list(request):
-    users = User.objects.order_by('id')
-    
-    filter = request.GET.get('filter', '')
-    if filter:
-        if filter.startswith('-'):
-            users = users.exclude(uniq__icontains=filter[1:])
-        else:
-            users = users.filter(uniq__icontains=filter)
-    
-    try:
-        page = int(request.GET.get('page', 1))
-    except ValueError:
-        page = 1
-    offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
-    limit = offset + settings.ADMIN_PAGE_LIMIT
-    
-    npages = int(ceil(1.0 * users.count() / settings.ADMIN_PAGE_LIMIT))
-    prev = page - 1 if page > 1 else None
-    next = page + 1 if page < npages else None
-    return render_response('users_list.html',
-                            users=users[offset:limit],
-                            filter=filter,
-                            pages=range(1, npages + 1),
-                            page=page,
-                            prev=prev,
-                            next=next)
-
-@requires_admin
-def users_info(request, user_id):
-    user = User.objects.get(id=user_id)
-    states = [x[0] for x in User.ACCOUNT_STATE]
-    return render_response('users_info.html',
-                            user=user,
-                            states=states)
-
-
-@requires_admin
-def users_modify(request, user_id):
-    user = User.objects.get(id=user_id)
-    user.uniq = request.POST.get('uniq')
-    user.realname = request.POST.get('realname')
-    user.is_admin = True if request.POST.get('admin') else False
-    user.affiliation = request.POST.get('affiliation')
-    user.state = request.POST.get('state')
-    user.invitations = int(request.POST.get('invitations') or 0)
-    user.quota = int(request.POST.get('quota') or 0) * (1024 ** 3)  # In GiB
-    user.auth_token = request.POST.get('auth_token')
-    try:
-        auth_token_expires = request.POST.get('auth_token_expires')
-        d = datetime.strptime(auth_token_expires, '%Y-%m-%dT%H:%MZ')
-        user.auth_token_expires = d
-    except ValueError:
-        pass
-    user.save()
-    return redirect(users_info, user.id)
-
-@requires_admin
-def users_delete(request, user_id):
-    user = User.objects.get(id=user_id)
-    user.delete()
-    return redirect(users_list)
-
-@requires_admin
-def pending_users(request):
-    users = User.objects.order_by('id')
-    
-    users = users.filter(state = 'PENDING')
-    
-    try:
-        page = int(request.GET.get('page', 1))
-    except ValueError:
-        page = 1
-    offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
-    limit = offset + settings.ADMIN_PAGE_LIMIT
-    
-    npages = int(ceil(1.0 * users.count() / settings.ADMIN_PAGE_LIMIT))
-    prev = page - 1 if page > 1 else None
-    next = page + 1 if page < npages else None
-    return render_response('pending_users.html',
-                            users=users[offset:limit],
-                            filter=filter,
-                            pages=range(1, npages + 1),
-                            page=page,
-                            prev=prev,
-                            next=next)
-
-def send_greeting(baseurl, user):
-    url = baseurl
-    subject = _('Welcome to Pithos')
-    message = render_to_string('welcome.txt', {
-                'user': user,
-                'url': url,
-                'baseurl': baseurl,
-                'service': settings.SERVICE_NAME,
-                'support': settings.DEFAULT_CONTACT_EMAIL})
-    sender = settings.DEFAULT_FROM_EMAIL
-    send_mail(subject, message, sender, [user.email])
-    logging.info('Sent greeting %s', user)
-
-@requires_admin
-def users_activate(request, user_id):
-    user = User.objects.get(id=user_id)
-    user.state = 'ACTIVE'
-    status = 'success'
-    try:
-        send_greeting(request.build_absolute_uri('/').rstrip('/'), user)
-        message = _('Greeting sent to %s' % user.email)
-        user.save()
-    except (SMTPException, socket.error) as e:
-        status = 'error'
-        name = 'strerror'
-        message = getattr(e, name) if hasattr(e, name) else e
-    
-    users = User.objects.order_by('id')
-    users = users.filter(state = 'PENDING')
-    
-    try:
-        page = int(request.POST.get('page', 1))
-    except ValueError:
-        page = 1
-    offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
-    limit = offset + settings.ADMIN_PAGE_LIMIT
-    
-    npages = int(ceil(1.0 * users.count() / settings.ADMIN_PAGE_LIMIT))
-    prev = page - 1 if page > 1 else None
-    next = page + 1 if page < npages else None
-    return render_response('pending_users.html',
-                            users=users[offset:limit],
-                            filter=filter,
-                            pages=range(1, npages + 1),
-                            page=page,
-                            prev=prev,
-                            next=next,
-                            message=message)
-
-def generate_invitation_code():
-    while True:
-        code = randint(1, 2L**63 - 1)
-        try:
-            Invitation.objects.get(code=code)
-            # An invitation with this code already exists, try again
-        except Invitation.DoesNotExist:
-            return code
-
-
-def send_invitation(baseurl, inv):
-    url = settings.SIGNUP_TARGET % (baseurl, inv.code, quote(baseurl))
-    subject = _('Invitation to Pithos')
-    message = render_to_string('invitation.txt', {
-                'invitation': inv,
-                'url': url,
-                'baseurl': baseurl,
-                'service': settings.SERVICE_NAME,
-                'support': settings.DEFAULT_CONTACT_EMAIL})
-    sender = settings.DEFAULT_FROM_EMAIL
-    send_mail(subject, message, sender, [inv.uniq])
-    logging.info('Sent invitation %s', inv)
-
-
-@requires_login
-def invite(request):
-    status = None
-    message = None
-    inviter = request.user
-
-    if request.method == 'POST':
-        uniq = request.POST.get('uniq')
-        realname = request.POST.get('realname')
-        
-        if inviter.invitations > 0:
-            code = generate_invitation_code()
-            invitation, created = Invitation.objects.get_or_create(
-                inviter=inviter,
-                uniq=uniq,
-                defaults={'code': code, 'realname': realname})
-            
-            try:
-                send_invitation(request.build_absolute_uri('/').rstrip('/'), invitation)
-                if created:
-                    inviter.invitations = max(0, inviter.invitations - 1)
-                    inviter.save()
-                status = 'success'
-                message = _('Invitation sent to %s' % uniq)
-            except (SMTPException, socket.error) as e:
-                status = 'error'
-                message = getattr(e, 'strerror', '')
-        else:
-            status = 'error'
-            message = _('No invitations left')
-
-    if request.GET.get('format') == 'json':
-        sent = [{'email': inv.uniq,
-                 'realname': inv.realname,
-                 'is_accepted': inv.is_accepted}
-                    for inv in inviter.invitations_sent.all()]
-        rep = {'invitations': inviter.invitations, 'sent': sent}
-        return HttpResponse(json.dumps(rep))
-    
-    html = render_to_string('invitations.html', {
-            'user': inviter,
-            'status': status,
-            'message': message})
-    return HttpResponse(html)
-
-def send_verification(baseurl, user):
-    url = settings.ACTIVATION_LOGIN_TARGET % (baseurl,
-                                              quote(user.auth_token),
-                                              quote(baseurl))
-    message = render_to_string('activation.txt', {
-            'user': user,
-            'url': url,
-            'baseurl': baseurl,
-            'service': settings.SERVICE_NAME,
-            'support': settings.DEFAULT_CONTACT_EMAIL})
-    sender = settings.DEFAULT_FROM_EMAIL
-    send_mail('Pithos account activation', message, sender, [user.email])
-    logging.info('Sent activation %s', user)
-
-def send_password(baseurl, user):
-    url = settings.PASSWORD_RESET_TARGET % (baseurl,
-                                            quote(user.uniq),
-                                            quote(baseurl))
-    message = render_to_string('password.txt', {
-            'user': user,
-            'url': url,
-            'baseurl': baseurl,
-            'service': settings.SERVICE_NAME,
-            'support': settings.DEFAULT_CONTACT_EMAIL})
-    sender = settings.DEFAULT_FROM_EMAIL
-    send_mail('Pithos password recovering', message, sender, [user.email])
-    logging.info('Sent password %s', user)
-
-def reclaim_password(request):
-    if request.method == 'GET':
-        return render_response('reclaim.html')
-    elif request.method == 'POST':
-        username = request.POST.get('uniq')
-        try:
-            user = User.objects.get(uniq=username)
-            try:
-                send_password(request.build_absolute_uri('/').rstrip('/'), user)
-                status = 'success'
-                message = _('Password reset sent to %s' % user.email)
-                user.status = 'UNVERIFIED'
-                user.save()
-            except (SMTPException, socket.error) as e:
-                status = 'error'
-                name = 'strerror'
-                message = getattr(e, name) if hasattr(e, name) else e
-        except User.DoesNotExist:
-            status = 'error'
-            message = 'Username does not exist'
-        
-        html = render_to_string('reclaim.html', {
-                'status': status,
-                'message': message})
-        return HttpResponse(html)
-
-@requires_admin
-def invitations_list(request):
-    invitations = Invitation.objects.order_by('id')
-    
-    filter = request.GET.get('filter', '')
-    if filter:
-        if filter.startswith('-'):
-            invitations = invitations.exclude(uniq__icontains=filter[1:])
-        else:
-            invitations = invitations.filter(uniq__icontains=filter)
-    
-    try:
-        page = int(request.GET.get('page', 1))
-    except ValueError:
-        page = 1
-    offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
-    limit = offset + settings.ADMIN_PAGE_LIMIT
-    
-    npages = int(ceil(1.0 * invitations.count() / settings.ADMIN_PAGE_LIMIT))
-    prev = page - 1 if page > 1 else None
-    next = page + 1 if page < npages else None
-    return render_response('invitations_list.html',
-                            invitations=invitations[offset:limit],
-                            filter=filter,
-                            pages=range(1, npages + 1),
-                            page=page,
-                            prev=prev,
-                            next=next)
-
-@requires_admin
-def invitations_export(request):
-    # Create the HttpResponse object with the appropriate CSV header.
-    response = HttpResponse(mimetype='text/csv')
-    response['Content-Disposition'] = 'attachment; filename=invitations.csv'
-
-    writer = csv.writer(response)
-    writer.writerow(['ID',
-                     'Uniq',
-                     'Real Name',
-                     'Code',
-                     'Inviter Uniq',
-                     'Inviter Real Name',
-                     'Is_accepted',
-                     'Created',
-                     'Accepted',])
-    invitations = Invitation.objects.order_by('id')
-    for inv in invitations:
-        writer.writerow([inv.id,
-                         inv.uniq.encode("utf-8"),
-                         inv.realname.encode("utf-8"),
-                         inv.code,
-                         inv.inviter.uniq.encode("utf-8"),
-                         inv.inviter.realname.encode("utf-8"),
-                         inv.is_accepted,
-                         inv.created,
-                         inv.accepted])
-
-    return response
-
-
-@requires_admin
-def users_export(request):
-    # Create the HttpResponse object with the appropriate CSV header.
-    response = HttpResponse(mimetype='text/csv')
-    response['Content-Disposition'] = 'attachment; filename=users.csv'
-
-    writer = csv.writer(response)
-    writer.writerow(['ID',
-                     'Uniq',
-                     'Real Name',
-                     'Admin',
-                     'Affiliation',
-                     'State',
-                     'Quota (GiB)',
-                     'Updated',])
-    users = User.objects.order_by('id')
-    for u in users:
-        writer.writerow([u.id,
-                         u.uniq.encode("utf-8"),
-                         u.realname.encode("utf-8"),
-                         u.is_admin,
-                         u.affiliation.encode("utf-8"),
-                         u.state.encode("utf-8"),
-                         u.quota,
-                         u.updated])
-
-    return response
-
-@requires_admin
-def users_create(request):
-    if request.method == 'GET':
-        return render_response('users_local_create.html')
-    if request.method == 'POST':
-        user = User()
-        user.uniq = request.POST.get('uniq')
-        user.realname = request.POST.get('realname')
-        user.is_admin = True if request.POST.get('admin') else False
-        user.affiliation = request.POST.get('affiliation')
-        user.quota = int(request.POST.get('quota') or 0) * (1024 ** 3)  # In GiB
-        user.renew_token()
-        user.provider = 'local'
-        user.save()
-        return redirect(users_info, user.id)
-
-@requires_login
-def users_profile(request):
-    next = request.GET.get('next')
-    try:
-        user = User.objects.get(uniq=request.user)
-    except User.DoesNotExist:
-        user = User.objects.get(auth_token=request.GET.get('auth', None))
-    states = [x[0] for x in User.ACCOUNT_STATE]
-    return render_response('users_profile.html',
-                            user=user,
-                            states=states,
-                            next=next)
-
-@requires_login
-def users_edit(request):
-    try:
-        user = User.objects.get(uniq=request.user)
-    except User.DoesNotExist:
-        token = request.POST.get('auth', None)
-        users = User.objects.all()
-        user = User.objects.get(auth_token=token)
-    user.realname = request.POST.get('realname')
-    user.affiliation = request.POST.get('affiliation')
-    user.is_verified = True
-    user.save()
-    next = request.POST.get('next')
-    if next:
-        return redirect(next)
-    
-    status = 'success'
-    message = _('Profile has been updated')
-    html = render_to_string('users_profile.html', {
-            'user': user,
-            'status': status,
-            'message': message})
-    return HttpResponse(html)
-    
-def signup(request):
-    if request.method == 'GET':
-        kwargs = {'im_modules':settings.IM_MODULES,
-                  'next':request.GET.get('next', ''),
-                  'code':request.GET.get('code', '')}
-        return render_response('signup.html', **kwargs)
-    elif request.method == 'POST':
-        provider = request.POST.get('choice')
-        if not provider:
-            return on_failure(_('No provider selected'), template='signup.html')
-        
-        kwargs = {'code':request.POST.get('code', ''),
-                  'next':request.POST.get('next', '')}
-        url = '%s%s?' %(reverse('pithos.im.views.register'), provider)
-        for k,v in kwargs.items():
-            if v:
-                url = '%s%s=%s&' %(url, k, v)
-        return redirect(url)
-
-def render_registration(provider, code='', next=''):
-    initial_data = {'provider':provider}
-    if settings.INVITATIONS_ENABLED and code:
-        try:
-            print '#', type(code), code
-            invitation = Invitation.objects.get(code=code)
-            if invitation.is_consumed:
-                return HttpResponseBadRequest('Invitation has beeen used')
-            initial_data.update({'uniq':invitation.uniq,
-                                 'email':invitation.uniq,
-                                 'realname':invitation.realname})
-            try:
-                inviter = User.objects.get(uniq=invitation.inviter)
-                initial_data['inviter'] = inviter.realname
-            except User.DoesNotExist:
-                pass
-        except Invitation.DoesNotExist:
-            return on_failure(_('Wrong invitation code'), template='register.html')
-    
-    prefix = 'Invited' if code else ''
-    formclassname = '%s%sRegisterForm' %(prefix, provider.capitalize())
-    formclass_ = getattr(sys.modules['pithos.im.forms'], formclassname)
-    RegisterFormSet = formset_factory(formclass_, extra=0)
-    formset = RegisterFormSet(initial=[initial_data])
-    return render_response('register.html',
-                           formset=formset,
-                           next=next,
-                           filter=filter,
-                           code=code)
-
-def is_preaccepted(user):
-    if user.invitation and not user.invitation.is_consumed:
-        return True
-    
-    return False
-
-def should_send_verification():
-    if not settings.INVITATIONS_ENABLED:
-        return True    
-    return False
-
-def register(request, provider):
-    print '---', request
-    code = request.GET.get('code')
-    next = request.GET.get('next')
-    if request.method == 'GET':
-        code = request.GET.get('code', '')
-        next = request.GET.get('next', '')
-        if provider not in settings.IM_MODULES:
-            return on_failure(_('Invalid provider'))
-        return render_registration(provider, code, next)
-    elif request.method == 'POST':
-        provider = request.POST.get('form-0-provider')
-        inviter = request.POST.get('form-0-inviter')
-        
-        #instantiate the form
-        prefix = 'Invited' if inviter else ''
-        formclassname = '%sRegisterForm' %(provider.capitalize())
-        formclass_ = getattr(sys.modules['pithos.im.forms'], formclassname)
-        RegisterFormSet = formset_factory(formclass_, extra=0)
-        formset = RegisterFormSet(request.POST)
-        if not formset.is_valid():
-            return render_to_response('register.html',
-                                      {'formset':formset,
-                                       'code':code,
-                                       'next':next}) 
-        
-        user = User()
-        for form in formset.forms:
-            for field in form.fields:
-                if hasattr(user, field):
-                    setattr(user, field, form.cleaned_data[field])
-            break
-        
-        if user.openidurl:
-            redirect_url = reverse('pithos.im.views.create')
-            return ask_openid(request, 
-                        user.openidurl,
-                        redirect_url,
-                        'signup')
-        
-        #save hashed password
-        if user.password:
-            hasher = newhasher('sha256')
-            hasher.update(user.password)
-            user.password = hasher.hexdigest() 
-            
-        user.renew_token()
-        
-        if is_preaccepted(user):
-            user.state = 'ACTIVE'
-            user.save()
-            url = reverse('pithos.im.views.index')
-            return redirect(url)
-        
-        status = 'success'
-        if should_send_verification():
-            try:
-                send_verification(request.build_absolute_uri('/').rstrip('/'), user)
-                message = _('Verification sent to %s' % user.email)
-                user.save()
-            except (SMTPException, socket.error) as e:
-                status = 'error'
-                name = 'strerror'
-                message = getattr(e, name) if hasattr(e, name) else e
-        else:
-            user.save()
-            message = _('Registration completed. You will receive an email upon your account\'s activation')
-        
-        return info(status, message)
-
-#def discover_extensions(openid_url):
-#    service = discover(openid_url)
-#    use_ax = False
-#    use_sreg = False
-#    for endpoint in service[1]:
-#        if not use_sreg:
-#            use_sreg = sreg.supportsSReg(endpoint)
-#        if not use_ax:
-#            use_ax = endpoint.usesExtension("http://openid.net/srv/ax/1.0")
-#        if use_ax and use_sreg: break
-#    return use_ax, use_sreg
-#
-#def ask_openid(request, openid_url, redirect_to, on_failure=None):
-#    """ basic function to ask openid and return response """
-#    on_failure = on_failure or signin_failure
-#    sreg_req = None
-#    ax_req = None
-#    
-#    trust_root = getattr(
-#        settings, 'OPENID_TRUST_ROOT', request.build_absolute_uri() + '/'
-#    )
-#    request.session = {}
-#    consumer = Consumer(request.session, PithosOpenIDStore())
-#    try:
-#        auth_request = consumer.begin(openid_url)
-#    except DiscoveryFailure:
-#        msg = _("The OpenID %s was invalid") % openid_url
-#        return on_failure(request, msg)
-#    
-#     get capabilities
-#    use_ax, use_sreg = discover_extensions(openid_url)
-#    if use_sreg:
-#         set sreg extension
-#         we always ask for nickname and email
-#        sreg_attrs = getattr(settings, 'OPENID_SREG', {})
-#        sreg_attrs.update({ "optional": ['nickname', 'email'] })
-#        sreg_req = sreg.SRegRequest(**sreg_attrs)
-#    if use_ax:
-#         set ax extension
-#         we always ask for nickname and email
-#        ax_req = ax.FetchRequest()
-#        ax_req.add(ax.AttrInfo('http://schema.openid.net/contact/email', 
-#                                alias='email', required=True))
-#        ax_req.add(ax.AttrInfo('http://schema.openid.net/namePerson/friendly', 
-#                                alias='nickname', required=True))
-#                      
-#         add custom ax attrs          
-#        ax_attrs = getattr(settings, 'OPENID_AX', [])
-#        for attr in ax_attrs:
-#            if len(attr) == 2:
-#                ax_req.add(ax.AttrInfo(attr[0], required=alias[1]))
-#            else:
-#                ax_req.add(ax.AttrInfo(attr[0]))
-#       
-#    if sreg_req is not None:
-#        auth_request.addExtension(sreg_req)
-#    if ax_req is not None:
-#        auth_request.addExtension(ax_req)
-#    
-#    redirect_url = auth_request.redirectURL(trust_root, redirect_to)
-#    return HttpResponseRedirect(redirect_url)
-
-def info(status, message, template='base.html'):
-    html = render_to_string(template, {
-            'status': status,
-            'message': message})
-    response = HttpResponse(html)
-    return response
-
-def on_success(message, template='base.html'):
-    return info('success', message)
-    
-def on_failure(message, template='base.html'):
-    return info('error', message)
\ No newline at end of file
index 28476e7..f442c21 100644 (file)
@@ -1,3 +1,3 @@
 from log import LoggingConfigMiddleware
 from secure import SecureMiddleware
-from auth import AuthMiddleware
+from astakos import AstakosMiddleware
similarity index 62%
rename from pithos/im/target/invitation.py
rename to pithos/middleware/astakos.py
index fa458c4..f52d394 100644 (file)
@@ -1,18 +1,18 @@
 # Copyright 2011 GRNET S.A. All rights reserved.
-#
+# 
 # Redistribution and use in source and binary forms, with or
 # without modification, are permitted provided that the following
 # conditions are met:
-#
+# 
 #   1. Redistributions of source code must retain the above
 #      copyright notice, this list of conditions and the following
 #      disclaimer.
-#
+# 
 #   2. Redistributions in binary form must reproduce the above
 #      copyright notice, this list of conditions and the following
 #      disclaimer in the documentation and/or other materials
 #      provided with the distribution.
-#
+# 
 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
-#
+# 
 # The views and conclusions contained in the software and
 # documentation are those of the authors and should not be
 # interpreted as representing official policies, either expressed
 # or implied, of GRNET S.A.
 
-import logging
-
-from datetime import datetime
-
+from time import time, mktime
+from urllib import quote, unquote
 from django.conf import settings
-from django.http import HttpResponseBadRequest
-
-from pithos.im.models import Invitation
-from pithos.im.target.util import get_or_create_user, prepare_response
+from django.utils import simplejson as json
 
+from pithos.lib.client import authenticate, Fault
 
-def login(request):
-    code = request.GET.get('code')
-    try:
-        invitation = Invitation.objects.get(code=code)
-    except Invitation.DoesNotExist:
-        return HttpResponseBadRequest('Wrong invitation code')
-    
-    if not invitation.is_accepted:
-        invitation.is_accepted = True
-        invitation.accepted = datetime.now()
-        invitation.save()
-        logging.info('Accepted invitation %s', invitation)
+def get_user_from_token(token):
+    if not token:
+        return None
     
-    user = get_or_create_user(invitation.uniq,
-                                invitation.realname,
-                                'Invitation',
-                                invitation.inviter.level + 1)
-    
-    next = request.GET.get('next')
-    
-    return prepare_response(request, user, next, 'renew' in request.GET)
+    host = settings.AUTHENTICATION_HOST
+    try:
+        status, headers, user = authenticate(host, token)
+        return json.loads(user)
+    except Fault, f:
+        return None
+
+class AuthMiddleware(object):
+    def process_request(self, request):
+        request.user = None
+        request.user_uniq = None
+        
+        # Try to find token in a parameter, in a request header, or in a cookie.
+        user = get_user_from_token(request.GET.get('X-Auth-Token'))
+        if not user:
+            user = get_user_from_token(request.META.get('HTTP_X_AUTH_TOKEN'))
+        if not user:
+            return
+        
+        request.user = user
+        request.user_uniq = user['uniq']
diff --git a/pithos/middleware/auth.py b/pithos/middleware/auth.py
deleted file mode 100644 (file)
index 9808907..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright 2011 GRNET S.A. All rights reserved.
-# 
-# Redistribution and use in source and binary forms, with or
-# without modification, are permitted provided that the following
-# conditions are met:
-# 
-#   1. Redistributions of source code must retain the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer.
-# 
-#   2. Redistributions in binary form must reproduce the above
-#      copyright notice, this list of conditions and the following
-#      disclaimer in the documentation and/or other materials
-#      provided with the distribution.
-# 
-# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-# 
-# The views and conclusions contained in the software and
-# documentation are those of the authors and should not be
-# interpreted as representing official policies, either expressed
-# or implied, of GRNET S.A.
-
-from time import time, mktime
-from urllib import quote, unquote
-from django.conf import settings
-from django.utils import simplejson as json
-
-from pithos.im.models import User
-from pithos.lib.client import authenticate, Fault
-
-def get_user_from_token(token):
-    if not token:
-        return None
-    
-    host = settings.AUTHENTICATION_HOST
-    try:
-        status, headers, user = authenticate(host, token)
-        return json.loads(user)
-    except Fault, f:
-        return None
-
-class AuthMiddleware(object):
-    def process_request(self, request):
-        try:
-            host, port = settings.AUTHENTICATION_HOST.split(':')
-            if request.META['SERVER_NAME'] and request.META['SERVER_PORT'] == port:
-                #bypass authentication
-                #if it is an authentication request
-                return
-            
-            request.user = None
-            request.user_uniq = None
-            
-            # Try to find token in a parameter, in a request header, or in a cookie.
-            user = get_user_from_token(request.GET.get('X-Auth-Token'))
-            if not user:
-                user = get_user_from_token(request.META.get('HTTP_X_AUTH_TOKEN'))
-            if not user:
-                # Back from an im login target.
-                if request.GET.get('user', None):
-                    token = request.GET.get('token', None)
-                    if token:
-                        request.set_auth_cookie = True
-                    user = get_user_from_token(token)
-                if not user:
-                    cookie_value = unquote(request.COOKIES.get('_pithos2_a', ''))
-                    if cookie_value and '|' in cookie_value:
-                        token = cookie_value.split('|', 1)[1]
-                        user = get_user_from_token(token)
-            if not user:
-                return
-            
-            request.user = user
-            request.user_uniq = user['uniq']
-        except Exception, e:
-            print e
-    
-    def process_response(self, request, response):
-        if getattr(request, 'user', None) and getattr(request, 'set_auth_cookie', False):
-            expire_fmt = request.user.auth_token_expires.strftime('%a, %d-%b-%Y %H:%M:%S %Z')
-            cookie_value = quote(request.user.uniq + '|' + request.user.auth_token)
-            response.set_cookie('_pithos2_a', value=cookie_value, expires=expire_fmt, path='/')
-        return response
index bb0a280..ac14d2d 100644 (file)
@@ -8,7 +8,7 @@ MIDDLEWARE_CLASSES = (
     'django.middleware.common.CommonMiddleware',
     'pithos.middleware.LoggingConfigMiddleware',
     'pithos.middleware.SecureMiddleware',
-    'pithos.middleware.AuthMiddleware'
+    'pithos.middleware.AstakosMiddleware'
 )
 
 ROOT_URLCONF = 'pithos.urls'
@@ -21,10 +21,5 @@ TEMPLATE_DIRS = (
 
 INSTALLED_APPS = (
     'pithos.api',
-    'pithos.im',
-    'pithos.ui',
-    'south'
+    'pithos.ui'
 )
-
-#where astakos is hosted
-AUTHENTICATION_HOST = '127.0.0.1:10000'
index 069d9e5..0b59172 100644 (file)
@@ -13,3 +13,7 @@ BACKEND_DB_CONNECTION = 'sqlite:///' + join(PROJECT_PATH, 'backend.db')
 # Block storage.
 BACKEND_BLOCK_MODULE = 'pithos.backends.lib.hashfiler'
 BACKEND_BLOCK_PATH = join(PROJECT_PATH, 'data/')
+
+# Default setting for new accounts.
+DEFAULT_QUOTA = 50 * 1024 * 1024 * 1024
+DEFAULT_VERSIONING = 'auto'
\ No newline at end of file
diff --git a/pithos/settings.d/20-api.conf b/pithos/settings.d/20-api.conf
deleted file mode 100644 (file)
index 0765cc1..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default setting for new accounts.
-DEFAULT_QUOTA = 50 * 1024 * 1024 * 1024
-DEFAULT_VERSIONING = 'auto'
diff --git a/pithos/settings.d/20-im.conf b/pithos/settings.d/20-im.conf
deleted file mode 100644 (file)
index 98b18e1..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-# Set the expiration time of newly created auth tokens
-# to be this many hours after their creation time.
-AUTH_TOKEN_DURATION = 30 * 24
-
-# Bypass authentication for user administration.
-BYPASS_ADMIN_AUTH = False
-
-# Show these many users per page in admin interface.
-ADMIN_PAGE_LIMIT = 100
-
-# Authenticate via Twitter.
-TWITTER_KEY = ''
-TWITTER_SECRET = ''
-
-INVITATIONS_PER_LEVEL = {
-    0   :   100,
-    1   :   2,
-    2   :   0,
-    3   :   0,
-    4   :   0
-}
-
-SERVICE_NAME = 'Pithos'
-
-# Address to use for outgoing emails
-DEFAULT_FROM_EMAIL = 'Pithos <no-reply@grnet.gr>'
-DEFAULT_CONTACT_EMAIL = 'support@pithos.grnet.gr'
-
-# Where users should signup with their invitation code
-SIGNUP_TARGET = '%s/im/signup/?code=%d&next=%s'
-
-# Where users should activate their local account
-ACTIVATION_LOGIN_TARGET = '%s/im/local/activate/?auth=%s&next=%s'
-
-# Where users should reset their local password
-PASSWORD_RESET_TARGET = '%s/im/local/reset/?username=%s&next=%s'
-
-# Identity Management enabled modules
-IM_MODULES = ['local', 'twitter', 'shibboleth']
-
-# Force user profile verification
-FORCE_PROFILE_UPDATE = False
-
-#Enable invitations
-INVITATIONS_ENABLED = True
diff --git a/pithos/settings.d/20-ui.conf b/pithos/settings.d/20-ui.conf
new file mode 100644 (file)
index 0000000..295a3c5
--- /dev/null
@@ -0,0 +1,2 @@
+FEEDBACK_FROM_EMAIL = 'Pithos <no-reply@grnet.gr>'
+FEEDBACK_CONTACT_EMAIL = 'support@pithos.grnet.gr'
\ No newline at end of file
diff --git a/pithos/settings.d/20-users.conf b/pithos/settings.d/20-users.conf
new file mode 100644 (file)
index 0000000..082840e
--- /dev/null
@@ -0,0 +1,2 @@
+# Where astakos is hosted.
+AUTHENTICATION_HOST = '127.0.0.1:10000'
diff --git a/pithos/settings.d/30-ui.conf b/pithos/settings.d/30-ui.conf
deleted file mode 100644 (file)
index f8041f0..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-FEEDBACK_FROM_EMAIL = DEFAULT_FROM_EMAIL
-FEEDBACK_CONTACT_EMAIL = DEFAULT_CONTACT_EMAIL
index 17cc94b..ca9f372 100644 (file)
@@ -38,6 +38,5 @@ urlpatterns = patterns('',
     (r'^v1(?:$|/)', include('pithos.api.urls')),
     (r'^v1\.0(?:$|/)', include('pithos.api.urls')),
     (r'^public/(?P<v_public>.+?)/?$', 'pithos.api.public.public_demux'),
-    (r'^im/', include('pithos.im.urls')),
     (r'^ui', include('pithos.ui.urls'))
 )
index 1d54a10..ddeba38 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -47,8 +47,6 @@ VERSION = get_version().replace(' ', '')
 
 INSTALL_REQUIRES = [
     'Django==1.2.3',
-    'South==0.7',
-    'httplib2==0.6.0',
     'SQLAlchemy==0.6.3',
     'MySQL-python==1.2.2',
     'psycopg2==2.2.1'