This commit is contained in:
Nick Bebout 2019-07-02 18:25:47 -05:00
parent 0797e48248
commit 275436c5a0
126 changed files with 25270 additions and 4380 deletions

View file

@ -1,6 +1,6 @@
#!/bin/sh
# $Id: cgi_memo,v 1.45 2019/02/10 14:28:53 gilles Exp gilles $
# $Id: cgi_memo,v 1.48 2019/06/25 16:49:11 gilles Exp gilles $
if test -n "$1"; then
echoq() { echo "$@" ; } # not quiet mode
@ -149,7 +149,7 @@ grep_any() {
grep_load() {
echo G_Load.txt
egrep -o 'Load is ..?\... ..?\... ..?\...' grep_stats.txt > G_Load.txt
egrep -o 'Load is ..?\... ..?\... ..?\... .*' grep_stats.txt > G_Load.txt
}
grep_all2() {
@ -169,16 +169,21 @@ stat_patterns_list() {
}
echoq stat_load
stat_load() {
echo -n 'Load min: ' ; datamash --format=%6.1f -W min 3 min 4 min 5 < G_Load.txt
echo -n 'Load q1: ' ; datamash --format=%6.1f -W q1 3 q1 4 q1 5 < G_Load.txt
echo -n 'Load median: ' ; datamash --format=%6.1f -W median 3 median 4 median 5 < G_Load.txt
echo -n 'Load mean: ' ; datamash --format=%6.1f -W mean 3 mean 4 mean 5 < G_Load.txt
echo -n 'Load q3: ' ; datamash --format=%6.1f -W q3 3 q3 4 q3 5 < G_Load.txt
echo -n 'Load max: ' ; datamash --format=%6.1f -W max 3 max 4 max 5 < G_Load.txt
stat_load()
{
echo -n 'Load 1 min 5 min 15 min ' ; grep -o 'on.*cores' G_Load.txt|uniq
echo -n 'Load min: ' ; datamash --format=%3.1f -W min 3 min 4 min 5 < G_Load.txt
echo -n 'Load q1: ' ; datamash --format=%3.1f -W q1 3 q1 4 q1 5 < G_Load.txt
echo -n 'Load median: ' ; datamash --format=%3.1f -W median 3 median 4 median 5 < G_Load.txt
echo -n 'Load mean: ' ; datamash --format=%3.1f -W mean 3 mean 4 mean 5 < G_Load.txt
echo -n 'Load q3: ' ; datamash --format=%3.1f -W q3 3 q3 4 q3 5 < G_Load.txt
echo -n 'Load max: ' ; datamash --format=%3.1f -W max 3 max 4 max 5 < G_Load.txt
}
datamash_file_op_index() {
file="$1"
op="${2:-mean}"
@ -205,7 +210,8 @@ stat_any() {
}
echoq stat_all
stat_all() {
stat_all()
{
stat_load ; echo
# stat_any G_REMOTE_ADDR.txt
# stat_any G_REMOTE_HOST.txt
@ -225,7 +231,30 @@ stat_all() {
stat_any G_Detected_errors.txt 2
stat_any G_Exiting_with_return_value.txt 5 # GROUP
stat_any G_Memory_consumption_at_the_end.txt 7
stat_any G_Messages_found_in_host1_not_in_host2.txt 9
stat_any G_Messages_found_in_host2_not_in_host1.txt 9
#stat_any G_failure_Error_login.txt
echo "Data made at" `date -r grep_stats.txt`
}
stat_transfer_time_mean()
{
datamash_file_op_index G_Transfer_time.txt mean
}
stat_throuput_since_day_one_in_days()
{
number_of_syncs=`number_of_syncs`
days_since_first_use=`days_since_first_use`
c "$number_of_syncs / $days_since_first_use"
}
stat_queue_mean()
{
stat_throuput_since_day_one_in_days=`stat_throuput_since_day_one_in_days`
stat_transfer_time_mean=`stat_transfer_time_mean`
stat_queue_mean_raw=`c "$stat_throuput_since_day_one_in_days * $stat_transfer_time_mean / 3600 / 24"`
printf "%2.2f\n" $stat_queue_mean_raw
}
echoq dirs_of_syncs_finished_recently
@ -257,7 +286,7 @@ logfiles_finished_recently()
last_dirs_written()
{
ls -tr | tail -800
ls -tr | tail -1800
}
last_file_written_in_dir()
@ -268,7 +297,7 @@ last_file_written_in_dir()
is_dir_running_imapsync()
{
test -d "$1" || return 1
test -f "$1/imapsync.pid" && PID=`cat "$1/imapsync.pid"` &&
test -f "$1/imapsync.pid" && PID=`head -1 "$1/imapsync.pid"` &&
ps -p $PID -o comm= > /dev/null
}
@ -318,7 +347,7 @@ pids_of_imapsync_not_writing_since_x_secondes()
do
is_dir_running_imapsync "$d" &&
is_file_older_than `last_file_written_in_dir "$d"` "$x_secondes" &&
cat "$d/imapsync.pid" && echo -n " "
head -1 "$d/imapsync.pid" | tr '\n' ' '
done
@ -327,7 +356,7 @@ pids_of_imapsync_not_writing_since_x_secondes()
kill_HUP_pids_of_imapsync_not_writing_since_x_secondes()
{
pids_not_writing=`pids_of_imapsync_not_writing_since_x_secondes ${1:-900}`
test -n "$pids_not_writing" && echo kill -HUP "$pids_not_writing" && kill -HUP "$pids_not_writing"
test -n "$pids_not_writing" && echo kill -HUP "$pids_not_writing" # && kill -HUP "$pids_not_writing"
}
@ -385,7 +414,7 @@ watch_new_runs() {
inotifywait . -e create 2>/dev/null | { read path action f
echo $f
sleep 2
test -f $f/imapsync.pid && PID=`cat $f/imapsync.pid` && echo PID $PID
test -f $f/imapsync.pid && PID=`head -1 $f/imapsync.pid` && echo PID $PID
echo -e '\a'
}
done
@ -394,7 +423,7 @@ watch_new_runs() {
echoq pidfiles_running_and_not_running
pidfiles_running_and_not_running() {
ls -tr | while read f; do
test -f $f/imapsync.pid && PID=`cat $f/imapsync.pid` && echo -n "$PID " &&
test -f $f/imapsync.pid && PID=`head -1 $f/imapsync.pid` && echo -n "$PID " &&
{ ps -p $PID -o comm= | tr '\n' ' ' && { test -f /proc/$PID/oom_score &&
{ echo -12 > /proc/$PID/oom_adj ; } && echo -n "oom_score " && cat /proc/$PID/oom_score | tr '\n' ' ' ; : ; }
} &&
@ -406,7 +435,7 @@ pidfile_dandling() {
pidfile_dandling_DIR=$1
test -d $pidfile_dandling_DIR || return 2
test -f $pidfile_dandling_DIR/imapsync.pid || return 3
pidfile_dandling_PID=`cat $pidfile_dandling_DIR/imapsync.pid`
pidfile_dandling_PID=`head -1 $pidfile_dandling_DIR/imapsync.pid`
#echo "$pidfile_dandling_PID"
test -n "$pidfile_dandling_PID" || return 4
test "$pidfile_dandling_PID" -ge 1 || return 5
@ -423,10 +452,11 @@ echoq pidfiles_not_running
pidfiles_not_running() {
ls -tr | while read f; do
if pidfile_dandling "$f" ; then
pidfiles_not_running_PID=`cat $f/imapsync.pid`
pidfiles_not_running_PID=`head -1 $f/imapsync.pid`
echo -n "rm $f/imapsync.pid # "
{ ls -tr $f/LOG_imapsync/* 2>/dev/null |tail -1 ; } | tr '\n' ' '
echo "# PID $pidfiles_not_running_PID"
#head -2 $f/imapsync.pid
fi
done
}
@ -464,7 +494,11 @@ seconds_to_days_hours_echo() {
date --date="1 day ago" > /dev/null && echo "echo $(date -ud "@${1:-0}" +'$((%s/3600/24)) days %_H hours %_M min %_S sec')" && return
}
printf_this_one_div10()
{
num=$1
printf "% $((num/10))s\n" $1
}
echoq 'runs_per_day 7 # last 7 days'
runs_per_day() {
@ -472,7 +506,10 @@ runs_per_day() {
start=${1:-$historic_start}
for cc in `count 0 $start`; do
DATE=`date_x_days_ago $cc`
echo -n "$DATE $cc days ago: "; find . -maxdepth 1 -mtime $cc -ls |wc -l
# find on FreeBSD finds nothing with -mtime 0
test FreeBSD = `uname -s` && cc=`expr 1 + $cc`
runs_this_day=`find . -maxdepth 1 -mtime $cc -ls |wc -l`
echo -n "$DATE $cc days ago: " ; printf_this_one_div10 $runs_this_day
done
}
@ -556,7 +593,8 @@ nb_syncs_badly_finished() {
nb_syncs_badly_finished=`echo $logfiles_finished_recently | xargs grep -i 'Exiting with return value' | grep -v 'return value 0' | wc -l `
echo $nb_syncs_badly_finished / $nb_logfiles_finished_recently
cat <<EOF
logfiles_finished_recently $1 | xargs grep -i 'Exiting with return value' | grep -v 'return value 0'
logfiles_finished_recently $1 | xargs grep -i 'Exiting with return value' | grep -v 'return value 0'
logfiles_finished_recently $1 | xargs grep -i 'Exiting with return value' | grep -v 'return value 0' | grep -o 'Exiting with return value.*' | sort | uniq -c | sort -n
EOF
}
@ -593,13 +631,18 @@ summary_compute2() {
&& summary_display
}
number_of_syncs()
{
list_all_logs | wc -l
}
echoq summary_display
summary_display() {
vnstat_gen > /dev/null
echo "Start date of /X (aaaa mm dd): `first_use` (`days_since_first_use` days of service)"
echo -n "Number of /X users: " ; number_of_X_users
echo -n "Number of /X accounts synced: " ; nb_migrations_launched
echo -n "Number of /X syncs: " ; list_all_logs| grep -v abort.txt | wc -l
echo -n "Number of /X syncs: " ; number_of_syncs
echo -n "Total volume /X transferred: " ; total_volume_transferred
echo -n "Total messages /X transferred: " ; total_messages_transferred
echo -n "Biggest transfer: " ; biggest_transfer
@ -607,6 +650,8 @@ summary_display() {
echo -n "Biggest message transferred: " ; biggest_message_transferred
echo -n "Biggest bandwidth rate: " ; biggest_bandwidth_rate
echo -n "Longest transfer: " ; seconds_to_days_hours `longest_transfer`
echo -n "Queue length mean is: " ; stat_queue_mean
echo "Data made at" `date -r grep_stats.txt`
}
echoq sync_ks2_i005
@ -623,8 +668,9 @@ sync_ks2_i005()
&& summary_compute2 \
&& echo sending txt back to ks2 \
&& rsync -av /home/imapsync_cgi_ks2/*txt root@ks2:/var/tmp/imapsync_cgi/ \
&& summary_display \
&& date \
&& pwd
&& pwd
}
echoq watch_number_of_imapsync_running

View file

@ -1,16 +1,29 @@
/* $Id: imapsync_form.css,v 1.1 2018/01/27 21:58:41 gilles Exp gilles $ */
/* $Id: imapsync_form.css,v 1.5 2019/06/25 21:31:44 gilles Exp gilles $ */
#account1 {
background-color: DodgerBlue ;
// background-color: DodgerBlue ;
background-color: Fuchsia ;
}
#account2 {
background-color: DarkTurquoise ;
}
#parameters {
// background-color: GreenYellow ;
// background-color: White ;
}
#progress {
text-align: center ;
font-size: 1.6em ;
margin: 0 0 0px;
}
.padd0 {
padding-left: 0px ;
padding-right: 0px ;
}
}

112
X/imapsync_form.html Normal file → Executable file
View file

@ -1,5 +1,5 @@
<!DOCTYPE html>
<!-- $Id: imapsync_form.html,v 1.62 2019/02/01 21:34:28 gilles Exp gilles $ -->
<!-- $Id: imapsync_form.html,v 1.75 2019/06/27 05:27:13 gilles Exp gilles $ -->
<html lang="en" id="top">
@ -20,9 +20,7 @@
<noscript>
<style>
.scripton {display:none;}
</style>
<link rel="stylesheet" href="noscript.css">
</noscript>
</head>
@ -30,22 +28,33 @@
<body>
<div class="hidden scripton">
<pre id="tests">
</pre>
<input type="checkbox" id="test_checkbox">
<input type="text" id="test_text">
<input type="radio" id="test_radio" name="test_radio" value="first" >
<input type="radio" id="test_radio" name="test_radio" value="second" >
</div>
<div class="container-fluid" >
<div class="row">
<div class="text-center">
<a href="https://imapsync.lamiral.info/">
<img alt="Imapsync home" src="https://imapsync.lamiral.info/X/logo_imapsync_Xn.png" height="38" width="60">
<img alt="Imapsync home" title="Imapsync home page" src="https://imapsync.lamiral.info/X/logo_imapsync_Xn.png" height="38" width="60">
</a>
<a href="#top" class="btn btn-info active" role="button">Top</a>
<a href="#top" title="Top of the page" class="btn btn-info " role="button">Top</a>
<!-- <a href="#payment" class="btn btn-success" data-toggle="collapse">Pricing</a> -->
<a href="#buttons" class="btn btn-info scripton" role="button">Consoles</a>
<a href="#bottom" class="btn btn-info" role="button">Bottom</a>
<!-- <a href="#buttons" class="btn btn-info scripton" role="button">Consoles</a> -->
<a href="#bottom" title="Bottom of the page" class="btn btn-info active" role="button">Bottom</a>
</div>
</div>
<h1 class="text-center">Imapsync online</h1>
<p class="text-center"> <strong>Copy</strong>/synchronize a <strong>complete</strong> mailbox to another, without <strong>duplicates!</strong></p>
<!-- Paypal part start
new: NDGMR6TLFZ926
old: H2YTURNFT4XT4
@ -57,11 +66,11 @@ old: H2YTURNFT4XT4
<a href="#payment" class="btn btn-warning btn-lg" data-toggle="collapse">Pricing</a>
</div>
-->
<!-- the "in" makes the form not collapsed by default
Remove the in in order to mask the pricing section
<div id="payment" class="well text-center collapse in" > -->
<div id="payment" class="well text-center collapse in" >
<div id="payment" class="well text-center collapse out" >
<p class="lead">Pay by usage type</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
<input type="hidden" name="cmd" value="_s-xclick" />
@ -91,37 +100,40 @@ old: H2YTURNFT4XT4
</form>
</div>
<!-- Paypal part end -->
<form id="form" action="/cgi-bin/imapsync" method="post" autocomplete="on">
<div class="row">
<div id="account1" class="col-md-6" >
<fieldset>
<legend class="text-center h2">Source account</legend>
<fieldset>
<legend class="text-center h2">IMAP source mailbox</legend>
<label for="user1">--user1</label>
<label for="user1">Login</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"> </i></span>
<input
data-toggle="tooltip" data-placement="top" title="It is usually an email address or its left part before @"
data-toggle="tooltip" data-placement="bottom" title="It is usually an email address or its left part before @"
type="text" class="form-control input-lg" id="user1" name="user1" tabindex="1"
placeholder="Enter source login name">
placeholder="Enter login name">
</div>
<label for="password1">--password1</label>
<label for="password1">Password</label>
<label class="checkbox-inline out">
<input type="checkbox" id="showpassword1"> show password
</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input
data-toggle="tooltip" data-placement="top" title="Passwords are not stored on the server"
data-toggle="tooltip" data-placement="bottom" title="Passwords are not stored on the server"
type="password" class="form-control input-lg" id="password1" name="password1" tabindex="2"
placeholder="Enter password">
</div>
<label for="host1">--host1</label>
<label for="host1">Server</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-cloud"></i></span>
<input
data-toggle="tooltip" data-placement="top" title="IMAP transfers are done with encryption if the servers support it."
data-toggle="tooltip" data-placement="bottom" title="IMAP transfers are done with encryption if the servers support it."
list="servers1" type="text" class="form-control input-lg" id="host1" name="host1" tabindex="3"
placeholder="Enter imap source server name or IP address">
<datalist id="servers1">
@ -141,36 +153,39 @@ old: H2YTURNFT4XT4
<div>
<br>
</div>
</fieldset>
</fieldset>
</div>
<div id="account2" class="col-md-6" >
<fieldset>
<legend class="text-center h2">Destination account</legend>
<fieldset>
<legend class="text-center h2">IMAP destination mailbox</legend>
<label for="user2">--user2</label>
<label for="user2">Login</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input
data-toggle="tooltip" data-placement="top" title="It is usually an email address or its left part before @"
data-toggle="tooltip" data-placement="bottom" title="It is usually an email address or its left part before @"
type="text" class="form-control input-lg" id="user2" name="user2" tabindex="6"
placeholder="Enter destination login name">
placeholder="Enter login name">
</div>
<label for="password2">--password2</label>
<label for="password2">Password</label>
<label class="checkbox-inline out">
<input type="checkbox" id="showpassword2"> show password
</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input
data-toggle="tooltip" data-placement="top" title="Passwords are not stored on the server"
data-toggle="tooltip" data-placement="bottom" title="Passwords are not stored on the server"
type="password" class="form-control input-lg" id="password2" name="password2" tabindex="7"
placeholder="Enter password">
</div>
<label for="host2">--host2</label>
<label for="host2">Server</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-cloud"></i></span>
<input
data-toggle="tooltip" data-placement="top" title="IMAP transfers are done with encryption if the servers support it."
data-toggle="tooltip" data-placement="bottom" title="IMAP transfers are done with encryption if the servers support it."
list="servers2" type="text" class="form-control input-lg" id="host2" name="host2" tabindex="8"
placeholder="Enter imap destination server name or IP address">
<datalist id="servers2">
@ -189,30 +204,31 @@ old: H2YTURNFT4XT4
<div>
<br>
</div>
</fieldset>
</fieldset>
</div>
</div>
<input type="hidden" name="automap" value="on">
<input type="hidden" name="addheader" value="on">
<!--
<input type="hidden" name="simulong" value="3600">
-->
<!-- --#>
<input type="hidden" name="simulong" value="360">
<#!-- -->
<a name="buttons"></a>
<hr>
<!-- Classical button to go to the log only -->
<noscript>
<button type="submit" class="btn btn-success btn-lg center-block btn-block">Go sync!</button>
<button type="submit" class="btn btn-success btn-lg center-block btn-block">Go sync!</button>
</noscript>
<!-- Javascript buttons using xhr -->
<!-- Javascript buttons using xhr -->
<div class="row scripton">
<div class="col-sm-6 padd0" >
<button id="bt-sync" type="button"
class="btn btn-success btn-lg center-block btn-block"
tabindex="11"
data-toggle="tooltip" data-placement="top" title="Launch the sync! You can abort the sync with the red Abort button nearby or by closing the tab/window."
data-toggle="tooltip" data-placement="top"
title="Launch the sync! You can abort the sync with the red Abort button nearby or by closing the tab/window."
>
Sync or resync!<br>
<span class="glyphicon glyphicon-envelope"></span>
@ -223,7 +239,8 @@ old: H2YTURNFT4XT4
<div class="col-sm-6 padd0" >
<button id="bt-abort" type="button"
class="btn btn-danger btn-lg center-block btn-block" tabindex="12"
data-toggle="tooltip" data-placement="top" title="You can abort and restart the sync later, no duplicates should happen"
data-toggle="tooltip" data-placement="top"
title="Abort the sync! You can restart the sync later, no duplicates should happen."
>
Abort!<br>
<span class="glyphicon glyphicon-scissors"></span>
@ -232,8 +249,11 @@ old: H2YTURNFT4XT4
</div>
</form>
<div class="row scripton" id="consoles">
<pre id="progress" ></pre>
<div class="col-sm-6 well">
<h2 class="text-center">Console of imapsync run</h2>
<pre id="console">
@ -297,13 +317,13 @@ old: H2YTURNFT4XT4
<div class="row">
<div class="text-center">
<a href="https://imapsync.lamiral.info/">
<img alt="Imapsync home" src="https://imapsync.lamiral.info/X/logo_imapsync_Xn.png" height="38" width="60">
<img alt="Imapsync home page" src="https://imapsync.lamiral.info/X/logo_imapsync_Xn.png" height="38" width="60">
</a>
<a href="#top" class="btn btn-info " role="button">Top</a>
<a href="#buttons" class="btn btn-info scripton" role="button">Consoles</a>
<a href="#bottom" class="btn btn-info active" role="button">Bottom</a>
<a href="#top" title="Top of the page" class="btn btn-info " role="button">Top</a>
<!-- <a href="#buttons" class="btn btn-info scripton" role="button">Consoles</a> -->
<a href="#bottom" title="Bottom of the page" class="btn btn-info active" role="button">Bottom</a>
<br>
<small> ($Id: imapsync_form.html,v 1.62 2019/02/01 21:34:28 gilles Exp gilles $) </small><br>
<small> ($Id: imapsync_form.html,v 1.75 2019/06/27 05:27:13 gilles Exp gilles $) </small><br>
Terms and conditions for anything: <a href="https://imapsync.lamiral.info/LICENSE">No limits to do anything with this work and this license!</a><br>
</div>
</div>
@ -326,7 +346,7 @@ crossorigin="anonymous"
<script
src="imapsync_form.js"
src="imapsync_form.js"
>
</script>

View file

@ -1,104 +1,453 @@
// $Id: imapsync_form.js,v 1.2 2018/01/27 21:58:52 gilles Exp gilles $
// $Id: imapsync_form.js,v 1.8 2019/06/25 16:41:43 gilles Exp gilles $
/*jslint browser: true*/ /*global $*/
$(document).ready(function () {
"use strict";
// Bootstrap popover and tooltip
$("[data-toggle='tooltip']").tooltip();
var readyStateStr = {
"0": "Request not initialized",
"1": "Server connection established",
"2": "Response headers received",
"3": "Processing request",
"4": "Finished and response is ready"
};
function refreshLog(xhr) {
$("#output").html(xhr.responseText);
}
$(document).ready(
function ()
{
"use strict";
// Bootstrap popover and tooltip
$("[data-toggle='tooltip']").tooltip();
function handleRun(xhr, timerRefreshLog) {
var readyStateStr = {
"0": "Request not initialized",
"1": "Server connection established",
"2": "Response headers received",
"3": "Processing request",
"4": "Finished and response is ready"
};
$("#console").text("Status: " + xhr.status + " " + xhr.statusText + "\n" + "State: " + readyStateStr[xhr.readyState] + "\n");
if (xhr.readyState === 4) {
// var headers = xhr.getAllResponseHeaders();
// $("#console").append(headers);
// $("#console").append("See the completed log\n");
$("#link_to_bottom").show();
clearInterval(timerRefreshLog);
refreshLog(xhr); // a last time
$("#bt-sync").prop("disabled", false); // back to enable state for next run
function is( expected, given, comment )
{
var message = ": ["
+ expected
+ "] === ["
+ given
+ "] "
+ comment
+ "\n" ;
if ( expected === given )
{
message = "ok " + message ;
}
else
{
message = "Nok" + message ;
}
$("#tests").append( message ) ;
}
}
function imapsync() {
var querystring = $("#form").serialize();
$("#abort").text("\n\n"); // clean abort console
$("#output").text("Here comes the log!\n\n");
if ("imap.gmail.com" === $("#host1").val()) {
querystring = querystring + "&gmail1=on";
function last_eta( string )
{
// return the last occurrence of the substring "ETA: ...\n"
// or ""
var eta ;
var last_found ;
if ( undefined === string )
{
return "" ;
}
var eta_re = /ETA:.*\n/g ;
eta = string.match( eta_re ) ;
if ( eta )
{
last_found = eta[eta.length -1 ] ;
return last_found ;
}
else
{
return "" ;
}
}
if ("imap.gmail.com" === $("#host2").val()) {
querystring = querystring + "&gmail2=on";
function tests_last_eta()
{
is( "", last_eta( ), "last_eta: no args => empty string" ) ;
is( "", last_eta( "" ), "last_eta: empty => empty string" ) ;
is( "", last_eta( "ETA" ), "last_eta: ETA => empty string" ) ;
is( "", last_eta( "ETA: but no CR" ),
"last_eta: ETA: but no CR => empty string" ) ;
is(
"ETA: with CR\n",
last_eta( "Blabla ETA: with CR\n" ),
"last_eta: ETA: with CR => ETA: with CR"
) ;
is(
"ETA: 2 with CR\n",
last_eta( "Blabla ETA: 1 with CR\nBlabla ETA: 2 with CR\n" ),
"last_eta: several ETA: with CR => ETA: 2 with CR"
) ;
}
var xhr;
xhr = new XMLHttpRequest();
var timerRefreshLog = setInterval(function () {
refreshLog(xhr);
}, 5000);
xhr.onreadystatechange = function () {
handleRun(xhr, timerRefreshLog);
};
xhr.open("POST", "/cgi-bin/imapsync", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring);
}
function handleAbort(xhr) {
$("#abort").text("Status: " + xhr.status + " " + xhr.statusText + "\n" + "State: " + readyStateStr[xhr.readyState] + "\n\n");
if (xhr.readyState === 4) {
$("#abort").append(xhr.responseText);
$("#bt-sync").prop("disabled", false);
$("#bt-abort").prop("disabled", false); // back for next abort
function refreshLog(xhr)
{
var slice_length ;
$("#output").text(xhr.responseText) ;
if (xhr.readyState === 4) {
slice_length = -2400 ;
}
else
{
slice_length = -240 ;
}
$("#progress").text( last_eta( xhr.responseText.slice( slice_length ) ) ) ;
}
}
function abort() {
var querystring = $("#form").serialize() + "&abort=on";
var xhr;
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
handleAbort(xhr);
};
xhr.open("POST", "/cgi-bin/imapsync", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring);
}
// in case of a manual refresh, start
$("#bt-sync").prop("disabled", false);
$("#bt-abort").prop("disabled", false);
$("#link_to_bottom").hide();
$("#bt-sync").click(function () {
$("#bt-sync").prop("disabled", true);
$("#bt-abort").prop("disabled", false);
$("#link_to_bottom").hide();
imapsync();
});
function handleRun(xhr, timerRefreshLog)
{
$("#bt-abort").click(function () {
$("#bt-sync").prop("disabled", true);
$("#bt-abort").prop("disabled", true);
abort();
});
$("#console").text("Status: " + xhr.status + " " + xhr.statusText + "\n" + "State: " + readyStateStr[xhr.readyState] + "\n") ;
});
if (xhr.readyState === 4) {
// var headers = xhr.getAllResponseHeaders();
// $("#console").append(headers);
// $("#console").append("See the completed log\n");
$("#link_to_bottom").show();
clearInterval(timerRefreshLog);
refreshLog(xhr); // a last time
$("#bt-sync").prop("disabled", false); // back to enable state for next run
}
}
function imapsync()
{
var querystring = $("#form").serialize();
$("#abort").text("\n\n"); // clean abort console
$("#output").text("Here comes the log!\n\n");
if ( "imap.gmail.com" === $("#host1").val() )
{
querystring = querystring + "&gmail1=on";
}
if ( "imap.gmail.com" === $("#host2").val() )
{
querystring = querystring + "&gmail2=on";
}
var xhr;
xhr = new XMLHttpRequest();
var timerRefreshLog = setInterval(
function ()
{
refreshLog(xhr);
}, 5000 ) ;
xhr.onreadystatechange = function ()
{
handleRun(xhr, timerRefreshLog);
};
xhr.open("POST", "/cgi-bin/imapsync", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring);
}
function handleAbort(xhr)
{
$("#abort").text("Status: " + xhr.status + " " + xhr.statusText + "\n" + "State: " + readyStateStr[xhr.readyState] + "\n\n");
if (xhr.readyState === 4)
{
$("#abort").append(xhr.responseText);
$("#bt-sync").prop("disabled", false);
$("#bt-abort").prop("disabled", false); // back for next abort
}
}
function abort()
{
var querystring = $("#form").serialize() + "&abort=on";
var xhr;
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function ()
{
handleAbort(xhr);
};
xhr.open("POST", "/cgi-bin/imapsync", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring);
}
function store( id )
{
var stored ;
$( "#tests" ).append( "Eco: " + id + " type is " + $( id ).attr( "type" ) + "\n" ) ;
if ( "text" === $( id ).attr( "type" ) || "password" === $( id ).attr( "type" ) )
{
localStorage.setItem( id, $(id).val() ) ;
stored = $(id).val() ;
}
else if ( "checkbox" === $( id ).attr( "type" ) )
{
$( "#tests" ).append( "Eco: " + id + " checked is " + $( id )[0].checked + "\n" ) ;
localStorage.setItem( id, $( id )[0].checked ) ;
stored = $( id )[0].checked ;
}
return stored ;
}
function retrieve( id )
{
var retrieved ;
$( "#tests" ).append( "Eco: " + id + " type is " + $( id ).attr( "type" ) + " length is " + $( id ).length + "\n" ) ;
if ( "text" === $( id ).attr( "type" ) || "password" === $( id ).attr( "type" ) )
{
$( id ).val( localStorage.getItem( id ) ) ;
retrieved = $( id ).val() ;
}
else if ( "checkbox" === $( id ).attr( "type" ) )
{
$( "#tests" ).append( "Eco: " + id + " getItem is " + localStorage.getItem( id ) + "\n" ) ;
$( id )[0].checked = JSON.parse( localStorage.getItem( id ) ) ;
retrieved = $( id )[0].checked ;
}
return retrieved ;
}
function tests_store_retrieve()
{
if ( $("#tests").length !== 0 )
{
is( 1, 1, "one equals one" ) ;
// isnot( 0, 1, "zero differs one" ) ;
// no exist
is( undefined, store( "#test_noexists" ), "store: #test_noexists" ) ;
is( undefined, retrieve( "#test_noexists" ), "retrieve: #test_noexists" ) ;
is( undefined, retrieve( "#test_noexists2" ), "retrieve: #test_noexists2" ) ;
// input text
$("#test_text" ).val( "foo" ) ;
is( "foo", $("#test_text" ).val( ), "#test_text val = foo" ) ;
is( "foo", store( "#test_text" ), "store: #test_text" ) ;
$("#test_text" ).val( "bar" ) ;
is( "bar", $("#test_text" ).val( ), "#test_text val = bar" ) ;
is( "foo", retrieve( "#test_text" ), "retrieve: #test_text = foo" ) ;
is( "foo", $("#test_text" ).val( ), "#test_text val = foo" ) ;
// input check button
$( "#test_checkbox" ).prop( "checked", true );
is( true, store( "#test_checkbox" ), "store: #test_checkbox checked" ) ;
$( "#test_checkbox" ).prop( "checked", false );
is( true, retrieve( "#test_checkbox" ), "retrieve: #test_checkbox = true" ) ;
$( "#test_checkbox" ).prop( "checked", false );
is( false, store( "#test_checkbox" ), "store: #test_checkbox not checked" ) ;
$( "#test_checkbox" ).prop( "checked", true );
is( false, retrieve( "#test_checkbox" ), "retrieve: #test_checkbox = false" ) ;
}
}
function store_form()
{
if ( Storage !== "undefined")
{
// Code for localStorage.
store("#user1") ;
store("#password1") ;
store("#host1") ;
store("#subfolder1") ;
store("#showpassword1") ;
store("#user2") ;
store("#password2") ;
store("#host2") ;
store("#subfolder2") ;
store("#showpassword2") ;
store("#dry") ;
store("#justlogin") ;
store("#justfolders") ;
store("#justfoldersizes") ;
localStorage.account1_background_color = $("#account1").css("background-color") ;
localStorage.account2_background_color = $("#account2").css("background-color") ;
}
}
function show_extra_if_needed()
{
if ( $("#subfolder1").length && $("#subfolder1").val().length > 0 )
{
$(".extra_param").show() ;
}
if ( $("#subfolder2").length && $("#subfolder2").val().length > 0 )
{
$(".extra_param").show() ;
}
}
function retrieve_form()
{
if ( Storage !== "undefined" )
{
// Code for localStorage.
retrieve( "#user1" ) ;
retrieve( "#password1" ) ;
// retrieve("#showpassword1") ;
retrieve( "#host1" ) ;
retrieve( "#subfolder1" ) ;
retrieve( "#user2" ) ;
retrieve( "#password2" ) ;
// retrieve("#showpassword2") ;
retrieve( "#host2" ) ;
retrieve( "#subfolder2" ) ;
retrieve( "#dry" ) ;
retrieve( "#justlogin" ) ;
retrieve( "#justfolders" ) ;
retrieve( "#justfoldersizes" ) ;
// In case
// localStorage.removeItem( "account1_background_color" ) ;
// localStorage.removeItem( "account2_background_color" ) ;
if ( localStorage.account1_background_color )
{
$("#account1").css("background-color", localStorage.account1_background_color ) ;
}
if ( localStorage.account2_background_color )
{
$("#account2").css("background-color", localStorage.account2_background_color ) ;
}
// Show the extra parameters if they are not empty because it would be dangerous
// to retrieve them without knowing
show_extra_if_needed() ;
}
}
function showpassword( id, button )
{
var x = document.getElementById( id );
if ( button.checked )
{
x.type = "text";
} else {
x.type = "password";
}
}
function init()
{
// in case of a manual refresh, start with
$("#bt-sync").prop("disabled", false);
$("#bt-abort").prop("disabled", false);
$("#link_to_bottom").hide();
retrieve_form();
$("#showpassword1").click(
function ()
{
// does not change jslint report...
/*jshint validthis: true */
var button = this ;
showpassword( "password1", button ) ;
}
);
$("#showpassword2").click(
function ()
{
var button = this ;
showpassword( "password2", button ) ;
}
);
$("#bt-sync").click(
function ()
{
$("#bt-sync").prop("disabled", true);
$("#bt-abort").prop("disabled", false);
$("#link_to_bottom").hide();
store_form();
imapsync();
}
);
$("#bt-abort").click(
function ()
{
$("#bt-sync").prop("disabled", true);
$("#bt-abort").prop("disabled", true);
abort();
}
);
$.fn.swapWith = function(to)
{
var temp = $(to).val();
$(to).val($(this).val());
$(this).val(temp);
};
$("#swap").click(
function()
{
// swaping colors can't use swapWith()
var temp1 = $("#account1").css("background-color") ;
var temp2 = $("#account2").css("background-color") ;
$("#account1").css("background-color", temp2 );
$("#account2").css("background-color", temp1 );
$("#user1").swapWith("#user2");
$("#password1").swapWith("#password2");
$("#host1").swapWith("#host2");
$("#subfolder1").swapWith("#subfolder2");
var temp = $("#showpassword1")[0].checked ;
$("#showpassword1")[0].checked = $("#showpassword2")[0].checked ;
$("#showpassword2")[0].checked = temp ;
showpassword( "password1", $("#showpassword1")[0] ) ;
showpassword( "password2", $("#showpassword2")[0] ) ;
}
);
}
function progress_bar_update( string )
{
//
return ;
}
function tests()
{
if ( $("#tests").length !== 0 )
{
tests_store_retrieve() ;
tests_last_eta() ;
}
}
init( ) ;
tests( ) ;
}
);

159
X/imapsync_form_1.3.js Executable file
View file

@ -0,0 +1,159 @@
// $Id: imapsync_form.js,v 1.3 2019/03/18 19:21:16 gilles Exp gilles $
/*jslint browser: true*/ /*global $*/
$(document).ready(function () {
"use strict";
// Bootstrap popover and tooltip
$("[data-toggle='tooltip']").tooltip();
var readyStateStr = {
"0": "Request not initialized",
"1": "Server connection established",
"2": "Response headers received",
"3": "Processing request",
"4": "Finished and response is ready"
};
function refreshLog(xhr) {
$("#output").html(xhr.responseText);
}
function handleRun(xhr, timerRefreshLog) {
$("#console").text("Status: " + xhr.status + " " + xhr.statusText + "\n" + "State: " + readyStateStr[xhr.readyState] + "\n");
if (xhr.readyState === 4) {
// var headers = xhr.getAllResponseHeaders();
// $("#console").append(headers);
// $("#console").append("See the completed log\n");
$("#link_to_bottom").show();
clearInterval(timerRefreshLog);
refreshLog(xhr); // a last time
$("#bt-sync").prop("disabled", false); // back to enable state for next run
}
}
function imapsync() {
var querystring = $("#form").serialize();
$("#abort").text("\n\n"); // clean abort console
$("#output").text("Here comes the log!\n\n");
if ("imap.gmail.com" === $("#host1").val()) {
querystring = querystring + "&gmail1=on";
}
if ("imap.gmail.com" === $("#host2").val()) {
querystring = querystring + "&gmail2=on";
}
var xhr;
xhr = new XMLHttpRequest();
var timerRefreshLog = setInterval(function () {
refreshLog(xhr);
}, 5000);
xhr.onreadystatechange = function () {
handleRun(xhr, timerRefreshLog);
};
xhr.open("POST", "/cgi-bin/imapsync", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring);
}
function handleAbort(xhr) {
$("#abort").text("Status: " + xhr.status + " " + xhr.statusText + "\n" + "State: " + readyStateStr[xhr.readyState] + "\n\n");
if (xhr.readyState === 4) {
$("#abort").append(xhr.responseText);
$("#bt-sync").prop("disabled", false);
$("#bt-abort").prop("disabled", false); // back for next abort
}
}
function abort() {
var querystring = $("#form").serialize() + "&abort=on";
var xhr;
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
handleAbort(xhr);
};
xhr.open("POST", "/cgi-bin/imapsync", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring);
}
function store_form() {
if (typeof(Storage) !== "undefined") {
// Code for localStorage.
localStorage.user1 = $("#user1").val();
localStorage.password1 = $("#password1").val();
localStorage.host1 = $("#host1").val();
localStorage.user2 = $("#user2").val();
localStorage.password2 = $("#password2").val();
localStorage.host2 = $("#host2").val();
} else {
// Sorry! No Web Storage support...
}
}
function retrieve_form() {
if (typeof(Storage) !== "undefined") {
// Code for localStorage.
$("#user1").val(localStorage.user1);
$("#password1").val(localStorage.password1);
$("#host1").val(localStorage.host1);
$("#user2").val(localStorage.user2);
$("#password2").val(localStorage.password2);
$("#host2").val(localStorage.host2);
} else {
// Sorry! No Web Storage support...
}
}
function showpassword() {
}
// in case of a manual refresh, start with
$("#bt-sync").prop("disabled", false);
$("#bt-abort").prop("disabled", false);
$("#link_to_bottom").hide();
retrieve_form();
// Well I should write function showpassword() body and use it
// I'm just dumb in js and jQuery
$("#showpassword1").click(function () {
var x = document.getElementById("password1");
if (x.type === "password") {
x.type = "text";
} else {
x.type = "password";
}
});
$("#showpassword2").click(function () {
var x = document.getElementById("password2");
if (x.type === "password") {
x.type = "text";
} else {
x.type = "password";
}
});
$("#bt-sync").click(function () {
$("#bt-sync").prop("disabled", true);
$("#bt-abort").prop("disabled", false);
$("#link_to_bottom").hide();
store_form();
imapsync();
});
$("#bt-abort").click(function () {
$("#bt-sync").prop("disabled", true);
$("#bt-abort").prop("disabled", true);
abort();
});
});

228
X/imapsync_form_1.4.js Executable file
View file

@ -0,0 +1,228 @@
// $Id: imapsync_form.js,v 1.4 2019/04/28 03:02:37 gilles Exp $
/*jslint browser: true*/ /*global $*/
$(document).ready(function () {
"use strict";
// Bootstrap popover and tooltip
$("[data-toggle='tooltip']").tooltip();
var readyStateStr = {
"0": "Request not initialized",
"1": "Server connection established",
"2": "Response headers received",
"3": "Processing request",
"4": "Finished and response is ready"
};
function refreshLog(xhr) {
$("#output").html(xhr.responseText);
}
function handleRun(xhr, timerRefreshLog) {
$("#console").text("Status: " + xhr.status + " " + xhr.statusText + "\n" + "State: " + readyStateStr[xhr.readyState] + "\n");
if (xhr.readyState === 4) {
// var headers = xhr.getAllResponseHeaders();
// $("#console").append(headers);
// $("#console").append("See the completed log\n");
$("#link_to_bottom").show();
clearInterval(timerRefreshLog);
refreshLog(xhr); // a last time
$("#bt-sync").prop("disabled", false); // back to enable state for next run
}
}
function imapsync() {
var querystring = $("#form").serialize();
$("#abort").text("\n\n"); // clean abort console
$("#output").text("Here comes the log!\n\n");
if ("imap.gmail.com" === $("#host1").val()) {
querystring = querystring + "&gmail1=on";
}
if ("imap.gmail.com" === $("#host2").val()) {
querystring = querystring + "&gmail2=on";
}
var xhr;
xhr = new XMLHttpRequest();
var timerRefreshLog = setInterval(function () {
refreshLog(xhr);
}, 5000);
xhr.onreadystatechange = function () {
handleRun(xhr, timerRefreshLog);
};
xhr.open("POST", "/cgi-bin/imapsync", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring);
}
function handleAbort(xhr) {
$("#abort").text("Status: " + xhr.status + " " + xhr.statusText + "\n" + "State: " + readyStateStr[xhr.readyState] + "\n\n");
if (xhr.readyState === 4) {
$("#abort").append(xhr.responseText);
$("#bt-sync").prop("disabled", false);
$("#bt-abort").prop("disabled", false); // back for next abort
}
}
function abort() {
var querystring = $("#form").serialize() + "&abort=on";
var xhr;
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
handleAbort(xhr);
};
xhr.open("POST", "/cgi-bin/imapsync", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring);
}
function store_form() {
if (typeof(Storage) !== "undefined") {
// Code for localStorage.
localStorage.user1 = $("#user1").val();
localStorage.password1 = $("#password1").val();
localStorage.host1 = $("#host1").val();
localStorage.subfolder1 = $("#subfolder1").val();
localStorage.showpassword1 = $("#showpassword1")[0].checked ;
//
localStorage.account1_background_color = $("#account1").css("background-color") ;
localStorage.user2 = $("#user2").val();
localStorage.password2 = $("#password2").val();
localStorage.host2 = $("#host2").val();
localStorage.subfolder2 = $("#subfolder2").val();
localStorage.showpassword2 = $("#showpassword2")[0].checked ;
// alert( $("#dry")[0].checked ) ;
localStorage.dry = $("#dry")[0].checked ;
localStorage.justlogin = $("#justlogin")[0].checked ;
localStorage.justfolders = $("#justfolders")[0].checked ;
localStorage.justfoldersizes = $("#justfoldersizes")[0].checked ;
localStorage.account2_background_color = $("#account2").css("background-color") ;
} else {
// Sorry! No Web Storage support...
}
}
function retrieve_form() {
if (typeof(Storage) !== "undefined")
{
// Code for localStorage.
$("#user1").val(localStorage.user1);
$("#password1").val(localStorage.password1);
// $("#showpassword1")[0].checked = JSON.parse(localStorage.showpassword1);
$("#host1").val(localStorage.host1);
$("#subfolder1").val(localStorage.subfolder1);
$("#user2").val(localStorage.user2);
$("#password2").val(localStorage.password2);
// $("#showpassword2")[0].checked = JSON.parse(localStorage.showpassword2);
$("#host2").val(localStorage.host2);
$("#subfolder2").val(localStorage.subfolder2);
$("#dry")[0].checked = JSON.parse(localStorage.dry || false );
$("#justlogin")[0].checked = JSON.parse(localStorage.justlogin || false );
$("#justfolders")[0].checked = JSON.parse(localStorage.justfolders || false );
$("#justfoldersizes")[0].checked = JSON.parse(localStorage.justfoldersizes || false );
// In case
// localStorage.removeItem( "account1_background_color" ) ;
// localStorage.removeItem( "account2_background_color" ) ;
if ( localStorage.account1_background_color )
{
$("#account1").css("background-color", localStorage.account1_background_color ) ;
}
if ( localStorage.account2_background_color )
{
$("#account2").css("background-color", localStorage.account2_background_color ) ;
}
}
else
{
// Sorry! No Web Storage support...
}
}
function showpassword() {
}
// in case of a manual refresh, start with
$("#bt-sync").prop("disabled", false);
$("#bt-abort").prop("disabled", false);
$("#link_to_bottom").hide();
retrieve_form();
// Well I should write function showpassword() body and use it
// I'm just dumb in js and jQuery
$("#showpassword1").click(function () {
var x = document.getElementById("password1");
if (x.type === "password" && this.checked ) {
x.type = "text";
} else {
x.type = "password";
}
});
$("#showpassword2").click(function () {
var x = document.getElementById("password2");
if (x.type === "password" && this.checked ) {
x.type = "text";
} else {
x.type = "password";
}
});
$("#bt-sync").click(function () {
$("#bt-sync").prop("disabled", true);
$("#bt-abort").prop("disabled", false);
$("#link_to_bottom").hide();
store_form();
imapsync();
});
$("#bt-abort").click(function () {
$("#bt-sync").prop("disabled", true);
$("#bt-abort").prop("disabled", true);
abort();
});
jQuery.fn.swapWith = function(to) {
var temp = $(to).val();
$(to).val($(this).val());
$(this).val(temp);
};
$("#swap").click(function(){
$("#user1").swapWith("#user2");
$("#password1").swapWith("#password2");
$("#host1").swapWith("#host2");
$("#subfolder1").swapWith("#subfolder2");
var temp = $("#account1").css("background-color") ;
$("#account1").css("background-color", $("#account2").css("background-color") ) ;
$("#account2").css("background-color", temp ) ;
});
// End of
});

344
X/imapsync_form_1.69.html Executable file
View file

@ -0,0 +1,344 @@
<!DOCTYPE html>
<!-- $Id: imapsync_form.html,v 1.69 2019/03/31 22:25:15 gilles Exp $ -->
<html lang="en" id="top">
<head>
<title>Imapsync online</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<link rel="stylesheet" href="imapsync_form.css">
<link rel="license" href="https://imapsync.lamiral.info/NOLIMIT">
<noscript>
<style>
.scripton {display:none;}
</style>
</noscript>
</head>
<body>
<div class="container-fluid" >
<div class="row">
<div class="text-center">
<a href="https://imapsync.lamiral.info/">
<img alt="Imapsync home" title="Imapsync home page" src="https://imapsync.lamiral.info/X/logo_imapsync_Xn.png" height="38" width="60">
</a>
<a href="#top" title="Top of the page" class="btn btn-info " role="button">Top</a>
<!-- <a href="#payment" class="btn btn-success" data-toggle="collapse">Pricing</a> -->
<!-- <a href="#buttons" class="btn btn-info scripton" role="button">Consoles</a> -->
<a href="#bottom" title="Bottom of the page" class="btn btn-info active" role="button">Bottom</a>
</div>
</div>
<h1 class="text-center">Imapsync online</h1>
<p class="text-center"> <strong>Copy</strong>/synchronize a <strong>complete</strong> mailbox to another, without <strong>duplicates!</strong></p>
<!-- Paypal part start
new: NDGMR6TLFZ926
old: H2YTURNFT4XT4
-->
<!-- A button above the pricing form, not very beautiful...
I should give it a try anyway because nearly no one buy this service...
<div class="text-center">
<a href="#payment" class="btn btn-warning btn-lg" data-toggle="collapse">Pricing</a>
</div>
-->
<!-- the "in" makes the form not collapsed by default
Remove the in in order to mask the pricing section
<div id="payment" class="well text-center collapse in" > -->
<div id="payment" class="well text-center collapse" >
<p class="lead">Pay by usage type</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
<input type="hidden" name="cmd" value="_s-xclick" />
<input type="hidden" name="hosted_button_id" value="H2YTURNFT4XT4" />
<input type="hidden" name="on0" value="imapsync choice" />
<fieldset>
<!--
<label data-toggle="tooltip" data-placement="top" title="Fair enough"
class="radio-inline"><input type="radio" name="os0" value="Tiny" > €1,00 </label>
-->
<label data-toggle="tooltip" data-placement="top" title="A big mailbox"
class="radio-inline"><input type="radio" name="os0" value="Small" > €6,00 </label>
<label data-toggle="tooltip" data-placement="top" title="Several mailboxes to migrate"
class="radio-inline"><input type="radio" name="os0" value="Normal" checked > €59,00 </label>
<!--
<label data-toggle="tooltip" data-placement="top" title="Tons of gigabytes to copy"
class="radio-inline"><input type="radio" name="os0" value="High" > €125,00 </label>
-->
<br>
<input type="hidden" name="currency_code" value="EUR" />
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_buynowCC_LG.gif" name="submit" alt="PayPal - A safe, easy way to pay online!" />
</fieldset>
<p>
<strong>30-day money back guarantee!</strong> <br>
<em>No question nor condition to get a refund, really, just request it and you'll sure get a refund!</em>
</p>
</form>
</div>
<!-- Paypal part end -->
<form id="form" action="/cgi-bin/imapsync" method="post" autocomplete="on">
<div class="row">
<div id="account1" class="col-md-6" >
<fieldset>
<legend class="text-center h2">IMAP source mailbox</legend>
<label for="user1">Login</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"> </i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="It is usually an email address or its left part before @"
type="text" class="form-control input-lg" id="user1" name="user1" tabindex="1"
placeholder="Enter login name">
</div>
<label for="password1">Password</label>
<label class="checkbox-inline">
<input type="checkbox" id="showpassword1"> show password
</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="Passwords are not stored on the server"
type="password" class="form-control input-lg" id="password1" name="password1" tabindex="2"
placeholder="Enter password">
</div>
<label for="host1">Server</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-cloud"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="IMAP transfers are done with encryption if the servers support it."
list="servers1" type="text" class="form-control input-lg" id="host1" name="host1" tabindex="3"
placeholder="Enter imap source server name or IP address">
<datalist id="servers1">
<option value="imap.gmail.com">
<option value="outlook.office365.com">
<option value="imap.mail.yahoo.com">
</datalist>
</div>
<!--
<div class="form-group" style="padding-bottom: 15px;">
<label class="checkbox-inline">
<input type="checkbox" id="ssl1" name="ssl1" tabindex="4">-ssl1 (port 993)
</label>
</div>
-->
<div>
<br>
</div>
</fieldset>
</div>
<div id="account2" class="col-md-6" >
<fieldset>
<legend class="text-center h2">IMAP destination mailbox</legend>
<label for="user2">Login</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="It is usually an email address or its left part before @"
type="text" class="form-control input-lg" id="user2" name="user2" tabindex="6"
placeholder="Enter login name">
</div>
<label for="password2">Password</label>
<label class="checkbox-inline">
<input type="checkbox" id="showpassword2"> show password
</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="Passwords are not stored on the server"
type="password" class="form-control input-lg" id="password2" name="password2" tabindex="7"
placeholder="Enter password">
</div>
<label for="host2">Server</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-cloud"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="IMAP transfers are done with encryption if the servers support it."
list="servers2" type="text" class="form-control input-lg" id="host2" name="host2" tabindex="8"
placeholder="Enter imap destination server name or IP address">
<datalist id="servers2">
<option value="imap.gmail.com">
<option value="outlook.office365.com">
<option value="imap.mail.yahoo.com">
</datalist>
</div>
<!--
<div class="form-group" style="padding-bottom: 15px;">
<label class="checkbox-inline">
<input type="checkbox" id="ssl2" name="ssl2" tabindex="9">-ssl2 (port 993)
</label>
</div>
-->
<div>
<br>
</div>
</fieldset>
</div>
</div>
<input type="hidden" name="automap" value="on">
<input type="hidden" name="addheader" value="on">
<!-- --#>
<input type="hidden" name="simulong" value="360">
<#!-- -->
<a name="buttons"></a>
<hr>
<!-- Classical button to go to the log only -->
<noscript>
<button type="submit" class="btn btn-success btn-lg center-block btn-block">Go sync!</button>
</noscript>
<!-- Javascript buttons using xhr -->
<div class="row scripton">
<div class="col-sm-6 padd0" >
<button id="bt-sync" type="button"
class="btn btn-success btn-lg center-block btn-block"
tabindex="11"
data-toggle="tooltip" data-placement="top"
title="Launch the sync! You can abort the sync with the red Abort button nearby or by closing the tab/window."
>
Sync or resync!<br>
<span class="glyphicon glyphicon-envelope"></span>
<span class="glyphicon glyphicon-arrow-right"></span>
<span class="glyphicon glyphicon-envelope"></span>
</button>
</div>
<div class="col-sm-6 padd0" >
<button id="bt-abort" type="button"
class="btn btn-danger btn-lg center-block btn-block" tabindex="12"
data-toggle="tooltip" data-placement="top"
title="Abort the sync! You can restart the sync later, no duplicates should happen."
>
Abort!<br>
<span class="glyphicon glyphicon-scissors"></span>
</button>
</div>
</div>
</form>
<div class="row scripton" id="consoles">
<div class="col-sm-6 well">
<h2 class="text-center">Console of imapsync run</h2>
<pre id="console">
</pre>
<a id="link_to_bottom" href="#bottom">Bottom of imapsync log</a>
</div>
<div class="col-sm-6 well">
<h2 class="text-center">Console of abort</h2>
<pre id="abort">
</pre>
</div>
</div>
</div>
<h2 class="text-center scripton">Log of imapsync run</h2>
<pre id="output" class="scripton">
</pre>
<a name="bottom"></a>
<hr>
<p class="text-center">
Local bandwidth statistics <br>
<a href="/vnstat/vnstati.html">
<img alt="Local bandwidth statistics" src="/vnstat/vnstat_vs.png" >
</a>
</p>
<p class="text-center">Feel free to contact
<strong><a href="https://imapsync.lamiral.info/#AUTHOR" target="_blank">Gilles LAMIRAL</a></strong>
</p>
<div class="container-fluid" >
<div class="row">
<div class="text-center">
<a href="https://imapsync.lamiral.info/">
<img alt="Imapsync home page" src="https://imapsync.lamiral.info/X/logo_imapsync_Xn.png" height="38" width="60">
</a>
<a href="#top" title="Top of the page" class="btn btn-info " role="button">Top</a>
<!-- <a href="#buttons" class="btn btn-info scripton" role="button">Consoles</a> -->
<a href="#bottom" title="Bottom of the page" class="btn btn-info active" role="button">Bottom</a>
<br>
<small> ($Id: imapsync_form.html,v 1.69 2019/03/31 22:25:15 gilles Exp $) </small><br>
Terms and conditions for anything: <a href="https://imapsync.lamiral.info/LICENSE">No limits to do anything with this work and this license!</a><br>
</div>
</div>
</div>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"
integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f"
crossorigin="anonymous"
>
</script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"
>
</script>
<script
src="imapsync_form.js"
>
</script>
</body>
</html>

455
X/imapsync_form_extra.html Executable file
View file

@ -0,0 +1,455 @@
<!DOCTYPE html>
<!-- $Id: imapsync_form_extra.html,v 1.2 2019/06/25 16:38:24 gilles Exp gilles $ -->
<html lang="en" id="top">
<head>
<title>Imapsync online</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<link rel="stylesheet" href="imapsync_form.css">
<link rel="license" href="https://imapsync.lamiral.info/NOLIMIT">
<noscript>
<link rel="stylesheet" href="noscript.css">
</noscript>
</head>
<body>
<div class="hidden scripton">
<pre id="tests">
</pre>
<input type="checkbox" id="test_checkbox">
<input type="text" id="test_text">
<input type="radio" id="test_radio" name="test_radio" value="first" >
<input type="radio" id="test_radio" name="test_radio" value="second" >
</div>
<div class="container-fluid" >
<div class="row">
<div class="text-center">
<a href="https://imapsync.lamiral.info/">
<img alt="Imapsync home" title="Imapsync home page" src="https://imapsync.lamiral.info/X/logo_imapsync_Xn.png" height="38" width="60">
</a>
<a href="#top" title="Top of the page" class="btn btn-info " role="button">Top</a>
<!-- <a href="#payment" class="btn btn-success" data-toggle="collapse">Pricing</a> -->
<!-- <a href="#buttons" class="btn btn-info scripton" role="button">Consoles</a> -->
<a href="#bottom" title="Bottom of the page" class="btn btn-info active" role="button">Bottom</a>
</div>
</div>
<h1 class="text-center">Imapsync online</h1>
<p class="text-center"> <strong>Copy</strong>/synchronize a <strong>complete</strong> mailbox to another, without <strong>duplicates!</strong></p>
<!-- Paypal part start
new: NDGMR6TLFZ926
old: H2YTURNFT4XT4
-->
<!-- A button above the pricing form, not very beautiful...
I should give it a try anyway because nearly no one buy this service...
<div class="text-center">
<a href="#payment" class="btn btn-warning btn-lg" data-toggle="collapse">Pricing</a>
</div>
-->
<!-- the "in" makes the form not collapsed by default
Remove the in in order to mask the pricing section
<div id="payment" class="well text-center collapse in" > -->
<div id="payment" class="well text-center collapse out" >
<p class="lead">Pay by usage type</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
<input type="hidden" name="cmd" value="_s-xclick" />
<input type="hidden" name="hosted_button_id" value="H2YTURNFT4XT4" />
<input type="hidden" name="on0" value="imapsync choice" />
<fieldset>
<!--
<label data-toggle="tooltip" data-placement="top" title="Fair enough"
class="radio-inline"><input type="radio" name="os0" value="Tiny" > €1,00 </label>
-->
<label data-toggle="tooltip" data-placement="top" title="A big mailbox"
class="radio-inline"><input type="radio" name="os0" value="Small" > €6,00 </label>
<label data-toggle="tooltip" data-placement="top" title="Several mailboxes to migrate"
class="radio-inline"><input type="radio" name="os0" value="Normal" checked > €59,00 </label>
<!--
<label data-toggle="tooltip" data-placement="top" title="Tons of gigabytes to copy"
class="radio-inline"><input type="radio" name="os0" value="High" > €125,00 </label>
-->
<br>
<input type="hidden" name="currency_code" value="EUR" />
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_buynowCC_LG.gif" name="submit" alt="PayPal - A safe, easy way to pay online!" />
</fieldset>
<p>
<strong>30-day money back guarantee!</strong> <br>
<em>No question nor condition to get a refund, really, just request it and you'll sure get a refund!</em>
</p>
</form>
</div>
<!-- Paypal part end -->
<form id="form" action="/cgi-bin/imapsync" method="post" autocomplete="on">
<div id="form_row" class="row">
<div id="account1" class="col-md-5" >
<fieldset>
<legend class="text-center h2">IMAP source mailbox</legend>
<label for="user1">Login</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"> </i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="It is usually an email address or its left part before @"
type="text" class="form-control input-lg" id="user1" name="user1" tabindex="1"
placeholder="Enter login name">
</div>
<label for="password1">Password</label>
<label class="checkbox-inline out">
<input type="checkbox" id="showpassword1"> show password
</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="Passwords are not stored on the server"
type="password" class="form-control input-lg" id="password1" name="password1" tabindex="2"
placeholder="Enter password">
</div>
<label for="host1">Server</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-cloud"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="IMAP transfers are done with encryption if the servers support it."
list="servers1" type="text" class="form-control input-lg" id="host1" name="host1" tabindex="3"
placeholder="Enter imap source server name or IP address">
<datalist id="servers1">
<option value="imap.gmail.com">
<option value="outlook.office365.com">
<option value="imap.mail.yahoo.com">
</datalist>
</div>
<div class="form-group collapse extra_param">
<label class="checkbox-inline">
<input
data-toggle="tooltip" data-placement="bottom" title="Be careful with this option"
type="checkbox" id="delete1" name="delete1">Move sync. Deletes messages on source mailbox after a successful transfer.
</label>
</div>
<div class="form-group collapse extra_param" >
<label for="subfolder1">Sub-folder</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-folder-open"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="A subfolder where all the source mailbox comes from."
type="text" class="form-control input-lg" id="subfolder1" name="subfolder1"
placeholder="Enter sub-folder name">
</div>
</div>
<div>
<br>
</div>
</fieldset>
</div>
<div id="parameters" class="col-md-2" >
<div>
<br>
</div>
<div>
<label class="checkbox-inline">
<input
data-toggle="tooltip" data-placement="bottom" title="Shows what would be done without really doing it."
type="checkbox" id="dry" name="dry" >Dry run.
</label>
</div>
<div>
<label class="checkbox-inline">
<input
data-toggle="tooltip" data-placement="bottom" title="Checks credentials without syncing anything."
type="checkbox" id="justlogin" name="justlogin" >Login only.
</label>
</div>
<div>
<label class="checkbox-inline">
<input
data-toggle="tooltip" data-placement="bottom" title="Shows folders sizes and exits."
type="checkbox" id="justfoldersizes" name="justfoldersizes" >Just folders sizes.
</label>
</div>
<div>
<label class="checkbox-inline">
<input
data-toggle="tooltip" data-placement="bottom" title="Just create the folder hierarchy, messages are not synced."
type="checkbox" id="justfolders" name="justfolders" >Folders only.
</label>
</div>
<div>
<br>
</div>
<div id="button_extra_param" class="text-center scripton">
<button type="button" class="btn btn-default btn-block" data-toggle="collapse"
data-target=".extra_param">Show / Hide extra parameters</button>
</div>
<div>
<br>
</div>
<div id="button_swap" class="text-center scripton">
<button type="button" class="btn btn-default btn-block" id="swap">
Swap Source <span class="glyphicon glyphicon-transfer"></span> Destination
</button>
</div>
<div>
<br>
</div>
</div>
<div id="account2" class="col-md-5" >
<fieldset>
<legend class="text-center h2">IMAP destination mailbox</legend>
<label for="user2">Login</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="It is usually an email address or its left part before @"
type="text" class="form-control input-lg" id="user2" name="user2" tabindex="6"
placeholder="Enter login name">
</div>
<label for="password2">Password</label>
<label class="checkbox-inline out">
<input type="checkbox" id="showpassword2"> show password
</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="Passwords are not stored on the server"
type="password" class="form-control input-lg" id="password2" name="password2" tabindex="7"
placeholder="Enter password">
</div>
<label for="host2">Server</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-cloud"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="IMAP transfers are done with encryption if the servers support it."
list="servers2" type="text" class="form-control input-lg" id="host2" name="host2" tabindex="8"
placeholder="Enter imap destination server name or IP address">
<datalist id="servers2">
<option value="imap.gmail.com">
<option value="outlook.office365.com">
<option value="imap.mail.yahoo.com">
</datalist>
</div>
<!-- -->
<div class="form-group collapse extra_param">
<label class="checkbox-inline">
<input
data-toggle="tooltip" data-placement="bottom" title="Be careful with this option"
type="checkbox" id="delete2" name="delete2" tabindex="9">Strict sync. Deletes messages on destination mailbox that are not at the source mailbox.
</label>
</div>
<div class="form-group collapse extra_param" id="extra_subfolder2" >
<label for="subfolder2">Sub-folder</label>
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-folder-open"></i></span>
<input
data-toggle="tooltip" data-placement="bottom" title="A subfolder where all the source mailbox will go."
type="text" class="form-control input-lg" id="subfolder2" name="subfolder2"
placeholder="Enter sub-folder name">
</div>
</div>
<!-- -->
<div>
<br>
</div>
</fieldset>
</div>
</div>
<input type="hidden" name="automap" value="on">
<input type="hidden" name="addheader" value="on">
<!-- --#>
<input type="hidden" name="simulong" value="360">
<!-- -->
<a name="buttons"></a>
<hr>
<!-- Classical button to go to the log only -->
<noscript>
<div class="row">
<div class="col-sm-12 padd0" >
<button type="submit" class="btn btn-success btn-lg center-block btn-block">Go sync!</button>
</div>
</div>
</noscript>
<!-- Javascript buttons using xhr -->
<div class="row scripton">
<div class="col-sm-6 padd0" >
<button id="bt-sync" type="button"
class="btn btn-success btn-lg center-block btn-block"
tabindex="11"
data-toggle="tooltip" data-placement="top"
title="Launch the sync! You can abort the sync with the red Abort button nearby or by closing the tab/window."
>
Sync or resync!<br>
<span class="glyphicon glyphicon-envelope"></span>
<span class="glyphicon glyphicon-arrow-right"></span>
<span class="glyphicon glyphicon-envelope"></span>
</button>
</div>
<div class="col-sm-6 padd0" >
<button id="bt-abort" type="button"
class="btn btn-danger btn-lg center-block btn-block" tabindex="12"
data-toggle="tooltip" data-placement="top"
title="Abort the sync! You can restart the sync later, no duplicates should happen."
>
Abort!<br>
<span class="glyphicon glyphicon-scissors"></span>
</button>
</div>
</div>
</form>
<div class="row scripton" id="consoles" >
<pre id="progress"></pre>
<div class="col-sm-6 well">
<h2 class="text-center">Console of imapsync launch</h2>
<pre id="console">
</pre>
<a id="link_to_bottom" href="#bottom">Bottom of imapsync log</a>
</div>
<div class="col-sm-6 well">
<h2 class="text-center">Console of abort</h2>
<pre id="abort">
</pre>
</div>
</div>
</div>
<h2 class="text-center scripton">Log of imapsync run</h2>
<pre id="output" class="scripton">
</pre>
<a name="bottom"></a>
<hr>
<p class="text-center">
Local bandwidth statistics <br>
<a href="/vnstat/vnstati.html">
<img alt="Local bandwidth statistics" src="/vnstat/vnstat_vs.png" >
</a>
</p>
<p class="text-center">Feel free to contact
<strong><a href="https://imapsync.lamiral.info/#AUTHOR" target="_blank">Gilles LAMIRAL</a></strong>
</p>
<div class="container-fluid" >
<div class="row">
<div class="text-center">
<a href="https://imapsync.lamiral.info/">
<img alt="Imapsync home page" src="https://imapsync.lamiral.info/X/logo_imapsync_Xn.png" height="38" width="60">
</a>
<a href="#top" title="Top of the page" class="btn btn-info " role="button">Top</a>
<!-- <a href="#buttons" class="btn btn-info scripton" role="button">Consoles</a> -->
<a href="#bottom" title="Bottom of the page" class="btn btn-info active" role="button">Bottom</a>
<br>
<small> ($Id: imapsync_form_extra.html,v 1.2 2019/06/25 16:38:24 gilles Exp gilles $) </small><br>
Terms and conditions for anything: <a href="https://imapsync.lamiral.info/LICENSE">No limits to do anything with this work and this license!</a><br>
</div>
</div>
</div>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"
integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f"
crossorigin="anonymous"
>
</script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"
>
</script>
<script
src="imapsync_form_new.js"
>
</script>
</body>
</html>

453
X/imapsync_form_new.js Executable file
View file

@ -0,0 +1,453 @@
// $Id: imapsync_form_new.js,v 1.4 2019/06/25 16:34:19 gilles Exp gilles $
/*jslint browser: true*/ /*global $*/
$(document).ready(
function ()
{
"use strict";
// Bootstrap popover and tooltip
$("[data-toggle='tooltip']").tooltip();
var readyStateStr = {
"0": "Request not initialized",
"1": "Server connection established",
"2": "Response headers received",
"3": "Processing request",
"4": "Finished and response is ready"
};
function is( expected, given, comment )
{
var message = ": ["
+ expected
+ "] === ["
+ given
+ "] "
+ comment
+ "\n" ;
if ( expected === given )
{
message = "ok " + message ;
}
else
{
message = "Nok" + message ;
}
$("#tests").append( message ) ;
}
function last_eta( string )
{
// return the last occurrence of the substring "ETA: ...\n"
// or ""
var eta ;
var last_found ;
if ( undefined === string )
{
return "" ;
}
var eta_re = /ETA:.*\n/g ;
eta = string.match( eta_re ) ;
if ( eta )
{
last_found = eta[eta.length -1 ] ;
return last_found ;
}
else
{
return "" ;
}
}
function tests_last_eta()
{
is( "", last_eta( ), "last_eta: no args => empty string" ) ;
is( "", last_eta( "" ), "last_eta: empty => empty string" ) ;
is( "", last_eta( "ETA" ), "last_eta: ETA => empty string" ) ;
is( "", last_eta( "ETA: but no CR" ),
"last_eta: ETA: but no CR => empty string" ) ;
is(
"ETA: with CR\n",
last_eta( "Blabla ETA: with CR\n" ),
"last_eta: ETA: with CR => ETA: with CR"
) ;
is(
"ETA: 2 with CR\n",
last_eta( "Blabla ETA: 1 with CR\nBlabla ETA: 2 with CR\n" ),
"last_eta: several ETA: with CR => ETA: 2 with CR"
) ;
}
function refreshLog(xhr)
{
var slice_length ;
$("#output").text(xhr.responseText) ;
if (xhr.readyState === 4) {
slice_length = -2400 ;
}
else
{
slice_length = -240 ;
}
$("#progress").text( last_eta( xhr.responseText.slice( slice_length ) ) ) ;
}
function handleRun(xhr, timerRefreshLog)
{
$("#console").text("Status: " + xhr.status + " " + xhr.statusText + "\n" + "State: " + readyStateStr[xhr.readyState] + "\n") ;
if (xhr.readyState === 4) {
// var headers = xhr.getAllResponseHeaders();
// $("#console").append(headers);
// $("#console").append("See the completed log\n");
$("#link_to_bottom").show();
clearInterval(timerRefreshLog);
refreshLog(xhr); // a last time
$("#bt-sync").prop("disabled", false); // back to enable state for next run
}
}
function imapsync()
{
var querystring = $("#form").serialize();
$("#abort").text("\n\n"); // clean abort console
$("#output").text("Here comes the log!\n\n");
if ( "imap.gmail.com" === $("#host1").val() )
{
querystring = querystring + "&gmail1=on";
}
if ( "imap.gmail.com" === $("#host2").val() )
{
querystring = querystring + "&gmail2=on";
}
var xhr;
xhr = new XMLHttpRequest();
var timerRefreshLog = setInterval(
function ()
{
refreshLog(xhr);
}, 5000 ) ;
xhr.onreadystatechange = function ()
{
handleRun(xhr, timerRefreshLog);
};
xhr.open("POST", "/cgi-bin/imapsync", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring);
}
function handleAbort(xhr)
{
$("#abort").text("Status: " + xhr.status + " " + xhr.statusText + "\n" + "State: " + readyStateStr[xhr.readyState] + "\n\n");
if (xhr.readyState === 4)
{
$("#abort").append(xhr.responseText);
$("#bt-sync").prop("disabled", false);
$("#bt-abort").prop("disabled", false); // back for next abort
}
}
function abort()
{
var querystring = $("#form").serialize() + "&abort=on";
var xhr;
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function ()
{
handleAbort(xhr);
};
xhr.open("POST", "/cgi-bin/imapsync", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring);
}
function store( id )
{
var stored ;
$( "#tests" ).append( "Eco: " + id + " type is " + $( id ).attr( "type" ) + "\n" ) ;
if ( "text" === $( id ).attr( "type" ) || "password" === $( id ).attr( "type" ) )
{
localStorage.setItem( id, $(id).val() ) ;
stored = $(id).val() ;
}
else if ( "checkbox" === $( id ).attr( "type" ) )
{
$( "#tests" ).append( "Eco: " + id + " checked is " + $( id )[0].checked + "\n" ) ;
localStorage.setItem( id, $( id )[0].checked ) ;
stored = $( id )[0].checked ;
}
return stored ;
}
function retrieve( id )
{
var retrieved ;
$( "#tests" ).append( "Eco: " + id + " type is " + $( id ).attr( "type" ) + " length is " + $( id ).length + "\n" ) ;
if ( "text" === $( id ).attr( "type" ) || "password" === $( id ).attr( "type" ) )
{
$( id ).val( localStorage.getItem( id ) ) ;
retrieved = $( id ).val() ;
}
else if ( "checkbox" === $( id ).attr( "type" ) )
{
$( "#tests" ).append( "Eco: " + id + " getItem is " + localStorage.getItem( id ) + "\n" ) ;
$( id )[0].checked = JSON.parse( localStorage.getItem( id ) ) ;
retrieved = $( id )[0].checked ;
}
return retrieved ;
}
function tests_store_retrieve()
{
if ( $("#tests").length !== 0 )
{
is( 1, 1, "one equals one" ) ;
// isnot( 0, 1, "zero differs one" ) ;
// no exist
is( undefined, store( "#test_noexists" ), "store: #test_noexists" ) ;
is( undefined, retrieve( "#test_noexists" ), "retrieve: #test_noexists" ) ;
is( undefined, retrieve( "#test_noexists2" ), "retrieve: #test_noexists2" ) ;
// input text
$("#test_text" ).val( "foo" ) ;
is( "foo", $("#test_text" ).val( ), "#test_text val = foo" ) ;
is( "foo", store( "#test_text" ), "store: #test_text" ) ;
$("#test_text" ).val( "bar" ) ;
is( "bar", $("#test_text" ).val( ), "#test_text val = bar" ) ;
is( "foo", retrieve( "#test_text" ), "retrieve: #test_text = foo" ) ;
is( "foo", $("#test_text" ).val( ), "#test_text val = foo" ) ;
// input check button
$( "#test_checkbox" ).prop( "checked", true );
is( true, store( "#test_checkbox" ), "store: #test_checkbox checked" ) ;
$( "#test_checkbox" ).prop( "checked", false );
is( true, retrieve( "#test_checkbox" ), "retrieve: #test_checkbox = true" ) ;
$( "#test_checkbox" ).prop( "checked", false );
is( false, store( "#test_checkbox" ), "store: #test_checkbox not checked" ) ;
$( "#test_checkbox" ).prop( "checked", true );
is( false, retrieve( "#test_checkbox" ), "retrieve: #test_checkbox = false" ) ;
}
}
function store_form()
{
if ( Storage !== "undefined")
{
// Code for localStorage.
store("#user1") ;
store("#password1") ;
store("#host1") ;
store("#subfolder1") ;
store("#showpassword1") ;
store("#user2") ;
store("#password2") ;
store("#host2") ;
store("#subfolder2") ;
store("#showpassword2") ;
store("#dry") ;
store("#justlogin") ;
store("#justfolders") ;
store("#justfoldersizes") ;
localStorage.account1_background_color = $("#account1").css("background-color") ;
localStorage.account2_background_color = $("#account2").css("background-color") ;
}
}
function show_extra_if_needed()
{
if ( $("#subfolder1").length && $("#subfolder1").val().length > 0 )
{
$(".extra_param").show() ;
}
if ( $("#subfolder2").length && $("#subfolder2").val().length > 0 )
{
$(".extra_param").show() ;
}
}
function retrieve_form()
{
if ( Storage !== "undefined" )
{
// Code for localStorage.
retrieve( "#user1" ) ;
retrieve( "#password1" ) ;
// retrieve("#showpassword1") ;
retrieve( "#host1" ) ;
retrieve( "#subfolder1" ) ;
retrieve( "#user2" ) ;
retrieve( "#password2" ) ;
// retrieve("#showpassword2") ;
retrieve( "#host2" ) ;
retrieve( "#subfolder2" ) ;
retrieve( "#dry" ) ;
retrieve( "#justlogin" ) ;
retrieve( "#justfolders" ) ;
retrieve( "#justfoldersizes" ) ;
// In case
// localStorage.removeItem( "account1_background_color" ) ;
// localStorage.removeItem( "account2_background_color" ) ;
if ( localStorage.account1_background_color )
{
$("#account1").css("background-color", localStorage.account1_background_color ) ;
}
if ( localStorage.account2_background_color )
{
$("#account2").css("background-color", localStorage.account2_background_color ) ;
}
// Show the extra parameters if they are not empty because it would be dangerous
// to retrieve them without knowing
show_extra_if_needed() ;
}
}
function showpassword( id, button )
{
var x = document.getElementById( id );
if ( button.checked )
{
x.type = "text";
} else {
x.type = "password";
}
}
function init()
{
// in case of a manual refresh, start with
$("#bt-sync").prop("disabled", false);
$("#bt-abort").prop("disabled", false);
$("#link_to_bottom").hide();
retrieve_form();
$("#showpassword1").click(
function ()
{
// does not change jslint report...
/*jshint validthis: true */
var button = this ;
showpassword( "password1", button ) ;
}
);
$("#showpassword2").click(
function ()
{
var button = this ;
showpassword( "password2", button ) ;
}
);
$("#bt-sync").click(
function ()
{
$("#bt-sync").prop("disabled", true);
$("#bt-abort").prop("disabled", false);
$("#link_to_bottom").hide();
store_form();
imapsync();
}
);
$("#bt-abort").click(
function ()
{
$("#bt-sync").prop("disabled", true);
$("#bt-abort").prop("disabled", true);
abort();
}
);
$.fn.swapWith = function(to)
{
var temp = $(to).val();
$(to).val($(this).val());
$(this).val(temp);
};
$("#swap").click(
function()
{
// swaping colors can't use swapWith()
var temp1 = $("#account1").css("background-color") ;
var temp2 = $("#account2").css("background-color") ;
$("#account1").css("background-color", temp2 );
$("#account2").css("background-color", temp1 );
$("#user1").swapWith("#user2");
$("#password1").swapWith("#password2");
$("#host1").swapWith("#host2");
$("#subfolder1").swapWith("#subfolder2");
var temp = $("#showpassword1")[0].checked ;
$("#showpassword1")[0].checked = $("#showpassword2")[0].checked ;
$("#showpassword2")[0].checked = temp ;
showpassword( "password1", $("#showpassword1")[0] ) ;
showpassword( "password2", $("#showpassword2")[0] ) ;
}
);
}
function progress_bar_update( string )
{
//
return ;
}
function tests()
{
if ( $("#tests").length !== 0 )
{
tests_store_retrieve() ;
tests_last_eta() ;
}
}
init( ) ;
tests( ) ;
}
);

13
X/noscript.css Executable file
View file

@ -0,0 +1,13 @@
.scripton {
display:none;
}
.collapse {
display: block;
}
.out {
display:none;
}

View file

@ -12,6 +12,16 @@
<h1>Imapsync online</h1>
<input
data-toggle="tooltip" data-placement="top" title="It is usually an email address or its left part before @"
type="text" class="form-control input-lg" id="user1" name="user1" tabindex="1"
placeholder="Enter source login name">
<pre id="user2">
</pre>
<button type="button"
onclick="imapsync('?lalala=zzz&host1=sss&user1=uuu&password1=uuu&host2=ttt&user2=uuu&password2=uuu&simulong=22&debugenv=on', handleRun)"
>Run imapsync
@ -45,6 +55,9 @@
<script>
$("#user2").text("toto");
$("#user1").val("RRRR");
var readyStateStr = {
0: "Request not initialized",
1: "Server connection established",

View file

@ -1,6 +1,7 @@
^Here is imapsync
^Load end is
^Load is
^Server is on heavy load
^Temp directory is
^Current directory is
^REMOTE_ADDR
@ -37,5 +38,6 @@
^Exiting with return value
^Memory consumption
^Memory consumption at the end
failure: Error login
^Read:.*\* *ID
failure: Error login
failure: can not open imap connection on