Refresh the active tab or a tab that you want to grab media resources (image, audio or video) from.
17 |
If there is a video source in the tab, it needs to be streamed for the media source to be grabbed.
18 |
When the intended resource is grabbed, make sure to press the "Pause" button to release network observer and prevent cluttering of this window with new resources.
19 |
Detection of YouTube resources is locked because of restrictions of the Chrome Store.
Refresh the active tab or a tab that you want to grab media resources (image, audio or video) from.
16 |
If there is a video source in the tab, it needs to be streamed for the media source to be grabbed.
17 |
When the intended resource is grabbed, make sure to press the "Pause" button to release network observer and prevent cluttering of this window with new resources.
18 |
Detection of YouTube resources is locked because of restrictions of the Chrome Store.
19 |
To download all loaded images on a page, use the image grabber tool from right-click over the toolbar button
20 |
To convert media files to different formats, use Media Converter add-on.
147 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/v2/data/window/index.js:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2017 InBasic
2 | *
3 | * This Source Code Form is subject to the terms of the Mozilla Public
4 | * License, v. 2.0. If a copy of the MPL was not distributed with this
5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 |
7 | * Home: http://add0n.com/media-tools.html
8 | * GitHub: https://github.com/inbasic/bulk-media-downloader/ */
9 |
10 | /* globals $, persist */
11 | 'use strict';
12 |
13 | document.body.dataset.os = navigator.userAgent.indexOf('Firefox') !== -1 ? 'firefox' : (
14 | navigator.userAgent.indexOf('OPR') === -1 ? 'chrome' : 'opera'
15 | );
16 | if (window.location.search) {
17 | document.body.dataset.tabId = window.location.search.replace('?tabId=', '');
18 | }
19 |
20 | const update = (function(callback) {
21 | $.filters.parent.addEventListener('change', callback);
22 | $.filters.parent.addEventListener('keyup', callback);
23 |
24 | return () => callback();
25 | })(function() {
26 | [...$.tbody.querySelectorAll('tr')]
27 | .forEach(tr => tr.querySelector('[type=checkbox]').checked = isChecked(tr));
28 | state();
29 | });
30 |
31 | const is = {
32 | application: tr => tr.dataset.type === 'application',
33 | document: tr => tr.dataset.type === 'document' || /\.(txt|docm|xps|odc|otc|odb|odf|odft|odg|otg|odi|oti|odp|otp|ods|ots|odt|odm|ott|oth|pptx|sldx|ppsx|potx|xlsx|xltx|docx|dotx)$/.test(tr.dataset.url),
34 | video: tr => tr.dataset.type === 'video' || /\.(3gp|3g2|h261|h263|h264|jpgv|jpm|jpgm|mj2|mjp2|ts|mp4|mp4v|mpg4|mpeg|mpg|mpe|m1v|m2v|ogv|qt|mov|uvh|uvvh|uvm|uvvm|uvp|uvvp|uvs|uvvs|uvv|uvvv|dvb|fvt|mxu|m4u|pyv|uvu|uvvu|viv|webm|f4v|fli|flv|m4v|mkv|mk3d|mks|mng|asf|asx|vob|wm|wmv|wmx|wvx|avi|movie|smv)$/.test(tr.dataset.url),
35 | audio: tr => tr.dataset.type === 'audio' || /\.(adp|au|snd|mid|midi|kar|rmi|m4a|mp3|mpga|mp2|mp2a|m2a|m3a|oga|ogg|spx|s3m|sil|uva|uvva|eol|dra|dts|dtshd|lvp|pya|rip|weba|aac|aif|aiff|aifc|caf|flac|mka|m3u|wax|wma|ra|rmp|wav)$/.test(tr.dataset.url),
36 | archive: tr => tr.dataset.type === 'archive' || /\.(zip|rar|jar|apk|xpi|crx|joda|tao)$/.test(tr.dataset.url),
37 | image: tr => tr.dataset.type === 'image' || /\.(bmp|cgm|g3|gif|ief|jpeg|jpg|jpe|ktx|png|btif|sgi|svg|svgz|tiff|tif|psd|uvi|uvvi|uvg|uvvg|djv|sub|dwg|dxf|fbs|fpx|fst|mmr|rlc|mdi|wdp|npx|wbmp|xif|webp|3ds|ras|cmx|fh|fhc|fh4|fh5|fh7|ico|sid|pcx|pic|pct|pnm|pbm|pgm|ppm|rgb|tga|xbm|xpm|xwd)$/.test(tr.dataset.url),
38 | tab: tr => tr.dataset.tabId === document.body.dataset.tabId
39 | };
40 |
41 | let urls = [];
42 |
43 | const config = {
44 | _filter: 'all',
45 | _monitor: true,
46 | _size: 'all' // 'all', '100k', '1m', '10m'
47 | };
48 | Object.defineProperty(config, 'filter', {
49 | enumerable: true,
50 | configurable: true,
51 | get() {
52 | return config._filter;
53 | },
54 | set(val) {
55 | config._filter = val;
56 | document.body.dataset.filterVideo = val === 'video' || val === 'all' || val === 'media';
57 | document.body.dataset.filterAudio = val === 'audio' || val === 'all' || val === 'media';
58 | document.body.dataset.filterImage = val === 'image' || val === 'all';
59 | document.body.dataset.filterApp = val === 'application' || val === 'all';
60 | $.filter.textContent = `Type (${val})`;
61 | persist.save('filter', val);
62 | }
63 | });
64 | Object.defineProperty(config, 'monitor', {
65 | enumerable: true,
66 | configurable: true,
67 | get() {
68 | return config._monitor;
69 | },
70 | set(val) {
71 | config._monitor = val;
72 | chrome.runtime.sendMessage(val ? 'resume' : 'pause');
73 | document.body.dataset.active = val;
74 | $.pause.dataset.cmd = val ? 'pause' : 'resume';
75 | $.pause.value = val ? 'Pause' : 'Resume';
76 | document.title = `Bulk Media Downloader (${val ? 'active' : 'paused'})`;
77 | }
78 | });
79 | Object.defineProperty(config, 'size', {
80 | enumerable: true,
81 | configurable: true,
82 | get() {
83 | return config._size;
84 | },
85 | set(val) {
86 | config._size = val;
87 | document.body.dataset.size = val;
88 | $.size.textContent = `Size (${val})`;
89 | persist.save('size', val);
90 | }
91 | });
92 |
93 | function notify(message) {
94 | chrome.storage.local.get({
95 | notify: true
96 | }, prefs => prefs.notify && chrome.notifications.create(null, {
97 | type: 'basic',
98 | iconUrl: '/data/icons/48.png',
99 | title: 'Bulk Media Downloader',
100 | message
101 | }));
102 | }
103 | function visible(e) {
104 | return Boolean(e.offsetWidth || e.offsetHeight || e.getClientRects().length);
105 | }
106 |
107 | function state() {
108 | const disabled = [...$.links.querySelectorAll('[type=checkbox]:checked')].filter(visible).length === 0;
109 | $.buttons.browser.disabled =
110 | $.buttons.links.disabled =
111 | $.external.run.disabled =
112 | disabled;
113 | }
114 |
115 | function isChecked(tr) {
116 | let checked = false;
117 | if ($.filters.all.checked) {
118 | checked = true;
119 | }
120 | else {
121 | if ($.filters.applications.checked) {
122 | checked = checked || (tr.dataset.type === 'application' || /\.(exe|xpi)/.test(tr.dataset.url));
123 | }
124 | if ($.filters.images.checked) {
125 | checked = checked || is.image(tr);
126 | }
127 | if ($.filters.videos.checked) {
128 | checked = checked || is.video(tr);
129 | }
130 | if ($.filters.audios.checked) {
131 | checked = checked || is.audio(tr);
132 | }
133 | if ($.filters.archives.checked) {
134 | checked = checked || is.archive(tr);
135 | }
136 | if ($.filters.documents.checked) {
137 | checked = checked || is.document(tr);
138 | }
139 | if ($.filters.tab.checked) {
140 | checked = checked || is.tab(tr);
141 | }
142 | if ($.filters.regexp.value) {
143 | try {
144 | const r = new RegExp($.filters.regexp.value);
145 | checked = checked || r.test(tr.dataset.url);
146 | if (tr.dataset.filename && tr.dataset.filename !== '-') {
147 | checked = checked || r.test(tr.dataset.filename);
148 | }
149 | }
150 | catch (e) {}
151 | }
152 | }
153 | return checked;
154 | }
155 |
156 | function bytesToSize(bytes) {
157 | if (bytes === 0 || bytes === '0') {
158 | return '0 Byte';
159 | }
160 | const k = 1024;
161 | const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
162 | const i = Math.floor(Math.log(bytes) / Math.log(k));
163 | return (bytes / Math.pow(k, i)).toFixed(i ? 1 : 0) + ' ' + sizes[i];
164 | }
165 | // display or hide a top menu
166 | document.addEventListener('click', e => {
167 | const cmd = e.target.dataset.cmd;
168 | $.head.dataset.select = cmd === 'toggle-select';
169 | $.head.dataset.filter = cmd === 'toggle-filter';
170 | $.head.dataset.size = cmd === 'toggle-size';
171 | });
172 |
173 | // toggle item's selection on click
174 | document.addEventListener('click', e => {
175 | const target = e.target;
176 | const tr = target.closest('tr');
177 | if (tr && tr.closest('#links')) {
178 | if (target.localName !== 'input') {
179 | const input = tr.querySelector('[type=checkbox]');
180 | input.checked = !input.checked;
181 | }
182 | state();
183 | }
184 | });
185 |
186 | // commands
187 | document.addEventListener('click', e => {
188 | const cmd = e.target.dataset.cmd;
189 | if (cmd === 'pause' || cmd === 'resume') {
190 | config.monitor = cmd === 'resume';
191 | }
192 | else if (cmd === 'clear') {
193 | $.tbody.textContent = '';
194 | urls = [];
195 | state();
196 | }
197 | else if (cmd === 'download-browser') {
198 | const items = [...$.links.querySelectorAll(':checked')]
199 | .filter(item => visible(item));
200 | if (items.length > 10) {
201 | if (!window.confirm('Are you sure you want to download ' + items.length + ' items at once?')) {
202 | return;
203 | }
204 | }
205 | items.map(e => e.closest('tr'))
206 | .forEach(tr => chrome.runtime.sendMessage({
207 | cmd,
208 | url: tr.dataset.url,
209 | referrer: tr.dataset.referrer,
210 | filename: tr.dataset.filename
211 | }));
212 | if (cmd === 'download-browser') {
213 | notify(items.length + ' link' + (items.length > 1 ? 's are' : ' is') + ' being downloaded');
214 | }
215 | }
216 | else if (cmd === 'copy-links') {
217 | const links = [...$.links.querySelectorAll(':checked')]
218 | .filter(item => visible(item))
219 | .map(e => e.closest('tr'))
220 | .map(tr => tr.dataset.url);
221 | document.oncopy = e => {
222 | e.clipboardData.setData('text/plain', links.join('\n'));
223 | e.preventDefault();
224 | };
225 | window.focus();
226 | document.execCommand('Copy', false, null);
227 | notify(links.length + ' link' + (links.length > 1 ? 's are' : ' is') + ' copied to the clipboard');
228 | }
229 | });
230 | // top menu selection or filter changes
231 | document.addEventListener('click', e => {
232 | const cmd = e.target.dataset.cmd;
233 |
234 | if (cmd && cmd.startsWith('select-')) {
235 | [...$.links.querySelectorAll('[type=checkbox]')]
236 | .forEach(e => {
237 | if (cmd === 'select-all' || cmd === 'select-none') {
238 | e.checked = cmd === 'select-all';
239 | }
240 | else {
241 | e.checked = is[cmd.replace('select-', '')](e.closest('tr'));
242 | }
243 | });
244 | state();
245 | }
246 | else if (cmd && cmd.startsWith('filter-')) {
247 | config.filter = cmd.replace('filter-', '');
248 | state();
249 | }
250 | else if (cmd && cmd.startsWith('size-')) {
251 | config.size = cmd.replace('size-', '');
252 | state();
253 | }
254 | });
255 |
256 | function findTitle(message) {
257 | if (message.disposition) {
258 | if (message.disposition.indexOf('inline') !== -1) {
259 | const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(message.disposition);
260 | if (matches && matches.length) {
261 | return matches[1].replace(/['"]/g, '');
262 | }
263 | }
264 | else {
265 | const matches = /filename=([^;]*)/.exec(message.disposition);
266 | if (matches && matches.length) {
267 | return matches[1].replace(/["']$/, '').replace(/^["']/, '');
268 | }
269 | }
270 | }
271 | let name = message.url.split('/').pop().split('?').shift();
272 | let extension = /\.([^.]+)$/.exec(name);
273 | if (extension && extension.length) {
274 | extension = extension[1];
275 | name = name.replace('.' + extension, '');
276 | }
277 | else {
278 | extension = message.type.split('/').pop().split('+').shift().split(';').shift();
279 | }
280 | return name + '.' + extension;
281 | }
282 |
283 | const referrer = (() => {
284 | const cache = {};
285 |
286 | chrome.tabs.onUpdated.addListener((tabId, changeInfo) => {
287 | if (changeInfo.url) {
288 | cache[tabId] = changeInfo.url;
289 | }
290 | });
291 |
292 | return (id, tr) => {
293 | if (cache[id]) {
294 | tr.dataset.referrer = cache[id];
295 | }
296 | else {
297 | chrome.tabs.get(id, t => {
298 | cache[id] = t.url;
299 | tr.dataset.referrer = cache[id];
300 | });
301 | }
302 | };
303 | })();
304 |
305 | chrome.runtime.onMessage.addListener(message => {
306 | if (message.cmd === 'append') {
307 | if (urls.indexOf(message.url) !== -1) {
308 | return;
309 | }
310 | const tr = $.tr.cloneNode(true);
311 | const tds = tr.querySelectorAll('td');
312 | tds[1].title = tds[1].textContent = message.type.split(';').shift();
313 | tds[2].textContent = isNaN(message.length) ? 'N/A' : bytesToSize(message.length);
314 | tds[3].title = tds[3].textContent = message.url;
315 | tds[4].title = tds[4].textContent = (new Date()).toLocaleTimeString();
316 | tds[6].title = tds[6].textContent = message.tabId;
317 |
318 | Object.assign(tr.dataset, {
319 | id: message.id,
320 | url: message.url,
321 | type: message.type.split('/')[0],
322 | size: isNaN(message.length) || message.length > 10 * 1024 * 1024 ? 'iii' : (
323 | message.length > 1 * 1024 * 1024 ? 'ii' : (
324 | message.length > 100 * 1024 ? 'i' : ''
325 | )
326 | )
327 | });
328 | referrer(message.tabId, tr);
329 |
330 | tr.dataset.filename = tds[5].title = tds[5].textContent = findTitle(message);
331 |
332 | tr.dataset.tabId = message.tabId;
333 |
334 | const shouldScroll = $.links.scrollHeight - $.links.clientHeight === $.links.scrollTop;
335 | $.tbody.appendChild(tr);
336 | if (shouldScroll) {
337 | $.links.scrollTop = $.links.scrollHeight - $.links.clientHeight;
338 | }
339 | tr.querySelector('input').checked = isChecked(tr);
340 | state();
341 | $.stats.textContent = message.stats.media + '/' + message.stats.total;
342 | urls.push(message.url);
343 | }
344 | else if (message.cmd === 'error') {
345 | const tr = document.querySelector(`[data-id="${message.id}"]`);
346 | if (tr) {
347 | tr.dataset.error = true;
348 | const tds = tr.querySelectorAll('td');
349 | tds[5].textContent = message.msg;
350 | }
351 | }
352 | else if (message.cmd === 'update-id') {
353 | document.body.dataset.tabId = message.id;
354 | update();
355 | }
356 | });
357 | // load
358 | chrome.storage.local.get({
359 | filter: 'media',
360 | size: 'all'
361 | }, prefs => {
362 | Object.assign(config, prefs);
363 | });
364 | // unload
365 | const port = chrome.runtime.connect({
366 | name: 'window'
367 | });
368 |
369 | window.addEventListener('beforeunload', () => {
370 | port.postMessage({
371 | method: 'resize',
372 | left: window.screenX,
373 | top: window.screenY,
374 | width: Math.max(window.outerWidth, 100),
375 | height: Math.max(window.outerHeight, 100)
376 | });
377 | });
378 |
379 |
--------------------------------------------------------------------------------
/v3/data/window/index.js:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2025 InBasic
2 | *
3 | * This Source Code Form is subject to the terms of the Mozilla Public
4 | * License, v. 2.0. If a copy of the MPL was not distributed with this
5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 |
7 | * Home: https://webextension.org/listing/bulk-media-downloader.html
8 | * GitHub: https://github.com/inbasic/bulk-media-downloader/
9 | */
10 |
11 | /* globals $, persist */
12 | 'use strict';
13 |
14 | document.body.dataset.os = navigator.userAgent.includes('Firefox') ? 'firefox' : (
15 | navigator.userAgent.includes('OPR') ? 'opera' : 'chrome'
16 | );
17 | if (window.location.search) {
18 | document.body.dataset.tabId = window.location.search.replace('?tabId=', '');
19 | }
20 |
21 | const stats = {
22 | total: 0,
23 | media: 0
24 | };
25 |
26 | const ui = {
27 | append(request) {
28 | if (urls.indexOf(request.url) !== -1) {
29 | return;
30 | }
31 | const tr = $.tr.cloneNode(true);
32 | const tds = tr.querySelectorAll('td');
33 | tds[1].title = tds[1].textContent = request.type.split(';').shift();
34 | tds[2].textContent = isNaN(request.length) ? 'N/A' : bytesToSize(request.length);
35 | tds[3].title = tds[3].textContent = request.url;
36 | tds[4].title = tds[4].textContent = (new Date()).toLocaleTimeString();
37 | tds[6].title = tds[6].textContent = request.tabId;
38 |
39 | Object.assign(tr.dataset, {
40 | id: request.id,
41 | url: request.url,
42 | type: request.type.split('/')[0],
43 | size: isNaN(request.length) || request.length > 10 * 1024 * 1024 ? 'iii' : (
44 | request.length > 1 * 1024 * 1024 ? 'ii' : (
45 | request.length > 100 * 1024 ? 'i' : ''
46 | )
47 | )
48 | });
49 | referrer(request.tabId, tr);
50 |
51 | tr.dataset.filename = tds[5].title = tds[5].textContent = findTitle(request);
52 |
53 | tr.dataset.tabId = request.tabId;
54 |
55 | const shouldScroll = $.links.scrollHeight - $.links.clientHeight === $.links.scrollTop;
56 | $.tbody.appendChild(tr);
57 | if (shouldScroll) {
58 | $.links.scrollTop = $.links.scrollHeight - $.links.clientHeight;
59 | }
60 | tr.querySelector('input').checked = isChecked(tr);
61 | state();
62 | $.stats.textContent = request.stats.media + '/' + request.stats.total;
63 | urls.push(request.url);
64 | }
65 | };
66 |
67 | const monitor = {
68 | observe: d => {
69 | if (d.tabId === -1) {
70 | return;
71 | }
72 | // prevent YouTube video link detection
73 | if (d.url.indexOf('googlevideo.') !== -1) {
74 | return;
75 | }
76 | let type = d.responseHeaders.filter(o => o.name === 'content-type' || o.name === 'Content-Type');
77 |
78 | // remove range from stream URL if possible;
79 | d.url = d.url.replace(/&range=\d+-\d+/, '');
80 |
81 | if (type.length) {
82 | stats.total += 1;
83 | type = type[0].value;
84 |
85 | const length = d.responseHeaders
86 | .filter(o => o.name === 'content-length' || o.name === 'Content-Length')
87 | .map(l => l.value).shift();
88 |
89 | if (
90 | type.startsWith('image') ||
91 | type.startsWith('video') ||
92 | type.startsWith('audio') ||
93 | (type.startsWith('application') && type.indexOf('javascript') === -1)
94 | ) {
95 | stats.media += 1;
96 | ui.append({
97 | id: d.requestId,
98 | url: d.url,
99 | otype: d.type,
100 | tabId: d.tabId,
101 | timeStamp: d.timeStamp,
102 | methd: d.method,
103 | length,
104 | disposition: d.responseHeaders
105 | .filter(o => o.name === 'content-disposition' || o.name === 'Content-Disposition')
106 | .map(o => o.value)
107 | .shift(),
108 | type,
109 | stats
110 | });
111 | }
112 | }
113 | },
114 | activate: () => {
115 | chrome.webRequest.onHeadersReceived.addListener(monitor.observe,
116 | {urls: ['*://*/*']},
117 | ['responseHeaders']
118 | );
119 | chrome.action.setBadgeText({text: 'R'});
120 | },
121 | deactivate: () => {
122 | chrome.webRequest.onHeadersReceived.removeListener(monitor.observe);
123 | chrome.action.setBadgeText({text: ''});
124 | }
125 | };
126 | monitor.activate();
127 |
128 | const update = (function(callback) {
129 | $.filters.parent.addEventListener('change', callback);
130 | $.filters.parent.addEventListener('keyup', callback);
131 |
132 | return () => callback();
133 | })(function() {
134 | [...$.tbody.querySelectorAll('tr')]
135 | .forEach(tr => tr.querySelector('[type=checkbox]').checked = isChecked(tr));
136 | state();
137 | });
138 |
139 | const is = {
140 | application: tr => tr.dataset.type === 'application',
141 | document: tr => tr.dataset.type === 'document' || /\.(txt|docm|xps|odc|otc|odb|odf|odft|odg|otg|odi|oti|odp|otp|ods|ots|odt|odm|ott|oth|pptx|sldx|ppsx|potx|xlsx|xltx|docx|dotx)$/.test(tr.dataset.url),
142 | video: tr => tr.dataset.type === 'video' || /\.(3gp|3g2|h261|h263|h264|jpgv|jpm|jpgm|mj2|mjp2|ts|mp4|mp4v|mpg4|mpeg|mpg|mpe|m1v|m2v|ogv|qt|mov|uvh|uvvh|uvm|uvvm|uvp|uvvp|uvs|uvvs|uvv|uvvv|dvb|fvt|mxu|m4u|pyv|uvu|uvvu|viv|webm|f4v|fli|flv|m4v|mkv|mk3d|mks|mng|asf|asx|vob|wm|wmv|wmx|wvx|avi|movie|smv)$/.test(tr.dataset.url),
143 | audio: tr => tr.dataset.type === 'audio' || /\.(adp|au|snd|mid|midi|kar|rmi|m4a|mp3|mpga|mp2|mp2a|m2a|m3a|oga|ogg|spx|s3m|sil|uva|uvva|eol|dra|dts|dtshd|lvp|pya|rip|weba|aac|aif|aiff|aifc|caf|flac|mka|m3u|wax|wma|ra|rmp|wav)$/.test(tr.dataset.url),
144 | archive: tr => tr.dataset.type === 'archive' || /\.(zip|rar|jar|apk|xpi|crx|joda|tao)$/.test(tr.dataset.url),
145 | image: tr => tr.dataset.type === 'image' || /\.(bmp|cgm|g3|gif|ief|jpeg|jpg|jpe|ktx|png|btif|sgi|svg|svgz|tiff|tif|psd|uvi|uvvi|uvg|uvvg|djv|sub|dwg|dxf|fbs|fpx|fst|mmr|rlc|mdi|wdp|npx|wbmp|xif|webp|3ds|ras|cmx|fh|fhc|fh4|fh5|fh7|ico|sid|pcx|pic|pct|pnm|pbm|pgm|ppm|rgb|tga|xbm|xpm|xwd)$/.test(tr.dataset.url),
146 | tab: tr => tr.dataset.tabId === document.body.dataset.tabId
147 | };
148 |
149 | let urls = [];
150 |
151 | const config = {
152 | _filter: 'all',
153 | _monitor: true,
154 | _size: 'all' // 'all', '100k', '1m', '10m'
155 | };
156 | Object.defineProperty(config, 'filter', {
157 | enumerable: true,
158 | configurable: true,
159 | get() {
160 | return config._filter;
161 | },
162 | set(val) {
163 | config._filter = val;
164 | document.body.dataset.filterVideo = val === 'video' || val === 'all' || val === 'media';
165 | document.body.dataset.filterAudio = val === 'audio' || val === 'all' || val === 'media';
166 | document.body.dataset.filterImage = val === 'image' || val === 'all';
167 | document.body.dataset.filterApp = val === 'application' || val === 'all';
168 | $.filter.textContent = `Type (${val})`;
169 | persist.save('filter', val);
170 | }
171 | });
172 | Object.defineProperty(config, 'monitor', {
173 | enumerable: true,
174 | configurable: true,
175 | get() {
176 | return config._monitor;
177 | },
178 | set(val) {
179 | config._monitor = val;
180 | if (val) {
181 | monitor.activate();
182 | }
183 | else {
184 | monitor.deactivate();
185 | }
186 | document.body.dataset.active = val;
187 | $.pause.dataset.cmd = val ? 'pause' : 'resume';
188 | $.pause.value = val ? 'Pause' : 'Resume';
189 | document.title = `Bulk Media Downloader (${val ? 'active' : 'paused'})`;
190 | }
191 | });
192 | Object.defineProperty(config, 'size', {
193 | enumerable: true,
194 | configurable: true,
195 | get() {
196 | return config._size;
197 | },
198 | set(val) {
199 | config._size = val;
200 | document.body.dataset.size = val;
201 | $.size.textContent = `Size (${val})`;
202 | persist.save('size', val);
203 | }
204 | });
205 |
206 | async function notify(message) {
207 | const prefs = await chrome.storage.local.get({
208 | notify: true
209 | });
210 | if (prefs.notify) {
211 | const id = await chrome.notifications.create({
212 | type: 'basic',
213 | iconUrl: '/data/icons/48.png',
214 | title: 'Bulk Media Downloader',
215 | message
216 | });
217 | setTimeout(chrome.notifications.clear, 3000, id);
218 | }
219 | }
220 | function visible(e) {
221 | return Boolean(e.offsetWidth || e.offsetHeight || e.getClientRects().length);
222 | }
223 |
224 | function state() {
225 | const disabled = [...$.links.querySelectorAll('[type=checkbox]:checked')].filter(visible).length === 0;
226 | $.buttons.browser.disabled =
227 | $.buttons.links.disabled =
228 | $.external.run.disabled =
229 | disabled;
230 | }
231 |
232 | function isChecked(tr) {
233 | let checked = false;
234 | if ($.filters.all.checked) {
235 | checked = true;
236 | }
237 | else {
238 | if ($.filters.applications.checked) {
239 | checked = checked || (tr.dataset.type === 'application' || /\.(exe|xpi)/.test(tr.dataset.url));
240 | }
241 | if ($.filters.images.checked) {
242 | checked = checked || is.image(tr);
243 | }
244 | if ($.filters.videos.checked) {
245 | checked = checked || is.video(tr);
246 | }
247 | if ($.filters.audios.checked) {
248 | checked = checked || is.audio(tr);
249 | }
250 | if ($.filters.archives.checked) {
251 | checked = checked || is.archive(tr);
252 | }
253 | if ($.filters.documents.checked) {
254 | checked = checked || is.document(tr);
255 | }
256 | if ($.filters.tab.checked) {
257 | checked = checked || is.tab(tr);
258 | }
259 | if ($.filters.regexp.value) {
260 | try {
261 | const r = new RegExp($.filters.regexp.value);
262 | checked = checked || r.test(tr.dataset.url);
263 | if (tr.dataset.filename && tr.dataset.filename !== '-') {
264 | checked = checked || r.test(tr.dataset.filename);
265 | }
266 | }
267 | catch (e) {}
268 | }
269 | }
270 | return checked;
271 | }
272 |
273 | function bytesToSize(bytes) {
274 | if (bytes === 0 || bytes === '0') {
275 | return '0 Byte';
276 | }
277 | const k = 1024;
278 | const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
279 | const i = Math.floor(Math.log(bytes) / Math.log(k));
280 | return (bytes / Math.pow(k, i)).toFixed(i ? 1 : 0) + ' ' + sizes[i];
281 | }
282 | // display or hide a top menu
283 | document.addEventListener('click', e => {
284 | const cmd = e.target.dataset.cmd;
285 | $.head.dataset.select = cmd === 'toggle-select';
286 | $.head.dataset.filter = cmd === 'toggle-filter';
287 | $.head.dataset.size = cmd === 'toggle-size';
288 | });
289 |
290 | // toggle item's selection on click
291 | document.addEventListener('click', e => {
292 | const target = e.target;
293 | const tr = target.closest('tr');
294 | if (tr && tr.closest('#links')) {
295 | if (target.localName !== 'input') {
296 | const input = tr.querySelector('[type=checkbox]');
297 | input.checked = !input.checked;
298 | }
299 | state();
300 | }
301 | });
302 |
303 | // commands
304 | document.addEventListener('click', async e => {
305 | const cmd = e.target.dataset.cmd;
306 | if (cmd === 'pause' || cmd === 'resume') {
307 | config.monitor = cmd === 'resume';
308 | }
309 | else if (cmd === 'clear') {
310 | $.tbody.textContent = '';
311 | urls = [];
312 | state();
313 | }
314 | else if (cmd === 'download-browser') {
315 | const items = [...$.links.querySelectorAll(':checked')]
316 | .filter(item => visible(item));
317 | if (items.length > 10) {
318 | if (!window.confirm('Are you sure you want to download ' + items.length + ' items at once?')) {
319 | return;
320 | }
321 | }
322 | notify(items.length + ' link' + (items.length > 1 ? 's are' : ' is') + ' being downloaded');
323 | for (let i = 0; i < items.length; i += 5) {
324 | for (let j = 0; j < 5; j += 1) {
325 | const tr = items[i + j]?.closest('tr');
326 | if (tr) {
327 | const options = {
328 | url: tr.dataset.url
329 | };
330 | const filename = tr.dataset.filename;
331 | if (filename && filename !== '-') {
332 | options.filename = filename
333 | .replace(/[`~!@#$%^&*()_|+\-=?;:'",<>{}[\]\\/]/gi, '');
334 | }
335 |
336 | chrome.downloads.download(options, () => {
337 | if (chrome.runtime.lastError) {
338 | delete options.filename;
339 | chrome.downloads.download(options);
340 | }
341 | });
342 | }
343 | }
344 | await new Promise(resolve => setTimeout(resolve, 2000));
345 | }
346 | }
347 | else if (cmd === 'copy-links') {
348 | const links = [...$.links.querySelectorAll(':checked')]
349 | .filter(item => visible(item))
350 | .map(e => e.closest('tr'))
351 | .map(tr => tr.dataset.url);
352 | document.oncopy = e => {
353 | e.clipboardData.setData('text/plain', links.join('\n'));
354 | e.preventDefault();
355 | };
356 | window.focus();
357 | document.execCommand('Copy', false, null);
358 | notify(links.length + ' link' + (links.length > 1 ? 's are' : ' is') + ' copied to the clipboard');
359 | }
360 | });
361 | // top menu selection or filter changes
362 | document.addEventListener('click', e => {
363 | const cmd = e.target.dataset.cmd;
364 |
365 | if (cmd && cmd.startsWith('select-')) {
366 | [...$.links.querySelectorAll('[type=checkbox]')]
367 | .forEach(e => {
368 | if (cmd === 'select-all' || cmd === 'select-none') {
369 | e.checked = cmd === 'select-all';
370 | }
371 | else {
372 | e.checked = is[cmd.replace('select-', '')](e.closest('tr'));
373 | }
374 | });
375 | state();
376 | }
377 | else if (cmd && cmd.startsWith('filter-')) {
378 | config.filter = cmd.replace('filter-', '');
379 | state();
380 | }
381 | else if (cmd && cmd.startsWith('size-')) {
382 | config.size = cmd.replace('size-', '');
383 | state();
384 | }
385 | });
386 |
387 | function findTitle(message) {
388 | if (message.disposition) {
389 | if (message.disposition.indexOf('inline') !== -1) {
390 | const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(message.disposition);
391 | if (matches && matches.length) {
392 | return matches[1].replace(/['"]/g, '');
393 | }
394 | }
395 | else {
396 | const matches = /filename=([^;]*)/.exec(message.disposition);
397 | if (matches && matches.length) {
398 | return matches[1].replace(/["']$/, '').replace(/^["']/, '');
399 | }
400 | }
401 | }
402 | let name = message.url.split('/').pop().split('?').shift();
403 | let extension = /\.([^.]+)$/.exec(name);
404 | if (extension && extension.length) {
405 | extension = extension[1];
406 | name = name.replace('.' + extension, '');
407 | }
408 | else {
409 | extension = message.type.split('/').pop().split('+').shift().split(';').shift();
410 | }
411 | return name + '.' + extension;
412 | }
413 |
414 | const referrer = (() => {
415 | const cache = {};
416 |
417 | chrome.tabs.onUpdated.addListener((tabId, changeInfo) => {
418 | if (changeInfo.url) {
419 | cache[tabId] = changeInfo.url;
420 | }
421 | });
422 |
423 | return (id, tr) => {
424 | if (cache[id]) {
425 | tr.dataset.referrer = cache[id];
426 | }
427 | else {
428 | chrome.tabs.get(id, t => {
429 | cache[id] = t.url;
430 | tr.dataset.referrer = cache[id];
431 | });
432 | }
433 | };
434 | })();
435 |
436 | chrome.runtime.onMessage.addListener((message, sender, response) => {
437 | if (message.cmd === 'update-id') {
438 | document.body.dataset.tabId = message.id;
439 | update();
440 | }
441 | else if (message.cmd === 'bring-to-front') {
442 | response(true);
443 | chrome.runtime.sendMessage({cmd: 'focus'});
444 | }
445 | });
446 |
447 | // load
448 | chrome.storage.local.get({
449 | filter: 'all',
450 | size: 'all'
451 | }, prefs => {
452 | Object.assign(config, prefs);
453 | });
454 |
455 | // resize
456 | addEventListener('resize', () => {
457 | chrome.storage.local.set({
458 | width: Math.max(window.outerWidth, 100),
459 | height: Math.max(window.outerHeight, 100)
460 | });
461 | });
462 |
463 | // unload
464 | addEventListener('beforeunload', () => {
465 | monitor.deactivate();
466 | });
467 |
468 |
--------------------------------------------------------------------------------
/v2/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
374 |
--------------------------------------------------------------------------------
/v3/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
374 |
--------------------------------------------------------------------------------