3 * Jirafeau, your web file repository
4 * Copyright (C) 2015 Jerome Jutteau <j.jutteau@gmail.com>
5 * Copyright (C) 2015 Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
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.
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.
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/>.
21 header('Content-Type: text/javascript');
23 define('JIRAFEAU_ROOT', dirname(__FILE__
) . '/../');
25 require(JIRAFEAU_ROOT
. 'lib/settings.php');
26 require(JIRAFEAU_ROOT
. 'lib/functions.php');
27 require(JIRAFEAU_ROOT
. 'lib/lang.php');
30 function translate (expr
)
32 var lang_array
= <?php
echo json_lang_generator() ?
>;
33 if (lang_array
.hasOwnProperty(expr
))
34 return lang_array
[expr
];
38 function isEmpty(str
) {
39 return (!str ||
0 === str
.length
);
42 // Extend date object with format method
43 Date
.prototype
.format
= function(format
) {
44 format
= format ||
'YYYY-MM-DD hh:mm';
46 var zeropad
= function(number
, length
) {
47 number
= number
.toString();
49 while(number
.length
< length
)
50 number
= '0' + number
;
54 YYYY
: this
.getFullYear(),
55 MM
: zeropad(this
.getMonth() +
1),
56 DD
: zeropad(this
.getDate()),
57 hh
: zeropad(this
.getHours()),
58 mm
: zeropad(this
.getMinutes()),
61 sign
= (localDate
.getTimezoneOffset() > 0) ?
'-' : '+';
62 offset
= Math
.abs(localDate
.getTimezoneOffset());
63 hours
= zeropad(Math
.floor(offset
/ 60));
64 minutes
= zeropad(offset %
60);
65 return sign + hours +
":" + minutes
;
68 pattern
= '(' +
Object.keys(formats
).join(')|(') +
')';
70 return format
.replace(new RegExp(pattern
, 'g'), function(match
) {
71 return formats
[match
];
75 function dateToUtcString(datelocal
) {
77 datelocal
.getUTCFullYear(),
78 datelocal
.getUTCMonth(),
79 datelocal
.getUTCDate(),
80 datelocal
.getUTCHours(),
81 datelocal
.getUTCMinutes(),
82 datelocal
.getUTCSeconds()
86 function show_link (url
, reference
, delete_code
, crypt_key
, date
)
89 document
.getElementById('uploading').style
.display
= 'none';
90 document
.getElementById('upload').style
.display
= 'none';
91 document
.getElementById('upload_finished').style
.display
= '';
92 document
.title
= 'Jirafeau - 100%';
95 var download_link
= url +
'f.php?h=' + reference
;
96 var download_link_href
= url +
'f.php?h=' + reference
;
97 if (crypt_key
.length
> 0)
99 download_link +
= '&k=' + crypt_key
;
100 download_link_href +
= '&k=' + crypt_key
;
102 if (!!document
.getElementById('upload_finished_download_page'))
104 document
.getElementById('upload_link').innerHTML
= download_link
;
105 document
.getElementById('upload_link').href
= download_link_href
;
109 var filename
= document
.getElementById('file_select').files
[0].name
;
110 var b
= encodeURIComponent("Download file \"" + filename +
"\":") +
"%0D";
111 b +
= encodeURIComponent(download_link_href
) +
"%0D";
112 if (false == isEmpty(date
))
114 b +
= "%0D" +
encodeURIComponent("This file will be available until " +
dateToUtcString(date
)) +
"%0D";
115 document
.getElementById('upload_link_email').href
= "mailto:?body=" + b +
"&subject=" +
encodeURIComponent(filename
);
119 var delete_link
= url +
'f.php?h=' + reference +
'&d=' + delete_code
;
120 var delete_link_href
= url +
'f.php?h=' + reference +
'&d=' + delete_code
;
121 document
.getElementById('delete_link').innerHTML
= delete_link
;
122 document
.getElementById('delete_link').href
= delete_link_href
;
127 document
.getElementById('validity').style
.display
= 'none';
130 document
.getElementById('date').innerHTML
= '<span class="datetime">'
131 +
dateToUtcString(date
) +
' (GMT)'
133 document
.getElementById('validity').style
.display
= '';
136 // Preview link (if allowed)
137 if (!!document
.getElementById('preview_link'))
139 document
.getElementById('upload_finished_preview').style
.display
= 'none';
140 var preview_link
= url +
'f.php?h=' + reference +
'&p=1';
141 var preview_link_href
= url +
'f.php?h=' + reference +
'&p=1';
142 if (crypt_key
.length
> 0)
144 preview_link +
= '&k=' + crypt_key
;
145 preview_link_href +
= '&k=' + crypt_key
;
148 // Test if content can be previewed
149 type
= document
.getElementById('file_select').files
[0].type
;
150 if (type
.indexOf("image") > -1 ||
151 type
.indexOf("audio") > -1 ||
152 type
.indexOf("text") > -1 ||
153 type
.indexOf("video") > -1)
155 document
.getElementById('preview_link').innerHTML
= preview_link
;
156 document
.getElementById('preview_link').href
= preview_link_href
;
157 document
.getElementById('upload_finished_preview').style
.display
= '';
161 // Direct download link
162 var direct_download_link
= url +
'f.php?h=' + reference +
'&d=1';
163 var direct_download_link_href
= url +
'f.php?h=' + reference +
'&d=1';
164 if (crypt_key
.length
> 0)
166 direct_download_link +
= '&k=' + crypt_key
;
167 direct_download_link_href +
= '&k=' + crypt_key
;
169 document
.getElementById('direct_link').innerHTML
= direct_download_link
;
170 document
.getElementById('direct_link').href
= direct_download_link_href
;
173 // Hide preview and direct download link if password is set
174 if (document
.getElementById('input_key').value
.length
> 0)
176 if (!!document
.getElementById('preview_link'))
177 document
.getElementById('upload_finished_preview').style
.display
= 'none';
178 document
.getElementById('upload_direct_download').style
.display
= 'none';
182 function show_upload_progression (percentage
, speed
, time_left
)
184 document
.getElementById('uploaded_percentage').innerHTML
= percentage
;
185 document
.getElementById('uploaded_speed').innerHTML
= speed
;
186 document
.getElementById('uploaded_time').innerHTML
= time_left
;
187 document
.title
= 'Jirafeau - ' + percentage
;
190 function hide_upload_progression ()
192 document
.getElementById('uploaded_percentage').style
.display
= 'none';
193 document
.getElementById('uploaded_speed').style
.display
= 'none';
194 document
.getElementById('uploaded_time').style
.display
= 'none';
195 document
.title
= 'Jirafeau';
198 function upload_progress (e
)
200 if (e
== undefined || e
== null ||
!e
.lengthComputable
)
203 // Init time estimation if needed
204 if (upload_time_estimation_total_size
== 0)
205 upload_time_estimation_total_size
= e
.total
;
207 // Compute percentage
208 var p
= Math
.round (e
.loaded
* 100 / e
.total
);
211 p_str
= p
.toString() +
'%';
212 // Update estimation speed
213 upload_time_estimation_add(e
.loaded
);
215 var speed_str
= upload_time_estimation_speed_string();
216 speed_str
= upload_speed_refresh_limiter(speed_str
);
218 var time_str
= chrono_update(upload_time_estimation_time());
220 show_upload_progression (p_str
, speed_str
, time_str
);
223 function control_selected_file_size(max_size
, error_str
)
225 f_size
= document
.getElementById('file_select').files
[0].size
;
226 if (max_size
> 0 && f_size
> max_size
* 1024 * 1024)
228 pop_failure(error_str
);
229 document
.getElementById('send').style
.display
= 'none';
233 document
.getElementById('options').style
.display
= '';
234 document
.getElementById('send').style
.display
= '';
235 document
.getElementById('error_pop').style
.display
= 'none';
236 document
.getElementById('file_select').style
.left
= 'inherit';
237 document
.getElementById('file_select').style
.height
= 'inherit';
238 document
.getElementById('file_select').style
.opacity
= '1';
242 function pop_failure (e
)
244 var text
= "An error occured";
245 if (typeof e
!== 'undefined')
247 text
= "<p>" + text +
"</p>";
248 document
.getElementById('error_pop').innerHTML
= e
;
250 document
.getElementById('uploading').style
.display
= 'none';
251 document
.getElementById('error_pop').style
.display
= '';
252 document
.getElementById('upload').style
.display
= '';
253 document
.getElementById('send').style
.display
= '';
256 function add_time_string_to_date(d
, time
)
258 if(typeof(d
) != 'object' ||
!(d
instanceof Date
))
263 if (time
== 'minute')
265 d
.setSeconds (d
.getSeconds() +
60);
270 d
.setSeconds (d
.getSeconds() +
3600);
275 d
.setSeconds (d
.getSeconds() +
86400);
280 d
.setSeconds (d
.getSeconds() +
604800);
285 d
.setSeconds (d
.getSeconds() +
2419200);
288 if (time
== 'quarter')
290 d
.setSeconds (d
.getSeconds() +
7257600);
295 d
.setSeconds (d
.getSeconds() +
29030400);
301 function classic_upload (url
, file
, time
, password
, one_time
, upload_password
)
303 // Delay time estimation init as we can't have file size
304 upload_time_estimation_init(0);
306 var req
= new XMLHttpRequest ();
307 req
.upload
.addEventListener ("progress", upload_progress
, false);
308 req
.addEventListener ("error", pop_failure
, false);
309 req
.addEventListener ("abort", pop_failure
, false);
310 req
.onreadystatechange
= function ()
312 if (req
.readyState
== 4 && req
.status
== 200)
314 var res
= req
.responseText
;
316 // if response starts with "Error" then show a failure
317 if (/^Error
/.test(res
))
323 res
= res
.split ("\n");
327 // convert time (local time + selected expiry date)
328 var localDatetime
= new Date();
329 if(!add_time_string_to_date(localDatetime
, time
))
331 pop_failure ('Error: Date can not be parsed');
334 expiryDate
= localDatetime
;
337 show_link (url
, res
[0], res
[1], res
[2], expiryDate
);
340 req
.open ("POST", url +
'script.php' , true);
342 var form
= new FormData();
343 form
.append ("file", file
);
345 form
.append ("time", time
);
347 form
.append ("key", password
);
349 form
.append ("one_time_download", '1');
350 if (upload_password
.length
> 0)
351 form
.append ("upload_password", upload_password
);
356 function check_html5_file_api ()
358 return window
.File
&& window
.FileReader
&& window
.FileList
&& window
.Blob
;
361 var async_global_transfered
= 0;
362 var async_global_url
= '';
363 var async_global_file
;
364 var async_global_ref
= '';
365 var async_global_max_size
= 0;
366 var async_global_time
;
367 var async_global_transfering
= 0;
369 function async_upload_start (url
, max_size
, file
, time
, password
, one_time
, upload_password
)
371 async_global_transfered
= 0;
372 async_global_url
= url
;
373 async_global_file
= file
;
374 async_global_max_size
= max_size
;
375 async_global_time
= time
;
377 var req
= new XMLHttpRequest ();
378 req
.addEventListener ("error", pop_failure
, false);
379 req
.addEventListener ("abort", pop_failure
, false);
380 req
.onreadystatechange
= function ()
382 if (req
.readyState
== 4 && req
.status
== 200)
384 var res
= req
.responseText
;
386 if (/^Error
/.test(res
))
392 res
= res
.split ("\n");
393 async_global_ref
= res
[0];
395 async_upload_push (code
);
398 req
.open ("POST", async_global_url +
'script.php?init_async' , true);
400 var form
= new FormData();
401 form
.append ("filename", async_global_file
.name
);
402 form
.append ("type", async_global_file
.type
);
404 form
.append ("time", time
);
406 form
.append ("key", password
);
408 form
.append ("one_time_download", '1');
409 if (upload_password
.length
> 0)
410 form
.append ("upload_password", upload_password
);
412 // Start time estimation
413 upload_time_estimation_init(async_global_file
.size
);
418 function async_upload_progress (e
)
420 if (e
== undefined || e
== null ||
!e
.lengthComputable
&& async_global_file
.size
!= 0)
423 // Compute percentage
424 var p
= Math
.round ((e
.loaded + async_global_transfered
) * 100 / (async_global_file
.size
));
427 p_str
= p
.toString() +
'%';
428 // Update estimation speed
429 upload_time_estimation_add(e
.loaded + async_global_transfered
);
431 var speed_str
= upload_time_estimation_speed_string();
432 speed_str
= upload_speed_refresh_limiter(speed_str
);
434 var time_str
= chrono_update(upload_time_estimation_time());
436 show_upload_progression (p_str
, speed_str
, time_str
);
439 function async_upload_push (code
)
441 if (async_global_transfered
== async_global_file
.size
)
443 hide_upload_progression ();
444 async_upload_end (code
);
447 var req
= new XMLHttpRequest ();
448 req
.upload
.addEventListener ("progress", async_upload_progress
, false);
449 req
.addEventListener ("error", pop_failure
, false);
450 req
.addEventListener ("abort", pop_failure
, false);
451 req
.onreadystatechange
= function ()
453 if (req
.readyState
== 4 && req
.status
== 200)
455 var res
= req
.responseText
;
457 if (/^Error
/.test(res
))
463 res
= res
.split ("\n");
465 async_global_transfered
= async_global_transfering
;
466 async_upload_push (code
);
469 req
.open ("POST", async_global_url +
'script.php?push_async' , true);
471 var chunk_size
= parseInt (async_global_max_size
* 0.50);
472 var start
= async_global_transfered
;
473 var end
= start + chunk_size
;
474 if (end
>= async_global_file
.size
)
475 end
= async_global_file
.size
;
476 var blob
= async_global_file
.slice (start
, end
);
477 async_global_transfering
= end
;
479 var form
= new FormData();
480 form
.append ("ref", async_global_ref
);
481 form
.append ("data", blob
);
482 form
.append ("code", code
);
486 function async_upload_end (code
)
488 var req
= new XMLHttpRequest ();
489 req
.addEventListener ("error", pop_failure
, false);
490 req
.addEventListener ("abort", pop_failure
, false);
491 req
.onreadystatechange
= function ()
493 if (req
.readyState
== 4 && req
.status
== 200)
495 var res
= req
.responseText
;
497 if (/^Error
/.test(res
))
503 res
= res
.split ("\n");
505 if (async_global_time
!= 'none')
507 // convert time (local time + selected expiry date)
508 var localDatetime
= new Date();
509 if(!add_time_string_to_date(localDatetime
, async_global_time
)) {
510 pop_failure ('Error: Date can not be parsed');
513 expiryDate
= localDatetime
;
516 show_link (async_global_url
, res
[0], res
[1], res
[2], expiryDate
);
519 req
.open ("POST", async_global_url +
'script.php?end_async' , true);
521 var form
= new FormData();
522 form
.append ("ref", async_global_ref
);
523 form
.append ("code", code
);
527 function upload (url
, max_size
)
529 if (check_html5_file_api ()
530 && document
.getElementById('file_select').files
[0].size
>= max_size
)
532 async_upload_start (url
,
534 document
.getElementById('file_select').files
[0],
535 document
.getElementById('select_time').value
,
536 document
.getElementById('input_key').value
,
537 document
.getElementById('one_time_download').checked
,
538 document
.getElementById('upload_password').value
544 document
.getElementById('file_select').files
[0],
545 document
.getElementById('select_time').value
,
546 document
.getElementById('input_key').value
,
547 document
.getElementById('one_time_download').checked
,
548 document
.getElementById('upload_password').value
553 var upload_time_estimation_total_size
= 42;
554 var upload_time_estimation_transfered_size
= 42;
555 var upload_time_estimation_transfered_date
= 42;
556 var upload_time_estimation_moving_average_speed
= 42;
558 function upload_time_estimation_init(total_size
)
560 upload_time_estimation_total_size
= total_size
;
561 upload_time_estimation_transfered_size
= 0;
562 upload_time_estimation_moving_average_speed
= 0;
564 upload_time_estimation_transfered_date
= d
.getTime();
567 function upload_time_estimation_add(total_transfered_size
)
569 // Let's compute the current speed
571 var speed
= upload_time_estimation_moving_average_speed
;
572 if (d
.getTime() - upload_time_estimation_transfered_date
!= 0)
573 speed
= (total_transfered_size
- upload_time_estimation_transfered_size
)
574 / (d
.getTime() - upload_time_estimation_transfered_date
);
575 // Let's compute moving average speed on 30 values
576 var m
= (upload_time_estimation_moving_average_speed
* 29 + speed
) / 30;
577 // Update global values
578 upload_time_estimation_transfered_size
= total_transfered_size
;
579 upload_time_estimation_transfered_date
= d
.getTime();
580 upload_time_estimation_moving_average_speed
= m
;
583 function upload_time_estimation_speed_string()
586 var s
= upload_time_estimation_moving_average_speed
* 1000;
594 else if (s
< 1000000)
596 res
= Math
.floor(s
/100) / 10;
601 res
= Math
.floor(s
/100000) / 10;
606 return res
.toString() +
' ' + scale
;
609 function milliseconds_to_time_string (milliseconds
)
611 function numberEnding (number
) {
612 return (number
> 1) ?
's' : '';
615 var temp
= Math
.floor(milliseconds
/ 1000);
616 var years
= Math
.floor(temp
/ 31536000);
618 return years +
' ' +
translate ('year') +
numberEnding(years
);
620 var days
= Math
.floor((temp %
= 31536000) / 86400);
622 return days +
' ' +
translate ('day') +
numberEnding(days
);
624 var hours
= Math
.floor((temp %
= 86400) / 3600);
626 return hours +
' ' +
translate ('hour') +
numberEnding(hours
);
628 var minutes
= Math
.floor((temp %
= 3600) / 60);
630 return minutes +
' ' +
translate ('minute') +
numberEnding(minutes
);
632 var seconds
= temp %
60;
634 return seconds +
' ' +
translate ('second') +
numberEnding(seconds
);
636 return translate ('less than a second');
639 function upload_time_estimation_time()
641 // Estimate remaining time
642 if (upload_time_estimation_moving_average_speed
== 0)
644 return (upload_time_estimation_total_size
- upload_time_estimation_transfered_size
)
645 / upload_time_estimation_moving_average_speed
;
648 var chrono_last_update
= 0;
649 var chrono_time_ms
= 0;
650 var chrono_time_ms_last_update
= 0;
651 function chrono_update(time_ms
)
655 // Don't update too often
656 if (d
.getTime() - chrono_last_update
< 3000 &&
657 chrono_time_ms_last_update
> 0)
658 chrono
= chrono_time_ms
;
661 chrono_last_update
= d
.getTime();
662 chrono_time_ms
= time_ms
;
664 chrono_time_ms_last_update
= d
.getTime();
667 // Adjust chrono for smooth estimation
668 chrono
= chrono
- (d
.getTime() - chrono_time_ms_last_update
);
670 // Let's update chronometer
673 time_str
= milliseconds_to_time_string (chrono
);
677 var upload_speed_refresh_limiter_last_update
= 0;
678 var upload_speed_refresh_limiter_last_value
= '';
679 function upload_speed_refresh_limiter(speed_str
)
682 if (d
.getTime() - upload_speed_refresh_limiter_last_update
> 1500)
684 upload_speed_refresh_limiter_last_value
= speed_str
;
685 upload_speed_refresh_limiter_last_update
= d
.getTime();
687 return upload_speed_refresh_limiter_last_value
;