mirror of
https://codeberg.org/scip/digiproof.git
synced 2025-12-16 20:21:00 +01:00
initial commit
This commit is contained in:
15
Makefile
Normal file
15
Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
ts != date +"%Y-%m-%d-%H%M%S"
|
||||
dst = .backup/$(ts)
|
||||
src = js index.html css
|
||||
vers = js/libs/version.js
|
||||
|
||||
all: backup
|
||||
@echo var VERSION = \"$(ts)\" > $(vers);
|
||||
./mksingleton.pl index.html
|
||||
|
||||
backup:
|
||||
mkdir -p $(dst)
|
||||
cp -pRP $(src) $(dst)/
|
||||
|
||||
|
||||
|
||||
13
README.md
13
README.md
@@ -2,3 +2,16 @@ digiproof
|
||||
=========
|
||||
|
||||
Ember.js Digital Testament App
|
||||
|
||||
This is an javascript app which allows you to
|
||||
create and maintain a digital testament.
|
||||
|
||||
This is BETA software, use on your own risk.
|
||||
|
||||
If you want to try it, download the file ''digiproof.html''
|
||||
and open it locally in your browser.
|
||||
|
||||
Licensed under the GPL v2. Commercial redistribution
|
||||
prohibited.
|
||||
|
||||
Copyright (c) T.Linden.
|
||||
|
||||
8
TODO
Normal file
8
TODO
Normal file
@@ -0,0 +1,8 @@
|
||||
- wenn man beim Neuanlegen eines Assets die beiden
|
||||
Selects (Successor und Order) so lässt wie sie sind,
|
||||
wird null eingetragen, das Asset taucht nicht im
|
||||
Testament auf, successor.has_assets returned 0
|
||||
und das bleibt auch so, wenn man das Asset nach-
|
||||
träglich ändert.
|
||||
|
||||
Supposed Fix: Validate New Asset order+successor.
|
||||
132
css/bootstrap-fileupload.css
vendored
Normal file
132
css/bootstrap-fileupload.css
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/*!
|
||||
* Bootstrap v2.3.1-j6
|
||||
*
|
||||
* Copyright 2012 Twitter, Inc
|
||||
* Licensed under the Apache License v2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Designed and built with all the love in the world by @mdo and @fat, extended by @ArnoldDaniels.
|
||||
*/
|
||||
.clearfix {
|
||||
*zoom: 1;
|
||||
}
|
||||
.clearfix:before,
|
||||
.clearfix:after {
|
||||
display: table;
|
||||
content: "";
|
||||
line-height: 0;
|
||||
}
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
.hide-text {
|
||||
font: 0/0 a;
|
||||
color: transparent;
|
||||
text-shadow: none;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
.input-block-level {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: 30px;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.btn-file {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.btn-file > input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
filter: alpha(opacity=0);
|
||||
transform: translate(-300px, 0) scale(4);
|
||||
font-size: 23px;
|
||||
direction: ltr;
|
||||
cursor: pointer;
|
||||
}
|
||||
.fileupload {
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
.fileupload .uneditable-input {
|
||||
display: inline-block;
|
||||
margin-bottom: 0px;
|
||||
vertical-align: middle;
|
||||
cursor: text;
|
||||
}
|
||||
.fileupload .thumbnail {
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
margin-bottom: 5px;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
.fileupload .thumbnail > img {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
max-height: 100%;
|
||||
}
|
||||
.fileupload .btn {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.fileupload-exists .fileupload-new,
|
||||
.fileupload-new .fileupload-exists {
|
||||
display: none;
|
||||
}
|
||||
.fileupload-inline .fileupload-controls {
|
||||
display: inline;
|
||||
}
|
||||
.fileupload-new .input-append .btn-file {
|
||||
-webkit-border-radius: 0 3px 3px 0;
|
||||
-moz-border-radius: 0 3px 3px 0;
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
.thumbnail-borderless .thumbnail {
|
||||
border: none;
|
||||
padding: 0;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.fileupload-new.thumbnail-borderless .thumbnail {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.control-group.warning .fileupload .uneditable-input {
|
||||
color: #a47e3c;
|
||||
border-color: #a47e3c;
|
||||
}
|
||||
.control-group.warning .fileupload .fileupload-preview {
|
||||
color: #a47e3c;
|
||||
}
|
||||
.control-group.warning .fileupload .thumbnail {
|
||||
border-color: #a47e3c;
|
||||
}
|
||||
.control-group.error .fileupload .uneditable-input {
|
||||
color: #b94a48;
|
||||
border-color: #b94a48;
|
||||
}
|
||||
.control-group.error .fileupload .fileupload-preview {
|
||||
color: #b94a48;
|
||||
}
|
||||
.control-group.error .fileupload .thumbnail {
|
||||
border-color: #b94a48;
|
||||
}
|
||||
.control-group.success .fileupload .uneditable-input {
|
||||
color: #468847;
|
||||
border-color: #468847;
|
||||
}
|
||||
.control-group.success .fileupload .fileupload-preview {
|
||||
color: #468847;
|
||||
}
|
||||
.control-group.success .fileupload .thumbnail {
|
||||
border-color: #468847;
|
||||
}
|
||||
1109
css/bootstrap-responsive.css
vendored
Executable file
1109
css/bootstrap-responsive.css
vendored
Executable file
File diff suppressed because it is too large
Load Diff
6160
css/bootstrap.css
vendored
Executable file
6160
css/bootstrap.css
vendored
Executable file
File diff suppressed because one or more lines are too long
396
css/normalize.css
vendored
Executable file
396
css/normalize.css
vendored
Executable file
@@ -0,0 +1,396 @@
|
||||
/*! normalize.css v2.1.0 | MIT License | git.io/normalize */
|
||||
|
||||
/* ==========================================================================
|
||||
HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Correct `block` display not defined in IE 8/9.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct `inline-block` display not defined in IE 8/9.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Base
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Set default font family to sans-serif.
|
||||
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||
* user zoom.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default margin.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Links
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address `outline` inconsistency between Chrome and other browsers.
|
||||
*/
|
||||
|
||||
a:focus {
|
||||
outline: thin dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability when focused and also mouse hovered in all browsers.
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Typography
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address variable `h1` font-size and margin within `section` and `article`
|
||||
* contexts in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari 5 and Chrome.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
|
||||
hr {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct font family set oddly in Safari 5 and Chrome.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability of pre-formatted text in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set consistent quote types.
|
||||
*/
|
||||
|
||||
q {
|
||||
quotes: "\201C" "\201D" "\2018" "\2019";
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent and variable font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove border when inside `a` element in IE 8/9.
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct overflow displayed oddly in IE 9.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Figures
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address margin not present in IE 8/9 and Safari 5.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `color` not being inherited in IE 8/9.
|
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct font family not being inherited in all browsers.
|
||||
* 2. Correct font size not being inherited in all browsers.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
*/
|
||||
|
||||
button,
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||
* All other form control elements do not inherit `text-transform` values.
|
||||
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
|
||||
* Correct `select` style inheritance in Firefox 4+ and Opera.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Correct inability to style clickable `input` types in iOS.
|
||||
* 3. Improve usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
*/
|
||||
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address box sizing set to `content-box` in IE 8/9.
|
||||
* 2. Remove excess padding in IE 8/9.
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
|
||||
* (include `-moz` to future-proof).
|
||||
*/
|
||||
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box; /* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and search cancel button in Safari 5 and Chrome
|
||||
* on OS X.
|
||||
*/
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and border in Firefox 4+.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove default vertical scrollbar in IE 8/9.
|
||||
* 2. Improve readability and alignment in all browsers.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto; /* 1 */
|
||||
vertical-align: top; /* 2 */
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Tables
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
76
css/style.css
Executable file
76
css/style.css
Executable file
File diff suppressed because one or more lines are too long
3452
digiproof.html
Normal file
3452
digiproof.html
Normal file
File diff suppressed because one or more lines are too long
835
index.html
Normal file
835
index.html
Normal file
@@ -0,0 +1,835 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8 />
|
||||
<title>Digital Testament App</title>
|
||||
<link rel="stylesheet" href="css/normalize.css">
|
||||
<link rel="stylesheet" href="css/bootstrap.css" media="all">
|
||||
<link rel="stylesheet" href="css/bootstrap-fileupload.css" media="all">
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<script type="text/x-handlebars">
|
||||
<div class="navbar hidden-print">
|
||||
<div class="navbar-inner">
|
||||
<a class="brand" href="#">DigiProof</a>
|
||||
<ul class="nav">
|
||||
<li>{{#linkTo 'self'}}{{loc _self}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'successors'}}{{loc _successors}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'assets'}}{{loc _assets}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'testament'}}{{loc _testament}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'data'}}{{loc _data}}{{/linkTo}}</li>
|
||||
<li>{{#linkTo 'about'}}about{{/linkTo}}</li>
|
||||
</ul>
|
||||
<span class="pull-right">digiproof version {{VERSION}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{outlet}}
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/x-handlebars" id="about">
|
||||
<div class="row-fluid">
|
||||
<div class="span4">
|
||||
<div class="well">
|
||||
{{controller}}
|
||||
<span class="label label-info popup-marker" data-content="{{popup.login.title}}" data-original-title="{{popup.login.help}}">?</span>
|
||||
<span class="badge badge-success popup-marker" data-content="hilfetext III" data-original-title="Kurzhilfe III">?</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" id="my-popover-content">
|
||||
<p>tpl help</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" id="index">
|
||||
<div class="hero-unit">
|
||||
<div class="row-fluid">
|
||||
<div class="span4">
|
||||
<h4>{{loc _welcome}}</h4>
|
||||
<p>{{loc _intro}}</p>
|
||||
<p><img class="addlogo" src="" alt="" /></p>
|
||||
</div>
|
||||
<div class="span4">
|
||||
<h4>{{loc _fill}}</h4>
|
||||
<ol>
|
||||
<li>{{loc _fill_self}}<br/>
|
||||
{{#linkTo 'self'}}{{loc _enterself}}{{/linkTo}}
|
||||
</li>
|
||||
<li>{{loc _fill_successor}}<br/>
|
||||
{{#linkTo 'successors'}}{{loc _entersuccessor}}{{/linkTo}}
|
||||
</li>
|
||||
<li>{{loc _fill_asset}}<br/>
|
||||
{{#linkTo 'assets'}}{{loc _enterasset}}{{/linkTo}}
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" id="assets">
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
<div class="span3 bs-docs-sidebar">
|
||||
<ul class="nav nav-list bs-docs-sidenav">
|
||||
<li class="nav-header"><h4>{{loc _assets}} {{#linkTo 'assets.new'}}<span class="addicon"> <!--[if IE]>{{loc _add}}<![endif]--></span>{{/linkTo}}</h4></li>
|
||||
{{#each model}}
|
||||
{{#view App.NavView}}{{#linkTo 'assets.asset' this}}{{name}}{{/linkTo}}{{/view}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span9">
|
||||
{{outlet}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" id="assets/index">
|
||||
<div class="span9">
|
||||
{{loc _assetsindex}}
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/x-handlebars" id="assets/asset">
|
||||
<h4>{{loc _asset}}: {{name}}</h4>
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<!-- data -->
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _name}}:</p></div>
|
||||
<div class="span9">
|
||||
{{#if isEditing}}
|
||||
{{view Ember.TextField valueBinding="name"}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_name}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
{{else}}
|
||||
{{name}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _uri}}:</p></div>
|
||||
<div class="span9">
|
||||
{{#if isEditing}}
|
||||
{{view Ember.TextField valueBinding="uri"}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_uri}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
{{else}}
|
||||
{{uri}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _login}}:</p></div>
|
||||
<div class="span9">
|
||||
{{#if isEditing}}
|
||||
{{view Ember.TextField valueBinding="login"}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_login}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
{{else}}
|
||||
{{login}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _pass}}:</p></div>
|
||||
<div class="span9">
|
||||
{{#if isEditing}}
|
||||
{{view Ember.TextField valueBinding="password"}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_pass}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
{{else}}
|
||||
{{password}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _mail}}:</p></div>
|
||||
<div class="span9">
|
||||
{{#if isEditing}}
|
||||
{{view Ember.TextField valueBinding="mail"}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_mail}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
{{else}}
|
||||
{{mail}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{#if isEditing}}
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _successor}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.Select selectionBinding="successor"
|
||||
contentBinding="successors"
|
||||
optionValuePath="content.id"
|
||||
optionLabelPath="content.name"}}
|
||||
{{errors.successor}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_successor}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _ordered}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.Select selectionBinding="order"
|
||||
contentBinding="orders"
|
||||
optionValuePath="content.id"
|
||||
optionLabelPath="content.name"
|
||||
}}
|
||||
{{errors.order}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_order}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
{{#if isEditing}}
|
||||
<button class="btn btn-primary btn-default" {{action doneEditing}}>{{loc _save}}</button>
|
||||
<button class="btn btn-primary btn-default" {{action cancelEditing}}>{{loc _cancel}}</button>
|
||||
{{else}}
|
||||
<button class="btn btn-primary btn-default" {{action edit}}>{{loc _edit}}</button>
|
||||
<button class="btn btn-primary btn-default" {{action remove}}>{{loc _remove}}</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- formular end -->
|
||||
<div class="span6">
|
||||
<!-- successor display -->
|
||||
{{#if isEditing}}
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<h4>{{loc _notes}}:</h4>
|
||||
{{view Ember.TextArea valueBinding="notes" rows="10" cols="80"}}
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="row-fluid">
|
||||
<div class="span12"><h4>{{loc _successor}}</h4></div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _name}}:</p></div>
|
||||
<div class="span9">
|
||||
{{successor.name}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _address}}:</p></div>
|
||||
<div class="span9">
|
||||
{{successor.address}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _birth}}:</p></div>
|
||||
<div class="span9">
|
||||
{{successor.birth}}
|
||||
</div>
|
||||
</div>
|
||||
{{#if successor.name2}}
|
||||
<div class="row-fluid">
|
||||
<div class="span12"><h4>{{loc _substitute}}</h4></div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _name}}:</p></div>
|
||||
<div class="span9">
|
||||
{{successor.name2}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _address}}:</p></div>
|
||||
<div class="span9">
|
||||
{{successor.address2}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _birth}}:</p></div>
|
||||
<div class="span9">
|
||||
{{successor.birth2}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if order}}
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
{{loc _preordered}} <strong>{{order.name}}</strong> {{loc _postordered}}.
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if notes}}
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<h4>{{loc _notes}}:</h4>
|
||||
{{notes}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" id="assets/new">
|
||||
<h4>{{loc _addasset}}</h4>
|
||||
<div class="row-fluid">
|
||||
<div class="span7">
|
||||
<!-- formular -->
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _name}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="name"}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_name}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _uri}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="uri"}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_uri}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _login}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="login"}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_login}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _pass}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="password"}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_pass}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _mail}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="mail"}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_mail}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _successor}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.Select selectionBinding="successor"
|
||||
contentBinding="successors"
|
||||
optionValuePath="content.id"
|
||||
valueBinding="controller.selected_successor"
|
||||
optionLabelPath="content.name"
|
||||
}}
|
||||
{{errors.successor}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_successor}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _ordered}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.Select selectionBinding="order"
|
||||
contentBinding="orders"
|
||||
optionValuePath="content.id"
|
||||
optionLabelPath="content.name"
|
||||
valueBinding="controller.selected_order"
|
||||
}}
|
||||
{{errors.order}}
|
||||
<span class="label label-success popup-marker" data-content="{{loc _pop_order}}" data-original-title="{{loc _pop_title}}">?</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<button class="btn btn-primary btn-default" {{action 'createAsset'}}>{{loc _save}}</button>
|
||||
<button class="btn btn-primary btn-default" {{action 'createNextAsset'}}>{{loc _savenext}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- formular end -->
|
||||
<div class="span5">
|
||||
<!-- formular continued -->
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<h4>{{loc _notes}}:</h4>
|
||||
{{view Ember.TextArea valueBinding="notes" rows="10" cols="80"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- <img class="addicon" src="" alt="" /> -->
|
||||
|
||||
|
||||
|
||||
|
||||
<script type="text/x-handlebars" id="successors">
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
<div class="span3 bs-docs-sidebar">
|
||||
<ul class="nav nav-list bs-docs-sidenav">
|
||||
<li class="nav-header"><h4>{{loc _successors}} {{#linkTo 'successors.new'}}<span class="addicon"> <!--[if IE]>{{loc _add}}<![endif]--></span>{{/linkTo}}</h4></li>
|
||||
{{#each model}}
|
||||
{{#view App.NavView}}{{#linkTo 'successors.successor' this}}{{name}}{{/linkTo}}{{/view}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span9">
|
||||
{{outlet}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" id="successors/index">
|
||||
<div class="span9">
|
||||
{{loc _successorsindex}}
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
<script type="text/x-handlebars" id="successors/successor">
|
||||
<h4>{{loc _successor}}: {{name}}</h4>
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<!-- data -->
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _name}}:</p></div>
|
||||
<div class="span9">
|
||||
{{#if isEditing}}
|
||||
{{view Ember.TextField valueBinding="name"}} <span style="color: red">{{errors.name}}</span>
|
||||
{{else}}
|
||||
{{name}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _address}}:</p></div>
|
||||
<div class="span9">
|
||||
{{#if isEditing}}
|
||||
{{view Ember.TextField valueBinding="address"}}
|
||||
{{else}}
|
||||
{{address}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _birth}}:</p></div>
|
||||
<div class="span9">
|
||||
{{#if isEditing}}
|
||||
{{view Ember.TextField valueBinding="birth"}}
|
||||
{{else}}
|
||||
{{birth}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
{{#if isEditing}}
|
||||
<button class="btn btn-primary btn-default" {{action doneEditing}}>{{loc _save}}</button>
|
||||
<button class="btn btn-primary btn-default" {{action cancelEditing}}>{{loc _cancel}}</button>
|
||||
{{else}}
|
||||
<button class="btn btn-primary btn-default" {{action edit}}>{{loc _edit}}</button>
|
||||
<button class="btn btn-primary btn-default" {{action remove}}>{{loc _remove}}</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- formular end -->
|
||||
<div class="span6">
|
||||
<!-- substitute successor form -->
|
||||
{{#if isEditing}}
|
||||
<div class="row-fluid">
|
||||
<div class="span12"><h4>{{loc _substitute}}</h4></div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _name}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="name2"}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _address}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="address2"}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _birth}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="birth2"}}
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
{{#if name2}}
|
||||
<div class="row-fluid">
|
||||
<div class="span12"><h4>{{loc _substitute}}</h4></div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _name}}:</p></div>
|
||||
<div class="span9">
|
||||
{{name2}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _address}}:</p></div>
|
||||
<div class="span9">
|
||||
{{address2}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _birth}}:</p></div>
|
||||
<div class="span9">
|
||||
{{birth2}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
<script type="text/x-handlebars" id="successors/new">
|
||||
<h4>{{loc _addsuccessor}}</h4>
|
||||
<div class="row-fluid">
|
||||
<div class="span7">
|
||||
<!-- formular -->
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _name}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="name"}} <span style="color: red">{{errors.name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _address}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="address"}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _birth}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="birth"}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<button class="btn btn-primary btn-default" {{action 'createSuccessor'}}>{{loc _save}}</button>
|
||||
<button class="btn btn-primary btn-default" {{action 'createNextSuccessor'}}>{{loc _savenext}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- formular end -->
|
||||
<div class="span5">
|
||||
<!-- substitute successor -->
|
||||
<div class="row-fluid">
|
||||
<div class="span12"><h4>{{loc _substitute}}</h4></div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _name}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="name2"}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _address}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="address2"}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _birth}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="birth2"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/x-handlebars" id="testament">
|
||||
<div class="row-fluid">
|
||||
{{#if notempty}}
|
||||
{{#if self.password}}
|
||||
<div class="span12 hidden-print">
|
||||
<p>{{loc _print}} <a href="http://www.howtogeek.com/howto/the-geek-blog/prevent-firefox-or-internet-explorer-from-printing-the-url-on-every-page/">setup browser</a></p>
|
||||
<button class="btn btn-primary btn-large" onClick="window.print()">{{loc _doprint}}</button>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="span4 hidden-print">
|
||||
{{loc _testamentempty}}{{#linkTo 'successors.new'}}{{loc _addsuccessor}}{{/linkTo}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<div class="span4 hidden-print">
|
||||
{{loc _testamentempty}}{{#linkTo 'successors.new'}}{{loc _addsuccessor}}{{/linkTo}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
{{#if notempty}}
|
||||
{{#if self.password}}
|
||||
<p class="pr-toptitle">{{loc _ttitle}}</p>
|
||||
{{#each successor in successors}}
|
||||
{{#if successor.has_assets}}
|
||||
<p class="pr-text">{{loc _appoint1}}{{self.name}} ({{self.birth}}, {{self.address}}){{loc _appoint2}}</p>
|
||||
<p>
|
||||
<span class="pr-title">{{successor.name}}:</span><br/>
|
||||
<span class="pr-text">
|
||||
{{#if successor.address}}{{successor.address}}<br/>{{/if}}
|
||||
{{#if successor.birth}}{{loc _birth}}: {{successor.birth}}{{/if}}
|
||||
</span>
|
||||
{{#if successor.name2}}
|
||||
</p>
|
||||
<p class="pr-text">{{loc _appoint2}}</p>
|
||||
<p>
|
||||
<span class="pr-title">{{successor.name2}}:</span><br/>
|
||||
<span class="pr-text">
|
||||
{{#if successor.address2}}{{successor.address2}}<br/>{{/if}}
|
||||
{{#if successor.birth2}}{{loc _birth}}: {{successor.birth2}}{{/if}}
|
||||
</span>
|
||||
{{/if}}
|
||||
<p class="pr-text">{{loc _successorshall}}</p>
|
||||
</p>
|
||||
{{#each asset in successor.assets}}
|
||||
<p class="pr-title">{{loc _asset}}: <strong>{{asset.name}}</strong></span>
|
||||
<table class="table ">
|
||||
<tr><th width="15%" class="pr-label">{{loc _uri}}</th><td>{{asset.uri}}</td></tr>
|
||||
<tr><th class="pr-label">{{loc _login}}</th><td class="pr-data">{{asset.login}}</td></tr>
|
||||
<tr><th class="pr-label">{{loc _pass}}</th><td class="pr-data">{{asset.password}}</td></tr>
|
||||
<tr><th class="pr-label">{{loc _mail}}</th><td class="pr-data">{{asset.mail}}</td></tr>
|
||||
<tr><th class="pr-label">{{loc _notes}}</th><td class="pr-data">{{asset.notes}}</td></tr>
|
||||
<tr><td colspan="2" class="pr-text">
|
||||
{{loc _preordered}} <strong>{{asset.order.name}}</strong>
|
||||
{{loc _postordered}}.</td></tr>
|
||||
</table>
|
||||
<!--<div style="page-break-before:always"></div>-->
|
||||
{{/each}}
|
||||
<p><strong>{{loc _date}}</strong>: {{date now}}</p>
|
||||
<p><strong>{{loc _place}}</strong>:</p>
|
||||
<p><strong>{{loc _sign}}</strong>:</p>
|
||||
{{/if}}
|
||||
{{/each}} <!-- end each successor -->
|
||||
{{/if}} <!-- end if self.haspasswd -->
|
||||
{{/if}} <! -- end if notempty -->
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" id="self">
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<h4>{{loc _selftitle}}</h4>
|
||||
<!-- data -->
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _name}}:</p></div>
|
||||
<div class="span9">
|
||||
{{#if isEditing}}
|
||||
{{view Ember.TextField valueBinding="name"}} <span style="color: red">{{errors.name}}</span>
|
||||
{{else}}
|
||||
{{name}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _address}}:</p></div>
|
||||
<div class="span9">
|
||||
{{#if isEditing}}
|
||||
{{view Ember.TextField valueBinding="address"}} <span style="color: red">{{errors.address}}</span>
|
||||
{{else}}
|
||||
{{address}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _birth}}:</p></div>
|
||||
<div class="span9">
|
||||
{{#if isEditing}}
|
||||
{{view Ember.TextField valueBinding="birth"}} <span style="color: red">{{errors.birth}}</span>
|
||||
{{else}}
|
||||
{{birth}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{#if isEditing}}
|
||||
<div class="row-fluid">
|
||||
<div class="span3"><p>{{loc _pass}}:</p></div>
|
||||
<div class="span9">
|
||||
{{view Ember.TextField valueBinding="password" type="password"}} <span style="color: red">{{errors.password}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
{{#if isEditing}}
|
||||
<button class="btn btn-primary btn-default" {{action doneEditing}}>{{loc _save}}</button>
|
||||
<button class="btn btn-primary btn-default" {{action cancelEditing}}>{{loc _cancel}}</button>
|
||||
{{else}}
|
||||
<button class="btn btn-primary btn-default" {{action edit}}>{{loc _edit}}</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- formular end -->
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" id="data">
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
<div class="span3 bs-docs-sidebar">
|
||||
<ul class="nav nav-list bs-docs-sidenav">
|
||||
<li class="nav-header"><h4>{{loc _data}}</h4></li>
|
||||
{{#view App.NavView}}{{#linkTo 'data.export'}}{{loc _export}}{{/linkTo}}{{/view}}
|
||||
{{#view App.NavView}}{{#linkTo 'data.import'}}{{loc _import}}{{/linkTo}}{{/view}}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span9">
|
||||
{{outlet}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" id="data/index">
|
||||
<h4>{{loc _data}}</h4>
|
||||
<p>{{loc _dataindex}}</p>
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<script type="text/x-handlebars" id="data/export">
|
||||
<h4>{{loc _export}}</h4>
|
||||
{{#if self.password}}
|
||||
<p>{{loc _exporthelp}}</p>
|
||||
<div id="rawjson" style="display: none">
|
||||
{
|
||||
"successors": [
|
||||
{{#each successor in successors}}
|
||||
{{successor.toJson}},
|
||||
{{/each}}
|
||||
],
|
||||
"assets": [
|
||||
{{#each asset in assets}}
|
||||
{{asset.toJson}},
|
||||
{{/each}}
|
||||
],
|
||||
"self": {{self.toJson}}
|
||||
}
|
||||
</div>
|
||||
<div id="rawdata" style="display: none"></div>
|
||||
<div id="rawp" style="display: none">{{self.password}}</div>
|
||||
<button class="btn btn-primary btn-default" {{action download}}>{{loc _download}}</button>
|
||||
{{else}}
|
||||
{{loc _nopasswd}}: {{#linkTo 'self'}}{{loc _self}}{{/linkTo}}.
|
||||
{{/if}}
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" id="data/import">
|
||||
<h4>{{loc _import}}</h4>
|
||||
{{#if isEditing}}
|
||||
<div class="row-fluid">
|
||||
<div class="span4">
|
||||
<p>{{loc _importhelp}}</p>
|
||||
</div>
|
||||
<div class="span8">
|
||||
{{view Ember.TextArea valueBinding="importdata" rows="10" cols="80"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span4">
|
||||
<p>{{loc _up_file}}</p>
|
||||
</div>
|
||||
<div class="span8">
|
||||
<!--
|
||||
via http://jasny.github.io/bootstrap/javascript.html#fileupload
|
||||
-->
|
||||
<div class="fileupload fileupload-new" data-provides="fileupload">
|
||||
<div class="input-append">
|
||||
<div class="uneditable-input span3">
|
||||
<i class="icon-file fileupload-exists"></i>
|
||||
<span class="fileupload-preview"></span>
|
||||
</div>
|
||||
<span class="btn btn-file">
|
||||
<span class="fileupload-new">{{loc _up_select}}</span>
|
||||
<span class="fileupload-exists">{{loc _up_change}}</span>
|
||||
{{view App.UploadFileView name="import" contentBinding="content"}}
|
||||
</span>
|
||||
<a href="#" class="btn fileupload-exists" data-dismiss="fileupload">{{loc _up_remove}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span4">
|
||||
<p>{{loc _importpass}}</p>
|
||||
</div>
|
||||
<div class="span8">
|
||||
{{view Ember.TextField valueBinding="password" type="password"}} <span style="color: red">{{errors.password}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<button class="btn btn-primary btn-default" {{action doneEditing}}>{{loc _import}}</button>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<p>{{clear}}</p>
|
||||
<p><button class="btn btn-primary btn-default" {{action repeatEditing}}>{{loc _importagain}}</button></p>
|
||||
{{/if}}
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" id="data/done">
|
||||
<h4>{{loc _import}}</h4>
|
||||
<p>{{clear}}</p>
|
||||
<p>{{controller}}</p>
|
||||
</script>
|
||||
|
||||
|
||||
<script src="js/libs/globals.js"></script>
|
||||
<script src="js/libs/jquery.js"></script>
|
||||
<script src="js/libs/handlebars.js"></script>
|
||||
<script src="js/libs/ember.js"></script>
|
||||
<script src="js/libs/ember-data.js"></script>
|
||||
<script src="js/libs/localstorage_adapter.js"></script>
|
||||
<script src="js/libs/moment.js"></script>
|
||||
|
||||
<script src="js/libs/aes.js"></script>
|
||||
<script src="js/libs/sha512.js"></script>
|
||||
<script src="js/libs/hmac-sha512.js"></script>
|
||||
|
||||
<script src="js/libs/blob.js"></script>
|
||||
<script src="js/libs/filesaver.js"></script>
|
||||
<script src="js/libs/bootstrap-fileupload.js"></script>
|
||||
<script src="js/libs/bootstrap-tooltip.js"></script>
|
||||
<script src="js/libs/bootstrap-popover.js"></script>
|
||||
<script src="js/libs/json3.js"></script>
|
||||
<script src="js/libs/version.js"></script>
|
||||
|
||||
<script src="js/init.js"></script>
|
||||
<script src="js/locale.js"></script>
|
||||
<script src="js/mixins.js"></script>
|
||||
<script src="js/models.js"></script>
|
||||
<script src="js/store.js"></script>
|
||||
<script src="js/router.js"></script>
|
||||
<script src="js/apphelpers.js"></script>
|
||||
<script src="js/controllers_asset.js"></script>
|
||||
<script src="js/controllers_index.js"></script>
|
||||
<script src="js/controllers_self.js"></script>
|
||||
<script src="js/controllers_successor.js"></script>
|
||||
<script src="js/controllers_data.js"></script>
|
||||
<script src="js/controllers_testament.js"></script>
|
||||
<script src="js/controllers_about.js"></script>
|
||||
<script src="js/handlebars_helpers.js"></script>
|
||||
|
||||
</body>
|
||||
81
js/apphelpers.js
Normal file
81
js/apphelpers.js
Normal file
@@ -0,0 +1,81 @@
|
||||
function CheckForEmptyDB() {
|
||||
var assets = App.Asset.find();
|
||||
var notempty = true;
|
||||
notempty = assets.forEach(function(asset) {
|
||||
return false;
|
||||
});
|
||||
return notempty;
|
||||
}
|
||||
|
||||
|
||||
// Convert hex string to ASCII.
|
||||
// See http://stackoverflow.com/questions/11889329/word-array-to-string
|
||||
function hex2a(hex) {
|
||||
var str = '';
|
||||
for (var i = 0; i < hex.length; i += 2)
|
||||
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
|
||||
return str;
|
||||
}
|
||||
|
||||
function decryptimportOLD(pass, data) {
|
||||
var enpass = CryptoJS.SHA512(pass).toString(CryptoJS.enc.Base64);
|
||||
var clear = CryptoJS.AES.decrypt(data, enpass);
|
||||
return unescape(hex2a(clear.toString()));
|
||||
}
|
||||
|
||||
function decryptimport(hash, data) {
|
||||
var clear = CryptoJS.AES.decrypt(data, hash);
|
||||
return unescape(hex2a(clear.toString()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// from:
|
||||
// http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html
|
||||
function decode64(input) {
|
||||
var output = "";
|
||||
var chr1, chr2, chr3 = "";
|
||||
var enc1, enc2, enc3, enc4 = "";
|
||||
var i = 0;
|
||||
|
||||
var keyStr = "ABCDEFGHIJKLMNOP" +
|
||||
"QRSTUVWXYZabcdef" +
|
||||
"ghijklmnopqrstuv" +
|
||||
"wxyz0123456789+/" +
|
||||
"=";
|
||||
|
||||
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
|
||||
var base64test = /[^A-Za-z0-9\+\/\=]/g; //
|
||||
if (base64test.exec(input)) {
|
||||
alert("There were invalid base64 characters in the input text.\n" +
|
||||
"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
|
||||
"Expect errors in decoding.");
|
||||
}
|
||||
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||
|
||||
do {
|
||||
enc1 = keyStr.indexOf(input.charAt(i++));
|
||||
enc2 = keyStr.indexOf(input.charAt(i++));
|
||||
enc3 = keyStr.indexOf(input.charAt(i++));
|
||||
enc4 = keyStr.indexOf(input.charAt(i++));
|
||||
|
||||
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||
|
||||
output = output + String.fromCharCode(chr1);
|
||||
|
||||
if (enc3 != 64) {
|
||||
output = output + String.fromCharCode(chr2);
|
||||
}
|
||||
if (enc4 != 64) {
|
||||
output = output + String.fromCharCode(chr3);
|
||||
}
|
||||
|
||||
chr1 = chr2 = chr3 = "";
|
||||
enc1 = enc2 = enc3 = enc4 = "";
|
||||
|
||||
} while (i < input.length);
|
||||
|
||||
return unescape(output);
|
||||
}
|
||||
8
js/controllers_about.js
Normal file
8
js/controllers_about.js
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
App.AboutController = Ember.Controller.extend({
|
||||
popup: { login: { title: "titel", help: "hilfe" } }
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
100
js/controllers_asset.js
Normal file
100
js/controllers_asset.js
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
|
||||
App.AssetsAssetController = Ember.ObjectController.extend({
|
||||
isEditing: false,
|
||||
orders: App.Order.find(),
|
||||
errors: {},
|
||||
|
||||
edit: function() {
|
||||
// prepare order to the actual object, not id
|
||||
this.set('isEditing', true);
|
||||
this.set('successors', App.Successor.find());
|
||||
},
|
||||
|
||||
doneEditing: function() {
|
||||
var validated = this.get('model').validate();
|
||||
if(validated.valid){
|
||||
this.set('isEditing', false);
|
||||
this.get('model').get("store").commit();
|
||||
}
|
||||
else {
|
||||
this.set('errors', validated);
|
||||
this.set('isEditing', true);
|
||||
}
|
||||
},
|
||||
|
||||
cancelEditing: function() {
|
||||
this.set('isEditing', false);
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
var asset = this.get('model');
|
||||
asset.deleteRecord();
|
||||
asset.get("store").commit();
|
||||
this.get("target").transitionTo("assets");
|
||||
}
|
||||
});
|
||||
|
||||
App.AssetsNewController = Ember.ArrayController.extend({
|
||||
successors: App.Successor.find(),
|
||||
orders: App.Order.find(),
|
||||
next: 0,
|
||||
selected_successor: 0,
|
||||
selected_order: 0,
|
||||
errors: {},
|
||||
|
||||
|
||||
createNextAsset: function () {
|
||||
this.set('next', 1);
|
||||
this.createAsset();
|
||||
},
|
||||
|
||||
createAsset: function () {
|
||||
var name = this.get('name');
|
||||
if (!name.trim()) { return; }
|
||||
//console.log("successor: %o", this.get('order'));
|
||||
|
||||
var asset = App.Asset.createRecord({
|
||||
name: name,
|
||||
uri: this.get('uri'),
|
||||
login: this.get('login'),
|
||||
password: this.get('password'),
|
||||
mail: this.get('mail'),
|
||||
successor: this.get('successor'),
|
||||
order: this.get('order'),
|
||||
notes: this.get('notes')
|
||||
});
|
||||
|
||||
var validated = asset.validate();
|
||||
//console.log("validated: %o", validated);
|
||||
if(! validated.valid) {
|
||||
asset.deleteRecord();
|
||||
this.set('errors', validated);
|
||||
this.set('isEditing', true);
|
||||
}
|
||||
else {
|
||||
// Save the new model
|
||||
asset.get("store").commit();
|
||||
|
||||
// empty form fields so new entries starts from scratch
|
||||
this.set('name', '');
|
||||
this.set('uri', '');
|
||||
this.set('login', '');
|
||||
this.set('password', '');
|
||||
this.set('mail', '');
|
||||
this.set('order', '');
|
||||
this.set('successor','');
|
||||
this.set('notes', '');
|
||||
|
||||
if(this.get('next') == 1) {
|
||||
this.get("target").transitionTo("assets.new");
|
||||
}
|
||||
else {
|
||||
// redirect to newly created entry
|
||||
this.get("target").transitionTo("assets.asset", asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
337
js/controllers_data.js
Normal file
337
js/controllers_data.js
Normal file
@@ -0,0 +1,337 @@
|
||||
|
||||
|
||||
App.DataExportController = Ember.ArrayController.extend({
|
||||
successors: App.Successor.find(),
|
||||
self: App.Self.find(0),
|
||||
assets: App.Asset.find(),
|
||||
download: function() {
|
||||
/*
|
||||
Encrypt the data:
|
||||
|
||||
1) the data/export template receives all objects and puts
|
||||
json objects of it into the invisible div 'rawjson'.
|
||||
this happened on first template execution.
|
||||
|
||||
2) when the 'download' action gets triggered, fetch that
|
||||
generated json out of the div.
|
||||
|
||||
3) fetch self.pass and create an SHA512 hash from it.
|
||||
|
||||
4) hash this hash 32times recursive (that is, create a
|
||||
hash of the previous hash and so on 32 times).
|
||||
|
||||
5) encrypt the json string using AES256 using the generated
|
||||
base64 encoded hash.
|
||||
|
||||
6) put the base64 encoded encrypted data into the div 'rawdata'
|
||||
|
||||
7) retrieve the data from 'rawdata'. note: it doesn't work
|
||||
to just continue to work with the already base64 encoded
|
||||
data (variable cr), it is empty. however, if we put it into
|
||||
the div and retrieve it right away then it's filled.
|
||||
that's reliable javascript programming, yay.
|
||||
|
||||
8) now calculate a SHA256 MAC authentication message of the
|
||||
base64 encoded encrypted data using the base64 encoded
|
||||
password hash (=> mac).
|
||||
|
||||
9) concatenate the mac and the encrypted data (mac first minus
|
||||
the last 2 chars '==') (=> signedcrypted).
|
||||
|
||||
10) insert a msdos newline every 64 chars so that we get a nice
|
||||
base64 encoded block.
|
||||
|
||||
11) add a header and footer to that block.
|
||||
|
||||
12) create a Blob object of that block.
|
||||
|
||||
13) put up a "save as..." dialog box to the user using this
|
||||
blob as content.
|
||||
|
||||
*/
|
||||
var raw = $('#rawjson').text();
|
||||
var pass = $('#rawp').text();
|
||||
var hash = CryptoJS.SHA512(pass);
|
||||
|
||||
for(var i=0; i<31; i++) {
|
||||
hash = CryptoJS.SHA512(hash);
|
||||
}
|
||||
|
||||
var cr = CryptoJS.AES.encrypt(escape(raw), hash.toString(CryptoJS.enc.Base64));
|
||||
|
||||
$('#rawdata').text(cr);
|
||||
|
||||
var crypted = $('#rawdata').text();
|
||||
|
||||
var mac = CryptoJS.HmacSHA512(crypted, hash.toString(CryptoJS.enc.Base64));
|
||||
var signedcrypted = mac.toString(CryptoJS.enc.Base64).substring(0,86) + crypted;
|
||||
|
||||
console.log("raw: %s", raw);
|
||||
console.log("cr: %s", crypted);
|
||||
console.log("pass: <%s>, hash: <%s>", pass, hash.toString(CryptoJS.enc.Base64));
|
||||
console.log("mac: %s", mac.toString(CryptoJS.enc.Base64).substring(0,86));
|
||||
|
||||
var block = '';
|
||||
var c = 1;
|
||||
for(var i=0; i<signedcrypted.length; i++) {
|
||||
block += signedcrypted[i];
|
||||
if(c == 64) {
|
||||
block += "\r\n";
|
||||
c = 0;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
|
||||
|
||||
block = "---- BEGIN ENCRYPTED DIGIPROOF DATA ----\r\n"
|
||||
+ block + "\r\n---- END ENCRYPTED DIGIPROOF DATA ----\r\n";
|
||||
var blob = new Blob([block], {type: "text/plain;charset=utf-8"});
|
||||
saveAs(blob, "digiproof-export.txt");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
var UploadedImport = null;
|
||||
App.UploadFileView = Ember.TextField.extend({
|
||||
// WARN: this one gets fired as soon as the user selected a file
|
||||
// that is, before the submit button got clicked
|
||||
type: 'file',
|
||||
attributeBindings: ['name'],
|
||||
change: function(evt) {
|
||||
var self = this;
|
||||
var input = evt.target;
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
var that = this;
|
||||
reader.onload = function(e) {
|
||||
var fileToUpload = e.srcElement.result;
|
||||
UploadedImport = decode64(fileToUpload.split(',')[1]);
|
||||
}
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
App.DataImportController = Ember.ObjectController.extend({
|
||||
isEditing: true,
|
||||
clear: '',
|
||||
errors: {},
|
||||
|
||||
doneEditing: function() {
|
||||
// decrypt and reload models
|
||||
var validated = this.get('model').validate();
|
||||
if(validated.valid) {
|
||||
this.set('isEditing', false);
|
||||
pass = this.get('password');
|
||||
|
||||
try {
|
||||
var raw = '';
|
||||
if(UploadedImport) {
|
||||
//console.log("using upload");
|
||||
raw = UploadedImport;
|
||||
UploadedImport = null;
|
||||
}
|
||||
else if (this.get('importdata')) {
|
||||
//console.log("using input");
|
||||
raw = this.get('importdata');
|
||||
}
|
||||
else {
|
||||
throw 'No import data provided';
|
||||
}
|
||||
|
||||
// check for header and footer
|
||||
var begin = raw.search(/BEGIN ENCRYPTED DIGIPROOF DATA/);
|
||||
var end = raw.search(/END ENCRYPTED DIGIPROOF DATA/);
|
||||
if(begin == -1 || end == -1) {
|
||||
throw 'Invalid formatted import data';
|
||||
}
|
||||
|
||||
// remove them
|
||||
var rawlines = raw.split(/\r\n/);
|
||||
var b64lines = rawlines.slice(1).slice(0, rawlines.length - 3);
|
||||
|
||||
// put together as full b64 string
|
||||
var b64 = b64lines.join('');
|
||||
|
||||
// extract the auth message
|
||||
var b64mac = b64.substring(0,86) + '==';
|
||||
var b64cr = b64.substring(86);
|
||||
|
||||
console.log("b64mac: %s", b64mac);
|
||||
|
||||
// create the password hash
|
||||
var hash = CryptoJS.SHA512(pass);
|
||||
for(var i=0; i<31; i++) {
|
||||
hash = CryptoJS.SHA512(hash);
|
||||
}
|
||||
|
||||
// verify the mac
|
||||
var mac = CryptoJS.HmacSHA512(b64cr, hash.toString(CryptoJS.enc.Base64));
|
||||
console.log("mac: %s", mac.toString(CryptoJS.enc.Base64));
|
||||
if(mac.toString(CryptoJS.enc.Base64) !== b64mac) {
|
||||
throw 'Authentication MAC verification failed, rejecting manipulated encrypted data';
|
||||
}
|
||||
|
||||
// now if we're her, decrypt the data
|
||||
var json = decryptimport(hash.toString(CryptoJS.enc.Base64), b64cr);
|
||||
console.log("pass: <%s>, hash: <%s>, hash: %o", pass, hash.toString(CryptoJS.enc.Base64), hash);
|
||||
console.log("json: %s", json);
|
||||
|
||||
// make it an obj
|
||||
var importobj = JSON.parse(json); // FIXME: SyntaxError: Unexpected token ], liegt am Komma nach dem letzten item
|
||||
console.log("imported json: %o", importobj);
|
||||
}
|
||||
catch (e) {
|
||||
console.log("decryption exception: %o", e);
|
||||
this.set('clear', translate('_error_decrypt') + " (" + e + ")");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no password given
|
||||
this.set('isEditing', true);
|
||||
this.set('errors', validated);
|
||||
this.set('clear', translate('_error_decrypt'));
|
||||
}
|
||||
},
|
||||
|
||||
doneEditingXXX: function() {
|
||||
var validated = this.get('model').validate();
|
||||
|
||||
// decrypt and reload models
|
||||
if(validated.valid) {
|
||||
this.set('isEditing', false);
|
||||
pass = this.get('password');
|
||||
|
||||
try {
|
||||
var entries = '';
|
||||
if(UploadedImport) {
|
||||
//console.log("using upload");
|
||||
entries = UploadedImport.match(/[^\r\n]+/g);
|
||||
UploadedImport = null;
|
||||
}
|
||||
else if (this.get('importdata')) {
|
||||
//console.log("using input");
|
||||
entries = this.get('importdata').match(/[^\r\n]+/g);
|
||||
}
|
||||
else {
|
||||
throw 'No import data provided';
|
||||
}
|
||||
//console.log("got %d entries: %o", entries.length, entries);
|
||||
var json = '';
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
var importline = entries[i].split(',');
|
||||
//console.log("splitted: %o", importline);
|
||||
if(importline[0] === 'asset') {
|
||||
//console.log("import asset");
|
||||
json = decryptimport(pass, importline[1]);
|
||||
if(json) {
|
||||
//console.log("evaluating: %s", json);
|
||||
var obj = JSON.parse(json);
|
||||
//console.log("code: %o", obj);
|
||||
var exists = App.Asset.all().some(function(asset) {
|
||||
return asset.get('id') === obj.id;
|
||||
});
|
||||
if(exists) {
|
||||
/* update
|
||||
FIXME: Updating doesn't work yet for some unknown reason
|
||||
App.Asset.find(obj.id).then(function(asset) {
|
||||
asset.set("name", obj.name);
|
||||
asset.set("uri", obj.uri);
|
||||
asset.set("login", obj.login);
|
||||
asset.set("password", obj.password);
|
||||
asset.set("mail", obj.mail);
|
||||
asset.set("successor", App.Successor.find(obj.successor));
|
||||
asset.set("order", App.Order.find(obj.order));
|
||||
asset.set("notes", obj.notes);
|
||||
});
|
||||
*/
|
||||
}
|
||||
else {
|
||||
// create
|
||||
var asset = App.Asset.createRecord({
|
||||
id: obj.id,
|
||||
name: obj.name,
|
||||
uri: obj.uri,
|
||||
login: obj.login,
|
||||
password: obj.password,
|
||||
mail: obj.mail,
|
||||
successor: App.Successor.find(obj.successor),
|
||||
order: App.Order.find(obj.order),
|
||||
notes: obj.notes
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw 'decrypted variable $json doesnt contain anything, weird';
|
||||
}
|
||||
}
|
||||
else if (importline[0] === 'successor') {
|
||||
console.log("import successor");
|
||||
json = decryptimport(pass, importline[1]);
|
||||
console.log("evaluating: %s", json);
|
||||
if(json) {
|
||||
var obj = JSON.parse(json);
|
||||
if(obj.id !== "0") {
|
||||
var exists = App.Successor.all().some(function(successor) {
|
||||
return successor.get('id') === obj.id;
|
||||
});
|
||||
if(! exists) {
|
||||
var successor = App.Successor.createRecord(obj);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//console.log("ignoring id 0");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw 'decrypted variable $json doesnt contain anything, weird';
|
||||
}
|
||||
}
|
||||
else if (importline[0] === 'self') {
|
||||
console.log("import self");
|
||||
json = decryptimport(pass, importline[1]);
|
||||
console.log("evaluating: %s", json);
|
||||
if(json) {
|
||||
var obj = JSON.parse(json);
|
||||
var self = App.Self.find(0).then(function(self) {
|
||||
//console.log("didLoad on self fired, putting %o with pass %s", obj, pass);
|
||||
self.set('name', obj.name);
|
||||
self.set('birth', obj.birth);
|
||||
self.set('address', obj.address);
|
||||
self.set('password', pass);
|
||||
});
|
||||
}
|
||||
else {
|
||||
throw 'decrypted variable $json doesnt contain anything, weird';
|
||||
}
|
||||
}
|
||||
/*
|
||||
else {
|
||||
console.log("import unknown");
|
||||
}
|
||||
*/
|
||||
}
|
||||
App.store.commit();
|
||||
this.set('clear', translate('_importdone'));
|
||||
}
|
||||
catch (e) {
|
||||
console.log("decryption exception: %o", e);
|
||||
this.set('clear', translate('_error_decrypt') + " (" + e + ")");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no password given
|
||||
this.set('isEditing', true);
|
||||
this.set('errors', validated);
|
||||
this.set('clear', translate('_error_decrypt'));
|
||||
}
|
||||
},
|
||||
|
||||
repeatEditing: function() {
|
||||
this.set('isEditing', true);
|
||||
this.set('importdata', '');
|
||||
this.set('password', '');
|
||||
}
|
||||
});
|
||||
27
js/controllers_index.js
Normal file
27
js/controllers_index.js
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
App.IndexController = Ember.Controller.extend({
|
||||
has_self: App.Self.find(),
|
||||
has_asset: App.Asset.find(),
|
||||
has_successor: App.Successor.find(),
|
||||
VERSION: VERSION
|
||||
});
|
||||
|
||||
|
||||
|
||||
App.NavView = Ember.View.extend({
|
||||
tagName: 'li',
|
||||
classNameBindings: 'active'.w(),
|
||||
|
||||
didInsertElement: function () {
|
||||
this._super();
|
||||
var _this = this;
|
||||
this.get('parentView').on('click', function () {
|
||||
_this.notifyPropertyChange('active');
|
||||
});
|
||||
},
|
||||
|
||||
active: function () {
|
||||
return this.get('childViews.firstObject.active');
|
||||
}.property()
|
||||
});
|
||||
|
||||
27
js/controllers_self.js
Normal file
27
js/controllers_self.js
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
App.SelfController = Ember.ObjectController.extend({
|
||||
isEditing: false,
|
||||
errors: {},
|
||||
|
||||
edit: function() {
|
||||
// prepare order to the actual object, not id
|
||||
this.set('isEditing', true);
|
||||
},
|
||||
|
||||
doneEditing: function() {
|
||||
var validated = this.get('model').validate();
|
||||
if(! validated.valid) {
|
||||
this.set('errors', validated);
|
||||
this.set('isEditing', true);
|
||||
}
|
||||
else {
|
||||
this.set('isEditing', false);
|
||||
this.get('model').get("store").commit();
|
||||
}
|
||||
},
|
||||
|
||||
cancelEditing: function() {
|
||||
this.set('isEditing', false);
|
||||
}
|
||||
});
|
||||
|
||||
86
js/controllers_successor.js
Normal file
86
js/controllers_successor.js
Normal file
@@ -0,0 +1,86 @@
|
||||
|
||||
|
||||
|
||||
|
||||
App.SuccessorsSuccessorController = Ember.ObjectController.extend({
|
||||
isEditing: false,
|
||||
errors: {},
|
||||
|
||||
edit: function() {
|
||||
this.set('isEditing', true);
|
||||
},
|
||||
|
||||
doneEditing: function() {
|
||||
var validated = this.get('model').validate();
|
||||
if(! validated.valid) {
|
||||
this.set('errors', validated);
|
||||
this.set('isEditing', true);
|
||||
}
|
||||
else {
|
||||
this.set('isEditing', false);
|
||||
this.get('model').get("store").commit();
|
||||
}
|
||||
},
|
||||
|
||||
cancelEditing: function() {
|
||||
this.set('isEditing', false);
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
var successor = this.get('model');
|
||||
successor.deleteRecord();
|
||||
successor.get("store").commit();
|
||||
this.get("target").transitionTo("successors");
|
||||
}
|
||||
});
|
||||
|
||||
App.SuccessorsNewController = Ember.ArrayController.extend({
|
||||
newName: '',
|
||||
next: 0,
|
||||
erros: {},
|
||||
|
||||
createNextSuccessor: function () {
|
||||
this.set('next', 1);
|
||||
this.createSuccessor();
|
||||
},
|
||||
|
||||
createSuccessor: function () {
|
||||
var successor = App.Successor.createRecord({
|
||||
name: this.get('name'),
|
||||
address: this.get('address'),
|
||||
birth: this.get('birth'),
|
||||
name2: this.get('name2'),
|
||||
address2: this.get('address2'),
|
||||
birth2: this.get('birth2')
|
||||
});
|
||||
|
||||
var validated = successor.validate();
|
||||
//console.log("validated: %o", validated);
|
||||
if(! validated.valid) {
|
||||
successor.deleteRecord();
|
||||
this.set('errors', validated);
|
||||
this.set('isEditing', true);
|
||||
}
|
||||
else {
|
||||
// Save the new model
|
||||
successor.get("store").commit();
|
||||
|
||||
// empty form fields so new entries starts from scratch
|
||||
this.set('name', '');
|
||||
this.set('address', '');
|
||||
this.set('birth', '');
|
||||
this.set('name2', '');
|
||||
this.set('address2', '');
|
||||
this.set('birth2', '');
|
||||
|
||||
if(this.get('next') == 1) {
|
||||
this.get("target").transitionTo("successors.new");
|
||||
}
|
||||
else {
|
||||
// redirect to newly created entry
|
||||
this.get("target").transitionTo("successors.successor", successor);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
10
js/controllers_testament.js
Normal file
10
js/controllers_testament.js
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
App.TestamentController = Ember.ArrayController.extend({
|
||||
needs: "self",
|
||||
//self: Ember.computed.alias("controllers.self"),
|
||||
successors: App.Successor.find(),
|
||||
self: App.Self.find(0),
|
||||
now: new Date(),
|
||||
notempty: CheckForEmptyDB()
|
||||
});
|
||||
|
||||
275
js/fs.js
Executable file
275
js/fs.js
Executable file
@@ -0,0 +1,275 @@
|
||||
|
||||
//--
|
||||
//-- Filesystem code from TiddlyWiki
|
||||
//--
|
||||
|
||||
function convertUTF8ToUnicode(u)
|
||||
{
|
||||
return window.netscape == undefined ? manualConvertUTF8ToUnicode(u) : mozConvertUTF8ToUnicode(u);
|
||||
}
|
||||
|
||||
function manualConvertUTF8ToUnicode(utf)
|
||||
{
|
||||
var uni = utf;
|
||||
var src = 0;
|
||||
var dst = 0;
|
||||
var b1, b2, b3;
|
||||
var c;
|
||||
while(src < utf.length) {
|
||||
b1 = utf.charCodeAt(src++);
|
||||
if(b1 < 0x80) {
|
||||
dst++;
|
||||
} else if(b1 < 0xE0) {
|
||||
b2 = utf.charCodeAt(src++);
|
||||
c = String.fromCharCode(((b1 & 0x1F) << 6) | (b2 & 0x3F));
|
||||
uni = uni.substring(0,dst++).concat(c,utf.substr(src));
|
||||
} else {
|
||||
b2 = utf.charCodeAt(src++);
|
||||
b3 = utf.charCodeAt(src++);
|
||||
c = String.fromCharCode(((b1 & 0xF) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F));
|
||||
uni = uni.substring(0,dst++).concat(c,utf.substr(src));
|
||||
}
|
||||
}
|
||||
return uni;
|
||||
}
|
||||
|
||||
function mozConvertUTF8ToUnicode(u)
|
||||
{
|
||||
try {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
} catch(ex) {
|
||||
return manualConvertUTF8ToUnicode(u);
|
||||
} // fallback
|
||||
var s = converter.ConvertToUnicode(u);
|
||||
var fin = converter.Finish();
|
||||
return (fin.length > 0) ? s+fin : s;
|
||||
}
|
||||
|
||||
function convertUnicodeToUTF8(s)
|
||||
{
|
||||
if(window.netscape == undefined)
|
||||
return manualConvertUnicodeToUTF8(s);
|
||||
else
|
||||
return mozConvertUnicodeToUTF8(s);
|
||||
}
|
||||
|
||||
|
||||
function manualConvertUnicodeToUTF8(s)
|
||||
{
|
||||
var re = /[^\u0000-\u007F]/g ;
|
||||
return s.replace(re,function($0) {return "&#" + $0.charCodeAt(0).toString() + ";";});
|
||||
}
|
||||
|
||||
function mozConvertUnicodeToUTF8(s)
|
||||
{
|
||||
try {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
} catch(ex) {
|
||||
return manualConvertUnicodeToUTF8(s);
|
||||
} // fallback
|
||||
var u = converter.ConvertFromUnicode(s);
|
||||
var fin = converter.Finish();
|
||||
return fin.length > 0 ? u + fin : u;
|
||||
}
|
||||
|
||||
function convertUriToUTF8(uri,charSet)
|
||||
{
|
||||
if(window.netscape == undefined || charSet == undefined || charSet == "")
|
||||
return uri;
|
||||
try {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var converter = Components.classes["@mozilla.org/intl/utf8converterservice;1"].getService(Components.interfaces.nsIUTF8ConverterService);
|
||||
} catch(ex) {
|
||||
return uri;
|
||||
}
|
||||
return converter.convertURISpecToUTF8(uri,charSet);
|
||||
}
|
||||
|
||||
function saveFile(fileUrl,content)
|
||||
{
|
||||
var r = mozillaSaveFile(fileUrl,content);
|
||||
if(!r)
|
||||
r = ieSaveFile(fileUrl,content);
|
||||
if(!r)
|
||||
r = javaSaveFile(fileUrl,content);
|
||||
return r;
|
||||
}
|
||||
|
||||
function loadFile(fileUrl)
|
||||
{
|
||||
var r = mozillaLoadFile(fileUrl);
|
||||
if((r == null) || (r == false))
|
||||
r = ieLoadFile(fileUrl);
|
||||
if((r == null) || (r == false))
|
||||
r = javaLoadFile(fileUrl);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
function ieCreatePath(path)
|
||||
{
|
||||
try {
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
} catch(ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var pos = path.lastIndexOf("\\");
|
||||
if(pos!=-1)
|
||||
path = path.substring(0, pos+1);
|
||||
|
||||
var scan = [];
|
||||
scan.push(path);
|
||||
var i = 0;
|
||||
do {
|
||||
var parent = fso.GetParentFolderName(scan[i++]);
|
||||
if (fso.FolderExists(parent))
|
||||
break;
|
||||
scan.push(parent);
|
||||
} while(true);
|
||||
|
||||
for(i=scan.length-1;i>=0;i--) {
|
||||
if (!fso.FolderExists(scan[i]))
|
||||
fso.CreateFolder(scan[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns null if it can't do it, false if there's an error, true if it saved OK
|
||||
function ieSaveFile(filePath,content)
|
||||
{
|
||||
ieCreatePath(filePath);
|
||||
try {
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
} catch(ex) {
|
||||
return null;
|
||||
}
|
||||
var file = fso.OpenTextFile(filePath,2,-1,0);
|
||||
file.Write(content);
|
||||
file.Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Returns null if it can't do it, false if there's an error, or a string of the content if successful
|
||||
function ieLoadFile(filePath)
|
||||
{
|
||||
try {
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
var file = fso.OpenTextFile(filePath,1);
|
||||
var content = file.ReadAll();
|
||||
file.Close();
|
||||
} catch(ex) {
|
||||
return null;
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
function ieCopyFile(dest,source)
|
||||
{
|
||||
ieCreatePath(dest);
|
||||
try {
|
||||
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
fso.GetFile(source).Copy(dest);
|
||||
} catch(ex) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns null if it can't do it, false if there's an error, true if it saved OK
|
||||
function mozillaSaveFile(filePath,content)
|
||||
{
|
||||
if(window.Components) {
|
||||
try {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
|
||||
file.initWithPath(filePath);
|
||||
if(!file.exists())
|
||||
file.create(0,0664);
|
||||
var out = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
out.init(file,0x20|0x02,00004,null);
|
||||
out.write(content,content.length);
|
||||
out.flush();
|
||||
out.close();
|
||||
return true;
|
||||
} catch(ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Returns null if it can't do it, false if there's an error, or a string of the content if successful
|
||||
function mozillaLoadFile(filePath)
|
||||
{
|
||||
if(window.Components) {
|
||||
try {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
|
||||
file.initWithPath(filePath);
|
||||
if(!file.exists())
|
||||
return null;
|
||||
var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
|
||||
inputStream.init(file,0x01,00004,null);
|
||||
var sInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
|
||||
sInputStream.init(inputStream);
|
||||
return sInputStream.read(sInputStream.available());
|
||||
} catch(ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function javaUrlToFilename(url)
|
||||
{
|
||||
var f = "//localhost";
|
||||
if(url.indexOf(f) == 0)
|
||||
return url.substring(f.length);
|
||||
var i = url.indexOf(":");
|
||||
if(i > 0)
|
||||
return url.substring(i-1);
|
||||
return url;
|
||||
}
|
||||
|
||||
function javaSaveFile(filePath,content)
|
||||
{
|
||||
try {
|
||||
if(document.applets["TiddlySaver"])
|
||||
return document.applets["TiddlySaver"].saveFile(javaUrlToFilename(filePath),"UTF-8",content);
|
||||
} catch(ex) {
|
||||
}
|
||||
try {
|
||||
var s = new java.io.PrintStream(new java.io.FileOutputStream(javaUrlToFilename(filePath)));
|
||||
s.print(content);
|
||||
s.close();
|
||||
} catch(ex) {
|
||||
return null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function javaLoadFile(filePath)
|
||||
{
|
||||
try {
|
||||
if(document.applets["TiddlySaver"])
|
||||
return String(document.applets["TiddlySaver"].loadFile(javaUrlToFilename(filePath),"UTF-8"));
|
||||
} catch(ex) {
|
||||
}
|
||||
var content = [];
|
||||
try {
|
||||
var r = new java.io.BufferedReader(new java.io.FileReader(javaUrlToFilename(filePath)));
|
||||
var line;
|
||||
while((line = r.readLine()) != null)
|
||||
content.push(new String(line));
|
||||
r.close();
|
||||
} catch(ex) {
|
||||
return null;
|
||||
}
|
||||
return content.join("\n");
|
||||
}
|
||||
55
js/handlebars_helpers.js
Normal file
55
js/handlebars_helpers.js
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
// https://gist.github.com/tracend/3261055
|
||||
Ember.Handlebars.registerBoundHelper('loc', function(keyword, options) {
|
||||
// pick the right dictionary
|
||||
var locale = window.locale[lang] || window.locale['en-US'];
|
||||
|
||||
// loop through all the key hierarchy (if any)
|
||||
var target = locale;
|
||||
|
||||
//console.log("key: %o", [keyword, options.data.properties[0]]);
|
||||
var key;
|
||||
if(keyword) {
|
||||
key = keyword;
|
||||
}
|
||||
else {
|
||||
key = options.data.properties[0];
|
||||
}
|
||||
keyword = '';
|
||||
options.data.properties[0] = '';
|
||||
|
||||
if(key) {
|
||||
if(key in locale) {
|
||||
return locale[key];
|
||||
}
|
||||
else {
|
||||
return '__UNTRANSLATED_STRING__(' + key + ')';
|
||||
}
|
||||
}
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
Ember.Handlebars.registerBoundHelper('ifeq', function(v1, v2, options) {
|
||||
return (this.get(v1) == v2) ? options.fn(this) : '';
|
||||
});
|
||||
|
||||
Ember.Handlebars.registerBoundHelper('date', function(date) {
|
||||
moment().lang(lang);
|
||||
return moment(date).format('LL');
|
||||
});
|
||||
|
||||
Ember.Handlebars.registerBoundHelper('encrypt', function(cleartext) {
|
||||
pass = App.Self.find(0).get('password');
|
||||
if(pass) {
|
||||
var enpass = CryptoJS.SHA512(pass).toString(CryptoJS.enc.Base64);
|
||||
//console.log("pass: %s, enpass: %s", pass, enpass);
|
||||
var cr = CryptoJS.AES.encrypt(escape(cleartext), enpass);
|
||||
return cr;
|
||||
|
||||
}
|
||||
else {
|
||||
return "Failed to encrypt, not password set";
|
||||
}
|
||||
});
|
||||
25
js/hmac-sha512.js
Normal file
25
js/hmac-sha512.js
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
var CryptoJS=CryptoJS||function(a,j){var c={},b=c.lib={},f=function(){},l=b.Base={extend:function(a){f.prototype=this;var d=new f;a&&d.mixIn(a);d.hasOwnProperty("init")||(d.init=function(){d.$super.init.apply(this,arguments)});d.init.prototype=d;d.$super=this;return d},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var d in a)a.hasOwnProperty(d)&&(this[d]=a[d]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
|
||||
u=b.WordArray=l.extend({init:function(a,d){a=this.words=a||[];this.sigBytes=d!=j?d:4*a.length},toString:function(a){return(a||m).stringify(this)},concat:function(a){var d=this.words,M=a.words,e=this.sigBytes;a=a.sigBytes;this.clamp();if(e%4)for(var b=0;b<a;b++)d[e+b>>>2]|=(M[b>>>2]>>>24-8*(b%4)&255)<<24-8*((e+b)%4);else if(65535<M.length)for(b=0;b<a;b+=4)d[e+b>>>2]=M[b>>>2];else d.push.apply(d,M);this.sigBytes+=a;return this},clamp:function(){var D=this.words,d=this.sigBytes;D[d>>>2]&=4294967295<<
|
||||
32-8*(d%4);D.length=a.ceil(d/4)},clone:function(){var a=l.clone.call(this);a.words=this.words.slice(0);return a},random:function(D){for(var d=[],b=0;b<D;b+=4)d.push(4294967296*a.random()|0);return new u.init(d,D)}}),k=c.enc={},m=k.Hex={stringify:function(a){var d=a.words;a=a.sigBytes;for(var b=[],e=0;e<a;e++){var c=d[e>>>2]>>>24-8*(e%4)&255;b.push((c>>>4).toString(16));b.push((c&15).toString(16))}return b.join("")},parse:function(a){for(var d=a.length,b=[],e=0;e<d;e+=2)b[e>>>3]|=parseInt(a.substr(e,
|
||||
2),16)<<24-4*(e%8);return new u.init(b,d/2)}},y=k.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var c=[],e=0;e<a;e++)c.push(String.fromCharCode(b[e>>>2]>>>24-8*(e%4)&255));return c.join("")},parse:function(a){for(var b=a.length,c=[],e=0;e<b;e++)c[e>>>2]|=(a.charCodeAt(e)&255)<<24-8*(e%4);return new u.init(c,b)}},z=k.Utf8={stringify:function(a){try{return decodeURIComponent(escape(y.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return y.parse(unescape(encodeURIComponent(a)))}},
|
||||
x=b.BufferedBlockAlgorithm=l.extend({reset:function(){this._data=new u.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=z.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(b){var d=this._data,c=d.words,e=d.sigBytes,l=this.blockSize,k=e/(4*l),k=b?a.ceil(k):a.max((k|0)-this._minBufferSize,0);b=k*l;e=a.min(4*b,e);if(b){for(var x=0;x<b;x+=l)this._doProcessBlock(c,x);x=c.splice(0,b);d.sigBytes-=e}return new u.init(x,e)},clone:function(){var a=l.clone.call(this);
|
||||
a._data=this._data.clone();return a},_minBufferSize:0});b.Hasher=x.extend({cfg:l.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){x.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,c){return(new a.init(c)).finalize(b)}},_createHmacHelper:function(a){return function(b,c){return(new ja.HMAC.init(a,
|
||||
c)).finalize(b)}}});var ja=c.algo={};return c}(Math);
|
||||
(function(a){var j=CryptoJS,c=j.lib,b=c.Base,f=c.WordArray,j=j.x64={};j.Word=b.extend({init:function(a,b){this.high=a;this.low=b}});j.WordArray=b.extend({init:function(b,c){b=this.words=b||[];this.sigBytes=c!=a?c:8*b.length},toX32:function(){for(var a=this.words,b=a.length,c=[],m=0;m<b;m++){var y=a[m];c.push(y.high);c.push(y.low)}return f.create(c,this.sigBytes)},clone:function(){for(var a=b.clone.call(this),c=a.words=this.words.slice(0),k=c.length,f=0;f<k;f++)c[f]=c[f].clone();return a}})})();
|
||||
(function(){function a(){return f.create.apply(f,arguments)}for(var j=CryptoJS,c=j.lib.Hasher,b=j.x64,f=b.Word,l=b.WordArray,b=j.algo,u=[a(1116352408,3609767458),a(1899447441,602891725),a(3049323471,3964484399),a(3921009573,2173295548),a(961987163,4081628472),a(1508970993,3053834265),a(2453635748,2937671579),a(2870763221,3664609560),a(3624381080,2734883394),a(310598401,1164996542),a(607225278,1323610764),a(1426881987,3590304994),a(1925078388,4068182383),a(2162078206,991336113),a(2614888103,633803317),
|
||||
a(3248222580,3479774868),a(3835390401,2666613458),a(4022224774,944711139),a(264347078,2341262773),a(604807628,2007800933),a(770255983,1495990901),a(1249150122,1856431235),a(1555081692,3175218132),a(1996064986,2198950837),a(2554220882,3999719339),a(2821834349,766784016),a(2952996808,2566594879),a(3210313671,3203337956),a(3336571891,1034457026),a(3584528711,2466948901),a(113926993,3758326383),a(338241895,168717936),a(666307205,1188179964),a(773529912,1546045734),a(1294757372,1522805485),a(1396182291,
|
||||
2643833823),a(1695183700,2343527390),a(1986661051,1014477480),a(2177026350,1206759142),a(2456956037,344077627),a(2730485921,1290863460),a(2820302411,3158454273),a(3259730800,3505952657),a(3345764771,106217008),a(3516065817,3606008344),a(3600352804,1432725776),a(4094571909,1467031594),a(275423344,851169720),a(430227734,3100823752),a(506948616,1363258195),a(659060556,3750685593),a(883997877,3785050280),a(958139571,3318307427),a(1322822218,3812723403),a(1537002063,2003034995),a(1747873779,3602036899),
|
||||
a(1955562222,1575990012),a(2024104815,1125592928),a(2227730452,2716904306),a(2361852424,442776044),a(2428436474,593698344),a(2756734187,3733110249),a(3204031479,2999351573),a(3329325298,3815920427),a(3391569614,3928383900),a(3515267271,566280711),a(3940187606,3454069534),a(4118630271,4000239992),a(116418474,1914138554),a(174292421,2731055270),a(289380356,3203993006),a(460393269,320620315),a(685471733,587496836),a(852142971,1086792851),a(1017036298,365543100),a(1126000580,2618297676),a(1288033470,
|
||||
3409855158),a(1501505948,4234509866),a(1607167915,987167468),a(1816402316,1246189591)],k=[],m=0;80>m;m++)k[m]=a();b=b.SHA512=c.extend({_doReset:function(){this._hash=new l.init([new f.init(1779033703,4089235720),new f.init(3144134277,2227873595),new f.init(1013904242,4271175723),new f.init(2773480762,1595750129),new f.init(1359893119,2917565137),new f.init(2600822924,725511199),new f.init(528734635,4215389547),new f.init(1541459225,327033209)])},_doProcessBlock:function(a,b){for(var c=this._hash.words,
|
||||
f=c[0],j=c[1],d=c[2],l=c[3],e=c[4],m=c[5],N=c[6],c=c[7],aa=f.high,O=f.low,ba=j.high,P=j.low,ca=d.high,Q=d.low,da=l.high,R=l.low,ea=e.high,S=e.low,fa=m.high,T=m.low,ga=N.high,U=N.low,ha=c.high,V=c.low,r=aa,n=O,G=ba,E=P,H=ca,F=Q,Y=da,I=R,s=ea,p=S,W=fa,J=T,X=ga,K=U,Z=ha,L=V,t=0;80>t;t++){var A=k[t];if(16>t)var q=A.high=a[b+2*t]|0,g=A.low=a[b+2*t+1]|0;else{var q=k[t-15],g=q.high,v=q.low,q=(g>>>1|v<<31)^(g>>>8|v<<24)^g>>>7,v=(v>>>1|g<<31)^(v>>>8|g<<24)^(v>>>7|g<<25),C=k[t-2],g=C.high,h=C.low,C=(g>>>19|
|
||||
h<<13)^(g<<3|h>>>29)^g>>>6,h=(h>>>19|g<<13)^(h<<3|g>>>29)^(h>>>6|g<<26),g=k[t-7],$=g.high,B=k[t-16],w=B.high,B=B.low,g=v+g.low,q=q+$+(g>>>0<v>>>0?1:0),g=g+h,q=q+C+(g>>>0<h>>>0?1:0),g=g+B,q=q+w+(g>>>0<B>>>0?1:0);A.high=q;A.low=g}var $=s&W^~s&X,B=p&J^~p&K,A=r&G^r&H^G&H,ka=n&E^n&F^E&F,v=(r>>>28|n<<4)^(r<<30|n>>>2)^(r<<25|n>>>7),C=(n>>>28|r<<4)^(n<<30|r>>>2)^(n<<25|r>>>7),h=u[t],la=h.high,ia=h.low,h=L+((p>>>14|s<<18)^(p>>>18|s<<14)^(p<<23|s>>>9)),w=Z+((s>>>14|p<<18)^(s>>>18|p<<14)^(s<<23|p>>>9))+(h>>>
|
||||
0<L>>>0?1:0),h=h+B,w=w+$+(h>>>0<B>>>0?1:0),h=h+ia,w=w+la+(h>>>0<ia>>>0?1:0),h=h+g,w=w+q+(h>>>0<g>>>0?1:0),g=C+ka,A=v+A+(g>>>0<C>>>0?1:0),Z=X,L=K,X=W,K=J,W=s,J=p,p=I+h|0,s=Y+w+(p>>>0<I>>>0?1:0)|0,Y=H,I=F,H=G,F=E,G=r,E=n,n=h+g|0,r=w+A+(n>>>0<h>>>0?1:0)|0}O=f.low=O+n;f.high=aa+r+(O>>>0<n>>>0?1:0);P=j.low=P+E;j.high=ba+G+(P>>>0<E>>>0?1:0);Q=d.low=Q+F;d.high=ca+H+(Q>>>0<F>>>0?1:0);R=l.low=R+I;l.high=da+Y+(R>>>0<I>>>0?1:0);S=e.low=S+p;e.high=ea+s+(S>>>0<p>>>0?1:0);T=m.low=T+J;m.high=fa+W+(T>>>0<J>>>0?1:
|
||||
0);U=N.low=U+K;N.high=ga+X+(U>>>0<K>>>0?1:0);V=c.low=V+L;c.high=ha+Z+(V>>>0<L>>>0?1:0)},_doFinalize:function(){var a=this._data,b=a.words,c=8*this._nDataBytes,f=8*a.sigBytes;b[f>>>5]|=128<<24-f%32;b[(f+128>>>10<<5)+30]=Math.floor(c/4294967296);b[(f+128>>>10<<5)+31]=c;a.sigBytes=4*b.length;this._process();return this._hash.toX32()},clone:function(){var a=c.clone.call(this);a._hash=this._hash.clone();return a},blockSize:32});j.SHA512=c._createHelper(b);j.HmacSHA512=c._createHmacHelper(b)})();
|
||||
(function(){var a=CryptoJS,j=a.enc.Utf8;a.algo.HMAC=a.lib.Base.extend({init:function(a,b){a=this._hasher=new a.init;"string"==typeof b&&(b=j.parse(b));var f=a.blockSize,l=4*f;b.sigBytes>l&&(b=a.finalize(b));b.clamp();for(var u=this._oKey=b.clone(),k=this._iKey=b.clone(),m=u.words,y=k.words,z=0;z<f;z++)m[z]^=1549556828,y[z]^=909522486;u.sigBytes=k.sigBytes=l;this.reset()},reset:function(){var a=this._hasher;a.reset();a.update(this._iKey)},update:function(a){this._hasher.update(a);return this},finalize:function(a){var b=
|
||||
this._hasher;a=b.finalize(a);b.reset();return b.finalize(this._oKey.clone().concat(a))}})})();
|
||||
26
js/init.js
Normal file
26
js/init.js
Normal file
@@ -0,0 +1,26 @@
|
||||
App = Ember.Application.create({
|
||||
//LOG_TRANSITIONS: true
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* make sure, only one popover appears at a time.
|
||||
* if the user hovers over another help button,
|
||||
* hide other popovers and display the new. Hide
|
||||
* all if not above a help button at all.
|
||||
*/
|
||||
$(document).ready(function () {
|
||||
$('.popup-marker').popover({
|
||||
html: true,
|
||||
trigger: 'hover'
|
||||
}).click(function(e) {
|
||||
$('.popup-marker').not(this).popover('hide');
|
||||
$(this).popover('toggle');
|
||||
});
|
||||
$(document).click(function(e) {
|
||||
if (!$(e.target).is('.popup-marker, .popover-title, .popover-content')) {
|
||||
$('.popup-marker').popover('hide');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
35
js/libs/aes.js
Normal file
35
js/libs/aes.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
|
||||
r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k<a;k++)c[j+k>>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535<e.length)for(k=0;k<a;k+=4)c[j+k>>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<
|
||||
32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e<a;e+=4)c.push(4294967296*u.random()|0);return new r.init(c,a)}}),w=d.enc={},v=w.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++){var k=c[j>>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j+=2)e[j>>>3]|=parseInt(a.substr(j,
|
||||
2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++)e.push(String.fromCharCode(c[j>>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j++)e[j>>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}},
|
||||
q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q<a;q+=k)this._doProcessBlock(e,q);q=e.splice(0,a);c.sigBytes-=j}return new r.init(q,j)},clone:function(){var a=t.clone.call(this);
|
||||
a._data=this._data.clone();return a},_minBufferSize:0});l.Hasher=q.extend({cfg:t.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){q.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,e){return(new a.init(e)).finalize(b)}},_createHmacHelper:function(a){return function(b,e){return(new n.HMAC.init(a,
|
||||
e)).finalize(b)}}});var n=d.algo={};return d}(Math);
|
||||
(function(){var u=CryptoJS,p=u.lib.WordArray;u.enc.Base64={stringify:function(d){var l=d.words,p=d.sigBytes,t=this._map;d.clamp();d=[];for(var r=0;r<p;r+=3)for(var w=(l[r>>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v<p;v++)d.push(t.charAt(w>>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w<
|
||||
l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();
|
||||
(function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<<j|b>>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<<j|b>>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<<j|b>>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<<j|b>>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])},
|
||||
_doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]),
|
||||
f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f,
|
||||
m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m,
|
||||
E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/
|
||||
4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math);
|
||||
(function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length<q;){n&&s.update(n);var n=s.update(d).finalize(r);s.reset();for(var a=1;a<p;a++)n=s.finalize(n),s.reset();b.concat(n)}b.sigBytes=4*q;return b}});u.EvpKDF=function(d,l,p){return s.create(p).compute(d,
|
||||
l)}})();
|
||||
CryptoJS.lib.Cipher||function(u){var p=CryptoJS,d=p.lib,l=d.Base,s=d.WordArray,t=d.BufferedBlockAlgorithm,r=p.enc.Base64,w=p.algo.EvpKDF,v=d.Cipher=t.extend({cfg:l.extend(),createEncryptor:function(e,a){return this.create(this._ENC_XFORM_MODE,e,a)},createDecryptor:function(e,a){return this.create(this._DEC_XFORM_MODE,e,a)},init:function(e,a,b){this.cfg=this.cfg.extend(b);this._xformMode=e;this._key=a;this.reset()},reset:function(){t.reset.call(this);this._doReset()},process:function(e){this._append(e);return this._process()},
|
||||
finalize:function(e){e&&this._append(e);return this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(e){return{encrypt:function(b,k,d){return("string"==typeof k?c:a).encrypt(e,b,k,d)},decrypt:function(b,k,d){return("string"==typeof k?c:a).decrypt(e,b,k,d)}}}});d.StreamCipher=v.extend({_doFinalize:function(){return this._process(!0)},blockSize:1});var b=p.mode={},x=function(e,a,b){var c=this._iv;c?this._iv=u:c=this._prevBlock;for(var d=0;d<b;d++)e[a+d]^=
|
||||
c[d]},q=(d.BlockCipherMode=l.extend({createEncryptor:function(e,a){return this.Encryptor.create(e,a)},createDecryptor:function(e,a){return this.Decryptor.create(e,a)},init:function(e,a){this._cipher=e;this._iv=a}})).extend();q.Encryptor=q.extend({processBlock:function(e,a){var b=this._cipher,c=b.blockSize;x.call(this,e,a,c);b.encryptBlock(e,a);this._prevBlock=e.slice(a,a+c)}});q.Decryptor=q.extend({processBlock:function(e,a){var b=this._cipher,c=b.blockSize,d=e.slice(a,a+c);b.decryptBlock(e,a);x.call(this,
|
||||
e,a,c);this._prevBlock=d}});b=b.CBC=q;q=(p.pad={}).Pkcs7={pad:function(a,b){for(var c=4*b,c=c-a.sigBytes%c,d=c<<24|c<<16|c<<8|c,l=[],n=0;n<c;n+=4)l.push(d);c=s.create(l,c);a.concat(c)},unpad:function(a){a.sigBytes-=a.words[a.sigBytes-1>>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a,
|
||||
this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684,
|
||||
1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})},
|
||||
decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d,
|
||||
b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}();
|
||||
(function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8,
|
||||
16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j<a;j++)if(j<d)e[j]=c[j];else{var k=e[j-1];j%d?6<d&&4==j%d&&(k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;d<a;d++)j=a-d,k=d%4?e[j]:e[j-4],c[d]=4>d||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>>
|
||||
8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r<m;r++)var q=d[g>>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t=
|
||||
d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})();
|
||||
166
js/libs/blob.js
Normal file
166
js/libs/blob.js
Normal file
@@ -0,0 +1,166 @@
|
||||
/* Blob.js
|
||||
* A Blob implementation.
|
||||
* 2013-06-20
|
||||
*
|
||||
* By Eli Grey, http://eligrey.com
|
||||
* By Devin Samarin, https://github.com/eboyjr
|
||||
* License: X11/MIT
|
||||
* See LICENSE.md
|
||||
*/
|
||||
|
||||
/*global self, unescape */
|
||||
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
|
||||
plusplus: true */
|
||||
|
||||
/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
|
||||
|
||||
if (!(typeof Blob === "function" || typeof Blob === "object") || typeof URL === "undefined")
|
||||
if ((typeof Blob === "function" || typeof Blob === "object") && typeof webkitURL !== "undefined") self.URL = webkitURL;
|
||||
else var Blob = (function (view) {
|
||||
"use strict";
|
||||
|
||||
var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || view.MSBlobBuilder || (function(view) {
|
||||
var
|
||||
get_class = function(object) {
|
||||
return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
|
||||
}
|
||||
, FakeBlobBuilder = function BlobBuilder() {
|
||||
this.data = [];
|
||||
}
|
||||
, FakeBlob = function Blob(data, type, encoding) {
|
||||
this.data = data;
|
||||
this.size = data.length;
|
||||
this.type = type;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
, FBB_proto = FakeBlobBuilder.prototype
|
||||
, FB_proto = FakeBlob.prototype
|
||||
, FileReaderSync = view.FileReaderSync
|
||||
, FileException = function(type) {
|
||||
this.code = this[this.name = type];
|
||||
}
|
||||
, file_ex_codes = (
|
||||
"NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
|
||||
+ "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
|
||||
).split(" ")
|
||||
, file_ex_code = file_ex_codes.length
|
||||
, real_URL = view.URL || view.webkitURL || view
|
||||
, real_create_object_URL = real_URL.createObjectURL
|
||||
, real_revoke_object_URL = real_URL.revokeObjectURL
|
||||
, URL = real_URL
|
||||
, btoa = view.btoa
|
||||
, atob = view.atob
|
||||
|
||||
, ArrayBuffer = view.ArrayBuffer
|
||||
, Uint8Array = view.Uint8Array
|
||||
;
|
||||
FakeBlob.fake = FB_proto.fake = true;
|
||||
while (file_ex_code--) {
|
||||
FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
|
||||
}
|
||||
if (!real_URL.createObjectURL) {
|
||||
URL = view.URL = {};
|
||||
}
|
||||
URL.createObjectURL = function(blob) {
|
||||
var
|
||||
type = blob.type
|
||||
, data_URI_header
|
||||
;
|
||||
if (type === null) {
|
||||
type = "application/octet-stream";
|
||||
}
|
||||
if (blob instanceof FakeBlob) {
|
||||
data_URI_header = "data:" + type;
|
||||
if (blob.encoding === "base64") {
|
||||
return data_URI_header + ";base64," + blob.data;
|
||||
} else if (blob.encoding === "URI") {
|
||||
return data_URI_header + "," + decodeURIComponent(blob.data);
|
||||
} if (btoa) {
|
||||
return data_URI_header + ";base64," + btoa(blob.data);
|
||||
} else {
|
||||
return data_URI_header + "," + encodeURIComponent(blob.data);
|
||||
}
|
||||
} else if (real_create_object_URL) {
|
||||
return real_create_object_URL.call(real_URL, blob);
|
||||
}
|
||||
};
|
||||
URL.revokeObjectURL = function(object_URL) {
|
||||
if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
|
||||
real_revoke_object_URL.call(real_URL, object_URL);
|
||||
}
|
||||
};
|
||||
FBB_proto.append = function(data/*, endings*/) {
|
||||
var bb = this.data;
|
||||
// decode data to a binary string
|
||||
if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
|
||||
var
|
||||
str = ""
|
||||
, buf = new Uint8Array(data)
|
||||
, i = 0
|
||||
, buf_len = buf.length
|
||||
;
|
||||
for (; i < buf_len; i++) {
|
||||
str += String.fromCharCode(buf[i]);
|
||||
}
|
||||
bb.push(str);
|
||||
} else if (get_class(data) === "Blob" || get_class(data) === "File") {
|
||||
if (FileReaderSync) {
|
||||
var fr = new FileReaderSync;
|
||||
bb.push(fr.readAsBinaryString(data));
|
||||
} else {
|
||||
// async FileReader won't work as BlobBuilder is sync
|
||||
throw new FileException("NOT_READABLE_ERR");
|
||||
}
|
||||
} else if (data instanceof FakeBlob) {
|
||||
if (data.encoding === "base64" && atob) {
|
||||
bb.push(atob(data.data));
|
||||
} else if (data.encoding === "URI") {
|
||||
bb.push(decodeURIComponent(data.data));
|
||||
} else if (data.encoding === "raw") {
|
||||
bb.push(data.data);
|
||||
}
|
||||
} else {
|
||||
if (typeof data !== "string") {
|
||||
data += ""; // convert unsupported types to strings
|
||||
}
|
||||
// decode UTF-16 to binary string
|
||||
bb.push(unescape(encodeURIComponent(data)));
|
||||
}
|
||||
};
|
||||
FBB_proto.getBlob = function(type) {
|
||||
if (!arguments.length) {
|
||||
type = null;
|
||||
}
|
||||
return new FakeBlob(this.data.join(""), type, "raw");
|
||||
};
|
||||
FBB_proto.toString = function() {
|
||||
return "[object BlobBuilder]";
|
||||
};
|
||||
FB_proto.slice = function(start, end, type) {
|
||||
var args = arguments.length;
|
||||
if (args < 3) {
|
||||
type = null;
|
||||
}
|
||||
return new FakeBlob(
|
||||
this.data.slice(start, args > 1 ? end : this.data.length)
|
||||
, type
|
||||
, this.encoding
|
||||
);
|
||||
};
|
||||
FB_proto.toString = function() {
|
||||
return "[object Blob]";
|
||||
};
|
||||
return FakeBlobBuilder;
|
||||
}(view));
|
||||
|
||||
return function Blob(blobParts, options) {
|
||||
var type = options ? (options.type || "") : "";
|
||||
var builder = new BlobBuilder();
|
||||
if (blobParts) {
|
||||
for (var i = 0, len = blobParts.length; i < len; i++) {
|
||||
builder.append(blobParts[i]);
|
||||
}
|
||||
}
|
||||
return builder.getBlob(type);
|
||||
};
|
||||
}(self));
|
||||
169
js/libs/bootstrap-fileupload.js
vendored
Normal file
169
js/libs/bootstrap-fileupload.js
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
/* ===========================================================
|
||||
* bootstrap-fileupload.js j2
|
||||
* http://jasny.github.com/bootstrap/javascript.html#fileupload
|
||||
* ===========================================================
|
||||
* Copyright 2012 Jasny BV, Netherlands.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License")
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ========================================================== */
|
||||
|
||||
!function ($) {
|
||||
|
||||
"use strict"; // jshint ;_
|
||||
|
||||
/* FILEUPLOAD PUBLIC CLASS DEFINITION
|
||||
* ================================= */
|
||||
|
||||
var Fileupload = function (element, options) {
|
||||
this.$element = $(element)
|
||||
this.type = this.$element.data('uploadtype') || (this.$element.find('.thumbnail').length > 0 ? "image" : "file")
|
||||
|
||||
this.$input = this.$element.find(':file')
|
||||
if (this.$input.length === 0) return
|
||||
|
||||
this.name = this.$input.attr('name') || options.name
|
||||
|
||||
this.$hidden = this.$element.find('input[type=hidden][name="'+this.name+'"]')
|
||||
if (this.$hidden.length === 0) {
|
||||
this.$hidden = $('<input type="hidden" />')
|
||||
this.$element.prepend(this.$hidden)
|
||||
}
|
||||
|
||||
this.$preview = this.$element.find('.fileupload-preview')
|
||||
var height = this.$preview.css('height')
|
||||
if (this.$preview.css('display') != 'inline' && height != '0px' && height != 'none') this.$preview.css('line-height', height)
|
||||
|
||||
this.original = {
|
||||
'exists': this.$element.hasClass('fileupload-exists'),
|
||||
'preview': this.$preview.html(),
|
||||
'hiddenVal': this.$hidden.val()
|
||||
}
|
||||
|
||||
this.$remove = this.$element.find('[data-dismiss="fileupload"]')
|
||||
|
||||
this.$element.find('[data-trigger="fileupload"]').on('click.fileupload', $.proxy(this.trigger, this))
|
||||
|
||||
this.listen()
|
||||
}
|
||||
|
||||
Fileupload.prototype = {
|
||||
|
||||
listen: function() {
|
||||
this.$input.on('change.fileupload', $.proxy(this.change, this))
|
||||
$(this.$input[0].form).on('reset.fileupload', $.proxy(this.reset, this))
|
||||
if (this.$remove) this.$remove.on('click.fileupload', $.proxy(this.clear, this))
|
||||
},
|
||||
|
||||
change: function(e, invoked) {
|
||||
if (invoked === 'clear') return
|
||||
|
||||
var file = e.target.files !== undefined ? e.target.files[0] : (e.target.value ? { name: e.target.value.replace(/^.+\\/, '') } : null)
|
||||
|
||||
if (!file) {
|
||||
this.clear()
|
||||
return
|
||||
}
|
||||
|
||||
this.$hidden.val('')
|
||||
this.$hidden.attr('name', '')
|
||||
this.$input.attr('name', this.name)
|
||||
|
||||
if (this.type === "image" && this.$preview.length > 0 && (typeof file.type !== "undefined" ? file.type.match('image.*') : file.name.match(/\.(gif|png|jpe?g)$/i)) && typeof FileReader !== "undefined") {
|
||||
var reader = new FileReader()
|
||||
var preview = this.$preview
|
||||
var element = this.$element
|
||||
|
||||
reader.onload = function(e) {
|
||||
preview.html('<img src="' + e.target.result + '" ' + (preview.css('max-height') != 'none' ? 'style="max-height: ' + preview.css('max-height') + ';"' : '') + ' />')
|
||||
element.addClass('fileupload-exists').removeClass('fileupload-new')
|
||||
}
|
||||
|
||||
reader.readAsDataURL(file)
|
||||
} else {
|
||||
this.$preview.text(file.name)
|
||||
this.$element.addClass('fileupload-exists').removeClass('fileupload-new')
|
||||
}
|
||||
},
|
||||
|
||||
clear: function(e) {
|
||||
this.$hidden.val('')
|
||||
this.$hidden.attr('name', this.name)
|
||||
this.$input.attr('name', '')
|
||||
|
||||
//ie8+ doesn't support changing the value of input with type=file so clone instead
|
||||
if (navigator.userAgent.match(/msie/i)){
|
||||
var inputClone = this.$input.clone(true);
|
||||
this.$input.after(inputClone);
|
||||
this.$input.remove();
|
||||
this.$input = inputClone;
|
||||
}else{
|
||||
this.$input.val('')
|
||||
}
|
||||
|
||||
this.$preview.html('')
|
||||
this.$element.addClass('fileupload-new').removeClass('fileupload-exists')
|
||||
|
||||
if (e) {
|
||||
this.$input.trigger('change', [ 'clear' ])
|
||||
e.preventDefault()
|
||||
}
|
||||
},
|
||||
|
||||
reset: function(e) {
|
||||
this.clear()
|
||||
|
||||
this.$hidden.val(this.original.hiddenVal)
|
||||
this.$preview.html(this.original.preview)
|
||||
|
||||
if (this.original.exists) this.$element.addClass('fileupload-exists').removeClass('fileupload-new')
|
||||
else this.$element.addClass('fileupload-new').removeClass('fileupload-exists')
|
||||
},
|
||||
|
||||
trigger: function(e) {
|
||||
this.$input.trigger('click')
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* FILEUPLOAD PLUGIN DEFINITION
|
||||
* =========================== */
|
||||
|
||||
$.fn.fileupload = function (options) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('fileupload')
|
||||
if (!data) $this.data('fileupload', (data = new Fileupload(this, options)))
|
||||
if (typeof options == 'string') data[options]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.fileupload.Constructor = Fileupload
|
||||
|
||||
|
||||
/* FILEUPLOAD DATA-API
|
||||
* ================== */
|
||||
|
||||
$(document).on('click.fileupload.data-api', '[data-provides="fileupload"]', function (e) {
|
||||
var $this = $(this)
|
||||
if ($this.data('fileupload')) return
|
||||
$this.fileupload($this.data())
|
||||
|
||||
var $target = $(e.target).closest('[data-dismiss="fileupload"],[data-trigger="fileupload"]');
|
||||
if ($target.length > 0) {
|
||||
$target.trigger('click.fileupload')
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
}(window.jQuery);
|
||||
95
js/libs/bootstrap-popover.js
vendored
Executable file
95
js/libs/bootstrap-popover.js
vendored
Executable file
@@ -0,0 +1,95 @@
|
||||
/* ===========================================================
|
||||
* bootstrap-popover.js v2.0.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#popovers
|
||||
* ===========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =========================================================== */
|
||||
|
||||
|
||||
!function( $ ) {
|
||||
|
||||
"use strict"
|
||||
|
||||
var Popover = function ( element, options ) {
|
||||
this.init('popover', element, options)
|
||||
}
|
||||
|
||||
/* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
|
||||
========================================== */
|
||||
|
||||
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
|
||||
|
||||
constructor: Popover
|
||||
|
||||
, setContent: function () {
|
||||
var $tip = this.tip()
|
||||
, title = this.getTitle()
|
||||
, content = this.getContent()
|
||||
|
||||
$tip.find('.popover-title')[ $.type(title) == 'object' ? 'append' : 'html' ](title)
|
||||
$tip.find('.popover-content > *')[ $.type(content) == 'object' ? 'append' : 'html' ](content)
|
||||
|
||||
$tip.removeClass('fade top bottom left right in')
|
||||
}
|
||||
|
||||
, hasContent: function () {
|
||||
return this.getTitle() || this.getContent()
|
||||
}
|
||||
|
||||
, getContent: function () {
|
||||
var content
|
||||
, $e = this.$element
|
||||
, o = this.options
|
||||
|
||||
content = $e.attr('data-content')
|
||||
|| (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
|
||||
|
||||
content = content.toString().replace(/(^\s*|\s*$)/, "")
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
, tip: function() {
|
||||
if (!this.$tip) {
|
||||
this.$tip = $(this.options.template)
|
||||
}
|
||||
return this.$tip
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
/* POPOVER PLUGIN DEFINITION
|
||||
* ======================= */
|
||||
|
||||
$.fn.popover = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('popover')
|
||||
, options = typeof option == 'object' && option
|
||||
if (!data) $this.data('popover', (data = new Popover(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.popover.Constructor = Popover
|
||||
|
||||
$.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
|
||||
placement: 'right'
|
||||
, content: ''
|
||||
, template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
|
||||
})
|
||||
|
||||
}( window.jQuery );
|
||||
270
js/libs/bootstrap-tooltip.js
vendored
Executable file
270
js/libs/bootstrap-tooltip.js
vendored
Executable file
@@ -0,0 +1,270 @@
|
||||
/* ===========================================================
|
||||
* bootstrap-tooltip.js v2.0.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#tooltips
|
||||
* Inspired by the original jQuery.tipsy by Jason Frame
|
||||
* ===========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ========================================================== */
|
||||
|
||||
!function( $ ) {
|
||||
|
||||
"use strict"
|
||||
|
||||
/* TOOLTIP PUBLIC CLASS DEFINITION
|
||||
* =============================== */
|
||||
|
||||
var Tooltip = function ( element, options ) {
|
||||
this.init('tooltip', element, options)
|
||||
}
|
||||
|
||||
Tooltip.prototype = {
|
||||
|
||||
constructor: Tooltip
|
||||
|
||||
, init: function ( type, element, options ) {
|
||||
var eventIn
|
||||
, eventOut
|
||||
|
||||
this.type = type
|
||||
this.$element = $(element)
|
||||
this.options = this.getOptions(options)
|
||||
this.enabled = true
|
||||
|
||||
if (this.options.trigger != 'manual') {
|
||||
eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
|
||||
eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
|
||||
this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
|
||||
this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
|
||||
}
|
||||
|
||||
this.options.selector ?
|
||||
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
|
||||
this.fixTitle()
|
||||
}
|
||||
|
||||
, getOptions: function ( options ) {
|
||||
options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
|
||||
|
||||
if (options.delay && typeof options.delay == 'number') {
|
||||
options.delay = {
|
||||
show: options.delay
|
||||
, hide: options.delay
|
||||
}
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
, enter: function ( e ) {
|
||||
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
|
||||
|
||||
if (!self.options.delay || !self.options.delay.show) {
|
||||
self.show()
|
||||
} else {
|
||||
self.hoverState = 'in'
|
||||
setTimeout(function() {
|
||||
if (self.hoverState == 'in') {
|
||||
self.show()
|
||||
}
|
||||
}, self.options.delay.show)
|
||||
}
|
||||
}
|
||||
|
||||
, leave: function ( e ) {
|
||||
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
|
||||
|
||||
if (!self.options.delay || !self.options.delay.hide) {
|
||||
self.hide()
|
||||
} else {
|
||||
self.hoverState = 'out'
|
||||
setTimeout(function() {
|
||||
if (self.hoverState == 'out') {
|
||||
self.hide()
|
||||
}
|
||||
}, self.options.delay.hide)
|
||||
}
|
||||
}
|
||||
|
||||
, show: function () {
|
||||
var $tip
|
||||
, inside
|
||||
, pos
|
||||
, actualWidth
|
||||
, actualHeight
|
||||
, placement
|
||||
, tp
|
||||
|
||||
if (this.hasContent() && this.enabled) {
|
||||
$tip = this.tip()
|
||||
this.setContent()
|
||||
|
||||
if (this.options.animation) {
|
||||
$tip.addClass('fade')
|
||||
}
|
||||
|
||||
placement = typeof this.options.placement == 'function' ?
|
||||
this.options.placement.call(this, $tip[0], this.$element[0]) :
|
||||
this.options.placement
|
||||
|
||||
inside = /in/.test(placement)
|
||||
|
||||
$tip
|
||||
.remove()
|
||||
.css({ top: 0, left: 0, display: 'block' })
|
||||
.appendTo(inside ? this.$element : document.body)
|
||||
|
||||
pos = this.getPosition(inside)
|
||||
|
||||
actualWidth = $tip[0].offsetWidth
|
||||
actualHeight = $tip[0].offsetHeight
|
||||
|
||||
switch (inside ? placement.split(' ')[1] : placement) {
|
||||
case 'bottom':
|
||||
tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
|
||||
break
|
||||
case 'top':
|
||||
tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
|
||||
break
|
||||
case 'left':
|
||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
|
||||
break
|
||||
case 'right':
|
||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
|
||||
break
|
||||
}
|
||||
|
||||
$tip
|
||||
.css(tp)
|
||||
.addClass(placement)
|
||||
.addClass('in')
|
||||
}
|
||||
}
|
||||
|
||||
, setContent: function () {
|
||||
var $tip = this.tip()
|
||||
$tip.find('.tooltip-inner').html(this.getTitle())
|
||||
$tip.removeClass('fade in top bottom left right')
|
||||
}
|
||||
|
||||
, hide: function () {
|
||||
var that = this
|
||||
, $tip = this.tip()
|
||||
|
||||
$tip.removeClass('in')
|
||||
|
||||
function removeWithAnimation() {
|
||||
var timeout = setTimeout(function () {
|
||||
$tip.off($.support.transition.end).remove()
|
||||
}, 500)
|
||||
|
||||
$tip.one($.support.transition.end, function () {
|
||||
clearTimeout(timeout)
|
||||
$tip.remove()
|
||||
})
|
||||
}
|
||||
|
||||
$.support.transition && this.$tip.hasClass('fade') ?
|
||||
removeWithAnimation() :
|
||||
$tip.remove()
|
||||
}
|
||||
|
||||
, fixTitle: function () {
|
||||
var $e = this.$element
|
||||
if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
|
||||
$e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
|
||||
}
|
||||
}
|
||||
|
||||
, hasContent: function () {
|
||||
return this.getTitle()
|
||||
}
|
||||
|
||||
, getPosition: function (inside) {
|
||||
return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
|
||||
width: this.$element[0].offsetWidth
|
||||
, height: this.$element[0].offsetHeight
|
||||
})
|
||||
}
|
||||
|
||||
, getTitle: function () {
|
||||
var title
|
||||
, $e = this.$element
|
||||
, o = this.options
|
||||
|
||||
title = $e.attr('data-original-title')
|
||||
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
|
||||
|
||||
title = title.toString().replace(/(^\s*|\s*$)/, "")
|
||||
|
||||
return title
|
||||
}
|
||||
|
||||
, tip: function () {
|
||||
return this.$tip = this.$tip || $(this.options.template)
|
||||
}
|
||||
|
||||
, validate: function () {
|
||||
if (!this.$element[0].parentNode) {
|
||||
this.hide()
|
||||
this.$element = null
|
||||
this.options = null
|
||||
}
|
||||
}
|
||||
|
||||
, enable: function () {
|
||||
this.enabled = true
|
||||
}
|
||||
|
||||
, disable: function () {
|
||||
this.enabled = false
|
||||
}
|
||||
|
||||
, toggleEnabled: function () {
|
||||
this.enabled = !this.enabled
|
||||
}
|
||||
|
||||
, toggle: function () {
|
||||
this[this.tip().hasClass('in') ? 'hide' : 'show']()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* TOOLTIP PLUGIN DEFINITION
|
||||
* ========================= */
|
||||
|
||||
$.fn.tooltip = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('tooltip')
|
||||
, options = typeof option == 'object' && option
|
||||
if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.tooltip.Constructor = Tooltip
|
||||
|
||||
$.fn.tooltip.defaults = {
|
||||
animation: true
|
||||
, delay: 0
|
||||
, selector: false
|
||||
, placement: 'top'
|
||||
, trigger: 'hover'
|
||||
, title: ''
|
||||
, template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
|
||||
}
|
||||
|
||||
}( window.jQuery );
|
||||
712
js/libs/core.js
Normal file
712
js/libs/core.js
Normal file
@@ -0,0 +1,712 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
/**
|
||||
* CryptoJS core components.
|
||||
*/
|
||||
var CryptoJS = CryptoJS || (function (Math, undefined) {
|
||||
/**
|
||||
* CryptoJS namespace.
|
||||
*/
|
||||
var C = {};
|
||||
|
||||
/**
|
||||
* Library namespace.
|
||||
*/
|
||||
var C_lib = C.lib = {};
|
||||
|
||||
/**
|
||||
* Base object for prototypal inheritance.
|
||||
*/
|
||||
var Base = C_lib.Base = (function () {
|
||||
function F() {}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Creates a new object that inherits from this object.
|
||||
*
|
||||
* @param {Object} overrides Properties to copy into the new object.
|
||||
*
|
||||
* @return {Object} The new object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var MyType = CryptoJS.lib.Base.extend({
|
||||
* field: 'value',
|
||||
*
|
||||
* method: function () {
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
extend: function (overrides) {
|
||||
// Spawn
|
||||
F.prototype = this;
|
||||
var subtype = new F();
|
||||
|
||||
// Augment
|
||||
if (overrides) {
|
||||
subtype.mixIn(overrides);
|
||||
}
|
||||
|
||||
// Create default initializer
|
||||
if (!subtype.hasOwnProperty('init')) {
|
||||
subtype.init = function () {
|
||||
subtype.$super.init.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
// Initializer's prototype is the subtype object
|
||||
subtype.init.prototype = subtype;
|
||||
|
||||
// Reference supertype
|
||||
subtype.$super = this;
|
||||
|
||||
return subtype;
|
||||
},
|
||||
|
||||
/**
|
||||
* Extends this object and runs the init method.
|
||||
* Arguments to create() will be passed to init().
|
||||
*
|
||||
* @return {Object} The new object.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var instance = MyType.create();
|
||||
*/
|
||||
create: function () {
|
||||
var instance = this.extend();
|
||||
instance.init.apply(instance, arguments);
|
||||
|
||||
return instance;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes a newly created object.
|
||||
* Override this method to add some logic when your objects are created.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var MyType = CryptoJS.lib.Base.extend({
|
||||
* init: function () {
|
||||
* // ...
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
init: function () {
|
||||
},
|
||||
|
||||
/**
|
||||
* Copies properties into this object.
|
||||
*
|
||||
* @param {Object} properties The properties to mix in.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* MyType.mixIn({
|
||||
* field: 'value'
|
||||
* });
|
||||
*/
|
||||
mixIn: function (properties) {
|
||||
for (var propertyName in properties) {
|
||||
if (properties.hasOwnProperty(propertyName)) {
|
||||
this[propertyName] = properties[propertyName];
|
||||
}
|
||||
}
|
||||
|
||||
// IE won't copy toString using the loop above
|
||||
if (properties.hasOwnProperty('toString')) {
|
||||
this.toString = properties.toString;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a copy of this object.
|
||||
*
|
||||
* @return {Object} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = instance.clone();
|
||||
*/
|
||||
clone: function () {
|
||||
return this.init.prototype.extend(this);
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
/**
|
||||
* An array of 32-bit words.
|
||||
*
|
||||
* @property {Array} words The array of 32-bit words.
|
||||
* @property {number} sigBytes The number of significant bytes in this word array.
|
||||
*/
|
||||
var WordArray = C_lib.WordArray = Base.extend({
|
||||
/**
|
||||
* Initializes a newly created word array.
|
||||
*
|
||||
* @param {Array} words (Optional) An array of 32-bit words.
|
||||
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.lib.WordArray.create();
|
||||
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
|
||||
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
|
||||
*/
|
||||
init: function (words, sigBytes) {
|
||||
words = this.words = words || [];
|
||||
|
||||
if (sigBytes != undefined) {
|
||||
this.sigBytes = sigBytes;
|
||||
} else {
|
||||
this.sigBytes = words.length * 4;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts this word array to a string.
|
||||
*
|
||||
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
|
||||
*
|
||||
* @return {string} The stringified word array.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var string = wordArray + '';
|
||||
* var string = wordArray.toString();
|
||||
* var string = wordArray.toString(CryptoJS.enc.Utf8);
|
||||
*/
|
||||
toString: function (encoder) {
|
||||
return (encoder || Hex).stringify(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Concatenates a word array to this word array.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array to append.
|
||||
*
|
||||
* @return {WordArray} This word array.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* wordArray1.concat(wordArray2);
|
||||
*/
|
||||
concat: function (wordArray) {
|
||||
// Shortcuts
|
||||
var thisWords = this.words;
|
||||
var thatWords = wordArray.words;
|
||||
var thisSigBytes = this.sigBytes;
|
||||
var thatSigBytes = wordArray.sigBytes;
|
||||
|
||||
// Clamp excess bits
|
||||
this.clamp();
|
||||
|
||||
// Concat
|
||||
if (thisSigBytes % 4) {
|
||||
// Copy one byte at a time
|
||||
for (var i = 0; i < thatSigBytes; i++) {
|
||||
var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
|
||||
}
|
||||
} else if (thatWords.length > 0xffff) {
|
||||
// Copy one word at a time
|
||||
for (var i = 0; i < thatSigBytes; i += 4) {
|
||||
thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
|
||||
}
|
||||
} else {
|
||||
// Copy all words at once
|
||||
thisWords.push.apply(thisWords, thatWords);
|
||||
}
|
||||
this.sigBytes += thatSigBytes;
|
||||
|
||||
// Chainable
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes insignificant bits.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* wordArray.clamp();
|
||||
*/
|
||||
clamp: function () {
|
||||
// Shortcuts
|
||||
var words = this.words;
|
||||
var sigBytes = this.sigBytes;
|
||||
|
||||
// Clamp
|
||||
words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
|
||||
words.length = Math.ceil(sigBytes / 4);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a copy of this word array.
|
||||
*
|
||||
* @return {WordArray} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = wordArray.clone();
|
||||
*/
|
||||
clone: function () {
|
||||
var clone = Base.clone.call(this);
|
||||
clone.words = this.words.slice(0);
|
||||
|
||||
return clone;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a word array filled with random bytes.
|
||||
*
|
||||
* @param {number} nBytes The number of random bytes to generate.
|
||||
*
|
||||
* @return {WordArray} The random word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.lib.WordArray.random(16);
|
||||
*/
|
||||
random: function (nBytes) {
|
||||
var words = [];
|
||||
for (var i = 0; i < nBytes; i += 4) {
|
||||
words.push((Math.random() * 0x100000000) | 0);
|
||||
}
|
||||
|
||||
return new WordArray.init(words, nBytes);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Encoder namespace.
|
||||
*/
|
||||
var C_enc = C.enc = {};
|
||||
|
||||
/**
|
||||
* Hex encoding strategy.
|
||||
*/
|
||||
var Hex = C_enc.Hex = {
|
||||
/**
|
||||
* Converts a word array to a hex string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The hex string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hexString = CryptoJS.enc.Hex.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
// Shortcuts
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
|
||||
// Convert
|
||||
var hexChars = [];
|
||||
for (var i = 0; i < sigBytes; i++) {
|
||||
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
hexChars.push((bite >>> 4).toString(16));
|
||||
hexChars.push((bite & 0x0f).toString(16));
|
||||
}
|
||||
|
||||
return hexChars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a hex string to a word array.
|
||||
*
|
||||
* @param {string} hexStr The hex string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Hex.parse(hexString);
|
||||
*/
|
||||
parse: function (hexStr) {
|
||||
// Shortcut
|
||||
var hexStrLength = hexStr.length;
|
||||
|
||||
// Convert
|
||||
var words = [];
|
||||
for (var i = 0; i < hexStrLength; i += 2) {
|
||||
words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
|
||||
}
|
||||
|
||||
return new WordArray.init(words, hexStrLength / 2);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Latin1 encoding strategy.
|
||||
*/
|
||||
var Latin1 = C_enc.Latin1 = {
|
||||
/**
|
||||
* Converts a word array to a Latin1 string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The Latin1 string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
// Shortcuts
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
|
||||
// Convert
|
||||
var latin1Chars = [];
|
||||
for (var i = 0; i < sigBytes; i++) {
|
||||
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
latin1Chars.push(String.fromCharCode(bite));
|
||||
}
|
||||
|
||||
return latin1Chars.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a Latin1 string to a word array.
|
||||
*
|
||||
* @param {string} latin1Str The Latin1 string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
|
||||
*/
|
||||
parse: function (latin1Str) {
|
||||
// Shortcut
|
||||
var latin1StrLength = latin1Str.length;
|
||||
|
||||
// Convert
|
||||
var words = [];
|
||||
for (var i = 0; i < latin1StrLength; i++) {
|
||||
words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
|
||||
}
|
||||
|
||||
return new WordArray.init(words, latin1StrLength);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* UTF-8 encoding strategy.
|
||||
*/
|
||||
var Utf8 = C_enc.Utf8 = {
|
||||
/**
|
||||
* Converts a word array to a UTF-8 string.
|
||||
*
|
||||
* @param {WordArray} wordArray The word array.
|
||||
*
|
||||
* @return {string} The UTF-8 string.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
|
||||
*/
|
||||
stringify: function (wordArray) {
|
||||
try {
|
||||
return decodeURIComponent(escape(Latin1.stringify(wordArray)));
|
||||
} catch (e) {
|
||||
throw new Error('Malformed UTF-8 data');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a UTF-8 string to a word array.
|
||||
*
|
||||
* @param {string} utf8Str The UTF-8 string.
|
||||
*
|
||||
* @return {WordArray} The word array.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
|
||||
*/
|
||||
parse: function (utf8Str) {
|
||||
return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract buffered block algorithm template.
|
||||
*
|
||||
* The property blockSize must be implemented in a concrete subtype.
|
||||
*
|
||||
* @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
|
||||
*/
|
||||
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
|
||||
/**
|
||||
* Resets this block algorithm's data buffer to its initial state.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* bufferedBlockAlgorithm.reset();
|
||||
*/
|
||||
reset: function () {
|
||||
// Initial values
|
||||
this._data = new WordArray.init();
|
||||
this._nDataBytes = 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds new data to this block algorithm's buffer.
|
||||
*
|
||||
* @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* bufferedBlockAlgorithm._append('data');
|
||||
* bufferedBlockAlgorithm._append(wordArray);
|
||||
*/
|
||||
_append: function (data) {
|
||||
// Convert string to WordArray, else assume WordArray already
|
||||
if (typeof data == 'string') {
|
||||
data = Utf8.parse(data);
|
||||
}
|
||||
|
||||
// Append
|
||||
this._data.concat(data);
|
||||
this._nDataBytes += data.sigBytes;
|
||||
},
|
||||
|
||||
/**
|
||||
* Processes available data blocks.
|
||||
*
|
||||
* This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
|
||||
*
|
||||
* @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
|
||||
*
|
||||
* @return {WordArray} The processed data.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var processedData = bufferedBlockAlgorithm._process();
|
||||
* var processedData = bufferedBlockAlgorithm._process(!!'flush');
|
||||
*/
|
||||
_process: function (doFlush) {
|
||||
// Shortcuts
|
||||
var data = this._data;
|
||||
var dataWords = data.words;
|
||||
var dataSigBytes = data.sigBytes;
|
||||
var blockSize = this.blockSize;
|
||||
var blockSizeBytes = blockSize * 4;
|
||||
|
||||
// Count blocks ready
|
||||
var nBlocksReady = dataSigBytes / blockSizeBytes;
|
||||
if (doFlush) {
|
||||
// Round up to include partial blocks
|
||||
nBlocksReady = Math.ceil(nBlocksReady);
|
||||
} else {
|
||||
// Round down to include only full blocks,
|
||||
// less the number of blocks that must remain in the buffer
|
||||
nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
|
||||
}
|
||||
|
||||
// Count words ready
|
||||
var nWordsReady = nBlocksReady * blockSize;
|
||||
|
||||
// Count bytes ready
|
||||
var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
|
||||
|
||||
// Process blocks
|
||||
if (nWordsReady) {
|
||||
for (var offset = 0; offset < nWordsReady; offset += blockSize) {
|
||||
// Perform concrete-algorithm logic
|
||||
this._doProcessBlock(dataWords, offset);
|
||||
}
|
||||
|
||||
// Remove processed words
|
||||
var processedWords = dataWords.splice(0, nWordsReady);
|
||||
data.sigBytes -= nBytesReady;
|
||||
}
|
||||
|
||||
// Return processed words
|
||||
return new WordArray.init(processedWords, nBytesReady);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a copy of this object.
|
||||
*
|
||||
* @return {Object} The clone.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var clone = bufferedBlockAlgorithm.clone();
|
||||
*/
|
||||
clone: function () {
|
||||
var clone = Base.clone.call(this);
|
||||
clone._data = this._data.clone();
|
||||
|
||||
return clone;
|
||||
},
|
||||
|
||||
_minBufferSize: 0
|
||||
});
|
||||
|
||||
/**
|
||||
* Abstract hasher template.
|
||||
*
|
||||
* @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
|
||||
*/
|
||||
var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
|
||||
/**
|
||||
* Configuration options.
|
||||
*/
|
||||
cfg: Base.extend(),
|
||||
|
||||
/**
|
||||
* Initializes a newly created hasher.
|
||||
*
|
||||
* @param {Object} cfg (Optional) The configuration options to use for this hash computation.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hasher = CryptoJS.algo.SHA256.create();
|
||||
*/
|
||||
init: function (cfg) {
|
||||
// Apply config defaults
|
||||
this.cfg = this.cfg.extend(cfg);
|
||||
|
||||
// Set initial values
|
||||
this.reset();
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets this hasher to its initial state.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* hasher.reset();
|
||||
*/
|
||||
reset: function () {
|
||||
// Reset data buffer
|
||||
BufferedBlockAlgorithm.reset.call(this);
|
||||
|
||||
// Perform concrete-hasher logic
|
||||
this._doReset();
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates this hasher with a message.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate The message to append.
|
||||
*
|
||||
* @return {Hasher} This hasher.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* hasher.update('message');
|
||||
* hasher.update(wordArray);
|
||||
*/
|
||||
update: function (messageUpdate) {
|
||||
// Append
|
||||
this._append(messageUpdate);
|
||||
|
||||
// Update the hash
|
||||
this._process();
|
||||
|
||||
// Chainable
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Finalizes the hash computation.
|
||||
* Note that the finalize operation is effectively a destructive, read-once operation.
|
||||
*
|
||||
* @param {WordArray|string} messageUpdate (Optional) A final message update.
|
||||
*
|
||||
* @return {WordArray} The hash.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var hash = hasher.finalize();
|
||||
* var hash = hasher.finalize('message');
|
||||
* var hash = hasher.finalize(wordArray);
|
||||
*/
|
||||
finalize: function (messageUpdate) {
|
||||
// Final message update
|
||||
if (messageUpdate) {
|
||||
this._append(messageUpdate);
|
||||
}
|
||||
|
||||
// Perform concrete-hasher logic
|
||||
var hash = this._doFinalize();
|
||||
|
||||
return hash;
|
||||
},
|
||||
|
||||
blockSize: 512/32,
|
||||
|
||||
/**
|
||||
* Creates a shortcut function to a hasher's object interface.
|
||||
*
|
||||
* @param {Hasher} hasher The hasher to create a helper for.
|
||||
*
|
||||
* @return {Function} The shortcut function.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
|
||||
*/
|
||||
_createHelper: function (hasher) {
|
||||
return function (message, cfg) {
|
||||
return new hasher.init(cfg).finalize(message);
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a shortcut function to the HMAC's object interface.
|
||||
*
|
||||
* @param {Hasher} hasher The hasher to use in this HMAC helper.
|
||||
*
|
||||
* @return {Function} The shortcut function.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
|
||||
*/
|
||||
_createHmacHelper: function (hasher) {
|
||||
return function (message, key) {
|
||||
return new C_algo.HMAC.init(hasher, key).finalize(message);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Algorithm namespace.
|
||||
*/
|
||||
var C_algo = C.algo = {};
|
||||
|
||||
return C;
|
||||
}(Math));
|
||||
8431
js/libs/ember-data.js
Normal file
8431
js/libs/ember-data.js
Normal file
File diff suppressed because it is too large
Load Diff
29735
js/libs/ember.js
Normal file
29735
js/libs/ember.js
Normal file
File diff suppressed because it is too large
Load Diff
229
js/libs/filesaver.js
Normal file
229
js/libs/filesaver.js
Normal file
@@ -0,0 +1,229 @@
|
||||
/* FileSaver.js
|
||||
* A saveAs() FileSaver implementation.
|
||||
* 2013-01-23
|
||||
*
|
||||
* By Eli Grey, http://eligrey.com
|
||||
* License: X11/MIT
|
||||
* See LICENSE.md
|
||||
*/
|
||||
|
||||
/*global self */
|
||||
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
|
||||
plusplus: true */
|
||||
|
||||
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
|
||||
|
||||
function bindEvent(el, eventName, eventHandler) {
|
||||
if (el.addEventListener){
|
||||
el.addEventListener(eventName, eventHandler, false);
|
||||
} else if (el.attachEvent){
|
||||
el.attachEvent('on'+eventName, eventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
var saveAs = saveAs
|
||||
|| (navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
|
||||
|| (function(view) {
|
||||
"use strict";
|
||||
var
|
||||
doc = view.document
|
||||
// only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
|
||||
, get_URL = function() {
|
||||
return view.URL || view.webkitURL || view;
|
||||
}
|
||||
, URL = view.URL || view.webkitURL || view
|
||||
//, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
|
||||
, save_link = doc.createElement('a')
|
||||
, can_use_save_link = !view.externalHost && "download" in save_link
|
||||
, click = function(node) {
|
||||
var event = doc.createEvent("MouseEvents");
|
||||
event.initMouseEvent(
|
||||
"click", true, false, view, 0, 0, 0, 0, 0
|
||||
, false, false, false, false, 0, null
|
||||
);
|
||||
node.dispatchEvent(event);
|
||||
}
|
||||
, webkit_req_fs = view.webkitRequestFileSystem
|
||||
, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
|
||||
, throw_outside = function (ex) {
|
||||
(view.setImmediate || view.setTimeout)(function() {
|
||||
throw ex;
|
||||
}, 0);
|
||||
}
|
||||
, force_saveable_type = "application/octet-stream"
|
||||
, fs_min_size = 0
|
||||
, deletion_queue = []
|
||||
, process_deletion_queue = function() {
|
||||
var i = deletion_queue.length;
|
||||
while (i--) {
|
||||
var file = deletion_queue[i];
|
||||
if (typeof file === "string") { // file is an object URL
|
||||
URL.revokeObjectURL(file);
|
||||
} else { // file is a File
|
||||
file.remove();
|
||||
}
|
||||
}
|
||||
deletion_queue.length = 0; // clear queue
|
||||
}
|
||||
, dispatch = function(filesaver, event_types, event) {
|
||||
event_types = [].concat(event_types);
|
||||
var i = event_types.length;
|
||||
while (i--) {
|
||||
var listener = filesaver["on" + event_types[i]];
|
||||
if (typeof listener === "function") {
|
||||
try {
|
||||
listener.call(filesaver, event || filesaver);
|
||||
} catch (ex) {
|
||||
throw_outside(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
, FileSaver = function(blob, name) {
|
||||
// First try a.download, then web filesystem, then object URLs
|
||||
var
|
||||
filesaver = this
|
||||
, type = blob.type
|
||||
, blob_changed = false
|
||||
, object_url
|
||||
, target_view
|
||||
, get_object_url = function() {
|
||||
var object_url = get_URL().createObjectURL(blob);
|
||||
deletion_queue.push(object_url);
|
||||
return object_url;
|
||||
}
|
||||
, dispatch_all = function() {
|
||||
dispatch(filesaver, "writestart progress write writeend".split(" "));
|
||||
}
|
||||
// on any filesys errors revert to saving with object URLs
|
||||
, fs_error = function() {
|
||||
// don't create more object URLs than needed
|
||||
if (blob_changed || !object_url) {
|
||||
object_url = get_object_url(blob);
|
||||
}
|
||||
if (target_view) {
|
||||
target_view.location.href = object_url;
|
||||
} else {
|
||||
window.open(object_url, "_blank");
|
||||
}
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch_all();
|
||||
}
|
||||
, abortable = function(func) {
|
||||
return function() {
|
||||
if (filesaver.readyState !== filesaver.DONE) {
|
||||
return func.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
}
|
||||
, create_if_not_found = {create: true, exclusive: false}
|
||||
, slice
|
||||
;
|
||||
filesaver.readyState = filesaver.INIT;
|
||||
if (!name) {
|
||||
name = "download";
|
||||
}
|
||||
if (can_use_save_link) {
|
||||
object_url = get_object_url(blob);
|
||||
save_link.href = object_url;
|
||||
save_link.download = name;
|
||||
click(save_link);
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch_all();
|
||||
return;
|
||||
}
|
||||
// Object and web filesystem URLs have a problem saving in Google Chrome when
|
||||
// viewed in a tab, so I force save with application/octet-stream
|
||||
// http://code.google.com/p/chromium/issues/detail?id=91158
|
||||
if (view.chrome && type && type !== force_saveable_type) {
|
||||
slice = blob.slice || blob.webkitSlice;
|
||||
blob = slice.call(blob, 0, blob.size, force_saveable_type);
|
||||
blob_changed = true;
|
||||
}
|
||||
// Since I can't be sure that the guessed media type will trigger a download
|
||||
// in WebKit, I append .download to the filename.
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=65440
|
||||
if (webkit_req_fs && name !== "download") {
|
||||
name += ".download";
|
||||
}
|
||||
if (type === force_saveable_type || webkit_req_fs) {
|
||||
target_view = view;
|
||||
}
|
||||
if (!req_fs) {
|
||||
fs_error();
|
||||
return;
|
||||
}
|
||||
fs_min_size += blob.size;
|
||||
req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
|
||||
fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
|
||||
var save = function() {
|
||||
dir.getFile(name, create_if_not_found, abortable(function(file) {
|
||||
file.createWriter(abortable(function(writer) {
|
||||
writer.onwriteend = function(event) {
|
||||
target_view.location.href = file.toURL();
|
||||
deletion_queue.push(file);
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch(filesaver, "writeend", event);
|
||||
};
|
||||
writer.onerror = function() {
|
||||
var error = writer.error;
|
||||
if (error.code !== error.ABORT_ERR) {
|
||||
fs_error();
|
||||
}
|
||||
};
|
||||
"writestart progress write abort".split(" ").forEach(function(event) {
|
||||
writer["on" + event] = filesaver["on" + event];
|
||||
});
|
||||
writer.write(blob);
|
||||
filesaver.abort = function() {
|
||||
writer.abort();
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
};
|
||||
filesaver.readyState = filesaver.WRITING;
|
||||
}), fs_error);
|
||||
}), fs_error);
|
||||
};
|
||||
dir.getFile(name, {create: false}, abortable(function(file) {
|
||||
// delete file if it already exists
|
||||
file.remove();
|
||||
save();
|
||||
}), abortable(function(ex) {
|
||||
if (ex.code === ex.NOT_FOUND_ERR) {
|
||||
save();
|
||||
} else {
|
||||
fs_error();
|
||||
}
|
||||
}));
|
||||
}), fs_error);
|
||||
}), fs_error);
|
||||
}
|
||||
, FS_proto = FileSaver.prototype
|
||||
, saveAs = function(blob, name) {
|
||||
return new FileSaver(blob, name);
|
||||
}
|
||||
;
|
||||
FS_proto.abort = function() {
|
||||
var filesaver = this;
|
||||
filesaver.readyState = filesaver.DONE;
|
||||
dispatch(filesaver, "abort");
|
||||
};
|
||||
FS_proto.readyState = FS_proto.INIT = 0;
|
||||
FS_proto.WRITING = 1;
|
||||
FS_proto.DONE = 2;
|
||||
|
||||
FS_proto.error =
|
||||
FS_proto.onwritestart =
|
||||
FS_proto.onprogress =
|
||||
FS_proto.onwrite =
|
||||
FS_proto.onabort =
|
||||
FS_proto.onerror =
|
||||
FS_proto.onwriteend =
|
||||
null;
|
||||
|
||||
//view.addEventListener("unload", process_deletion_queue, false);
|
||||
bindEvent(view, 'unload', process_deletion_queue);
|
||||
return saveAs;
|
||||
}(self));
|
||||
|
||||
if (typeof module !== 'undefined') module.exports = saveAs;
|
||||
|
||||
1
js/libs/globals.js
Normal file
1
js/libs/globals.js
Normal file
@@ -0,0 +1 @@
|
||||
var Slash = '/';
|
||||
2282
js/libs/handlebars.js
Normal file
2282
js/libs/handlebars.js
Normal file
File diff suppressed because it is too large
Load Diff
25
js/libs/hmac-sha512.js
Normal file
25
js/libs/hmac-sha512.js
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
var CryptoJS=CryptoJS||function(a,j){var c={},b=c.lib={},f=function(){},l=b.Base={extend:function(a){f.prototype=this;var d=new f;a&&d.mixIn(a);d.hasOwnProperty("init")||(d.init=function(){d.$super.init.apply(this,arguments)});d.init.prototype=d;d.$super=this;return d},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var d in a)a.hasOwnProperty(d)&&(this[d]=a[d]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
|
||||
u=b.WordArray=l.extend({init:function(a,d){a=this.words=a||[];this.sigBytes=d!=j?d:4*a.length},toString:function(a){return(a||m).stringify(this)},concat:function(a){var d=this.words,M=a.words,e=this.sigBytes;a=a.sigBytes;this.clamp();if(e%4)for(var b=0;b<a;b++)d[e+b>>>2]|=(M[b>>>2]>>>24-8*(b%4)&255)<<24-8*((e+b)%4);else if(65535<M.length)for(b=0;b<a;b+=4)d[e+b>>>2]=M[b>>>2];else d.push.apply(d,M);this.sigBytes+=a;return this},clamp:function(){var D=this.words,d=this.sigBytes;D[d>>>2]&=4294967295<<
|
||||
32-8*(d%4);D.length=a.ceil(d/4)},clone:function(){var a=l.clone.call(this);a.words=this.words.slice(0);return a},random:function(D){for(var d=[],b=0;b<D;b+=4)d.push(4294967296*a.random()|0);return new u.init(d,D)}}),k=c.enc={},m=k.Hex={stringify:function(a){var d=a.words;a=a.sigBytes;for(var b=[],e=0;e<a;e++){var c=d[e>>>2]>>>24-8*(e%4)&255;b.push((c>>>4).toString(16));b.push((c&15).toString(16))}return b.join("")},parse:function(a){for(var d=a.length,b=[],e=0;e<d;e+=2)b[e>>>3]|=parseInt(a.substr(e,
|
||||
2),16)<<24-4*(e%8);return new u.init(b,d/2)}},y=k.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var c=[],e=0;e<a;e++)c.push(String.fromCharCode(b[e>>>2]>>>24-8*(e%4)&255));return c.join("")},parse:function(a){for(var b=a.length,c=[],e=0;e<b;e++)c[e>>>2]|=(a.charCodeAt(e)&255)<<24-8*(e%4);return new u.init(c,b)}},z=k.Utf8={stringify:function(a){try{return decodeURIComponent(escape(y.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return y.parse(unescape(encodeURIComponent(a)))}},
|
||||
x=b.BufferedBlockAlgorithm=l.extend({reset:function(){this._data=new u.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=z.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(b){var d=this._data,c=d.words,e=d.sigBytes,l=this.blockSize,k=e/(4*l),k=b?a.ceil(k):a.max((k|0)-this._minBufferSize,0);b=k*l;e=a.min(4*b,e);if(b){for(var x=0;x<b;x+=l)this._doProcessBlock(c,x);x=c.splice(0,b);d.sigBytes-=e}return new u.init(x,e)},clone:function(){var a=l.clone.call(this);
|
||||
a._data=this._data.clone();return a},_minBufferSize:0});b.Hasher=x.extend({cfg:l.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){x.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,c){return(new a.init(c)).finalize(b)}},_createHmacHelper:function(a){return function(b,c){return(new ja.HMAC.init(a,
|
||||
c)).finalize(b)}}});var ja=c.algo={};return c}(Math);
|
||||
(function(a){var j=CryptoJS,c=j.lib,b=c.Base,f=c.WordArray,j=j.x64={};j.Word=b.extend({init:function(a,b){this.high=a;this.low=b}});j.WordArray=b.extend({init:function(b,c){b=this.words=b||[];this.sigBytes=c!=a?c:8*b.length},toX32:function(){for(var a=this.words,b=a.length,c=[],m=0;m<b;m++){var y=a[m];c.push(y.high);c.push(y.low)}return f.create(c,this.sigBytes)},clone:function(){for(var a=b.clone.call(this),c=a.words=this.words.slice(0),k=c.length,f=0;f<k;f++)c[f]=c[f].clone();return a}})})();
|
||||
(function(){function a(){return f.create.apply(f,arguments)}for(var j=CryptoJS,c=j.lib.Hasher,b=j.x64,f=b.Word,l=b.WordArray,b=j.algo,u=[a(1116352408,3609767458),a(1899447441,602891725),a(3049323471,3964484399),a(3921009573,2173295548),a(961987163,4081628472),a(1508970993,3053834265),a(2453635748,2937671579),a(2870763221,3664609560),a(3624381080,2734883394),a(310598401,1164996542),a(607225278,1323610764),a(1426881987,3590304994),a(1925078388,4068182383),a(2162078206,991336113),a(2614888103,633803317),
|
||||
a(3248222580,3479774868),a(3835390401,2666613458),a(4022224774,944711139),a(264347078,2341262773),a(604807628,2007800933),a(770255983,1495990901),a(1249150122,1856431235),a(1555081692,3175218132),a(1996064986,2198950837),a(2554220882,3999719339),a(2821834349,766784016),a(2952996808,2566594879),a(3210313671,3203337956),a(3336571891,1034457026),a(3584528711,2466948901),a(113926993,3758326383),a(338241895,168717936),a(666307205,1188179964),a(773529912,1546045734),a(1294757372,1522805485),a(1396182291,
|
||||
2643833823),a(1695183700,2343527390),a(1986661051,1014477480),a(2177026350,1206759142),a(2456956037,344077627),a(2730485921,1290863460),a(2820302411,3158454273),a(3259730800,3505952657),a(3345764771,106217008),a(3516065817,3606008344),a(3600352804,1432725776),a(4094571909,1467031594),a(275423344,851169720),a(430227734,3100823752),a(506948616,1363258195),a(659060556,3750685593),a(883997877,3785050280),a(958139571,3318307427),a(1322822218,3812723403),a(1537002063,2003034995),a(1747873779,3602036899),
|
||||
a(1955562222,1575990012),a(2024104815,1125592928),a(2227730452,2716904306),a(2361852424,442776044),a(2428436474,593698344),a(2756734187,3733110249),a(3204031479,2999351573),a(3329325298,3815920427),a(3391569614,3928383900),a(3515267271,566280711),a(3940187606,3454069534),a(4118630271,4000239992),a(116418474,1914138554),a(174292421,2731055270),a(289380356,3203993006),a(460393269,320620315),a(685471733,587496836),a(852142971,1086792851),a(1017036298,365543100),a(1126000580,2618297676),a(1288033470,
|
||||
3409855158),a(1501505948,4234509866),a(1607167915,987167468),a(1816402316,1246189591)],k=[],m=0;80>m;m++)k[m]=a();b=b.SHA512=c.extend({_doReset:function(){this._hash=new l.init([new f.init(1779033703,4089235720),new f.init(3144134277,2227873595),new f.init(1013904242,4271175723),new f.init(2773480762,1595750129),new f.init(1359893119,2917565137),new f.init(2600822924,725511199),new f.init(528734635,4215389547),new f.init(1541459225,327033209)])},_doProcessBlock:function(a,b){for(var c=this._hash.words,
|
||||
f=c[0],j=c[1],d=c[2],l=c[3],e=c[4],m=c[5],N=c[6],c=c[7],aa=f.high,O=f.low,ba=j.high,P=j.low,ca=d.high,Q=d.low,da=l.high,R=l.low,ea=e.high,S=e.low,fa=m.high,T=m.low,ga=N.high,U=N.low,ha=c.high,V=c.low,r=aa,n=O,G=ba,E=P,H=ca,F=Q,Y=da,I=R,s=ea,p=S,W=fa,J=T,X=ga,K=U,Z=ha,L=V,t=0;80>t;t++){var A=k[t];if(16>t)var q=A.high=a[b+2*t]|0,g=A.low=a[b+2*t+1]|0;else{var q=k[t-15],g=q.high,v=q.low,q=(g>>>1|v<<31)^(g>>>8|v<<24)^g>>>7,v=(v>>>1|g<<31)^(v>>>8|g<<24)^(v>>>7|g<<25),C=k[t-2],g=C.high,h=C.low,C=(g>>>19|
|
||||
h<<13)^(g<<3|h>>>29)^g>>>6,h=(h>>>19|g<<13)^(h<<3|g>>>29)^(h>>>6|g<<26),g=k[t-7],$=g.high,B=k[t-16],w=B.high,B=B.low,g=v+g.low,q=q+$+(g>>>0<v>>>0?1:0),g=g+h,q=q+C+(g>>>0<h>>>0?1:0),g=g+B,q=q+w+(g>>>0<B>>>0?1:0);A.high=q;A.low=g}var $=s&W^~s&X,B=p&J^~p&K,A=r&G^r&H^G&H,ka=n&E^n&F^E&F,v=(r>>>28|n<<4)^(r<<30|n>>>2)^(r<<25|n>>>7),C=(n>>>28|r<<4)^(n<<30|r>>>2)^(n<<25|r>>>7),h=u[t],la=h.high,ia=h.low,h=L+((p>>>14|s<<18)^(p>>>18|s<<14)^(p<<23|s>>>9)),w=Z+((s>>>14|p<<18)^(s>>>18|p<<14)^(s<<23|p>>>9))+(h>>>
|
||||
0<L>>>0?1:0),h=h+B,w=w+$+(h>>>0<B>>>0?1:0),h=h+ia,w=w+la+(h>>>0<ia>>>0?1:0),h=h+g,w=w+q+(h>>>0<g>>>0?1:0),g=C+ka,A=v+A+(g>>>0<C>>>0?1:0),Z=X,L=K,X=W,K=J,W=s,J=p,p=I+h|0,s=Y+w+(p>>>0<I>>>0?1:0)|0,Y=H,I=F,H=G,F=E,G=r,E=n,n=h+g|0,r=w+A+(n>>>0<h>>>0?1:0)|0}O=f.low=O+n;f.high=aa+r+(O>>>0<n>>>0?1:0);P=j.low=P+E;j.high=ba+G+(P>>>0<E>>>0?1:0);Q=d.low=Q+F;d.high=ca+H+(Q>>>0<F>>>0?1:0);R=l.low=R+I;l.high=da+Y+(R>>>0<I>>>0?1:0);S=e.low=S+p;e.high=ea+s+(S>>>0<p>>>0?1:0);T=m.low=T+J;m.high=fa+W+(T>>>0<J>>>0?1:
|
||||
0);U=N.low=U+K;N.high=ga+X+(U>>>0<K>>>0?1:0);V=c.low=V+L;c.high=ha+Z+(V>>>0<L>>>0?1:0)},_doFinalize:function(){var a=this._data,b=a.words,c=8*this._nDataBytes,f=8*a.sigBytes;b[f>>>5]|=128<<24-f%32;b[(f+128>>>10<<5)+30]=Math.floor(c/4294967296);b[(f+128>>>10<<5)+31]=c;a.sigBytes=4*b.length;this._process();return this._hash.toX32()},clone:function(){var a=c.clone.call(this);a._hash=this._hash.clone();return a},blockSize:32});j.SHA512=c._createHelper(b);j.HmacSHA512=c._createHmacHelper(b)})();
|
||||
(function(){var a=CryptoJS,j=a.enc.Utf8;a.algo.HMAC=a.lib.Base.extend({init:function(a,b){a=this._hasher=new a.init;"string"==typeof b&&(b=j.parse(b));var f=a.blockSize,l=4*f;b.sigBytes>l&&(b=a.finalize(b));b.clamp();for(var u=this._oKey=b.clone(),k=this._iKey=b.clone(),m=u.words,y=k.words,z=0;z<f;z++)m[z]^=1549556828,y[z]^=909522486;u.sigBytes=k.sigBytes=l;this.reset()},reset:function(){var a=this._hasher;a.reset();a.update(this._iKey)},update:function(a){this._hasher.update(a);return this},finalize:function(a){var b=
|
||||
this._hasher;a=b.finalize(a);b.reset();return b.finalize(this._oKey.clone().concat(a))}})})();
|
||||
9597
js/libs/jquery.js
vendored
Normal file
9597
js/libs/jquery.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
850
js/libs/json3.js
Executable file
850
js/libs/json3.js
Executable file
@@ -0,0 +1,850 @@
|
||||
/*! JSON v3.2.5 | http://bestiejs.github.io/json3 | Copyright 2012-2013, Kit Cambridge | http://kit.mit-license.org */
|
||||
;(function (window) {
|
||||
// Convenience aliases.
|
||||
var getClass = {}.toString, isProperty, forEach, undef;
|
||||
|
||||
// Detect the `define` function exposed by asynchronous module loaders. The
|
||||
// strict `define` check is necessary for compatibility with `r.js`.
|
||||
var isLoader = typeof define === "function" && define.amd, JSON3 = typeof exports == "object" && exports;
|
||||
|
||||
if (JSON3 || isLoader) {
|
||||
if (typeof JSON == "object" && JSON) {
|
||||
// Delegate to the native `stringify` and `parse` implementations in
|
||||
// asynchronous module loaders and CommonJS environments.
|
||||
if (JSON3) {
|
||||
JSON3.stringify = JSON.stringify;
|
||||
JSON3.parse = JSON.parse;
|
||||
} else {
|
||||
JSON3 = JSON;
|
||||
}
|
||||
} else if (isLoader) {
|
||||
JSON3 = window.JSON = {};
|
||||
}
|
||||
} else {
|
||||
// Export for web browsers and JavaScript engines.
|
||||
JSON3 = window.JSON || (window.JSON = {});
|
||||
}
|
||||
|
||||
// Test the `Date#getUTC*` methods. Based on work by @Yaffle.
|
||||
var isExtended = new Date(-3509827334573292);
|
||||
try {
|
||||
// The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical
|
||||
// results for certain dates in Opera >= 10.53.
|
||||
isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 &&
|
||||
// Safari < 2.0.2 stores the internal millisecond time value correctly,
|
||||
// but clips the values returned by the date methods to the range of
|
||||
// signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).
|
||||
isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;
|
||||
} catch (exception) {}
|
||||
|
||||
// Internal: Determines whether the native `JSON.stringify` and `parse`
|
||||
// implementations are spec-compliant. Based on work by Ken Snyder.
|
||||
function has(name) {
|
||||
if (name == "bug-string-char-index") {
|
||||
// IE <= 7 doesn't support accessing string characters using square
|
||||
// bracket notation. IE 8 only supports this for primitives.
|
||||
return "a"[0] != "a";
|
||||
}
|
||||
var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}', isAll = name == "json";
|
||||
if (isAll || name == "json-stringify" || name == "json-parse") {
|
||||
// Test `JSON.stringify`.
|
||||
if (name == "json-stringify" || isAll) {
|
||||
var stringify = JSON3.stringify, stringifySupported = typeof stringify == "function" && isExtended;
|
||||
if (stringifySupported) {
|
||||
// A test function object with a custom `toJSON` method.
|
||||
(value = function () {
|
||||
return 1;
|
||||
}).toJSON = value;
|
||||
try {
|
||||
stringifySupported =
|
||||
// Firefox 3.1b1 and b2 serialize string, number, and boolean
|
||||
// primitives as object literals.
|
||||
stringify(0) === "0" &&
|
||||
// FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object
|
||||
// literals.
|
||||
stringify(new Number()) === "0" &&
|
||||
stringify(new String()) == '""' &&
|
||||
// FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or
|
||||
// does not define a canonical JSON representation (this applies to
|
||||
// objects with `toJSON` properties as well, *unless* they are nested
|
||||
// within an object or array).
|
||||
stringify(getClass) === undef &&
|
||||
// IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and
|
||||
// FF 3.1b3 pass this test.
|
||||
stringify(undef) === undef &&
|
||||
// Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,
|
||||
// respectively, if the value is omitted entirely.
|
||||
stringify() === undef &&
|
||||
// FF 3.1b1, 2 throw an error if the given value is not a number,
|
||||
// string, array, object, Boolean, or `null` literal. This applies to
|
||||
// objects with custom `toJSON` methods as well, unless they are nested
|
||||
// inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`
|
||||
// methods entirely.
|
||||
stringify(value) === "1" &&
|
||||
stringify([value]) == "[1]" &&
|
||||
// Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of
|
||||
// `"[null]"`.
|
||||
stringify([undef]) == "[null]" &&
|
||||
// YUI 3.0.0b1 fails to serialize `null` literals.
|
||||
stringify(null) == "null" &&
|
||||
// FF 3.1b1, 2 halts serialization if an array contains a function:
|
||||
// `[1, true, getClass, 1]` serializes as "[1,true,],". These versions
|
||||
// of Firefox also allow trailing commas in JSON objects and arrays.
|
||||
// FF 3.1b3 elides non-JSON values from objects and arrays, unless they
|
||||
// define custom `toJSON` methods.
|
||||
stringify([undef, getClass, null]) == "[null,null,null]" &&
|
||||
// Simple serialization test. FF 3.1b1 uses Unicode escape sequences
|
||||
// where character escape codes are expected (e.g., `\b` => `\u0008`).
|
||||
stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized &&
|
||||
// FF 3.1b1 and b2 ignore the `filter` and `width` arguments.
|
||||
stringify(null, value) === "1" &&
|
||||
stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" &&
|
||||
// JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly
|
||||
// serialize extended years.
|
||||
stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' &&
|
||||
// The milliseconds are optional in ES 5, but required in 5.1.
|
||||
stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' &&
|
||||
// Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
|
||||
// four-digit years instead of six-digit years. Credits: @Yaffle.
|
||||
stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' &&
|
||||
// Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond
|
||||
// values less than 1000. Credits: @Yaffle.
|
||||
stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"';
|
||||
} catch (exception) {
|
||||
stringifySupported = false;
|
||||
}
|
||||
}
|
||||
if (!isAll) {
|
||||
return stringifySupported;
|
||||
}
|
||||
}
|
||||
// Test `JSON.parse`.
|
||||
if (name == "json-parse" || isAll) {
|
||||
var parse = JSON3.parse;
|
||||
if (typeof parse == "function") {
|
||||
try {
|
||||
// FF 3.1b1, b2 will throw an exception if a bare literal is provided.
|
||||
// Conforming implementations should also coerce the initial argument to
|
||||
// a string prior to parsing.
|
||||
if (parse("0") === 0 && !parse(false)) {
|
||||
// Simple parsing test.
|
||||
value = parse(serialized);
|
||||
var parseSupported = value["a"].length == 5 && value["a"][0] === 1;
|
||||
if (parseSupported) {
|
||||
try {
|
||||
// Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.
|
||||
parseSupported = !parse('"\t"');
|
||||
} catch (exception) {}
|
||||
if (parseSupported) {
|
||||
try {
|
||||
// FF 4.0 and 4.0.1 allow leading `+` signs, and leading and
|
||||
// trailing decimal points. FF 4.0, 4.0.1, and IE 9-10 also
|
||||
// allow certain octal literals.
|
||||
parseSupported = parse("01") !== 1;
|
||||
} catch (exception) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (exception) {
|
||||
parseSupported = false;
|
||||
}
|
||||
}
|
||||
if (!isAll) {
|
||||
return parseSupported;
|
||||
}
|
||||
}
|
||||
return stringifySupported && parseSupported;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has("json")) {
|
||||
// Common `[[Class]]` name aliases.
|
||||
var functionClass = "[object Function]";
|
||||
var dateClass = "[object Date]";
|
||||
var numberClass = "[object Number]";
|
||||
var stringClass = "[object String]";
|
||||
var arrayClass = "[object Array]";
|
||||
var booleanClass = "[object Boolean]";
|
||||
|
||||
// Detect incomplete support for accessing string characters by index.
|
||||
var charIndexBuggy = has("bug-string-char-index");
|
||||
|
||||
// Define additional utility methods if the `Date` methods are buggy.
|
||||
if (!isExtended) {
|
||||
var floor = Math.floor;
|
||||
// A mapping between the months of the year and the number of days between
|
||||
// January 1st and the first of the respective month.
|
||||
var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
|
||||
// Internal: Calculates the number of days between the Unix epoch and the
|
||||
// first day of the given month.
|
||||
var getDay = function (year, month) {
|
||||
return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
|
||||
};
|
||||
}
|
||||
|
||||
// Internal: Determines if a property is a direct property of the given
|
||||
// object. Delegates to the native `Object#hasOwnProperty` method.
|
||||
if (!(isProperty = {}.hasOwnProperty)) {
|
||||
isProperty = function (property) {
|
||||
var members = {}, constructor;
|
||||
if ((members.__proto__ = null, members.__proto__ = {
|
||||
// The *proto* property cannot be set multiple times in recent
|
||||
// versions of Firefox and SeaMonkey.
|
||||
"toString": 1
|
||||
}, members).toString != getClass) {
|
||||
// Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
|
||||
// supports the mutable *proto* property.
|
||||
isProperty = function (property) {
|
||||
// Capture and break the object's prototype chain (see section 8.6.2
|
||||
// of the ES 5.1 spec). The parenthesized expression prevents an
|
||||
// unsafe transformation by the Closure Compiler.
|
||||
var original = this.__proto__, result = property in (this.__proto__ = null, this);
|
||||
// Restore the original prototype chain.
|
||||
this.__proto__ = original;
|
||||
return result;
|
||||
};
|
||||
} else {
|
||||
// Capture a reference to the top-level `Object` constructor.
|
||||
constructor = members.constructor;
|
||||
// Use the `constructor` property to simulate `Object#hasOwnProperty` in
|
||||
// other environments.
|
||||
isProperty = function (property) {
|
||||
var parent = (this.constructor || constructor).prototype;
|
||||
return property in this && !(property in parent && this[property] === parent[property]);
|
||||
};
|
||||
}
|
||||
members = null;
|
||||
return isProperty.call(this, property);
|
||||
};
|
||||
}
|
||||
|
||||
// Internal: A set of primitive types used by `isHostType`.
|
||||
var PrimitiveTypes = {
|
||||
'boolean': 1,
|
||||
'number': 1,
|
||||
'string': 1,
|
||||
'undefined': 1
|
||||
};
|
||||
|
||||
// Internal: Determines if the given object `property` value is a
|
||||
// non-primitive.
|
||||
var isHostType = function (object, property) {
|
||||
var type = typeof object[property];
|
||||
return type == 'object' ? !!object[property] : !PrimitiveTypes[type];
|
||||
};
|
||||
|
||||
// Internal: Normalizes the `for...in` iteration algorithm across
|
||||
// environments. Each enumerated key is yielded to a `callback` function.
|
||||
forEach = function (object, callback) {
|
||||
var size = 0, Properties, members, property, forEach;
|
||||
|
||||
// Tests for bugs in the current environment's `for...in` algorithm. The
|
||||
// `valueOf` property inherits the non-enumerable flag from
|
||||
// `Object.prototype` in older versions of IE, Netscape, and Mozilla.
|
||||
(Properties = function () {
|
||||
this.valueOf = 0;
|
||||
}).prototype.valueOf = 0;
|
||||
|
||||
// Iterate over a new instance of the `Properties` class.
|
||||
members = new Properties();
|
||||
for (property in members) {
|
||||
// Ignore all properties inherited from `Object.prototype`.
|
||||
if (isProperty.call(members, property)) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
Properties = members = null;
|
||||
|
||||
// Normalize the iteration algorithm.
|
||||
if (!size) {
|
||||
// A list of non-enumerable properties inherited from `Object.prototype`.
|
||||
members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"];
|
||||
// IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable
|
||||
// properties.
|
||||
forEach = function (object, callback) {
|
||||
var isFunction = getClass.call(object) == functionClass, property, length;
|
||||
var hasProperty = !isFunction && typeof object.constructor != 'function' && isHostType(object, 'hasOwnProperty') ? object.hasOwnProperty : isProperty;
|
||||
for (property in object) {
|
||||
// Gecko <= 1.0 enumerates the `prototype` property of functions under
|
||||
// certain conditions; IE does not.
|
||||
if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) {
|
||||
callback(property);
|
||||
}
|
||||
}
|
||||
// Manually invoke the callback for each non-enumerable property.
|
||||
for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property));
|
||||
};
|
||||
} else if (size == 2) {
|
||||
// Safari <= 2.0.4 enumerates shadowed properties twice.
|
||||
forEach = function (object, callback) {
|
||||
// Create a set of iterated properties.
|
||||
var members = {}, isFunction = getClass.call(object) == functionClass, property;
|
||||
for (property in object) {
|
||||
// Store each property name to prevent double enumeration. The
|
||||
// `prototype` property of functions is not enumerated due to cross-
|
||||
// environment inconsistencies.
|
||||
if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {
|
||||
callback(property);
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// No bugs detected; use the standard `for...in` algorithm.
|
||||
forEach = function (object, callback) {
|
||||
var isFunction = getClass.call(object) == functionClass, property, isConstructor;
|
||||
for (property in object) {
|
||||
if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) {
|
||||
callback(property);
|
||||
}
|
||||
}
|
||||
// Manually invoke the callback for the `constructor` property due to
|
||||
// cross-environment inconsistencies.
|
||||
if (isConstructor || isProperty.call(object, (property = "constructor"))) {
|
||||
callback(property);
|
||||
}
|
||||
};
|
||||
}
|
||||
return forEach(object, callback);
|
||||
};
|
||||
|
||||
// Public: Serializes a JavaScript `value` as a JSON string. The optional
|
||||
// `filter` argument may specify either a function that alters how object and
|
||||
// array members are serialized, or an array of strings and numbers that
|
||||
// indicates which properties should be serialized. The optional `width`
|
||||
// argument may be either a string or number that specifies the indentation
|
||||
// level of the output.
|
||||
if (!has("json-stringify")) {
|
||||
// Internal: A map of control characters and their escaped equivalents.
|
||||
var Escapes = {
|
||||
92: "\\\\",
|
||||
34: '\\"',
|
||||
8: "\\b",
|
||||
12: "\\f",
|
||||
10: "\\n",
|
||||
13: "\\r",
|
||||
9: "\\t"
|
||||
};
|
||||
|
||||
// Internal: Converts `value` into a zero-padded string such that its
|
||||
// length is at least equal to `width`. The `width` must be <= 6.
|
||||
var leadingZeroes = "000000";
|
||||
var toPaddedString = function (width, value) {
|
||||
// The `|| 0` expression is necessary to work around a bug in
|
||||
// Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
|
||||
return (leadingZeroes + (value || 0)).slice(-width);
|
||||
};
|
||||
|
||||
// Internal: Double-quotes a string `value`, replacing all ASCII control
|
||||
// characters (characters with code unit values between 0 and 31) with
|
||||
// their escaped equivalents. This is an implementation of the
|
||||
// `Quote(value)` operation defined in ES 5.1 section 15.12.3.
|
||||
var unicodePrefix = "\\u00";
|
||||
var quote = function (value) {
|
||||
var result = '"', index = 0, length = value.length, isLarge = length > 10 && charIndexBuggy, symbols;
|
||||
if (isLarge) {
|
||||
symbols = value.split("");
|
||||
}
|
||||
for (; index < length; index++) {
|
||||
var charCode = value.charCodeAt(index);
|
||||
// If the character is a control character, append its Unicode or
|
||||
// shorthand escape sequence; otherwise, append the character as-is.
|
||||
switch (charCode) {
|
||||
case 8: case 9: case 10: case 12: case 13: case 34: case 92:
|
||||
result += Escapes[charCode];
|
||||
break;
|
||||
default:
|
||||
if (charCode < 32) {
|
||||
result += unicodePrefix + toPaddedString(2, charCode.toString(16));
|
||||
break;
|
||||
}
|
||||
result += isLarge ? symbols[index] : charIndexBuggy ? value.charAt(index) : value[index];
|
||||
}
|
||||
}
|
||||
return result + '"';
|
||||
};
|
||||
|
||||
// Internal: Recursively serializes an object. Implements the
|
||||
// `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
|
||||
var serialize = function (property, object, callback, properties, whitespace, indentation, stack) {
|
||||
var value = object[property], className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, hasMembers, result;
|
||||
try {
|
||||
// Necessary for host object support.
|
||||
value = object[property];
|
||||
} catch (exception) {}
|
||||
if (typeof value == "object" && value) {
|
||||
className = getClass.call(value);
|
||||
if (className == dateClass && !isProperty.call(value, "toJSON")) {
|
||||
if (value > -1 / 0 && value < 1 / 0) {
|
||||
// Dates are serialized according to the `Date#toJSON` method
|
||||
// specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
|
||||
// for the ISO 8601 date time string format.
|
||||
if (getDay) {
|
||||
// Manually compute the year, month, date, hours, minutes,
|
||||
// seconds, and milliseconds if the `getUTC*` methods are
|
||||
// buggy. Adapted from @Yaffle's `date-shim` project.
|
||||
date = floor(value / 864e5);
|
||||
for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);
|
||||
for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);
|
||||
date = 1 + date - getDay(year, month);
|
||||
// The `time` value specifies the time within the day (see ES
|
||||
// 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used
|
||||
// to compute `A modulo B`, as the `%` operator does not
|
||||
// correspond to the `modulo` operation for negative numbers.
|
||||
time = (value % 864e5 + 864e5) % 864e5;
|
||||
// The hours, minutes, seconds, and milliseconds are obtained by
|
||||
// decomposing the time within the day. See section 15.9.1.10.
|
||||
hours = floor(time / 36e5) % 24;
|
||||
minutes = floor(time / 6e4) % 60;
|
||||
seconds = floor(time / 1e3) % 60;
|
||||
milliseconds = time % 1e3;
|
||||
} else {
|
||||
year = value.getUTCFullYear();
|
||||
month = value.getUTCMonth();
|
||||
date = value.getUTCDate();
|
||||
hours = value.getUTCHours();
|
||||
minutes = value.getUTCMinutes();
|
||||
seconds = value.getUTCSeconds();
|
||||
milliseconds = value.getUTCMilliseconds();
|
||||
}
|
||||
// Serialize extended years correctly.
|
||||
value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
|
||||
"-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
|
||||
// Months, dates, hours, minutes, and seconds should have two
|
||||
// digits; milliseconds should have three.
|
||||
"T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) +
|
||||
// Milliseconds are optional in ES 5.0, but required in 5.1.
|
||||
"." + toPaddedString(3, milliseconds) + "Z";
|
||||
} else {
|
||||
value = null;
|
||||
}
|
||||
} else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) {
|
||||
// Prototype <= 1.6.1 adds non-standard `toJSON` methods to the
|
||||
// `Number`, `String`, `Date`, and `Array` prototypes. JSON 3
|
||||
// ignores all `toJSON` methods on these objects unless they are
|
||||
// defined directly on an instance.
|
||||
value = value.toJSON(property);
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
// If a replacement function was provided, call it to obtain the value
|
||||
// for serialization.
|
||||
value = callback.call(object, property, value);
|
||||
}
|
||||
if (value === null) {
|
||||
return "null";
|
||||
}
|
||||
className = getClass.call(value);
|
||||
if (className == booleanClass) {
|
||||
// Booleans are represented literally.
|
||||
return "" + value;
|
||||
} else if (className == numberClass) {
|
||||
// JSON numbers must be finite. `Infinity` and `NaN` are serialized as
|
||||
// `"null"`.
|
||||
return value > -1 / 0 && value < 1 / 0 ? "" + value : "null";
|
||||
} else if (className == stringClass) {
|
||||
// Strings are double-quoted and escaped.
|
||||
return quote("" + value);
|
||||
}
|
||||
// Recursively serialize objects and arrays.
|
||||
if (typeof value == "object") {
|
||||
// Check for cyclic structures. This is a linear search; performance
|
||||
// is inversely proportional to the number of unique nested objects.
|
||||
for (length = stack.length; length--;) {
|
||||
if (stack[length] === value) {
|
||||
// Cyclic structures cannot be serialized by `JSON.stringify`.
|
||||
throw TypeError();
|
||||
}
|
||||
}
|
||||
// Add the object to the stack of traversed objects.
|
||||
stack.push(value);
|
||||
results = [];
|
||||
// Save the current indentation level and indent one additional level.
|
||||
prefix = indentation;
|
||||
indentation += whitespace;
|
||||
if (className == arrayClass) {
|
||||
// Recursively serialize array elements.
|
||||
for (index = 0, length = value.length; index < length; hasMembers || (hasMembers = true), index++) {
|
||||
element = serialize(index, value, callback, properties, whitespace, indentation, stack);
|
||||
results.push(element === undef ? "null" : element);
|
||||
}
|
||||
result = hasMembers ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]";
|
||||
} else {
|
||||
// Recursively serialize object members. Members are selected from
|
||||
// either a user-specified list of property names, or the object
|
||||
// itself.
|
||||
forEach(properties || value, function (property) {
|
||||
var element = serialize(property, value, callback, properties, whitespace, indentation, stack);
|
||||
if (element !== undef) {
|
||||
// According to ES 5.1 section 15.12.3: "If `gap` {whitespace}
|
||||
// is not the empty string, let `member` {quote(property) + ":"}
|
||||
// be the concatenation of `member` and the `space` character."
|
||||
// The "`space` character" refers to the literal space
|
||||
// character, not the `space` {width} argument provided to
|
||||
// `JSON.stringify`.
|
||||
results.push(quote(property) + ":" + (whitespace ? " " : "") + element);
|
||||
}
|
||||
hasMembers || (hasMembers = true);
|
||||
});
|
||||
result = hasMembers ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}";
|
||||
}
|
||||
// Remove the object from the traversed object stack.
|
||||
stack.pop();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
|
||||
JSON3.stringify = function (source, filter, width) {
|
||||
var whitespace, callback, properties;
|
||||
if (typeof filter == "function" || typeof filter == "object" && filter) {
|
||||
if (getClass.call(filter) == functionClass) {
|
||||
callback = filter;
|
||||
} else if (getClass.call(filter) == arrayClass) {
|
||||
// Convert the property names array into a makeshift set.
|
||||
properties = {};
|
||||
for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((getClass.call(value) == stringClass || getClass.call(value) == numberClass) && (properties[value] = 1)));
|
||||
}
|
||||
}
|
||||
if (width) {
|
||||
if (getClass.call(width) == numberClass) {
|
||||
// Convert the `width` to an integer and create a string containing
|
||||
// `width` number of space characters.
|
||||
if ((width -= width % 1) > 0) {
|
||||
for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
|
||||
}
|
||||
} else if (getClass.call(width) == stringClass) {
|
||||
whitespace = width.length <= 10 ? width : width.slice(0, 10);
|
||||
}
|
||||
}
|
||||
// Opera <= 7.54u2 discards the values associated with empty string keys
|
||||
// (`""`) only if they are used directly within an object member list
|
||||
// (e.g., `!("" in { "": 1})`).
|
||||
return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []);
|
||||
};
|
||||
}
|
||||
|
||||
// Public: Parses a JSON source string.
|
||||
if (!has("json-parse")) {
|
||||
var fromCharCode = String.fromCharCode;
|
||||
|
||||
// Internal: A map of escaped control characters and their unescaped
|
||||
// equivalents.
|
||||
var Unescapes = {
|
||||
92: "\\",
|
||||
34: '"',
|
||||
47: "/",
|
||||
98: "\b",
|
||||
116: "\t",
|
||||
110: "\n",
|
||||
102: "\f",
|
||||
114: "\r"
|
||||
};
|
||||
|
||||
// Internal: Stores the parser state.
|
||||
var Index, Source;
|
||||
|
||||
// Internal: Resets the parser state and throws a `SyntaxError`.
|
||||
var abort = function() {
|
||||
Index = Source = null;
|
||||
throw SyntaxError();
|
||||
};
|
||||
|
||||
// Internal: Returns the next token, or `"$"` if the parser has reached
|
||||
// the end of the source string. A token may be a string, number, `null`
|
||||
// literal, or Boolean literal.
|
||||
var lex = function () {
|
||||
var source = Source, length = source.length, value, begin, position, isSigned, charCode;
|
||||
while (Index < length) {
|
||||
charCode = source.charCodeAt(Index);
|
||||
switch (charCode) {
|
||||
case 9: case 10: case 13: case 32:
|
||||
// Skip whitespace tokens, including tabs, carriage returns, line
|
||||
// feeds, and space characters.
|
||||
Index++;
|
||||
break;
|
||||
case 123: case 125: case 91: case 93: case 58: case 44:
|
||||
// Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at
|
||||
// the current position.
|
||||
value = charIndexBuggy ? source.charAt(Index) : source[Index];
|
||||
Index++;
|
||||
return value;
|
||||
case 34:
|
||||
// `"` delimits a JSON string; advance to the next character and
|
||||
// begin parsing the string. String tokens are prefixed with the
|
||||
// sentinel `@` character to distinguish them from punctuators and
|
||||
// end-of-string tokens.
|
||||
for (value = "@", Index++; Index < length;) {
|
||||
charCode = source.charCodeAt(Index);
|
||||
if (charCode < 32) {
|
||||
// Unescaped ASCII control characters (those with a code unit
|
||||
// less than the space character) are not permitted.
|
||||
abort();
|
||||
} else if (charCode == 92) {
|
||||
// A reverse solidus (`\`) marks the beginning of an escaped
|
||||
// control character (including `"`, `\`, and `/`) or Unicode
|
||||
// escape sequence.
|
||||
charCode = source.charCodeAt(++Index);
|
||||
switch (charCode) {
|
||||
case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114:
|
||||
// Revive escaped control characters.
|
||||
value += Unescapes[charCode];
|
||||
Index++;
|
||||
break;
|
||||
case 117:
|
||||
// `\u` marks the beginning of a Unicode escape sequence.
|
||||
// Advance to the first character and validate the
|
||||
// four-digit code point.
|
||||
begin = ++Index;
|
||||
for (position = Index + 4; Index < position; Index++) {
|
||||
charCode = source.charCodeAt(Index);
|
||||
// A valid sequence comprises four hexdigits (case-
|
||||
// insensitive) that form a single hexadecimal value.
|
||||
if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) {
|
||||
// Invalid Unicode escape sequence.
|
||||
abort();
|
||||
}
|
||||
}
|
||||
// Revive the escaped character.
|
||||
value += fromCharCode("0x" + source.slice(begin, Index));
|
||||
break;
|
||||
default:
|
||||
// Invalid escape sequence.
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
if (charCode == 34) {
|
||||
// An unescaped double-quote character marks the end of the
|
||||
// string.
|
||||
break;
|
||||
}
|
||||
charCode = source.charCodeAt(Index);
|
||||
begin = Index;
|
||||
// Optimize for the common case where a string is valid.
|
||||
while (charCode >= 32 && charCode != 92 && charCode != 34) {
|
||||
charCode = source.charCodeAt(++Index);
|
||||
}
|
||||
// Append the string as-is.
|
||||
value += source.slice(begin, Index);
|
||||
}
|
||||
}
|
||||
if (source.charCodeAt(Index) == 34) {
|
||||
// Advance to the next character and return the revived string.
|
||||
Index++;
|
||||
return value;
|
||||
}
|
||||
// Unterminated string.
|
||||
abort();
|
||||
default:
|
||||
// Parse numbers and literals.
|
||||
begin = Index;
|
||||
// Advance past the negative sign, if one is specified.
|
||||
if (charCode == 45) {
|
||||
isSigned = true;
|
||||
charCode = source.charCodeAt(++Index);
|
||||
}
|
||||
// Parse an integer or floating-point value.
|
||||
if (charCode >= 48 && charCode <= 57) {
|
||||
// Leading zeroes are interpreted as octal literals.
|
||||
if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) {
|
||||
// Illegal octal literal.
|
||||
abort();
|
||||
}
|
||||
isSigned = false;
|
||||
// Parse the integer component.
|
||||
for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++);
|
||||
// Floats cannot contain a leading decimal point; however, this
|
||||
// case is already accounted for by the parser.
|
||||
if (source.charCodeAt(Index) == 46) {
|
||||
position = ++Index;
|
||||
// Parse the decimal component.
|
||||
for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
|
||||
if (position == Index) {
|
||||
// Illegal trailing decimal.
|
||||
abort();
|
||||
}
|
||||
Index = position;
|
||||
}
|
||||
// Parse exponents. The `e` denoting the exponent is
|
||||
// case-insensitive.
|
||||
charCode = source.charCodeAt(Index);
|
||||
if (charCode == 101 || charCode == 69) {
|
||||
charCode = source.charCodeAt(++Index);
|
||||
// Skip past the sign following the exponent, if one is
|
||||
// specified.
|
||||
if (charCode == 43 || charCode == 45) {
|
||||
Index++;
|
||||
}
|
||||
// Parse the exponential component.
|
||||
for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
|
||||
if (position == Index) {
|
||||
// Illegal empty exponent.
|
||||
abort();
|
||||
}
|
||||
Index = position;
|
||||
}
|
||||
// Coerce the parsed value to a JavaScript number.
|
||||
return +source.slice(begin, Index);
|
||||
}
|
||||
// A negative sign may only precede numbers.
|
||||
if (isSigned) {
|
||||
abort();
|
||||
}
|
||||
// `true`, `false`, and `null` literals.
|
||||
if (source.slice(Index, Index + 4) == "true") {
|
||||
Index += 4;
|
||||
return true;
|
||||
} else if (source.slice(Index, Index + 5) == "false") {
|
||||
Index += 5;
|
||||
return false;
|
||||
} else if (source.slice(Index, Index + 4) == "null") {
|
||||
Index += 4;
|
||||
return null;
|
||||
}
|
||||
// Unrecognized token.
|
||||
abort();
|
||||
}
|
||||
}
|
||||
// Return the sentinel `$` character if the parser has reached the end
|
||||
// of the source string.
|
||||
return "$";
|
||||
};
|
||||
|
||||
// Internal: Parses a JSON `value` token.
|
||||
var get = function (value) {
|
||||
var results, hasMembers;
|
||||
if (value == "$") {
|
||||
// Unexpected end of input.
|
||||
abort();
|
||||
}
|
||||
if (typeof value == "string") {
|
||||
if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") {
|
||||
// Remove the sentinel `@` character.
|
||||
return value.slice(1);
|
||||
}
|
||||
// Parse object and array literals.
|
||||
if (value == "[") {
|
||||
// Parses a JSON array, returning a new JavaScript array.
|
||||
results = [];
|
||||
for (;; hasMembers || (hasMembers = true)) {
|
||||
value = lex();
|
||||
// A closing square bracket marks the end of the array literal.
|
||||
if (value == "]") {
|
||||
break;
|
||||
}
|
||||
// If the array literal contains elements, the current token
|
||||
// should be a comma separating the previous element from the
|
||||
// next.
|
||||
if (hasMembers) {
|
||||
if (value == ",") {
|
||||
value = lex();
|
||||
if (value == "]") {
|
||||
// Unexpected trailing `,` in array literal.
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
// A `,` must separate each array element.
|
||||
abort();
|
||||
}
|
||||
}
|
||||
// Elisions and leading commas are not permitted.
|
||||
if (value == ",") {
|
||||
abort();
|
||||
}
|
||||
results.push(get(value));
|
||||
}
|
||||
return results;
|
||||
} else if (value == "{") {
|
||||
// Parses a JSON object, returning a new JavaScript object.
|
||||
results = {};
|
||||
for (;; hasMembers || (hasMembers = true)) {
|
||||
value = lex();
|
||||
// A closing curly brace marks the end of the object literal.
|
||||
if (value == "}") {
|
||||
break;
|
||||
}
|
||||
// If the object literal contains members, the current token
|
||||
// should be a comma separator.
|
||||
if (hasMembers) {
|
||||
if (value == ",") {
|
||||
value = lex();
|
||||
if (value == "}") {
|
||||
// Unexpected trailing `,` in object literal.
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
// A `,` must separate each object member.
|
||||
abort();
|
||||
}
|
||||
}
|
||||
// Leading commas are not permitted, object property names must be
|
||||
// double-quoted strings, and a `:` must separate each property
|
||||
// name and value.
|
||||
if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") {
|
||||
abort();
|
||||
}
|
||||
results[value.slice(1)] = get(lex());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
// Unexpected token encountered.
|
||||
abort();
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
// Internal: Updates a traversed object member.
|
||||
var update = function(source, property, callback) {
|
||||
var element = walk(source, property, callback);
|
||||
if (element === undef) {
|
||||
delete source[property];
|
||||
} else {
|
||||
source[property] = element;
|
||||
}
|
||||
};
|
||||
|
||||
// Internal: Recursively traverses a parsed JSON object, invoking the
|
||||
// `callback` function for each value. This is an implementation of the
|
||||
// `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
|
||||
var walk = function (source, property, callback) {
|
||||
var value = source[property], length;
|
||||
if (typeof value == "object" && value) {
|
||||
// `forEach` can't be used to traverse an array in Opera <= 8.54
|
||||
// because its `Object#hasOwnProperty` implementation returns `false`
|
||||
// for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`).
|
||||
if (getClass.call(value) == arrayClass) {
|
||||
for (length = value.length; length--;) {
|
||||
update(value, length, callback);
|
||||
}
|
||||
} else {
|
||||
forEach(value, function (property) {
|
||||
update(value, property, callback);
|
||||
});
|
||||
}
|
||||
}
|
||||
return callback.call(source, property, value);
|
||||
};
|
||||
|
||||
// Public: `JSON.parse`. See ES 5.1 section 15.12.2.
|
||||
JSON3.parse = function (source, callback) {
|
||||
var result, value;
|
||||
Index = 0;
|
||||
Source = "" + source;
|
||||
result = get(lex());
|
||||
// If a JSON string contains multiple tokens, it is invalid.
|
||||
if (lex() != "$") {
|
||||
abort();
|
||||
}
|
||||
// Reset the parser state.
|
||||
Index = Source = null;
|
||||
return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Export for asynchronous module loaders.
|
||||
if (isLoader) {
|
||||
define(function () {
|
||||
return JSON3;
|
||||
});
|
||||
}
|
||||
}(this));
|
||||
62
js/libs/lib-typedarrays.js
Normal file
62
js/libs/lib-typedarrays.js
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
(function () {
|
||||
// Check if typed arrays are supported
|
||||
if (typeof ArrayBuffer != 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
var C = CryptoJS;
|
||||
var C_lib = C.lib;
|
||||
var WordArray = C_lib.WordArray;
|
||||
|
||||
// Reference original init
|
||||
var superInit = WordArray.init;
|
||||
|
||||
// Augment WordArray.init to handle typed arrays
|
||||
var subInit = WordArray.init = function (typedArray) {
|
||||
// Convert buffers to uint8
|
||||
if (typedArray instanceof ArrayBuffer) {
|
||||
typedArray = new Uint8Array(typedArray);
|
||||
}
|
||||
|
||||
// Convert other array views to uint8
|
||||
if (
|
||||
typedArray instanceof Int8Array ||
|
||||
typedArray instanceof Uint8ClampedArray ||
|
||||
typedArray instanceof Int16Array ||
|
||||
typedArray instanceof Uint16Array ||
|
||||
typedArray instanceof Int32Array ||
|
||||
typedArray instanceof Uint32Array ||
|
||||
typedArray instanceof Float32Array ||
|
||||
typedArray instanceof Float64Array
|
||||
) {
|
||||
typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
|
||||
}
|
||||
|
||||
// Handle Uint8Array
|
||||
if (typedArray instanceof Uint8Array) {
|
||||
// Shortcut
|
||||
var typedArrayByteLength = typedArray.byteLength;
|
||||
|
||||
// Extract bytes
|
||||
var words = [];
|
||||
for (var i = 0; i < typedArrayByteLength; i++) {
|
||||
words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8);
|
||||
}
|
||||
|
||||
// Initialize this word array
|
||||
superInit.call(this, words, typedArrayByteLength);
|
||||
} else {
|
||||
// Else call normal init
|
||||
superInit.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
subInit.prototype = WordArray;
|
||||
}());
|
||||
221
js/libs/localstorage_adapter.js
Normal file
221
js/libs/localstorage_adapter.js
Normal file
@@ -0,0 +1,221 @@
|
||||
DS.LSSerializer = DS.JSONSerializer.extend({
|
||||
|
||||
addBelongsTo: function(data, record, key, association) {
|
||||
data[key] = record.get(key + '.id');
|
||||
},
|
||||
|
||||
addHasMany: function(data, record, key, association) {
|
||||
data[key] = record.get(key).map(function(record) {
|
||||
return record.get('id');
|
||||
});
|
||||
},
|
||||
|
||||
// extract expects a root key, we don't want to save all these keys to
|
||||
// localStorage so we generate the root keys here
|
||||
extract: function(loader, json, type, record) {
|
||||
this._super(loader, this.rootJSON(json, type), type, record);
|
||||
},
|
||||
|
||||
extractMany: function(loader, json, type, records) {
|
||||
this._super(loader, this.rootJSON(json, type, 'pluralize'), type, records);
|
||||
},
|
||||
|
||||
rootJSON: function(json, type, pluralize) {
|
||||
var root = this.rootForType(type);
|
||||
if (pluralize == 'pluralize') { root = this.pluralize(root); }
|
||||
var rootedJSON = {};
|
||||
rootedJSON[root] = json;
|
||||
return rootedJSON;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
DS.LSAdapter = DS.Adapter.extend(Ember.Evented, {
|
||||
|
||||
init: function() {
|
||||
this._loadData();
|
||||
},
|
||||
|
||||
generateIdForRecord: function() {
|
||||
return Math.random().toString(32).slice(2).substr(0,5);
|
||||
},
|
||||
|
||||
serializer: DS.LSSerializer.create(),
|
||||
|
||||
find: function(store, type, id) {
|
||||
var namespace = this._namespaceForType(type);
|
||||
this._async(function(){
|
||||
var copy = Ember.copy(namespace.records[id]);
|
||||
this.didFindRecord(store, type, copy, id);
|
||||
});
|
||||
},
|
||||
|
||||
findMany: function(store, type, ids) {
|
||||
var namespace = this._namespaceForType(type);
|
||||
this._async(function(){
|
||||
var results = [];
|
||||
for (var i = 0; i < ids.length; i++) {
|
||||
results.push(Ember.copy(namespace.records[ids[i]]));
|
||||
}
|
||||
this.didFindMany(store, type, results);
|
||||
});
|
||||
},
|
||||
|
||||
// Supports queries that look like this:
|
||||
//
|
||||
// {
|
||||
// <property to query>: <value or regex (for strings) to match>,
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Every property added to the query is an "AND" query, not "OR"
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// match records with "complete: true" and the name "foo" or "bar"
|
||||
//
|
||||
// { complete: true, name: /foo|bar/ }
|
||||
findQuery: function(store, type, query, recordArray) {
|
||||
var namespace = this._namespaceForType(type);
|
||||
this._async(function() {
|
||||
var results = this.query(namespace.records, query);
|
||||
this.didFindQuery(store, type, results, recordArray);
|
||||
});
|
||||
},
|
||||
|
||||
query: function(records, query) {
|
||||
var results = [];
|
||||
var id, record, property, test, push;
|
||||
for (id in records) {
|
||||
record = records[id];
|
||||
for (property in query) {
|
||||
test = query[property];
|
||||
push = false;
|
||||
if (Object.prototype.toString.call(test) == '[object RegExp]') {
|
||||
push = test.test(record[property]);
|
||||
} else {
|
||||
push = record[property] === test;
|
||||
}
|
||||
}
|
||||
if (push) {
|
||||
results.push(record);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
|
||||
findAll: function(store, type) {
|
||||
var namespace = this._namespaceForType(type);
|
||||
this._async(function() {
|
||||
var results = [];
|
||||
for (var id in namespace.records) {
|
||||
results.push(Ember.copy(namespace.records[id]));
|
||||
}
|
||||
this.didFindAll(store, type, results);
|
||||
});
|
||||
},
|
||||
|
||||
createRecords: function(store, type, records) {
|
||||
var namespace = this._namespaceForType(type);
|
||||
records.forEach(function(record) {
|
||||
this._addRecordToNamespace(namespace, record);
|
||||
}, this);
|
||||
this._async(function() {
|
||||
this._didSaveRecords(store, type, records);
|
||||
});
|
||||
},
|
||||
|
||||
updateRecords: function(store, type, records) {
|
||||
var namespace = this._namespaceForType(type);
|
||||
this._async(function() {
|
||||
records.forEach(function(record) {
|
||||
var id = record.get('id');
|
||||
namespace.records[id] = record.serialize({includeId:true});
|
||||
}, this);
|
||||
this._didSaveRecords(store, type, records);
|
||||
});
|
||||
},
|
||||
|
||||
deleteRecords: function(store, type, records) {
|
||||
var namespace = this._namespaceForType(type);
|
||||
this._async(function() {
|
||||
records.forEach(function(record) {
|
||||
var id = record.get('id');
|
||||
delete namespace.records[id];
|
||||
});
|
||||
this._didSaveRecords(store, type, records);
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
dirtyRecordsForHasManyChange: function(dirtySet, parent, relationship) {
|
||||
dirtySet.add(parent);
|
||||
},
|
||||
|
||||
dirtyRecordsForBelongsToChange: function(dirtySet, child, relationship) {
|
||||
dirtySet.add(child);
|
||||
},
|
||||
|
||||
// private
|
||||
|
||||
_getNamespace: function() {
|
||||
return this.namespace || 'DS.LSAdapter';
|
||||
},
|
||||
|
||||
_loadData: function() {
|
||||
try {
|
||||
var storage = localStorage.getItem(this._getNamespace());
|
||||
this._data = storage ? JSON.parse(storage) : {};
|
||||
}
|
||||
catch(e) {
|
||||
this._data = {};
|
||||
}
|
||||
},
|
||||
|
||||
_didSaveRecords: function(store, type, records) {
|
||||
var success = this._saveData();
|
||||
if (success) {
|
||||
store.didSaveRecords(records);
|
||||
} else {
|
||||
records.forEach(function(record) {
|
||||
store.recordWasError(record);
|
||||
});
|
||||
this.trigger('QUOTA_EXCEEDED_ERR', records);
|
||||
}
|
||||
},
|
||||
|
||||
_saveData: function() {
|
||||
try {
|
||||
localStorage.setItem(this._getNamespace(), JSON.stringify(this._data));
|
||||
return true;
|
||||
}
|
||||
catch(error) {
|
||||
if (error.name == 'QUOTA_EXCEEDED_ERR') {
|
||||
return false;
|
||||
} else {
|
||||
// IE, Ignore. throw new Error(error);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_namespaceForType: function(type) {
|
||||
var namespace = type.url || type.toString();
|
||||
return this._data[namespace] || (
|
||||
this._data[namespace] = {records: {}}
|
||||
);
|
||||
},
|
||||
|
||||
_addRecordToNamespace: function(namespace, record) {
|
||||
var data = record.serialize({includeId: true});
|
||||
namespace.records[data.id] = data;
|
||||
},
|
||||
|
||||
_async: function(callback) {
|
||||
var _this = this;
|
||||
setTimeout(function(){
|
||||
Ember.run(_this, callback);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
1400
js/libs/moment.js
Executable file
1400
js/libs/moment.js
Executable file
File diff suppressed because it is too large
Load Diff
23
js/libs/sha512.js
Normal file
23
js/libs/sha512.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
var CryptoJS=CryptoJS||function(a,m){var r={},f=r.lib={},g=function(){},l=f.Base={extend:function(a){g.prototype=this;var b=new g;a&&b.mixIn(a);b.hasOwnProperty("init")||(b.init=function(){b.$super.init.apply(this,arguments)});b.init.prototype=b;b.$super=this;return b},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
|
||||
p=f.WordArray=l.extend({init:function(a,b){a=this.words=a||[];this.sigBytes=b!=m?b:4*a.length},toString:function(a){return(a||q).stringify(this)},concat:function(a){var b=this.words,d=a.words,c=this.sigBytes;a=a.sigBytes;this.clamp();if(c%4)for(var j=0;j<a;j++)b[c+j>>>2]|=(d[j>>>2]>>>24-8*(j%4)&255)<<24-8*((c+j)%4);else if(65535<d.length)for(j=0;j<a;j+=4)b[c+j>>>2]=d[j>>>2];else b.push.apply(b,d);this.sigBytes+=a;return this},clamp:function(){var n=this.words,b=this.sigBytes;n[b>>>2]&=4294967295<<
|
||||
32-8*(b%4);n.length=a.ceil(b/4)},clone:function(){var a=l.clone.call(this);a.words=this.words.slice(0);return a},random:function(n){for(var b=[],d=0;d<n;d+=4)b.push(4294967296*a.random()|0);return new p.init(b,n)}}),y=r.enc={},q=y.Hex={stringify:function(a){var b=a.words;a=a.sigBytes;for(var d=[],c=0;c<a;c++){var j=b[c>>>2]>>>24-8*(c%4)&255;d.push((j>>>4).toString(16));d.push((j&15).toString(16))}return d.join("")},parse:function(a){for(var b=a.length,d=[],c=0;c<b;c+=2)d[c>>>3]|=parseInt(a.substr(c,
|
||||
2),16)<<24-4*(c%8);return new p.init(d,b/2)}},G=y.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var d=[],c=0;c<a;c++)d.push(String.fromCharCode(b[c>>>2]>>>24-8*(c%4)&255));return d.join("")},parse:function(a){for(var b=a.length,d=[],c=0;c<b;c++)d[c>>>2]|=(a.charCodeAt(c)&255)<<24-8*(c%4);return new p.init(d,b)}},fa=y.Utf8={stringify:function(a){try{return decodeURIComponent(escape(G.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return G.parse(unescape(encodeURIComponent(a)))}},
|
||||
h=f.BufferedBlockAlgorithm=l.extend({reset:function(){this._data=new p.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=fa.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(n){var b=this._data,d=b.words,c=b.sigBytes,j=this.blockSize,l=c/(4*j),l=n?a.ceil(l):a.max((l|0)-this._minBufferSize,0);n=l*j;c=a.min(4*n,c);if(n){for(var h=0;h<n;h+=j)this._doProcessBlock(d,h);h=d.splice(0,n);b.sigBytes-=c}return new p.init(h,c)},clone:function(){var a=l.clone.call(this);
|
||||
a._data=this._data.clone();return a},_minBufferSize:0});f.Hasher=h.extend({cfg:l.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){h.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,d){return(new a.init(d)).finalize(b)}},_createHmacHelper:function(a){return function(b,d){return(new ga.HMAC.init(a,
|
||||
d)).finalize(b)}}});var ga=r.algo={};return r}(Math);
|
||||
(function(a){var m=CryptoJS,r=m.lib,f=r.Base,g=r.WordArray,m=m.x64={};m.Word=f.extend({init:function(a,p){this.high=a;this.low=p}});m.WordArray=f.extend({init:function(l,p){l=this.words=l||[];this.sigBytes=p!=a?p:8*l.length},toX32:function(){for(var a=this.words,p=a.length,f=[],q=0;q<p;q++){var G=a[q];f.push(G.high);f.push(G.low)}return g.create(f,this.sigBytes)},clone:function(){for(var a=f.clone.call(this),p=a.words=this.words.slice(0),g=p.length,q=0;q<g;q++)p[q]=p[q].clone();return a}})})();
|
||||
(function(){function a(){return g.create.apply(g,arguments)}for(var m=CryptoJS,r=m.lib.Hasher,f=m.x64,g=f.Word,l=f.WordArray,f=m.algo,p=[a(1116352408,3609767458),a(1899447441,602891725),a(3049323471,3964484399),a(3921009573,2173295548),a(961987163,4081628472),a(1508970993,3053834265),a(2453635748,2937671579),a(2870763221,3664609560),a(3624381080,2734883394),a(310598401,1164996542),a(607225278,1323610764),a(1426881987,3590304994),a(1925078388,4068182383),a(2162078206,991336113),a(2614888103,633803317),
|
||||
a(3248222580,3479774868),a(3835390401,2666613458),a(4022224774,944711139),a(264347078,2341262773),a(604807628,2007800933),a(770255983,1495990901),a(1249150122,1856431235),a(1555081692,3175218132),a(1996064986,2198950837),a(2554220882,3999719339),a(2821834349,766784016),a(2952996808,2566594879),a(3210313671,3203337956),a(3336571891,1034457026),a(3584528711,2466948901),a(113926993,3758326383),a(338241895,168717936),a(666307205,1188179964),a(773529912,1546045734),a(1294757372,1522805485),a(1396182291,
|
||||
2643833823),a(1695183700,2343527390),a(1986661051,1014477480),a(2177026350,1206759142),a(2456956037,344077627),a(2730485921,1290863460),a(2820302411,3158454273),a(3259730800,3505952657),a(3345764771,106217008),a(3516065817,3606008344),a(3600352804,1432725776),a(4094571909,1467031594),a(275423344,851169720),a(430227734,3100823752),a(506948616,1363258195),a(659060556,3750685593),a(883997877,3785050280),a(958139571,3318307427),a(1322822218,3812723403),a(1537002063,2003034995),a(1747873779,3602036899),
|
||||
a(1955562222,1575990012),a(2024104815,1125592928),a(2227730452,2716904306),a(2361852424,442776044),a(2428436474,593698344),a(2756734187,3733110249),a(3204031479,2999351573),a(3329325298,3815920427),a(3391569614,3928383900),a(3515267271,566280711),a(3940187606,3454069534),a(4118630271,4000239992),a(116418474,1914138554),a(174292421,2731055270),a(289380356,3203993006),a(460393269,320620315),a(685471733,587496836),a(852142971,1086792851),a(1017036298,365543100),a(1126000580,2618297676),a(1288033470,
|
||||
3409855158),a(1501505948,4234509866),a(1607167915,987167468),a(1816402316,1246189591)],y=[],q=0;80>q;q++)y[q]=a();f=f.SHA512=r.extend({_doReset:function(){this._hash=new l.init([new g.init(1779033703,4089235720),new g.init(3144134277,2227873595),new g.init(1013904242,4271175723),new g.init(2773480762,1595750129),new g.init(1359893119,2917565137),new g.init(2600822924,725511199),new g.init(528734635,4215389547),new g.init(1541459225,327033209)])},_doProcessBlock:function(a,f){for(var h=this._hash.words,
|
||||
g=h[0],n=h[1],b=h[2],d=h[3],c=h[4],j=h[5],l=h[6],h=h[7],q=g.high,m=g.low,r=n.high,N=n.low,Z=b.high,O=b.low,$=d.high,P=d.low,aa=c.high,Q=c.low,ba=j.high,R=j.low,ca=l.high,S=l.low,da=h.high,T=h.low,v=q,s=m,H=r,E=N,I=Z,F=O,W=$,J=P,w=aa,t=Q,U=ba,K=R,V=ca,L=S,X=da,M=T,x=0;80>x;x++){var B=y[x];if(16>x)var u=B.high=a[f+2*x]|0,e=B.low=a[f+2*x+1]|0;else{var u=y[x-15],e=u.high,z=u.low,u=(e>>>1|z<<31)^(e>>>8|z<<24)^e>>>7,z=(z>>>1|e<<31)^(z>>>8|e<<24)^(z>>>7|e<<25),D=y[x-2],e=D.high,k=D.low,D=(e>>>19|k<<13)^
|
||||
(e<<3|k>>>29)^e>>>6,k=(k>>>19|e<<13)^(k<<3|e>>>29)^(k>>>6|e<<26),e=y[x-7],Y=e.high,C=y[x-16],A=C.high,C=C.low,e=z+e.low,u=u+Y+(e>>>0<z>>>0?1:0),e=e+k,u=u+D+(e>>>0<k>>>0?1:0),e=e+C,u=u+A+(e>>>0<C>>>0?1:0);B.high=u;B.low=e}var Y=w&U^~w&V,C=t&K^~t&L,B=v&H^v&I^H&I,ha=s&E^s&F^E&F,z=(v>>>28|s<<4)^(v<<30|s>>>2)^(v<<25|s>>>7),D=(s>>>28|v<<4)^(s<<30|v>>>2)^(s<<25|v>>>7),k=p[x],ia=k.high,ea=k.low,k=M+((t>>>14|w<<18)^(t>>>18|w<<14)^(t<<23|w>>>9)),A=X+((w>>>14|t<<18)^(w>>>18|t<<14)^(w<<23|t>>>9))+(k>>>0<M>>>
|
||||
0?1:0),k=k+C,A=A+Y+(k>>>0<C>>>0?1:0),k=k+ea,A=A+ia+(k>>>0<ea>>>0?1:0),k=k+e,A=A+u+(k>>>0<e>>>0?1:0),e=D+ha,B=z+B+(e>>>0<D>>>0?1:0),X=V,M=L,V=U,L=K,U=w,K=t,t=J+k|0,w=W+A+(t>>>0<J>>>0?1:0)|0,W=I,J=F,I=H,F=E,H=v,E=s,s=k+e|0,v=A+B+(s>>>0<k>>>0?1:0)|0}m=g.low=m+s;g.high=q+v+(m>>>0<s>>>0?1:0);N=n.low=N+E;n.high=r+H+(N>>>0<E>>>0?1:0);O=b.low=O+F;b.high=Z+I+(O>>>0<F>>>0?1:0);P=d.low=P+J;d.high=$+W+(P>>>0<J>>>0?1:0);Q=c.low=Q+t;c.high=aa+w+(Q>>>0<t>>>0?1:0);R=j.low=R+K;j.high=ba+U+(R>>>0<K>>>0?1:0);S=l.low=
|
||||
S+L;l.high=ca+V+(S>>>0<L>>>0?1:0);T=h.low=T+M;h.high=da+X+(T>>>0<M>>>0?1:0)},_doFinalize:function(){var a=this._data,f=a.words,h=8*this._nDataBytes,g=8*a.sigBytes;f[g>>>5]|=128<<24-g%32;f[(g+128>>>10<<5)+30]=Math.floor(h/4294967296);f[(g+128>>>10<<5)+31]=h;a.sigBytes=4*f.length;this._process();return this._hash.toX32()},clone:function(){var a=r.clone.call(this);a._hash=this._hash.clone();return a},blockSize:32});m.SHA512=r._createHelper(f);m.HmacSHA512=r._createHmacHelper(f)})();
|
||||
42
js/libs/sjcl.js
Normal file
42
js/libs/sjcl.js
Normal file
@@ -0,0 +1,42 @@
|
||||
"use strict";var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a},notReady:function(a){this.toString=function(){return"NOT READY: "+this.message};this.message=a}}};
|
||||
if(typeof module!="undefined"&&module.exports)module.exports=sjcl;
|
||||
sjcl.cipher.aes=function(a){this.h[0][0][0]||this.z();var b,c,d,e,f=this.h[0][4],g=this.h[1];b=a.length;var h=1;if(b!==4&&b!==6&&b!==8)throw new sjcl.exception.invalid("invalid aes key size");this.a=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(a%b===0||b===8&&a%b===4){c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255];if(a%b===0){c=c<<8^c>>>24^h<<24;h=h<<1^(h>>7)*283}}d[a]=d[a-b]^c}for(b=0;a;b++,a--){c=d[b&3?a:a-4];e[b]=a<=4||b<4?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^
|
||||
g[3][f[c&255]]}};
|
||||
sjcl.cipher.aes.prototype={encrypt:function(a){return this.I(a,0)},decrypt:function(a){return this.I(a,1)},h:[[[],[],[],[],[]],[[],[],[],[],[]]],z:function(){var a=this.h[0],b=this.h[1],c=a[4],d=b[4],e,f,g,h=[],i=[],k,j,l,m;for(e=0;e<0x100;e++)i[(h[e]=e<<1^(e>>7)*283)^e]=e;for(f=g=0;!c[f];f^=k||1,g=i[g]||1){l=g^g<<1^g<<2^g<<3^g<<4;l=l>>8^l&255^99;c[f]=l;d[l]=f;j=h[e=h[k=h[f]]];m=j*0x1010101^e*0x10001^k*0x101^f*0x1010100;j=h[l]*0x101^l*0x1010100;for(e=0;e<4;e++){a[e][f]=j=j<<24^j>>>8;b[e][l]=m=m<<24^m>>>8}}for(e=
|
||||
0;e<5;e++){a[e]=a[e].slice(0);b[e]=b[e].slice(0)}},I:function(a,b){if(a.length!==4)throw new sjcl.exception.invalid("invalid aes block size");var c=this.a[b],d=a[0]^c[0],e=a[b?3:1]^c[1],f=a[2]^c[2];a=a[b?1:3]^c[3];var g,h,i,k=c.length/4-2,j,l=4,m=[0,0,0,0];g=this.h[b];var n=g[0],o=g[1],p=g[2],q=g[3],r=g[4];for(j=0;j<k;j++){g=n[d>>>24]^o[e>>16&255]^p[f>>8&255]^q[a&255]^c[l];h=n[e>>>24]^o[f>>16&255]^p[a>>8&255]^q[d&255]^c[l+1];i=n[f>>>24]^o[a>>16&255]^p[d>>8&255]^q[e&255]^c[l+2];a=n[a>>>24]^o[d>>16&
|
||||
255]^p[e>>8&255]^q[f&255]^c[l+3];l+=4;d=g;e=h;f=i}for(j=0;j<4;j++){m[b?3&-j:j]=r[d>>>24]<<24^r[e>>16&255]<<16^r[f>>8&255]<<8^r[a&255]^c[l++];g=d;d=e;e=f;f=a;a=g}return m}};
|
||||
sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.P(a.slice(b/32),32-(b&31)).slice(1);return c===undefined?a:sjcl.bitArray.clamp(a,c-b)},extract:function(a,b,c){var d=Math.floor(-b-c&31);return((b+c-1^b)&-32?a[b/32|0]<<32-d^a[b/32+1|0]>>>d:a[b/32|0]>>>d)&(1<<c)-1},concat:function(a,b){if(a.length===0||b.length===0)return a.concat(b);var c=a[a.length-1],d=sjcl.bitArray.getPartial(c);return d===32?a.concat(b):sjcl.bitArray.P(b,d,c|0,a.slice(0,a.length-1))},bitLength:function(a){var b=a.length;
|
||||
if(b===0)return 0;return(b-1)*32+sjcl.bitArray.getPartial(a[b-1])},clamp:function(a,b){if(a.length*32<b)return a;a=a.slice(0,Math.ceil(b/32));var c=a.length;b&=31;if(c>0&&b)a[c-1]=sjcl.bitArray.partial(b,a[c-1]&2147483648>>b-1,1);return a},partial:function(a,b,c){if(a===32)return b;return(c?b|0:b<<32-a)+a*0x10000000000},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return false;var c=0,d;for(d=0;d<a.length;d++)c|=
|
||||
a[d]^b[d];return c===0},P:function(a,b,c,d){var e;e=0;if(d===undefined)d=[];for(;b>=32;b-=32){d.push(c);c=0}if(b===0)return d.concat(a);for(e=0;e<a.length;e++){d.push(c|a[e]>>>b);c=a[e]<<32-b}e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,b+a>32?c:d.pop(),1));return d},k:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]}};
|
||||
sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d<c/8;d++){if((d&3)===0)e=a[d/4];b+=String.fromCharCode(e>>>24);e<<=8}return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c<a.length;c++){d=d<<8|a.charCodeAt(c);if((c&3)===3){b.push(d);d=0}}c&3&&b.push(sjcl.bitArray.partial(8*(c&3),d));return b}};
|
||||
sjcl.codec.hex={fromBits:function(a){var b="",c;for(c=0;c<a.length;c++)b+=((a[c]|0)+0xf00000000000).toString(16).substr(4);return b.substr(0,sjcl.bitArray.bitLength(a)/4)},toBits:function(a){var b,c=[],d;a=a.replace(/\s|0x/g,"");d=a.length;a+="00000000";for(b=0;b<a.length;b+=8)c.push(parseInt(a.substr(b,8),16)^0);return sjcl.bitArray.clamp(c,d*4)}};
|
||||
sjcl.codec.base64={F:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b,c){var d="",e=0,f=sjcl.codec.base64.F,g=0,h=sjcl.bitArray.bitLength(a);if(c)f=f.substr(0,62)+"-_";for(c=0;d.length*6<h;){d+=f.charAt((g^a[c]>>>e)>>>26);if(e<6){g=a[c]<<6-e;e+=26;c++}else{g<<=6;e-=6}}for(;d.length&3&&!b;)d+="=";return d},toBits:function(a,b){a=a.replace(/\s|=/g,"");var c=[],d=0,e=sjcl.codec.base64.F,f=0,g;if(b)e=e.substr(0,62)+"-_";for(b=0;b<a.length;b++){g=e.indexOf(a.charAt(b));
|
||||
if(g<0)throw new sjcl.exception.invalid("this isn't base64!");if(d>26){d-=26;c.push(f^g>>>d);f=g<<32-d}else{d+=6;f^=g<<32-d}}d&56&&c.push(sjcl.bitArray.partial(d&56,f,1));return c}};sjcl.codec.base64url={fromBits:function(a){return sjcl.codec.base64.fromBits(a,1,1)},toBits:function(a){return sjcl.codec.base64.toBits(a,1)}};sjcl.hash.sha256=function(a){this.a[0]||this.z();if(a){this.n=a.n.slice(0);this.i=a.i.slice(0);this.e=a.e}else this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()};
|
||||
sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.n=this.N.slice(0);this.i=[];this.e=0;return this},update:function(a){if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);var b,c=this.i=sjcl.bitArray.concat(this.i,a);b=this.e;a=this.e=b+sjcl.bitArray.bitLength(a);for(b=512+b&-512;b<=a;b+=512)this.D(c.splice(0,16));return this},finalize:function(){var a,b=this.i,c=this.n;b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);b.push(Math.floor(this.e/
|
||||
4294967296));for(b.push(this.e|0);b.length;)this.D(b.splice(0,16));this.reset();return c},N:[],a:[],z:function(){function a(e){return(e-Math.floor(e))*0x100000000|0}var b=0,c=2,d;a:for(;b<64;c++){for(d=2;d*d<=c;d++)if(c%d===0)continue a;if(b<8)this.N[b]=a(Math.pow(c,0.5));this.a[b]=a(Math.pow(c,1/3));b++}},D:function(a){var b,c,d=a.slice(0),e=this.n,f=this.a,g=e[0],h=e[1],i=e[2],k=e[3],j=e[4],l=e[5],m=e[6],n=e[7];for(a=0;a<64;a++){if(a<16)b=d[a];else{b=d[a+1&15];c=d[a+14&15];b=d[a&15]=(b>>>7^b>>>18^
|
||||
b>>>3^b<<25^b<<14)+(c>>>17^c>>>19^c>>>10^c<<15^c<<13)+d[a&15]+d[a+9&15]|0}b=b+n+(j>>>6^j>>>11^j>>>25^j<<26^j<<21^j<<7)+(m^j&(l^m))+f[a];n=m;m=l;l=j;j=k+b|0;k=i;i=h;h=g;g=b+(h&i^k&(h^i))+(h>>>2^h>>>13^h>>>22^h<<30^h<<19^h<<10)|0}e[0]=e[0]+g|0;e[1]=e[1]+h|0;e[2]=e[2]+i|0;e[3]=e[3]+k|0;e[4]=e[4]+j|0;e[5]=e[5]+l|0;e[6]=e[6]+m|0;e[7]=e[7]+n|0}};
|
||||
sjcl.mode.ccm={name:"ccm",encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,i=h.bitLength(c)/8,k=h.bitLength(g)/8;e=e||64;d=d||[];if(i<7)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(f=2;f<4&&k>>>8*f;f++);if(f<15-i)f=15-i;c=h.clamp(c,8*(15-f));b=sjcl.mode.ccm.H(a,b,c,d,e,f);g=sjcl.mode.ccm.J(a,g,c,b,e,f);return h.concat(g.data,g.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var f=sjcl.bitArray,g=f.bitLength(c)/8,h=f.bitLength(b),i=f.clamp(b,h-e),k=f.bitSlice(b,
|
||||
h-e);h=(h-e)/8;if(g<7)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(b=2;b<4&&h>>>8*b;b++);if(b<15-g)b=15-g;c=f.clamp(c,8*(15-b));i=sjcl.mode.ccm.J(a,i,c,k,e,b);a=sjcl.mode.ccm.H(a,i.data,c,d,e,b);if(!f.equal(i.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");return i.data},H:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,i=h.k;e/=8;if(e%2||e<4||e>16)throw new sjcl.exception.invalid("ccm: invalid tag length");if(d.length>0xffffffff||b.length>0xffffffff)throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data");
|
||||
f=[h.partial(8,(d.length?64:0)|e-2<<2|f-1)];f=h.concat(f,c);f[3]|=h.bitLength(b)/8;f=a.encrypt(f);if(d.length){c=h.bitLength(d)/8;if(c<=65279)g=[h.partial(16,c)];else if(c<=0xffffffff)g=h.concat([h.partial(16,65534)],[c]);g=h.concat(g,d);for(d=0;d<g.length;d+=4)f=a.encrypt(i(f,g.slice(d,d+4).concat([0,0,0])))}for(d=0;d<b.length;d+=4)f=a.encrypt(i(f,b.slice(d,d+4).concat([0,0,0])));return h.clamp(f,e*8)},J:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.k;var i=b.length,k=h.bitLength(b);c=h.concat([h.partial(8,
|
||||
f-1)],c).concat([0,0,0]).slice(0,4);d=h.bitSlice(g(d,a.encrypt(c)),0,e);if(!i)return{tag:d,data:[]};for(g=0;g<i;g+=4){c[3]++;e=a.encrypt(c);b[g]^=e[0];b[g+1]^=e[1];b[g+2]^=e[2];b[g+3]^=e[3]}return{tag:d,data:h.clamp(b,k)}}};
|
||||
sjcl.mode.ocb2={name:"ocb2",encrypt:function(a,b,c,d,e,f){if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("ocb iv must be 128 bits");var g,h=sjcl.mode.ocb2.B,i=sjcl.bitArray,k=i.k,j=[0,0,0,0];c=h(a.encrypt(c));var l,m=[];d=d||[];e=e||64;for(g=0;g+4<b.length;g+=4){l=b.slice(g,g+4);j=k(j,l);m=m.concat(k(c,a.encrypt(k(c,l))));c=h(c)}l=b.slice(g);b=i.bitLength(l);g=a.encrypt(k(c,[0,0,0,b]));l=i.clamp(k(l.concat([0,0,0]),g),b);j=k(j,k(l.concat([0,0,0]),g));j=a.encrypt(k(j,k(c,h(c))));
|
||||
if(d.length)j=k(j,f?d:sjcl.mode.ocb2.pmac(a,d));return m.concat(i.concat(l,i.clamp(j,e)))},decrypt:function(a,b,c,d,e,f){if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("ocb iv must be 128 bits");e=e||64;var g=sjcl.mode.ocb2.B,h=sjcl.bitArray,i=h.k,k=[0,0,0,0],j=g(a.encrypt(c)),l,m,n=sjcl.bitArray.bitLength(b)-e,o=[];d=d||[];for(c=0;c+4<n/32;c+=4){l=i(j,a.decrypt(i(j,b.slice(c,c+4))));k=i(k,l);o=o.concat(l);j=g(j)}m=n-c*32;l=a.encrypt(i(j,[0,0,0,m]));l=i(l,h.clamp(b.slice(c),
|
||||
m).concat([0,0,0]));k=i(k,l);k=a.encrypt(i(k,i(j,g(j))));if(d.length)k=i(k,f?d:sjcl.mode.ocb2.pmac(a,d));if(!h.equal(h.clamp(k,e),h.bitSlice(b,n)))throw new sjcl.exception.corrupt("ocb: tag doesn't match");return o.concat(h.clamp(l,m))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.B,e=sjcl.bitArray,f=e.k,g=[0,0,0,0],h=a.encrypt([0,0,0,0]);h=f(h,d(d(h)));for(c=0;c+4<b.length;c+=4){h=d(h);g=f(g,a.encrypt(f(h,b.slice(c,c+4))))}b=b.slice(c);if(e.bitLength(b)<128){h=f(h,d(h));b=e.concat(b,[2147483648|0,0,
|
||||
0,0])}g=f(g,b);return a.encrypt(f(d(f(h,d(h))),g))},B:function(a){return[a[0]<<1^a[1]>>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^(a[0]>>>31)*135]}};sjcl.misc.hmac=function(a,b){this.M=b=b||sjcl.hash.sha256;var c=[[],[]],d=b.prototype.blockSize/32;this.l=[new b,new b];if(a.length>d)a=b.hash(a);for(b=0;b<d;b++){c[0][b]=a[b]^909522486;c[1][b]=a[b]^1549556828}this.l[0].update(c[0]);this.l[1].update(c[1])};
|
||||
sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a,b){a=(new this.M(this.l[0])).update(a,b).finalize();return(new this.M(this.l[1])).update(a).finalize()};
|
||||
sjcl.misc.pbkdf2=function(a,b,c,d,e){c=c||1E3;if(d<0||c<0)throw sjcl.exception.invalid("invalid params to pbkdf2");if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,i,k=[],j=sjcl.bitArray;for(i=1;32*k.length<(d||1);i++){e=f=a.encrypt(j.concat(b,[i]));for(g=1;g<c;g++){f=a.encrypt(f);for(h=0;h<f.length;h++)e[h]^=f[h]}k=k.concat(e)}if(d)k=j.clamp(k,d);return k};
|
||||
sjcl.random={randomWords:function(a,b){var c=[];b=this.isReady(b);var d;if(b===0)throw new sjcl.exception.notReady("generator isn't seeded");else b&2&&this.U(!(b&1));for(b=0;b<a;b+=4){(b+1)%0x10000===0&&this.L();d=this.w();c.push(d[0],d[1],d[2],d[3])}this.L();return c.slice(0,a)},setDefaultParanoia:function(a){this.t=a},addEntropy:function(a,b,c){c=c||"user";var d,e,f=(new Date).valueOf(),g=this.q[c],h=this.isReady(),i=0;d=this.G[c];if(d===undefined)d=this.G[c]=this.R++;if(g===undefined)g=this.q[c]=
|
||||
0;this.q[c]=(this.q[c]+1)%this.b.length;switch(typeof a){case "number":if(b===undefined)b=1;this.b[g].update([d,this.u++,1,b,f,1,a|0]);break;case "object":c=Object.prototype.toString.call(a);if(c==="[object Uint32Array]"){e=[];for(c=0;c<a.length;c++)e.push(a[c]);a=e}else{if(c!=="[object Array]")i=1;for(c=0;c<a.length&&!i;c++)if(typeof a[c]!="number")i=1}if(!i){if(b===undefined)for(c=b=0;c<a.length;c++)for(e=a[c];e>0;){b++;e>>>=1}this.b[g].update([d,this.u++,2,b,f,a.length].concat(a))}break;case "string":if(b===
|
||||
undefined)b=a.length;this.b[g].update([d,this.u++,3,b,f,a.length]);this.b[g].update(a);break;default:i=1}if(i)throw new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string");this.j[g]+=b;this.f+=b;if(h===0){this.isReady()!==0&&this.K("seeded",Math.max(this.g,this.f));this.K("progress",this.getProgress())}},isReady:function(a){a=this.C[a!==undefined?a:this.t];return this.g&&this.g>=a?this.j[0]>80&&(new Date).valueOf()>this.O?3:1:this.f>=a?2:0},getProgress:function(a){a=
|
||||
this.C[a?a:this.t];return this.g>=a?1:this.f>a?1:this.f/a},startCollectors:function(){if(!this.m){if(window.addEventListener){window.addEventListener("load",this.o,false);window.addEventListener("mousemove",this.p,false)}else if(document.attachEvent){document.attachEvent("onload",this.o);document.attachEvent("onmousemove",this.p)}else throw new sjcl.exception.bug("can't attach event");this.m=true}},stopCollectors:function(){if(this.m){if(window.removeEventListener){window.removeEventListener("load",
|
||||
this.o,false);window.removeEventListener("mousemove",this.p,false)}else if(window.detachEvent){window.detachEvent("onload",this.o);window.detachEvent("onmousemove",this.p)}this.m=false}},addEventListener:function(a,b){this.r[a][this.Q++]=b},removeEventListener:function(a,b){var c;a=this.r[a];var d=[];for(c in a)a.hasOwnProperty(c)&&a[c]===b&&d.push(c);for(b=0;b<d.length;b++){c=d[b];delete a[c]}},b:[new sjcl.hash.sha256],j:[0],A:0,q:{},u:0,G:{},R:0,g:0,f:0,O:0,a:[0,0,0,0,0,0,0,0],d:[0,0,0,0],s:undefined,
|
||||
t:6,m:false,r:{progress:{},seeded:{}},Q:0,C:[0,48,64,96,128,192,0x100,384,512,768,1024],w:function(){for(var a=0;a<4;a++){this.d[a]=this.d[a]+1|0;if(this.d[a])break}return this.s.encrypt(this.d)},L:function(){this.a=this.w().concat(this.w());this.s=new sjcl.cipher.aes(this.a)},T:function(a){this.a=sjcl.hash.sha256.hash(this.a.concat(a));this.s=new sjcl.cipher.aes(this.a);for(a=0;a<4;a++){this.d[a]=this.d[a]+1|0;if(this.d[a])break}},U:function(a){var b=[],c=0,d;this.O=b[0]=(new Date).valueOf()+3E4;for(d=
|
||||
0;d<16;d++)b.push(Math.random()*0x100000000|0);for(d=0;d<this.b.length;d++){b=b.concat(this.b[d].finalize());c+=this.j[d];this.j[d]=0;if(!a&&this.A&1<<d)break}if(this.A>=1<<this.b.length){this.b.push(new sjcl.hash.sha256);this.j.push(0)}this.f-=c;if(c>this.g)this.g=c;this.A++;this.T(b)},p:function(a){sjcl.random.addEntropy([a.x||a.clientX||a.offsetX,a.y||a.clientY||a.offsetY],2,"mouse")},o:function(){sjcl.random.addEntropy((new Date).valueOf(),2,"loadtime")},K:function(a,b){var c;a=sjcl.random.r[a];
|
||||
var d=[];for(c in a)a.hasOwnProperty(c)&&d.push(a[c]);for(c=0;c<d.length;c++)d[c](b)}};try{var s=new Uint32Array(32);crypto.getRandomValues(s);sjcl.random.addEntropy(s,1024,"crypto['getRandomValues']")}catch(t){}
|
||||
sjcl.json={defaults:{v:1,iter:1E3,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},encrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.c({iv:sjcl.random.randomWords(4,0)},e.defaults),g;e.c(f,c);c=f.adata;if(typeof f.salt==="string")f.salt=sjcl.codec.base64.toBits(f.salt);if(typeof f.iv==="string")f.iv=sjcl.codec.base64.toBits(f.iv);if(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||typeof a==="string"&&f.iter<=100||f.ts!==64&&f.ts!==96&&f.ts!==128||f.ks!==128&&f.ks!==192&&f.ks!==0x100||f.iv.length<
|
||||
2||f.iv.length>4)throw new sjcl.exception.invalid("json encrypt: invalid parameters");if(typeof a==="string"){g=sjcl.misc.cachedPbkdf2(a,f);a=g.key.slice(0,f.ks/32);f.salt=g.salt}if(typeof b==="string")b=sjcl.codec.utf8String.toBits(b);if(typeof c==="string")c=sjcl.codec.utf8String.toBits(c);g=new sjcl.cipher[f.cipher](a);e.c(d,f);d.key=a;f.ct=sjcl.mode[f.mode].encrypt(g,b,f.iv,c,f.ts);return e.encode(f)},decrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.c(e.c(e.c({},e.defaults),e.decode(b)),
|
||||
c,true);var f;c=b.adata;if(typeof b.salt==="string")b.salt=sjcl.codec.base64.toBits(b.salt);if(typeof b.iv==="string")b.iv=sjcl.codec.base64.toBits(b.iv);if(!sjcl.mode[b.mode]||!sjcl.cipher[b.cipher]||typeof a==="string"&&b.iter<=100||b.ts!==64&&b.ts!==96&&b.ts!==128||b.ks!==128&&b.ks!==192&&b.ks!==0x100||!b.iv||b.iv.length<2||b.iv.length>4)throw new sjcl.exception.invalid("json decrypt: invalid parameters");if(typeof a==="string"){f=sjcl.misc.cachedPbkdf2(a,b);a=f.key.slice(0,b.ks/32);b.salt=f.salt}if(typeof c===
|
||||
"string")c=sjcl.codec.utf8String.toBits(c);f=new sjcl.cipher[b.cipher](a);c=sjcl.mode[b.mode].decrypt(f,b.ct,b.iv,c,b.ts);e.c(d,b);d.key=a;return sjcl.codec.utf8String.fromBits(c)},encode:function(a){var b,c="{",d="";for(b in a)if(a.hasOwnProperty(b)){if(!b.match(/^[a-z0-9]+$/i))throw new sjcl.exception.invalid("json encode: invalid property name");c+=d+'"'+b+'":';d=",";switch(typeof a[b]){case "number":case "boolean":c+=a[b];break;case "string":c+='"'+escape(a[b])+'"';break;case "object":c+='"'+
|
||||
sjcl.codec.base64.fromBits(a[b],1)+'"';break;default:throw new sjcl.exception.bug("json encode: unsupported type");}}return c+"}"},decode:function(a){a=a.replace(/\s/g,"");if(!a.match(/^\{.*\}$/))throw new sjcl.exception.invalid("json decode: this isn't json!");a=a.replace(/^\{|\}$/g,"").split(/,/);var b={},c,d;for(c=0;c<a.length;c++){if(!(d=a[c].match(/^(?:(["']?)([a-z][a-z0-9]*)\1):(?:(\d+)|"([a-z0-9+\/%*_.@=\-]*)")$/i)))throw new sjcl.exception.invalid("json decode: this isn't json!");b[d[2]]=
|
||||
d[3]?parseInt(d[3],10):d[2].match(/^(ct|salt|iv)$/)?sjcl.codec.base64.toBits(d[4]):unescape(d[4])}return b},c:function(a,b,c){if(a===undefined)a={};if(b===undefined)return a;var d;for(d in b)if(b.hasOwnProperty(d)){if(c&&a[d]!==undefined&&a[d]!==b[d])throw new sjcl.exception.invalid("required parameter overridden");a[d]=b[d]}return a},W:function(a,b){var c={},d;for(d in a)if(a.hasOwnProperty(d)&&a[d]!==b[d])c[d]=a[d];return c},V:function(a,b){var c={},d;for(d=0;d<b.length;d++)if(a[b[d]]!==undefined)c[b[d]]=
|
||||
a[b[d]];return c}};sjcl.encrypt=sjcl.json.encrypt;sjcl.decrypt=sjcl.json.decrypt;sjcl.misc.S={};sjcl.misc.cachedPbkdf2=function(a,b){var c=sjcl.misc.S,d;b=b||{};d=b.iter||1E3;c=c[a]=c[a]||{};d=c[d]=c[d]||{firstSalt:b.salt&&b.salt.length?b.salt.slice(0):sjcl.random.randomWords(2,0)};c=b.salt===undefined?d.firstSalt:b.salt;d[c]=d[c]||sjcl.misc.pbkdf2(a,c,b.iter);return{key:d[c].slice(0),salt:c.slice(0)}};
|
||||
1
js/libs/version.js
Normal file
1
js/libs/version.js
Normal file
@@ -0,0 +1 @@
|
||||
var VERSION = "2013-09-11-232202"
|
||||
248
js/locale.js
Normal file
248
js/locale.js
Normal file
@@ -0,0 +1,248 @@
|
||||
var lang = (navigator.language) ? navigator.language : navigator.userLanguage;
|
||||
|
||||
|
||||
|
||||
window.locale = {
|
||||
"en-US": {
|
||||
"_successors": "Legal Successors",
|
||||
"_successor": "Legal Successor",
|
||||
"_addsuccessor": "Add Legal Successor",
|
||||
"_substitute": "Substitute Successor",
|
||||
"_assets": "Network Assets",
|
||||
"_asset": "Network Asset",
|
||||
"_addasset": "Network Asset",
|
||||
"_add": "add",
|
||||
"_name": "Name",
|
||||
"_uri": "URI",
|
||||
"_login": "Login/ID",
|
||||
"_pass": "Password",
|
||||
"_mail": "Mail",
|
||||
"_ordered": "is ordered to",
|
||||
"_preordered": "The successor is ordered to",
|
||||
"_postordered": "the asset",
|
||||
"_save": "Save",
|
||||
"_savenext": "Save and add another",
|
||||
"_cancel": "Cancel",
|
||||
"_remove": "Remove",
|
||||
"_edit": "Edit",
|
||||
"_notes": "Special Notes",
|
||||
"_address": "Address",
|
||||
"_birth": "Birth Date",
|
||||
"_testament": "View Testament",
|
||||
"_print": "This is the complete digital testament.",
|
||||
"_doprint": "Print it",
|
||||
"_ttitle": "My Digital Testament",
|
||||
"_appoint1": "I, ",
|
||||
"_appoint2": ", being of sound mind and disposing memory, hereby appoint the following person as my legal "
|
||||
+"successor for the listed network assets after my death:",
|
||||
"_appoint3": "If the above person doesn't live anymore or cannot be "
|
||||
+"found, this shall be the replacement legal successor:",
|
||||
"_selftitle": "Information about yourself",
|
||||
"_self": "Yourself",
|
||||
"_place": "Place",
|
||||
"_date": "Date",
|
||||
"_sign": "Signature",
|
||||
"_welcome": "Welcome to DigiProof",
|
||||
"_intro": "You can use DigiProof to generate a digital testament. "
|
||||
+"Enter your data, print it out, sign it and hand it to your solicitor.",
|
||||
"_fill": "Data you have to enter",
|
||||
"_fill_self": "Personal information about yourself",
|
||||
"_fill_successor": "Information about your legal successor(s)",
|
||||
"_fill_asset": "Information about network assets (logins, passwords)"
|
||||
+" and how the successor has to handle it",
|
||||
"_enterself": "Enter data about yourself",
|
||||
"_entersuccessor": "Enter successors",
|
||||
"_enterasset": "Enter network assets",
|
||||
"_has_self": "You already entered data about yourself",
|
||||
"_has_no_self": "You didn't yet enter data about yourself",
|
||||
"_has_successor": "You already entered one or more successors",
|
||||
"_has_no_successor": "You didn't yet enter any succesor",
|
||||
"_has_asset": "You already entered one or more network assets",
|
||||
"_has_no_asset": "You didn't yet enter yet any network assets",
|
||||
"_data": "Manage Data",
|
||||
"_export": "Export Data",
|
||||
"_import": "Import Data",
|
||||
"_exporthelp": "Copy the contents of the box into a textfile "
|
||||
+"and save that somewhere. You can use it later to restore "
|
||||
+"informations:",
|
||||
"_importdone": "Data imported",
|
||||
"_importhelp": "Paste previously exported data in here to restore your informations",
|
||||
"_successorsindex": "This is the list of your legal successors. You may add one or "
|
||||
+"more persons but you can leave it out as well. In this case the regular lawful successor "
|
||||
+"will be responsible for your network assets. The regular successor is the person or "
|
||||
+"persons you appoint in your official testament or are appointed by law according to "
|
||||
+"legal order of succession.",
|
||||
"_assetsindex": "This is the list of your network assets. A network asset is usually "
|
||||
+"an account on a website, email accounts, social network account or webhosting credentials. "
|
||||
+"Specify as much detail of the resource as possible so that your successor will be "
|
||||
+"able to properly manage it after your death.",
|
||||
"_error_address": "Address required",
|
||||
"_error_birth": "Birth date required",
|
||||
"_error_name": "Name required",
|
||||
"_error_password": "Password required",
|
||||
"_dataindex": "Maintain your data, save it for future uses and restore it from previous backups",
|
||||
"_importpass": "Import password",
|
||||
"_error_decrypt": "Failed to decrypt imported data",
|
||||
"_error_order": "Select an order",
|
||||
"_error_successor": "Select a legal successor",
|
||||
"_importagain": "Import again",
|
||||
"_download": "Save data to disk",
|
||||
"_up_file": "Or, import from a previously exported file",
|
||||
"_up_select": "Select Importfile",
|
||||
"_up_change": "Change",
|
||||
"_up_remove": "Remove",
|
||||
"_successorshall": "My legal successor shall maintain the following network assets "
|
||||
+"as ordered per asset.",
|
||||
"_nopasswd": "No personal password has been set. Go to the 'Yourself' settings, "
|
||||
+"enter one and then come back here",
|
||||
"_testamentempty": "You have not entered any network assets and no legal successor, therefore you cannot print a testament yet. Start here: ",
|
||||
"_pop_title": "Quick Help",
|
||||
"_pop_login": "Enter Loginname, User-ID or whatever else is required as identifier for authentication.",
|
||||
"_pop_pass": "Enter the password, passphrase or whatever else the secret for this asset maybe. <b>However, for security reasons you may leave "
|
||||
+"this field blank and fill it out after printing the testament.</b> This way no passwords stay on your computer.",
|
||||
"_pop_uri": "Enter the URI, hostname or ip address of the network asset. If the asset can't be identified this way - e.g. your notebook, "
|
||||
+"then just enter something which identifies the asset best.",
|
||||
"_pop_name": "Enter a name for the asset, e.g. 'Facebook' or 'My tablet pc'",
|
||||
"_pop_notes": "Anything which doesn't fit into the special fields, put in here. Some examples: answers to security questions, "
|
||||
+"additional id's, descriptions about the assets purpose or even special orders for your legal successor.",
|
||||
"_pop_mail": "Enter the email address connected to this network asset. It is advisable to add information about "
|
||||
+"this email into another asset as well.",
|
||||
"_pop_successor": "Select a legal successor. You may use the default in which case the person selected by succesion or "
|
||||
+"your general testament would receive this orders. Or enter a legal successor and select it here.",
|
||||
"_pop_order": "Select how your successor has to manage the network asset. You may add complemental informations "
|
||||
+"into the notes field below."
|
||||
},
|
||||
|
||||
"de": {
|
||||
"_successors": "Rechtsnachfolger",
|
||||
"_successor": "Rechtsnachfolger",
|
||||
"_addsuccessor": "Rechtsnachfolger Hinzufügen",
|
||||
"_substitute": "Ersatzrechtsnachfolger",
|
||||
"_assets": "Netzaccounts",
|
||||
"_asset": "Netzaccount",
|
||||
"_addasset": "Netzaccount hinzufügen",
|
||||
"_add": "neu",
|
||||
"_name": "Bezeichnung",
|
||||
"_uri": "URL",
|
||||
"_login": "Benutzername",
|
||||
"_pass": "Passwort",
|
||||
"_mail": "E-Mail",
|
||||
"_ordered": "wird beauftragt",
|
||||
"_preordered": "Der Rechtsnachfolger wird beauftragt, den Netzaccount",
|
||||
"_postordered": "",
|
||||
"_save": "Speichern",
|
||||
"_savenext": "Speichern und Fortfahren",
|
||||
"_cancel": "Abbrechen",
|
||||
"_edit": "Bearbeiten",
|
||||
"_remove": "Entfernen",
|
||||
"_notes": "Besondere Hinweise",
|
||||
"_birth": "Geburtsdatum",
|
||||
"_testament": "Testament Anschauen",
|
||||
"_address": "Adresse",
|
||||
"_print": "Dies ist das vollständige digitale Testament.",
|
||||
"_doprint": "Ausdrucken",
|
||||
"_ttitle": "Mein digitales Testament",
|
||||
"_appoint1": "Hiermit bestimme ich, ",
|
||||
"_appoint2": ", im Vollbesitz meiner geistigen Kräfte, die folgende Person als Rechtsnachfolger "
|
||||
+"für die aufgeführten Netzwerkaccounts nach meinem Tode:",
|
||||
"_appoint3": "Falls die oben aufgeführte Person nicht mehr leben sollte "
|
||||
+"oder unauffindbar sein, so soll dies der Ersatzrechtsnachfolger "
|
||||
+"sein:",
|
||||
"_successorshall": "Mein Rechtsnachfolger soll sich um die im folgenden "
|
||||
+"aufgelisteten Netzaccounts den dabeistehenden Anweisungen entsprechend "
|
||||
+"kümmern.",
|
||||
"_selftitle": "Angaben über Sie",
|
||||
"_self": "Eigene Angaben",
|
||||
"_place": "Ort",
|
||||
"_date": "Datum",
|
||||
"_sign": "Unterschrift",
|
||||
"_welcome": "Willkommen bei DigiProof",
|
||||
"_intro": "Sie können DigiProof verwenden, um ein digitales Testament "
|
||||
+"zu erstellen. Machen Sie Ihre Angaben, drucken Sie das Testament aus,"
|
||||
+"unterschreiben Sie es und hinterlegen Sie es bei Ihrem Notar.",
|
||||
"_fill": "Erforderliche Angaben",
|
||||
"_fill_self": "Persönliche Angaben über Sie selbst",
|
||||
"_fill_successor": "Informationen über Ihre(n) Rechtsnachfolger (Erbe)",
|
||||
"_fill_asset": "Informationen über Netzwerkaccounts (Benutzernamen, "
|
||||
+"Passwörter) und wie Ihr Erbe damit verfahren soll",
|
||||
"_enterself": "Persönliche Angaben Eingeben",
|
||||
"_entersuccessor": "Rechtsnachfolger Eingeben",
|
||||
"_enterasset": "Netzwerkaccounts Eingeben",
|
||||
"_has_self": "Sie haben bereits persönliche Angaben gemacht",
|
||||
"_has_no_self": "Sie haben noch keine persönliche Angaben gemacht",
|
||||
"_has_successor": "Sie haben bereits einen oder mehrere Rechtsnachfolger eingegeben",
|
||||
"_has_no_successor": "Sie haben noch keinen Rechtsnachfolger eingegeben",
|
||||
"_has_asset": "Sie haben bereits einen oder mehrere Netzwerkaccounts eingegeben",
|
||||
"_has_no_asset": "Sie haben noch keine Netzwerkaccounts eingegeben",
|
||||
"_data": "Daten Verwalten",
|
||||
"_export": "Daten Exportieren",
|
||||
"_import": "Daten Importieren",
|
||||
"_importdone": "Daten wurden importiert",
|
||||
"_exporthelp": "Kopieren Sie den Inhalt der Box in eine Textdatei und "
|
||||
+"speichern Sie sie ab. Sie können damit Ihre Eingaben später "
|
||||
+"wieder herstellen:",
|
||||
"_dataindex": "Hier können Sie Ihre Daten verwalten, für die Zukunft sichern und wiederherstellen.",
|
||||
"_importhelp": "Fügen Sie hier den Inhalt eines vorherigen Exports hinein um Ihre Daten wiederherzustellen",
|
||||
"_successorsindex": "Dies ist die Liste Ihrer Rechtsnachfolger. Sie können eine oder "
|
||||
+"mehrere Personen bestimmen, die sich nach Ihrem Tode um Ihre Netzwerkaccounts kümmern "
|
||||
+"sollen. Sie können diesen Teil aber auch weglassen. In dem Fall werden Ihre legalen "
|
||||
+"Erben, bestimmt durch Testament oder gesetzliche Erbfolge, für Ihre Accounts zuständig.",
|
||||
"_assetsindex": "Dies ist die Liste Ihrer Netzwerkaccounts. Dabei handelt es sich um "
|
||||
+"Zugänge zu Webseiten, Foren, sozialen Netzwerken, Email oder auch Webhosting. Geben Sie "
|
||||
+"so viele Details wie möglich an, umso besser wird sich Ihr Rechtsnachfolger nach Ihrem "
|
||||
+"Ableben darum kümmern können.",
|
||||
"_error_address": "Addresse erforderlich",
|
||||
"_error_birth": "Geburtsdatum erforderlich",
|
||||
"_error_name": "Name erforderlich",
|
||||
"_error_password": "Passwort erforderlich",
|
||||
"_importpass": "Import Passwort",
|
||||
"_error_decrypt": "Entschlüsseln der importierten Daten fehlgeschlagen",
|
||||
"_error_order": "Wählen Sie einen Auftrag",
|
||||
"_error_successor": "Wählen Sie einen Rechtsnachfolger",
|
||||
"_importagain": "Import Wiederholen",
|
||||
"_download": "Daten auf die Festplatte Speichern",
|
||||
"_up_file": "Oder, verwenden Sie eine vorher exportierte Datei",
|
||||
"_up_select": "Importdatei Auswählen",
|
||||
"_up_change": "Ändern",
|
||||
"_up_remove": "Entfernen",
|
||||
"_nopasswd": "Es wurde bisher noch kein Passwort eingestellt. Gehen Sie zu 'Eigene Angaben', "
|
||||
+"stellen Sie dort ein Passwort ein und versuchen Sie es dann erneut",
|
||||
"_testamentempty": "Sie haben noch keine Netzwerkaccounts und keine Rechtsnachfolger eingeben, "
|
||||
+"daher können Sie noch kein Testament ausdrucken. Beginnen Sie mit der Dateneingabe hier: ",
|
||||
"_pop_title": "Kurzhilfe",
|
||||
"_pop_login": "Geben Sie den Benutzername, ID oder was sonst als Identifikation zur Anmeldung am Netzwerkaccount "
|
||||
+"erforderlich ist, ein.",
|
||||
"_pop_pass": "Geben Sie das Passwort für den Zugang zum Netzwerkaccount ein. <b>Wenn Sie Bedenken bezüglich der Sicherheit "
|
||||
+"Ihrer Zugangsdaten haben, lassen Sie das Feld einfach frei und tragen das Passwort nach dem Ausdrucken von Hand ein.</b>",
|
||||
"_pop_uri": "Geben Sie die URL, den Rechnernamen oder die IP Adresse des Netzwerkaccounts ein. Wenn der Account auf diese "
|
||||
+"Weise nicht identifiziert werden kann, zum Beispiel weil es sich um Ihr Notebook handelt, dann geben Sie "
|
||||
+"einen möglichst eindeutigen Namen des Geräts oder des Accounts ein.",
|
||||
"_pop_name": "Geben Sie die Bezeichnung für den Netzwerkaccount ein wie 'Facebook' oder 'Mein Notebook'",
|
||||
"_pop_notes": "Hier können Sie alles eintragen, für das die Spezialfelder nicht ausreichend sind. Ein paar Beispiele: "
|
||||
+"zusätzliche IDs oder PINs, Beschreibungen über den Zweck des Accounts, Antworten zu Sicherheitsfragen "
|
||||
+"oder aber spezielle bzw. ergänzende Anweisungen für Ihren Rechtsnachfolger",
|
||||
"_pop_mail": "Geben Sie hier die Emailadresse ein, mit der der Netzwerkaccount verbunden ist. Es ist ratsam in einem "
|
||||
+"weiteren Netzwerkaccount ebenfalls den Zugang zu dieser Email anzugeben.",
|
||||
"_pop_successor": "Wählen Sie Ihren Rechtsnachfolger aus. Sie können den Standard verwenden, in dem Fall erhält Ihr "
|
||||
+"regulärer Erbe (bestimmt durch gesetzliche Erbfolge oder anderweitig durch Testament) diese Anweisungen erhalten. "
|
||||
+"Oder Sie geben einen speziellen Rechtsnachfolger ein und wählen diesen hier aus.",
|
||||
"_pop_order": "Bestimmen Sie, wie Ihr Rechtsnachfolger mit dem Netzwerkaccount umgehen soll. Sie können im Notizfeld "
|
||||
+"dazugehörige Ergänzungen hinzufügen."
|
||||
}
|
||||
};
|
||||
|
||||
// locale helper for use in app.js, not for templates
|
||||
function translate(key) {
|
||||
var locale = window.locale[lang] || window.locale['en-US'];
|
||||
if(key) {
|
||||
if(key in locale) {
|
||||
return locale[key];
|
||||
}
|
||||
else {
|
||||
return '__UNTRANSLATED_STRING__(' + key + ')';
|
||||
}
|
||||
}
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
95
js/mixins.js
Normal file
95
js/mixins.js
Normal file
@@ -0,0 +1,95 @@
|
||||
App.SelfMixin = Ember.Mixin.create({
|
||||
passwdset: null,
|
||||
|
||||
/*
|
||||
didLoad: function() {
|
||||
this._passwdset();
|
||||
},
|
||||
|
||||
didUpdate: function() {
|
||||
this.didLoad();
|
||||
},
|
||||
*/
|
||||
|
||||
validate: function() {
|
||||
var valid = true;
|
||||
var errors = {valid: true};
|
||||
if(! this.get('password')) {
|
||||
errors.password = translate('_error_password');
|
||||
errors.valid = false;
|
||||
}
|
||||
if(! this.get('name')) {
|
||||
errors.name = translate('_error_name');
|
||||
errors.valid = false;
|
||||
}
|
||||
if(! this.get('birth')) {
|
||||
errors.birth = translate('_error_birth');
|
||||
errors.valid = false;
|
||||
}
|
||||
if(! this.get('address')) {
|
||||
errors.address = translate('_error_address');
|
||||
errors.valid = false;
|
||||
}
|
||||
return errors;
|
||||
},
|
||||
|
||||
haspasswd: function() {
|
||||
var p = this.get('password');
|
||||
if(p) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}.property()
|
||||
});
|
||||
|
||||
App.ImportMixin = Ember.Mixin.create({
|
||||
validate: function() {
|
||||
var valid = true;
|
||||
var errors = {valid: true};
|
||||
if(! this.get('password')) {
|
||||
errors.password = translate('_error_password');
|
||||
errors.valid = false;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
});
|
||||
|
||||
App.SuccessorMixin = Ember.Mixin.create({
|
||||
validate: function() {
|
||||
var valid = true;
|
||||
var errors = {valid: true};
|
||||
if(! this.get('name')) {
|
||||
errors.name = translate('_error_name');
|
||||
errors.valid = false;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
});
|
||||
|
||||
App.AssetMixin = Ember.Mixin.create({
|
||||
validate: function() {
|
||||
var orderid;
|
||||
var successorid;
|
||||
var errors = {valid: true};
|
||||
try {
|
||||
orderid = this.get('order').get('id');
|
||||
}
|
||||
catch (e) { }
|
||||
try {
|
||||
successorid = this.get('successor').get('id');
|
||||
}
|
||||
catch (e) { }
|
||||
//console.log("got o: %o, s: %o", orderid, successorid);
|
||||
if(! orderid) {
|
||||
errors.order = translate('_error_order');
|
||||
errors.valid = false;
|
||||
}
|
||||
if(! successorid) {
|
||||
errors.successor = translate('_error_successor');
|
||||
errors.valid = false;
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
});
|
||||
95
js/models.js
Normal file
95
js/models.js
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
var attr = DS.attr;
|
||||
|
||||
App.Order = DS.Model.extend({
|
||||
name: attr('string')
|
||||
});
|
||||
|
||||
App.Self = DS.Model.extend(App.SelfMixin, {
|
||||
name: attr('string'),
|
||||
address: attr('string'),
|
||||
birth: attr('string'),
|
||||
password: attr('string'),
|
||||
toJson: function() {
|
||||
return JSON.stringify({
|
||||
name: this.get('name'),
|
||||
address: this.get('address'),
|
||||
birth: this.get('birth')
|
||||
});
|
||||
}.property()
|
||||
});
|
||||
|
||||
|
||||
App.Import = DS.Model.extend(App.ImportMixin, {
|
||||
importdata: attr('string'),
|
||||
password: attr('string')
|
||||
});
|
||||
|
||||
|
||||
|
||||
App.Successor = DS.Model.extend(App.SuccessorMixin, {
|
||||
name: attr('string'),
|
||||
address: attr('string'),
|
||||
birth: attr('string'),
|
||||
name2: attr('string'),
|
||||
address2: attr('string'),
|
||||
birth2: attr('string'),
|
||||
assets: DS.hasMany('App.Asset', {
|
||||
inverse: 'successor'
|
||||
}),
|
||||
toJson: function() {
|
||||
return JSON.stringify({
|
||||
id: this.get('id'),
|
||||
name: this.get('name'),
|
||||
address: this.get('address'),
|
||||
birth: this.get('birth'),
|
||||
name2: this.get('name2'),
|
||||
address2: this.get('address2'),
|
||||
birth2: this.get('birth2')
|
||||
});
|
||||
}.property(),
|
||||
has_assets: function() {
|
||||
var has = false;
|
||||
var assets = this.get('assets');
|
||||
has = assets.forEach(function(asset) {
|
||||
return true;
|
||||
});
|
||||
return has;
|
||||
}.property()
|
||||
});
|
||||
|
||||
|
||||
App.Asset = DS.Model.extend(App.AssetMixin, {
|
||||
name: attr('string'),
|
||||
uri: attr('string'),
|
||||
login: attr('string'),
|
||||
password: attr('string'),
|
||||
mail: attr('string'),
|
||||
order: DS.belongsTo('App.Order'),
|
||||
notes: attr('string'),
|
||||
successor: DS.belongsTo('App.Successor'),
|
||||
toJson: function() {
|
||||
var orderid = "0";
|
||||
var successorid = "0";
|
||||
try {
|
||||
orderid = this.get('order').get('id');
|
||||
}
|
||||
catch (e) {}
|
||||
try {
|
||||
successorid = this.get('successor').get('id');
|
||||
}
|
||||
catch (e) {}
|
||||
return JSON.stringify({
|
||||
id: this.get('id'),
|
||||
name: this.get('name'),
|
||||
uri: this.get('uri'),
|
||||
login: this.get('login'),
|
||||
password: this.get('password'),
|
||||
mail: this.get('mail'),
|
||||
notes: this.get('notes'),
|
||||
order: orderid,
|
||||
successor: successorid
|
||||
});
|
||||
}.property()
|
||||
});
|
||||
|
||||
49
js/router.js
Normal file
49
js/router.js
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
App.Router.map(function() {
|
||||
this.resource('assets', function() {
|
||||
this.route('asset', { path: ':asset_id' });
|
||||
this.route('new');
|
||||
});
|
||||
|
||||
this.resource('successors', function() {
|
||||
this.route('successor', { path: ':successor_id' });
|
||||
this.route('new');
|
||||
});
|
||||
|
||||
this.route('self');
|
||||
|
||||
this.route('testament');
|
||||
|
||||
this.route('about');
|
||||
|
||||
this.resource('data', function() {
|
||||
this.route('export');
|
||||
this.route('import');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
App.AssetsRoute = Ember.Route.extend({
|
||||
model: function() {
|
||||
return App.Asset.find();
|
||||
}
|
||||
});
|
||||
|
||||
App.SelfRoute = Ember.Route.extend({
|
||||
setupController: function(controller) {
|
||||
controller.set('model', App.Self.find(0));
|
||||
}
|
||||
});
|
||||
|
||||
App.DataImportRoute = Ember.Route.extend({
|
||||
setupController: function(controller) {
|
||||
controller.set('model', App.Import.find(0));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
App.SuccessorsRoute = Ember.Route.extend({
|
||||
model: function() {
|
||||
return App.Successor.find();
|
||||
}
|
||||
});
|
||||
11
js/security.js
Executable file
11
js/security.js
Executable file
@@ -0,0 +1,11 @@
|
||||
/* crypto helpers */
|
||||
|
||||
|
||||
function pwhash(pass) {
|
||||
/* get the clear text password, generate a salt
|
||||
and hash them together. return the hash */
|
||||
var salt = CryptoJS.lib.WordArray.random(128/8);
|
||||
console.log("key: %s, salt: %s", pass, salt);
|
||||
var key512iter32 = CryptoJS.PBKDF2(pass, salt,{ keySize: 512/32, iterations: 32, hasher: CryptoJS.algo.SHA512 });
|
||||
return key512iter32;
|
||||
}
|
||||
33
js/store.js
Normal file
33
js/store.js
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
App.store = DS.Store.createWithMixins({
|
||||
revision: 12,
|
||||
adapter: DS.LSAdapter.create({
|
||||
namespace: 'digiproof'
|
||||
}),
|
||||
init: function() {
|
||||
this._super();
|
||||
this.loadMany(App.Import,[ { 'id': 0, 'importdata': '' }]);
|
||||
if(lang === 'de') {
|
||||
this.loadMany(App.Order,
|
||||
[
|
||||
{ 'id': 0, 'name': 'weiter zu betreiben' },
|
||||
{ 'id': 1, 'name': 'zu kündigen' },
|
||||
{ 'id': 2, 'name': 'zu übertragen' },
|
||||
{ 'id': 3, 'name': 'nach Gutdünken abzuwickeln' },
|
||||
]
|
||||
);
|
||||
this.loadMany(App.Successor, [{ 'id': 0, 'name': 'Mein(e) regulären Erbe(n)' }]);
|
||||
}
|
||||
else {
|
||||
this.loadMany(App.Order,
|
||||
[
|
||||
{ 'id': 0, 'name': 'maintain' },
|
||||
{ 'id': 1, 'name': 'liquidate' },
|
||||
{ 'id': 2, 'name': 'transfer' },
|
||||
{ 'id': 3, 'name': 'decide herself' },
|
||||
]
|
||||
);
|
||||
this.loadMany(App.Successor, [{ 'id': 0, 'name': 'My regular legal succesor(s)' }]);
|
||||
}
|
||||
}
|
||||
});
|
||||
70
mksingleton.pl
Executable file
70
mksingleton.pl
Executable file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/perl
|
||||
use Data::Dumper;
|
||||
use JavaScript::Minifier qw(minify);
|
||||
use CSS::Compressor qw( css_compress );
|
||||
|
||||
my $index = shift;
|
||||
|
||||
if (!$index) {
|
||||
print STDERR "Usage: $0 <index.html>\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $out = "digiproof.html";
|
||||
|
||||
print STDERR "open index\n";
|
||||
open I, "<$index" or die "Could not open index: $index $!\n";
|
||||
my @source = <I>;
|
||||
close I;
|
||||
|
||||
print STDERR "open $out\n";
|
||||
open OUT, ">$out" or die "Could not open output $out: $!\n";
|
||||
select OUT;
|
||||
|
||||
print STDERR "enter loop\n";
|
||||
foreach (@source) {
|
||||
chomp;
|
||||
next if(/^\s*$/);
|
||||
if (/rel="stylesheet" href="([^"]*)"/) {
|
||||
my $cssfile = $1;
|
||||
my $media = "";
|
||||
if (/media="([^"]*)"/) {
|
||||
$media = qq( media="$1" );
|
||||
}
|
||||
print STDERR "Inserting $cssfile\n";
|
||||
print qq(<style type="text/css" $media>\n);
|
||||
print &fetch($cssfile);
|
||||
print qq(</style>\n);
|
||||
}
|
||||
elsif (/script src="([^"]*)"/) {
|
||||
my $jsfile = $1;
|
||||
print STDERR "Inserting $jsfile\n";
|
||||
print qq(<script type="text/javascript">\n);
|
||||
print &fetch($jsfile);
|
||||
print qq(</script>\n);
|
||||
}
|
||||
else {
|
||||
print qq($_\n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sub fetch {
|
||||
my $file = shift;
|
||||
open F, "<$file" or die "Could not open index: $file $!\n";
|
||||
if($file =~ /\.js/) {
|
||||
my $js = minify(input => *F);
|
||||
# ember.js (and probably others) contain strings which contain </script>
|
||||
# which leads to rendering failures, those will be fixed here
|
||||
$js =~ s/<\/script>/' + Slash + 'script>/g;
|
||||
close F;
|
||||
return "/* js from $file */\n" . $js;
|
||||
}
|
||||
else {
|
||||
my $src = join "", <F>;
|
||||
close F;
|
||||
return "/* css from $file */\n" . css_compress($src);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user