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 function show_link (url
, reference
, delete_code
, crypt_key
, date
)
45 document
.getElementById('uploading').style
.display
= 'none';
46 document
.getElementById('upload').style
.display
= 'none';
47 document
.getElementById('upload_finished').style
.display
= '';
48 document
.title
= 'Jirafeau - 100%';
51 var download_link
= url +
'f.php?h=' + reference
;
52 var download_link_href
= url +
'f.php?h=' + reference
;
53 if (crypt_key
.length
> 0)
55 download_link +
= '&k=' + crypt_key
;
56 download_link_href +
= '&k=' + crypt_key
;
58 if (!!document
.getElementById('upload_finished_download_page'))
60 document
.getElementById('upload_link').innerHTML
= download_link
;
61 document
.getElementById('upload_link').href
= download_link_href
;
65 var filename
= document
.getElementById('file_select').files
[0].name
;
66 var b
= encodeURIComponent("Download file \"" + filename +
"\":") +
"%0D";
67 b +
= encodeURIComponent(download_link_href
) +
"%0D";
68 if (false == isEmpty(date
))
70 b +
= "%0D" +
encodeURIComponent("This file will be available until " + date
.toString()) +
"%0D";
71 document
.getElementById('upload_link_email').href
= "mailto:?body=" + b +
"&subject=" +
encodeURIComponent(filename
);
75 var delete_link
= url +
'f.php?h=' + reference +
'&d=' + delete_code
;
76 var delete_link_href
= url +
'f.php?h=' + reference +
'&d=' + delete_code
;
77 document
.getElementById('delete_link').innerHTML
= delete_link
;
78 document
.getElementById('delete_link').href
= delete_link_href
;
83 document
.getElementById('validity').style
.display
= 'none';
86 document
.getElementById('date').innerHTML
= date
.toString();
87 document
.getElementById('validity').style
.display
= '';
90 // Preview link (if allowed)
91 if (!!document
.getElementById('preview_link'))
93 document
.getElementById('upload_finished_preview').style
.display
= 'none';
94 var preview_link
= url +
'f.php?h=' + reference +
'&p=1';
95 var preview_link_href
= url +
'f.php?h=' + reference +
'&p=1';
96 if (crypt_key
.length
> 0)
98 preview_link +
= '&k=' + crypt_key
;
99 preview_link_href +
= '&k=' + crypt_key
;
102 // Test if content can be previewed
103 type
= document
.getElementById('file_select').files
[0].type
;
104 if (type
.indexOf("image") > -1 ||
105 type
.indexOf("audio") > -1 ||
106 type
.indexOf("text") > -1 ||
107 type
.indexOf("video") > -1)
109 document
.getElementById('preview_link').innerHTML
= preview_link
;
110 document
.getElementById('preview_link').href
= preview_link_href
;
111 document
.getElementById('upload_finished_preview').style
.display
= '';
115 // Direct download link
116 var direct_download_link
= url +
'f.php?h=' + reference +
'&d=1';
117 var direct_download_link_href
= url +
'f.php?h=' + reference +
'&d=1';
118 if (crypt_key
.length
> 0)
120 direct_download_link +
= '&k=' + crypt_key
;
121 direct_download_link_href +
= '&k=' + crypt_key
;
123 document
.getElementById('direct_link').innerHTML
= direct_download_link
;
124 document
.getElementById('direct_link').href
= direct_download_link_href
;
127 // Hide preview and direct download link if password is set
128 if (document
.getElementById('input_key').value
.length
> 0)
130 if (!!document
.getElementById('preview_link'))
131 document
.getElementById('upload_finished_preview').style
.display
= 'none';
132 document
.getElementById('upload_direct_download').style
.display
= 'none';
136 function show_upload_progression (percentage
, speed
, time_left
)
138 document
.getElementById('uploaded_percentage').innerHTML
= percentage
;
139 document
.getElementById('uploaded_speed').innerHTML
= speed
;
140 document
.getElementById('uploaded_time').innerHTML
= time_left
;
141 document
.title
= 'Jirafeau - ' + percentage
;
144 function hide_upload_progression ()
146 document
.getElementById('uploaded_percentage').style
.display
= 'none';
147 document
.getElementById('uploaded_speed').style
.display
= 'none';
148 document
.getElementById('uploaded_time').style
.display
= 'none';
149 document
.title
= 'Jirafeau';
152 function upload_progress (e
)
154 if (e
== undefined || e
== null ||
!e
.lengthComputable
)
157 // Init time estimation if needed
158 if (upload_time_estimation_total_size
== 0)
159 upload_time_estimation_total_size
= e
.total
;
161 // Compute percentage
162 var p
= Math
.round (e
.loaded
* 100 / e
.total
);
165 p_str
= p
.toString() +
'%';
166 // Update estimation speed
167 upload_time_estimation_add(e
.loaded
);
169 var speed_str
= upload_time_estimation_speed_string();
170 speed_str
= upload_speed_refresh_limiter(speed_str
);
172 var time_str
= chrono_update(upload_time_estimation_time());
174 show_upload_progression (p_str
, speed_str
, time_str
);
177 function control_selected_file_size(max_size
, error_str
)
179 f_size
= document
.getElementById('file_select').files
[0].size
;
180 if (max_size
> 0 && f_size
> max_size
* 1024 * 1024)
182 pop_failure(error_str
);
183 document
.getElementById('send').style
.display
= 'none';
187 document
.getElementById('options').style
.display
= '';
188 document
.getElementById('send').style
.display
= '';
189 document
.getElementById('error_pop').style
.display
= 'none';
190 document
.getElementById('file_select').style
.left
= 'inherit';
191 document
.getElementById('file_select').style
.height
= 'inherit';
192 document
.getElementById('file_select').style
.opacity
= '1';
196 function pop_failure (e
)
198 var text
= "An error occured";
199 if (typeof e
!== 'undefined')
201 text
= "<p>" + text +
"</p>";
202 document
.getElementById('error_pop').innerHTML
= e
;
204 document
.getElementById('uploading').style
.display
= 'none';
205 document
.getElementById('error_pop').style
.display
= '';
206 document
.getElementById('upload').style
.display
= '';
207 document
.getElementById('send').style
.display
= '';
210 function add_time_string_to_date(d
, time
)
212 if(typeof(d
) != 'object' ||
!(d
instanceof Date
))
217 if (time
== 'minute')
219 d
.setSeconds (d
.getSeconds() +
60);
224 d
.setSeconds (d
.getSeconds() +
3600);
229 d
.setSeconds (d
.getSeconds() +
86400);
234 d
.setSeconds (d
.getSeconds() +
604800);
239 d
.setSeconds (d
.getSeconds() +
2419200);
242 if (time
== 'quarter')
244 d
.setSeconds (d
.getSeconds() +
7257600);
249 d
.setSeconds (d
.getSeconds() +
29030400);
255 function classic_upload (url
, file
, time
, password
, one_time
, upload_password
)
257 // Delay time estimation init as we can't have file size
258 upload_time_estimation_init(0);
260 var req
= new XMLHttpRequest ();
261 req
.upload
.addEventListener ("progress", upload_progress
, false);
262 req
.addEventListener ("error", pop_failure
, false);
263 req
.addEventListener ("abort", pop_failure
, false);
264 req
.onreadystatechange
= function ()
266 if (req
.readyState
== 4 && req
.status
== 200)
268 var res
= req
.responseText
;
270 // if response starts with "Error" then show a failure
271 if (/^Error
/.test(res
))
277 res
= res
.split ("\n");
281 // convert time (local time + selected expiry date)
282 var localDatetime
= new Date();
283 if(!add_time_string_to_date(localDatetime
, time
))
285 pop_failure ('Error: Date can not be parsed');
288 expiryDate
= localDatetime
;
291 show_link (url
, res
[0], res
[1], res
[2], expiryDate
);
294 req
.open ("POST", url +
'script.php' , true);
296 var form
= new FormData();
297 form
.append ("file", file
);
299 form
.append ("time", time
);
301 form
.append ("key", password
);
303 form
.append ("one_time_download", '1');
304 if (upload_password
.length
> 0)
305 form
.append ("upload_password", upload_password
);
310 function check_html5_file_api ()
312 return window
.File
&& window
.FileReader
&& window
.FileList
&& window
.Blob
;
315 var async_global_transfered
= 0;
316 var async_global_url
= '';
317 var async_global_file
;
318 var async_global_ref
= '';
319 var async_global_max_size
= 0;
320 var async_global_time
;
321 var async_global_transfering
= 0;
323 function async_upload_start (url
, max_size
, file
, time
, password
, one_time
, upload_password
)
325 async_global_transfered
= 0;
326 async_global_url
= url
;
327 async_global_file
= file
;
328 async_global_max_size
= max_size
;
329 async_global_time
= time
;
331 var req
= new XMLHttpRequest ();
332 req
.addEventListener ("error", pop_failure
, false);
333 req
.addEventListener ("abort", pop_failure
, false);
334 req
.onreadystatechange
= function ()
336 if (req
.readyState
== 4 && req
.status
== 200)
338 var res
= req
.responseText
;
340 if (/^Error
/.test(res
))
346 res
= res
.split ("\n");
347 async_global_ref
= res
[0];
349 async_upload_push (code
);
352 req
.open ("POST", async_global_url +
'script.php?init_async' , true);
354 var form
= new FormData();
355 form
.append ("filename", async_global_file
.name
);
356 form
.append ("type", async_global_file
.type
);
358 form
.append ("time", time
);
360 form
.append ("key", password
);
362 form
.append ("one_time_download", '1');
363 if (upload_password
.length
> 0)
364 form
.append ("upload_password", upload_password
);
366 // Start time estimation
367 upload_time_estimation_init(async_global_file
.size
);
372 function async_upload_progress (e
)
374 if (e
== undefined || e
== null ||
!e
.lengthComputable
&& async_global_file
.size
!= 0)
377 // Compute percentage
378 var p
= Math
.round ((e
.loaded + async_global_transfered
) * 100 / (async_global_file
.size
));
381 p_str
= p
.toString() +
'%';
382 // Update estimation speed
383 upload_time_estimation_add(e
.loaded + async_global_transfered
);
385 var speed_str
= upload_time_estimation_speed_string();
386 speed_str
= upload_speed_refresh_limiter(speed_str
);
388 var time_str
= chrono_update(upload_time_estimation_time());
390 show_upload_progression (p_str
, speed_str
, time_str
);
393 function async_upload_push (code
)
395 if (async_global_transfered
== async_global_file
.size
)
397 hide_upload_progression ();
398 async_upload_end (code
);
401 var req
= new XMLHttpRequest ();
402 req
.upload
.addEventListener ("progress", async_upload_progress
, false);
403 req
.addEventListener ("error", pop_failure
, false);
404 req
.addEventListener ("abort", pop_failure
, false);
405 req
.onreadystatechange
= function ()
407 if (req
.readyState
== 4 && req
.status
== 200)
409 var res
= req
.responseText
;
411 if (/^Error
/.test(res
))
417 res
= res
.split ("\n");
419 async_global_transfered
= async_global_transfering
;
420 async_upload_push (code
);
423 req
.open ("POST", async_global_url +
'script.php?push_async' , true);
425 var chunk_size
= parseInt (async_global_max_size
* 0.50);
426 var start
= async_global_transfered
;
427 var end
= start + chunk_size
;
428 if (end
>= async_global_file
.size
)
429 end
= async_global_file
.size
;
430 var blob
= async_global_file
.slice (start
, end
);
431 async_global_transfering
= end
;
433 var form
= new FormData();
434 form
.append ("ref", async_global_ref
);
435 form
.append ("data", blob
);
436 form
.append ("code", code
);
440 function async_upload_end (code
)
442 var req
= new XMLHttpRequest ();
443 req
.addEventListener ("error", pop_failure
, false);
444 req
.addEventListener ("abort", pop_failure
, false);
445 req
.onreadystatechange
= function ()
447 if (req
.readyState
== 4 && req
.status
== 200)
449 var res
= req
.responseText
;
451 if (/^Error
/.test(res
))
457 res
= res
.split ("\n");
459 if (async_global_time
!= 'none')
461 // convert time (local time + selected expiry date)
462 var localDatetime
= new Date();
463 if(!add_time_string_to_date(localDatetime
, async_global_time
)) {
464 pop_failure ('Error: Date can not be parsed');
467 expiryDate
= localDatetime
;
470 show_link (async_global_url
, res
[0], res
[1], res
[2], expiryDate
);
473 req
.open ("POST", async_global_url +
'script.php?end_async' , true);
475 var form
= new FormData();
476 form
.append ("ref", async_global_ref
);
477 form
.append ("code", code
);
481 function upload (url
, max_size
)
483 if (check_html5_file_api ()
484 && document
.getElementById('file_select').files
[0].size
>= max_size
)
486 async_upload_start (url
,
488 document
.getElementById('file_select').files
[0],
489 document
.getElementById('select_time').value
,
490 document
.getElementById('input_key').value
,
491 document
.getElementById('one_time_download').checked
,
492 document
.getElementById('upload_password').value
498 document
.getElementById('file_select').files
[0],
499 document
.getElementById('select_time').value
,
500 document
.getElementById('input_key').value
,
501 document
.getElementById('one_time_download').checked
,
502 document
.getElementById('upload_password').value
507 var upload_time_estimation_total_size
= 42;
508 var upload_time_estimation_transfered_size
= 42;
509 var upload_time_estimation_transfered_date
= 42;
510 var upload_time_estimation_moving_average_speed
= 42;
512 function upload_time_estimation_init(total_size
)
514 upload_time_estimation_total_size
= total_size
;
515 upload_time_estimation_transfered_size
= 0;
516 upload_time_estimation_moving_average_speed
= 0;
518 upload_time_estimation_transfered_date
= d
.getTime();
521 function upload_time_estimation_add(total_transfered_size
)
523 // Let's compute the current speed
525 var speed
= upload_time_estimation_moving_average_speed
;
526 if (d
.getTime() - upload_time_estimation_transfered_date
!= 0)
527 speed
= (total_transfered_size
- upload_time_estimation_transfered_size
)
528 / (d
.getTime() - upload_time_estimation_transfered_date
);
529 // Let's compute moving average speed on 30 values
530 var m
= (upload_time_estimation_moving_average_speed
* 29 + speed
) / 30;
531 // Update global values
532 upload_time_estimation_transfered_size
= total_transfered_size
;
533 upload_time_estimation_transfered_date
= d
.getTime();
534 upload_time_estimation_moving_average_speed
= m
;
537 function upload_time_estimation_speed_string()
540 var s
= upload_time_estimation_moving_average_speed
* 1000;
548 else if (s
< 1000000)
550 res
= Math
.floor(s
/100) / 10;
555 res
= Math
.floor(s
/100000) / 10;
560 return res
.toString() +
' ' + scale
;
563 function milliseconds_to_time_string (milliseconds
)
565 function numberEnding (number
) {
566 return (number
> 1) ?
's' : '';
569 var temp
= Math
.floor(milliseconds
/ 1000);
570 var years
= Math
.floor(temp
/ 31536000);
572 return years +
' ' +
translate ('year') +
numberEnding(years
);
574 var days
= Math
.floor((temp %
= 31536000) / 86400);
576 return days +
' ' +
translate ('day') +
numberEnding(days
);
578 var hours
= Math
.floor((temp %
= 86400) / 3600);
580 return hours +
' ' +
translate ('hour') +
numberEnding(hours
);
582 var minutes
= Math
.floor((temp %
= 3600) / 60);
584 return minutes +
' ' +
translate ('minute') +
numberEnding(minutes
);
586 var seconds
= temp %
60;
588 return seconds +
' ' +
translate ('second') +
numberEnding(seconds
);
590 return translate ('less than a second');
593 function upload_time_estimation_time()
595 // Estimate remaining time
596 if (upload_time_estimation_moving_average_speed
== 0)
598 return (upload_time_estimation_total_size
- upload_time_estimation_transfered_size
)
599 / upload_time_estimation_moving_average_speed
;
602 var chrono_last_update
= 0;
603 var chrono_time_ms
= 0;
604 var chrono_time_ms_last_update
= 0;
605 function chrono_update(time_ms
)
609 // Don't update too often
610 if (d
.getTime() - chrono_last_update
< 3000 &&
611 chrono_time_ms_last_update
> 0)
612 chrono
= chrono_time_ms
;
615 chrono_last_update
= d
.getTime();
616 chrono_time_ms
= time_ms
;
618 chrono_time_ms_last_update
= d
.getTime();
621 // Adjust chrono for smooth estimation
622 chrono
= chrono
- (d
.getTime() - chrono_time_ms_last_update
);
624 // Let's update chronometer
627 time_str
= milliseconds_to_time_string (chrono
);
631 var upload_speed_refresh_limiter_last_update
= 0;
632 var upload_speed_refresh_limiter_last_value
= '';
633 function upload_speed_refresh_limiter(speed_str
)
636 if (d
.getTime() - upload_speed_refresh_limiter_last_update
> 1500)
638 upload_speed_refresh_limiter_last_value
= speed_str
;
639 upload_speed_refresh_limiter_last_update
= d
.getTime();
641 return upload_speed_refresh_limiter_last_value
;