├── .gitignore
├── README.md
├── config.json
├── package.json
├── public
├── bootstrap-3.2.0-dist
│ ├── css
│ │ ├── bootstrap-theme.css
│ │ ├── bootstrap-theme.css.map
│ │ ├── bootstrap-theme.min.css
│ │ ├── bootstrap.css
│ │ ├── bootstrap.css.map
│ │ └── bootstrap.min.css
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ └── glyphicons-halflings-regular.woff
│ └── js
│ │ ├── bootstrap.js
│ │ └── bootstrap.min.js
├── img
│ └── icon.png
├── index.html
├── js
│ ├── binary.js
│ ├── jquery-1.11.1.min.js
│ ├── re-sampler.js
│ ├── site.js
│ └── worker
│ │ ├── resampler-worker.js
│ │ └── resampler.js
└── style
│ └── site.css
├── server
├── server.js
└── ua-parser.js
└── ssl
├── server.crt
└── server.key
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | recordings
3 | .idea
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | AudioStreamer
2 | =============
3 |
4 | HTML5 realtime audio streaming to nodejs
5 | ----------------------------------------
6 |
7 | Stream audio from the microphone connected to your browser to a node js server.
8 | You can change the encoding of the saved audio from "WAV" to "MP3" in ```config.json```
9 |
10 | install dependencies:
11 |
12 | npm install
13 |
14 | run:
15 |
16 | npm start
17 |
18 |
19 |
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "AudioEncoding":"WAV"
3 | }
4 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "AudioStreamer",
3 | "version": "1.0.0",
4 | "description": "Audio Streamer Web Server",
5 | "main": "server/server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node server/server.js"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "https://github.com/noamtcohen/AudioStreamer.git"
13 | },
14 | "author": "noamtcohen",
15 | "license": "none",
16 | "bugs": {
17 | "url": "https://github.com/noamtcohen/AudioStreamer/issues"
18 | },
19 | "homepage": "https://github.com/noamtcohen/AudioStreamer",
20 | "dependencies": {
21 | "binaryjs": "^0.2.1",
22 | "connect": "^3.3.4",
23 | "lame": "^1.2.3",
24 | "opener": "^1.4.1",
25 | "serve-static": "^1.9.1",
26 | "uaparser": "0.0.2",
27 | "wav": "^0.1.2"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/public/bootstrap-3.2.0-dist/css/bootstrap-theme.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.2.0 (http://getbootstrap.com)
3 | * Copyright 2011-2014 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | .btn-default,
8 | .btn-primary,
9 | .btn-success,
10 | .btn-info,
11 | .btn-warning,
12 | .btn-danger {
13 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
14 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
15 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
16 | }
17 | .btn-default:active,
18 | .btn-primary:active,
19 | .btn-success:active,
20 | .btn-info:active,
21 | .btn-warning:active,
22 | .btn-danger:active,
23 | .btn-default.active,
24 | .btn-primary.active,
25 | .btn-success.active,
26 | .btn-info.active,
27 | .btn-warning.active,
28 | .btn-danger.active {
29 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
30 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
31 | }
32 | .btn:active,
33 | .btn.active {
34 | background-image: none;
35 | }
36 | .btn-default {
37 | text-shadow: 0 1px 0 #fff;
38 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
39 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
40 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
41 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
42 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
43 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
44 | background-repeat: repeat-x;
45 | border-color: #dbdbdb;
46 | border-color: #ccc;
47 | }
48 | .btn-default:hover,
49 | .btn-default:focus {
50 | background-color: #e0e0e0;
51 | background-position: 0 -15px;
52 | }
53 | .btn-default:active,
54 | .btn-default.active {
55 | background-color: #e0e0e0;
56 | border-color: #dbdbdb;
57 | }
58 | .btn-default:disabled,
59 | .btn-default[disabled] {
60 | background-color: #e0e0e0;
61 | background-image: none;
62 | }
63 | .btn-primary {
64 | background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
65 | background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
66 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2));
67 | background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
68 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
69 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
70 | background-repeat: repeat-x;
71 | border-color: #2b669a;
72 | }
73 | .btn-primary:hover,
74 | .btn-primary:focus {
75 | background-color: #2d6ca2;
76 | background-position: 0 -15px;
77 | }
78 | .btn-primary:active,
79 | .btn-primary.active {
80 | background-color: #2d6ca2;
81 | border-color: #2b669a;
82 | }
83 | .btn-primary:disabled,
84 | .btn-primary[disabled] {
85 | background-color: #2d6ca2;
86 | background-image: none;
87 | }
88 | .btn-success {
89 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
90 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
91 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
92 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
93 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
94 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
95 | background-repeat: repeat-x;
96 | border-color: #3e8f3e;
97 | }
98 | .btn-success:hover,
99 | .btn-success:focus {
100 | background-color: #419641;
101 | background-position: 0 -15px;
102 | }
103 | .btn-success:active,
104 | .btn-success.active {
105 | background-color: #419641;
106 | border-color: #3e8f3e;
107 | }
108 | .btn-success:disabled,
109 | .btn-success[disabled] {
110 | background-color: #419641;
111 | background-image: none;
112 | }
113 | .btn-info {
114 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
115 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
116 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
117 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
118 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
119 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
120 | background-repeat: repeat-x;
121 | border-color: #28a4c9;
122 | }
123 | .btn-info:hover,
124 | .btn-info:focus {
125 | background-color: #2aabd2;
126 | background-position: 0 -15px;
127 | }
128 | .btn-info:active,
129 | .btn-info.active {
130 | background-color: #2aabd2;
131 | border-color: #28a4c9;
132 | }
133 | .btn-info:disabled,
134 | .btn-info[disabled] {
135 | background-color: #2aabd2;
136 | background-image: none;
137 | }
138 | .btn-warning {
139 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
140 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
141 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
142 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
143 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
144 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
145 | background-repeat: repeat-x;
146 | border-color: #e38d13;
147 | }
148 | .btn-warning:hover,
149 | .btn-warning:focus {
150 | background-color: #eb9316;
151 | background-position: 0 -15px;
152 | }
153 | .btn-warning:active,
154 | .btn-warning.active {
155 | background-color: #eb9316;
156 | border-color: #e38d13;
157 | }
158 | .btn-warning:disabled,
159 | .btn-warning[disabled] {
160 | background-color: #eb9316;
161 | background-image: none;
162 | }
163 | .btn-danger {
164 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
165 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
166 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
167 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
168 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
169 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
170 | background-repeat: repeat-x;
171 | border-color: #b92c28;
172 | }
173 | .btn-danger:hover,
174 | .btn-danger:focus {
175 | background-color: #c12e2a;
176 | background-position: 0 -15px;
177 | }
178 | .btn-danger:active,
179 | .btn-danger.active {
180 | background-color: #c12e2a;
181 | border-color: #b92c28;
182 | }
183 | .btn-danger:disabled,
184 | .btn-danger[disabled] {
185 | background-color: #c12e2a;
186 | background-image: none;
187 | }
188 | .thumbnail,
189 | .img-thumbnail {
190 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
191 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
192 | }
193 | .dropdown-menu > li > a:hover,
194 | .dropdown-menu > li > a:focus {
195 | background-color: #e8e8e8;
196 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
197 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
198 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
199 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
200 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
201 | background-repeat: repeat-x;
202 | }
203 | .dropdown-menu > .active > a,
204 | .dropdown-menu > .active > a:hover,
205 | .dropdown-menu > .active > a:focus {
206 | background-color: #357ebd;
207 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
208 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
209 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
210 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
211 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
212 | background-repeat: repeat-x;
213 | }
214 | .navbar-default {
215 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
216 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
217 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
218 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
219 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
220 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
221 | background-repeat: repeat-x;
222 | border-radius: 4px;
223 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
224 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
225 | }
226 | .navbar-default .navbar-nav > .active > a {
227 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
228 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
229 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3));
230 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
231 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
232 | background-repeat: repeat-x;
233 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
234 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
235 | }
236 | .navbar-brand,
237 | .navbar-nav > li > a {
238 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
239 | }
240 | .navbar-inverse {
241 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
242 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
243 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
244 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
245 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
246 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
247 | background-repeat: repeat-x;
248 | }
249 | .navbar-inverse .navbar-nav > .active > a {
250 | background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%);
251 | background-image: -o-linear-gradient(top, #222 0%, #282828 100%);
252 | background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828));
253 | background-image: linear-gradient(to bottom, #222 0%, #282828 100%);
254 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);
255 | background-repeat: repeat-x;
256 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
257 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
258 | }
259 | .navbar-inverse .navbar-brand,
260 | .navbar-inverse .navbar-nav > li > a {
261 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
262 | }
263 | .navbar-static-top,
264 | .navbar-fixed-top,
265 | .navbar-fixed-bottom {
266 | border-radius: 0;
267 | }
268 | .alert {
269 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
270 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
271 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
272 | }
273 | .alert-success {
274 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
275 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
276 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
277 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
278 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
279 | background-repeat: repeat-x;
280 | border-color: #b2dba1;
281 | }
282 | .alert-info {
283 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
284 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
285 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
286 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
287 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
288 | background-repeat: repeat-x;
289 | border-color: #9acfea;
290 | }
291 | .alert-warning {
292 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
293 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
294 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
295 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
296 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
297 | background-repeat: repeat-x;
298 | border-color: #f5e79e;
299 | }
300 | .alert-danger {
301 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
302 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
303 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
304 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
305 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
306 | background-repeat: repeat-x;
307 | border-color: #dca7a7;
308 | }
309 | .progress {
310 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
311 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
312 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
313 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
314 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
315 | background-repeat: repeat-x;
316 | }
317 | .progress-bar {
318 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
319 | background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%);
320 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9));
321 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
322 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
323 | background-repeat: repeat-x;
324 | }
325 | .progress-bar-success {
326 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
327 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
328 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
329 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
330 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
331 | background-repeat: repeat-x;
332 | }
333 | .progress-bar-info {
334 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
335 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
336 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
337 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
338 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
339 | background-repeat: repeat-x;
340 | }
341 | .progress-bar-warning {
342 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
343 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
344 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
345 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
346 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
347 | background-repeat: repeat-x;
348 | }
349 | .progress-bar-danger {
350 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
351 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
352 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
353 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
354 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
355 | background-repeat: repeat-x;
356 | }
357 | .progress-bar-striped {
358 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
359 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
360 | background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
361 | }
362 | .list-group {
363 | border-radius: 4px;
364 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
365 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
366 | }
367 | .list-group-item.active,
368 | .list-group-item.active:hover,
369 | .list-group-item.active:focus {
370 | text-shadow: 0 -1px 0 #3071a9;
371 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
372 | background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%);
373 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3));
374 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
375 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
376 | background-repeat: repeat-x;
377 | border-color: #3278b3;
378 | }
379 | .panel {
380 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
381 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
382 | }
383 | .panel-default > .panel-heading {
384 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
385 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
386 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
387 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
388 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
389 | background-repeat: repeat-x;
390 | }
391 | .panel-primary > .panel-heading {
392 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
393 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
394 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
395 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
396 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
397 | background-repeat: repeat-x;
398 | }
399 | .panel-success > .panel-heading {
400 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
401 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
402 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
403 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
404 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
405 | background-repeat: repeat-x;
406 | }
407 | .panel-info > .panel-heading {
408 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
409 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
410 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
411 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
412 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
413 | background-repeat: repeat-x;
414 | }
415 | .panel-warning > .panel-heading {
416 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
417 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
418 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
419 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
420 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
421 | background-repeat: repeat-x;
422 | }
423 | .panel-danger > .panel-heading {
424 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
425 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
426 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
427 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
428 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
429 | background-repeat: repeat-x;
430 | }
431 | .well {
432 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
433 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
434 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
435 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
436 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
437 | background-repeat: repeat-x;
438 | border-color: #dcdcdc;
439 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
440 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
441 | }
442 | /*# sourceMappingURL=bootstrap-theme.css.map */
443 |
--------------------------------------------------------------------------------
/public/bootstrap-3.2.0-dist/css/bootstrap-theme.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"bootstrap-theme.css","sources":["less/theme.less","less/mixins/vendor-prefixes.less","bootstrap-theme.css","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAeA;;;;;;EAME,0CAAA;EC+CA,6FAAA;EACQ,qFAAA;EC5DT;AFiBC;;;;;;;;;;;;EC0CA,0DAAA;EACQ,kDAAA;EC7CT;AFqCC;;EAEE,wBAAA;EEnCH;AFwCD;EG/CI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EA+B2C,2BAAA;EAA2B,oBAAA;EE7BvE;AFAC;;EAEE,2BAAA;EACA,8BAAA;EEEH;AFCC;;EAEE,2BAAA;EACA,uBAAA;EECH;AFEC;;EAEE,2BAAA;EACA,wBAAA;EEAH;AFeD;EGhDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0BD;AFxBC;;EAEE,2BAAA;EACA,8BAAA;EE0BH;AFvBC;;EAEE,2BAAA;EACA,uBAAA;EEyBH;AFtBC;;EAEE,2BAAA;EACA,wBAAA;EEwBH;AFRD;EGjDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkDD;AFhDC;;EAEE,2BAAA;EACA,8BAAA;EEkDH;AF/CC;;EAEE,2BAAA;EACA,uBAAA;EEiDH;AF9CC;;EAEE,2BAAA;EACA,wBAAA;EEgDH;AF/BD;EGlDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0ED;AFxEC;;EAEE,2BAAA;EACA,8BAAA;EE0EH;AFvEC;;EAEE,2BAAA;EACA,uBAAA;EEyEH;AFtEC;;EAEE,2BAAA;EACA,wBAAA;EEwEH;AFtDD;EGnDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkGD;AFhGC;;EAEE,2BAAA;EACA,8BAAA;EEkGH;AF/FC;;EAEE,2BAAA;EACA,uBAAA;EEiGH;AF9FC;;EAEE,2BAAA;EACA,wBAAA;EEgGH;AF7ED;EGpDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0HD;AFxHC;;EAEE,2BAAA;EACA,8BAAA;EE0HH;AFvHC;;EAEE,2BAAA;EACA,uBAAA;EEyHH;AFtHC;;EAEE,2BAAA;EACA,wBAAA;EEwHH;AF7FD;;ECbE,oDAAA;EACQ,4CAAA;EC8GT;AFvFD;;EGvEI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHsEF,2BAAA;EE6FD;AF3FD;;;EG5EI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4EF,2BAAA;EEiGD;AFvFD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EJ4GA,oBAAA;EC9CA,6FAAA;EACQ,qFAAA;EC4IT;AFlGD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,0DAAA;EACQ,kDAAA;ECqJT;AF/FD;;EAEE,gDAAA;EEiGD;AF7FD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EFgOD;AFrGD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,yDAAA;EACQ,iDAAA;EC0KT;AF9GD;;EAWI,2CAAA;EEuGH;AFlGD;;;EAGE,kBAAA;EEoGD;AF1FD;EACE,+CAAA;EC3FA,4FAAA;EACQ,oFAAA;ECwLT;AFlFD;EGtJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8FD;AFzFD;EGvJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsGD;AFhGD;EGxJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8GD;AFvGD;EGzJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsHD;AFtGD;EGlKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED2QH;AFnGD;EG5KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDkRH;AFzGD;EG7KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDyRH;AF/GD;EG9KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDgSH;AFrHD;EG/KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDuSH;AF3HD;EGhLI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8SH;AF9HD;EGnJI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDoRH;AF1HD;EACE,oBAAA;EC/IA,oDAAA;EACQ,4CAAA;EC4QT;AF3HD;;;EAGE,+BAAA;EGpME,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHkMF,uBAAA;EEiID;AFvHD;ECjKE,mDAAA;EACQ,2CAAA;EC2RT;AFjHD;EG1NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8UH;AFvHD;EG3NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDqVH;AF7HD;EG5NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED4VH;AFnID;EG7NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDmWH;AFzID;EG9NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED0WH;AF/ID;EG/NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDiXH;AF9ID;EGvOI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHqOF,uBAAA;EC1LA,2FAAA;EACQ,mFAAA;EC+UT","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &:disabled,\n &[disabled] {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n &::-moz-placeholder { color: @color; // Firefox\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n",null,"// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]}
--------------------------------------------------------------------------------
/public/bootstrap-3.2.0-dist/css/bootstrap-theme.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.2.0 (http://getbootstrap.com)
3 | * Copyright 2011-2014 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-o-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#2d6ca2));background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-primary:disabled,.btn-primary[disabled]{background-color:#2d6ca2;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f3f3f3));background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:-o-linear-gradient(top,#222 0,#282828 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#222),to(#282828));background-image:linear-gradient(to bottom,#222 0,#282828 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-o-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3071a9));background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-o-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3278b3));background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);background-repeat:repeat-x;border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}
--------------------------------------------------------------------------------
/public/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noamtcohen/AudioStreamer/6fcd57dd3b74975a4efe34dcc163e63eca9b12d7/public/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/public/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noamtcohen/AudioStreamer/6fcd57dd3b74975a4efe34dcc163e63eca9b12d7/public/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/public/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noamtcohen/AudioStreamer/6fcd57dd3b74975a4efe34dcc163e63eca9b12d7/public/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/public/bootstrap-3.2.0-dist/js/bootstrap.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.2.0 (http://getbootstrap.com)
3 | * Copyright 2011-2014 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('
').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus"),f.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var e=c(d),g=e.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.divider):visible a",i=e.find('[role="menu"]'+h+', [role="listbox"]'+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j').appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;e?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(150):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var f=function(){c.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",f).emulateTransitionEnd(150):f()}else b&&b()},c.prototype.checkScrollbar=function(){document.body.clientWidth>=window.innerWidth||(this.scrollbarWidth=this.scrollbarWidth||this.measureScrollbar())},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.scrollbarWidth&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right","")},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};c.VERSION="3.2.0",c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var c=a.contains(document.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!c)return;var d=this,e=this.tip(),f=this.getUID(this.type);this.setContent(),e.attr("id",f),this.$element.attr("aria-describedby",f),this.options.animation&&e.addClass("fade");var g="function"==typeof this.options.placement?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,h=/\s?auto?\s?/i,i=h.test(g);i&&(g=g.replace(h,"")||"top"),e.detach().css({top:0,left:0,display:"block"}).addClass(g).data("bs."+this.type,this),this.options.container?e.appendTo(this.options.container):e.insertAfter(this.$element);var j=this.getPosition(),k=e[0].offsetWidth,l=e[0].offsetHeight;if(i){var m=g,n=this.$element.parent(),o=this.getPosition(n);g="bottom"==g&&j.top+j.height+l-o.scroll>o.height?"top":"top"==g&&j.top-o.scroll-l<0?"bottom":"right"==g&&j.right+k>o.width?"left":"left"==g&&j.left-kg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.2.0",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").empty()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},c.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){var e=a.proxy(this.process,this);this.$body=a("body"),this.$scrollElement=a(a(c).is("body")?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",e),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.2.0",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b="offset",c=0;a.isWindow(this.$scrollElement[0])||(b="position",c=this.$scrollElement.scrollTop()),this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight();var d=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+c,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){d.offsets.push(this[0]),d.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.2.0",c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.closest("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},c.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one("bsTransitionEnd",e).emulateTransitionEnd(150):e(),f.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(c){c.preventDefault(),b.call(a(this),"show")})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.2.0",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=a(document).height(),d=this.$target.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=b-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){null!=this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:b-this.$element.height()-h}))}}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},d.offsetBottom&&(d.offset.bottom=d.offsetBottom),d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
--------------------------------------------------------------------------------
/public/img/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/noamtcohen/AudioStreamer/6fcd57dd3b74975a4efe34dcc163e63eca9b12d7/public/img/icon.png
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Audio Streamer
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/public/js/binary.js:
--------------------------------------------------------------------------------
1 | /*! binary.js build:0.2.1, development. Copyright(c) 2012 Eric Zhang MIT Licensed */
2 | (function(exports){
3 | var binaryFeatures = {};
4 | binaryFeatures.useBlobBuilder = (function(){
5 | try {
6 | new Blob([]);
7 | return false;
8 | } catch (e) {
9 | return true;
10 | }
11 | })();
12 |
13 | binaryFeatures.useArrayBufferView = !binaryFeatures.useBlobBuilder && (function(){
14 | try {
15 | return (new Blob([new Uint8Array([])])).size === 0;
16 | } catch (e) {
17 | return true;
18 | }
19 | })();
20 | binaryFeatures.supportsBinaryWebsockets = (function(){
21 | return true;
22 | try {
23 | var wstest = new WebSocket('ws://null');
24 | wstest.onerror = function(){};
25 | if (typeof(wstest.binaryType) !== "undefined") {
26 | return true;
27 | } else {
28 | return false;
29 | }
30 | wstest.close();
31 | wstest = null;
32 | } catch (e) {
33 | return false;
34 | }
35 | })();
36 |
37 | exports.binaryFeatures = binaryFeatures;
38 | exports.BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder || window.BlobBuilder;
39 |
40 | function BufferBuilder(){
41 | this._pieces = [];
42 | this._parts = [];
43 | }
44 |
45 | BufferBuilder.prototype.append = function(data) {
46 | if(typeof data === 'number') {
47 | this._pieces.push(data);
48 | } else {
49 | this.flush();
50 | this._parts.push(data);
51 | }
52 | };
53 |
54 | BufferBuilder.prototype.flush = function() {
55 | if (this._pieces.length > 0) {
56 | var buf = new Uint8Array(this._pieces);
57 | if(!binaryFeatures.useArrayBufferView) {
58 | buf = buf.buffer;
59 | }
60 | this._parts.push(buf);
61 | this._pieces = [];
62 | }
63 | };
64 |
65 | BufferBuilder.prototype.getBuffer = function() {
66 | this.flush();
67 | if(binaryFeatures.useBlobBuilder) {
68 | var builder = new BlobBuilder();
69 | for(var i = 0, ii = this._parts.length; i < ii; i++) {
70 | builder.append(this._parts[i]);
71 | }
72 | return builder.getBlob();
73 | } else {
74 | return new Blob(this._parts);
75 | }
76 | };
77 | exports.BinaryPack = {
78 | unpack: function(data){
79 | var unpacker = new Unpacker(data);
80 | return unpacker.unpack();
81 | },
82 | pack: function(data){
83 | var packer = new Packer();
84 | packer.pack(data);
85 | var buffer = packer.getBuffer();
86 | return buffer;
87 | }
88 | };
89 |
90 | function Unpacker (data){
91 | // Data is ArrayBuffer
92 | this.index = 0;
93 | this.dataBuffer = data;
94 | this.dataView = new Uint8Array(this.dataBuffer);
95 | this.length = this.dataBuffer.byteLength;
96 | }
97 |
98 |
99 | Unpacker.prototype.unpack = function(){
100 | var type = this.unpack_uint8();
101 | if (type < 0x80){
102 | var positive_fixnum = type;
103 | return positive_fixnum;
104 | } else if ((type ^ 0xe0) < 0x20){
105 | var negative_fixnum = (type ^ 0xe0) - 0x20;
106 | return negative_fixnum;
107 | }
108 | var size;
109 | if ((size = type ^ 0xa0) <= 0x0f){
110 | return this.unpack_raw(size);
111 | } else if ((size = type ^ 0xb0) <= 0x0f){
112 | return this.unpack_string(size);
113 | } else if ((size = type ^ 0x90) <= 0x0f){
114 | return this.unpack_array(size);
115 | } else if ((size = type ^ 0x80) <= 0x0f){
116 | return this.unpack_map(size);
117 | }
118 | switch(type){
119 | case 0xc0:
120 | return null;
121 | case 0xc1:
122 | return undefined;
123 | case 0xc2:
124 | return false;
125 | case 0xc3:
126 | return true;
127 | case 0xca:
128 | return this.unpack_float();
129 | case 0xcb:
130 | return this.unpack_double();
131 | case 0xcc:
132 | return this.unpack_uint8();
133 | case 0xcd:
134 | return this.unpack_uint16();
135 | case 0xce:
136 | return this.unpack_uint32();
137 | case 0xcf:
138 | return this.unpack_uint64();
139 | case 0xd0:
140 | return this.unpack_int8();
141 | case 0xd1:
142 | return this.unpack_int16();
143 | case 0xd2:
144 | return this.unpack_int32();
145 | case 0xd3:
146 | return this.unpack_int64();
147 | case 0xd4:
148 | return undefined;
149 | case 0xd5:
150 | return undefined;
151 | case 0xd6:
152 | return undefined;
153 | case 0xd7:
154 | return undefined;
155 | case 0xd8:
156 | size = this.unpack_uint16();
157 | return this.unpack_string(size);
158 | case 0xd9:
159 | size = this.unpack_uint32();
160 | return this.unpack_string(size);
161 | case 0xda:
162 | size = this.unpack_uint16();
163 | return this.unpack_raw(size);
164 | case 0xdb:
165 | size = this.unpack_uint32();
166 | return this.unpack_raw(size);
167 | case 0xdc:
168 | size = this.unpack_uint16();
169 | return this.unpack_array(size);
170 | case 0xdd:
171 | size = this.unpack_uint32();
172 | return this.unpack_array(size);
173 | case 0xde:
174 | size = this.unpack_uint16();
175 | return this.unpack_map(size);
176 | case 0xdf:
177 | size = this.unpack_uint32();
178 | return this.unpack_map(size);
179 | }
180 | }
181 |
182 | Unpacker.prototype.unpack_uint8 = function(){
183 | var byte = this.dataView[this.index] & 0xff;
184 | this.index++;
185 | return byte;
186 | };
187 |
188 | Unpacker.prototype.unpack_uint16 = function(){
189 | var bytes = this.read(2);
190 | var uint16 =
191 | ((bytes[0] & 0xff) * 256) + (bytes[1] & 0xff);
192 | this.index += 2;
193 | return uint16;
194 | }
195 |
196 | Unpacker.prototype.unpack_uint32 = function(){
197 | var bytes = this.read(4);
198 | var uint32 =
199 | ((bytes[0] * 256 +
200 | bytes[1]) * 256 +
201 | bytes[2]) * 256 +
202 | bytes[3];
203 | this.index += 4;
204 | return uint32;
205 | }
206 |
207 | Unpacker.prototype.unpack_uint64 = function(){
208 | var bytes = this.read(8);
209 | var uint64 =
210 | ((((((bytes[0] * 256 +
211 | bytes[1]) * 256 +
212 | bytes[2]) * 256 +
213 | bytes[3]) * 256 +
214 | bytes[4]) * 256 +
215 | bytes[5]) * 256 +
216 | bytes[6]) * 256 +
217 | bytes[7];
218 | this.index += 8;
219 | return uint64;
220 | }
221 |
222 |
223 | Unpacker.prototype.unpack_int8 = function(){
224 | var uint8 = this.unpack_uint8();
225 | return (uint8 < 0x80 ) ? uint8 : uint8 - (1 << 8);
226 | };
227 |
228 | Unpacker.prototype.unpack_int16 = function(){
229 | var uint16 = this.unpack_uint16();
230 | return (uint16 < 0x8000 ) ? uint16 : uint16 - (1 << 16);
231 | }
232 |
233 | Unpacker.prototype.unpack_int32 = function(){
234 | var uint32 = this.unpack_uint32();
235 | return (uint32 < Math.pow(2, 31) ) ? uint32 :
236 | uint32 - Math.pow(2, 32);
237 | }
238 |
239 | Unpacker.prototype.unpack_int64 = function(){
240 | var uint64 = this.unpack_uint64();
241 | return (uint64 < Math.pow(2, 63) ) ? uint64 :
242 | uint64 - Math.pow(2, 64);
243 | }
244 |
245 | Unpacker.prototype.unpack_raw = function(size){
246 | if ( this.length < this.index + size){
247 | throw new Error('BinaryPackFailure: index is out of range'
248 | + ' ' + this.index + ' ' + size + ' ' + this.length);
249 | }
250 | var buf = this.dataBuffer.slice(this.index, this.index + size);
251 | this.index += size;
252 |
253 | //buf = util.bufferToString(buf);
254 |
255 | return buf;
256 | }
257 |
258 | Unpacker.prototype.unpack_string = function(size){
259 | var bytes = this.read(size);
260 | var i = 0, str = '', c, code;
261 | while(i < size){
262 | c = bytes[i];
263 | if ( c < 128){
264 | str += String.fromCharCode(c);
265 | i++;
266 | } else if ((c ^ 0xc0) < 32){
267 | code = ((c ^ 0xc0) << 6) | (bytes[i+1] & 63);
268 | str += String.fromCharCode(code);
269 | i += 2;
270 | } else {
271 | code = ((c & 15) << 12) | ((bytes[i+1] & 63) << 6) |
272 | (bytes[i+2] & 63);
273 | str += String.fromCharCode(code);
274 | i += 3;
275 | }
276 | }
277 | this.index += size;
278 | return str;
279 | }
280 |
281 | Unpacker.prototype.unpack_array = function(size){
282 | var objects = new Array(size);
283 | for(var i = 0; i < size ; i++){
284 | objects[i] = this.unpack();
285 | }
286 | return objects;
287 | }
288 |
289 | Unpacker.prototype.unpack_map = function(size){
290 | var map = {};
291 | for(var i = 0; i < size ; i++){
292 | var key = this.unpack();
293 | var value = this.unpack();
294 | map[key] = value;
295 | }
296 | return map;
297 | }
298 |
299 | Unpacker.prototype.unpack_float = function(){
300 | var uint32 = this.unpack_uint32();
301 | var sign = uint32 >> 31;
302 | var exp = ((uint32 >> 23) & 0xff) - 127;
303 | var fraction = ( uint32 & 0x7fffff ) | 0x800000;
304 | return (sign == 0 ? 1 : -1) *
305 | fraction * Math.pow(2, exp - 23);
306 | }
307 |
308 | Unpacker.prototype.unpack_double = function(){
309 | var h32 = this.unpack_uint32();
310 | var l32 = this.unpack_uint32();
311 | var sign = h32 >> 31;
312 | var exp = ((h32 >> 20) & 0x7ff) - 1023;
313 | var hfrac = ( h32 & 0xfffff ) | 0x100000;
314 | var frac = hfrac * Math.pow(2, exp - 20) +
315 | l32 * Math.pow(2, exp - 52);
316 | return (sign == 0 ? 1 : -1) * frac;
317 | }
318 |
319 | Unpacker.prototype.read = function(length){
320 | var j = this.index;
321 | if (j + length <= this.length) {
322 | return this.dataView.subarray(j, j + length);
323 | } else {
324 | throw new Error('BinaryPackFailure: read index out of range');
325 | }
326 | }
327 |
328 | function Packer(){
329 | this.bufferBuilder = new BufferBuilder();
330 | }
331 |
332 | Packer.prototype.getBuffer = function(){
333 | return this.bufferBuilder.getBuffer();
334 | }
335 |
336 | Packer.prototype.pack = function(value){
337 | var type = typeof(value);
338 | if (type == 'string'){
339 | this.pack_string(value);
340 | } else if (type == 'number'){
341 | if (Math.floor(value) === value){
342 | this.pack_integer(value);
343 | } else{
344 | this.pack_double(value);
345 | }
346 | } else if (type == 'boolean'){
347 | if (value === true){
348 | this.bufferBuilder.append(0xc3);
349 | } else if (value === false){
350 | this.bufferBuilder.append(0xc2);
351 | }
352 | } else if (type == 'undefined'){
353 | this.bufferBuilder.append(0xc0);
354 | } else if (type == 'object'){
355 | if (value === null){
356 | this.bufferBuilder.append(0xc0);
357 | } else {
358 | var constructor = value.constructor;
359 | if (constructor == Array){
360 | this.pack_array(value);
361 | } else if (constructor == Blob || constructor == File) {
362 | this.pack_bin(value);
363 | } else if (constructor == ArrayBuffer) {
364 | if(binaryFeatures.useArrayBufferView) {
365 | this.pack_bin(new Uint8Array(value));
366 | } else {
367 | this.pack_bin(value);
368 | }
369 | } else if ('BYTES_PER_ELEMENT' in value){
370 | if(binaryFeatures.useArrayBufferView) {
371 | this.pack_bin(new Uint8Array(value.buffer));
372 | } else {
373 | this.pack_bin(value.buffer);
374 | }
375 | } else if (constructor == Object){
376 | this.pack_object(value);
377 | } else if (constructor == Date){
378 | this.pack_string(value.toString());
379 | } else if (typeof value.toBinaryPack == 'function'){
380 | this.bufferBuilder.append(value.toBinaryPack());
381 | } else {
382 | throw new Error('Type "' + constructor.toString() + '" not yet supported');
383 | }
384 | }
385 | } else {
386 | throw new Error('Type "' + type + '" not yet supported');
387 | }
388 | this.bufferBuilder.flush();
389 | }
390 |
391 |
392 | Packer.prototype.pack_bin = function(blob){
393 | var length = blob.length || blob.byteLength || blob.size;
394 | if (length <= 0x0f){
395 | this.pack_uint8(0xa0 + length);
396 | } else if (length <= 0xffff){
397 | this.bufferBuilder.append(0xda) ;
398 | this.pack_uint16(length);
399 | } else if (length <= 0xffffffff){
400 | this.bufferBuilder.append(0xdb);
401 | this.pack_uint32(length);
402 | } else{
403 | throw new Error('Invalid length');
404 | return;
405 | }
406 | this.bufferBuilder.append(blob);
407 | }
408 |
409 | Packer.prototype.pack_string = function(str){
410 | var length = utf8Length(str);
411 |
412 | if (length <= 0x0f){
413 | this.pack_uint8(0xb0 + length);
414 | } else if (length <= 0xffff){
415 | this.bufferBuilder.append(0xd8) ;
416 | this.pack_uint16(length);
417 | } else if (length <= 0xffffffff){
418 | this.bufferBuilder.append(0xd9);
419 | this.pack_uint32(length);
420 | } else{
421 | throw new Error('Invalid length');
422 | return;
423 | }
424 | this.bufferBuilder.append(str);
425 | }
426 |
427 | Packer.prototype.pack_array = function(ary){
428 | var length = ary.length;
429 | if (length <= 0x0f){
430 | this.pack_uint8(0x90 + length);
431 | } else if (length <= 0xffff){
432 | this.bufferBuilder.append(0xdc)
433 | this.pack_uint16(length);
434 | } else if (length <= 0xffffffff){
435 | this.bufferBuilder.append(0xdd);
436 | this.pack_uint32(length);
437 | } else{
438 | throw new Error('Invalid length');
439 | }
440 | for(var i = 0; i < length ; i++){
441 | this.pack(ary[i]);
442 | }
443 | }
444 |
445 | Packer.prototype.pack_integer = function(num){
446 | if ( -0x20 <= num && num <= 0x7f){
447 | this.bufferBuilder.append(num & 0xff);
448 | } else if (0x00 <= num && num <= 0xff){
449 | this.bufferBuilder.append(0xcc);
450 | this.pack_uint8(num);
451 | } else if (-0x80 <= num && num <= 0x7f){
452 | this.bufferBuilder.append(0xd0);
453 | this.pack_int8(num);
454 | } else if ( 0x0000 <= num && num <= 0xffff){
455 | this.bufferBuilder.append(0xcd);
456 | this.pack_uint16(num);
457 | } else if (-0x8000 <= num && num <= 0x7fff){
458 | this.bufferBuilder.append(0xd1);
459 | this.pack_int16(num);
460 | } else if ( 0x00000000 <= num && num <= 0xffffffff){
461 | this.bufferBuilder.append(0xce);
462 | this.pack_uint32(num);
463 | } else if (-0x80000000 <= num && num <= 0x7fffffff){
464 | this.bufferBuilder.append(0xd2);
465 | this.pack_int32(num);
466 | } else if (-0x8000000000000000 <= num && num <= 0x7FFFFFFFFFFFFFFF){
467 | this.bufferBuilder.append(0xd3);
468 | this.pack_int64(num);
469 | } else if (0x0000000000000000 <= num && num <= 0xFFFFFFFFFFFFFFFF){
470 | this.bufferBuilder.append(0xcf);
471 | this.pack_uint64(num);
472 | } else{
473 | throw new Error('Invalid integer');
474 | }
475 | }
476 |
477 | Packer.prototype.pack_double = function(num){
478 | var sign = 0;
479 | if (num < 0){
480 | sign = 1;
481 | num = -num;
482 | }
483 | var exp = Math.floor(Math.log(num) / Math.LN2);
484 | var frac0 = num / Math.pow(2, exp) - 1;
485 | var frac1 = Math.floor(frac0 * Math.pow(2, 52));
486 | var b32 = Math.pow(2, 32);
487 | var h32 = (sign << 31) | ((exp+1023) << 20) |
488 | (frac1 / b32) & 0x0fffff;
489 | var l32 = frac1 % b32;
490 | this.bufferBuilder.append(0xcb);
491 | this.pack_int32(h32);
492 | this.pack_int32(l32);
493 | }
494 |
495 | Packer.prototype.pack_object = function(obj){
496 | var keys = Object.keys(obj);
497 | var length = keys.length;
498 | if (length <= 0x0f){
499 | this.pack_uint8(0x80 + length);
500 | } else if (length <= 0xffff){
501 | this.bufferBuilder.append(0xde);
502 | this.pack_uint16(length);
503 | } else if (length <= 0xffffffff){
504 | this.bufferBuilder.append(0xdf);
505 | this.pack_uint32(length);
506 | } else{
507 | throw new Error('Invalid length');
508 | }
509 | for(var prop in obj){
510 | if (obj.hasOwnProperty(prop)){
511 | this.pack(prop);
512 | this.pack(obj[prop]);
513 | }
514 | }
515 | }
516 |
517 | Packer.prototype.pack_uint8 = function(num){
518 | this.bufferBuilder.append(num);
519 | }
520 |
521 | Packer.prototype.pack_uint16 = function(num){
522 | this.bufferBuilder.append(num >> 8);
523 | this.bufferBuilder.append(num & 0xff);
524 | }
525 |
526 | Packer.prototype.pack_uint32 = function(num){
527 | var n = num & 0xffffffff;
528 | this.bufferBuilder.append((n & 0xff000000) >>> 24);
529 | this.bufferBuilder.append((n & 0x00ff0000) >>> 16);
530 | this.bufferBuilder.append((n & 0x0000ff00) >>> 8);
531 | this.bufferBuilder.append((n & 0x000000ff));
532 | }
533 |
534 | Packer.prototype.pack_uint64 = function(num){
535 | var high = num / Math.pow(2, 32);
536 | var low = num % Math.pow(2, 32);
537 | this.bufferBuilder.append((high & 0xff000000) >>> 24);
538 | this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
539 | this.bufferBuilder.append((high & 0x0000ff00) >>> 8);
540 | this.bufferBuilder.append((high & 0x000000ff));
541 | this.bufferBuilder.append((low & 0xff000000) >>> 24);
542 | this.bufferBuilder.append((low & 0x00ff0000) >>> 16);
543 | this.bufferBuilder.append((low & 0x0000ff00) >>> 8);
544 | this.bufferBuilder.append((low & 0x000000ff));
545 | }
546 |
547 | Packer.prototype.pack_int8 = function(num){
548 | this.bufferBuilder.append(num & 0xff);
549 | }
550 |
551 | Packer.prototype.pack_int16 = function(num){
552 | this.bufferBuilder.append((num & 0xff00) >> 8);
553 | this.bufferBuilder.append(num & 0xff);
554 | }
555 |
556 | Packer.prototype.pack_int32 = function(num){
557 | this.bufferBuilder.append((num >>> 24) & 0xff);
558 | this.bufferBuilder.append((num & 0x00ff0000) >>> 16);
559 | this.bufferBuilder.append((num & 0x0000ff00) >>> 8);
560 | this.bufferBuilder.append((num & 0x000000ff));
561 | }
562 |
563 | Packer.prototype.pack_int64 = function(num){
564 | var high = Math.floor(num / Math.pow(2, 32));
565 | var low = num % Math.pow(2, 32);
566 | this.bufferBuilder.append((high & 0xff000000) >>> 24);
567 | this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
568 | this.bufferBuilder.append((high & 0x0000ff00) >>> 8);
569 | this.bufferBuilder.append((high & 0x000000ff));
570 | this.bufferBuilder.append((low & 0xff000000) >>> 24);
571 | this.bufferBuilder.append((low & 0x00ff0000) >>> 16);
572 | this.bufferBuilder.append((low & 0x0000ff00) >>> 8);
573 | this.bufferBuilder.append((low & 0x000000ff));
574 | }
575 |
576 | function _utf8Replace(m){
577 | var code = m.charCodeAt(0);
578 |
579 | if(code <= 0x7ff) return '00';
580 | if(code <= 0xffff) return '000';
581 | if(code <= 0x1fffff) return '0000';
582 | if(code <= 0x3ffffff) return '00000';
583 | return '000000';
584 | }
585 |
586 | function utf8Length(str){
587 | if (str.length > 600) {
588 | // Blob method faster for large strings
589 | return (new Blob([str])).size;
590 | } else {
591 | return str.replace(/[^\u0000-\u007F]/g, _utf8Replace).length;
592 | }
593 | }
594 | /**
595 | * Light EventEmitter. Ported from Node.js/events.js
596 | * Eric Zhang
597 | */
598 |
599 | /**
600 | * EventEmitter class
601 | * Creates an object with event registering and firing methods
602 | */
603 | function EventEmitter() {
604 | // Initialise required storage variables
605 | this._events = {};
606 | }
607 |
608 | var isArray = Array.isArray;
609 |
610 |
611 | EventEmitter.prototype.addListener = function(type, listener, scope, once) {
612 | if ('function' !== typeof listener) {
613 | throw new Error('addListener only takes instances of Function');
614 | }
615 |
616 | // To avoid recursion in the case that type == "newListeners"! Before
617 | // adding it to the listeners, first emit "newListeners".
618 | this.emit('newListener', type, typeof listener.listener === 'function' ?
619 | listener.listener : listener);
620 |
621 | if (!this._events[type]) {
622 | // Optimize the case of one listener. Don't need the extra array object.
623 | this._events[type] = listener;
624 | } else if (isArray(this._events[type])) {
625 |
626 | // If we've already got an array, just append.
627 | this._events[type].push(listener);
628 |
629 | } else {
630 | // Adding the second element, need to change to array.
631 | this._events[type] = [this._events[type], listener];
632 | }
633 |
634 | };
635 |
636 | EventEmitter.prototype.on = EventEmitter.prototype.addListener;
637 |
638 | EventEmitter.prototype.once = function(type, listener, scope) {
639 | if ('function' !== typeof listener) {
640 | throw new Error('.once only takes instances of Function');
641 | }
642 |
643 | var self = this;
644 | function g() {
645 | self.removeListener(type, g);
646 | listener.apply(this, arguments);
647 | };
648 |
649 | g.listener = listener;
650 | self.on(type, g);
651 |
652 | return this;
653 | };
654 |
655 | EventEmitter.prototype.removeListener = function(type, listener, scope) {
656 | if ('function' !== typeof listener) {
657 | throw new Error('removeListener only takes instances of Function');
658 | }
659 |
660 | // does not use listeners(), so no side effect of creating _events[type]
661 | if (!this._events[type]) return this;
662 |
663 | var list = this._events[type];
664 |
665 | if (isArray(list)) {
666 | var position = -1;
667 | for (var i = 0, length = list.length; i < length; i++) {
668 | if (list[i] === listener ||
669 | (list[i].listener && list[i].listener === listener))
670 | {
671 | position = i;
672 | break;
673 | }
674 | }
675 |
676 | if (position < 0) return this;
677 | list.splice(position, 1);
678 | if (list.length == 0)
679 | delete this._events[type];
680 | } else if (list === listener ||
681 | (list.listener && list.listener === listener))
682 | {
683 | delete this._events[type];
684 | }
685 |
686 | return this;
687 | };
688 |
689 |
690 | EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
691 |
692 |
693 | EventEmitter.prototype.removeAllListeners = function(type) {
694 | if (arguments.length === 0) {
695 | this._events = {};
696 | return this;
697 | }
698 |
699 | // does not use listeners(), so no side effect of creating _events[type]
700 | if (type && this._events && this._events[type]) this._events[type] = null;
701 | return this;
702 | };
703 |
704 | EventEmitter.prototype.listeners = function(type) {
705 | if (!this._events[type]) this._events[type] = [];
706 | if (!isArray(this._events[type])) {
707 | this._events[type] = [this._events[type]];
708 | }
709 | return this._events[type];
710 | };
711 |
712 | EventEmitter.prototype.emit = function(type) {
713 | var type = arguments[0];
714 | var handler = this._events[type];
715 | if (!handler) return false;
716 |
717 | if (typeof handler == 'function') {
718 | switch (arguments.length) {
719 | // fast cases
720 | case 1:
721 | handler.call(this);
722 | break;
723 | case 2:
724 | handler.call(this, arguments[1]);
725 | break;
726 | case 3:
727 | handler.call(this, arguments[1], arguments[2]);
728 | break;
729 | // slower
730 | default:
731 | var l = arguments.length;
732 | var args = new Array(l - 1);
733 | for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
734 | handler.apply(this, args);
735 | }
736 | return true;
737 |
738 | } else if (isArray(handler)) {
739 | var l = arguments.length;
740 | var args = new Array(l - 1);
741 | for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
742 |
743 | var listeners = handler.slice();
744 | for (var i = 0, l = listeners.length; i < l; i++) {
745 | listeners[i].apply(this, args);
746 | }
747 | return true;
748 | } else {
749 | return false;
750 | }
751 | };
752 |
753 |
754 |
755 |
756 | var util = {
757 | inherits: function(ctor, superCtor) {
758 | ctor.super_ = superCtor;
759 | ctor.prototype = Object.create(superCtor.prototype, {
760 | constructor: {
761 | value: ctor,
762 | enumerable: false,
763 | writable: true,
764 | configurable: true
765 | }
766 | });
767 | },
768 | extend: function(dest, source) {
769 | for(var key in source) {
770 | if(source.hasOwnProperty(key)) {
771 | dest[key] = source[key];
772 | }
773 | }
774 | return dest;
775 | },
776 | pack: BinaryPack.pack,
777 | unpack: BinaryPack.unpack,
778 | setZeroTimeout: (function(global) {
779 | var timeouts = [];
780 | var messageName = 'zero-timeout-message';
781 |
782 | // Like setTimeout, but only takes a function argument. There's
783 | // no time argument (always zero) and no arguments (you have to
784 | // use a closure).
785 | function setZeroTimeoutPostMessage(fn) {
786 | timeouts.push(fn);
787 | global.postMessage(messageName, '*');
788 | }
789 |
790 | function handleMessage(event) {
791 | if (event.source == global && event.data == messageName) {
792 | if (event.stopPropagation) {
793 | event.stopPropagation();
794 | }
795 | if (timeouts.length) {
796 | timeouts.shift()();
797 | }
798 | }
799 | }
800 | if (global.addEventListener) {
801 | global.addEventListener('message', handleMessage, true);
802 | } else if (global.attachEvent) {
803 | global.attachEvent('onmessage', handleMessage);
804 | }
805 | return setZeroTimeoutPostMessage;
806 | }(this))
807 | };
808 |
809 |
810 |
811 | function Stream() {
812 | EventEmitter.call(this);
813 | }
814 |
815 | util.inherits(Stream, EventEmitter);
816 |
817 | Stream.prototype.pipe = function(dest, options) {
818 | var source = this;
819 |
820 | function ondata(chunk) {
821 | if (dest.writable) {
822 | if (false === dest.write(chunk) && source.pause) {
823 | source.pause();
824 | }
825 | }
826 | }
827 |
828 | source.on('data', ondata);
829 |
830 | function ondrain() {
831 | if (source.readable && source.resume) {
832 | source.resume();
833 | }
834 | }
835 |
836 | dest.on('drain', ondrain);
837 |
838 | // If the 'end' option is not supplied, dest.end() will be called when
839 | // source gets the 'end' or 'close' events. Only dest.end() once.
840 | if (!dest._isStdio && (!options || options.end !== false)) {
841 | source.on('end', onend);
842 | source.on('close', onclose);
843 | }
844 |
845 | var didOnEnd = false;
846 | function onend() {
847 | if (didOnEnd) return;
848 | didOnEnd = true;
849 |
850 | dest.end();
851 | }
852 |
853 |
854 | function onclose() {
855 | if (didOnEnd) return;
856 | didOnEnd = true;
857 |
858 | dest.destroy();
859 | }
860 |
861 | // don't leave dangling pipes when there are errors.
862 | function onerror(er) {
863 | cleanup();
864 | if (this.listeners('error').length === 0) {
865 | throw er; // Unhandled stream error in pipe.
866 | }
867 | }
868 |
869 | source.on('error', onerror);
870 | dest.on('error', onerror);
871 |
872 | // remove all the event listeners that were added.
873 | function cleanup() {
874 | source.removeListener('data', ondata);
875 | dest.removeListener('drain', ondrain);
876 |
877 | source.removeListener('end', onend);
878 | source.removeListener('close', onclose);
879 |
880 | source.removeListener('error', onerror);
881 | dest.removeListener('error', onerror);
882 |
883 | source.removeListener('end', cleanup);
884 | source.removeListener('close', cleanup);
885 |
886 | dest.removeListener('end', cleanup);
887 | dest.removeListener('close', cleanup);
888 | }
889 |
890 | source.on('end', cleanup);
891 | source.on('close', cleanup);
892 |
893 | dest.on('end', cleanup);
894 | dest.on('close', cleanup);
895 |
896 | dest.emit('pipe', source);
897 |
898 | // Allow for unix-like usage: A.pipe(B).pipe(C)
899 | return dest;
900 | };
901 | function BlobReadStream(source, options){
902 | Stream.call(this);
903 |
904 | options = util.extend({
905 | readDelay: 0,
906 | paused: false
907 | }, options);
908 |
909 | this._source = source;
910 | this._start = 0;
911 | this._readChunkSize = options.chunkSize || source.size;
912 | this._readDelay = options.readDelay;
913 |
914 | this.readable = true;
915 | this.paused = options.paused;
916 |
917 | this._read();
918 | }
919 |
920 | util.inherits(BlobReadStream, Stream);
921 |
922 |
923 | BlobReadStream.prototype.pause = function(){
924 | this.paused = true;
925 | };
926 |
927 | BlobReadStream.prototype.resume = function(){
928 | this.paused = false;
929 | this._read();
930 | };
931 |
932 | BlobReadStream.prototype.destroy = function(){
933 | this.readable = false;
934 | clearTimeout(this._timeoutId);
935 | };
936 |
937 | BlobReadStream.prototype._read = function(){
938 |
939 | var self = this;
940 |
941 | function emitReadChunk(){
942 | self._emitReadChunk();
943 | }
944 |
945 | var readDelay = this._readDelay;
946 | if (readDelay !== 0){
947 | this._timeoutId = setTimeout(emitReadChunk, readDelay);
948 | } else {
949 | util.setZeroTimeout(emitReadChunk);
950 | }
951 |
952 | };
953 |
954 | BlobReadStream.prototype._emitReadChunk = function(){
955 |
956 | if(this.paused || !this.readable) return;
957 |
958 | var chunkSize = Math.min(this._source.size - this._start, this._readChunkSize);
959 |
960 | if(chunkSize === 0){
961 | this.readable = false;
962 | this.emit("end");
963 | return;
964 | }
965 |
966 | var sourceEnd = this._start + chunkSize;
967 | var chunk = (this._source.slice || this._source.webkitSlice || this._source.mozSlice).call(this._source, this._start, sourceEnd);
968 |
969 | this._start = sourceEnd;
970 | this._read();
971 |
972 | this.emit("data", chunk);
973 |
974 | };
975 |
976 | /*
977 |
978 |
979 |
980 |
981 | function BlobWriteStream(options){
982 |
983 | stream.Stream.call(this);
984 |
985 | options = _.extend({
986 | onFull: onFull,
987 | onEnd: function(){},
988 | minBlockAllocSize: 0,
989 | drainDelay:0
990 | }, options);
991 |
992 | this._onFull = options.onFull;
993 | this._onEnd = options.onEnd;
994 | this._onWrite = options.onWrite;
995 |
996 | this._minBlockAllocSize = options.minBlockAllocSize;
997 | this._maxBlockAllocSize = options.maxBlockAllocSize;
998 | this._drainDelay = options.drainDelay;
999 |
1000 | this._buffer = new Buffer(options.minBlockAllocSize);
1001 | this._destination = this._buffer;
1002 | this._destinationPos = 0;
1003 |
1004 | this._writeQueue = [];
1005 | this._pendingOnFull = false;
1006 | this._pendingQueueDrain = false;
1007 |
1008 | this.writable = true;
1009 | this.bytesWritten = 0;
1010 | }
1011 |
1012 | util.inherits(BlobWriteStream, stream.Stream);
1013 |
1014 | BlobWriteStream.prototype.getBuffer = function(){
1015 | return this._buffer;
1016 | };
1017 |
1018 | BlobWriteStream.prototype.write = function(data, encoding){
1019 |
1020 | if(!this.writable){
1021 | throw new Error("stream is not writable");
1022 | }
1023 |
1024 | if(!Buffer.isBuffer(data)){
1025 | data = new Buffer(data, encoding);
1026 | }
1027 |
1028 | if(data.length){
1029 | this._writeQueue.push(data);
1030 | }
1031 |
1032 | this._commit();
1033 |
1034 | return this._writeQueue.length === 0;
1035 | };
1036 |
1037 | BlobWriteStream.prototype._commit = function(){
1038 |
1039 | var self = this;
1040 |
1041 | var destination = this._destination;
1042 | var writeQueue = this._writeQueue;
1043 |
1044 | var startDestinationPos = this._destinationPos;
1045 |
1046 | while(writeQueue.length && destination.length){
1047 |
1048 | var head = writeQueue[0];
1049 |
1050 | var copySize = Math.min(destination.length, head.length);
1051 |
1052 | head.copy(destination, 0, 0, copySize);
1053 |
1054 | head = head.slice(copySize);
1055 | destination = destination.slice(copySize);
1056 |
1057 | this.bytesWritten += copySize;
1058 | this._destinationPos += copySize;
1059 |
1060 | if(head.length === 0){
1061 | writeQueue.shift();
1062 | }
1063 | else{
1064 | writeQueue[0] = head;
1065 | }
1066 | }
1067 |
1068 | this._destination = destination;
1069 |
1070 | bytesCommitted = this._destinationPos - startDestinationPos;
1071 | if(bytesCommitted){
1072 | if(this._onWrite){
1073 |
1074 | if(writeQueue.length){
1075 | this._pendingQueueDrain = true;
1076 | }
1077 |
1078 | // By locking destination the buffer is frozen and the onWrite
1079 | // callback cannot miss any write commits
1080 | this._destination = emptyBuffer;
1081 |
1082 | var consumer = this._onWrite;
1083 | this._onWrite = null;
1084 |
1085 | consumer.call(this, function(nextCallback){
1086 | util.setZeroTimeout(function(){
1087 | self._destination = destination;
1088 | self._onWrite = nextCallback;
1089 | self._commit();
1090 | });
1091 | }, consumer);
1092 |
1093 | return;
1094 | }
1095 | }
1096 |
1097 | if(writeQueue.length){
1098 |
1099 | this._pendingQueueDrain = true;
1100 | this._growBuffer();
1101 | }
1102 | else if(this._pendingQueueDrain){
1103 |
1104 | this._pendingQueueDrain = false;
1105 |
1106 | if(this._drainDelay !== 0){
1107 | setTimeout(function(){
1108 | self.emit("drain");
1109 | }, this._drainDelay);
1110 | }
1111 | else{
1112 | util.setZeroTimeout(function(){
1113 | self.emit("drain");
1114 | });
1115 | }
1116 | }
1117 | };
1118 |
1119 | BlobWriteStream.prototype._growBuffer = function(){
1120 |
1121 | var self = this;
1122 | var writeQueue = this._writeQueue;
1123 |
1124 | var requestSize = this._minBlockAllocSize;
1125 |
1126 | var maxBlockAllocSize = this._maxBlockAllocSize;
1127 | var add = (maxBlockAllocSize === undefined ? function(a, b){return a + b;} : function(a, b){return Math.min(a + b, maxBlockAllocSize);});
1128 |
1129 | for(var i = 0, queueLength = writeQueue.length; i < queueLength; i++){
1130 | requestSize = add(requestSize, writeQueue[i].length);
1131 | }
1132 |
1133 | // Prevent concurrent onFull callbacks
1134 | if(this._pendingOnFull){
1135 | return;
1136 | }
1137 | this._pendingOnFull = true;
1138 |
1139 | this._onFull(this._buffer, requestSize, function(buffer, destination){
1140 | util.setZeroTimeout(function(){
1141 |
1142 | self._pendingOnFull = false;
1143 |
1144 | if(!destination){
1145 | if(self.writable){
1146 | self.emit("error", new Error("buffer is full"));
1147 | }
1148 | self.destroy();
1149 | return;
1150 | }
1151 |
1152 | self._buffer = buffer;
1153 | self._destination = destination;
1154 |
1155 | self._commit();
1156 | });
1157 | });
1158 | };
1159 |
1160 | BlobWriteStream.prototype.end = function(data, encoding){
1161 |
1162 | var self = this;
1163 |
1164 | function _end(){
1165 | self.writable = false;
1166 | self._onEnd();
1167 | }
1168 |
1169 | if(data){
1170 | if(this.write(data, encoding)){
1171 | _end();
1172 | }else{
1173 | self.writable = false;
1174 | this.once("drain", _end);
1175 | }
1176 | }
1177 | else{
1178 | _end();
1179 | }
1180 | };
1181 |
1182 | BlobWriteStream.prototype.destroy = function(){
1183 | this.writable = false;
1184 | this._pendingQueueDrain = false;
1185 | this._writeQueue = [];
1186 | };
1187 |
1188 | BlobWriteStream.prototype.consume = function(consume){
1189 |
1190 | this._buffer = this._buffer.slice(consume);
1191 | this._destinationPos -= consume;
1192 | };
1193 |
1194 | BlobWriteStream.prototype.getCommittedSlice = function(){
1195 | return this._buffer.slice(0, this._destinationPos);
1196 | };
1197 |
1198 | function onFull(buffer, extraSize, callback){
1199 | var newBuffer = new Buffer(buffer.length + extraSize);
1200 | buffer.copy(newBuffer);
1201 | callback(newBuffer, newBuffer.slice(buffer.length));
1202 | }
1203 | */
1204 | exports.BlobReadStream = BlobReadStream;
1205 |
1206 | function BinaryStream(socket, id, create, meta) {
1207 | if (!(this instanceof BinaryStream)) return new BinaryStream(options);
1208 |
1209 | var self = this;
1210 |
1211 | Stream.call(this);
1212 |
1213 |
1214 | this.id = id;
1215 | this._socket = socket;
1216 |
1217 | this.writable = true;
1218 | this.readable = true;
1219 | this.paused = false;
1220 |
1221 | this._closed = false;
1222 | this._ended = false;
1223 |
1224 | if(create) {
1225 | // This is a stream we are creating
1226 | this._write(1, meta, this.id);
1227 | }
1228 | }
1229 |
1230 | util.inherits(BinaryStream, Stream);
1231 |
1232 |
1233 | BinaryStream.prototype._onDrain = function() {
1234 | if(!this.paused) {
1235 | this.emit('drain');
1236 | }
1237 | };
1238 |
1239 | BinaryStream.prototype._onClose = function() {
1240 | // Emit close event
1241 | if (this._closed) {
1242 | return;
1243 | }
1244 | this.readable = false;
1245 | this.writable = false;
1246 | this._closed = true;
1247 | this.emit('close');
1248 | };
1249 |
1250 | BinaryStream.prototype._onError = function(error){
1251 | this.readable = false;
1252 | this.writable = false;
1253 | this.emit('error', error);
1254 | };
1255 |
1256 | // Write stream
1257 |
1258 | BinaryStream.prototype._onPause = function() {
1259 | // Emit pause event
1260 | this.paused = true;
1261 | this.emit('pause');
1262 | };
1263 |
1264 | BinaryStream.prototype._onResume = function() {
1265 | // Emit resume event
1266 | this.paused = false;
1267 | this.emit('resume');
1268 | this.emit('drain');
1269 | };
1270 |
1271 | BinaryStream.prototype._write = function(code, data, bonus) {
1272 | if (this._socket.readyState !== this._socket.constructor.OPEN) {
1273 | return false;
1274 | }
1275 | var message = util.pack([code, data, bonus]);
1276 | return this._socket.send(message) !== false;
1277 | };
1278 |
1279 | BinaryStream.prototype.write = function(data) {
1280 | if(this.writable) {
1281 | var out = this._write(2, data, this.id);
1282 | return !this.paused && out;
1283 | } else {
1284 | throw new Error('Stream is not writable');
1285 | }
1286 | };
1287 |
1288 | BinaryStream.prototype.end = function() {
1289 | this._ended = true;
1290 | this.readable = false;
1291 | this._write(5, null, this.id);
1292 | };
1293 |
1294 | BinaryStream.prototype.destroy = BinaryStream.prototype.destroySoon = function() {
1295 | this._onClose();
1296 | this._write(6, null, this.id);
1297 | };
1298 |
1299 |
1300 | // Read stream
1301 |
1302 | BinaryStream.prototype._onEnd = function() {
1303 | if(this._ended) {
1304 | return;
1305 | }
1306 | this._ended = true;
1307 | this.readable = false;
1308 | this.emit('end');
1309 | };
1310 |
1311 | BinaryStream.prototype._onData = function(data) {
1312 | // Dispatch
1313 | this.emit('data', data);
1314 | };
1315 |
1316 | BinaryStream.prototype.pause = function() {
1317 | this._onPause();
1318 | this._write(3, null, this.id);
1319 | };
1320 |
1321 | BinaryStream.prototype.resume = function() {
1322 | this._onResume();
1323 | this._write(4, null, this.id);
1324 | };
1325 |
1326 |
1327 | function BinaryClient(socket, options) {
1328 | if (!(this instanceof BinaryClient)) return new BinaryClient(socket, options);
1329 |
1330 | EventEmitter.call(this);
1331 |
1332 | var self = this;
1333 |
1334 | this._options = util.extend({
1335 | chunkSize: 40960
1336 | }, options);
1337 |
1338 | this.streams = {};
1339 |
1340 | if(typeof socket === 'string') {
1341 | this._nextId = 0;
1342 | this._socket = new WebSocket(socket);
1343 | } else {
1344 | // Use odd numbered ids for server originated streams
1345 | this._nextId = 1;
1346 | this._socket = socket;
1347 | }
1348 |
1349 | this._socket.binaryType = 'arraybuffer';
1350 |
1351 | this._socket.addEventListener('open', function(){
1352 | self.emit('open');
1353 | });
1354 | this._socket.addEventListener('error', function(error){
1355 | var ids = Object.keys(self.streams);
1356 | for (var i = 0, ii = ids.length; i < ii; i++) {
1357 | self.streams[ids[i]]._onError(error);
1358 | }
1359 | self.emit('error', error);
1360 | });
1361 | this._socket.addEventListener('close', function(code, message){
1362 | var ids = Object.keys(self.streams);
1363 | for (var i = 0, ii = ids.length; i < ii; i++) {
1364 | self.streams[ids[i]]._onClose();
1365 | }
1366 | self.emit('close', code, message);
1367 | });
1368 | this._socket.addEventListener('message', function(data, flags){
1369 | util.setZeroTimeout(function(){
1370 |
1371 | // Message format
1372 | // [type, payload, bonus ]
1373 | //
1374 | // Reserved
1375 | // [ 0 , X , X ]
1376 | //
1377 | //
1378 | // New stream
1379 | // [ 1 , Meta , new streamId ]
1380 | //
1381 | //
1382 | // Data
1383 | // [ 2 , Data , streamId ]
1384 | //
1385 | //
1386 | // Pause
1387 | // [ 3 , null , streamId ]
1388 | //
1389 | //
1390 | // Resume
1391 | // [ 4 , null , streamId ]
1392 | //
1393 | //
1394 | // End
1395 | // [ 5 , null , streamId ]
1396 | //
1397 | //
1398 | // Close
1399 | // [ 6 , null , streamId ]
1400 | //
1401 |
1402 | data = data.data;
1403 |
1404 | try {
1405 | data = util.unpack(data);
1406 | } catch (ex) {
1407 | return self.emit('error', new Error('Received unparsable message: ' + ex));
1408 | }
1409 | if (!(data instanceof Array))
1410 | return self.emit('error', new Error('Received non-array message'));
1411 | if (data.length != 3)
1412 | return self.emit('error', new Error('Received message with wrong part count: ' + data.length));
1413 | if ('number' != typeof data[0])
1414 | return self.emit('error', new Error('Received message with non-number type: ' + data[0]));
1415 |
1416 | switch(data[0]) {
1417 | case 0:
1418 | // Reserved
1419 | break;
1420 | case 1:
1421 | var meta = data[1];
1422 | var streamId = data[2];
1423 | var binaryStream = self._receiveStream(streamId);
1424 | self.emit('stream', binaryStream, meta);
1425 | break;
1426 | case 2:
1427 | var payload = data[1];
1428 | var streamId = data[2];
1429 | var binaryStream = self.streams[streamId];
1430 | if(binaryStream) {
1431 | binaryStream._onData(payload);
1432 | } else {
1433 | self.emit('error', new Error('Received `data` message for unknown stream: ' + streamId));
1434 | }
1435 | break;
1436 | case 3:
1437 | var streamId = data[2];
1438 | var binaryStream = self.streams[streamId];
1439 | if(binaryStream) {
1440 | binaryStream._onPause();
1441 | } else {
1442 | self.emit('error', new Error('Received `pause` message for unknown stream: ' + streamId));
1443 | }
1444 | break;
1445 | case 4:
1446 | var streamId = data[2];
1447 | var binaryStream = self.streams[streamId];
1448 | if(binaryStream) {
1449 | binaryStream._onResume();
1450 | } else {
1451 | self.emit('error', new Error('Received `resume` message for unknown stream: ' + streamId));
1452 | }
1453 | break;
1454 | case 5:
1455 | var streamId = data[2];
1456 | var binaryStream = self.streams[streamId];
1457 | if(binaryStream) {
1458 | binaryStream._onEnd();
1459 | } else {
1460 | self.emit('error', new Error('Received `end` message for unknown stream: ' + streamId));
1461 | }
1462 | break;
1463 | case 6:
1464 | var streamId = data[2];
1465 | var binaryStream = self.streams[streamId];
1466 | if(binaryStream) {
1467 | binaryStream._onClose();
1468 | } else {
1469 | self.emit('error', new Error('Received `close` message for unknown stream: ' + streamId));
1470 | }
1471 | break;
1472 | default:
1473 | self.emit('error', new Error('Unrecognized message type received: ' + data[0]));
1474 | }
1475 | });
1476 | });
1477 | }
1478 |
1479 | util.inherits(BinaryClient, EventEmitter);
1480 |
1481 | BinaryClient.prototype.send = function(data, meta){
1482 | var stream = this.createStream(meta);
1483 | if(data instanceof Stream) {
1484 | data.pipe(stream);
1485 | } else if (util.isNode === true) {
1486 | if(Buffer.isBuffer(data)) {
1487 | (new BufferReadStream(data, {chunkSize: this._options.chunkSize})).pipe(stream);
1488 | } else {
1489 | stream.write(data);
1490 | }
1491 | } else if (util.isNode !== true) {
1492 | if(data.constructor == Blob || data.constructor == File) {
1493 | (new BlobReadStream(data, {chunkSize: this._options.chunkSize})).pipe(stream);
1494 | } else if (data.constructor == ArrayBuffer) {
1495 | var blob;
1496 | if(binaryFeatures.useArrayBufferView) {
1497 | data = new Uint8Array(data);
1498 | }
1499 | if(binaryFeatures.useBlobBuilder) {
1500 | var builder = new BlobBuilder();
1501 | builder.append(data);
1502 | blob = builder.getBlob()
1503 | } else {
1504 | blob = new Blob([data]);
1505 | }
1506 | (new BlobReadStream(blob, {chunkSize: this._options.chunkSize})).pipe(stream);
1507 | } else if (typeof data === 'object' && 'BYTES_PER_ELEMENT' in data) {
1508 | var blob;
1509 | if(!binaryFeatures.useArrayBufferView) {
1510 | // Warn
1511 | data = data.buffer;
1512 | }
1513 | if(binaryFeatures.useBlobBuilder) {
1514 | var builder = new BlobBuilder();
1515 | builder.append(data);
1516 | blob = builder.getBlob()
1517 | } else {
1518 | blob = new Blob([data]);
1519 | }
1520 | (new BlobReadStream(blob, {chunkSize: this._options.chunkSize})).pipe(stream);
1521 | } else {
1522 | stream.write(data);
1523 | }
1524 | }
1525 | return stream;
1526 | };
1527 |
1528 | BinaryClient.prototype._receiveStream = function(streamId){
1529 | var self = this;
1530 | var binaryStream = new BinaryStream(this._socket, streamId, false);
1531 | binaryStream.on('close', function(){
1532 | delete self.streams[streamId];
1533 | });
1534 | this.streams[streamId] = binaryStream;
1535 | return binaryStream;
1536 | };
1537 |
1538 | BinaryClient.prototype.createStream = function(meta){
1539 | if(this._socket.readyState !== WebSocket.OPEN) {
1540 | throw new Error('Client is not yet connected or has closed');
1541 | return;
1542 | }
1543 | var self = this;
1544 | var streamId = this._nextId;
1545 | this._nextId += 2;
1546 | var binaryStream = new BinaryStream(this._socket, streamId, true, meta);
1547 | binaryStream.on('close', function(){
1548 | delete self.streams[streamId];
1549 | });
1550 | this.streams[streamId] = binaryStream;
1551 | return binaryStream;
1552 | };
1553 |
1554 | BinaryClient.prototype.close = BinaryClient.prototype.destroy = function() {
1555 | this._socket.close();
1556 | };
1557 |
1558 | exports.BinaryClient = BinaryClient;
1559 |
1560 | })(this);
1561 |
--------------------------------------------------------------------------------
/public/js/re-sampler.js:
--------------------------------------------------------------------------------
1 | //https://github.com/notthetup/resampler
2 |
3 | function reSample(audioBuffer, targetSampleRate, onComplete) {
4 | var channel = audioBuffer.numberOfChannels;
5 | var samples = audioBuffer.length * targetSampleRate / audioBuffer.sampleRate;
6 |
7 | var offlineContext = new OfflineAudioContext(channel, samples, targetSampleRate);
8 | var bufferSource = offlineContext.createBufferSource();
9 | bufferSource.buffer = audioBuffer;
10 |
11 | bufferSource.connect(offlineContext.destination);
12 | bufferSource.start(0);
13 | offlineContext.startRendering().then(function(renderedBuffer){
14 | onComplete(renderedBuffer);
15 | })
16 | }
17 |
--------------------------------------------------------------------------------
/public/js/site.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by noamc on 8/31/14.
3 | */
4 |
5 | $(function () {
6 | var client,
7 | recorder,
8 | context,
9 | bStream,
10 | contextSampleRate = (new AudioContext()).sampleRate;
11 | resampleRate = contextSampleRate,
12 | worker = new Worker('js/worker/resampler-worker.js');
13 |
14 | worker.postMessage({cmd:"init",from:contextSampleRate,to:resampleRate});
15 |
16 | worker.addEventListener('message', function (e) {
17 | if (bStream && bStream.writable)
18 | bStream.write(convertFloat32ToInt16(e.data.buffer));
19 | }, false);
20 |
21 | $("#start-rec-btn").click(function () {
22 | close();
23 | client = new BinaryClient('wss://'+location.host);
24 | client.on('open', function () {
25 | bStream = client.createStream({sampleRate: resampleRate});
26 | });
27 |
28 | if (context) {
29 | recorder.connect(context.destination);
30 | return;
31 | }
32 |
33 | var session = {
34 | audio: true,
35 | video: false
36 | };
37 |
38 |
39 | navigator.getUserMedia(session, function (stream) {
40 | context = new AudioContext();
41 | var audioInput = context.createMediaStreamSource(stream);
42 | var bufferSize = 0; // let implementation decide
43 |
44 | recorder = context.createScriptProcessor(bufferSize, 1, 1);
45 |
46 | recorder.onaudioprocess = onAudio;
47 |
48 | audioInput.connect(recorder);
49 |
50 | recorder.connect(context.destination);
51 |
52 | }, function (e) {
53 |
54 | });
55 | });
56 |
57 | function onAudio(e) {
58 | var left = e.inputBuffer.getChannelData(0);
59 |
60 | worker.postMessage({cmd: "resample", buffer: left});
61 |
62 | drawBuffer(left);
63 | }
64 |
65 | function convertFloat32ToInt16(buffer) {
66 | var l = buffer.length;
67 | var buf = new Int16Array(l);
68 | while (l--) {
69 | buf[l] = Math.min(1, buffer[l]) * 0x7FFF;
70 | }
71 | return buf.buffer;
72 | }
73 |
74 | //https://github.com/cwilso/Audio-Buffer-Draw/blob/master/js/audiodisplay.js
75 | function drawBuffer(data) {
76 | var canvas = document.getElementById("canvas"),
77 | width = canvas.width,
78 | height = canvas.height,
79 | context = canvas.getContext('2d');
80 |
81 | context.clearRect (0, 0, width, height);
82 | var step = Math.ceil(data.length / width);
83 | var amp = height / 2;
84 | for (var i = 0; i < width; i++) {
85 | var min = 1.0;
86 | var max = -1.0;
87 | for (var j = 0; j < step; j++) {
88 | var datum = data[(i * step) + j];
89 | if (datum < min)
90 | min = datum;
91 | if (datum > max)
92 | max = datum;
93 | }
94 | context.fillRect(i, (1 + min) * amp, 1, Math.max(1, (max - min) * amp));
95 | }
96 | }
97 |
98 | $("#stop-rec-btn").click(function () {
99 | close();
100 | });
101 |
102 | function close(){
103 | console.log('close');
104 | if(recorder)
105 | recorder.disconnect();
106 | if(client)
107 | client.close();
108 | }
109 | });
110 |
111 | navigator.getUserMedia = navigator.getUserMedia ||
112 | navigator.webkitGetUserMedia ||
113 | navigator.mozGetUserMedia ||
114 | navigator.msGetUserMedia;
--------------------------------------------------------------------------------
/public/js/worker/resampler-worker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by noam on 12/15/15.
3 | */
4 |
5 | importScripts('resampler.js');
6 |
7 | var _resampler;
8 |
9 | self.addEventListener('message', function(e) {
10 | if(e.data.cmd=="init"){
11 | var info = e.data;
12 | _resampler = new Resampler({originalSampleRate:info.from,resampledRate:info.to,numberOfChannels:1})
13 | }
14 | if(e.data.cmd=="resample"){
15 | var resampled = _resampler.resample(e.data.buffer,0);
16 | self.postMessage({buffer:resampled},[resampled.buffer]);
17 | }
18 | }, false);
--------------------------------------------------------------------------------
/public/js/worker/resampler.js:
--------------------------------------------------------------------------------
1 | //https://github.com/chris-rudmin/Recorderjs
2 |
3 | "use strict";
4 |
5 | var Resampler = function( config ){
6 | this.originalSampleRate = config.originalSampleRate;
7 | this.numberOfChannels = config.numberOfChannels;
8 | this.resampledRate = config.resampledRate;
9 | this.lastSampleCache = [];
10 |
11 | for ( var i = 0; i < this.numberOfChannels; i++ ){
12 | this.lastSampleCache[i] = [0,0];
13 | }
14 |
15 | if ( this.resampledRate === this.originalSampleRate ) {
16 | this.resample = function( buffer ) { return buffer; };
17 | }
18 | };
19 |
20 | // From http://johncostella.webs.com/magic/
21 | Resampler.prototype.magicKernel = function( x ) {
22 | if ( x < -0.5 ) {
23 | return 0.5 * ( x + 1.5 ) * ( x + 1.5 );
24 | }
25 | else if ( x > 0.5 ) {
26 | return 0.5 * ( x - 1.5 ) * ( x - 1.5 );
27 | }
28 | return 0.75 - ( x * x );
29 | };
30 |
31 | Resampler.prototype.resample = function( buffer, channel ) {
32 | var resampledBufferLength = Math.round( buffer.length * this.resampledRate / this.originalSampleRate );
33 | var resampleRatio = buffer.length / resampledBufferLength;
34 | var outputData = new Float32Array( resampledBufferLength );
35 |
36 | for ( var i = 0; i < resampledBufferLength - 1; i++ ) {
37 | var resampleValue = ( resampleRatio - 1 ) + ( i * resampleRatio );
38 | var nearestPoint = Math.round( resampleValue );
39 |
40 | for ( var tap = -1; tap < 2; tap++ ) {
41 | var sampleValue = buffer[ nearestPoint + tap ] || this.lastSampleCache[ channel ][ 1 + tap ] || buffer[ nearestPoint ];
42 | outputData[ i ] += sampleValue * this.magicKernel( resampleValue - nearestPoint - tap );
43 | }
44 | }
45 |
46 | this.lastSampleCache[ channel ][ 0 ] = buffer[ buffer.length - 2 ];
47 | this.lastSampleCache[ channel ][ 1 ] = outputData[ resampledBufferLength - 1 ] = buffer[ buffer.length - 1 ];
48 |
49 | return outputData;
50 | };
51 |
--------------------------------------------------------------------------------
/public/style/site.css:
--------------------------------------------------------------------------------
1 | #canvas-container{
2 | margin-top: 20px;
3 | border: 1px dashed lightblue;
4 | align-content: center;
5 | width: 515px;
6 | }
7 | .page-header .glyphicon{
8 | vertical-align: bottom;
9 | }
10 |
11 | #icon{
12 | height: 40px;
13 | }
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by noamc on 8/31/14.
3 | */
4 | var binaryServer = require('binaryjs').BinaryServer,
5 | https = require('https'),
6 | wav = require('wav'),
7 | opener = require('opener'),
8 | fs = require('fs'),
9 | connect = require('connect'),
10 | serveStatic = require('serve-static'),
11 | UAParser = require('./ua-parser'),
12 | CONFIG = require("../config.json"),
13 | lame = require('lame');
14 |
15 | var uaParser = new UAParser();
16 |
17 | if(!fs.existsSync("recordings"))
18 | fs.mkdirSync("recordings");
19 |
20 | var options = {
21 | key: fs.readFileSync('ssl/server.key'),
22 | cert: fs.readFileSync('ssl/server.crt'),
23 | };
24 |
25 | var app = connect();
26 |
27 | app.use(serveStatic('public'));
28 |
29 | var server = https.createServer(options,app);
30 | server.listen(9191);
31 |
32 | opener("https://localhost:9191");
33 |
34 | var server = binaryServer({server:server});
35 |
36 | server.on('connection', function(client) {
37 | console.log("new connection...");
38 | var fileWriter = null;
39 | var writeStream = null;
40 |
41 | var userAgent =client._socket.upgradeReq.headers['user-agent'];
42 | uaParser.setUA(userAgent);
43 | var ua = uaParser.getResult();
44 |
45 | client.on('stream', function(stream, meta) {
46 |
47 | console.log("Stream Start@" + meta.sampleRate +"Hz");
48 | var fileName = "recordings/"+ ua.os.name +"-"+ ua.os.version +"_"+ new Date().getTime();
49 |
50 | switch(CONFIG.AudioEncoding){
51 | case "WAV":
52 | fileWriter = new wav.FileWriter(fileName + ".wav", {
53 | channels: 1,
54 | sampleRate: meta.sampleRate,
55 | bitDepth: 16 });
56 | stream.pipe(fileWriter);
57 | break;
58 |
59 | case "MP3":
60 | writeStream = fs.createWriteStream( fileName + ".mp3" );
61 | stream.pipe( new lame.Encoder(
62 | {
63 | channels: 1, bitDepth: 16, sampleRate: meta.sampleRate, bitRate: 128, outSampleRate: 22050, mode: lame.MONO
64 | })
65 | )
66 | .pipe( writeStream );
67 | break;
68 | };
69 |
70 | });
71 |
72 |
73 | client.on('close', function() {
74 | if ( fileWriter != null ) {
75 | fileWriter.end();
76 | } else if ( writeStream != null ) {
77 | writeStream.end();
78 | }
79 | console.log("Connection Closed");
80 | });
81 | });
82 |
--------------------------------------------------------------------------------
/server/ua-parser.js:
--------------------------------------------------------------------------------
1 | /**
2 | * UAParser.js v0.7.10
3 | * Lightweight JavaScript-based User-Agent string parser
4 | * https://github.com/faisalman/ua-parser-js
5 | *
6 | * Copyright © 2012-2015 Faisal Salman
7 | * Dual licensed under GPLv2 & MIT
8 | */
9 |
10 | (function (window, undefined) {
11 |
12 | 'use strict';
13 |
14 | //////////////
15 | // Constants
16 | /////////////
17 |
18 |
19 | var LIBVERSION = '0.7.10',
20 | EMPTY = '',
21 | UNKNOWN = '?',
22 | FUNC_TYPE = 'function',
23 | UNDEF_TYPE = 'undefined',
24 | OBJ_TYPE = 'object',
25 | STR_TYPE = 'string',
26 | MAJOR = 'major', // deprecated
27 | MODEL = 'model',
28 | NAME = 'name',
29 | TYPE = 'type',
30 | VENDOR = 'vendor',
31 | VERSION = 'version',
32 | ARCHITECTURE= 'architecture',
33 | CONSOLE = 'console',
34 | MOBILE = 'mobile',
35 | TABLET = 'tablet',
36 | SMARTTV = 'smarttv',
37 | WEARABLE = 'wearable',
38 | EMBEDDED = 'embedded';
39 |
40 |
41 | ///////////
42 | // Helper
43 | //////////
44 |
45 |
46 | var util = {
47 | extend : function (regexes, extensions) {
48 | var margedRegexes = {};
49 | for (var i in regexes) {
50 | if (extensions[i] && extensions[i].length % 2 === 0) {
51 | margedRegexes[i] = extensions[i].concat(regexes[i]);
52 | } else {
53 | margedRegexes[i] = regexes[i];
54 | }
55 | }
56 | return margedRegexes;
57 | },
58 | has : function (str1, str2) {
59 | if (typeof str1 === "string") {
60 | return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1;
61 | } else {
62 | return false;
63 | }
64 | },
65 | lowerize : function (str) {
66 | return str.toLowerCase();
67 | },
68 | major : function (version) {
69 | return typeof(version) === STR_TYPE ? version.split(".")[0] : undefined;
70 | }
71 | };
72 |
73 |
74 | ///////////////
75 | // Map helper
76 | //////////////
77 |
78 |
79 | var mapper = {
80 |
81 | rgx : function () {
82 |
83 | var result, i = 0, j, k, p, q, matches, match, args = arguments;
84 |
85 | // loop through all regexes maps
86 | while (i < args.length && !matches) {
87 |
88 | var regex = args[i], // even sequence (0,2,4,..)
89 | props = args[i + 1]; // odd sequence (1,3,5,..)
90 |
91 | // construct object barebones
92 | if (typeof result === UNDEF_TYPE) {
93 | result = {};
94 | for (p in props) {
95 | if (props.hasOwnProperty(p)){
96 | q = props[p];
97 | if (typeof q === OBJ_TYPE) {
98 | result[q[0]] = undefined;
99 | } else {
100 | result[q] = undefined;
101 | }
102 | }
103 | }
104 | }
105 |
106 | // try matching uastring with regexes
107 | j = k = 0;
108 | while (j < regex.length && !matches) {
109 | matches = regex[j++].exec(this.getUA());
110 | if (!!matches) {
111 | for (p = 0; p < props.length; p++) {
112 | match = matches[++k];
113 | q = props[p];
114 | // check if given property is actually array
115 | if (typeof q === OBJ_TYPE && q.length > 0) {
116 | if (q.length == 2) {
117 | if (typeof q[1] == FUNC_TYPE) {
118 | // assign modified match
119 | result[q[0]] = q[1].call(this, match);
120 | } else {
121 | // assign given value, ignore regex match
122 | result[q[0]] = q[1];
123 | }
124 | } else if (q.length == 3) {
125 | // check whether function or regex
126 | if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) {
127 | // call function (usually string mapper)
128 | result[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;
129 | } else {
130 | // sanitize match using given regex
131 | result[q[0]] = match ? match.replace(q[1], q[2]) : undefined;
132 | }
133 | } else if (q.length == 4) {
134 | result[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
135 | }
136 | } else {
137 | result[q] = match ? match : undefined;
138 | }
139 | }
140 | }
141 | }
142 | i += 2;
143 | }
144 | return result;
145 | },
146 |
147 | str : function (str, map) {
148 |
149 | for (var i in map) {
150 | // check if array
151 | if (typeof map[i] === OBJ_TYPE && map[i].length > 0) {
152 | for (var j = 0; j < map[i].length; j++) {
153 | if (util.has(map[i][j], str)) {
154 | return (i === UNKNOWN) ? undefined : i;
155 | }
156 | }
157 | } else if (util.has(map[i], str)) {
158 | return (i === UNKNOWN) ? undefined : i;
159 | }
160 | }
161 | return str;
162 | }
163 | };
164 |
165 |
166 | ///////////////
167 | // String map
168 | //////////////
169 |
170 |
171 | var maps = {
172 |
173 | browser : {
174 | oldsafari : {
175 | version : {
176 | '1.0' : '/8',
177 | '1.2' : '/1',
178 | '1.3' : '/3',
179 | '2.0' : '/412',
180 | '2.0.2' : '/416',
181 | '2.0.3' : '/417',
182 | '2.0.4' : '/419',
183 | '?' : '/'
184 | }
185 | }
186 | },
187 |
188 | device : {
189 | amazon : {
190 | model : {
191 | 'Fire Phone' : ['SD', 'KF']
192 | }
193 | },
194 | sprint : {
195 | model : {
196 | 'Evo Shift 4G' : '7373KT'
197 | },
198 | vendor : {
199 | 'HTC' : 'APA',
200 | 'Sprint' : 'Sprint'
201 | }
202 | }
203 | },
204 |
205 | os : {
206 | windows : {
207 | version : {
208 | 'ME' : '4.90',
209 | 'NT 3.11' : 'NT3.51',
210 | 'NT 4.0' : 'NT4.0',
211 | '2000' : 'NT 5.0',
212 | 'XP' : ['NT 5.1', 'NT 5.2'],
213 | 'Vista' : 'NT 6.0',
214 | '7' : 'NT 6.1',
215 | '8' : 'NT 6.2',
216 | '8.1' : 'NT 6.3',
217 | '10' : ['NT 6.4', 'NT 10.0'],
218 | 'RT' : 'ARM'
219 | }
220 | }
221 | }
222 | };
223 |
224 |
225 | //////////////
226 | // Regex map
227 | /////////////
228 |
229 |
230 | var regexes = {
231 |
232 | browser : [[
233 |
234 | // Presto based
235 | /(opera\smini)\/([\w\.-]+)/i, // Opera Mini
236 | /(opera\s[mobiletab]+).+version\/([\w\.-]+)/i, // Opera Mobi/Tablet
237 | /(opera).+version\/([\w\.]+)/i, // Opera > 9.80
238 | /(opera)[\/\s]+([\w\.]+)/i // Opera < 9.80
239 | ], [NAME, VERSION], [
240 |
241 | /(OPiOS)[\/\s]+([\w\.]+)/i // Opera mini on iphone >= 8.0
242 | ], [[NAME, 'Opera Mini'], VERSION], [
243 |
244 | /\s(opr)\/([\w\.]+)/i // Opera Webkit
245 | ], [[NAME, 'Opera'], VERSION], [
246 |
247 | // Mixed
248 | /(kindle)\/([\w\.]+)/i, // Kindle
249 | /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]+)*/i,
250 | // Lunascape/Maxthon/Netfront/Jasmine/Blazer
251 |
252 | // Trident based
253 | /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i,
254 | // Avant/IEMobile/SlimBrowser/Baidu
255 | /(?:ms|\()(ie)\s([\w\.]+)/i, // Internet Explorer
256 |
257 | // Webkit/KHTML based
258 | /(rekonq)\/([\w\.]+)*/i, // Rekonq
259 | /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs)\/([\w\.-]+)/i
260 | // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS
261 | ], [NAME, VERSION], [
262 |
263 | /(trident).+rv[:\s]([\w\.]+).+like\sgecko/i // IE11
264 | ], [[NAME, 'IE'], VERSION], [
265 |
266 | /(edge)\/((\d+)?[\w\.]+)/i // Microsoft Edge
267 | ], [NAME, VERSION], [
268 |
269 | /(yabrowser)\/([\w\.]+)/i // Yandex
270 | ], [[NAME, 'Yandex'], VERSION], [
271 |
272 | /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon
273 | ], [[NAME, /_/g, ' '], VERSION], [
274 |
275 | /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i,
276 | // Chrome/OmniWeb/Arora/Tizen/Nokia
277 | /(qqbrowser)[\/\s]?([\w\.]+)/i
278 | // QQBrowser
279 | ], [NAME, VERSION], [
280 |
281 | /(uc\s?browser)[\/\s]?([\w\.]+)/i,
282 | /ucweb.+(ucbrowser)[\/\s]?([\w\.]+)/i,
283 | /JUC.+(ucweb)[\/\s]?([\w\.]+)/i
284 | // UCBrowser
285 | ], [[NAME, 'UCBrowser'], VERSION], [
286 |
287 | /(dolfin)\/([\w\.]+)/i // Dolphin
288 | ], [[NAME, 'Dolphin'], VERSION], [
289 |
290 | /((?:android.+)crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS
291 | ], [[NAME, 'Chrome'], VERSION], [
292 |
293 | /XiaoMi\/MiuiBrowser\/([\w\.]+)/i // MIUI Browser
294 | ], [VERSION, [NAME, 'MIUI Browser']], [
295 |
296 | /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)/i // Android Browser
297 | ], [VERSION, [NAME, 'Android Browser']], [
298 |
299 | /FBAV\/([\w\.]+);/i // Facebook App for iOS
300 | ], [VERSION, [NAME, 'Facebook']], [
301 |
302 | /fxios\/([\w\.-]+)/i // Firefox for iOS
303 | ], [VERSION, [NAME, 'Firefox']], [
304 |
305 | /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari
306 | ], [VERSION, [NAME, 'Mobile Safari']], [
307 |
308 | /version\/([\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile
309 | ], [VERSION, NAME], [
310 |
311 | /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0
312 | ], [NAME, [VERSION, mapper.str, maps.browser.oldsafari.version]], [
313 |
314 | /(konqueror)\/([\w\.]+)/i, // Konqueror
315 | /(webkit|khtml)\/([\w\.]+)/i
316 | ], [NAME, VERSION], [
317 |
318 | // Gecko based
319 | /(navigator|netscape)\/([\w\.-]+)/i // Netscape
320 | ], [[NAME, 'Netscape'], VERSION], [
321 | /(swiftfox)/i, // Swiftfox
322 | /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i,
323 | // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
324 | /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/([\w\.-]+)/i,
325 | // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
326 | /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla
327 |
328 | // Other
329 | /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\/\s]?([\w\.]+)/i,
330 | // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir
331 | /(links)\s\(([\w\.]+)/i, // Links
332 | /(gobrowser)\/?([\w\.]+)*/i, // GoBrowser
333 | /(ice\s?browser)\/v?([\w\._]+)/i, // ICE Browser
334 | /(mosaic)[\/\s]([\w\.]+)/i // Mosaic
335 | ], [NAME, VERSION]
336 |
337 | /* /////////////////////
338 | // Media players BEGIN
339 | ////////////////////////
340 |
341 | , [
342 |
343 | /(apple(?:coremedia|))\/((\d+)[\w\._]+)/i, // Generic Apple CoreMedia
344 | /(coremedia) v((\d+)[\w\._]+)/i
345 | ], [NAME, VERSION], [
346 |
347 | /(aqualung|lyssna|bsplayer)\/((\d+)?[\w\.-]+)/i // Aqualung/Lyssna/BSPlayer
348 | ], [NAME, VERSION], [
349 |
350 | /(ares|ossproxy)\s((\d+)[\w\.-]+)/i // Ares/OSSProxy
351 | ], [NAME, VERSION], [
352 |
353 | /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/((\d+)[\w\.-]+)/i,
354 | // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC
355 | // NSPlayer/PSP-InternetRadioPlayer/Videos
356 | /(clementine|music player daemon)\s((\d+)[\w\.-]+)/i, // Clementine/MPD
357 | /(lg player|nexplayer)\s((\d+)[\d\.]+)/i,
358 | /player\/(nexplayer|lg player)\s((\d+)[\w\.-]+)/i // NexPlayer/LG Player
359 | ], [NAME, VERSION], [
360 | /(nexplayer)\s((\d+)[\w\.-]+)/i // Nexplayer
361 | ], [NAME, VERSION], [
362 |
363 | /(flrp)\/((\d+)[\w\.-]+)/i // Flip Player
364 | ], [[NAME, 'Flip Player'], VERSION], [
365 |
366 | /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i
367 | // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit
368 | ], [NAME], [
369 |
370 | /(gstreamer) souphttpsrc (?:\([^\)]+\)){0,1} libsoup\/((\d+)[\w\.-]+)/i
371 | // Gstreamer
372 | ], [NAME, VERSION], [
373 |
374 | /(htc streaming player)\s[\w_]+\s\/\s((\d+)[\d\.]+)/i, // HTC Streaming Player
375 | /(java|python-urllib|python-requests|wget|libcurl)\/((\d+)[\w\.-_]+)/i,
376 | // Java/urllib/requests/wget/cURL
377 | /(lavf)((\d+)[\d\.]+)/i // Lavf (FFMPEG)
378 | ], [NAME, VERSION], [
379 |
380 | /(htc_one_s)\/((\d+)[\d\.]+)/i // HTC One S
381 | ], [[NAME, /_/g, ' '], VERSION], [
382 |
383 | /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+){0,1})/i
384 | // MPlayer SVN
385 | ], [NAME, VERSION], [
386 |
387 | /(mplayer)(?:\s|\/|[unkow-]+)((\d+)[\w\.-]+)/i // MPlayer
388 | ], [NAME, VERSION], [
389 |
390 | /(mplayer)/i, // MPlayer (no other info)
391 | /(yourmuze)/i, // YourMuze
392 | /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime
393 | ], [NAME], [
394 |
395 | /(nero (?:home|scout))\/((\d+)[\w\.-]+)/i // Nero Home/Nero Scout
396 | ], [NAME, VERSION], [
397 |
398 | /(nokia\d+)\/((\d+)[\w\.-]+)/i // Nokia
399 | ], [NAME, VERSION], [
400 |
401 | /\s(songbird)\/((\d+)[\w\.-]+)/i // Songbird/Philips-Songbird
402 | ], [NAME, VERSION], [
403 |
404 | /(winamp)3 version ((\d+)[\w\.-]+)/i, // Winamp
405 | /(winamp)\s((\d+)[\w\.-]+)/i,
406 | /(winamp)mpeg\/((\d+)[\w\.-]+)/i
407 | ], [NAME, VERSION], [
408 |
409 | /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info)
410 | // inlight radio
411 | ], [NAME], [
412 |
413 | /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/((\d+)[\w\.-]+)/i
414 | // QuickTime/RealMedia/RadioApp/RadioClientApplication/
415 | // SoundTap/Totem/Stagefright/Streamium
416 | ], [NAME, VERSION], [
417 |
418 | /(smp)((\d+)[\d\.]+)/i // SMP
419 | ], [NAME, VERSION], [
420 |
421 | /(vlc) media player - version ((\d+)[\w\.]+)/i, // VLC Videolan
422 | /(vlc)\/((\d+)[\w\.-]+)/i,
423 | /(xbmc|gvfs|xine|xmms|irapp)\/((\d+)[\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp
424 | /(foobar2000)\/((\d+)[\d\.]+)/i, // Foobar2000
425 | /(itunes)\/((\d+)[\d\.]+)/i // iTunes
426 | ], [NAME, VERSION], [
427 |
428 | /(wmplayer)\/((\d+)[\w\.-]+)/i, // Windows Media Player
429 | /(windows-media-player)\/((\d+)[\w\.-]+)/i
430 | ], [[NAME, /-/g, ' '], VERSION], [
431 |
432 | /windows\/((\d+)[\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i
433 | // Windows Media Server
434 | ], [VERSION, [NAME, 'Windows']], [
435 |
436 | /(com\.riseupradioalarm)\/((\d+)[\d\.]*)/i // RiseUP Radio Alarm
437 | ], [NAME, VERSION], [
438 |
439 | /(rad.io)\s((\d+)[\d\.]+)/i, // Rad.io
440 | /(radio.(?:de|at|fr))\s((\d+)[\d\.]+)/i
441 | ], [[NAME, 'rad.io'], VERSION]
442 |
443 | //////////////////////
444 | // Media players END
445 | ////////////////////*/
446 |
447 | ],
448 |
449 | cpu : [[
450 |
451 | /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64
452 | ], [[ARCHITECTURE, 'amd64']], [
453 |
454 | /(ia32(?=;))/i // IA32 (quicktime)
455 | ], [[ARCHITECTURE, util.lowerize]], [
456 |
457 | /((?:i[346]|x)86)[;\)]/i // IA32
458 | ], [[ARCHITECTURE, 'ia32']], [
459 |
460 | // PocketPC mistakenly identified as PowerPC
461 | /windows\s(ce|mobile);\sppc;/i
462 | ], [[ARCHITECTURE, 'arm']], [
463 |
464 | /((?:ppc|powerpc)(?:64)?)(?:\smac|;|\))/i // PowerPC
465 | ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [
466 |
467 | /(sun4\w)[;\)]/i // SPARC
468 | ], [[ARCHITECTURE, 'sparc']], [
469 |
470 | /((?:avr32|ia64(?=;))|68k(?=\))|arm(?:64|(?=v\d+;))|(?=atmel\s)avr|(?:irix|mips|sparc)(?:64)?(?=;)|pa-risc)/i
471 | // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
472 | ], [[ARCHITECTURE, util.lowerize]]
473 | ],
474 |
475 | device : [[
476 |
477 | /\((ipad|playbook);[\w\s\);-]+(rim|apple)/i // iPad/PlayBook
478 | ], [MODEL, VENDOR, [TYPE, TABLET]], [
479 |
480 | /applecoremedia\/[\w\.]+ \((ipad)/ // iPad
481 | ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [
482 |
483 | /(apple\s{0,1}tv)/i // Apple TV
484 | ], [[MODEL, 'Apple TV'], [VENDOR, 'Apple']], [
485 |
486 | /(archos)\s(gamepad2?)/i, // Archos
487 | /(hp).+(touchpad)/i, // HP TouchPad
488 | /(kindle)\/([\w\.]+)/i, // Kindle
489 | /\s(nook)[\w\s]+build\/(\w+)/i, // Nook
490 | /(dell)\s(strea[kpr\s\d]*[\dko])/i // Dell Streak
491 | ], [VENDOR, MODEL, [TYPE, TABLET]], [
492 |
493 | /(kf[A-z]+)\sbuild\/[\w\.]+.*silk\//i // Kindle Fire HD
494 | ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [
495 | /(sd|kf)[0349hijorstuw]+\sbuild\/[\w\.]+.*silk\//i // Fire Phone
496 | ], [[MODEL, mapper.str, maps.device.amazon.model], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [
497 |
498 | /\((ip[honed|\s\w*]+);.+(apple)/i // iPod/iPhone
499 | ], [MODEL, VENDOR, [TYPE, MOBILE]], [
500 | /\((ip[honed|\s\w*]+);/i // iPod/iPhone
501 | ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [
502 |
503 | /(blackberry)[\s-]?(\w+)/i, // BlackBerry
504 | /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|huawei|meizu|motorola|polytron)[\s_-]?([\w-]+)*/i,
505 | // BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Huawei/Meizu/Motorola/Polytron
506 | /(hp)\s([\w\s]+\w)/i, // HP iPAQ
507 | /(asus)-?(\w+)/i // Asus
508 | ], [VENDOR, MODEL, [TYPE, MOBILE]], [
509 | /\(bb10;\s(\w+)/i // BlackBerry 10
510 | ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [
511 | // Asus Tablets
512 | /android.+(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus 7)/i
513 | ], [MODEL, [VENDOR, 'Asus'], [TYPE, TABLET]], [
514 |
515 | /(sony)\s(tablet\s[ps])\sbuild\//i, // Sony
516 | /(sony)?(?:sgp.+)\sbuild\//i
517 | ], [[VENDOR, 'Sony'], [MODEL, 'Xperia Tablet'], [TYPE, TABLET]], [
518 | /(?:sony)?(?:(?:(?:c|d)\d{4})|(?:so[-l].+))\sbuild\//i
519 | ], [[VENDOR, 'Sony'], [MODEL, 'Xperia Phone'], [TYPE, MOBILE]], [
520 |
521 | /\s(ouya)\s/i, // Ouya
522 | /(nintendo)\s([wids3u]+)/i // Nintendo
523 | ], [VENDOR, MODEL, [TYPE, CONSOLE]], [
524 |
525 | /android.+;\s(shield)\sbuild/i // Nvidia
526 | ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [
527 |
528 | /(playstation\s[34portablevi]+)/i // Playstation
529 | ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [
530 |
531 | /(sprint\s(\w+))/i // Sprint Phones
532 | ], [[VENDOR, mapper.str, maps.device.sprint.vendor], [MODEL, mapper.str, maps.device.sprint.model], [TYPE, MOBILE]], [
533 |
534 | /(lenovo)\s?(S(?:5000|6000)+(?:[-][\w+]))/i // Lenovo tablets
535 | ], [VENDOR, MODEL, [TYPE, TABLET]], [
536 |
537 | /(htc)[;_\s-]+([\w\s]+(?=\))|\w+)*/i, // HTC
538 | /(zte)-(\w+)*/i, // ZTE
539 | /(alcatel|geeksphone|huawei|lenovo|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]+)*/i
540 | // Alcatel/GeeksPhone/Huawei/Lenovo/Nexian/Panasonic/Sony
541 | ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [
542 |
543 | /(nexus\s9)/i // HTC Nexus 9
544 | ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [
545 |
546 | /[\s\(;](xbox(?:\sone)?)[\s\);]/i // Microsoft Xbox
547 | ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [
548 | /(kin\.[onetw]{3})/i // Microsoft Kin
549 | ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [
550 |
551 | // Motorola
552 | /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?(:?\s4g)?)[\w\s]+build\//i,
553 | /mot[\s-]?(\w+)*/i,
554 | /(XT\d{3,4}) build\//i,
555 | /(nexus\s[6])/i
556 | ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [
557 | /android.+\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i
558 | ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [
559 |
560 | /android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n8000|sgh-t8[56]9|nexus 10))/i,
561 | /((SM-T\w+))/i
562 | ], [[VENDOR, 'Samsung'], MODEL, [TYPE, TABLET]], [ // Samsung
563 | /((s[cgp]h-\w+|gt-\w+|galaxy\snexus|sm-n900))/i,
564 | /(sam[sung]*)[\s-]*(\w+-?[\w-]*)*/i,
565 | /sec-((sgh\w+))/i
566 | ], [[VENDOR, 'Samsung'], MODEL, [TYPE, MOBILE]], [
567 | /(samsung);smarttv/i
568 | ], [VENDOR, MODEL, [TYPE, SMARTTV]], [
569 |
570 | /\(dtv[\);].+(aquos)/i // Sharp
571 | ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [
572 | /sie-(\w+)*/i // Siemens
573 | ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [
574 |
575 | /(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia
576 | /(nokia)[\s_-]?([\w-]+)*/i
577 | ], [[VENDOR, 'Nokia'], MODEL, [TYPE, MOBILE]], [
578 |
579 | /android\s3\.[\s\w;-]{10}(a\d{3})/i // Acer
580 | ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [
581 |
582 | /android\s3\.[\s\w;-]{10}(lg?)-([06cv9]{3,4})/i // LG Tablet
583 | ], [[VENDOR, 'LG'], MODEL, [TYPE, TABLET]], [
584 | /(lg) netcast\.tv/i // LG SmartTV
585 | ], [VENDOR, MODEL, [TYPE, SMARTTV]], [
586 | /(nexus\s[45])/i, // LG
587 | /lg[e;\s\/-]+(\w+)*/i
588 | ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [
589 |
590 | /android.+(ideatab[a-z0-9\-\s]+)/i // Lenovo
591 | ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [
592 |
593 | /linux;.+((jolla));/i // Jolla
594 | ], [VENDOR, MODEL, [TYPE, MOBILE]], [
595 |
596 | /((pebble))app\/[\d\.]+\s/i // Pebble
597 | ], [VENDOR, MODEL, [TYPE, WEARABLE]], [
598 |
599 | /android.+;\s(glass)\s\d/i // Google Glass
600 | ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [
601 |
602 | /android.+(\w+)\s+build\/hm\1/i, // Xiaomi Hongmi 'numeric' models
603 | /android.+(hm[\s\-_]*note?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Hongmi
604 | /android.+(mi[\s\-_]*(?:one|one[\s_]plus)?[\s_]*(?:\d\w)?)\s+build/i // Xiaomi Mi
605 | ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [
606 |
607 | /\s(tablet)[;\/\s]/i, // Unidentifiable Tablet
608 | /\s(mobile)[;\/\s]/i // Unidentifiable Mobile
609 | ], [[TYPE, util.lowerize], VENDOR, MODEL]
610 |
611 | /*//////////////////////////
612 | // TODO: move to string map
613 | ////////////////////////////
614 |
615 | /(C6603)/i // Sony Xperia Z C6603
616 | ], [[MODEL, 'Xperia Z C6603'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [
617 | /(C6903)/i // Sony Xperia Z 1
618 | ], [[MODEL, 'Xperia Z 1'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [
619 |
620 | /(SM-G900[F|H])/i // Samsung Galaxy S5
621 | ], [[MODEL, 'Galaxy S5'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [
622 | /(SM-G7102)/i // Samsung Galaxy Grand 2
623 | ], [[MODEL, 'Galaxy Grand 2'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [
624 | /(SM-G530H)/i // Samsung Galaxy Grand Prime
625 | ], [[MODEL, 'Galaxy Grand Prime'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [
626 | /(SM-G313HZ)/i // Samsung Galaxy V
627 | ], [[MODEL, 'Galaxy V'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [
628 | /(SM-T805)/i // Samsung Galaxy Tab S 10.5
629 | ], [[MODEL, 'Galaxy Tab S 10.5'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [
630 | /(SM-G800F)/i // Samsung Galaxy S5 Mini
631 | ], [[MODEL, 'Galaxy S5 Mini'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [
632 | /(SM-T311)/i // Samsung Galaxy Tab 3 8.0
633 | ], [[MODEL, 'Galaxy Tab 3 8.0'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [
634 |
635 | /(R1001)/i // Oppo R1001
636 | ], [MODEL, [VENDOR, 'OPPO'], [TYPE, MOBILE]], [
637 | /(X9006)/i // Oppo Find 7a
638 | ], [[MODEL, 'Find 7a'], [VENDOR, 'Oppo'], [TYPE, MOBILE]], [
639 | /(R2001)/i // Oppo YOYO R2001
640 | ], [[MODEL, 'Yoyo R2001'], [VENDOR, 'Oppo'], [TYPE, MOBILE]], [
641 | /(R815)/i // Oppo Clover R815
642 | ], [[MODEL, 'Clover R815'], [VENDOR, 'Oppo'], [TYPE, MOBILE]], [
643 | /(U707)/i // Oppo Find Way S
644 | ], [[MODEL, 'Find Way S'], [VENDOR, 'Oppo'], [TYPE, MOBILE]], [
645 |
646 | /(T3C)/i // Advan Vandroid T3C
647 | ], [MODEL, [VENDOR, 'Advan'], [TYPE, TABLET]], [
648 | /(ADVAN T1J\+)/i // Advan Vandroid T1J+
649 | ], [[MODEL, 'Vandroid T1J+'], [VENDOR, 'Advan'], [TYPE, TABLET]], [
650 | /(ADVAN S4A)/i // Advan Vandroid S4A
651 | ], [[MODEL, 'Vandroid S4A'], [VENDOR, 'Advan'], [TYPE, MOBILE]], [
652 |
653 | /(V972M)/i // ZTE V972M
654 | ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [
655 |
656 | /(i-mobile)\s(IQ\s[\d\.]+)/i // i-mobile IQ
657 | ], [VENDOR, MODEL, [TYPE, MOBILE]], [
658 | /(IQ6.3)/i // i-mobile IQ IQ 6.3
659 | ], [[MODEL, 'IQ 6.3'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [
660 | /(i-mobile)\s(i-style\s[\d\.]+)/i // i-mobile i-STYLE
661 | ], [VENDOR, MODEL, [TYPE, MOBILE]], [
662 | /(i-STYLE2.1)/i // i-mobile i-STYLE 2.1
663 | ], [[MODEL, 'i-STYLE 2.1'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [
664 |
665 | /(mobiistar touch LAI 512)/i // mobiistar touch LAI 512
666 | ], [[MODEL, 'Touch LAI 512'], [VENDOR, 'mobiistar'], [TYPE, MOBILE]], [
667 |
668 | /////////////
669 | // END TODO
670 | ///////////*/
671 |
672 | ],
673 |
674 | engine : [[
675 |
676 | /windows.+\sedge\/([\w\.]+)/i // EdgeHTML
677 | ], [VERSION, [NAME, 'EdgeHTML']], [
678 |
679 | /(presto)\/([\w\.]+)/i, // Presto
680 | /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m
681 | /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links
682 | /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab
683 | ], [NAME, VERSION], [
684 |
685 | /rv\:([\w\.]+).*(gecko)/i // Gecko
686 | ], [VERSION, NAME]
687 | ],
688 |
689 | os : [[
690 |
691 | // Windows based
692 | /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes)
693 | ], [NAME, VERSION], [
694 | /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT
695 | /(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i
696 | ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [
697 | /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i
698 | ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [
699 |
700 | // Mobile/Embedded OS
701 | /\((bb)(10);/i // BlackBerry 10
702 | ], [[NAME, 'BlackBerry'], VERSION], [
703 | /(blackberry)\w*\/?([\w\.]+)*/i, // Blackberry
704 | /(tizen)[\/\s]([\w\.]+)/i, // Tizen
705 | /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i,
706 | // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki
707 | /linux;.+(sailfish);/i // Sailfish OS
708 | ], [NAME, VERSION], [
709 | /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i // Symbian
710 | ], [[NAME, 'Symbian'], VERSION], [
711 | /\((series40);/i // Series 40
712 | ], [NAME], [
713 | /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS
714 | ], [[NAME, 'Firefox OS'], VERSION], [
715 |
716 | // Console
717 | /(nintendo|playstation)\s([wids34portablevu]+)/i, // Nintendo/Playstation
718 |
719 | // GNU/Linux based
720 | /(mint)[\/\s\(]?(\w+)*/i, // Mint
721 | /(mageia|vectorlinux)[;\s]/i, // Mageia/VectorLinux
722 | /(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|(?=\s)arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?([\w\.-]+)*/i,
723 | // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware
724 | // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus
725 | /(hurd|linux)\s?([\w\.]+)*/i, // Hurd/Linux
726 | /(gnu)\s?([\w\.]+)*/i // GNU
727 | ], [NAME, VERSION], [
728 |
729 | /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS
730 | ], [[NAME, 'Chromium OS'], VERSION],[
731 |
732 | // Solaris
733 | /(sunos)\s?([\w\.]+\d)*/i // Solaris
734 | ], [[NAME, 'Solaris'], VERSION], [
735 |
736 | // BSD based
737 | /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly
738 | ], [NAME, VERSION],[
739 |
740 | /(ip[honead]+)(?:.*os\s([\w]+)*\slike\smac|;\sopera)/i // iOS
741 | ], [[NAME, 'iOS'], [VERSION, /_/g, '.']], [
742 |
743 | /(mac\sos\sx)\s?([\w\s\.]+\w)*/i,
744 | /(macintosh|mac(?=_powerpc)\s)/i // Mac OS
745 | ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [
746 |
747 | // Other
748 | /((?:open)?solaris)[\/\s-]?([\w\.]+)*/i, // Solaris
749 | /(haiku)\s(\w+)/i, // Haiku
750 | /(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i, // AIX
751 | /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i,
752 | // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS
753 | /(unix)\s?([\w\.]+)*/i // UNIX
754 | ], [NAME, VERSION]
755 | ]
756 | };
757 |
758 |
759 | /////////////////
760 | // Constructor
761 | ////////////////
762 |
763 |
764 | var UAParser = function (uastring, extensions) {
765 |
766 | if (!(this instanceof UAParser)) {
767 | return new UAParser(uastring, extensions).getResult();
768 | }
769 |
770 | var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY);
771 | var rgxmap = extensions ? util.extend(regexes, extensions) : regexes;
772 |
773 | this.getBrowser = function () {
774 | var browser = mapper.rgx.apply(this, rgxmap.browser);
775 | browser.major = util.major(browser.version);
776 | return browser;
777 | };
778 | this.getCPU = function () {
779 | return mapper.rgx.apply(this, rgxmap.cpu);
780 | };
781 | this.getDevice = function () {
782 | return mapper.rgx.apply(this, rgxmap.device);
783 | };
784 | this.getEngine = function () {
785 | return mapper.rgx.apply(this, rgxmap.engine);
786 | };
787 | this.getOS = function () {
788 | return mapper.rgx.apply(this, rgxmap.os);
789 | };
790 | this.getResult = function() {
791 | return {
792 | ua : this.getUA(),
793 | browser : this.getBrowser(),
794 | engine : this.getEngine(),
795 | os : this.getOS(),
796 | device : this.getDevice(),
797 | cpu : this.getCPU()
798 | };
799 | };
800 | this.getUA = function () {
801 | return ua;
802 | };
803 | this.setUA = function (uastring) {
804 | ua = uastring;
805 | return this;
806 | };
807 | return this;
808 | };
809 |
810 | UAParser.VERSION = LIBVERSION;
811 | UAParser.BROWSER = {
812 | NAME : NAME,
813 | MAJOR : MAJOR, // deprecated
814 | VERSION : VERSION
815 | };
816 | UAParser.CPU = {
817 | ARCHITECTURE : ARCHITECTURE
818 | };
819 | UAParser.DEVICE = {
820 | MODEL : MODEL,
821 | VENDOR : VENDOR,
822 | TYPE : TYPE,
823 | CONSOLE : CONSOLE,
824 | MOBILE : MOBILE,
825 | SMARTTV : SMARTTV,
826 | TABLET : TABLET,
827 | WEARABLE: WEARABLE,
828 | EMBEDDED: EMBEDDED
829 | };
830 | UAParser.ENGINE = {
831 | NAME : NAME,
832 | VERSION : VERSION
833 | };
834 | UAParser.OS = {
835 | NAME : NAME,
836 | VERSION : VERSION
837 | };
838 |
839 |
840 | ///////////
841 | // Export
842 | //////////
843 |
844 |
845 | // check js environment
846 | if (typeof(exports) !== UNDEF_TYPE) {
847 | // nodejs env
848 | if (typeof module !== UNDEF_TYPE && module.exports) {
849 | //noinspection JSUnresolvedVariable
850 | exports = module.exports = UAParser;
851 | }
852 | exports.UAParser = UAParser;
853 | } else {
854 | // requirejs env (optional)
855 | if (typeof(define) === FUNC_TYPE && define.amd) {
856 | define("ua-parser-js", [], function () {
857 | return UAParser;
858 | });
859 | } else {
860 | // browser env
861 | window.UAParser = UAParser;
862 | }
863 | }
864 |
865 | // jQuery/Zepto specific (optional)
866 | // Note:
867 | // In AMD env the global scope should be kept clean, but jQuery is an exception.
868 | // jQuery always exports to global scope, unless jQuery.noConflict(true) is used,
869 | // and we should catch that.
870 | var $ = window.jQuery || window.Zepto;
871 | if (typeof $ !== UNDEF_TYPE) {
872 | var parser = new UAParser();
873 | $.ua = parser.getResult();
874 | $.ua.get = function() {
875 | return parser.getUA();
876 | };
877 | $.ua.set = function (uastring) {
878 | parser.setUA(uastring);
879 | var result = parser.getResult();
880 | for (var prop in result) {
881 | $.ua[prop] = result[prop];
882 | }
883 | };
884 | }
885 |
886 | })(typeof window === 'object' ? window : this);
887 |
--------------------------------------------------------------------------------
/ssl/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICATCCAWoCCQC9FHehqnNzujANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
3 | VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
4 | cyBQdHkgTHRkMB4XDTE2MDQwNTA5MjA1NloXDTE3MDQwNTA5MjA1NlowRTELMAkG
5 | A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
6 | IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxbgr
7 | 83CRO6Z9JOH9M4qTWyoirx48v487T/ryA6VOL7z0CGiU+HCqNhZXCPAfGYHizGkI
8 | W47zfoOkdMwF6dqHJmLeSCJL6IPdpfnhgjK2H4tLpz3I6jgZSCZfd+K5h7ZuE2U0
9 | VKta7eO3yser+jq8td8ug/b3yfTeAisLtKeXykcCAwEAATANBgkqhkiG9w0BAQsF
10 | AAOBgQA4Mmde6IJwo5K83ySgFIksV7dk2qq/RTMQMeGudX4Pxtvo1zCGc79ONmtE
11 | sJHY1d9cK9TKL3jPTanSTKWuE+PX3Xqtv3r1nKwZ/VPI24wDjAXHKh0WB6UEOgRp
12 | o9R2ZNTmptENf16hyxWEycJlRpjHCFxtNskAumXXFkoLP4TFiw==
13 | -----END CERTIFICATE-----
14 |
--------------------------------------------------------------------------------
/ssl/server.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXQIBAAKBgQDFuCvzcJE7pn0k4f0zipNbKiKvHjy/jztP+vIDpU4vvPQIaJT4
3 | cKo2FlcI8B8ZgeLMaQhbjvN+g6R0zAXp2ocmYt5IIkvog92l+eGCMrYfi0unPcjq
4 | OBlIJl934rmHtm4TZTRUq1rt47fKx6v6Ory13y6D9vfJ9N4CKwu0p5fKRwIDAQAB
5 | AoGAWPvdU++KfXUdh1bp9KNeVD4vY+7Q2kmlIQbImtlvyc5ZadtfiDx0bmk5fH1N
6 | EdbB8ssmhsZcUcj/X81er/O4tMRLW8xi9RFwxcwBhFpba5HxS4VxnQvrpCj3NHop
7 | /QspuuVPA8Gf55ReXYn3Huw7kX3ZOVBF2U3pjalLrS2bUZECQQDp2xsRXMPjvO4e
8 | N69FGB/9nmeHLDjPCvxeywkTksHx3Ia1DrUUTBI9opw5tnHjR4akGrs+gnMWC0gS
9 | EyGQdBbJAkEA2HEVPBB8SwTEsmYLCH2drBlvHS87fKXmJ845sk4+q8yluB/IFTDI
10 | vhlmnu4sY3uyS5r7dMrEGmra6nI/W36QjwJBAIaHUhHx4IqxU/Y0KHLCBx06M+pR
11 | 6ThJ5JaPjGAjK8j8CM49cLQFcvTcB603pFqP+geLjS3Pk28Z/FLRiJx1++kCQQC0
12 | AD+fpzonDX0jvFd6pTVGlhRhWhGH1VR2UDyNfCMEr3o2iT/V169q4ScGD5+c0Jdz
13 | 5x0ugR7btXgAOClWxwgjAkBj1JFl5lJj4OmddJ4BC3Q1+k87MuxXw+eEv4ChW8Id
14 | DcIuQaP4Ohl8Fd6aKUoQm2j2F17E5EW0h5RkkpfgUDao
15 | -----END RSA PRIVATE KEY-----
16 |
--------------------------------------------------------------------------------