]> git.p6c8.net - jirafeau.git/blob - lib/functions.js.php
17c6d0b8818f74b6c7298db4fcc678328328cd5a
[jirafeau.git] / lib / functions.js.php
1 <?php
2 /*
3 * Jirafeau, your web file repository
4 * Copyright (C) 2015 Jerome Jutteau <jerome@jutteau.fr>
5 * Copyright (C) 2015 Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 function template_js_preview_link() {
22 ?>
23 if (!!document.getElementById('preview_link'))
24 {
25 document.getElementById('upload_finished_preview').style.display = 'none';
26 var preview_link_href = 'f.php?h=' + reference + '&p=1';
27 if (crypt_key.length > 0)
28 {
29 preview_link_href += '&k=' + crypt_key;
30 }
31
32 // Test if content can be previewed
33 type = document.getElementById('file_select').files[0].type;
34 if ((type.startsWith('image/')
35 || type.startsWith('audio')
36 || type.startsWith('text/plain')
37 || type.startsWith('video/'))
38 && !type.includes('image/svg+xml'))
39 {
40 document.getElementById('preview_link').href = preview_link_href;
41 document.getElementById('preview_link_text').innerHTML = web_root + preview_link_href;
42 document.getElementById('upload_finished_preview').style.display = '';
43 }
44 }
45 <?php
46 }
47 function template_js_download_page() {
48 ?>
49 // Download page
50 var download_link_href = 'f.php?h=' + reference;
51 if (crypt_key.length > 0)
52 {
53 download_link_href += '&k=' + crypt_key;
54 }
55 if (!!document.getElementById('upload_finished_download_page'))
56 {
57 document.getElementById('upload_link').href = download_link_href;
58 document.getElementById('upload_link_text').innerHTML = web_root + download_link_href;
59 }
60 <?php
61 }
62 function template_js_email_link() {
63 ?>
64 // Email link
65 var b = encodeURIComponent("<?php echo t("DL"); ?> \"" + filename + "\":") + "%0D" + "%0A";
66 b += encodeURIComponent(web_root + download_link_href) + "%0D" + "%0A";
67 if (false == isEmpty(date))
68 {
69 b += "%0D" + "%0A" + encodeURIComponent("<?php echo t("VALID_UNTIL"); ?>: " + date.format('YYYY-MM-DD hh:mm (GMT O)')) + "%0D" + "%0A";
70 document.getElementById('upload_link_email').href = "mailto:?body=" + b + "&subject=" + encodeURIComponent(filename);
71 }
72 <?php
73 }
74 function template_js_delete_link() {
75 ?>
76 // Delete link
77 var delete_link_href = 'f.php?h=' + reference + '&d=' + delete_code;
78 document.getElementById('delete_link').href = delete_link_href;
79 document.getElementById('delete_link_text').innerHTML = web_root + delete_link_href;
80 <?php
81 }
82 function template_js_direct_download() {
83 ?>
84 // Direct download link
85 var direct_download_link_href = 'f.php?h=' + reference + '&d=1';
86 if (crypt_key.length > 0)
87 {
88 direct_download_link_href += '&k=' + crypt_key;
89 }
90 document.getElementById('direct_link').href = direct_download_link_href;
91 document.getElementById('direct_link_text').innerHTML = web_root + direct_download_link_href;
92 <?php
93 }
94 function template_js_date_function() {
95 ?>
96 // Validity date
97 if (isEmpty(date))
98 {
99 document.getElementById('date').style.display = 'none';
100 }
101 else {
102 document.getElementById('date').innerHTML =
103 '<span class="datetime"'
104 + 'data-datetime="'
105 + dateToUtcString(date) + ' (GMT"'
106 + 'title="'
107 + dateToUtcString(date) + ' (GMT)">'
108 + date.format('YYYY-MM-DD hh:mm (GMT O)')
109 + '</span>';
110 document.getElementById('date').style.display = '';
111 }
112 <?php
113 }
114
115
116
117
118 header('Content-Type: text/javascript');
119 define('JIRAFEAU_ROOT', dirname(__FILE__) . '/../');
120
121 require(JIRAFEAU_ROOT . 'lib/settings.php');
122 require(JIRAFEAU_ROOT . 'lib/functions.php');
123 require(JIRAFEAU_ROOT . 'lib/lang.php');
124
125 ?>
126 // @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
127 var web_root = "<?php echo $cfg['web_root']; ?>";
128
129 var lang_array = <?php echo json_lang_generator(null); ?>;
130 var lang_array_fallback = <?php echo json_lang_generator("en"); ?>;
131
132 function translate (expr) {
133 if (lang_array.hasOwnProperty(expr)) {
134 var e = lang_array[expr];
135 if (!isEmpty(e))
136 return e;
137 }
138 if (lang_array_fallback.hasOwnProperty(expr)) {
139 var e = lang_array_fallback[expr];
140 if (!isEmpty(e))
141 return e;
142 }
143 return "FIXME: " + expr;
144 }
145
146 function isEmpty(str) {
147 return (!str || 0 === str.length);
148 }
149
150 // Extend date object with format method
151 Date.prototype.format = function(format) {
152 format = format || 'YYYY-MM-DD hh:mm';
153
154 var zeropad = function(number, length) {
155 number = number.toString();
156 length = length || 2;
157 while(number.length < length)
158 number = '0' + number;
159 return number;
160 },
161 formats = {
162 YYYY: this.getFullYear(),
163 MM: zeropad(this.getMonth() + 1),
164 DD: zeropad(this.getDate()),
165 hh: zeropad(this.getHours()),
166 mm: zeropad(this.getMinutes()),
167 O: (function() {
168 localDate = new Date;
169 sign = (localDate.getTimezoneOffset() > 0) ? '-' : '+';
170 offset = Math.abs(localDate.getTimezoneOffset());
171 hours = zeropad(Math.floor(offset / 60));
172 minutes = zeropad(offset % 60);
173 return sign + hours + ":" + minutes;
174 })()
175 },
176 pattern = '(' + Object.keys(formats).join(')|(') + ')';
177
178 return format.replace(new RegExp(pattern, 'g'), function(match) {
179 return formats[match];
180 });
181 };
182
183 function dateFromUtcString(datestring) {
184 // matches »YYYY-MM-DD hh:mm«
185 var m = datestring.match(/(\d+)-(\d+)-(\d+)\s+(\d+):(\d+)/);
186 return new Date(Date.UTC(+m[1], +m[2] - 1, +m[3], +m[4], +m[5], 0));
187 }
188
189 function dateFromUtcTimestamp(datetimestamp) {
190 return new Date(parseInt(datetimestamp) * 1000)
191 }
192
193 function dateToUtcString(datelocal) {
194 return new Date(
195 datelocal.getUTCFullYear(),
196 datelocal.getUTCMonth(),
197 datelocal.getUTCDate(),
198 datelocal.getUTCHours(),
199 datelocal.getUTCMinutes(),
200 datelocal.getUTCSeconds()
201 ).format();
202 }
203
204 function dateToUtcTimestamp(datelocal) {
205 return (Date.UTC(
206 datelocal.getUTCFullYear(),
207 datelocal.getUTCMonth(),
208 datelocal.getUTCDate(),
209 datelocal.getUTCHours(),
210 datelocal.getUTCMinutes(),
211 datelocal.getUTCSeconds()
212 ) / 1000);
213 }
214
215 function convertAllDatetimeFields() {
216 datefields = document.getElementsByClassName('datetime')
217 for(var i=0; i<datefields.length; i++) {
218 dateUTC = datefields[i].getAttribute('data-datetime');
219 datefields[i].setAttribute('title', dateUTC + ' (GMT)');
220 datefields[i].innerHTML = dateFromUtcString(dateUTC).format('YYYY-MM-DD hh:mm (GMT O)');
221 }
222 }
223
224 // evil copy and paste from show_link - TODO refactor show link
225 function show_link_from_php (file_name,file_type, reference, delete_code, crypt_key, date)
226 {
227 <?php template_js_download_page(); ?>
228
229
230 var filename = file_name;
231 <?php template_js_email_link(); ?>
232 <?php template_js_delete_link(); ?>
233 <?php template_js_date_function(); ?>
234 var type = file_type;
235 <?php template_js_direct_download();?>
236 }
237
238
239
240 function show_link (reference, delete_code, crypt_key, date)
241 {
242 // Upload finished
243 document.getElementById('uploading').style.display = 'none';
244 document.getElementById('upload').style.display = 'none';
245 document.getElementById('upload_finished').style.display = '';
246 document.title = "100% - <?php echo empty($cfg['title']) ? 'Jirafeau' : $cfg['title']; ?>";
247
248 <?php template_js_download_page(); ?>
249 // Email link
250 var filename = document.getElementById('file_select').files[0].name;
251
252 <?php template_js_email_link(); ?>
253
254 <?php template_js_delete_link(); ?>
255 <?php template_js_date_function(); ?>
256
257
258 // Preview link (if allowed)
259
260 var type = document.getElementById('file_select').files[0].type;
261 <?php template_js_preview_link(); ?>
262
263 <?php template_js_direct_download();?>
264
265
266 // Hide preview and direct download link if password is set
267 if (document.getElementById('input_key').value.length > 0)
268 {
269 if (!!document.getElementById('preview_link'))
270 document.getElementById('upload_finished_preview').style.display = 'none';
271 document.getElementById('upload_direct_download').style.display = 'none';
272 }
273 }
274
275 function show_upload_progression (percentage, speed, time_left)
276 {
277 document.getElementById('uploaded_percentage').innerHTML = percentage;
278 document.getElementById('uploaded_speed').innerHTML = speed;
279 document.getElementById('uploaded_time').innerHTML = time_left;
280 document.title = percentage + " - <?php echo empty($cfg['title']) ? 'Jirafeau' : $cfg['title']; ?>";
281 }
282
283 function hide_upload_progression ()
284 {
285 document.getElementById('uploaded_percentage').style.display = 'none';
286 document.getElementById('uploaded_speed').style.display = 'none';
287 document.getElementById('uploaded_time').style.display = 'none';
288 document.title = "<?php echo empty($cfg['title']) ? 'Jirafeau' : $cfg['title']; ?>";
289 }
290
291 function upload_progress (e)
292 {
293 if (e == undefined || e == null || !e.lengthComputable)
294 return;
295
296 // Init time estimation if needed
297 if (upload_time_estimation_total_size == 0)
298 upload_time_estimation_total_size = e.total;
299
300 // Compute percentage
301 var p = Math.round (e.loaded * 100 / e.total);
302 var p_str = ' ';
303 if (p != 100)
304 p_str = p.toString() + '%';
305 // Update estimation speed
306 upload_time_estimation_add(e.loaded);
307 // Get speed string
308 var speed_str = upload_time_estimation_speed_string();
309 speed_str = upload_speed_refresh_limiter(speed_str);
310 // Get time string
311 var time_str = chrono_update(upload_time_estimation_time());
312
313 show_upload_progression (p_str, speed_str, time_str);
314 }
315
316 function control_selected_file_size(max_size, error_str)
317 {
318 f_size = document.getElementById('file_select').files[0].size;
319 if (max_size > 0 && f_size > max_size * 1024 * 1024)
320 {
321 pop_failure(error_str);
322 document.getElementById('send').style.display = 'none';
323 }
324 else
325 {
326 // add class to restyle upload form in next step
327 document.getElementById('upload').setAttribute('class', 'file-selected');
328 // display options
329 document.getElementById('options').style.display = 'block';
330 document.getElementById('send').style.display = 'block';
331 document.getElementById('error_pop').style.display = 'none';
332 document.getElementById('send').focus();
333 }
334 }
335
336 function XHRErrorHandler(e)
337 {
338 var text = "${e.type}: ${e.loaded} bytes transferred"
339 console.log(text)
340 }
341
342 function pop_failure (e)
343 {
344 var text = "<p>An error occured";
345 if (typeof e !== 'undefined')
346 text += ": " + e;
347 text += "</p>";
348 document.getElementById('error_pop').innerHTML = e;
349
350 document.getElementById('uploading').style.display = 'none';
351 document.getElementById('error_pop').style.display = '';
352 document.getElementById('upload').style.display = '';
353 document.getElementById('send').style.display = '';
354 }
355
356 function add_time_string_to_date(d, time)
357 {
358 if(typeof(d) != 'object' || !(d instanceof Date))
359 {
360 return false;
361 }
362
363 if (time == 'minute')
364 {
365 d.setSeconds (d.getSeconds() + 60);
366 return true;
367 }
368 if (time == 'hour')
369 {
370 d.setSeconds (d.getSeconds() + 3600);
371 return true;
372 }
373 if (time == 'day')
374 {
375 d.setSeconds (d.getSeconds() + 86400);
376 return true;
377 }
378 if (time == 'week')
379 {
380 d.setSeconds (d.getSeconds() + 604800);
381 return true;
382 }
383 if (time == 'fortnight')
384 {
385 d.setSeconds (d.getSeconds() + 1209600);
386 return true;
387 }
388 if (time == 'month')
389 {
390 d.setSeconds (d.getSeconds() + 2592000);
391 return true;
392 }
393 if (time == 'quarter')
394 {
395 d.setSeconds (d.getSeconds() + 7776000);
396 return true;
397 }
398 if (time == 'year')
399 {
400 d.setSeconds (d.getSeconds() + 31536000);
401 return true;
402 }
403 return false;
404 }
405
406 function classic_upload (file, time, password, one_time)
407 {
408 // Delay time estimation init as we can't have file size
409 upload_time_estimation_init(0);
410
411 var req = new XMLHttpRequest ();
412 req.upload.addEventListener ("progress", upload_progress, false);
413 req.addEventListener ("error", XHRErrorHandler, false);
414 req.addEventListener ("abort", XHRErrorHandler, false);
415 req.onreadystatechange = function ()
416 {
417 if (req.readyState == 4 && req.status == 200)
418 {
419 var res = req.responseText;
420
421 // if response starts with "Error" then show a failure
422 if (/^Error/.test(res))
423 {
424 pop_failure (res);
425 return;
426 }
427
428 res = res.split ("\n");
429 var expiryDate = '';
430 if (time != 'none')
431 {
432 // convert time (local time + selected expiry date)
433 var localDatetime = new Date();
434 if(!add_time_string_to_date(localDatetime, time))
435 {
436 pop_failure ('Error: Date can not be parsed');
437 return;
438 }
439 expiryDate = localDatetime;
440 }
441
442 show_link (res[0], res[1], res[2], expiryDate);
443 }
444 else
445 {
446 pop_failure ("<?php echo t("ERR_OCC"); ?>");
447 }
448 }
449 req.open ("POST", 'script.php' , true);
450
451 var form = new FormData();
452 form.append ("file", file);
453 if (time)
454 form.append ("time", time);
455 if (password)
456 form.append ("key", password);
457 if (one_time)
458 form.append ("one_time_download", '1');
459 req.send (form);
460 }
461
462 function check_html5_file_api ()
463 {
464 return window.File && window.FileReader && window.FileList && window.Blob;
465 }
466
467 var async_global_transfered = 0;
468 var async_global_file;
469 var async_global_ref = '';
470 var async_global_max_size = 0;
471 var async_global_time;
472 var async_global_transfering = 0;
473 var async_global_last_code;
474
475 function async_upload_start (max_size, file, time, password, one_time)
476 {
477 async_global_transfered = 0;
478 async_global_file = file;
479 async_global_max_size = max_size;
480 async_global_time = time;
481
482 var req = new XMLHttpRequest ();
483 req.addEventListener ("error", XHRErrorHandler, false);
484 req.addEventListener ("abort", XHRErrorHandler, false);
485 req.onreadystatechange = function ()
486 {
487 if (req.readyState == 4 && req.status == 200)
488 {
489 var res = req.responseText;
490
491 if (/^Error/.test(res))
492 {
493 pop_failure (res);
494 return;
495 }
496
497 res = res.split ("\n");
498 async_global_ref = res[0];
499 var code = res[1];
500 async_upload_push (code);
501 }
502 }
503 req.open ("POST", 'script.php?init_async' , true);
504
505 var form = new FormData();
506 form.append ("filename", async_global_file.name);
507 form.append ("type", async_global_file.type);
508 if (time)
509 form.append ("time", time);
510 if (password)
511 form.append ("key", password);
512 if (one_time)
513 form.append ("one_time_download", '1');
514
515 // Start time estimation
516 upload_time_estimation_init(async_global_file.size);
517
518 req.send (form);
519 }
520
521 function async_upload_progress (e)
522 {
523 if (e == undefined || e == null || !e.lengthComputable && async_global_file.size != 0)
524 return;
525
526 // Compute percentage
527 var p = Math.round ((e.loaded + async_global_transfered) * 100 / (async_global_file.size));
528 var p_str = ' ';
529 if (p != 100)
530 p_str = p.toString() + '%';
531 // Update estimation speed
532 upload_time_estimation_add(e.loaded + async_global_transfered);
533 // Get speed string
534 var speed_str = upload_time_estimation_speed_string();
535 speed_str = upload_speed_refresh_limiter(speed_str);
536 // Get time string
537 var time_str = chrono_update(upload_time_estimation_time());
538
539 show_upload_progression (p_str, speed_str, time_str);
540 }
541
542 function async_upload_push (code)
543 {
544 async_global_last_code = code;
545 if (async_global_transfered == async_global_file.size)
546 {
547 hide_upload_progression ();
548 async_upload_end (code);
549 return;
550 }
551 var req = new XMLHttpRequest ();
552 req.upload.addEventListener ("progress", async_upload_progress, false);
553 req.addEventListener ("error", XHRErrorHandler, false);
554 req.addEventListener ("abort", XHRErrorHandler, false);
555 req.onreadystatechange = function ()
556 {
557 if (req.readyState == 4)
558 {
559 if (req.status == 200)
560 {
561 var res = req.responseText;
562
563 // This error may be triggered when Jirafeau does not receive any file in POST.
564 // This may be due to bad php configuration where post_max_size is too low
565 // comparing to upload_max_filesize. Let's retry with lower file size.
566 if (res === "Error 23")
567 {
568 async_global_max_size = Math.max(1, async_global_max_size - 500);
569 async_upload_push (async_global_last_code);
570 return;
571 }
572 else if (/^Error/.test(res))
573 {
574 pop_failure (res);
575 return;
576 }
577
578 res = res.split ("\n");
579 var code = res[0]
580 async_global_transfered = async_global_transfering;
581 async_upload_push (code);
582 return;
583 }
584 else
585 {
586 // lower async_global_max_size and retry
587 // This can occurs in several cases:
588 // - Request Entity Too Large (413) due to server bad configuration relative to PHP configuration
589 // - Server Error (500) which can happen when PHP's `max_execution_time` is too low comparared to sent size
590 async_global_max_size = Math.max(1, parseInt (async_global_max_size * 0.5));
591 async_upload_push (async_global_last_code);
592 return;
593 }
594 }
595 }
596 req.open ("POST", 'script.php?push_async' , true);
597
598 var start = async_global_transfered;
599 var end = start + async_global_max_size;
600 if (end >= async_global_file.size)
601 end = async_global_file.size;
602 var blob = async_global_file.slice (start, end);
603 async_global_transfering = end;
604
605 var form = new FormData();
606 form.append ("ref", async_global_ref);
607 form.append ("data", blob);
608 form.append ("code", code);
609 req.send (form);
610 }
611
612 function async_upload_end (code)
613 {
614 var req = new XMLHttpRequest ();
615 req.addEventListener ("error", XHRErrorHandler, false);
616 req.addEventListener ("abort", XHRErrorHandler, false);
617 req.onreadystatechange = function ()
618 {
619 if (req.readyState == 4 && req.status == 200)
620 {
621 var res = req.responseText;
622
623 if (/^Error/.test(res))
624 {
625 pop_failure (res);
626 return;
627 }
628
629 res = res.split ("\n");
630 var expiryDate = '';
631 if (async_global_time != 'none')
632 {
633 // convert time (local time + selected expiry date)
634 var localDatetime = new Date();
635 if(!add_time_string_to_date(localDatetime, async_global_time)) {
636 pop_failure ('Error: Date can not be parsed');
637 return;
638 }
639 expiryDate = localDatetime;
640 }
641
642 show_link (res[0], res[1], res[2], expiryDate);
643 }
644 }
645 req.open ("POST", 'script.php?end_async' , true);
646
647 var form = new FormData();
648 form.append ("ref", async_global_ref);
649 form.append ("code", code);
650 req.send (form);
651 }
652
653 function upload (max_chunk_size)
654 {
655 var one_time_checkbox = document.getElementById('one_time_download');
656 var one_time = one_time_checkbox !== null ? one_time_checkbox.checked : false;
657 if (check_html5_file_api ())
658 {
659 async_upload_start (
660 max_chunk_size,
661 document.getElementById('file_select').files[0],
662 document.getElementById('select_time').value,
663 document.getElementById('input_key').value,
664 one_time
665 );
666 }
667 else
668 {
669 classic_upload (
670 document.getElementById('file_select').files[0],
671 document.getElementById('select_time').value,
672 document.getElementById('input_key').value,
673 one_time
674 );
675 }
676 }
677
678 var upload_time_estimation_total_size = 42;
679 var upload_time_estimation_transfered_size = 42;
680 var upload_time_estimation_transfered_date = 42;
681 var upload_time_estimation_moving_average_speed = 42;
682
683 function upload_time_estimation_init(total_size)
684 {
685 upload_time_estimation_total_size = total_size;
686 upload_time_estimation_transfered_size = 0;
687 upload_time_estimation_moving_average_speed = 0;
688 var d = new Date();
689 upload_time_estimation_transfered_date = d.getTime();
690 }
691
692 function upload_time_estimation_add(total_transfered_size)
693 {
694 // Let's compute the current speed
695 var d = new Date();
696 var speed = upload_time_estimation_moving_average_speed;
697 if (d.getTime() - upload_time_estimation_transfered_date != 0) {
698 speed = (total_transfered_size - upload_time_estimation_transfered_size)
699 / (d.getTime() - upload_time_estimation_transfered_date);
700 speed = Math.max(0, speed);
701 }
702 // Let's compute moving average speed on 30 values
703 var m = (upload_time_estimation_moving_average_speed * 29 + speed) / 30;
704 // Update global values
705 upload_time_estimation_transfered_size = total_transfered_size;
706 upload_time_estimation_transfered_date = d.getTime();
707 upload_time_estimation_moving_average_speed = m;
708 }
709
710 function upload_time_estimation_speed_string()
711 {
712 // speed ms -> s
713 var s = upload_time_estimation_moving_average_speed * 1000;
714 var res = 0;
715 var scale = '';
716 if (s <= 1000)
717 {
718 res = s.toString();
719 scale = "B/s";
720 }
721 else if (s < 1000000)
722 {
723 res = Math.floor(s/100) / 10;
724 scale = "KB/s";
725 }
726 else
727 {
728 res = Math.floor(s/100000) / 10;
729 scale = "MB/s";
730 }
731 if (res == 0)
732 return '';
733 return res.toString() + ' ' + scale;
734 }
735
736 function milliseconds_to_time_string (milliseconds)
737 {
738 function numberEnding (number) {
739 return (number > 1) ? translate ('PLURAL_ENDING') : '';
740 }
741
742 var temp = Math.floor(milliseconds / 1000);
743 var years = Math.floor(temp / 31536000);
744 if (years) {
745 return years + ' ' + translate ('YEAR') + numberEnding(years);
746 }
747 var days = Math.floor((temp %= 31536000) / 86400);
748 if (days) {
749 return days + ' ' + translate ('DAY') + numberEnding(days);
750 }
751 var hours = Math.floor((temp %= 86400) / 3600);
752 if (hours) {
753 return hours + ' ' + translate ('HOUR') + numberEnding(hours);
754 }
755 var minutes = Math.floor((temp %= 3600) / 60);
756 if (minutes) {
757 return minutes + ' ' + translate ('MINUTE') + numberEnding(minutes);
758 }
759 var seconds = temp % 60;
760 if (seconds) {
761 return seconds + ' ' + translate ('SECOND') + numberEnding(seconds);
762 }
763 return translate ('LESS_1_SEC');
764 }
765
766 function upload_time_estimation_time()
767 {
768 // Estimate remaining time
769 if (upload_time_estimation_moving_average_speed <= 0)
770 return 0;
771 return (upload_time_estimation_total_size - upload_time_estimation_transfered_size)
772 / upload_time_estimation_moving_average_speed;
773 }
774
775 var chrono_last_update = 0;
776 var chrono_time_ms = 0;
777 var chrono_time_ms_last_update = 0;
778 function chrono_update(time_ms)
779 {
780 var d = new Date();
781 var chrono = 0;
782 // Don't update too often
783 if (d.getTime() - chrono_last_update < 3000 &&
784 chrono_time_ms_last_update > 0)
785 chrono = chrono_time_ms;
786 else
787 {
788 chrono_last_update = d.getTime();
789 chrono_time_ms = time_ms;
790 chrono = time_ms;
791 chrono_time_ms_last_update = d.getTime();
792 }
793
794 // Adjust chrono for smooth estimation
795 chrono = chrono - (d.getTime() - chrono_time_ms_last_update);
796
797 // Let's update chronometer
798 var time_str = '';
799 if (chrono > 0)
800 time_str = milliseconds_to_time_string (chrono);
801 return time_str;
802 }
803
804 var upload_speed_refresh_limiter_last_update = 0;
805 var upload_speed_refresh_limiter_last_value = '';
806 function upload_speed_refresh_limiter(speed_str)
807 {
808 var d = new Date();
809 if (d.getTime() - upload_speed_refresh_limiter_last_update > 1500)
810 {
811 upload_speed_refresh_limiter_last_value = speed_str;
812 upload_speed_refresh_limiter_last_update = d.getTime();
813 }
814 return upload_speed_refresh_limiter_last_value;
815 }
816
817 // document.ready()
818 document.addEventListener('DOMContentLoaded', function(event) {
819 // Search for all datetime fields and convert the time to local timezone
820 convertAllDatetimeFields();
821 });
822
823 // Add copy event listeners
824 function copyLinkToClipboard(link_id) {
825 var focus = document.activeElement;
826 var e = document.getElementById(link_id);
827
828 var tmp = document.createElement("textarea");
829 document.body.appendChild(tmp);
830 tmp.textContent = e.href;
831 tmp.focus();
832 tmp.setSelectionRange(0, tmp.value.length);
833 document.execCommand("copy");
834 document.body.removeChild(tmp);
835
836 focus.focus();
837 }
838
839 function addCopyListener(button_id, link_id) {
840 if(document.getElementById(button_id)){
841 document.getElementById(button_id)
842 .addEventListener("click", function() {
843 copyLinkToClipboard(link_id);});
844 }
845 }
846
847 function copyTextToClipboard(text_id){
848 var copyText = document.getElementById(text_id);
849 copyText.select();
850 copyText.setSelectionRange(0, 99999);
851 navigator.clipboard.writeText(copyText.value);
852 }
853
854 function addTextCopyListener(button_id, text_id) {
855 if(document.getElementById(button_id)){
856 document.getElementById(button_id)
857 .addEventListener("click", function() {
858 copyTextToClipboard(text_id);});
859 }
860 }
861
862 function set_dark_mode() {
863 let steel_sheet = "<?php echo 'media/' . $cfg['dark_style'] . '/style.css.php'; ?>";
864 let shortcut_icon = "<?php echo 'media/' . $cfg['dark_style'] . '/favicon.ico'; ?>";
865 document.getElementById('stylesheet').href = steel_sheet;
866 document.getElementById('shortcut_icon').href = shortcut_icon;
867 }
868
869 function set_light_mode() {
870 let steel_sheet = "<?php echo 'media/' . $cfg['style'] . '/style.css.php'; ?>";
871 let shortcut_icon = "<?php echo 'media/' . $cfg['style'] . '/favicon.ico'; ?>";
872 document.getElementById('stylesheet').href = steel_sheet;
873 document.getElementById('shortcut_icon').href = shortcut_icon;
874 }
875
876 function color_scheme_preferences() {
877
878 let dark_mode_steel_sheet = "<?php echo 'media/' . $cfg['dark_style'] . '/style.css.php'; ?>"
879 if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
880 set_dark_mode();
881 } else {
882 set_light_mode();
883 }
884
885 // When user change its preference
886 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', lightMode => {
887 lightMode.matches ? set_dark_mode() : set_light_mode();
888 });
889 }
890
891 // @license-end

patrick-canterino.de