xframelib 0.5.6 → 0.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,166 +1,180 @@
1
- <!--
2
- mitm.html is the lite "man in the middle"
3
-
4
- This is only meant to signal the opener's messageChannel to
5
- the service worker - when that is done this mitm can be closed
6
- but it's better to keep it alive since this also stops the sw
7
- from restarting
8
-
9
- The service worker is capable of intercepting all request and fork their
10
- own "fake" response - wish we are going to craft
11
- when the worker then receives a stream then the worker will tell the opener
12
- to open up a link that will start the download
13
- -->
14
- <script>
15
- // This will prevent the sw from restarting
16
- let keepAlive = () => {
17
- keepAlive = () => {}
18
- var ping = location.href.substr(0, location.href.lastIndexOf('/')) + '/ping'
19
- var interval = setInterval(() => {
20
- if (sw) {
21
- sw.postMessage('ping')
22
- } else {
23
- fetch(ping).then(res => res.text(!res.ok && clearInterval(interval)))
24
- }
25
- }, 10000)
26
- }
27
-
28
- // message event is the first thing we need to setup a listner for
29
- // don't want the opener to do a random timeout - instead they can listen for
30
- // the ready event
31
- // but since we need to wait for the Service Worker registration, we store the
32
- // message for later
33
- let messages = []
34
- window.onmessage = evt => messages.push(evt)
35
-
36
- let sw = null
37
- let scope = ''
38
-
39
- function registerWorker() {
40
- return navigator.serviceWorker.getRegistration('./').then(swReg => {
41
- return swReg || navigator.serviceWorker.register('sw.js', { scope: './' })
42
- }).then(swReg => {
43
- const swRegTmp = swReg.installing || swReg.waiting
44
-
45
- scope = swReg.scope
46
-
47
- return (sw = swReg.active) || new Promise(resolve => {
48
- swRegTmp.addEventListener('statechange', fn = () => {
49
- if (swRegTmp.state === 'activated') {
50
- swRegTmp.removeEventListener('statechange', fn)
51
- sw = swReg.active
52
- resolve()
53
- }
54
- })
55
- })
56
- })
57
- }
58
-
59
- // Now that we have the Service Worker registered we can process messages
60
- function onMessage (event) {
61
- let { data, ports, origin } = event
62
-
63
- // It's important to have a messageChannel, don't want to interfere
64
- // with other simultaneous downloads
65
- if (!ports || !ports.length) {
66
- throw new TypeError("[StreamSaver] You didn't send a messageChannel")
67
- }
68
-
69
- if (typeof data !== 'object') {
70
- throw new TypeError("[StreamSaver] You didn't send a object")
71
- }
72
-
73
- // the default public service worker for StreamSaver is shared among others.
74
- // so all download links needs to be prefixed to avoid any other conflict
75
- data.origin = origin
76
-
77
- // if we ever (in some feature versoin of streamsaver) would like to
78
- // redirect back to the page of who initiated a http request
79
- data.referrer = data.referrer || document.referrer || origin
80
-
81
- // pass along version for possible backwards compatibility in sw.js
82
- data.streamSaverVersion = new URLSearchParams(location.search).get('version')
83
-
84
- if (data.streamSaverVersion === '1.2.0') {
85
- console.warn('[StreamSaver] please update streamsaver')
86
- }
87
-
88
- /** @since v2.0.0 */
89
- if (!data.headers) {
90
- console.warn("[StreamSaver] pass `data.headers` that you would like to pass along to the service worker\nit should be a 2D array or a key/val object that fetch's Headers api accepts")
91
- } else {
92
- // test if it's correct
93
- // should thorw a typeError if not
94
- new Headers(data.headers)
95
- }
96
-
97
- /** @since v2.0.0 */
98
- if (typeof data.filename === 'string') {
99
- console.warn("[StreamSaver] You shouldn't send `data.filename` anymore. It should be included in the Content-Disposition header option")
100
- // Do what File constructor do with fileNames
101
- data.filename = data.filename.replace(/\//g, ':')
102
- }
103
-
104
- /** @since v2.0.0 */
105
- if (data.size) {
106
- console.warn("[StreamSaver] You shouldn't send `data.size` anymore. It should be included in the content-length header option")
107
- }
108
-
109
- /** @since v2.0.0 */
110
- if (data.readableStream) {
111
- console.warn("[StreamSaver] You should send the readableStream in the messageChannel, not throught mitm")
112
- }
113
-
114
- /** @since v2.0.0 */
115
- if (!data.pathname) {
116
- console.warn("[StreamSaver] Please send `data.pathname` (eg: /pictures/summer.jpg)")
117
- data.pathname = Math.random().toString().slice(-6) + '/' + data.filename
118
- }
119
-
120
- // remove all leading slashes
121
- data.pathname = data.pathname.replace(/^\/+/g, '')
122
-
123
- // remove protocol
124
- let org = origin.replace(/(^\w+:|^)\/\//, '')
125
-
126
- // set the absolute pathname to the download url.
127
- data.url = new URL(`${scope + org}/${data.pathname}`).toString()
128
-
129
- if (!data.url.startsWith(`${scope + org}/`)) {
130
- throw new TypeError('[StreamSaver] bad `data.pathname`')
131
- }
132
-
133
- // This sends the message data as well as transferring
134
- // messageChannel.port2 to the service worker. The service worker can
135
- // then use the transferred port to reply via postMessage(), which
136
- // will in turn trigger the onmessage handler on messageChannel.port1.
137
-
138
- const transferable = data.readableStream
139
- ? [ ports[0], data.readableStream ]
140
- : [ ports[0] ]
141
-
142
- if (!(data.readableStream || data.transferringReadable)) {
143
- keepAlive()
144
- }
145
-
146
- return sw.postMessage(data, transferable)
147
- }
148
-
149
- if (window.opener) {
150
- // The opener can't listen to onload event, so we need to help em out!
151
- // (telling them that we are ready to accept postMessage's)
152
- window.opener.postMessage('StreamSaver::loadedPopup', '*')
153
- }
154
-
155
- if (navigator.serviceWorker) {
156
- registerWorker().then(() => {
157
- window.onmessage = onMessage
158
- messages.forEach(window.onmessage)
159
- })
160
- } else {
161
- // FF can ping sw with fetch from a secure hidden iframe
162
- // shouldn't really be possible?
163
- keepAlive()
164
- }
165
-
166
- </script>
1
+ <!--
2
+ mitm.html is the lite "man in the middle"
3
+
4
+ This is only meant to signal the opener's messageChannel to
5
+ the service worker - when that is done this mitm can be closed
6
+ but it's better to keep it alive since this also stops the sw
7
+ from restarting
8
+
9
+ The service worker is capable of intercepting all request and fork their
10
+ own "fake" response - wish we are going to craft
11
+ when the worker then receives a stream then the worker will tell the opener
12
+ to open up a link that will start the download
13
+ -->
14
+ <script>
15
+ // This will prevent the sw from restarting
16
+ let keepAlive = () => {
17
+ keepAlive = () => {};
18
+ var ping = location.href.substring(0, location.href.lastIndexOf('/')) + '/ping';
19
+ var interval = setInterval(() => {
20
+ if (sw) {
21
+ sw.postMessage('ping');
22
+ } else {
23
+ fetch(ping).then(res => res.text(!res.ok && clearInterval(interval)));
24
+ }
25
+ }, 10000);
26
+ };
27
+
28
+ // message event is the first thing we need to setup a listner for
29
+ // don't want the opener to do a random timeout - instead they can listen for
30
+ // the ready event
31
+ // but since we need to wait for the Service Worker registration, we store the
32
+ // message for later
33
+ let messages = [];
34
+ window.onmessage = evt => messages.push(evt);
35
+
36
+ let sw = null;
37
+ let scope = '';
38
+
39
+ function registerWorker() {
40
+ return navigator.serviceWorker
41
+ .getRegistration('./')
42
+ .then(swReg => {
43
+ return swReg || navigator.serviceWorker.register('sw.js', { scope: './' });
44
+ })
45
+ .then(swReg => {
46
+ const swRegTmp = swReg.installing || swReg.waiting;
47
+
48
+ scope = swReg.scope;
49
+
50
+ return (
51
+ (sw = swReg.active) ||
52
+ new Promise(resolve => {
53
+ swRegTmp.addEventListener(
54
+ 'statechange',
55
+ (fn = () => {
56
+ if (swRegTmp.state === 'activated') {
57
+ swRegTmp.removeEventListener('statechange', fn);
58
+ sw = swReg.active;
59
+ resolve();
60
+ }
61
+ })
62
+ );
63
+ })
64
+ );
65
+ });
66
+ }
67
+
68
+ // Now that we have the Service Worker registered we can process messages
69
+ function onMessage(event) {
70
+ let { data, ports, origin } = event;
71
+
72
+ // It's important to have a messageChannel, don't want to interfere
73
+ // with other simultaneous downloads
74
+ if (!ports || !ports.length) {
75
+ throw new TypeError("[StreamSaver] You didn't send a messageChannel");
76
+ }
77
+
78
+ if (typeof data !== 'object') {
79
+ throw new TypeError("[StreamSaver] You didn't send a object");
80
+ }
81
+
82
+ // the default public service worker for StreamSaver is shared among others.
83
+ // so all download links needs to be prefixed to avoid any other conflict
84
+ data.origin = origin;
85
+
86
+ // if we ever (in some feature versoin of streamsaver) would like to
87
+ // redirect back to the page of who initiated a http request
88
+ data.referrer = data.referrer || document.referrer || origin;
89
+
90
+ // pass along version for possible backwards compatibility in sw.js
91
+ data.streamSaverVersion = new URLSearchParams(location.search).get('version');
92
+
93
+ if (data.streamSaverVersion === '1.2.0') {
94
+ console.warn('[StreamSaver] please update streamsaver');
95
+ }
96
+
97
+ /** @since v2.0.0 */
98
+ if (!data.headers) {
99
+ console.warn(
100
+ "[StreamSaver] pass `data.headers` that you would like to pass along to the service worker\nit should be a 2D array or a key/val object that fetch's Headers api accepts"
101
+ );
102
+ } else {
103
+ // test if it's correct
104
+ // should thorw a typeError if not
105
+ new Headers(data.headers);
106
+ }
107
+
108
+ /** @since v2.0.0 */
109
+ if (typeof data.filename === 'string') {
110
+ console.warn(
111
+ "[StreamSaver] You shouldn't send `data.filename` anymore. It should be included in the Content-Disposition header option"
112
+ );
113
+ // Do what File constructor do with fileNames
114
+ data.filename = data.filename.replace(/\//g, ':');
115
+ }
116
+
117
+ /** @since v2.0.0 */
118
+ if (data.size) {
119
+ console.warn(
120
+ "[StreamSaver] You shouldn't send `data.size` anymore. It should be included in the content-length header option"
121
+ );
122
+ }
123
+
124
+ /** @since v2.0.0 */
125
+ if (data.readableStream) {
126
+ console.warn(
127
+ '[StreamSaver] You should send the readableStream in the messageChannel, not throught mitm'
128
+ );
129
+ }
130
+
131
+ /** @since v2.0.0 */
132
+ if (!data.pathname) {
133
+ console.warn('[StreamSaver] Please send `data.pathname` (eg: /pictures/summer.jpg)');
134
+ data.pathname = Math.random().toString().slice(-6) + '/' + data.filename;
135
+ }
136
+
137
+ // remove all leading slashes
138
+ data.pathname = data.pathname.replace(/^\/+/g, '');
139
+
140
+ // remove protocol
141
+ let org = origin.replace(/(^\w+:|^)\/\//, '');
142
+
143
+ // set the absolute pathname to the download url.
144
+ data.url = new URL(`${scope + org}/${data.pathname}`).toString();
145
+
146
+ if (!data.url.startsWith(`${scope + org}/`)) {
147
+ throw new TypeError('[StreamSaver] bad `data.pathname`');
148
+ }
149
+
150
+ // This sends the message data as well as transferring
151
+ // messageChannel.port2 to the service worker. The service worker can
152
+ // then use the transferred port to reply via postMessage(), which
153
+ // will in turn trigger the onmessage handler on messageChannel.port1.
154
+
155
+ const transferable = data.readableStream ? [ports[0], data.readableStream] : [ports[0]];
156
+
157
+ if (!(data.readableStream || data.transferringReadable)) {
158
+ keepAlive();
159
+ }
160
+
161
+ return sw.postMessage(data, transferable);
162
+ }
163
+
164
+ if (window.opener) {
165
+ // The opener can't listen to onload event, so we need to help em out!
166
+ // (telling them that we are ready to accept postMessage's)
167
+ window.opener.postMessage('StreamSaver::loadedPopup', '*');
168
+ }
169
+
170
+ if (navigator.serviceWorker) {
171
+ registerWorker().then(() => {
172
+ window.onmessage = onMessage;
173
+ messages.forEach(window.onmessage);
174
+ });
175
+ } else {
176
+ // FF can ping sw with fetch from a secure hidden iframe
177
+ // shouldn't really be possible?
178
+ keepAlive();
179
+ }
180
+ </script>
package/dist/public/sw.js CHANGED
@@ -1,128 +1,128 @@
1
- /* global self ReadableStream Response */
2
-
3
- self.addEventListener('install', () => {
4
- self.skipWaiting()
5
- })
6
-
7
- self.addEventListener('activate', event => {
8
- event.waitUntil(self.clients.claim())
9
- })
10
-
11
- const map = new Map()
12
-
13
- // This should be called once per download
14
- // Each event has a dataChannel that the data will be piped through
15
- self.onmessage = event => {
16
- // We send a heartbeat every x secound to keep the
17
- // service worker alive if a transferable stream is not sent
18
- if (event.data === 'ping') {
19
- return
20
- }
21
-
22
- const data = event.data
23
- const downloadUrl = data.url || self.registration.scope + Math.random() + '/' + (typeof data === 'string' ? data : data.filename)
24
- const port = event.ports[0]
25
- const metadata = new Array(3) // [stream, data, port]
26
-
27
- metadata[1] = data
28
- metadata[2] = port
29
-
30
- // Note to self:
31
- // old streamsaver v1.2.0 might still use `readableStream`...
32
- // but v2.0.0 will always transfer the stream throught MessageChannel #94
33
- if (event.data.readableStream) {
34
- metadata[0] = event.data.readableStream
35
- } else if (event.data.transferringReadable) {
36
- port.onmessage = evt => {
37
- port.onmessage = null
38
- metadata[0] = evt.data.readableStream
39
- }
40
- } else {
41
- metadata[0] = createStream(port)
42
- }
43
-
44
- map.set(downloadUrl, metadata)
45
- port.postMessage({ download: downloadUrl })
46
- }
47
-
48
- function createStream (port) {
49
- // ReadableStream is only supported by chrome 52
50
- return new ReadableStream({
51
- start (controller) {
52
- // When we receive data on the messageChannel, we write
53
- port.onmessage = ({ data }) => {
54
- if (data === 'end') {
55
- return controller.close()
56
- }
57
-
58
- if (data === 'abort') {
59
- controller.error('Aborted the download')
60
- return
61
- }
62
-
63
- controller.enqueue(data)
64
- }
65
- },
66
- cancel () {
67
- console.log('user aborted')
68
- }
69
- })
70
- }
71
-
72
- self.onfetch = event => {
73
- const url = event.request.url
74
-
75
- // this only works for Firefox
76
- if (url.endsWith('/ping')) {
77
- return event.respondWith(new Response('pong'))
78
- }
79
-
80
- const hijacke = map.get(url)
81
-
82
- if (!hijacke) return null
83
-
84
- const [ stream, data, port ] = hijacke
85
-
86
- map.delete(url)
87
-
88
- // Not comfortable letting any user control all headers
89
- // so we only copy over the length & disposition
90
- const responseHeaders = new Headers({
91
- 'Content-Type': 'application/octet-stream; charset=utf-8',
92
-
93
- // To be on the safe side, The link can be opened in a iframe.
94
- // but octet-stream should stop it.
95
- 'Content-Security-Policy': "default-src 'none'",
96
- 'X-Content-Security-Policy': "default-src 'none'",
97
- 'X-WebKit-CSP': "default-src 'none'",
98
- 'X-XSS-Protection': '1; mode=block'
99
- })
100
-
101
- let headers = new Headers(data.headers || {})
102
-
103
- if (headers.has('Content-Length')) {
104
- responseHeaders.set('Content-Length', headers.get('Content-Length'))
105
- }
106
-
107
- if (headers.has('Content-Disposition')) {
108
- responseHeaders.set('Content-Disposition', headers.get('Content-Disposition'))
109
- }
110
-
111
- // data, data.filename and size should not be used anymore
112
- if (data.size) {
113
- console.warn('Depricated')
114
- responseHeaders.set('Content-Length', data.size)
115
- }
116
-
117
- let fileName = typeof data === 'string' ? data : data.filename
118
- if (fileName) {
119
- console.warn('Depricated')
120
- // Make filename RFC5987 compatible
121
- fileName = encodeURIComponent(fileName).replace(/['()]/g, escape).replace(/\*/g, '%2A')
122
- responseHeaders.set('Content-Disposition', "attachment; filename*=UTF-8''" + fileName)
123
- }
124
-
125
- event.respondWith(new Response(stream, { headers: responseHeaders }))
126
-
127
- port.postMessage({ debug: 'Download started' })
128
- }
1
+ /* global self ReadableStream Response */
2
+
3
+ self.addEventListener('install', () => {
4
+ self.skipWaiting()
5
+ })
6
+
7
+ self.addEventListener('activate', event => {
8
+ event.waitUntil(self.clients.claim())
9
+ })
10
+
11
+ const map = new Map()
12
+
13
+ // This should be called once per download
14
+ // Each event has a dataChannel that the data will be piped through
15
+ self.onmessage = event => {
16
+ // We send a heartbeat every x secound to keep the
17
+ // service worker alive if a transferable stream is not sent
18
+ if (event.data === 'ping') {
19
+ return
20
+ }
21
+
22
+ const data = event.data
23
+ const downloadUrl = data.url || self.registration.scope + Math.random() + '/' + (typeof data === 'string' ? data : data.filename)
24
+ const port = event.ports[0]
25
+ const metadata = new Array(3) // [stream, data, port]
26
+
27
+ metadata[1] = data
28
+ metadata[2] = port
29
+
30
+ // Note to self:
31
+ // old streamsaver v1.2.0 might still use `readableStream`...
32
+ // but v2.0.0 will always transfer the stream throught MessageChannel #94
33
+ if (event.data.readableStream) {
34
+ metadata[0] = event.data.readableStream
35
+ } else if (event.data.transferringReadable) {
36
+ port.onmessage = evt => {
37
+ port.onmessage = null
38
+ metadata[0] = evt.data.readableStream
39
+ }
40
+ } else {
41
+ metadata[0] = createStream(port)
42
+ }
43
+
44
+ map.set(downloadUrl, metadata)
45
+ port.postMessage({ download: downloadUrl })
46
+ }
47
+
48
+ function createStream (port) {
49
+ // ReadableStream is only supported by chrome 52
50
+ return new ReadableStream({
51
+ start (controller) {
52
+ // When we receive data on the messageChannel, we write
53
+ port.onmessage = ({ data }) => {
54
+ if (data === 'end') {
55
+ return controller.close()
56
+ }
57
+
58
+ if (data === 'abort') {
59
+ controller.error('Aborted the download')
60
+ return
61
+ }
62
+
63
+ controller.enqueue(data)
64
+ }
65
+ },
66
+ cancel () {
67
+ console.log('user aborted')
68
+ }
69
+ })
70
+ }
71
+
72
+ self.onfetch = event => {
73
+ const url = event.request.url
74
+
75
+ // this only works for Firefox
76
+ if (url.endsWith('/ping')) {
77
+ return event.respondWith(new Response('pong'))
78
+ }
79
+
80
+ const hijacke = map.get(url)
81
+
82
+ if (!hijacke) return null
83
+
84
+ const [ stream, data, port ] = hijacke
85
+
86
+ map.delete(url)
87
+
88
+ // Not comfortable letting any user control all headers
89
+ // so we only copy over the length & disposition
90
+ const responseHeaders = new Headers({
91
+ 'Content-Type': 'application/octet-stream; charset=utf-8',
92
+
93
+ // To be on the safe side, The link can be opened in a iframe.
94
+ // but octet-stream should stop it.
95
+ 'Content-Security-Policy': "default-src 'none'",
96
+ 'X-Content-Security-Policy': "default-src 'none'",
97
+ 'X-WebKit-CSP': "default-src 'none'",
98
+ 'X-XSS-Protection': '1; mode=block'
99
+ })
100
+
101
+ let headers = new Headers(data.headers || {})
102
+
103
+ if (headers.has('Content-Length')) {
104
+ responseHeaders.set('Content-Length', headers.get('Content-Length'))
105
+ }
106
+
107
+ if (headers.has('Content-Disposition')) {
108
+ responseHeaders.set('Content-Disposition', headers.get('Content-Disposition'))
109
+ }
110
+
111
+ // data, data.filename and size should not be used anymore
112
+ if (data.size) {
113
+ console.warn('Depricated')
114
+ responseHeaders.set('Content-Length', data.size)
115
+ }
116
+
117
+ let fileName = typeof data === 'string' ? data : data.filename
118
+ if (fileName) {
119
+ console.warn('Depricated')
120
+ // Make filename RFC5987 compatible
121
+ fileName = encodeURIComponent(fileName).replace(/['()]/g, escape).replace(/\*/g, '%2A')
122
+ responseHeaders.set('Content-Disposition', "attachment; filename*=UTF-8''" + fileName)
123
+ }
124
+
125
+ event.respondWith(new Response(stream, { headers: responseHeaders }))
126
+
127
+ port.postMessage({ debug: 'Download started' })
128
+ }
@@ -95,4 +95,23 @@ export default class H5Tool {
95
95
  * @param text
96
96
  */
97
97
  static copyText: (text: string) => Promise<unknown>;
98
+ /**
99
+ * 设置是否开启网站灰模式
100
+ * @param isGray 是否暗灰模式
101
+ */
102
+ static setGrayMode(isGray: boolean): void;
103
+ /**
104
+ * 开关 HTML元素的Style类名
105
+ * @param flag
106
+ * @param clsName
107
+ * @param target
108
+ */
109
+ static toggleClass(flag: boolean, clsName: string, target?: HTMLElement): void;
110
+ /**
111
+ * 设置 css 变量(全局)
112
+ * @param prop
113
+ * @param val
114
+ * @param dom
115
+ */
116
+ static setCssVar(prop: string, val: any, dom?: HTMLElement): void;
98
117
  }
@@ -1,4 +1,4 @@
1
- import { ITokenInfo } from '../model/Token';
1
+ import { ITokenInfo } from '../model/IUserModel';
2
2
  import StorageHelper from '../utils/Storage';
3
3
  export declare const storageHelper: StorageHelper;
4
4
  /**
@@ -0,0 +1,15 @@
1
+ declare function toBytes(str: any): Uint8Array;
2
+ declare function toString(bytes: any): string;
3
+ declare function encrypt(data: any, key: any): any;
4
+ declare function encryptToString(data: any, key: any): string;
5
+ declare function decrypt(data: any, key: any): any;
6
+ declare function decryptToString(data: any, key: any): string;
7
+ declare const XXTEA: {
8
+ toBytes: typeof toBytes;
9
+ toString: typeof toString;
10
+ encrypt: typeof encrypt;
11
+ encryptToString: typeof encryptToString;
12
+ decrypt: typeof decrypt;
13
+ decryptToString: typeof decryptToString;
14
+ };
15
+ export default XXTEA;