From: fextracker Date: Tue, 5 Jan 2016 03:00:03 +0000 (+0100) Subject: Original release 20160104 X-Git-Tag: 20160104 X-Git-Url: https://git.treefish.org/fex.git/commitdiff_plain/20160104?hp=e5c93609849bda051fff54b5d5265af5608c6c69 Original release 20160104 2015-12-29: fexsend: added search pattern argument to option -l 2015-12-25: fup: added +/- download flag in LIST command output 2015-12-18: fup: allow AUTODELETE and KEEP parameter for anonymous user and 2015-12-18: sender=recipient 2015-12-01: hint for fexget and fexit in notification email 2015-12-01: fixed bug notification email ignores (sometimes) locale 2015-11-27: fixed bug first line in encrypted notification emails gets lost 2015-11-21: fixed bad UTF8 encoding for french spanish czech galician 2015-11-10: fexget: fixed bug timeout for big files on slow storage 2015-10-14: install: fixed bug missing fex group 2015-10-09: fexsend: better support for reverse proxy (closing connection) 2015-10-06: fexsend: abort if file has been modified while uploading 2015-10-04: fup: when forwarding a file, keep time is calculated for today, 2015-10-04: not for upload day 2015-09-29: fexget: fixed bug no https download 2015-09-26: fex_cleanup: fixed bug send no locale reactivation.txt 2015-09-21: fexget: fixed bug resume download on aborted storage test file 2015-09-21: leads to corrupted file 2015-09-17: changed LIST output formating (more consistent) 2015-09-17: fexget: fixed bug cannot forward a file that was received from myself 2015-09-16: fexsend: more robust fileID (md5sum of metadata) 2015-09-14: fup: show autodelete=no if sender == recipient 2015-09-11: moved comment to top in notification email 2015-09-08: fup,fuc: fixed bug link to F*EX clients tools.html broken (loop) 2015-09-06: fexsend: added ditto-zip for MacOSX 2015-09-02: fexsend: added MacOSX support 2015-09-01: fac: added option -Rl for local users 2015-09-01: fup: added local users restriction option --- diff --git a/bin/fac b/bin/fac index 1458ef8..c2d59f4 100755 --- a/bin/fac +++ b/bin/fac @@ -57,10 +57,10 @@ die "$0: \$admin not configured in $FEXLIB/fex.ph\n" unless $admin; $EDITOR = $ENV{EDITOR} || $ENV{VISUAL} || (-x '/usr/bin/editor' ? '/usr/bin/editor' : 'vi'); -$opt_c = $opt_v = $opt_l = $opt_L = $opt_h = $opt_w = $opt_u = $opt_R = 0; +$opt_c = $opt_v = $opt_l = $opt_L = $opt_h = $opt_w = $opt_u = 0; $opt_M = $opt_E = 0; $opt_r = $opt_d = $opt_q = $opt_a = $opt_n = $opt_k = $opt_m = ''; -$opt_y = $opt_S = $opt_C = $opt_D = $opt_A = $opt_V = $opt_P = ''; +$opt_y = $opt_S = $opt_C = $opt_D = $opt_A = $opt_V = $opt_P = $opt_R = ''; ${'opt_/'} = ''; @__ = @ARGV; @@ -80,7 +80,7 @@ if (abs_path($spooldir) ne abs_path("$FEXHOME/spool")) { warn "WARNING: \$spooldir differs from $FEXHOME/spool !\n"; } -getopts('hcvlLwuMRE/q:r:d:a:n:k:m:y:S:C:A:V:D:P:') or usage(2); +getopts('hcvlLwuME/q:r:d:a:n:k:m:y:S:C:A:V:D:P:R:') or usage(2); usage(0) if $opt_h; examples() if $opt_E; @@ -260,17 +260,32 @@ if ($opt_d) { # set user restriction file if ($opt_R) { - $user = shift or die "usage: $0 -R user\n"; - $user .= '@'.$mdomain if $mdomain and $user !~ /@/; - die "$0: no user $user\n" unless -d "$spooldir/$user"; - unless (@local_rdomains) { - die "$0: no \@local_rdomains in server config\n"; - } - my $rf = "$spooldir/$user/\@ALLOWED_RECIPIENTS"; - open $rf,'>',$rf or die "$0: cannot open $rf - $!"; - print {$rf} "\@LOCAL_RDOMAINS\n"; - close $rf; - print "$user restricted\n"; + if ($opt_R eq 'i') { + $user = shift or die "usage: $0 -Ri user\n"; + $user .= '@'.$mdomain if $mdomain and $user !~ /@/; + die "$0: no user $user\n" unless -d "$spooldir/$user"; + unless (@local_rdomains) { + die "$0: no \@local_rdomains in server config\n"; + } + my $rf = "$spooldir/$user/\@ALLOWED_RECIPIENTS"; + open $rf,'>',$rf or die "$0: cannot open $rf - $!"; + print {$rf} "\@LOCAL_RDOMAINS\n"; + close $rf; + print "$user restricted to internal recipients\n"; + exit; + } elsif ($opt_R eq 'l') { + $user = shift or die "usage: $0 -Rl user\n"; + $user .= '@'.$mdomain if $mdomain and $user !~ /@/; + die "$0: no user $user\n" unless -d "$spooldir/$user"; + my $rf = "$spooldir/$user/\@ALLOWED_RECIPIENTS"; + open $rf,'>',$rf or die "$0: cannot open $rf - $!"; + print {$rf} "\@LOCAL_USERS\n"; + close $rf; + print "$user restricted to local recipients\n"; + exit; + } else { + usage(2); + } exit; } @@ -862,7 +877,8 @@ $0 -u user auth-ID # create new user or set new auth-ID $0 -/ admin auth-ID # set new admin and auth-ID $0 -q user s:quota # set new disk quota (MB) for sender user $0 -q user r:quota # set new disk quota (MB) for recipient user -$0 -R user # restrict user: only internal recipients allowed +$0 -Ri user # restrict user: only internal domain recipients allowed +$0 -Rl user # restrict user: only local users as recipients allowed $0 -rr user # edit user recipients restriction $0 -ru user # edit user upload restriction $0 -rd user # edit user download restriction diff --git a/bin/fbm b/bin/fbm index f1d71d0..96d2a22 100755 --- a/bin/fbm +++ b/bin/fbm @@ -20,7 +20,7 @@ use constant M => 2**20; our ($SH,$windoof,$sigpipe,$useragent); our ($FEXSERVER); -our $version = 20150826; +our $version = 20160104; # server defaults my $server = 'fex.rus.uni-stuttgart.de'; diff --git a/bin/fex_cleanup b/bin/fex_cleanup index 1adec4e..2dabc00 100755 --- a/bin/fex_cleanup +++ b/bin/fex_cleanup @@ -71,60 +71,60 @@ chdir $spooldir or die "$0: $spooldir - $!\n"; # clean up regular spool opendir $spooldir,'.' or die "$0: $spooldir - $!\n"; while ($to = readdir $spooldir) { + next if $to =~ /^\./; next if $to !~ /@/ or $_ = readlink($to) and not /\//; + next unless -d $to; if (@demo and -f "$to/.demo" and time > lmtime("$to/.demo")+$demo[1]*DS) { logdel($to,"demo user $to deleted"); next; } - if (-d $to and $to !~ /^\./) { - unless (opendir TO,$to) { - warn "$0: $spooldir/$to - $!\n"; - next; - } - while ($from = readdir TO) { - next if $from !~ /@/; - if ($from eq '@GROUP') { - foreach $group (glob "$to/$from/*") { - if (readlink $group and not -f $group) { - logdel($group,"$group deleted (master has gone)"); - } + unless (opendir TO,$to) { + warn "$0: $spooldir/$to - $!\n"; + next; + } + while ($from = readdir TO) { + next if $from !~ /@/; + if ($from eq '@GROUP') { + foreach $group (glob "$to/$from/*") { + if (readlink $group and not -f $group) { + logdel($group,"$group deleted (master has gone)"); } - } else { - if (-d "$to/$from" and $from !~ /^\./) { - unless (opendir FROM,"$to/$from") { - warn "$0: $spooldir/$to/$from - $!\n"; - next; - } - while ($file = readdir FROM) { - next if $file eq '.' or $file eq '..'; - if (-d "$to/$from/$file" and $file !~ /^\./) { - cleanup($to,$from,$file); - rmdir "$to/$from/$file" unless $opt_d; - } + } + } else { + if (-d "$to/$from" and $from !~ /^\./) { + unless (opendir FROM,"$to/$from") { + warn "$0: $spooldir/$to/$from - $!\n"; + next; + } + while ($file = readdir FROM) { + next if $file eq '.' or $file eq '..'; + if (-d "$to/$from/$file" and $file !~ /^\./) { + cleanup($to,$from,$file); + rmdir "$to/$from/$file" unless $opt_d; } - closedir FROM; - rmdir "$to/$from" unless $opt_d; } + closedir FROM; + rmdir "$to/$from" unless $opt_d; } } - closedir TO; - unless (-f "$to/\@PERSISTENT" or $to eq $admin) { - @glob = glob "$to/*/* $to/\@MAINUSER/* $to/\@GROUP/*"; - unless (@glob or -f "$to/\@") { - logdel($to,"$to deleted"); - } - $user = $to; - if ($login_check and -l "$user/.login") { - my $lc = &$login_check(readlink("$user/.login")); - if ($lc) { - if (-f "$user/\@~" and not "$user/@") { - rename "$user/\@~","$user/@" unless $opt_d; - logv("$user reanimated (login_check)"); - } - } else { - rename "$user/@","$user/\@~" unless $opt_d; - logv("$user deactivated (login_check)"); + } + closedir TO; + unless (-f "$to/\@PERSISTENT" or $to eq $admin) { + @glob = glob "$to/*/* $to/\@MAINUSER/* $to/\@GROUP/*"; + unless (@glob or -f "$to/\@") { + logdel($to,"$to deleted"); + } + $user = $to; + if ($login_check and -l "$user/.login") { + my $lc = &$login_check(readlink("$user/.login")); + if ($lc) { + if (-f "$user/\@~" and not "$user/@") { + rename "$user/\@~","$user/@" unless $opt_d; + logv("$user reanimated (login_check)"); } + } else { + rename "$user/@","$user/\@~" unless $opt_d; + logv("$user deactivated (login_check)"); } } } @@ -350,7 +350,7 @@ if ($account_expire and $account_expire =~ /^(\d+)/) { if (time > lmtime($user)+$expire*DS) { # print "$spooldir/$user\n"; - my $locale = readlink "$user/\@LOCALE"; + local $locale = readlink "$user/\@LOCALE"; $locale = 'english' unless $locale and $reactivation{$locale}; &{$reactivation{$locale}}($expire,$user); sleep 1; diff --git a/bin/fexget b/bin/fexget index 8e00119..c375cea 100755 --- a/bin/fexget +++ b/bin/fexget @@ -30,9 +30,10 @@ our $SH; our ($fexhome,$idf,$tmpdir,$windoof,$useragent); our ($xv,%autoview); our $bs = 2**16; # blocksize for tcp-reading and writing file -our $version = 20150826; +our $version = 20160104; our $CTYPE = 'ISO-8859-1'; our $fexsend = $ENV{FEXSEND} || 'fexsend'; +our $DEBUG = $ENV{DEBUG}; my %SSL = (SSL_version => 'TLSv1'); my $sigpipe; @@ -57,6 +58,14 @@ if ($Config{osname} =~ /^mswin/i) { $SSL{SSL_verify_mode} = 0; chdir $ENV{USERPROFILE}.'\Desktop'; # open XX,'>XXXXXX';close XX; +} elsif ($Config{osname} =~ /^darwin/i or $ENV{MACOS}) { + $0 =~ s:(.*)/:: and $ENV{PATH} .= ":$1"; + $fexhome = $ENV{FEXHOME} || $ENV{HOME}.'/.fex'; + $tmpdir = $ENV{FEXTMP} || $ENV{TMPDIR} || "$fexhome/tmp"; + $idf = "$fexhome/id"; + $_ = `sw_vers -productVersion 2>/dev/null`||''; + chomp; + $useragent = "fexget-$version (MacOS $_)"; } else { $0 =~ s:(.*)/:: and $ENV{PATH} .= ":$1"; $fexhome = $ENV{FEXHOME} || $ENV{HOME}.'/.fex'; @@ -233,7 +242,7 @@ if ($opt_a) { } } -my ($file,%files,$download,$server,$port,$fop); +my ($file,%files,$download,$server,$port,$fop,$https); if ($opt_f) { unless ($ENV{FEXID} or -f $ENV{HOME}.'/.fex/id') { @@ -271,6 +280,7 @@ URL: foreach my $url (@ARGV) { } if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/.*fop/\S+)}) { + $https = $1; $server = $2; $port = $4 || ($1?443:80); $fop = $5; @@ -358,6 +368,7 @@ URL: foreach my $url (@ARGV) { if ($ENV{DISPLAY} and $download =~ /\.(gif|jpg|png|tiff?)$/i) { # see also mimeopen and xdg-mime + # http://unix.stackexchange.com/questions/144047/how-does-xdg-open-do-its-work if (my $xv = $xv || pathsearch('xv') || pathsearch('xdg-open')) { printf "run \"%s %s\" [Yn] ? ",basename($xv),basename($download); $_ = ||''; @@ -367,10 +378,10 @@ URL: foreach my $url (@ARGV) { } if ($download =~ /$atype/) { - if ($download =~ /\.(tgz|tar.gz)$/) { extract('tar tvzf','tar xvzf') } - elsif ($download =~ /\.tar$/) { extract('tar tvf','tar xvf') } - elsif ($download =~ /\.zip$/i) { extract('unzip -l','unzip') } - elsif ($download =~ /\.7z$/i) { extract('7z l','7z x') } + if ($download =~ /\.(tgz|tar.gz)$/) { extract('tar tvzf','tar xvzf') } + elsif ($download =~ /\.tar$/) { extract('tar tvf','tar xvf') } + elsif ($download =~ /\.zip$/i) { extract('unzip -l','unzip') } + elsif ($download =~ /\.7z$/i) { extract('7z l','7z x') } else { die "$0: unknown archive \"$download\"\n" } if ($? == 0) { unlink $download; @@ -388,7 +399,7 @@ sub extract { my $l = shift; my $x = shift; my $d = $download; - my $xd = '.'; + my $xd = ''; local $_; if (-t and not $windoof) { @@ -396,9 +407,10 @@ sub extract { system(split(' ',$l),$download); $d =~ s:.*/:./:; $d =~ s/\.[^.]+$//; + $d =~ s:/*$:/:; for (;;) { $xd = inquire("extract to directory (Ctrl-C to keep archive): ",$d); - last if $xd =~ s:^(\./*)*!?$:./:; + last if $xd =~ s:^(\./*)*!?$::; if ($xd eq '-') { print "keeping $download\n"; exit; @@ -420,8 +432,9 @@ sub extract { last; } } - print "extracting to $xd :\n"; + print "extracting to $xd :\n" if $xd; system(split(' ',$x),$download); + print "extracted to $xd\n" if $xd; } sub del { @@ -453,7 +466,7 @@ sub del { sub forward { my $url = shift; my ($server,$port); - my ($uri,$dkey,$list,$cmd,$n); + my ($uri,$dkey,$list,$cmd,$n,$copy); my @r; if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/fop/.+)}) { @@ -474,7 +487,13 @@ sub forward { die "$0: no reply from fex server $server\n" unless $_; warn "<-- $_" if $opt_v; - unless (/^HTTP.*200/) { + if (/^HTTP.*already exists/) { + if ($uri =~ m:/fop/(\w+)/:) { + $dkey = $1; + } + } elsif (/^HTTP.*200/) { + # ok! + } else { s/^HTTP.... \d+ //; die "$0: $_"; } @@ -486,8 +505,7 @@ sub forward { warn "<-- $_" if $opt_v; } - $cmd = 'fexsend -l >/dev/null 2>&1'; - print "$cmd\n" if $opt_v; + print "fexsend -l\n" if $opt_v; system 'fexsend -l >/dev/null 2>&1'; $list = $ENV{HOME}.'/.fex/tmp/fexlist'; open $list,$list or die "$0: cannot open $list - $!\n"; @@ -563,14 +581,18 @@ sub download { $pipe = $download = $opt_s; } elsif (-p $opt_s or -c $opt_s) { $download = $opt_s; + $nocheck = 'pipe or character device'; } else { $download = $file.'.tmp'; $seek = -s $download || 0; } } else { # ask server for real file name - serverconnect($server, $port); - sendheader("$server:$port","HEAD $proxy_prefix$fop HTTP/1.1","User-Agent: $useragent"); + sendheader( + "$server:$port", + "HEAD $proxy_prefix$fop HTTP/1.1", + "User-Agent: $useragent" + ); my $reply = $_ = <$SH>; unless (defined $_ and /\w/) { die "$0: no response from server\n"; @@ -644,28 +666,34 @@ sub download { } } if ($checkstorage and not $nocheck) { - $t0 = time; + my $t0 = my $t1 = my $t2 = time; my $n = 0; + my $buf = '.' x M; + my $storagetest = $file.'.test'; + my $error = "$0: cannot write \"$storagetest\""; + open $storagetest,'>',$storagetest or die "$error - $!\n"; print STDERR "checking storage...\r"; - $buf = '.' x M; - while (-s $download < $checkstorage) { - syswrite X,$buf or do { - unlink $download; - die "\n$0: cannot write $download - $!\n"; + while (-s $storagetest < $checkstorage) { + syswrite $storagetest,$buf or do { + unlink $storagetest; + die "\n$error - $!\n"; }; $n++; - print STDERR "checking storage... ".$n." MB\r"; + $t2 = int(time); + if ($t2 > $t1) { + print STDERR "checking storage... ".$n." MB\r"; + $t1 = $t2; + } } - close X or do { - unlink $download; - die "\n$0: cannot write $download - $!\n"; + close $storagetest or do { + unlink $storagetest; + die "\n$error - $!\n"; }; print STDERR "checking storage... ".$n." MB ok!\n"; - unlink $download; - if (time-$t0 < 25) { - open X,'>',$download or die "$0: cannot write to \"$download\" - $!\n"; - } else { + unlink $storagetest; + if (time-$t0 > 25) { # retry after timeout + serverconnect($server,$port); return(download($server,$port,$fop,'nocheck')) } } @@ -806,13 +834,6 @@ sub pathsearch { } -sub quote { - local $_ = shift; - s/([^\w¡-ÿ_%\/=~:.,-])/\\$1/g; - return $_; -} - - { my $tty; @@ -830,10 +851,11 @@ sub quote { if (defined(&TIOCSTI) and $tty and open($tty,'>',$tty)) { print $prompt; + # push default answer into keyboard buffer foreach my $a (split("",$default)) { ioctl($tty,&TIOCSTI,$a) } chomp($_ = ||''); } else { - $prompt =~ s/([\?:=]\s*)/ [$default]$1/ or $prompt .= " [$default]"; + $prompt =~ s/([\?:=]\s*)/ [$default]$1/ or $prompt .= " [$default] "; print $prompt; chomp($_ = ||''); $_ = $default unless length; @@ -915,15 +937,9 @@ sub serverconnect { my $connect = "CONNECT $server:$port HTTP/1.1"; local $_; - if ($opt_v and $port == 443 and %SSL) { - foreach my $v (keys %SSL) { - printf "%s => %s\n",$v,$SSL{$v}; - } - } - if ($proxy) { tcpconnect(split(':',$proxy)); - if ($port == 443) { + if ($https) { printf "--> %s\n",$connect if $opt_v; nvtsend($connect,""); $_ = <$SH>; @@ -932,14 +948,13 @@ sub serverconnect { unless (/^HTTP.1.. 200/) { die "$0: proxy error : $_"; } - eval "use IO::Socket::SSL"; - die "$0: cannot load IO::Socket::SSL\n" if $@; + &enable_ssl; $SH = IO::Socket::SSL->start_SSL($SH,%SSL); } } else { tcpconnect($server,$port); } -# if ($port == 443 and $opt_v) { +# if ($https and $opt_v) { # printf "%s\n",$SH->get_cipher(); # } } @@ -954,10 +969,9 @@ sub tcpconnect { undef $SH; } - if ($port == 443) { + if ($https) { # eval "use IO::Socket::SSL qw(debug3)"; - eval "use IO::Socket::SSL"; - die "$0: cannot load IO::Socket::SSL\n" if $@; + &enable_ssl; $SH = IO::Socket::SSL->new( PeerAddr => $server, PeerPort => $port, @@ -974,6 +988,7 @@ sub tcpconnect { if ($SH) { autoflush $SH 1; + binmode $SH; } else { die "$0: cannot connect $server:$port - $@\n"; } @@ -982,6 +997,18 @@ sub tcpconnect { } +sub enable_ssl { + eval "use IO::Socket::SSL"; + die "$0: cannot load IO::Socket::SSL\n" if $@; + eval '$SSL{SSL_verify_mode} = 0 if Net::SSLeay::SSLeay() <= 9470143'; + if ($opt_v) { + foreach my $v (keys %SSL) { + printf "%s => %s\n",$v,$SSL{$v}; + } + } +} + + sub sendheader { my $sp = shift; my @head = @_; @@ -1018,6 +1045,18 @@ sub nvtsend { } +sub quote { + local $_ = shift; + s/([^\w\@\/%^,.=+_:+-])/\\$1/g; + return $_; +} + + +sub debug { + print "## DEBUG: @_\n" if $DEBUG; +} + + # from MIME::Base64::Perl sub encode_b64 { my $res = ""; diff --git a/bin/fexsend b/bin/fexsend index e746b66..7e498dc 100755 --- a/bin/fexsend +++ b/bin/fexsend @@ -31,15 +31,15 @@ eval 'use Net::INET6Glue::INET_is_INET6'; $| = 1; -our ($SH,$fexhome,$idf,$tmpdir,$windoof,$useragent,$editor,$nomail); +our ($SH,$fexhome,$idf,$tmpdir,$windoof,$macos,$useragent,$editor,$nomail); our ($anonymous,$public); our ($tpid,$frecipient); our ($FEXID,$FEXXX,$HOME); our (%alias); our $chunksize = 0; -our $version = 20150826; +our $version = 20160104; our $_0 = $0; -our $DEBUG; +our $DEBUG = $ENV{DEBUG}; my %SSL = (SSL_version => 'TLSv1'); my $sigpipe; @@ -54,18 +54,31 @@ if ($Config{osname} =~ /^mswin/i) { $useragent = sprintf("fexsend-$version (%s %s)", $Config{osname},$Config{archname}); $SSL{SSL_verify_mode} = 0; +} elsif ($Config{osname} =~ /^darwin/i or $ENV{MACOS}) { + $macos = $Config{osname}; + # http://stackoverflow.com/questions/989349/running-a-command-in-a-new-mac-os-x-terminal-window + $HOME = (getpwuid($<))[7]||$ENV{HOME}; + $fexhome = $HOME.'/.fex'; + $tmpdir = $ENV{FEXTMP} || $ENV{TMPDIR} || "$fexhome/tmp"; + $tmpdir =~ s:/$::; + $idf = "$fexhome/id"; + chmod 0600,$idf; + $editor = $ENV{EDITOR} || 'open -W -n -e'; + $_ = `sw_vers -productVersion 2>/dev/null`||''; + chomp; + $useragent = "fexsend-$version (MacOS $_)"; } else { $0 =~ s:.*/::; $HOME = (getpwuid($<))[7]||$ENV{HOME}; $fexhome = $HOME.'/.fex'; $tmpdir = $ENV{FEXTMP} || "$fexhome/tmp"; $idf = "$fexhome/id"; + chmod 0600,$idf; $editor = $ENV{EDITOR} || 'vi'; $_ = `(lsb_release -d||uname -a)2>/dev/null`||''; chomp; s/^Description:\s+//; $useragent = "fexsend-$version ($_)"; - chmod 0600,$idf; } if (-f ($_ = '/etc/fex/config.pl')) { @@ -88,7 +101,7 @@ my $features = ''; my $timeout = 30; # server timeout my $fexlist = "$tmpdir/fexlist"; my ($usage,$hints); -my $xx = $0 =~ /^xx/; +my $xx = $0 =~ /\bxx$/; if ($xx) { $usage = "usage: send file(s): xx [:slot] file...\n". @@ -104,6 +117,7 @@ if ($xx) { $usage = <; + # $fexcgi = <$idf> if $fexcgi =~ /^\[.+\]/; $from = <$idf>; $id = <$idf>; while (<$idf>) { @@ -745,6 +765,7 @@ sub register { sendheader("$fs:$port","GET $proxy_prefix/fur?user=$mail&verify=no HTTP/1.1"); http_response(); + # header while (<$SH>) { s/\r//; printf "<-- $_"if $opt_v; @@ -779,10 +800,365 @@ sub register { } +# menu for MacOS users +sub menu { + my $key; + my $new; + local $_; + + system 'clear'; + print "\n"; + print "fexsend-$version\n"; + + for (;;) { + if (open $idf,$idf) { + $fexcgi = getline($idf) and + $from = getline($idf) and + $id = getline($idf); + close $idf; + last if $id; + } + &set_ID; + } + + print "\n"; + print "$from on $fexcgi\n"; + print "\n"; + + for (;;) { + print "\n"; + print "[s] send a file or directory\n"; + print "[u] update fexsend\n"; + print "[l] change login data (user, server, auth-ID)\n"; + print "[h] help\n"; + print "[q] quit\n"; + print "\n"; + print "your choice: "; + $key = ReadKey(0); + if ($key eq 'q') { + print "$key\n"; + print "\n"; + print "Type [Cmd]W to close this window.\n"; + exit; + } + if ($key eq 'h') { + print "$key\n"; + print + "\n". + "With fexsend you can send files of any size to any e-mail address.\n". + "\n". + "At the recipient or file prompt [RETURN] brings you to this option menu.\n". + "\n". + "To send more than one file:\n". + "When you enter * at the file prompt, you will be first asked for an archive name\n". + "and then you can drag+drop multiple files.\n". + "\n". + "Do not forget to terminate each input line with [RETURN].\n". + "\n". + "See http://fex.rus.uni-stuttgart.de/ for more informations.\n"; + next; + } + if ($key eq 'u') { + print "$key\n"; + if ($0 =~ m:(^/client/|/sw/):) { + print "\n"; + print "use swupdate to update fexsend!\n"; + next; + } + $new = $0.'.new'; + system "curl http://fex.belwue.de/download/fexsend>".quote($new); + chmod 0755,$new; + system qw'perl -c',$new; + if ($? == 0) { + rename $new,$0; + exec $0; + } else { + print "\n"; + print "cannot install new fexsend\n"; + } + next; + } + if ($key eq 'l') { + print "$key\n"; + system 'clear'; + &set_ID; + next; + } + if ($key eq 's' or $key eq "\n") { + print "s\n"; + &ask_file; + next; + } + } + exit; +} + + +# for MacOS +sub ask_file { + my ($file,$comment,$recipient,$archive,$size,$cmd,$key); + my @files; + my $qfiles; + local $_; + + system 'clear'; + + &set_ID unless -s $idf; + + print "\n"; + print "Enter [RETURN] after each input line.\n"; + print "\n"; + + for (;;) { + print "Recipient(s): "; + $recipient = ; + chomp $recipient; + $recipient =~ s/^\s+//; + $recipient =~ s/\s+$//; + $recipient =~ s/[\s;,]+/,/g; + &menu unless $recipient; + last if $recipient =~ /\w/ or $recipient eq '.'; + } + + for (;;) { + print "\n"; + print "Drag a file into this window or hit [RETURN] "; + print $archive ? "to continue.\n" : "for menu options.\n"; + print "File to send: "; + $file = ||''; + chomp $file; + $file =~ s/^\s+//; + $file =~ s/ $// if $file !~ /\\ $/; + &menu unless $file or $archive; + if ($file eq '*') { + print "Archive name: "; + $archive = ||''; + chomp $archive; + next unless $archive; + $archive =~ s/^\s+//g; + $archive =~ s/\s+$//g; + $archive =~ s/[^\w=.+-]/_/g; + next; + } + if ($file) { + unless (-e $file) { + $file =~ s/\\\\/\000/g; + $file =~ s/\\//g; + $file =~ s/\000/\\/g; + } + unless (-r $file) { + print "\"$file\" is not readable\n"; + next; + } + my $qf = quote($file); + if (`du -ms $qf` =~ /^(\d+)/) { + $size += $1; + printf "%d MB\n",$1; + } + if ($archive) { + push @files,$file; + next; + } + } + if ($archive) { + next unless @files; + $qfiles = join(' ',map(quote($_),@files)); + if ($size < 2048) { + $archive .= '.zip'; + } else { + $archive .= '.tar'; + } + } + print "\n"; + print "Comment: "; + $comment = ||''; + chomp $comment; + print "\n"; + if ($comment =~ s/^:\s*-/-/) { + $cmd = quote($0)." $comment "; + if ($archive) { + $cmd .= '-a '.quote($archive).' '.$qfiles; + } else { + $cmd .= quote($file); + } + $cmd .= ' '.quote($recipient); + print $cmd,"\n"; + system $cmd; + } else { + print quote($0)." -C '$comment' "; + if ($archive) { + printf "-a %s %s %s\n",quote($archive),$qfiles,$recipient; + system $0,'-C',$comment,'-a',$archive,@files,$recipient; + } else { + printf "%s %s\n",quote($file),$recipient; + system $0,'-C',$comment,$file,$recipient; + } + } + print "\n"; + print "[s] send another file to $recipient\n"; + print "[n] send another file to another recipient\n"; + print "[q] quit\n"; + print "\n"; + print "your choice: "; + for (;;) { + $key = ReadKey(0); + &ask_file if $key eq 'n'; + if ($key eq 's' or $key eq "\n") { + print "s\n"; + last; + } + if ($key eq 'q') { + print "$key\n"; + exit; + } + } + $file = $comment = $archive = ''; + @files = (); + } +} + + +sub set_ID { + my ($server,$port,$user,$logo); + local $_; + + print "\n"; + for (;;) { + print "F*EX server URL: "; + $server = ; + $server =~ s/[\s\n]//g; + if ($server =~ s:/fup/(\w+)$::) { + $_ = decode_b64($1); + if (/(from|user)=(.+)&id=(.+)/) { + $user = $2; + $id = $3; + } + } + $server =~ s:/fup.*::; + $server =~ s:/+$::; + next if $server !~ /\w/; + if ($server =~ s/^https:..// or $server =~ /:443/) { + $server =~ s/:.*//; + $port = 443; + eval "use IO::Socket::SSL"; + if ($@) { + print "\nno perl SSL modules installed - cannot use https\n\n"; + next; + } + $SH = IO::Socket::SSL->new( + PeerAddr => $server, + PeerPort => $port, + Proto => 'tcp', + %SSL + ); + } else { + $server =~ s:^http.//::; + if ($server =~ s/:(\d+)//) { + $port = $1; + } else { + $port = 80; + } + $SH = IO::Socket::INET->new( + PeerAddr => $server, + PeerPort => $port, + Proto => 'tcp', + ); + } + unless ($SH) { + print "\ncannot connect to $server:$port - $!\n\n"; + next; + } + sendheader( + "$server:$port", + "GET /logo.jpg HTTP/1.0", + "User-Agent: $useragent", + "Connection: close", + ); + $_ = <$SH>||''; + unless (/HTTP.1.1 200/) { + print "\nbad server reply: $_\n"; + next; + } + while (<$SH>) { last if /^\s*$/ } + local $/; + $logo = <$SH>||''; + close $SH; + if (length $logo < 9999) { + print "\n$server is not a F*EX server!\n\n"; + next; + } + open $logo,">$tmpdir/fex.jpg"; + print {$logo} $logo; + close $logo; + last; + } + + for (;;) { + last if $user; + print "Your login (e-mail address): "; + $user = ; + $user =~ s/[\s\n]//g; + if ($user !~ /.@[\w.-]+$/) { + print "\"$user\" is not a valid e-mail address!\n"; + next; + } + } + + for (;;) { + last if $id; + print "Your auth-ID for this account: "; + $id = ; + $id =~ s/[\s\n]//g; + } + + open $idf,'>',$idf or die "$0: cannot write to $idf - $!\n"; + print {$idf} "$server\n", + "$user\n", + "$id\n"; + close $idf; + print "\n"; + print "Login data written to $idf\n\n"; + print "fexing test file to $user:\n\n"; + system "$0 -o -M -C test $tmpdir/fex.jpg $user"; + print "\n"; + if ($? != 0) { + print "fexsend failed, login data is invalid, try again\n"; + &set_ID; + } else { + print "fexsend test succeeded!\n"; + sleep 3; + } +} + + +# read one key from terminal in raw mode +sub ReadKey { + my $key; + local $SIG{INT} = sub { stty('reset'); exit }; + + stty('raw'); + # loop necessary for ESXi support + while (not defined $key) { + $key = getc(STDIN); + } + stty('reset'); + return $key; +} + + +sub stty { + if (shift eq 'raw') { + system qw'stty -echo -icanon eol',"\001"; + } else { + system qw'stty echo icanon eol',"\000"; + } +} + + sub send_xx { my $transferfile = shift; my $file = ''; - my (@r,@tar); + my (@r,@tar,$dir); $SIG{PIPE} = $SIG{INT} = sub { unlink $transferfile; @@ -800,7 +1176,6 @@ sub send_xx { print "making tar transfer file $transferfile :\n"; # single file? then add this directly if (scalar @ARGV == 1) { - my ($dir,$file); # strip path if not ending with / if ($ARGV[0] =~ m:(.+)/(.+): and $2 !~ m:/$:) { ($dir,$file) = ($1,$2); @@ -947,49 +1322,54 @@ sub query_settings { # list spool sub list { my (@r,$r); - my ($data,$dkey,$n); + my ($data,$dkey); + my $n = 0; + my $s = 1; + my $a = shift @ARGV || '.'; local $_; female_mode("list spooled files?") if $opt_F; - if ($opt_l and $n = shift @ARGV and $n =~ /^\d+$/) { - open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; - while (<$fexlist>) { - if (/^\s*(\d+)\) (\w+) (.+)/ and $1 eq $n) { - serverconnect($server,$port) unless $SH; - sendheader( - "$server:$port", - "GET $proxy_prefix/fop/$2/$2?LIST HTTP/1.1", - "User-Agent: $useragent", - ); - $_ = <$SH>||''; - s/\r//; - print "<-- $_" if $opt_v; - if (/^HTTP.* 200/) { + if ($opt_l) { + if ($a =~ /^\d+$/) { + open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; + while (<$fexlist>) { + if (/^\s*(\d+)\) (\w+) (.+)/ and $1 eq $a) { + serverconnect($server,$port) unless $SH; + sendheader( + "$server:$port", + "GET $proxy_prefix/fop/$2/$2?LIST HTTP/1.1", + "User-Agent: $useragent", + ); + $_ = <$SH>||''; + s/\r//; print "<-- $_" if $opt_v; - while (<$SH>) { - s/\r//; - if (/^\n/) { - print; - print while <$SH>; + if (/^HTTP.* 200/) { + print "<-- $_" if $opt_v; + while (<$SH>) { + s/\r//; + if (/^\n/) { + print; + print while <$SH>; + } } + } elsif (s:HTTP/[\d\. ]+::) { + die "$0: server response: $_"; + } else { + die "$0: no response from fex server $server\n"; } - } elsif (s:HTTP/[\d\. ]+::) { - die "$0: server response: $_"; - } else { - die "$0: no response from fex server $server\n"; + exit; } - exit; } + die "$0: file \#$a not found in fexlist\n"; } - die "$0: file \#$n not found in fexlist\n"; - } else { - @r = formdatapost( - from => $from, - to => $opt_l ? '*' : $from, - command => $opt_C, - ); } + + @r = formdatapost( + from => $from, + to => $opt_l ? '*' : $from, + command => $opt_C, + ); die "$0: no response from fex server $server\n" unless @r; $_ = shift @r; unless (/^HTTP.* 200/) { @@ -1011,12 +1391,13 @@ sub list { s/&/&/g; s/"/\"/g; s/</) { @@ -1139,6 +1520,37 @@ sub delete { } +sub delete_file { + my ($from,$to,$file) = @_; + local $_; + + unless ($SH) { + serverconnect($server,$port); + query_sid($server,$port) unless $anonymous; + } + + $file = urlencode($file); + sendheader( + "$server:$port", + "GET $proxy_prefix/fop/$to/$from/$file?id=$sid&DELETE HTTP/1.1", + "User-Agent: $useragent", + ); + + while (<$SH>) { + s/\r//; + printf "<-- $_"if $opt_v; + last if /^\s*$/; + } +} + + +sub urlencode { + local $_ = shift; + s/([^_=:,;<>()+.\w\-])/'%'.uc(unpack("H2",$1))/ge; + return $_; +} + + sub send_fex { my @to; my $file = ''; @@ -1194,7 +1606,7 @@ sub send_fex { if ($anonymous) { my $aok; - sendheader("$server:$port","OPTIONS FEX HTTP/1.1"); + sendheader("$server:$port","OPTIONS /FEX HTTP/1.1"); $_ = <$SH>||''; s/\r//; die "$0: no response from fex server $server\n" unless $_; @@ -1287,10 +1699,21 @@ sub send_fex { } if (@ARGV > 1 and not ($opt_a or $opt_s or $opt_d)) { - print "Archive name (name.tar, name.tgz or name.zip) or [ENTER] to send file for file:\n"; + print "Archive name (name.tar, name.tgz or name.zip) or [RETURN] to send file for file:\n"; $opt_a = ; $opt_a =~ s/^\s+//; $opt_a =~ s/\s+$//; + $opt_a =~ s/\//_/g; + } + + if ($macos and not $opt_a and -d "@ARGV") { + my $dir = "@ARGV"; + my $qdir = quote($dir); + if (`du -s $qdir` =~ /^(\d+)/ and $1 < 2**21) { + $opt_a = "$dir.zip"; + } else { + $opt_a = "$dir.tar"; + } } if ($opt_s) { @@ -1317,7 +1740,7 @@ sub send_fex { $opt_a =~ s:.*/::g; } foreach my $file (@ARGV) { - die "$0: cannot read $file\n" unless -l $file or -r $file; + die "$0: cannot read \"$file\"\n" unless -l $file or -r $file; } $opt_a .= ".$atype" if $opt_a !~ /\.$atype$/; $transferfile = "$tmpdir/$opt_a"; @@ -1329,6 +1752,10 @@ sub send_fex { # else { system(qw'7z a -tzip -mm=copy',$transferfile,@ARGV) } system(qw'7z a -tzip',$transferfile,@ARGV); @files = ($transferfile); + } elsif ($macos and scalar(@ARGV) == 1) { + ## ditto-zip is now handled by formdatapost() + system 'true'; + @files = ($opt_a); } else { # zip archives must be < 2 GB, so split as necessary @files = zipsplit($transferfile,@ARGV); @@ -1358,6 +1785,7 @@ sub send_fex { } else { ## tar is now handled by formdatapost() # system(qw'tar cvf',$transferfile,@ARGV); + system 'true'; @files = ($opt_a); } } elsif ($atype eq 'tgz') { @@ -1403,12 +1831,12 @@ sub send_fex { unless ($opt_d) { unless (-f $file) { if (-e $file) { - die "$0: $file is not a regular file, try option -a\n" + die "$0: \"$file\" is not a regular file, try option -a\n" } else { - die "$0: $file does not exist\n"; + die "$0: \"$file\" does not exist\n"; } } - die "$0: cannot read $file\n" unless -r $file; + die "$0: cannot read \"$file\"\n" unless -r $file; } push @files,$file; } @@ -1418,7 +1846,7 @@ sub send_fex { foreach my $file (@files) { my @s = stat($file); unless (@s and ($s[2] & S_IROTH) and -r $file) { - die "$0: $file is not world readable\n"; + die "$0: \"$file\" is not world readable\n"; } } } @@ -1426,7 +1854,7 @@ sub send_fex { foreach my $file (@files) { sleep 1; # do not overrun server! unless (-s $file or $opt_d or $opt_a or $opt_s) { - die "$0: cannot send empty file $file\n"; + die "$0: cannot send empty file \"$file\"\n"; } female_mode("send file $file?") if $opt_F; @r = formdatapost( @@ -1443,15 +1871,32 @@ sub send_fex { if (not @r or not grep /\w/,@r) { die "$0: no response from server\n"; } + next if "@r" eq '0'; # already transfered if (($r) = grep /^ERROR:/,@r) { if ($anonymous and $r =~ /purge it/) { die "$0: file is already on server for $to - use another anonymous recipent\n"; + } elsif ($r =~ /timeout/i) { + close $SH; + retry("timed out"); } else { $r =~ s/.*?:\s*//; $r =~ s/<.+?>//g; die "$0: server error: $r\n"; } } + unless ($opt_d) { + if (scalar(@r) == 1) { + die "$0: server error: @r\n"; + } else { + if ($r[0] !~ /HTTP.1.. 2/) { + if ($r[0] =~ /HTTP.[\s\d.]+(.+)/) { + die "$0: server error: $1\n"; + } else { + die "$0: server error:\n".join("\n",@r)."\n"; + } + } + } + } if (($r) = grep /

\Q$file/,@r) { $r =~ s/<.+?>//g; print "$r\n"; @@ -1459,7 +1904,8 @@ sub send_fex { if ($opt_a !~ /^afex_\d+\.tar$/ and $file !~ /afex_\d+\.tar$/) { # print grep({s/^(X-Recipient:.*\((.+)\))/Parameters: $2\n/i} @r); my $nonot = 0; - my ($recipient,$location); + my $recipient = ''; + my $location = ''; foreach (@r) { if (/^(X-)?(Recipient.*)/i) { $recipient = $2; @@ -1468,23 +1914,13 @@ sub send_fex { } if (/^(X-)?(Location.*)/i) { $location = $2; - if ($from eq $to or $from =~ /^\Q$to\E@/i - or $nomail or $anonymous or $nonot) { - print "$recipient\n"; - print "$location\n"; - } } } - unless ($opt_d or $location) { - if (scalar(@r) == 1) { - die "$0: server error: @r\n"; - } else { - if ($r[0] !~ /HTTP.1.. 2/ and $r[0] =~ /HTTP.[\s\d.]+(.+)/) { - die "$0: server error: $1\n"; - } else { - die "$0: server error:\n".join("\n",@r)."\n"; - } - } + if ($from eq $to or $from =~ /^\Q$to\E@/i + or $nomail or $anonymous or $nonot) + { + print "$recipient\n" if $recipient; + print "$location\n" if $location; } } } @@ -1518,10 +1954,10 @@ sub forward { open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; while (<$fexlist>) { - if (/^\s*(\d+)\) (\w+) \[\d+ d\] (.+)/ and $1 eq $opt_f) { + if (/^\s*(\d+)\) (\w+) .\s*\d+ d. ([+-] )?(.+)/ and $1 eq $opt_f) { $n = $1; $dkey = $2; - $file = $3; + $file = $4; if ($file =~ s/ "(.*)"$//) { $opt_C ||= $1 if $1 ne 'NOMAIL'; } @@ -1572,7 +2008,7 @@ sub renotify { open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; while (<$fexlist>) { - if (/^\s*(\d+)\) (\w+) \[\d+ d\] (.+)/ and $1 eq $opt_N) { + if (/^\s*(\d+)\) (\w+) .\s*\d+ d. (.+)/ and $1 eq $opt_N) { $n = $1; $dkey = $2; last; @@ -1628,7 +2064,7 @@ sub modify { open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; while (<$fexlist>) { - if (/^\s*(\d+)\) (\w+) \[\d+ d\] (.+)/ and $1 eq $opt_x) { + if (/^\s*(\d+)\) (\w+) .\s*\d+ d. (.+)/ and $1 eq $opt_x) { $n = $1; $dkey = $2; $file = $3; @@ -1738,7 +2174,7 @@ sub get_xx { sub formdatapost { my %P = @_; - my ($boundary,$filename,$filesize,$length,$buf,$file,$fpsize,$resume,$seek); + my ($boundary,$filename,$length,$buf,$file,$fpsize,$resume,$seek); my ($flink); my (@hh,@hb,@r,@pv,$to); my ($bytes,$t,$bt); @@ -1746,9 +2182,11 @@ sub formdatapost { my $bs = 2**16; # blocksize for reading and sending file my $fileid = int(time); my $chunk = 0; + my $filesize = 0; my $connection = ''; my $pct = ''; - my ($tar,$aname,$atype,$tarlist,$tarerror,$location,$transferfile); + my $dittodir = '.'; + my ($tar,$ditto,$aname,$atype,$list,$error,$location,$transferfile); local $_; if (defined($file = $P{file})) { @@ -1771,7 +2209,7 @@ sub formdatapost { $of =~ s/([^_\w\.\-])/\\$1/g; shelldo("gzip <$if>$of"); $filesize = -s $transferfile; - die "$0: cannot gzip $file\n" unless $filesize; + die "$0: cannot gzip \"$file\"\n" unless $filesize; $file = $transferfile; } @@ -1779,12 +2217,12 @@ sub formdatapost { if (not $windoof and $opt_a and $file =~ /(.+)\.(tar|tgz)$/) { $aname = $1; $atype = $2; - $tarlist = "$tmpdir/$aname.list"; - $tarerror = "$tmpdir/$aname.error"; + $list = "$tmpdir/$aname.list"; + $error = "$tmpdir/$aname.error"; $tar = 'tar -cv'; $tar .= 'z' if $atype eq 'tgz'; if (`tar --help 2>/dev/null` =~ /--index-file/) { - $tar .= " --index-file=$tarlist -f-"; + $tar .= " --index-file=$list -f-"; } else { $tar .= " -f-"; } @@ -1794,12 +2232,10 @@ sub formdatapost { } } foreach (@ARGV) { - $file = $_; - $file =~ s/([^\w\-\@\#%,.=+~_:])/\\$1/g; - $tar .= ' '.$file; + $tar .= ' '.quote($_); } # print "calculating archive size... "; - open $tar,"$tar 2>$tarerror|" or die "$0: cannot run tar - $!\n"; + open $tar,"$tar 2>$error|" or die "$0: cannot run tar - $!\n"; $t0 = int(time) if -t STDOUT; while ($b = read $tar,$_,$bs) { $filesize += $b; @@ -1814,12 +2250,12 @@ sub formdatapost { printf "Archive size: %d MB\n",int($filesize/M) if -t STDOUT; unless (close $tar) { $_ = ''; - if (open $tarerror,$tarerror) { + if (open $error,$error) { local $/; - $_ = <$tarerror>; - close $tarerror; + $_ = <$error>; + close $error; } - unlink $tarlist,$tarerror; + unlink $list,$error; die "$0: tar error:\n$_"; } $file = "$aname.$atype"; @@ -1827,6 +2263,58 @@ sub formdatapost { undef $SH; # force reconnect (timeout!) } + # special file: ditto-zip-on-the-fly + # ditto: Can't archive multiple sources + elsif ($macos and $opt_a and $file =~ /(.+)\.(zip)$/ and scalar(@ARGV) == 1) { + $aname = $1; + $atype = $2; + $list = "$tmpdir/$aname.list"; + $error = "$tmpdir/$aname.error"; + $ditto = 'ditto -c -k --sequesterRsrc --keepParent'; + if (-d "@ARGV" and "@ARGV" =~ m:^(.+)/(.+):) { + $dittodir = $1; + $file = $2; + $file =~ s/([^\w\-\@\#%,.=+_:])/\\$1/g; + $ditto .= ' '.$file; + } else { + foreach (@ARGV) { + $file = $_; + $file =~ s/([^\w\-\@\#%,.=+_:])/\\$1/g; + $ditto .= ' '.$file; + } + } + # print "calculating archive size... "; + debug("cd $dittodir;$ditto -"); + open $ditto,"cd $dittodir;$ditto - 2>$error|" + or die "$0: cannot run ditto - $!\n"; + $t0 = int(time) if -t STDOUT; + while ($b = read $ditto,$_,$bs) { + $filesize += $b; + if ($t0) { + $t1 = int(time); + if ($t1>$t0) { + printf "Archive size: %d MB\r",int($filesize/M); + $t0 = $t1; + } + } + } + printf "Archive size: %d MB\n",int($filesize/M) if -t STDOUT; + unless (close $ditto) { + $_ = ''; + if (-s $error and open $error,$error) { + local $/; + $_ = <$error>; + close $error; + } + unlink $list,$error; + die "$0: ditto-zip error:\n$_"; + } + unlink $list,$error; + $file = "$aname.$atype"; + $filename = encode_utf8($file); + undef $SH; # force reconnect (timeout!) + } + # single file else { $filename = encode_utf8(${'opt_='} || $file); @@ -1840,7 +2328,7 @@ sub formdatapost { if ($opt_d) { $filesize = 0; } elsif (not $opt_g and not $opt_s) { - $filesize = -s $file or die "$0: $file is empty or not readable\n"; + $filesize = -s $file or die "$0: \"$file\" is empty or not readable\n"; } } @@ -1880,20 +2368,28 @@ sub formdatapost { $P{id} = $sid; # ugly hack! + $filename =~ s/\\/_/g; # \ is a illegal character for fexsrv + # ask server if this file has been already sent - if ($file and not $xx and not - ($opt_s or $opt_g or $opt_o or $opt_d or $opt_l or $opt_L or ${'opt_/'})) - { - ($seek,$location) = query_file($server,$port,$frecipient||$P{to},$P{from}, - $P{id},$filename,$fileid); - if ($filesize == $seek) { - print "Location: $location\n" if $location and $nomail; - warn "$0: $file has been already transferred\n"; - return $file; - } elsif ($seek and $seek < $filesize) { - $resume = " (resuming at byte $seek)"; - } elsif ($filesize <= $seek) { - $seek = 0; + if ($file and not $xx) { + if (not $opt_d and $opt_o) { + # delete before overwrite + delete_file($from,$to,$filename); + serverconnect($server,$port); + query_sid($server,$port) unless $anonymous; + $P{id} = $sid; # ugly hack! + } elsif (not($opt_s or $opt_g or $opt_d or $opt_l or $opt_L or ${'opt_/'})) { + ($seek,$location) = query_file($server,$port, + $frecipient||$P{to},$P{from},$P{id},$filename,$fileid); + if ($filesize == $seek) { + print "Location: $location\n" if $location and $nomail; + warn "$0: $file has been already transferred\n"; + return 0; + } elsif ($seek and $seek < $filesize) { + $resume = " (resuming at byte $seek)"; + } elsif ($filesize <= $seek) { + $seek = 0; + } } if ($proxy) { sleep 1; # do not overrun proxy @@ -1935,7 +2431,8 @@ sub formdatapost { push @hb,"--$boundary"; push @hb,"Content-Disposition: form-data; name=\"$name\""; push @hb,""; - push @hb,encode_utf8($P{$v}); + # push @hb,encode_utf8($P{$v}); + push @hb,$P{$v}; } } @@ -2027,10 +2524,10 @@ sub formdatapost { $tpid = fork(); if (defined $tpid and $tpid == 0) { sleep 1; - if (open $tarlist,$tarlist) { - # print "\n$tar|\n"; system "ls -l $tarlist"; - while ($tarlist) { - while (<$tarlist>) { + if (open $list,$list) { + # print "\n$tar|\n"; system "ls -l $list"; + while ($list) { + while (<$list>) { print ' 'x(length($file)+40),"\r",$_; } sleep 1; @@ -2044,13 +2541,19 @@ sub formdatapost { print "Fast forward to byte $seek (resuming)\n"; readahead($file,$seek); } + } elsif ($ditto) { + $ditto =~ s/ditto/ditto -V/; + open $file,"cd $dittodir;$ditto -|" or die "$0: cannot run ditto - $!\n"; + if ($seek) { + print "Fast forward to byte $seek (resuming)\n"; + readahead($file,$seek); + } } else { if ($opt_g) { - my $fileq = $file; - $fileq =~ s/([^\w\-\@\#%,.=+~_:])/\\$1/g; + my $fileq = quote($file); open $file,"gpg -e -r $to <$fileq|" or die "$0: cannot run gpg - $!\n"; } else { - open $file,$file or die "$0: cannot read $file - $!\n"; + open $file,$file or die "$0: cannot read \"$file\" - $!\n"; seek $file,$seek,0; } binmode $file; @@ -2072,7 +2575,11 @@ sub formdatapost { alarm(0); $bytes += $b; if ($filesize > 0 and $bytes+$seek > $filesize) { - die "$0: $file filesize has grown while uploading\n"; + if ($tpid) { + kill 9,$tpid; + unlink $list; + } + die "$0: \"$file\" filesize has grown while uploading\n"; } $bt += $b; $t2 = time; @@ -2121,12 +2628,26 @@ sub formdatapost { if ($tpid) { sleep 2; kill 9,$tpid; - unlink $tarlist; + unlink $list; } - + + if ($fileid =~ /[a-z]/ and not ($opt_s or $opt_g)) { + if ($opt_a) { + if ($fileid ne md5_hex(fmd(@ARGV))) { + print "\n" unless $opt_q; + die "$0: files have been modified while uploading\n"; + } + } else { + if ($fileid ne fileid($file)) { + print "\n" unless $opt_q; + die "$0: file has been modified while uploading\n"; + } + } + } + unless ($opt_q) { if (not $chunksize and $bytes+$seek < $filesize) { - die "$0: $file filesize has shrunk while uploading\n"; + die "$0: \"$file\" filesize has shrunk while uploading\n"; } if ($seek or $chunksize and $chunksize < $filesize) { @@ -2270,7 +2791,7 @@ sub zipsplit { $size = -s $file; if ($size > 2147480000) { unlink @zipfiles; - die "$0: $file too big for zip\n"; + die "$0: \"$file\" too big for zip\n"; } if ($zsize + $size > 2147000000) { push @zipfiles,zip($zipbase.'_'.$n.'.zip',@files); @@ -2336,7 +2857,7 @@ sub query_file { my $seek = 0; my $qfileid = ''; my ($head,$location); - my ($response,$fexsrv); + my ($response,$fexsrv,$cc); local $_; $to =~ s/,.*//; @@ -2377,11 +2898,17 @@ sub query_file { if (/^X-File-ID:\s+(.+)/) { $qfileid = $1 } if (/^X-Features:\s+(.+)/) { $features = $1 } if (/^X-Location:\s+(.+)/) { $location = $1 } + if (/^Connection: close/) { $cc = $_ } } # return true seek only if file is identified $seek = 0 if $qfileid and $qfileid ne $fileid; + if ($cc) { + serverconnect($server,$port); + $sid = $id; + } + return ($seek,$location); } @@ -2409,7 +2936,7 @@ sub edit_address_book { print {$ab} $AB{ADDRESS_BOOK}; close $ab; - system $editor,$ab; + system "$editor $ab"; exit unless -s $ab; $opt_o = $opt_A; @@ -2510,14 +3037,12 @@ sub query_sid { $sid = $id; - if ($port eq 443) { + if ($port eq 443 or $proxy) { return if $features; # early return if we know enough - $req = "OPTIONS FEX HTTP/1.1"; - } elsif ($proxy) { - return if $features; # early return if we know enough - $req = "GET $proxy_prefix/SID HTTP/1.1"; + $req = "OPTIONS /FEX HTTP/1.1"; + $req = "HEAD / HTTP/1.1"; } else { - $req = "GET SID HTTP/1.1"; + $req = "GET /SID HTTP/1.1"; } sendheader("$server:$port",$req,"User-Agent: $useragent"); @@ -2529,16 +3054,44 @@ sub query_sid { s/\r//; print "<-- $_" if $opt_v; - if (/^HTTP.* [25]0[01] /) { + if ($req =~ /OPTIONS/ and /^HTTP.* 502 /) { + # (reverse) proxy error + close $SH; + serverconnect($server,$port); + $req = "GET /SID HTTP/1.0"; + sendheader("$server:$port",$req,"User-Agent: $useragent"); + $_ = <$SH>; + unless (defined $_ and /\w/) { + print "\n" if $opt_v; + die "$0: no response from server\n"; + } + s/\r//; + print "<-- $_" if $opt_v; + while (<$SH>) { + s/\r//; + print "<-- $_" if $opt_v; + $features = $1 if /^X-Features: (.+)/; + $timeout = $1 if /^X-Timeout: (\d+)/; + last if /^\n/; + } + close $SH; + serverconnect($server,$port); + } elsif (/^HTTP.* [25]0[01] /) { if (not $proxy and $port ne 443 and /^HTTP.* 201 (.+)/) { $sid = 'MD5H:'.md5_hex($id.$1); } + my $cc; while (<$SH>) { s/\r//; print "<-- $_" if $opt_v; $features = $1 if /^X-Features: (.+)/; $timeout = $1 if /^X-Timeout: (\d+)/; - last if /^\n/; + $cc = $_ if /^Connection: close/; + last if /^\n/; + } + if ($cc) { + serverconnect($server,$port); + $sid = $id; } } elsif (/^HTTP.* 301 /) { while (<$SH>) { last if /Location/ } @@ -2588,15 +3141,15 @@ sub xxget { die "$0: no Content-Length in server-reply\n" unless $cl; - open F,">$save" or die "$0: cannot write to $save - $!\n"; - binmode F; + open $save,">$save" or die "$0: cannot write to $save - $!\n"; + binmode $save; $t0 = $t1 = int(time); $tso = ''; while ($b = read($SH,$_,$bs)) { $B += $b; - print F; + print {$save} $_; if (int(time) > $t1) { $t1 = int(time); $ts = ts($B,$cl); @@ -2609,7 +3162,7 @@ sub xxget { } print STDERR ts($B,$cl),"\n"; - close F; + close $save; } @@ -2745,10 +3298,16 @@ sub readahead { } -# fileid is inode and mtime sub fileid { - my @s = stat(shift); - return @s ? $s[1].$s[9] : int(time); + my $file = shift; + my @s = stat($file); + + if (@s) { + return md5_hex($file.$s[0].$s[1].$s[7].$s[9]); + } else { + warn "$0: $file - $!\n"; + return int(time); + } } @@ -2768,7 +3327,7 @@ sub get_mutt_alias { s/.*\s+//; s/[<>]//g; if (/,/) { - warn "$0: ignoring mutt multi-alias $to = $alias\n"; + warn "$0: ignoring mutt multi-alias $to = $_\n"; last; } if (/@/) { @@ -2783,7 +3342,7 @@ sub get_mutt_alias { } -# collect file meta data (filename, inode, mtime) +# collect (hashed) file meta data sub fmd { my @files = @_; my ($file,$dir); @@ -2796,7 +3355,7 @@ sub fmd { while (defined ($file = readdir($dir))) { next if $file eq '..'; if ($file eq '.') { - $fmd .= $file.fileid($dir); + $fmd .= fileid($dir); } else { $fmd .= fmd("$dir/$file"); } @@ -2804,7 +3363,7 @@ sub fmd { closedir $dir; } } else { - $fmd .= $file.fileid($file); + $fmd .= fileid($file); } } @@ -2862,8 +3421,8 @@ sub http_response { unless (defined $_ and /\w/) { die "$0: no response from server\n"; } - print "<-- $_\n" if $opt_v; s/\r?\n//; + print "<-- $_\n" if $opt_v; # CGI fatalsToBrowser if (/^HTTP.* 500/) { @r = <$SH> unless @r; @@ -2883,7 +3442,6 @@ sub http_response { die "$0: server error: $error\n"; } - print "<-- $_\n" if $opt_v; return $_; } @@ -2901,12 +3459,11 @@ sub update { local $/; open $0,$0 or die "cannot read $0 - $!\n"; - $_ = <$0>; + $cfc = <$0>; close $0; - s/.*\n$cfb\n//s; - $cfc = $_; + $cfc =~ s/.*\n$cfb\n//s; - foreach my $p (qw(fexget sexsend)) { + foreach my $p (qw'fexget sexsend') { open $p,$p or die "cannot read $p - $!\n"; $_ = <$p>; close $p; @@ -2917,7 +3474,7 @@ sub update { close $p; } - exec "l $0 fexget sexsend"; + exec "l fexsend fexget sexsend"; exit; } @@ -3039,6 +3596,7 @@ sub tcpconnect { if ($SH) { autoflush $SH 1; + binmode $SH; } else { die "$0: cannot connect $server:$port - $@\n"; } @@ -3095,6 +3653,18 @@ sub nvtsend { } +sub quote { + local $_ = shift; + s/([^\w\@\/%^,.=+_:+-])/\\$1/g; + return $_; +} + + +sub debug { + print "## DEBUG: @_\n" if $DEBUG; +} + + # from MIME::Base64::Perl sub encode_b64 { my $res = ""; diff --git a/bin/fexsrv b/bin/fexsrv index 6a3e80e..e89b6f9 100755 --- a/bin/fexsrv +++ b/bin/fexsrv @@ -91,7 +91,7 @@ foreach my $lib ( # import from fex.pp our ($hostname,$debug,$timeout,$max_error,$max_error_handler); -our ($spooldir,@logdir,$docdir,$xkeydir,$lockdir); +our ($spooldir,@logdir,$docdir,$xkeydir,$akeydir,$lockdir); our ($force_https,$default_locale,$bs,$MB,$adlm); our (@locales); @@ -247,15 +247,16 @@ REQUEST: while (*STDIN) { http_error(413); } - if (/^(GET \/|X-Forwarded-For|User-Agent)/i) { + if (/^(GET \/|\S*Forwarded|\S*Client-IP|\S*Coming-From|User-Agent)/i) { $hid .= $_."\n"; } # reverse-proxy? + # (only IPv4 support!) if ($reverse_proxy_ip and $reverse_proxy_ip eq $ra and - /^X-Forwarded-For: ([\d.]+)/ + /^\S*(Forwarded|Client-IP|Coming-From)\S*: ([\d.]+)/i ) { - $ENV{REMOTE_ADDR} = $ra = $1; + $ENV{REMOTE_ADDR} = $ra = $2; $ENV{REMOTE_HOST} = $rh = gethostbyaddr(inet_aton($ra),AF_INET) || ''; $ENV{HTTP_HOST} = $hostname; if ($ENV{PROTO} eq 'https') { $port = 443 } @@ -312,7 +313,7 @@ REQUEST: while (*STDIN) { } } - if ($request =~ /^OPTIONS FEX HTTP\/[\d\.]+$/i) { + if ($request =~ /^OPTIONS \/?FEX HTTP\/[\d\.]+$/i) { fexlog($connect,@log); nvt_print( "HTTP/1.1 201 OK", @@ -499,6 +500,22 @@ REQUEST: while (*STDIN) { $ENV{LOCALE} = $locale = $default_locale; } + # for dynamic HTML documents + if ($ENV{HTTP_COOKIE} =~ /akey=(\w+)/) { + my $akey = $1; + my ($user,$id); + if ($user = readlink "$akeydir/$akey") { + $user =~ s:.*/::; + $user = untaint($user); + if ($id = slurp("$spooldir/$user/@")) { + chomp $id; + $ENV{AKEY} = $akey; + $ENV{USER} = $user; + $ENV{ID} = $id; + } + } + } + # check for name based virtual host $vhost = vhost($ENV{'HTTP_HOST'}); diff --git a/bin/fpg b/bin/fpg new file mode 100755 index 0000000..be610fe --- /dev/null +++ b/bin/fpg @@ -0,0 +1,338 @@ +#!/usr/bin/perl -w +# +# Programname: fpg - Frams' Perl grep +# Author: framstag@rus.uni-stuttgart.de +# Copyright: GPL +# +# History: +# 2003-02-27 Framstag initial version +# 2003-02-28 Framstag added exit status +# 2007-03-09 Framstag added option -Q +# 2007-06-01 Framstag added options -s and -c +# and changed default output mode +# 2007-06-03 Framstag added ReadLine-support +# 2007-08-31 Framstag added option -x +# 2008-02-06 Framstag added implicit gunzip +# -F ==> -R, new -F option +# 2008-10-07 Framstag added option -p +# -n ==> -S, new -n option +# 2008-10-14 Framstag added option -M +# 2008-11-23 Framstag added option -~ + +use Getopt::Std; +use Term::ReadLine; +use locale; + +sub usage { + die <30 and not /\\w/' script +#See "perldoc perlre" for help on regular expressions. +} + +$0 =~ s:.*/::; +$| = 1; + +$maxlen = 0; + +$opt_i = $opt_r = $opt_v = $opt_l = $opt_h = $opt_e = $opt_n = $opt_o = 0; +$opt_s = $opt_c = $opt_Q = $opt_F = $opt_p = $opt_M = $opt_C = $opt_S = 0; +${'opt_~'} = 0; +$opt_S = 4; +$opt_x = $opt_X = ''; +$opt_R = "\n"; + +usage() if !getopts('hirvlLFMopscQen~S:R:C:x:X:') or $opt_h and not @ARGV; + +unless ($opt_Q) { + $exp = shift or usage(); +} + +if ($opt_C and ($opt_l or $opt_L or $opt_s or $opt_v or $opt_p or $opt_M)) { + die "$0: cannot mix option -C with any of -l -L -s -v -p -M\n"; +} + +if ($opt_M and ($opt_l or $opt_L or $opt_s or $opt_v or $opt_p or $opt_C)) { + die "$0: cannot mix option -M with any of -l -L -s -v -p -C\n"; +} + +if ($opt_o and ($opt_v or $opt_l or $opt_L or $opt_c or $opt_F or $opt_C)) { + die "$0: cannot mix option -E with any of -l -L -v -c -C -F\n"; +} + +$opt_XX = 0; +if (not ${'opt_~'}) { + @bfiles = grep(/~$|^#.*#$/,@ARGV); + if (@bfiles and + (grep(/[^~]$/,@ARGV) or grep(/(^|\/)#[^\/]*#$/,@ARGV))) { + $opt_XX = 1; + warn "$0: ignoring @bfiles\n"; # unless $opt_r; + } +} + +if (-t STDOUT) { + $B = "\033[1m"; + $N = "\033[m"; +} else { + $B = $N = ''; +} + +if ($opt_p) { $/ = '' } +else { $/ = $opt_R } +#else { eval '$/ = "'.$opt_R.'"' } + +$opt_h = 1 if not $opt_r and @ARGV < 2; + +if ($opt_Q) { + $q = new Term::ReadLine $0; + $q->ornaments(0) unless $ENV{PERL_RL}; + for (;;) { + $exp = $q->readline("$B\nsearch-expression:$N "); + last unless $exp; + &scan; + } +} else { + &scan; +} + +exit ($found?0:1); + +sub scan { + $egrep = ''; + if ($opt_e) { + eval "\$egrep = sub { $exp }"; + } else { + $exp =~ s/([\@\$\%\^\&\*\(\)\+\[\]\{\}\\\|\.\?])/\\$1/g if $opt_F; + $exp = '(?i)'.$exp if $opt_i; + $exp = '(?s)'.$exp if $opt_p or $opt_R; + #? $exp =~ s/\.\*\*/[.\n]*/g; + } + + $found = 0; + + if (@ARGV) { + foreach $file (@ARGV) { + next if $opt_X and $file =~ /$opt_X/; + next if $opt_XX and ($file =~ /~$/ or $file =~ m{(^|/)#[^/]*#$}); + my $error = ''; open $file,$file or $error = $!; close $file; + if ($error) { + warn "$0: cannot read file $file - $error\n"; + next; + } + unless (-f $file or -d $file or -c $file or -S $file or -p $file) { + warn "$0: ignoring special file $file\n"; + next; + } + $maxlen = length $file if $maxlen < length $file; + # printf "%s\r",substr("scanning $file".(" " x 255),0,$maxlen+9) if -t STDOUT; + # print $B."scanning $file\n".$N if -t STDOUT and not $opt_l||$opt_L; + if ($opt_r and -d $file) { + $found += grepd($file); + next; + } + # next if -z $file; # Achtung: special files unter /proc sind "empty" ! + # $type = `file -L $file`; + # if ($type =~ /text/i and open F,$file or open F,"strings $file|") { + $fileq = quotemeta $file; + if (-T $file) { + open $file,$file; + # warn "$file\n"; + } else { + if ($file =~ /\.bz2$/) { + open $file,"bunzip2 <$fileq|"; + # warn "gunzip <$file|\n"; + } elsif ($file =~ /\.gz$/) { + open $file,"gunzip <$fileq|"; + # warn "gunzip <$file|\n"; + } else { + open $file,"strings -a -n $opt_S $fileq|"; + # warn "strings -n $opt_S $file|\n"; + } + } + if (fileno $file) { + $found += grepf($file,$file); + close $file; + } else { + warn "$0: cannot open $file - $!\n"; + next; + } + } + # print " " x ($maxlen+9),"\r" if -t STDOUT; + } else { + $found = grepf(STDIN); + } +} + +sub grepd { + my $dir = shift; + my $file; + my $found = 0; + + opendir $dir,$dir or return; + while (defined($file = readdir $dir)) { + next if $file eq '.' or $file eq '..'; + if (not ${'opt_~'} and $file =~ /~$|^#[^\/]*#$/) { + # warn "$0: ignoring $dir/$file\n"; + next; + } + $file = "$dir/$file"; + next unless -r $file; + if (-d $file and not -l $file) { + $found += grepd($file); + next; + } + next unless -f $file or -c $file or -S $file or -p $file or -z $file; + $fileq = quotemeta $file; + if (-T $file and open $file,$file or + open $file,"strings -a -n $opt_S $fileq|") { + $found += grepf($file,$file); + close $file; + } + } + closedir $dir; + return $found; +} + + +sub grepf { + my $F = shift; + my $file = shift; + my $found = 0; + my ($n,$l,$c); + + warn $B."scanning $file".$N."\n" if -t STDOUT and $opt_s; + + while (<$F>) { + $_ .= "\n" unless /\n$/; + if ($opt_M) { + if ($mail and (/^From / or eof $F)) { + my $__ = $_; + $_ = $mail; + $mail = $__; + } else { + $mail .= $_; + next; + } + } + $l++; + $n = 0; + if ($opt_C) { + for (my $i=$opt_C;$i;$i--) { + $C{$i} = $C{$i-1} if defined $C{$i-1}; + } + $C{0} = [$l,$_]; + } + if ($opt_e) { + if ($opt_v) { + next if &$egrep; + } else { + unless (&$egrep) { + if ($opt_C and $c) { + print "$l:" if $opt_n; + print; + $L{$l} = $l; + $c--; + } + next; + } + } + $n++; + } else { + if ($opt_v) { + # print ">>>$_" if $opt_i and /$exp/oi or /$exp/o; + if ($opt_Q) { + next if /$exp/m; + } else { + next if /$exp/om; + } + $n++; + } else { + if ($opt_c) { + if ($opt_Q) { $n++ while /$exp/mg } + else { $n++ while /$exp/omg } + } else { + if ($opt_o) { + my $m = ''; + while (s/($exp)//) { + $n++; + $m .= "$1\n"; + } + $_ = $m; + } elsif ($opt_Q) { + $n += s/($exp)/$B$1$N/mg; + } else { + $n += s/($exp)/$B$1$N/omg; + } + } + } + } + unless ($n) { + if ($opt_C and $c) { + print "$l:" if $opt_n; + print; + $L{$l} = $l; + $c--; + } + next; + } + $found += $n; + # print " " x ($maxlen+9),"\r" if -t STDOUT and $found==1; + next if $opt_c; + last if $opt_l or $opt_L; + if ($file and not $opt_s) { + print "\n$B$file$N:\n"; + $file = ''; + } + if ($opt_x and $n) { + if ($opt_i) { s/($opt_x)/$B$1$N/ogi } + else { s/($opt_x)/$B$1$N/og } + } + for (my $i=$opt_C;$i;$i--) { + if (defined $C{$i}) { + my ($ln,$ls) = @{$C{$i}}; + unless (defined $L{$ln}) { + $L{$ln} = $ln; + print "$ln:" if $opt_n; + print $ls; + } + } + } + print "$l:" if $opt_n; + print; + $L{$l} = $l; + $c = $opt_C; + } + + if ($opt_c) { + print "$file:" if @ARGV>1; + print "$found\n"; + } else { + print "$file\n" if $opt_l and $found or $opt_L and not $found; + } + return $found; +} diff --git a/bin/l b/bin/l index 1389931..c7d7667 100755 --- a/bin/l +++ b/bin/l @@ -1,10 +1,10 @@ #!/usr/bin/perl -w # -# l / ll / lf / llf - substitute of the classic ls command +# l / ll / lf / llf - better replacement of the classic ls command # # Author: Ulli Horlacher # -# Copyright: GNU General Public License +# Copyright: Perl Artistic License use Cwd qw'abs_path'; use File::Basename; @@ -22,31 +22,24 @@ $ENV{LC_CTYPE} = 'C'; # parse CLI arguments $opt_l = $opt_i = $opt_t = $opt_s = $opt_a = $opt_r = $opt_d = $opt_n = 0; $opt_L = $opt_N = $opt_c = $opt_u = $opt_S = $opt_R = $opt_z = $opt_h = 0; -$opt_U = $opt_x = 0; -${'opt_*'} = ${'opt_?'} = 0; +$opt_U = $opt_x = $opt_E = 0; +${'opt_*'} = 0; $opt_m = $opt_f = $opt_F = $opt_D = ''; -&usage if !getopts('hdnlLNitcuarsxUSRz*?m:f:D:F:') || $opt_h; +getopts('hdnlLNitcuarsxUSREz*m:f:D:F:') or usage(1); +usage(0) if $opt_h; $opt_z = 1 unless $opt_R; $opt_l = 1 if $0 eq 'll'; $opt_l = $opt_i = $opt_a = $opt_S = 1 if $0 eq 'lll'; +&examples if $opt_E; if ($0 eq 'lf' or $0 eq 'llf') { - unless ($opt_F) { - $opt_F = shift; - unless (length $opt_F) { - print "find regexp: "; - chomp($opt_F = ||''); - } - } - $opt_l = $0 if $0 eq 'llf'; - $opt_F = '.' unless length $opt_F; - $opt_R = $opt_F; + $opt_F ||= shift or usage(1); + $opt_R ||= scalar(@ARGV) || ($opt_F eq '.'); + $opt_l ||= $0 eq 'llf'; } $postsort = $opt_t||$opt_s; $postproc = $postsort||$opt_z; -&examples if ${'opt_?'}; - # mark for squeeze operation $z = $opt_z ? "\0" : ''; @@ -551,14 +544,17 @@ sub fmatch { sub usage { + my $status = shift; my $opts = '[-lastcuidnrzLRxNS*] [-f format] [-D X:Y]'; + local *OUT = $status ? *STDERR : *STDOUT; + if ($0 ne 'lf') { - print "usage: $0 $opts [-F regexp] [file...]\n"; + print OUT "usage: $0 $opts [-F regexp] [file...]\n"; } $opts =~ s/R//; - print "usage: lf $opts regexp [directory...]\n"; - print </dev/null`; if ($log = $log[-1] and open $log,$log) { - # binmode($log,":encoding(UTF-8)"); + binmode($log,":encoding(UTF-8)"); while (<$log>) { s/\r//; if (/^Content-Disposition:.*name="FILE".*filename="(.+)"/i) { diff --git a/bin/sexsend b/bin/sexsend index ff3f1ed..d9fe821 100755 --- a/bin/sexsend +++ b/bin/sexsend @@ -19,7 +19,8 @@ use constant M => 2**20; eval 'use Net::INET6Glue::INET_is_INET6'; -our $version = 20150826; +our $version = 20160104; +our $DEBUG = $ENV{DEBUG}; my %SSL = (SSL_version => 'TLSv1'); my $sigpipe; @@ -142,6 +143,8 @@ if ($0 eq 'sexxx') { } } elsif ($0 eq 'sexget' or $0 eq 'fuckme') { + + $opt_g = 0; getopts('hgvVdu:') or die $usage; die $usage if $opt_h; @@ -175,7 +178,7 @@ if ($0 eq 'sexxx') { } else { # sexsend - $opt_g = 1; + $opt_g = 0; getopts('hguvqVTt:') or die $usage; die $usage if $opt_h; @@ -605,15 +608,9 @@ sub serverconnect { my $connect = "CONNECT $server:$port HTTP/1.1"; local $_; - if ($opt_v and $port == 443 and %SSL) { - foreach my $v (keys %SSL) { - printf "%s => %s\n",$v,$SSL{$v}; - } - } - if ($proxy) { tcpconnect(split(':',$proxy)); - if ($port == 443) { + if ($https) { printf "--> %s\n",$connect if $opt_v; nvtsend($connect,""); $_ = <$SH>; @@ -622,14 +619,13 @@ sub serverconnect { unless (/^HTTP.1.. 200/) { die "$0: proxy error : $_"; } - eval "use IO::Socket::SSL"; - die "$0: cannot load IO::Socket::SSL\n" if $@; + &enable_ssl; $SH = IO::Socket::SSL->start_SSL($SH,%SSL); } } else { tcpconnect($server,$port); } -# if ($port == 443 and $opt_v) { +# if ($https and $opt_v) { # printf "%s\n",$SH->get_cipher(); # } } @@ -644,10 +640,9 @@ sub tcpconnect { undef $SH; } - if ($port == 443) { + if ($https) { # eval "use IO::Socket::SSL qw(debug3)"; - eval "use IO::Socket::SSL"; - die "$0: cannot load IO::Socket::SSL\n" if $@; + &enable_ssl; $SH = IO::Socket::SSL->new( PeerAddr => $server, PeerPort => $port, @@ -664,6 +659,7 @@ sub tcpconnect { if ($SH) { autoflush $SH 1; + binmode $SH; } else { die "$0: cannot connect $server:$port - $@\n"; } @@ -672,6 +668,18 @@ sub tcpconnect { } +sub enable_ssl { + eval "use IO::Socket::SSL"; + die "$0: cannot load IO::Socket::SSL\n" if $@; + eval '$SSL{SSL_verify_mode} = 0 if Net::SSLeay::SSLeay() <= 9470143'; + if ($opt_v) { + foreach my $v (keys %SSL) { + printf "%s => %s\n",$v,$SSL{$v}; + } + } +} + + sub sendheader { my $sp = shift; my @head = @_; @@ -708,6 +716,18 @@ sub nvtsend { } +sub quote { + local $_ = shift; + s/([^\w\@\/%^,.=+_:+-])/\\$1/g; + return $_; +} + + +sub debug { + print "## DEBUG: @_\n" if $DEBUG; +} + + # from MIME::Base64::Perl sub encode_b64 { my $res = ""; diff --git a/cgi-bin/foc b/cgi-bin/foc index daf83f3..7a180a6 100755 --- a/cgi-bin/foc +++ b/cgi-bin/foc @@ -7,6 +7,7 @@ BEGIN { ($ENV{PERLINIT}||'') =~ /(.+)/s and eval $1 } +use utf8; use Fcntl qw(:flock); use Digest::MD5 qw(md5_hex); @@ -85,7 +86,15 @@ if ($user and $id) { # authorized login URL my $url = "$ENV{PROTO}://$ENV{HTTP_HOST}/fup/".b64("from=$user&id=$id"); pq(qq( - '

for user $user

' + '' + '

for user $user

' '' )); ($quota,$du) = check_sender_quota($user); @@ -119,7 +128,7 @@ if ($user and $id) { ' ' ' ' ' ' - ' Change your auth-ID to' + ' Change your auth-ID to' ' ' ' ' )); diff --git a/cgi-bin/fop b/cgi-bin/fop index fb37261..dec3abc 100755 --- a/cgi-bin/fop +++ b/cgi-bin/fop @@ -7,6 +7,7 @@ BEGIN { ($ENV{PERLINIT}||'') =~ /(.+)/s and eval $1 } +use utf8; use Fcntl qw':flock :seek'; use Cwd qw'abs_path'; use File::Basename; @@ -552,19 +553,18 @@ if (-f $data) { and not($dkey and ($ENV{HTTP_COOKIE}||'') =~ /dkey=$dkey/) and open $file,'<',"$file/download") { - $_ = <$file> || ''; + my $d1 = <$file> || ''; # first download + chomp $d1; close $file; - chomp; if ($ra) { # allow downloads from same ip - $_ = '' if /\Q$ra/; + $d1 = '' if $d1 =~ /\Q$ra/; # allow downloads from sender ip - $_ = '' if (readlink("$file/ip")||'') eq $ra; + $d1 = '' if (readlink("$file/ip")||'') eq $ra; } - if ($_) { - s/(.+) ([\w.:]+)$/by $2 at $1/; + if ($d1 and $d1 =~ s/(.+) ([\w.:]+)$/$2 at $1/) { $file = filename($file); - http_die("$file has already been downloaded $_"); + http_die("$file has already been downloaded by $d1"); } } $sb = sendfile($file,$seek,$stop); diff --git a/cgi-bin/fuc b/cgi-bin/fuc index 661c897..4d7ee3c 100755 --- a/cgi-bin/fuc +++ b/cgi-bin/fuc @@ -8,6 +8,7 @@ BEGIN { ($ENV{PERLINIT}||'') =~ /(.+)/s and eval $1 } +use utf8; use Fcntl qw(:flock); use Digest::MD5 qw(md5_hex); @@ -74,7 +75,7 @@ foreach my $v (keys %PARAM) { $v =~ /^group$/i ? $group = checkchars('group',$vv): $v =~ /^ab$/i ? $ab = $vv: $v =~ /^gm$/i ? $gm = $vv: - $v =~ /^show$/i ? $tools = checkchars('parameter',$vv): + $v =~ /^show$/i ? $show = checkchars('parameter',$vv): $ESAC; } @@ -87,6 +88,30 @@ $user .= '@'.$mdomain if $mdomain and $user !~ /@/; $nomail = $comment if $comment =~ /NOMAIL|!#!/; +if ($show and $show eq 'tools') { + nvt_print( + "HTTP/1.1 302 Found", + "Location: /tools.html", + 'Expires: 0', + 'Content-Length: 0', + '' + ); + &reexec; + + if (open $tools,"$docdir/tools.html") { + while (<$tools>) { + while (/\$([\w_]+)\$/) { + my $var = $1; + my $env = $ENV{$var} || ''; + s/\$$var\$/$env/g; + }; + print; + } + } + exit; +} + + if ($akey) { # sid is not set with web browser @@ -154,7 +179,7 @@ if ($user and $id) { # empty POST? ==> back to foc if ($ENV{REQUEST_METHOD} eq 'POST' and not - ($subuser or $notify or $nid or $ssid or $group or $ab or $gm or $tools + ($subuser or $notify or $nid or $ssid or $group or $ab or $gm or $disclaimer or $encryption or $pubkey)) { nvt_print( @@ -181,31 +206,6 @@ if ($gm and not $group) { exit; } -if ($tools) { - pq(qq( - 'To use one of the following F*EX clients you must configure them after' - 'download:' - '

' - '

' - ' ' - ' ' - ' ' - ' ' - '
F*EX server:$ENV{PROTO}://$ENV{HTTP_HOST}
Proxy:(your web proxy address, may be empty)
User:$user
Auth-ID:$id
' - )); - if (open $tools,"$docdir/tools.html") { - while (<$tools>) { - while (/\$([\w_]+)\$/) { - my $var = $1; - my $env = $ENV{$var} || ''; - s/\$$var\$/$env/g; - }; - print; - } - } - exit; -} - if ($group) { &handle_group; } @@ -924,7 +924,7 @@ sub notify_groupmember { '' 'to upload files to F*EX group "$group"' '' - 'See http://$ENV{HTTP_HOST}/ for more information about F*EX.' + 'See http://$ENV{HTTP_HOST}/index.html for more information about F*EX.' '' 'Questions? ==> F*EX admin: $admin' )); diff --git a/cgi-bin/fup b/cgi-bin/fup index 97624a0..7d222f9 100755 --- a/cgi-bin/fup +++ b/cgi-bin/fup @@ -10,6 +10,7 @@ BEGIN { ($ENV{PERLINIT}||'') =~ /(.+)/s and eval $1 } +use utf8; use Encode; use Fcntl qw':flock :seek :mode'; use IO::Handle; @@ -151,7 +152,7 @@ if ($from =~ /^anonymous@/ and $id = $rid = $anonymous = 'anonymous'; if ($to =~ /^anonymous/) { @to = ($to); - $autodelete{$to} = $autodelete = 'NO'; + $autodelete{$to} = $autodelete = $specific{'autodelete'}||'NO'; } $nomail = $anonymous; } @@ -199,10 +200,9 @@ if ($from and $id and not ($gkey or $skey or $public or $okey)) { # set akey link for HTTP sessions # (need original id for consistant non-moving akey) if (-d $akeydir and open $idf,'<',"$from/@" and my $id = getline($idf)) { - $akey = untaint(md5_hex("$from:$id")); - mksymlink("$akeydir/$akey","../$from"); - # show URL from fexsend - if ($from eq $to and $comment eq '*') { + # akey for webbrowser or fexsend special + if (not $sid or ($from eq $to and ($comment eq '*')) or $command) { + $akey = untaint(md5_hex("$from:$id")); mksymlink("$akeydir/$akey","../$from"); } } @@ -403,14 +403,14 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { - int((time-mtime("$file/filename"))/$DS); if ($comment =~ /NOMAIL/ or (readlink "$to/\@NOTIFICATION"||'') =~ /^no/i) { - printf "%8s MB [%s d] %s/%s/%s\n", + printf "%8s MB (%2s d) %s/%s/%s\n", $size, $rkeep, $durl, $dkey, urlencode(basename($file)); } else { - printf "%8s MB [%s d] %s%s %s\n", + printf "%8s MB (%2s d) %s%s %s\n", $size, $rkeep, untaint("/fup?akey=$akey&dkey=$dkey&command=RENOTIFY"), @@ -469,9 +469,10 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { } my $rkeep = untaint(readlink "$file/keep"||$keep_default) - int((time-mtime("$file/filename"))/$DS); - printf "%8s MB [%s d] %s%s\n", + printf "%8s MB (%2s d) %s %s%s\n", $size, $rkeep, + stat("$file/download")?'+':'-', untaint("/fup?akey=$akey&dkey=$dkey&command=FORWARD"), $filename, $comment?qq( "$comment"):''; @@ -528,7 +529,7 @@ if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { $akey,$dkey; printf "[forward] ", $akey,$dkey; - printf "%8s MB (%s d) %s%s\n", + printf "%8s MB (%2s d) %s%s\n", $size,$rkeep,$url,$filename,$comment; } } @@ -796,7 +797,7 @@ unless ($file) { my @cookies; if ($logout and my $cookie = $ENV{HTTP_COOKIE}) { while ($cookie =~ s/(\w+key)=\w+//) { - push @cookies,"Set-Cookie: $1=; Max-Age=0; Discard"; + push @cookies,"Set-Cookie: $1=x; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT"; } } @@ -876,7 +877,7 @@ unless ($file) { ' ' ' ' ' ' - ' ' + ' ' '
sender: $from
sender: $from
recipient(s):' '
' )); @@ -908,6 +909,11 @@ unless ($file) { foreach my $rd (@local_rdomains) { print "*\@$rd\n"; } + } elsif (/^\@LOCAL_USERS/) { + foreach (glob "*/@") { + s:/.::; + print "$_\n"; + } } else { print "$_\n"; } @@ -948,14 +954,16 @@ unless ($file) { pq(qq( '


' '' - 'Warning: the recipient must not be a mailing list, because after' - 'download the file will be no more available!' + 'Warning: the recipient must not be a mailing list,' + 'because after download the file will be no more available!' '
' - 'Contact fexmaster' - 'if you want to fex to a mailing list,' + 'Contact fexmaster if you want to fex to a mailing list,' 'he can allow multiple downloads for specific addresses.' + '

' + 'Use a F*EX client if you want to send more than one file or resume an interrupted upload.' '' - )); + '

+ )); exit; } @@ -1052,7 +1060,7 @@ unless ($file) { pq(qq( ' ' ' ' - ' ' + ' ' )); if ($anonymous) { pq(qq( @@ -1185,7 +1193,7 @@ unless ($file) { pq(qq( '' '
sender:$from
sender:$from
' '
sender:' @@ -1538,11 +1546,18 @@ sub parse_request { # parse HTTP QUERY_STRING (parameter=value pairs) if ($qs) { foreach (split '&',$qs) { - if (s/^(\w+)=//) { - my $x = $1; + if (s/^(\w+)=(.*)//) { + my $p = uc($1); + my $v = $2; # decode URL-encoding - s/%([a-f0-9]{2})/chr(hex($1))/gie; - setparam($x,$_); + $v =~ s/%([a-f0-9]{2})/chr(hex($1))/gie; + setparam($p,$v); + if ($p eq 'AUTODELETE') { + $specific{'autodelete'} = $autodelete = $v; + } + if ($p eq 'KEEP' and /^\d+$/) { + $specific{'keep'} = $keep = $v; + } } } } @@ -1680,9 +1695,9 @@ sub parse_request { foreach my $address (split(",",$address)) { $address .= '@'.$mdomain if $mdomain and $address !~ /@/; push @{$ab{$alias}},$address; - $autodelete{$alias} = $autodelete; - $keep{$alias} = $keep; - $locale{$alias} = $locale; + $autodelete{$alias} = $autodelete if $autodelete; + $keep{$alias} = $keep if $keep; + $locale{$alias} = $locale if $locale; } } } @@ -1710,7 +1725,7 @@ sub parse_request { } elsif ($locale{$to}) { $locale{$address} = $locale{$to}; } else { - $locale{$address} = $locale ; + $locale{$address} = $::locale ; } unless ($locale{$address}) { $locale{$address} = $default_locale || 'english'; @@ -2056,7 +2071,7 @@ sub get_file { if ($from eq "@to") { # special "fex yourself" - mksymlink("$filed/autodelete",'NO'); + mksymlink("$filed/autodelete",$specific{'autodelete'}||'NO'); } else { $autodelete{$to} = $autodelete unless $autodelete{$to}; if ($autodelete{$to} =~ /^(DELAY|NO|\d+)$/i) { @@ -2320,6 +2335,9 @@ sub check_rr { $ar .= '|[^\@]+\@' . $rd; } $ar .= ')'; + } elsif (/^\@LOCAL_USERS/ and -s "$to/@") { + $allowed = 1; + last; } else { # allow wildcard *, but not regexps $ar = quotemeta $_; @@ -2375,11 +2393,14 @@ sub expand { sub forward { my $file = shift; my ($nfile,$to,$AB); - my ($filename); + my ($filename,$keep); my (%to); http_die("no file data for $file") unless -f "$file/data"; + $keep = $::keep||$keep_default; + if (my $mt = mtime("$file/data")) { $keep += int((time-$mt)/$DS) } + if (@to) { # check recipients restriction @@ -2413,11 +2434,11 @@ sub forward { } } + @to = keys %to; + http_header('200 OK'); print html_header($head); - @to = keys %to; - foreach my $to (my @loop = @to) { $to =~ s/:\w+=.*//; # remove options from address $nfile = $file; @@ -2444,15 +2465,15 @@ sub forward { close $comment; } if ($autodelete =~ /^(DELAY|NO|\d+)$/i) { - symlink($autodelete,"$nfile/autodelete"); - } - symlink($keep||$keep_default, "$nfile/keep"); - copy("$file/id", "$nfile/id"); - copy("$file/ip", "$nfile/ip"); - copy("$file/speed", "$nfile/speed"); - copy("$file/replyto", "$nfile/replyto"); - $filename = copy("$file/filename", "$nfile/filename"); - link "$file/data", "$nfile/data" + symlink $autodelete,"$nfile/autodelete"; + } + symlink $keep, "$nfile/keep"; + copy("$file/id", "$nfile/id"); + copy("$file/ip", "$nfile/ip"); + copy("$file/speed", "$nfile/speed"); + copy("$file/replyto", "$nfile/replyto"); + $filename = copy("$file/filename", "$nfile/filename"); + link "$file/data", "$nfile/data" or die http_die("cannot create $nfile/data - $!"); unless ($dkey = readlink("$nfile/dkey") and -l "$dkeydir/$dkey") { $dkey = randstring(8); @@ -2622,6 +2643,7 @@ sub setparam { } elsif ($v eq 'FEXYOURSELF') { $submit = $vv; @to = ($from); + $specific{'autodelete'} = $autodelete = 'no'; } elsif ($v eq 'TO') { # extract AUTODELETE and KEEP options if ($vv =~ s/[\s,]+AUTODELETE=(\w+)//i) { @@ -2637,9 +2659,15 @@ sub setparam { if ($from) { if ($to eq '.') { $to = $from; + unless ($specific{'autodelete'}) { + $specific{'autodelete'} = $autodelete = 'no'; + } } if ($to eq '//') { $to = $from; + unless ($specific{'autodelete'}) { + $specific{'autodelete'} = $autodelete = 'no'; + } $comment = '//'; } } diff --git a/cgi-bin/fur b/cgi-bin/fur index ffccca6..5db49c4 100755 --- a/cgi-bin/fur +++ b/cgi-bin/fur @@ -7,6 +7,7 @@ BEGIN { ($ENV{PERLINIT}||'') =~ /(.+)/s and eval $1 } +use utf8; use Fcntl qw(:flock :seek :mode); # import from fex.ph diff --git a/cgi-bin/pup b/cgi-bin/pup index 0d00509..a944995 100755 --- a/cgi-bin/pup +++ b/cgi-bin/pup @@ -7,6 +7,8 @@ BEGIN { ($ENV{PERLINIT}||'') =~ /(.+)/s and eval $1 } +use utf8; + # add fex lib (our $FEXLIB) = $ENV{FEXLIB} =~ /(.+)/; die "$0: no $FEXLIB\n" unless -d $FEXLIB; diff --git a/cgi-bin/rup b/cgi-bin/rup index 5b2d4e0..0a4d0b0 100755 --- a/cgi-bin/rup +++ b/cgi-bin/rup @@ -7,6 +7,7 @@ BEGIN { ($ENV{PERLINIT}||'') =~ /(.+)/s and eval $1 } +use utf8; use Fcntl qw(:flock :seek :mode); use Digest::MD5 qw(md5_hex); diff --git a/doc/Changes b/doc/Changes index 29809c0..e95c668 100644 --- a/doc/Changes +++ b/doc/Changes @@ -1,13 +1,41 @@ +2015-12-29 fexsend: added search pattern argument to option -l +2015-12-25 fup: added +/- download flag in LIST command output +2015-12-18 fup: allow AUTODELETE and KEEP parameter for anonymous user and + sender=recipient +2015-12-01 hint for fexget and fexit in notification email +2015-12-01 fixed bug notification email ignores (sometimes) locale +2015-11-27 fixed bug first line in encrypted notification emails gets lost +2015-11-21 fixed bad UTF8 encoding for french spanish czech galician +2015-11-10 fexget: fixed bug timeout for big files on slow storage +2015-10-14 install: fixed bug missing fex group +2015-10-09 fexsend: better support for reverse proxy (closing connection) +2015-10-06 fexsend: abort if file has been modified while uploading +2015-10-04 fup: when forwarding a file, keep time is calculated for today, + not for upload day +2015-09-29 fexget: fixed bug no https download +2015-09-26 fex_cleanup: fixed bug send no locale reactivation.txt +2015-09-21 fexget: fixed bug resume download on aborted storage test file + leads to corrupted file +2015-09-17 changed LIST output formating (more consistent) +2015-09-17 fexget: fixed bug cannot forward a file that was received from myself +2015-09-16 fexsend: more robust fileID (md5sum of metadata) +2015-09-14 fup: show autodelete=no if sender == recipient +2015-09-11 moved comment to top in notification email +2015-09-08 fup,fuc: fixed bug link to F*EX clients tools.html broken (loop) +2015-09-06 fexsend: added ditto-zip for MacOSX +2015-09-02 fexsend: added MacOSX support +2015-09-01 fac: added option -Rl for local users +2015-09-01 fup: added local users restriction option 2015-08-26 fur: fixed bug no registration possible 2015-08-25 fup: fixed bug uninitialized value when called by sup.html - fac: option -q quota=0 means use default quota +2015-08-25 fac: option -q quota=0 means use default quota 2015-08-24 better detection of UTF8 in comment 2015-08-14 fixed bug "Wide character in print at (...)/fex.pp" in function pq() 2015-07-29 install: fixed various bugs 2015-07-15 dop: symbolic links generate a HTTP 302 (temporarily redirection) instead of a HTTP 301 (permanently redirection) response 2015-06-16 fexsend: fixed bug hangs with https - new fex.ph config variable @mailing_lists +2015-06-16 new fex.ph config variable @mailing_lists 2015-06-15 fup: always display fur link, if @local_domains is defined 2015-06-10 fexsrv: fixed warning with https and SIGCHLD 2015-05-16 fexsrv/dop: added active and passive redirect support @@ -24,7 +52,7 @@ 2015-03-08 fup: fixed bug uninitialized value $address if alias address is used twice 2015-03-07 disallow email addresses starting with "-" - fex_cleanup: do not terminate on sendmail error +2015-03-07 fex_cleanup: do not terminate on sendmail error 2015-03-01 no file name in email subject if notification is encrypted 2015-02-28 fexsrv: restrict HTTP header to 64 kB ($bs) and POST (not fup) to 128 MB @@ -34,25 +62,25 @@ 2015-02-18 fuc: fixed bug no gpg usage help 2015-02-17 fexsend: check SSLeay version and adjust SSL_verify_mode 2015-02-16 fup: save upload URL in spool - in notification+reminder emails use same protocol for download URL +2015-02-16 in notification+reminder emails use same protocol for download URL like in upload 2015-02-08 rup: fixed various bugs (not working at all) 2015-02-05 fup: fixed bug cannot send to groups 2015-01-27 fup: set autodelete=no if sender == recipient (use case: provide download link for mailing lists) - new fex.ph config variable $fex_yourself (default yes) +2015-01-27 new fex.ph config variable $fex_yourself (default yes) 2015-01-25 fexsend: fixed bug cannot forward a file name with "&" 2015-01-21 main user is always first member of a new group - substituted CGI::Carp with web error handler via PERLINIT environment +2015-01-21 substituted CGI::Carp with web error handler via PERLINIT environment 2015-01-17 new fex.ph config variable $mail_authid (default yes) 2015-01-16 fixed bug no notfication for still existing file (overwrite) 2015-01-15 fixed bug no locale reminder notfication - fixed bug wrong result for recipients with NOTIFICATION=no +2015-01-15 fixed bug wrong result for recipients with NOTIFICATION=no 2015-01-13 fexsend: added option -N resend notification email - resending notification email deletes download ip restriction - fup: fixed bug sending to groups broken +2015-01-13 resending notification email deletes download ip restriction +2015-01-13 fup: fixed bug sending to groups broken 2015-01-10 fexsend: added option -S show server/user settings - fup: added command LISTSETTINGS +2015-01-10 fup: added command LISTSETTINGS 2015-01-09 foc: added save-or-display (MIME) option for download 2015-01-04 fexsend: fixed bug dies too early on multiple files and one file has been already transfered @@ -60,27 +88,27 @@ DEFAULT:!3DES:!MD5 2014-12-24 fexget,fexsend,sexsend: evaluate environment variables SSLVERIFY SSLVERSION SSLCAPATH SSLCAFILE SSLCIPHERLIST - fexget,fexsend,sexsend: use TLS, not SSL +2014-12-24 fexget,fexsend,sexsend: use TLS, not SSL 2014-12-23 fexsend: $HOME/.fex/config with $opt_* and %alias variables - fexget: $HOME/.fex/config with $opt_* and %autoview variables +2014-12-23 fexget: $HOME/.fex/config with $opt_* and %autoview variables 2014-12-19 fur: fixed bug race condition with fex_cleanup (external->internal) 2014-12-17 install/update: fixed bug some spool files are owned by user root 2014-12-16 fexsrv: fixed bug handling of User-Agent FDM 2014-12-09 added l ll lf to distribution - fexwall: also mail to sub and group users +2014-12-09 fexwall: also mail to sub and group users 2014-12-03 fup: remove file after upload if restricted user has set NOMAIL - fup: fixed bug wrong message "user notified" if NOMAIL +2014-12-03 fup: fixed bug wrong message "user notified" if NOMAIL 2014-12-02 fup: also check recipient restrictions on command CHECKRECIPIENT 2014-11-24 fexget: autoview gif jpg png tif after download 2014-11-20 count unfinished upload size into quota, too - fixed bug wrong quota calculation on SysV UNIX like Solaris +2014-11-20 fixed bug wrong quota calculation on SysV UNIX like Solaris 2014-11-18 fexsend: added environment variables SSLVERIFY SSLCAPATH SSLCAFILE 2014-11-18 dop: added HTTP basic authentication for htdoc directory with .htauth file 2014-11-14 ignore @forbidden_recipients if $SPOOL/$USER exists (admin has created user) 2014-11-11 fup: fixed bug groups from other users in address book selection - fup: added useragent to $SPOOL/$TO/$FROM/$FILE/ +2014-11-11 fup: added useragent to $SPOOL/$TO/$FROM/$FILE/ 2014-11-10 fup: present locales in recipient query form, too 2014-11-07 FAQ: added text anchor URLs 2014-11-03 added missing fexget fexsend sexget sexsend for tools.html @@ -94,16 +122,16 @@ 2014-09-01 fup: upload status bar waits longer, until $timeout 2014-08-27 fex_cleanup: use wget for new release dedection 2014-08-18 fexsend: workaround for stunnel bug (options -s and -g) - fex_cleanup,fexsend: always restrict permissions on fexsend id-file +2014-08-18 fex_cleanup,fexsend: always restrict permissions on fexsend id-file 2014-08-16 fac: added options -P and -E (more examples) 2014-08-15 install: fixed bug wrong owner in spool - fex_cleanup: do not terminate on error, but print warning +2014-08-15 fex_cleanup: do not terminate on error, but print warning 2014-08-13 fexsrv,fexsend,fexget: reenabled IPv6 support 2014-08-10 fac: added option -/ to set new admin 2014-08-08 moved $admin_pw from fex.ph to auth-ID for user $admin - fex_cleanup: fixed bug in notify_newrelease - fac(CGI): switched from HTTP basic authorization to auth-ID/akey - fexsend: always use CHECKRECIPIENT, not only for aliases +2014-08-08 fex_cleanup: fixed bug in notify_newrelease +2014-08-08 fac(CGI): switched from HTTP basic authorization to auth-ID/akey +2014-08-08 fexsend: always use CHECKRECIPIENT, not only for aliases 2014-08-07 dop: generate on-the-fly gzipped documents if requested 2014-08-06 fixed bug install script dysfunctional (permission, hostname) 2014-07-25 reenabled vhost support @@ -144,25 +172,25 @@ 2013-09-23 fexsend: fixed bug option -c sends uncompressed file 2013-09-19 sub and group users have the same quota amount like their main user 2013-09-18 fixed bug permission denied for locale htdocs - anonymous user now with hostname domain instead of mail domain +2013-09-18 anonymous user now with hostname domain instead of mail domain 2013-09-17 dop: set locale cookie, too 2013-09-15 foc: added "Change the disclaimer" option 2013-09-12 fup: expand domainless address with server hostname if such a user exists (needed for fbm/nettest) 2013-09-09 new FAQ design (questions first, then Q+A) 2013-09-04 fac: modify $hostname when vhost fex.ph is created - fuc: recognize comment=NOMAIL +2013-09-04 fuc: recognize comment=NOMAIL 2013-08-26 fexsend: always show download URL if recipient is "." 2013-08-20 fup,fop: fixed bug no DELETE and RESUME for fexmail and anonymous users (because of storage swap) 2013-08-18 sexsend: fixed bug data corruption when using https - fop,fup: fixed bug bad file locking when using multiple recipients - fexsend: fixed bug hangs on server error when sending archive +2013-08-18 fop,fup: fixed bug bad file locking when using multiple recipients +2013-08-18 fexsend: fixed bug hangs on server error when sending archive 2013-08-17 fixed bug $sender_from ignored - fup,foc: added notification email resending on user request +2013-08-17 fup,foc: added notification email resending on user request 2013-08-16 fac: fixed bug wrong output order for option -l 2013-08-14 fop: fixed bug no multiple downloads for fexmail - fac: added option -M for resending notification emails +2013-08-14 fac: added option -M for resending notification emails 2013-08-09 afex: fixed bug ID for input 2013-08-06 fexsrv: always includes "Server: fexsrv" in HTTP reply fexsend: terminates if no fexsrv HTTP reply @@ -175,17 +203,17 @@ 2013-07-18 fup,fexsend: use header Content-Location instead of Content-Type for file linking 2013-07-15 fup: modifying keep references actual time, not upload date - fexsend: fixed bug no feedback on option -x -k (modify keep) +2013-07-15 fexsend: fixed bug no feedback on option -x -k (modify keep) 2013-07-13 fup: fixed bug user specific keep and autodelete defaults are ignored 2013-07-12 fup,fop: added file link support - fexsend: added option -/ for file linking +2013-07-12 fexsend: added option -/ for file linking 2013-07-09 fexget: added option -P proxy:port 2013-06-28 new all-in-one FAQ 2013-06-27 fup: to/from storage swap for fexmail and anonymous users - fup: anonymous recipient with random number +2013-06-27 fup: anonymous recipient with random number 2013-06-26 fop: allow multiple downloads from same ip - fup,fac: extended "fex yourself" support - added sup.html +2013-06-26 fup,fac: extended "fex yourself" support +2013-06-26 added sup.html 2013-06-22 fop,fexsend: Location output for fexmail for already transfered files 2013-06-19 fexget: fixed bug cannot download MIME file 2013-06-15 fex.ph: new config variable $notify_newrelease checks @@ -197,19 +225,19 @@ (with hooks in fop,fop.fuc,foc,fur) 2013-06-03 fuc: fixed bug user can modify his auth-ID to an illegal value 2013-05-30 install: force creation of $admin_pw - fex_cleanup: fixed bug wrong fexadmin fexid for reactivation emails +2013-05-30 fex_cleanup: fixed bug wrong fexadmin fexid for reactivation emails 2013-05-25 added afex and asex to distribution 2013-05-23 dop: fixed bug no output on file.stream 2013-05-22 install script installs as user fex (and not as root) 2013-05-19 security patch: config variable @local_rhosts restricts download of files from new external users to specific ip ranges - use and syntax in notification email header - added support for $max_fail_handler() +2013-05-19 use and syntax in notification email header +2013-05-19 added support for $max_fail_handler() 2013-05-18 fac: fixed bug option -rd does not work - fac: added option -R +2013-05-18 fac: added option -R 2013-05-16 fop: fexmail support (multiple downloads allowed) 2013-05-09 fup: fixed bug anonymous only works if $mdomain is defined - fop: fixed bug anonymous only works if recipient host is in +2013-05-09 fop: fixed bug anonymous only works if recipient host is in @anonymous_upload list 2013-05-07 fup: fixed bug multiple Location HTTP headers generate an error with some web browsers @@ -219,10 +247,10 @@ 2013-04-05 fexsend: fixed bug server timeout when sending huge ZIPs 2013-02-20 fac: added -m maintenance mode 2013-02-17 fup: fixed bug stored comment in spool not in UTF8 - fop: fixed bug file deletion also deletes fop.log +2013-02-17 fop: fixed bug file deletion also deletes fop.log 2013-02-16 fur,fex.ph: allow "*" for local domains self registration - fex.ph: new config variable @registration_hosts - fex.ph: new config variable @admin_hosts +2013-02-16 fex.ph: new config variable @registration_hosts + new config variable @admin_hosts 2013-02-11 fur: fixed bug insecure dependency with exuser 2013-01-31 receiving of reminder emails is user configurable 2013-01-24 fup: decode UTF8 comment @@ -243,32 +271,32 @@ 2012-11-08 fop: fixed bug cannot use "?" in file name with fexsend 2012-11-07 fixed security bug restricted user can redirect files 2012-11-06 fup: show download-URL after upload if sender = recipient - fup,fop,fac: added user up/download IP restriction by admin +2012-11-06 fup,fop,fac: added user up/download IP restriction by admin 2012-11-05 added HTTP Strict Transport Security (HSTS) if $force_https is set - fixed bug afex accessible via xkey from everywhere +2012-11-05 fixed bug afex accessible via xkey from everywhere 2012-11-02 fup: fixed bug one time upload URL gives "no recipient specified" error 2012-11-01 fup: fixed bug public upload always gives error 2012-10-16 fop,fup: added afex support - fup: accept recipients . and // +2012-10-16 fup: accept recipients . and // 2012-10-15 sex,sexsend: added anonymous mode (no auth-ID necessary) 2012-10-14 fop,fup: added support for fexsend anonymous mode 2012-10-11 fex.ph: added optional config variable $overwrite 2012-10-10 fup: anonymous upload with non-anonymous recipient 2012-09-30 fup: fixed bug groups not working any more (NOMAIL) 2012-09-19 fup: logout functions respects login CGI (or symlink) - foc: detailed/brief notification mail configuration +2012-09-19 foc: detailed/brief notification mail configuration 2012-09-18 fexsend: added options -. and -n - fup: added shortmail option in comment +2012-09-18 fup: added shortmail option in comment 2012-09-17 added mailmode configuration option in fex.ph - fup: shows download-URL if NOMAIL +2012-09-17 fup: shows download-URL if NOMAIL 2012-09-15 sex: public URL parameter may be in base64 format, too 2012-09-10 dop: added more security checks 2012-09-01 dop: added streaming document output 2012-08-30 sex: fixed bug second receiving client corrupts the stream 2012-08-26 Changed licence from AGPL to Perl Artistic 2012-08-21 schwuppdiwupp: error handling on network failures for Windows - schwuppdiwupp: removed Tk::FileSelect for Windows + removed Tk::FileSelect for Windows 2012-07-11 fop: fixed bug no multiple downloads for anonymous uploads 2012-07-10 fixed French, Spanish and Czech localization (code syntax) bugs 2012-07-09 fup: anonymous upload with modifyable keep option and multiple @@ -276,33 +304,33 @@ 2012-07-05 fexsrv: added camel easteregg 2012-07-02 fup: added optional anonymous upload with fex.ph variable @anonymous_upload - fup: fixed bug throttle 0 configuration is ignored +2012-07-02 fup: fixed bug throttle 0 configuration is ignored 2012-07-01 fexsend: optional argument '@' as files/recipients separator - fexsend: fixed bug notification email for recipient '.' + fixed bug notification email for recipient '.' 2012-06-21 dop: inside HTML documents: #include "file" 2012-06-06 fexget: new option -+ 2012-06-05 fexsend: new option -+ 2012-06-01 fup: show transfered size instead of total size in status window 2012-05-04 fexsrv: added bunny easteregg 2012-05-02 fexsrv: allow HTTP 1.0 with Range header (wget!) - fexsrv: disallow negative value in Range (client signed int bug) + disallow negative value in Range (client signed int bug) 2012-04-26 Changed licence from GPL to AGPL 2012-04-07 foc: check new address book for syntax errors 2012-04-06 foc: added comment field for new subuser information 2012-04-04 removed F*IX because of too many bugs and no maintainer any more 2012-03-05 fup: fixed bug shell wildcards in recipient address are expanded to known users from spool - fex.ph: added optional config variable @locales +2012-03-05 fex.ph: added optional config variable @locales 2012-03-01 dop: delivers MIME type text/plain if "?!" is appended to URL 2012-02-20 foc: show auth-ID after click on link 2012-02-07 fop: MIME-type text/html is no longer possible for security reasons 2012-02-04 added optional french localization 2012-02-03 fixed bug 0.0.0.0 not recognized as ip address - fex.ph: added optional config variable $keep_max +2012-02-03 fex.ph: added optional config variable $keep_max 2012-02-02 HTTP parameter filtering to prevent cross-site scripting attacks 2012-02-01 config variable @throttle may also contains ip addresses 2012-01-25 pup: locale selection in native language, default autodelete=no - fup: "send another file" with same keep and autodelete parameters +2012-01-25 fup: "send another file" with same keep and autodelete parameters 2012-01-17 fixed bug reactivation.txt in czech instead english 2012-01-06 fup: fixed bug show wrong remaining keep days 2012-01-02 fup.pl: fixed bug bad FAQ link @@ -324,48 +352,48 @@ 2011-09-07 fac(CGI): fixed bug infinitve loop in watch logfile 2011-09-06 fup,fac,fur: new additional login URL type: http://FEXSERVER/fup/B64ID - fup: show "or select from address book" only if there are entries +2011-09-06 fup: show "or select from address book" only if there are entries 2011-09-05 fexsrv: fixed bug locale cookie not fetched on http://cgi?parameter 2011-09-01 rup: fixed bug cannot find files (no more SID in akeys directory) 2011-08-30 fex.ph: new config variable @forbidden_recipients 2011-08-29 fexsend: accept file number for delete option -d, too - dop: fixed bug no text document output if external file command is +2011-08-29 dop: fixed bug no text document output if external file command is non-GNU 2011-08-26 added one time upload OKEY 2011-08-13 fex_cleanup: fixed bug comment missing in reminder email 2011-08-11 dop: #if ... #else ... #elseif ... #endif inside HTML documents - dop: show HTML sourcecode if "!" is appended to URL + show HTML sourcecode if "!" is appended to URL 2011-08-10 fex_cleanup: delete obsolete users, too, via fex.ph $account_expire new FAQ design (with Javascript/CSS) 2011-08-09 fup: show error on invalid SKEY or GKEY - fuc: fixed bug subuser and groupuser not lowercase forced - address book may also contain option locale= +2011-08-09 fuc: fixed bug subuser and groupuser not lowercase forced +2011-08-09 address book may also contain option locale= 2011-08-08 fex_cleanup: auto-expire user accounts with fex.ph variable $account_expire - fexsend,fup: allow forward with locale - dop: extra security check: files from lib and spool are not allowed +2011-08-08 fexsend,fup: allow forward with locale +2011-08-08 dop: extra security check: files from lib and spool are not allowed 2011-08-07 fup: subusers and groupusers can also select a locale - fup: if user selects a locale login, save it as default locale +2011-08-07 fup: if user selects a locale login, save it as default locale (does not affect fexsend and schwuppdiwupp) - notification emails come in default locale +2011-08-07 notification emails come in default locale 2011-08-03 fexsend: fixed bug uninitialized value when using chunked mode - fexsend: added undocumented option -F female mode + added undocumented option -F female mode 2011-07-31 fexsend: added option -s streaming data - fup: accept streaming data +2011-07-31 fup: accept streaming data 2011-07-30 fexsend: -a tar archives no longer use a intermediate transferfile, but send via pipe (streaming) - fexsend: fixed bug no resume on -a archives - fexsend: always ask server if file already has been uploaded - fup: more information on F*EX clients download and configuration +2011-07-30 fexsend: fixed bug no resume on -a archives +2011-07-30 fexsend: always ask server if file already has been uploaded +2011-07-30 fup: more information on F*EX clients download and configuration 2011-07-27 fup: if comment contains "!bcc!" then sender will get a bcc of notification email 2011-07-26 fexget: added option -X do not extract archive file - fexget: added option -a get all files - fexsrv: fixed bug uninitialized value when using a reverse proxy - fex_cleanup: fixed bug notify reminder email not localized +2011-07-26 fexget: added option -a get all files +2011-07-26 fexsrv: fixed bug uninitialized value when using a reverse proxy +2011-07-26 fex_cleanup: fixed bug notify reminder email not localized 2011-07-22 fac(CGI): fixed bug displaying < and & in logfiles - fac(CGI): added getting error.log - fop: allow multiple downloads from any client if sender = recipient +2011-07-22 fac(CGI): added getting error.log +2011-07-22 fop: allow multiple downloads from any client if sender = recipient 2011-07-16 added doc/reverse_proxy 2011-07-14 added optional czech localization 2011-07-01 FAQ.html reformated @@ -376,32 +404,32 @@ 2011-06-17 fixed bug $bcc is ignored 2011-06-16 fexsend,fexget: better reverse proxy support (always send Host header) - added optional galician localization +2011-06-16 added optional galician localization 2011-06-15 fup: fixed bug always keep_default days in notification email 2011-06-14 fexsend: transparent proxy detection (and support) - fixed bug $docdir ignored +2011-06-14 fixed bug $docdir ignored 2011-06-10 fex.ph: new config variable $bcc for notification emails 2011-06-09 set Reply-To in all notification emails - fup: fixed security bug everyone can upload files with empty auth-ID +2011-06-09 fup: fixed security bug everyone can upload files with empty auth-ID 2011-06-05 fup: fixed bug insecure dependency in printf on "forward file" 2011-06-03 fup,fop: added throttle bandwith limit option (fex.ph) 2011-06-02 fup: added bandwith limit option 2011-06-01 added PID and request-number to the logs - fex_cleanup: fixed bug no expire with AUTODELETE=NO +2011-06-01 fex_cleanup: fixed bug no expire with AUTODELETE=NO 2011-05-31 support for FEXLIB /usr/local/share/fex/lib /usr/share/fex/lib 2011-05-30 fup,fexsend: added option -x to modify file parameters 2011-05-29 fup,fexsend: forward files with new comment and keep time - rup: add mdomain to addresses without domain +2011-05-29 rup: add mdomain to addresses without domain 2011-05-18 fup: fixed bug restricted users can forward files to anybody 2011-05-17 fixed bug access problems with AKEYs: now use SID instead of SIP 2011-05-11 added helper script mksgkeys (regenerates missing SKEYs and GKEYs) 2011-05-10 fex_cleanup: cleanup ADDRESS_BOOK file upload - fex.ph,fex_cleanup: AUTODELETE=NUMBER ==> +2011-05-10 fex.ph,fex_cleanup: AUTODELETE=NUMBER ==> delete file on next NUMBER day after download 2011-05-09 fac,fup: added user specific autodelete default - fac,fex_cleanup: added user specific keep default +2011-05-09 fac,fex_cleanup: added user specific keep default 2011-04-27 fexsend: fixed bug archiv.zip not working on Windows - dop: added index function for htdoc directory with .htindex file +2011-04-27 dop: added index function for htdoc directory with .htindex file 2011-04-25 fexsend: better proxy support (non-persistent connections) 2011-04-24 xx: better ESXi support (heuristic guessing of tar format) 2011-04-22 sexsend: base64 support for $FEXID and $FEXXX @@ -415,59 +443,59 @@ 2011-02-24 dop: evaluate <> inside html documents 2011-02-21 fexsend,fup: added option fexsend -U show authorized (login) URL 2011-02-18 do not modify download URL protocol if $dkey is set in fex.ph - fac(CGI): fixed bug uninitialized value $server - URLs in notification emails are derived from config variable $durl +2011-02-18 fac(CGI): fixed bug uninitialized value $server +2011-02-18 URLs in notification emails are derived from config variable $durl 2011-02-17 fup: fixed bug access denied with SKEY 2011-02-08 fup,fop,fuc: fixed bug access problems with sip in AKEYs - fup: fixed bug no notification email for multiple recipients +2011-02-08 fup: fixed bug no notification email for multiple recipients 2011-02-07 fexsend,fop: do not send same file (filename and mtime) twice 2011-02-06 fup: fixed bug no notification email after first failed upload 2011-01-31 schwuppdiwupp: added ISO-8859-1 support 2011-01-30 schwuppdiwupp: added running camel 2011-01-28 schwuppdiwupp: added chunksize to proxy options - schwuppdiwupp: fixed bug timeout when using address book - fexsend: fixed bug chunksize 0 +2011-01-28 schwuppdiwupp: fixed bug timeout when using address book +2011-01-28 fexsend: fixed bug chunksize 0 2011-01-27 schwuppdiwupp: added advanced preferences Proxy and TMPDIR 2011-01-26 fex_cleanup: fixed bug uninitialized value in debuglog - fex_cleanup: added option -v - fexsend,fexget,sexsend: added option -V show version - schwuppdiwupp: added drag&drop support for windows - schwuppdiwupp: added 7zG support +2011-01-26 fex_cleanup: added option -v +2011-01-26 fexsend,fexget,sexsend: added option -V show version +2011-01-26 schwuppdiwupp: added drag&drop support for windows +2011-01-26 schwuppdiwupp: added 7zG support 2011-01-25 fuc: fixed bug cannot delete all subusers - schwuppdiwupp: fixed bug 7-zip not found - schwuppdiwupp: added drive letters in directory selection +2011-01-25 schwuppdiwupp: fixed bug 7-zip not found +2011-01-25 schwuppdiwupp: added drive letters in directory selection 2011-01-24 fop: IE bug workaround to store *.exe files 2011-01-18 schwuppdiwupp: added tar, zip and 7z container 2011-01-17 fexsend: fixed bug option -l not working with https URL 2011-01-16 fup: added 7zip hint in notification emails 2011-01-13 schwuppdiwupp: fixed bug no transfer at all when comment is set 2011-01-12 rup: added logging - rup: wrong recipient cannot download file, but will get an error - fac(CGI): fixed bug $server not declared +2011-01-12 rup: wrong recipient cannot download file, but will get an error +2011-01-12 fac(CGI): fixed bug $server not declared 2011-01-07 fexget: keep file permission in overwrite mode 2011-01-04 fex_cleanup: fixed bug autodelete after partial download 2010-12-26 fex_cleanup: fixed bug too early expire for forwarded files 2010-12-10 new config variable @public_recipients for new CGI pup - (public upload) - upload without auth-ID +2010-12-10 (public upload) - upload without auth-ID 2010-12-09 fex.ph,fur: new config variable @local_rdomain for self- registration of restricted external-to-internal users 2010-12-08 fup,foc: no access to foc for restricted users 2010-12-02 fup: if there is a cgi-bin/login it will be called on "logout" 2010-11-24 fex.ph: new config variable $default_locale - dop: auto-expires every document (to prevent browser caching) +2010-11-24 dop: auto-expires every document (to prevent browser caching) 2010-11-16 fexsrv: better error handling if CGI is not executable 2010-11-09 new SKEYs and GKEYs, because old ones could be not unique access for subuser only with SKEY access for groupuser only with GKEY 2010-11-07 fup,fuc: added GKEY - fexsend: SKEY or GKEY URLs can be recipients, too +2010-11-07 fexsend: SKEY or GKEY URLs can be recipients, too 2010-11-04 fexget: added (hidden) option -K 2010-11-03 fexsend: fixed bug proxy usage failed 2010-11-02 fop: fixed bug corrupted download with Internet Explorer 2010-10-25 fop,fup: better locking: no uploading is possible while a download is in progress for the same file 2010-10-24 fix,fop: fixed bug subuser not working (SKEY problem) - xx: added locking +2010-10-24 xx: added locking 2010-10-23 xx,fop: added xx :slot option (multiple storage slots) 2010-10-20 fup,fop,fexsend: fexsend for subuser with SKEY 2010-10-19 fup: expires *KEY cookies on logout @@ -476,44 +504,44 @@ 2010-09-27 fup: fixed bug missing Content-Type in upload status report 2010-09-20 fexsrv: IPv6 http support 2010-09-15 fac(CGI): fixed bug cannot delete and (re)create user - fac(CGI): fixed bug cannot create user who was a recipient +2010-09-15 fac(CGI): fixed bug cannot create user who was a recipient 2010-09-12 fexsend,fop: fixed bug resuming upload does not work with alias - fup: fixed bug resuming upload handles autodelete and keep +2010-09-12 fup: fixed bug resuming upload handles autodelete and keep parameters incorrectly 2010-09-07 fac(CGI): fixed bug not working if there is no user at all 2010-09-05 fop: extra parameter keep=days 2010-08-31 install: fixed bug wrong ownership for spool files 2010-08-25 perl 5.8 required - fexget: -s can write to named pipe or character special file +2010-08-25 fexget: -s can write to named pipe or character special file 2010-08-21 fop: $limited_download checks dkey cookie instead of client IP 2009-08-20 removed mma 2010-08-18 fex_cleanup: fixed bug not expiring 2010-08-17 fac: fixed bug accept users without domain - install: fixed bug empty $admin_pw +2010-08-17 install: fixed bug empty $admin_pw 2010-08-15 fex.ph: optional fix address $sender_from (instead of F*EX user) in notification email From 2010-08-14 added optional spanish localization 2010-08-12 fup: speedup 90% - fop: speedup 20% - fop: better fexget compatibility +2010-08-12 fop: speedup 20% +2010-08-12 fop: better fexget compatibility (close connection after file delivery) 2010-08-11 fop: fixed IE download bug (missing header separating line) - fop: fixed 1 min delay bug on AUTODELETE=YES +2010-08-11 fop: fixed 1 min delay bug on AUTODELETE=YES 2010-08-08 sex: support for compressed streams - sex,sexsend: removed unneccesary text mode (option -t) - sex,sexsend: speedup factor 5 - added sexxx +2010-08-08 sex,sexsend: removed unneccesary text mode (option -t) +2010-08-08 sex,sexsend: speedup factor 5 +2010-08-08 added sexxx 2010-08-06 sex: fixed various bugs in client and server - fac(CGI): fixed bug AKEY not working +2010-08-06 fac(CGI): fixed bug AKEY not working 2010-08-03 xx: no user inquiry for postprocessing if output is a pipe 2010-08-02 added optional german localization 2010-07-31 separated subusers in extra file $SPOOL/$USER/@SUBUSER 2010-07-25 fop: log also aborted downloads 2010-07-23 added fac CGI 2010-07-18 fexsrv,fup,fexsend: extra XKEY download with short // URL - fexsend: fixed bug CHECKRECIPIENT not working +2010-07-18 fexsend: fixed bug CHECKRECIPIENT not working 2010-07-16 added cookie support (for AKEY and SKEY) - fup: fixed bug showstatus window too small for close button +2010-07-16 fup: fixed bug showstatus window too small for close button 2010-07-13 schwuppdiwupp: added CHECKRECIPIENT 2010-07-12 fop,xx: allow several concurrent downloads of STDFEX 2010-07-10 fop: workaround for stupid IE download bug @@ -521,18 +549,18 @@ 2010-07-01 fexsrv,fex.ph: new config variable $force_https 2010-06-29 fop: new config variable $limited_download with default NO => allow multiple downloads through proxy farm (varying IPs) - fop: note every successful download in spool file "download" +2010-06-29 fop: note every successful download in spool file "download" 2010-06-25 fexget: fixed bug download status info update too often 2010-06-23 fur: better sendmail clone compatibility: use space instead of comma as address separator 2010-06-19 fexget: new option -o overwrite mode - fexget: use ./$file.tmp for downloading instead of $HOME/.fex/tmp/ +2010-06-19 fexget: use ./$file.tmp for downloading instead of $HOME/.fex/tmp/ 2010-06-16 schwuppdiwupp: edit and select address book entries 2010-06-15 rup: fixed bug case sensitive recipient address 2010-06-12 fop: send X-File-ID on HEAD request, too - fexget: added support of X-File-ID +2010-06-12 fexget: added support of X-File-ID 2010-06-11 schwuppdiwupp: (chunked) multi-POST for proxy with 4 GB limit - schwuppdiwupp: X-File-ID support +2010-06-11 schwuppdiwupp: X-File-ID support 2010-06-08 fup,fexsend: (chunked) multi-POST for proxy with 4 GB limit 2010-06-06 fup,fop,fexsend: protocol extension X-File-ID (contains mtime of file) is the successor of X-Size for more @@ -546,58 +574,58 @@ 2010-05-27 fexsend: added option -b bounce (copy-forward) 2010-05-26 fup,foc: added copy-forward feature 2010-05-20 fexsend: fixed bug uninitialized value with option -@ - fur: fixed bug $main::admin not declared +2010-05-20 fur: fixed bug $main::admin not declared 2010-05-17 fexsend: added option -H for hints - fexsend: added option -A for edit server address book +2010-05-17 fexsend: added option -A for edit server address book 2010-05-16 fexsend: added HTTPS proxy support - fup: fixed bug uninitialized value (line 1059) +2010-05-16 fup: fixed bug uninitialized value (line 1059) 2010-05-13 fup: fixed bug ignored KEEP and AUTODELETE options for groups 2010-05-12 fup: fixed bug ignored autodelete option from ADDRESSBOOK 2010-04-30 fup: fixed bug uninitialized value with CHECKRECIPIENT - fexsend: no SID for https +2010-04-30 fexsend: no SID for https 2010-04-28 fup: fixed bug case sensitiv group addresses 2010-04-27 fexsend: fixed bug ignored server address book options - fexsend: displays recipients and options before starting post - fup: fixed bug ignored server address book autodelete option +2010-04-27 fexsend: displays recipients and options before starting post +2010-04-27 fup: fixed bug ignored server address book autodelete option 2010-04-26 fexsrv: log all HTTP headers (no more ignore list) 2010-04-25 fexsrv: accept HTTP header with continuation lines 2010-04-22 fex.pp: added htdocs/header.html support - fex.ph: added variable @H1_extra organization link and logo +2010-04-22 fex.ph: added variable @H1_extra organization link and logo 2010-04-20 fexsrv,fexsend: HTTP header X-Timeout (info server->client) - fexsrv: logging with locking +2010-04-20 fexsrv: logging with locking 2010-04-19 fexsend: removed broken option -A and replaced it with more flexible feature "." for recipient address - fexsend: fixed bug dies if sender is subuser (ADDRESS_BOOK error) - fup: fixed bug no COMMENT in notification email - dop: fixed bug error output with non GNU file command +2010-04-19 fexsend: fixed bug dies if sender is subuser (ADDRESS_BOOK error) +2010-04-19 fup: fixed bug no COMMENT in notification email +2010-04-19 dop: fixed bug error output with non GNU file command 2010-04-17 fexsend,fexget: added option -i for alternative accounts or servers 2010-04-12 fexsend: new verbose output format --> <-- 2010-04-11 fexsend: added option -Q quota query 2010-04-09 fup,fac: added quota support 2010-03-25 fup: fixed bug "Insecure dependency" when using AKEY parameter (eg: sending a second file) - fup_template.html: fixed bug upload status window always shows +2010-03-25 fup_template.html: fixed bug upload status window always shows "ERROR: no file data received" 2010-03-24 fexsend: fixed bug dies if there is no server address book 2010-03-22 FIX.jar: fixed bug interpret HTTP response "200 OK" as error. 2010-03-20 fup,fop: set mtime on user directory for last successfull access 2010-03-19 fexsend: fixed bug abort on short address if there is no server address book - fex_cleanup: better cleanup for dkeys directory +2010-03-19 fex_cleanup: better cleanup for dkeys directory 2010-03-18 fup: fixed bug cannot DELETE with group recipient 2010-03-17 fup: fixed bug wrong success message on aborted uploads - fop: fixed bug cannot handle @group names +2010-03-17 fop: fixed bug cannot handle @group names 2010-03-16 fup,fuc: fixed bug mixed case in F*EX group names and addresses 2010-03-14 fex.pp: do not send notification emails on empty files - fup,fuc: added F*EX groups +2010-03-14 fup,fuc: added F*EX groups 2010-03-12 fup,fop: fixed bug case sensitiv FROM and TO addresses 2010-03-05 fup: fixed bug aliases are not accepted with fop_auth 2010-03-04 fexsrv: use CGI login if it exists as start-page 2010-02-26 fexsend: first check server address book, then mutt aliases - fop: do not terminate session after ADDRESSBOOK request +2010-02-26 fop: do not terminate session after ADDRESSBOOK request 2010-02-18 fexget: fixed bug always append existing file, ask for overwriting 2010-02-08 fexsrv: fixed bug uninitialized value in substitution (line 229) - fex.pp: better qmail compatibility (space separated addresses) +2010-02-08 fex.pp: better qmail compatibility (space separated addresses) 2010-02-07 fac: fixed bug uninitialized $EDITOR environment variable 2009-12-28 fup,fop,fexsend: protocol extension X-Size for more reliable resume function (checks size of file) @@ -622,25 +650,25 @@ 2009-08-12 fup: fixed bug "send another file" for subusers 2009-08-10 fexsend: fixed bug timeout on big archives 2009-07-27 to and from addresses in spool are now always localpart@domain, - install contains automatic spool converter - fup: fixed bug short aliases address list mismatch +2009-07-27 install contains automatic spool converter +2009-07-27 fup: fixed bug short aliases address list mismatch 2009-07-24 fup,fex_cleanup: fixed bug delete all files for multiple recipients after any download - fexget: fixed bug delete local file before download +2009-07-24 fexget: fixed bug delete local file before download 2009-07-20 fup: added autodelete and keep hack for HTML form 2009-07-18 fup: fixed bug leading . in file directory name - fup: added CHECKRECIPIENT support - fup: code cleanup, new 3-stage user interface - fexsend: added CHECKRECIPIENT feature +2009-07-18 fup: added CHECKRECIPIENT support +2009-07-18 fup: code cleanup, new 3-stage user interface +2009-07-18 fexsend: added CHECKRECIPIENT feature 2009-07-17 fexget: fixed bug wrong UTF8 handling 2009-07-16 fop: fixed bug sending wrong file size if TO or FROM has uppercase chars ==> resuming upload did not work 2009-07-11 fup: can select more than one address from address book 2009-07-08 fup,fex.pp: fixed bug wrong download URLs 2009-07-07 new spool directory layout $TO/$FROM/urlencode($FILENAME) - fup: be more restrictive in accepting (illegal) parameters values - fup,fuc: subuser access key name is now SKEY (KEY is depreciated) - rup: new HTML layout, fixed bug in file select box +2009-07-07 fup: be more restrictive in accepting (illegal) parameters values +2009-07-07 fup,fuc: subuser access key name is now SKEY (KEY is depreciated) +2009-07-07 rup: new HTML layout, fixed bug in file select box 2009-07-06 fup: substitute all control characters in file name and comment with "_" 2009-07-02 better install script, guesses IP @@ -648,7 +676,7 @@ $TO/$FROM/$FILE --> $TO/$FROM/md5h($FILENAME) to avoid filename collisions 2009-06-28 added mailman authorization mma - better address-book integration in fup +2009-06-28 fup: better address-book integration 2009-06-26 FIX.jar: fixed several bugs, now working with Windows Vista, too 2009-06-25 added fup_template.html as an example for customizing upload page 2009-06-22 fup,fexsend,fexget: LIST also shows COMMENT @@ -660,11 +688,11 @@ 2009-05-17 fup: check if there is enough free space in spool 2009-04-07 new perl based install; requires server IP for xinetd binding 2009-03-25 fexget: fixed bug saving failed if on other partition then FEXHOME - fexget: fixed bug calculated wrong transfer rate - fexget: changed default answers to more secure values +2009-03-25 fexget: fixed bug calculated wrong transfer rate +2009-03-25 fexget: changed default answers to more secure values 2009-03-24 fexsend: new option -l for listing sent files - fup: support for listing sent files - fex.pp: default charset is now UTF-8 in HTTP reply +2009-03-24 fup: support for listing sent files +2009-03-24 fex.pp: default charset is now UTF-8 in HTTP reply 2009-03-16 fur: fixed bug no lower case transformation for user and domain 2009-03-05 fop: fixed bug no parallel download possible on multiple recipients 2009-03-03 dop: send Last-Modified HTTP header (java needs it) @@ -672,15 +700,15 @@ 2009-02-22 fop: fixed bug download failed without FROM parameter 2009-02-20 test for /usr/lib/sendmail and /usr/sbin/sendmail 2009-02-18 fop: fixed bug file size query for alias recipient - fexget: added option -a to get address-book from server +2009-02-18 fexget: added option -a to get address-book from server 2009-02-17 fup,fuc: better linking 2009-02-14 fup: first send notification emails, then send HTTP 200 OK to client - fup: accept ADDRESS_BOOK as upload +2009-02-14 fup: accept ADDRESS_BOOK as upload 2009-02-13 fup,foc,fuc: added ADDRESS_BOOK support - added fix and FIX.jar (Java applet client) +2009-02-13 added fix and FIX.jar (Java applet client) 2009-02-11 fop: fixed bug file size request with multiple $to gives always 0 (no upload resume possible with multiple recipients) - fop: check for valid recipient address (in file path) +2009-02-11 fop: check for valid recipient address (in file path) ==> early abort possible when client uses illegal address for upload (resume-HEAD-request) 2009-02-10 fur: catch errors from sendmail(clone) and save them to $log @@ -690,13 +718,13 @@ 2009-01-31 fexsrv: fixed bug handling of missing trailing / in doc requests 2009-01-30 rup: fixed bug wrong download URL in notification email 2009-01-26 fexsend: archive format 7z and zip with default compression - fup,fuc,foc,rup: link to F*EX start page in top header +2009-01-26 fup,fuc,foc,rup: link to F*EX start page in top header 2009-01-21 fuc: URL for subusers with KEY parameter - fup.fuc,foc: fixed bug wrong AKEY lookup +2009-01-21 fup.fuc,foc: fixed bug wrong AKEY lookup 2009-01-20 fexsrv: better handling of URLs with trailing / (==> index.html) - fop: fixed bug endless loop with fop_auth mode +2009-01-20 fop: fixed bug endless loop with fop_auth mode 2009-01-13 fup,fop: support for MIME-file types - fexsend: added option -M for MIME-file to be displayed in webbrowser +2009-01-13 fexsend: added option -M for MIME-file to be displayed in webbrowser on download 2009-01-04 fup: increase minimum timeout to 10 s 2008-12-26 fup: do not allow re-upload (overwrite) if file is in download @@ -705,36 +733,36 @@ 2008-12-21 fup: fixed bug removing old autodelete and error files failed 2008-12-20 added logwatch 2008-12-18 fexget: fixed bug responsiveness on slow links - fexget: fixed bug save file name for archives +2008-12-18 fexget: fixed bug save file name for archives 2008-12-12 fexget: better responsiveness on slow links (modem, ISDN) - fup: added warning for incompatible clients (konqueror, etc) +2008-12-12 fup: added warning for incompatible clients (konqueror, etc) 2008-12-11 fexsend: allow comments in ID file 2008-12-03 fup,fex.pp: fixed bug UTF-8 subject in notfication email 2008-12-02 fexsend: better responsiveness on slow links (modem, ISDN) - fop: send UTF-8 filename in HTTP header Content-Disposition - fexget: save original filename (parse HTTP header) +2008-12-02 fop: send UTF-8 filename in HTTP header Content-Disposition +2008-12-02 fexget: save original filename (parse HTTP header) 2008-11-28 fexserv: added special FlashGet (download sucker) brake - html error messages now with HTTP_HOST und server-time info +2008-11-28 html error messages now with HTTP_HOST und server-time info 2008-11-27 added htdocs/version and htdocs/tools.html - added fexsend, fexget, sexsend, sexget to htdocs/download - dop: fixed bug symlink of symlink leads to hangup - fop: teergrub download managers and other suckers +2008-11-27 added fexsend, fexget, sexsend, sexget to htdocs/download +2008-11-27 dop: fixed bug symlink of symlink leads to hangup +2008-11-27 fop: teergrub download managers and other suckers 2008-11-26 fop: with URL parameter ?KEEP file can be downloaded more than once - fexget: added option -k for keep on server +2008-11-26 fexget: added option -k for keep on server 2008-11-24 fex_cleanup: fixed bug $autodelete not defined - fexget: added HTTPS/SSL support +2008-11-24 fexget: added HTTPS/SSL support 2008-11-22 fexsrv: reject requests with IP hostnames in HTTP Host header 2008-11-21 fex.ph,fop: $autodelete="DELAY" allows file download many times (but only from same IP and until next fex_cleanup run) - fup,fop: fixed bug options keep and delete autodelay do not +2008-11-21 fup,fop: fixed bug options keep and delete autodelay do not work with spool on NFS 2008-11-20 fexsend: added HTTPS/SSL support - fex.ph: added config variable $autodelete - fup: fixed bug subuser cannot send files +2008-11-20 fex.ph: added config variable $autodelete +2008-11-20 fup: fixed bug subuser cannot send files 2008-11-19 use md5-hash of $from:$id instead of URL parameters FROM=$from&ID=$id - fac: set correct exit status +2008-11-19 fac: set correct exit status 2008-11-16 fup: fixed bug DELETE not working - install: do not overwrite lib/fup.pl (perhaps contains site config) +2008-11-16 install: do not overwrite lib/fup.pl (perhaps contains site config) 2008-11-15 fex_cleanup: clean up $SPOOL/.ukeys/, too 2008-11-14 fup: show "user config" link only after authorization 2008-11-13 foc,fuc,fup: quick sub-user creation with auto-notification. @@ -742,21 +770,21 @@ 2008-10-29 fup: do not require HTTP authorization if request already contains ID (methode used by xx) 2008-10-28 fex.pp: fixed bug $warning not defined - fup: fixed bug do not allow subuser in fop_auth mode +2008-10-28 fup: fixed bug do not allow subuser in fop_auth mode 2008-10-27 install: do not overwrite existing htdoc/index.html - fup: fixed bug resend (SEEK) leads to HTTP error 666 +2008-10-27 fup: fixed bug resend (SEEK) leads to HTTP error 666 2008-10-26 fexsrv: accept HTTP request with absolute URLs (http://...), too 2008-10-23 fexsrv: fixed bug continue connect logfile entry 2008-10-17 fexsrv: fixed bug keep_alive with HTTP/1.0 - fexsrv: fixed bug wrong warning in debug mode with empty line +2008-10-17 fexsrv: fixed bug wrong warning in debug mode with empty line 2008-10-07 fexsrv: moved TIMEOUT message to debug.log 2008-10-06 dop: fixed bug opening file (did not deliver any file!) - dop: implemented HTTP keep-alive (delivering more than one +2008-10-06 dop: implemented HTTP keep-alive (delivering more than one document per session) 2008-10-04 if config variable $fop_auth is set, download requires - authentication and upload is restricted to registered users +2008-10-04 authentication and upload is restricted to registered users 2008-10-02 dop: declare exectuable scripts as application/octet-stream - fup: added link to Windows client schwuppdiwupp.exe +2008-10-02 fup: added link to Windows client schwuppdiwupp.exe 2008-09-29 write upload speed to upload directory 2008-09-17 fac: fixed bug locating FEXLIB 2008-09-12 fup: added config lib/fup.pl @@ -765,88 +793,89 @@ 2008-08-31 added fur (F*EX User (auto-) Registration) 2008-08-25 will die when no hostname is available 2008-08-21 added fexsend to htdocs/download - fup: added ID mail sendback option +2008-08-21 fup: added ID mail sendback option 2008-08-20 fac: added -l option 2008-08-19 fexsrv: fixed bug SSL handling 2008-08-15 fup,fuc,fexsrv: dynamic protocol detection (HTTP/HTTPS) 2008-08-14 fup: fixed bug login possible with wrong login data (but no upload) 2008-08-13 fup: showstatus terminates immediately when empty file was uploaded - fup: showstatus shows error message on illegal recipient address +2008-08-13 fup: showstatus shows error message on illegal recipient address or when no file was uploaded (nececessary for stupid Internet Explorer!) 2008-08-11 splitted debugfiles with time stamp in filename - fex_cleanup: clean up aborted uploads, .ukeys/ and .debug/, too - fexsend,fexget: allow more than one file (with all options) +2008-08-11 fex_cleanup: clean up aborted uploads, .ukeys/ and .debug/, too +2008-08-11 fexsend,fexget: allow more than one file (with all options) 2008-08-08 fup: eliminate superfluous newlines in logfile on error handling - changed bareword filehandles to indirect filehandles +2008-08-08 changed bareword filehandles to indirect filehandles 2008-08-06 fup: decode %NUMBERs in file names from POST 2008-08-02 fexsend: bug fix -A option and argument handling 2008-08-01 fup: regular users can change the recipient in the upload form, sub users can not 2008-07-31 fup: fixed bug internet explorer not showing upload status window - fup: fixed bug with id / special id / real id mixup - fuc: nearly complete rewrite, better user interface +2008-07-31 fup: fixed bug with id / special id / real id mixup +2008-07-31 fuc: nearly complete rewrite, better user interface 2008-07-30 fup: fixed bug when account is a symlink - fup: fixed bug in authentication of subusers +2008-07-30 fup: fixed bug in authentication of subusers 2008-07-03 fop: workaround for Internet Explorer download bug 2008-07-02 fup,fop: switched default charset from ISO-8859-1 to UTF-8 - fup: uid for showstatus synchronization +2008-07-02 fup: uid for showstatus synchronization 2008-06-21 fexget: downloading without wget, file number as argument 2008-06-20 fexget,fop: added DELETE option - fexsend: send more files in one run +2008-06-20 fexsend: send more files in one run 2008-05-30 added missing sex to distribution - fexsend: added -A archiv to yourself option +2008-05-30 fexsend: added -A archiv to yourself option 2008-05-28 fup: fixed bug in LIST and DELETE commands 2008-05-27 fexsrv: correct HTTP redirect on missing trailing / in URL 2008-05-26 sex,sexsend: better public mode 2008-05-24 sex,sexsend: added text mode option 2008-05-23 added missing foc and rup to distribution 2008-05-20 fexsend: fixed bug in list parsing (-l option) - dop: fixed bug in file type determining on symbolic links +2008-05-20 dop: fixed bug in file type determining on symbolic links 2008-05-15 fexsrv,dop: fixed bug in HTTP keep_alive multi-requests 2008-05-02 fexsrv,dop: support for HTTP keep_alive multi-requests - fexsrv: more robust header parsing (ignore superfluous spaces) +2008-05-02 fexsrv: more robust header parsing (ignore superfluous spaces) 2008-04-28 added support for HTTP keep_alive - fexsrv: added SID (session ID) support - fexsend: encrypt ID with MD5 and SID +2008-04-28 fexsrv: added SID (session ID) support +2008-04-28 fexsend: encrypt ID with MD5 and SID 2008-04-20 added foc and rup - fop: return apropriate error message when file has been (auto)deleted +2008-04-20 fop: return apropriate error message when file has been (auto)deleted or is expired; error message is kept 3*keep_default days 2008-04-19 install: do not overwrite old fex.ph, but create fex.ph_new instead 2008-04-18 fup: fixed bug filename with path in notification email 2008-04-16 fexsrv,fop,dop: implemented HTTP HEAD 2008-04-14 renamed cgilaunch to fexsrv - fup: do not send notify-mail if file already exists (overwrite mode) - fup: do not accept file if authentication fails - fup,fop,fexsend: new secure download URL scheme with random dkey +2008-04-14 fup: do not send notify-mail if file already exists (overwrite mode) +2008-04-14 fup: do not accept file if authentication fails +2008-04-14 fup,fop,fexsend: new secure download URL scheme with random dkey 2008-04-11 fup: fixed bug in upload bar with 8-bit file names - fex_cleanup: fixed bug not removing aborted uploads +2008-04-11 fex_cleanup: fixed bug not removing aborted uploads 2008-04-10 added F*EX camel logo 2008-04-09 added dop (generic document output) - install: better infos +2008-04-09 install: better infos 2008-04-08 renamed confusing ID to auth-ID (request by chris@citecs.de) - fuc: fixed bug with more than 1 sub-user +2008-04-08 fuc: fixed bug with more than 1 sub-user 2008-04-07 fup: readded keep parameter (code got lost sometime?) - fup: added sender restriction (ALLOWED_RECIPIENTS) - fac: added restriction option -r and delete user option -d +2008-04-07 fup: added sender restriction (ALLOWED_RECIPIENTS) +2008-04-07 fac: added restriction option -r and delete user option -d 2008-04-06 fup: use Net::DNS instead of external host command - fup: more debuglog, fixed wrong error messages - added doc/concept doc/FAQ +2008-04-06 fup: more debuglog, fixed wrong error messages +2008-04-06 added doc/concept doc/FAQ 2008-04-02 install: better error handling (patch by chris@citecs.de) - more docs and improved logging +2008-04-02 more docs and improved logging 2008-04-01 cgilaunch: fixed bug in determing REMOTE_HOST when using stunnel - fexget: added -s streaming option - sex,sexsend: added public mode +2008-04-01 fexget: added -s streaming option +2008-04-01 sex,sexsend: added public mode 2008-03-31 changed project name to F*EX because of name collision with http://freshmeat.net/projects/fex/ - added sex, sexsend and sexget to distribution +2008-03-31 added sex, sexsend and sexget to distribution 2008-03-28 xx: changed syntax, now compatible to zz - added zz to distribution +2008-03-28 added zz to distribution 2008-03-27 fup: fixed bug in mail address verification 2008-03-24 fup,fexsend: show transfer rate in kB if filesize < 2 MB - fup: code-cleanup, more comments - fex.pp: umask 077 +2008-03-24 fup: code-cleanup, more comments +2008-03-24 fex.pp: umask 077 2008-03-23 fup: fixed bug in using multiple recipients 2008-03-22 first public release 2007-01-27 first file fexed via fex.rus.uni-stuttgart.de +2007-01-15 first file fexed via wwwtest6.belwue.de 2006-11-?? first code diff --git a/doc/SSL b/doc/SSL index d0e95f6..14f5abd 100644 --- a/doc/SSL +++ b/doc/SSL @@ -3,6 +3,7 @@ # execute this as root! # Redhat : stunnel-4 does not work! you need to install stunnel-5 +# Debian : stunnel-5.06 does not work! you need to install stunnel-5.18 mkdir /home/fex/etc cd /home/fex/etc/ @@ -43,7 +44,7 @@ service fexs type = unlisted protocol = tcp port = 443 - cps = 5 10 + cps = 10 2 user = fex groups = yes server = $stunnel diff --git a/doc/new b/doc/new index 568080d..c0ae6f2 100644 --- a/doc/new +++ b/doc/new @@ -2,12 +2,6 @@ New release on http://fex.belwue.de/fex.html Important changes: -- moved to new distribution site fex.belwue.de - -- autodelete=no if sender == recipient - -- no file name in email subject if notification is encrypted - -- added active and passive redirect support for standard HTTP documents +- added fexit (Windows client) and macfexsend (MacOS client) support - fixed various bugs diff --git a/doc/newfeatures b/doc/newfeatures index d28f95a..57e383f 100644 --- a/doc/newfeatures +++ b/doc/newfeatures @@ -1,6 +1,14 @@ New features for users ---------------------- +2016-01-04: + +- new Windows client fexit + +- new MacOS client macfexsend + + + 2015-01-12: - user configuration: save-or-display (MIME) for download diff --git a/doc/version b/doc/version index 056cc38..366b2e9 100644 --- a/doc/version +++ b/doc/version @@ -1 +1 @@ -fex-20150826 +fex-20160104 diff --git a/htdocs/FAQ.html b/htdocs/FAQ.html deleted file mode 100644 index a096645..0000000 --- a/htdocs/FAQ.html +++ /dev/null @@ -1,12 +0,0 @@ - -F*EX FAQ - - -##
-## << while (($v,$vv) = each %ENV) { print "$v = $vv\n" } >>
-## 
- -<< require "./faq.pl" or print $! >> - - - diff --git a/htdocs/FAQ.html b/htdocs/FAQ.html new file mode 120000 index 0000000..b9014e9 --- /dev/null +++ b/htdocs/FAQ.html @@ -0,0 +1 @@ +FAQ/index.html \ No newline at end of file diff --git a/htdocs/FAQ/admin.faq b/htdocs/FAQ/admin.faq index 8ab089c..4c442ca 100644 --- a/htdocs/FAQ/admin.faq +++ b/htdocs/FAQ/admin.faq @@ -1,7 +1,7 @@ Q: I cannot install a web server like fexsrv, because I have no root permissions. Is there a pure-CGI-version of F*EX which runs with an apache web server? A: F*EX is hard bound to fexsrv for several reasons (performance, file size limit, session concept, etc) and cannot be run as CGI under apache. But you might have a look at - * http://gpl.univ-avignon.fr/filez/ + * https://github.com/FileZ/FileZ * http://freshmeat.net/projects/eventh/ * http://www.schaarwaechter.de/sp/projekte/dateiaustausch.html (German only!) diff --git a/htdocs/FAQ/meta.faq b/htdocs/FAQ/meta.faq index bc232d7..8a5f3a2 100644 --- a/htdocs/FAQ/meta.faq +++ b/htdocs/FAQ/meta.faq @@ -11,25 +11,25 @@ A: * They have a file size limit of 2 GB or even less. * It is unknown how long they will exist - DropLoad and ALLPeers already have terminated their business. Q: Why name "F*EX" and not shortly "FEX"? -A: At publication time there was already an (older) program named "FEX" listed on freshmeat.net. +A: At publication time there was already a program named "FEX" listed on freshmeat.net. Q: Who is the author? A: The main author is Ulli Horlacher
- But there are also a lot of contributors. + But there are also a lot of contributors all around the world. Q: Why a camel as the logo? A: The logo was inspired by the Perl camel, but it is based on a Steiff plush camel, which rides with us on our racing tandem. The logo was drawn by my stoker Beate. - http://fex.belwue.de/Vortrag/tosa.html + http://fex.rus.uni-stuttgart.de/Vortrag/tosa.html -Q: What do I need to install F*EX? +Q: What do I need to install a F*EX server? A: A UNIX or Windows server with a DNS entry, smtp for outgoing email and one open and free incoming tcp port. You must have administrative rights (UNIX: root) on this server and a basic understanding of UNIX and networking. Q: What means DNS and smtp? What is a tcp port? A: Do not install F*EX. It is beyond your horizon. -Q: Does F*EX support IPv6? +Q: Does F*EX support IPv6 and SSL/TLS? A: Yes. Q: Can I run F*EX on Windows? @@ -43,14 +43,14 @@ Q: I do not want to install a F*EX server of my own, but where can I use it? A: Contact http://www.nepustil.net/ for F*EX hosting. Q: The F*EX server is all in Perl?! Isn't Perl too slow for this job? -A: fex.belwue.de runs on a PC and F*EX is able to handle uploads with more than 300 MB/s. +A: F*EX is able to handle uploads with more than 300 MB/s on an office PC. Try this with an ordinary webserver like Apache! Q: Which licence does F*EX have? And why? A: Perl Artistic free software with a special anti-military clause: http://fex.belwue.de/doc/Licence "I want peace on earth and goodwill towards men" - http://www.youtube.com/watch?v=JHU0HinVhYc + https://www.youtube.com/watch?v=JHU0HinVhYc https://en.wikipedia.org/wiki/Sneakers_%281992_film%29 Q: Is there a F*EX mailing list? A: https://listserv.uni-stuttgart.de/mailman/listinfo/fex @@ -58,6 +58,12 @@ A: https://listserv.uni-stuttgart.de/mailman/listinfo/fex Q: Where can I get commercial support for F*EX? A: Contact http://www.nepustil.net/ +Q: How big is F*EX? +A: Server: 400 kB, 11000 lines of code + Clients: 180 kB, 5500 lines of code + Documentation: 130 kB + Localizations: 250 kB + Q: Who else is using F*EX? A: For example: * German Aerospace Center http://fex.dlr.de @@ -66,6 +72,8 @@ A: For example: * Swiss National Supercomputing Centre http://fex.cscs.ch * Centre National de la Recherche Scientifique (French National Center for Scientific Research) http://bigfiles.cnrs-gif.fr * Institut Pasteur http://dl.pasteur.fr + * Justus Liebig University http://fex.hrz.uni-giessen.de + * Fiat Chrysler https://fex.fiatitem.com/ * Palo Alto Research Center (Xerox PARC) http://parcftp.parc.com * Baden-Württembergs extended LAN http://fex.belwue.de * Deutsche Kinemathek Museum für Film und Fernsehen http://upload.deutsche-kinemathek.de diff --git a/htdocs/FAQ/misc.faq b/htdocs/FAQ/misc.faq index ddd5251..050902d 100644 --- a/htdocs/FAQ/misc.faq +++ b/htdocs/FAQ/misc.faq @@ -4,8 +4,8 @@ A: Contact the author Requested features are:
  • testers for MacOS, AIX and other UNIXes -
  • a new maintainer for the Java client F*IX
  • an Android or iOS client +
  • HTML5/websocket support
  • a F*EX plugin for thunderbird or outlook see thunderbird's filelink https://support.mozillamessaging.com/en-US/kb/filelink-large-attachments diff --git a/htdocs/FAQ/user.faq b/htdocs/FAQ/user.faq index b98c1d2..641886a 100644 --- a/htdocs/FAQ/user.faq +++ b/htdocs/FAQ/user.faq @@ -76,6 +76,10 @@ Q: Sending as a F*EX user is easy, but how to receive files from others, outside A: Register them as your subusers, create a F*EX group or a one-time upload key with "user config & operation control" See also http://fex.belwue.de/usecases/foreign.html +Q: I am not a user of your site. How can I send a file to a registered user? +A: See question above: you must ask a regular user to register you as his subuser. + You will then get a specific upload URL from him. + Q: Sometimes I can download a file more than once, especially when I repeat it quickly. Is the autodelete feature buggy? A: The F*EX server has a grace time of 1 minute after first sucessfully download in which the file is still available. This is necessary because of some stupid "download managers" which request the file several times at once. Otherwise they would report an error to the user. @@ -96,6 +100,9 @@ Q: I forgot to download a file. Now it is expired. How can I obtain it neverthel A: An expired file is definitively deleted. Even the admin cannot restore it. You must re-request it from the sender. +Q: When I try to download a file again, I get the error message: "file has been autodeleted after download". Can you restore it? +A: No. You must re-request it from the sender. + Q: I have sent a second file with the same name, but the recpient has not received a second notification email. Why? A: A file with the same name to the same recpient overwrites the first one if it is still there (no download so far). A second notification email of the same file(name) is not suggestive. @@ -107,6 +114,9 @@ Q: How can I suppress the automatic notification email? A: Use "!#!" as comment, then no notification email will be sent. Of course you then have to inform the recipient manually. +Q: Can I delete a file without downloading? +A: Add "?DELETE" to your download URL. + Q: Can I get a copy of the notification email? A: Add "!bcc!" to the comment field on upload. diff --git a/htdocs/download/fexget b/htdocs/download/fexget index 8e00119..c375cea 100755 --- a/htdocs/download/fexget +++ b/htdocs/download/fexget @@ -30,9 +30,10 @@ our $SH; our ($fexhome,$idf,$tmpdir,$windoof,$useragent); our ($xv,%autoview); our $bs = 2**16; # blocksize for tcp-reading and writing file -our $version = 20150826; +our $version = 20160104; our $CTYPE = 'ISO-8859-1'; our $fexsend = $ENV{FEXSEND} || 'fexsend'; +our $DEBUG = $ENV{DEBUG}; my %SSL = (SSL_version => 'TLSv1'); my $sigpipe; @@ -57,6 +58,14 @@ if ($Config{osname} =~ /^mswin/i) { $SSL{SSL_verify_mode} = 0; chdir $ENV{USERPROFILE}.'\Desktop'; # open XX,'>XXXXXX';close XX; +} elsif ($Config{osname} =~ /^darwin/i or $ENV{MACOS}) { + $0 =~ s:(.*)/:: and $ENV{PATH} .= ":$1"; + $fexhome = $ENV{FEXHOME} || $ENV{HOME}.'/.fex'; + $tmpdir = $ENV{FEXTMP} || $ENV{TMPDIR} || "$fexhome/tmp"; + $idf = "$fexhome/id"; + $_ = `sw_vers -productVersion 2>/dev/null`||''; + chomp; + $useragent = "fexget-$version (MacOS $_)"; } else { $0 =~ s:(.*)/:: and $ENV{PATH} .= ":$1"; $fexhome = $ENV{FEXHOME} || $ENV{HOME}.'/.fex'; @@ -233,7 +242,7 @@ if ($opt_a) { } } -my ($file,%files,$download,$server,$port,$fop); +my ($file,%files,$download,$server,$port,$fop,$https); if ($opt_f) { unless ($ENV{FEXID} or -f $ENV{HOME}.'/.fex/id') { @@ -271,6 +280,7 @@ URL: foreach my $url (@ARGV) { } if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/.*fop/\S+)}) { + $https = $1; $server = $2; $port = $4 || ($1?443:80); $fop = $5; @@ -358,6 +368,7 @@ URL: foreach my $url (@ARGV) { if ($ENV{DISPLAY} and $download =~ /\.(gif|jpg|png|tiff?)$/i) { # see also mimeopen and xdg-mime + # http://unix.stackexchange.com/questions/144047/how-does-xdg-open-do-its-work if (my $xv = $xv || pathsearch('xv') || pathsearch('xdg-open')) { printf "run \"%s %s\" [Yn] ? ",basename($xv),basename($download); $_ = ||''; @@ -367,10 +378,10 @@ URL: foreach my $url (@ARGV) { } if ($download =~ /$atype/) { - if ($download =~ /\.(tgz|tar.gz)$/) { extract('tar tvzf','tar xvzf') } - elsif ($download =~ /\.tar$/) { extract('tar tvf','tar xvf') } - elsif ($download =~ /\.zip$/i) { extract('unzip -l','unzip') } - elsif ($download =~ /\.7z$/i) { extract('7z l','7z x') } + if ($download =~ /\.(tgz|tar.gz)$/) { extract('tar tvzf','tar xvzf') } + elsif ($download =~ /\.tar$/) { extract('tar tvf','tar xvf') } + elsif ($download =~ /\.zip$/i) { extract('unzip -l','unzip') } + elsif ($download =~ /\.7z$/i) { extract('7z l','7z x') } else { die "$0: unknown archive \"$download\"\n" } if ($? == 0) { unlink $download; @@ -388,7 +399,7 @@ sub extract { my $l = shift; my $x = shift; my $d = $download; - my $xd = '.'; + my $xd = ''; local $_; if (-t and not $windoof) { @@ -396,9 +407,10 @@ sub extract { system(split(' ',$l),$download); $d =~ s:.*/:./:; $d =~ s/\.[^.]+$//; + $d =~ s:/*$:/:; for (;;) { $xd = inquire("extract to directory (Ctrl-C to keep archive): ",$d); - last if $xd =~ s:^(\./*)*!?$:./:; + last if $xd =~ s:^(\./*)*!?$::; if ($xd eq '-') { print "keeping $download\n"; exit; @@ -420,8 +432,9 @@ sub extract { last; } } - print "extracting to $xd :\n"; + print "extracting to $xd :\n" if $xd; system(split(' ',$x),$download); + print "extracted to $xd\n" if $xd; } sub del { @@ -453,7 +466,7 @@ sub del { sub forward { my $url = shift; my ($server,$port); - my ($uri,$dkey,$list,$cmd,$n); + my ($uri,$dkey,$list,$cmd,$n,$copy); my @r; if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/fop/.+)}) { @@ -474,7 +487,13 @@ sub forward { die "$0: no reply from fex server $server\n" unless $_; warn "<-- $_" if $opt_v; - unless (/^HTTP.*200/) { + if (/^HTTP.*already exists/) { + if ($uri =~ m:/fop/(\w+)/:) { + $dkey = $1; + } + } elsif (/^HTTP.*200/) { + # ok! + } else { s/^HTTP.... \d+ //; die "$0: $_"; } @@ -486,8 +505,7 @@ sub forward { warn "<-- $_" if $opt_v; } - $cmd = 'fexsend -l >/dev/null 2>&1'; - print "$cmd\n" if $opt_v; + print "fexsend -l\n" if $opt_v; system 'fexsend -l >/dev/null 2>&1'; $list = $ENV{HOME}.'/.fex/tmp/fexlist'; open $list,$list or die "$0: cannot open $list - $!\n"; @@ -563,14 +581,18 @@ sub download { $pipe = $download = $opt_s; } elsif (-p $opt_s or -c $opt_s) { $download = $opt_s; + $nocheck = 'pipe or character device'; } else { $download = $file.'.tmp'; $seek = -s $download || 0; } } else { # ask server for real file name - serverconnect($server, $port); - sendheader("$server:$port","HEAD $proxy_prefix$fop HTTP/1.1","User-Agent: $useragent"); + sendheader( + "$server:$port", + "HEAD $proxy_prefix$fop HTTP/1.1", + "User-Agent: $useragent" + ); my $reply = $_ = <$SH>; unless (defined $_ and /\w/) { die "$0: no response from server\n"; @@ -644,28 +666,34 @@ sub download { } } if ($checkstorage and not $nocheck) { - $t0 = time; + my $t0 = my $t1 = my $t2 = time; my $n = 0; + my $buf = '.' x M; + my $storagetest = $file.'.test'; + my $error = "$0: cannot write \"$storagetest\""; + open $storagetest,'>',$storagetest or die "$error - $!\n"; print STDERR "checking storage...\r"; - $buf = '.' x M; - while (-s $download < $checkstorage) { - syswrite X,$buf or do { - unlink $download; - die "\n$0: cannot write $download - $!\n"; + while (-s $storagetest < $checkstorage) { + syswrite $storagetest,$buf or do { + unlink $storagetest; + die "\n$error - $!\n"; }; $n++; - print STDERR "checking storage... ".$n." MB\r"; + $t2 = int(time); + if ($t2 > $t1) { + print STDERR "checking storage... ".$n." MB\r"; + $t1 = $t2; + } } - close X or do { - unlink $download; - die "\n$0: cannot write $download - $!\n"; + close $storagetest or do { + unlink $storagetest; + die "\n$error - $!\n"; }; print STDERR "checking storage... ".$n." MB ok!\n"; - unlink $download; - if (time-$t0 < 25) { - open X,'>',$download or die "$0: cannot write to \"$download\" - $!\n"; - } else { + unlink $storagetest; + if (time-$t0 > 25) { # retry after timeout + serverconnect($server,$port); return(download($server,$port,$fop,'nocheck')) } } @@ -806,13 +834,6 @@ sub pathsearch { } -sub quote { - local $_ = shift; - s/([^\w¡-ÿ_%\/=~:.,-])/\\$1/g; - return $_; -} - - { my $tty; @@ -830,10 +851,11 @@ sub quote { if (defined(&TIOCSTI) and $tty and open($tty,'>',$tty)) { print $prompt; + # push default answer into keyboard buffer foreach my $a (split("",$default)) { ioctl($tty,&TIOCSTI,$a) } chomp($_ = ||''); } else { - $prompt =~ s/([\?:=]\s*)/ [$default]$1/ or $prompt .= " [$default]"; + $prompt =~ s/([\?:=]\s*)/ [$default]$1/ or $prompt .= " [$default] "; print $prompt; chomp($_ = ||''); $_ = $default unless length; @@ -915,15 +937,9 @@ sub serverconnect { my $connect = "CONNECT $server:$port HTTP/1.1"; local $_; - if ($opt_v and $port == 443 and %SSL) { - foreach my $v (keys %SSL) { - printf "%s => %s\n",$v,$SSL{$v}; - } - } - if ($proxy) { tcpconnect(split(':',$proxy)); - if ($port == 443) { + if ($https) { printf "--> %s\n",$connect if $opt_v; nvtsend($connect,""); $_ = <$SH>; @@ -932,14 +948,13 @@ sub serverconnect { unless (/^HTTP.1.. 200/) { die "$0: proxy error : $_"; } - eval "use IO::Socket::SSL"; - die "$0: cannot load IO::Socket::SSL\n" if $@; + &enable_ssl; $SH = IO::Socket::SSL->start_SSL($SH,%SSL); } } else { tcpconnect($server,$port); } -# if ($port == 443 and $opt_v) { +# if ($https and $opt_v) { # printf "%s\n",$SH->get_cipher(); # } } @@ -954,10 +969,9 @@ sub tcpconnect { undef $SH; } - if ($port == 443) { + if ($https) { # eval "use IO::Socket::SSL qw(debug3)"; - eval "use IO::Socket::SSL"; - die "$0: cannot load IO::Socket::SSL\n" if $@; + &enable_ssl; $SH = IO::Socket::SSL->new( PeerAddr => $server, PeerPort => $port, @@ -974,6 +988,7 @@ sub tcpconnect { if ($SH) { autoflush $SH 1; + binmode $SH; } else { die "$0: cannot connect $server:$port - $@\n"; } @@ -982,6 +997,18 @@ sub tcpconnect { } +sub enable_ssl { + eval "use IO::Socket::SSL"; + die "$0: cannot load IO::Socket::SSL\n" if $@; + eval '$SSL{SSL_verify_mode} = 0 if Net::SSLeay::SSLeay() <= 9470143'; + if ($opt_v) { + foreach my $v (keys %SSL) { + printf "%s => %s\n",$v,$SSL{$v}; + } + } +} + + sub sendheader { my $sp = shift; my @head = @_; @@ -1018,6 +1045,18 @@ sub nvtsend { } +sub quote { + local $_ = shift; + s/([^\w\@\/%^,.=+_:+-])/\\$1/g; + return $_; +} + + +sub debug { + print "## DEBUG: @_\n" if $DEBUG; +} + + # from MIME::Base64::Perl sub encode_b64 { my $res = ""; diff --git a/htdocs/download/fexsend b/htdocs/download/fexsend index e746b66..7e498dc 100755 --- a/htdocs/download/fexsend +++ b/htdocs/download/fexsend @@ -31,15 +31,15 @@ eval 'use Net::INET6Glue::INET_is_INET6'; $| = 1; -our ($SH,$fexhome,$idf,$tmpdir,$windoof,$useragent,$editor,$nomail); +our ($SH,$fexhome,$idf,$tmpdir,$windoof,$macos,$useragent,$editor,$nomail); our ($anonymous,$public); our ($tpid,$frecipient); our ($FEXID,$FEXXX,$HOME); our (%alias); our $chunksize = 0; -our $version = 20150826; +our $version = 20160104; our $_0 = $0; -our $DEBUG; +our $DEBUG = $ENV{DEBUG}; my %SSL = (SSL_version => 'TLSv1'); my $sigpipe; @@ -54,18 +54,31 @@ if ($Config{osname} =~ /^mswin/i) { $useragent = sprintf("fexsend-$version (%s %s)", $Config{osname},$Config{archname}); $SSL{SSL_verify_mode} = 0; +} elsif ($Config{osname} =~ /^darwin/i or $ENV{MACOS}) { + $macos = $Config{osname}; + # http://stackoverflow.com/questions/989349/running-a-command-in-a-new-mac-os-x-terminal-window + $HOME = (getpwuid($<))[7]||$ENV{HOME}; + $fexhome = $HOME.'/.fex'; + $tmpdir = $ENV{FEXTMP} || $ENV{TMPDIR} || "$fexhome/tmp"; + $tmpdir =~ s:/$::; + $idf = "$fexhome/id"; + chmod 0600,$idf; + $editor = $ENV{EDITOR} || 'open -W -n -e'; + $_ = `sw_vers -productVersion 2>/dev/null`||''; + chomp; + $useragent = "fexsend-$version (MacOS $_)"; } else { $0 =~ s:.*/::; $HOME = (getpwuid($<))[7]||$ENV{HOME}; $fexhome = $HOME.'/.fex'; $tmpdir = $ENV{FEXTMP} || "$fexhome/tmp"; $idf = "$fexhome/id"; + chmod 0600,$idf; $editor = $ENV{EDITOR} || 'vi'; $_ = `(lsb_release -d||uname -a)2>/dev/null`||''; chomp; s/^Description:\s+//; $useragent = "fexsend-$version ($_)"; - chmod 0600,$idf; } if (-f ($_ = '/etc/fex/config.pl')) { @@ -88,7 +101,7 @@ my $features = ''; my $timeout = 30; # server timeout my $fexlist = "$tmpdir/fexlist"; my ($usage,$hints); -my $xx = $0 =~ /^xx/; +my $xx = $0 =~ /\bxx$/; if ($xx) { $usage = "usage: send file(s): xx [:slot] file...\n". @@ -104,6 +117,7 @@ if ($xx) { $usage = <; + # $fexcgi = <$idf> if $fexcgi =~ /^\[.+\]/; $from = <$idf>; $id = <$idf>; while (<$idf>) { @@ -745,6 +765,7 @@ sub register { sendheader("$fs:$port","GET $proxy_prefix/fur?user=$mail&verify=no HTTP/1.1"); http_response(); + # header while (<$SH>) { s/\r//; printf "<-- $_"if $opt_v; @@ -779,10 +800,365 @@ sub register { } +# menu for MacOS users +sub menu { + my $key; + my $new; + local $_; + + system 'clear'; + print "\n"; + print "fexsend-$version\n"; + + for (;;) { + if (open $idf,$idf) { + $fexcgi = getline($idf) and + $from = getline($idf) and + $id = getline($idf); + close $idf; + last if $id; + } + &set_ID; + } + + print "\n"; + print "$from on $fexcgi\n"; + print "\n"; + + for (;;) { + print "\n"; + print "[s] send a file or directory\n"; + print "[u] update fexsend\n"; + print "[l] change login data (user, server, auth-ID)\n"; + print "[h] help\n"; + print "[q] quit\n"; + print "\n"; + print "your choice: "; + $key = ReadKey(0); + if ($key eq 'q') { + print "$key\n"; + print "\n"; + print "Type [Cmd]W to close this window.\n"; + exit; + } + if ($key eq 'h') { + print "$key\n"; + print + "\n". + "With fexsend you can send files of any size to any e-mail address.\n". + "\n". + "At the recipient or file prompt [RETURN] brings you to this option menu.\n". + "\n". + "To send more than one file:\n". + "When you enter * at the file prompt, you will be first asked for an archive name\n". + "and then you can drag+drop multiple files.\n". + "\n". + "Do not forget to terminate each input line with [RETURN].\n". + "\n". + "See http://fex.rus.uni-stuttgart.de/ for more informations.\n"; + next; + } + if ($key eq 'u') { + print "$key\n"; + if ($0 =~ m:(^/client/|/sw/):) { + print "\n"; + print "use swupdate to update fexsend!\n"; + next; + } + $new = $0.'.new'; + system "curl http://fex.belwue.de/download/fexsend>".quote($new); + chmod 0755,$new; + system qw'perl -c',$new; + if ($? == 0) { + rename $new,$0; + exec $0; + } else { + print "\n"; + print "cannot install new fexsend\n"; + } + next; + } + if ($key eq 'l') { + print "$key\n"; + system 'clear'; + &set_ID; + next; + } + if ($key eq 's' or $key eq "\n") { + print "s\n"; + &ask_file; + next; + } + } + exit; +} + + +# for MacOS +sub ask_file { + my ($file,$comment,$recipient,$archive,$size,$cmd,$key); + my @files; + my $qfiles; + local $_; + + system 'clear'; + + &set_ID unless -s $idf; + + print "\n"; + print "Enter [RETURN] after each input line.\n"; + print "\n"; + + for (;;) { + print "Recipient(s): "; + $recipient = ; + chomp $recipient; + $recipient =~ s/^\s+//; + $recipient =~ s/\s+$//; + $recipient =~ s/[\s;,]+/,/g; + &menu unless $recipient; + last if $recipient =~ /\w/ or $recipient eq '.'; + } + + for (;;) { + print "\n"; + print "Drag a file into this window or hit [RETURN] "; + print $archive ? "to continue.\n" : "for menu options.\n"; + print "File to send: "; + $file = ||''; + chomp $file; + $file =~ s/^\s+//; + $file =~ s/ $// if $file !~ /\\ $/; + &menu unless $file or $archive; + if ($file eq '*') { + print "Archive name: "; + $archive = ||''; + chomp $archive; + next unless $archive; + $archive =~ s/^\s+//g; + $archive =~ s/\s+$//g; + $archive =~ s/[^\w=.+-]/_/g; + next; + } + if ($file) { + unless (-e $file) { + $file =~ s/\\\\/\000/g; + $file =~ s/\\//g; + $file =~ s/\000/\\/g; + } + unless (-r $file) { + print "\"$file\" is not readable\n"; + next; + } + my $qf = quote($file); + if (`du -ms $qf` =~ /^(\d+)/) { + $size += $1; + printf "%d MB\n",$1; + } + if ($archive) { + push @files,$file; + next; + } + } + if ($archive) { + next unless @files; + $qfiles = join(' ',map(quote($_),@files)); + if ($size < 2048) { + $archive .= '.zip'; + } else { + $archive .= '.tar'; + } + } + print "\n"; + print "Comment: "; + $comment = ||''; + chomp $comment; + print "\n"; + if ($comment =~ s/^:\s*-/-/) { + $cmd = quote($0)." $comment "; + if ($archive) { + $cmd .= '-a '.quote($archive).' '.$qfiles; + } else { + $cmd .= quote($file); + } + $cmd .= ' '.quote($recipient); + print $cmd,"\n"; + system $cmd; + } else { + print quote($0)." -C '$comment' "; + if ($archive) { + printf "-a %s %s %s\n",quote($archive),$qfiles,$recipient; + system $0,'-C',$comment,'-a',$archive,@files,$recipient; + } else { + printf "%s %s\n",quote($file),$recipient; + system $0,'-C',$comment,$file,$recipient; + } + } + print "\n"; + print "[s] send another file to $recipient\n"; + print "[n] send another file to another recipient\n"; + print "[q] quit\n"; + print "\n"; + print "your choice: "; + for (;;) { + $key = ReadKey(0); + &ask_file if $key eq 'n'; + if ($key eq 's' or $key eq "\n") { + print "s\n"; + last; + } + if ($key eq 'q') { + print "$key\n"; + exit; + } + } + $file = $comment = $archive = ''; + @files = (); + } +} + + +sub set_ID { + my ($server,$port,$user,$logo); + local $_; + + print "\n"; + for (;;) { + print "F*EX server URL: "; + $server = ; + $server =~ s/[\s\n]//g; + if ($server =~ s:/fup/(\w+)$::) { + $_ = decode_b64($1); + if (/(from|user)=(.+)&id=(.+)/) { + $user = $2; + $id = $3; + } + } + $server =~ s:/fup.*::; + $server =~ s:/+$::; + next if $server !~ /\w/; + if ($server =~ s/^https:..// or $server =~ /:443/) { + $server =~ s/:.*//; + $port = 443; + eval "use IO::Socket::SSL"; + if ($@) { + print "\nno perl SSL modules installed - cannot use https\n\n"; + next; + } + $SH = IO::Socket::SSL->new( + PeerAddr => $server, + PeerPort => $port, + Proto => 'tcp', + %SSL + ); + } else { + $server =~ s:^http.//::; + if ($server =~ s/:(\d+)//) { + $port = $1; + } else { + $port = 80; + } + $SH = IO::Socket::INET->new( + PeerAddr => $server, + PeerPort => $port, + Proto => 'tcp', + ); + } + unless ($SH) { + print "\ncannot connect to $server:$port - $!\n\n"; + next; + } + sendheader( + "$server:$port", + "GET /logo.jpg HTTP/1.0", + "User-Agent: $useragent", + "Connection: close", + ); + $_ = <$SH>||''; + unless (/HTTP.1.1 200/) { + print "\nbad server reply: $_\n"; + next; + } + while (<$SH>) { last if /^\s*$/ } + local $/; + $logo = <$SH>||''; + close $SH; + if (length $logo < 9999) { + print "\n$server is not a F*EX server!\n\n"; + next; + } + open $logo,">$tmpdir/fex.jpg"; + print {$logo} $logo; + close $logo; + last; + } + + for (;;) { + last if $user; + print "Your login (e-mail address): "; + $user = ; + $user =~ s/[\s\n]//g; + if ($user !~ /.@[\w.-]+$/) { + print "\"$user\" is not a valid e-mail address!\n"; + next; + } + } + + for (;;) { + last if $id; + print "Your auth-ID for this account: "; + $id = ; + $id =~ s/[\s\n]//g; + } + + open $idf,'>',$idf or die "$0: cannot write to $idf - $!\n"; + print {$idf} "$server\n", + "$user\n", + "$id\n"; + close $idf; + print "\n"; + print "Login data written to $idf\n\n"; + print "fexing test file to $user:\n\n"; + system "$0 -o -M -C test $tmpdir/fex.jpg $user"; + print "\n"; + if ($? != 0) { + print "fexsend failed, login data is invalid, try again\n"; + &set_ID; + } else { + print "fexsend test succeeded!\n"; + sleep 3; + } +} + + +# read one key from terminal in raw mode +sub ReadKey { + my $key; + local $SIG{INT} = sub { stty('reset'); exit }; + + stty('raw'); + # loop necessary for ESXi support + while (not defined $key) { + $key = getc(STDIN); + } + stty('reset'); + return $key; +} + + +sub stty { + if (shift eq 'raw') { + system qw'stty -echo -icanon eol',"\001"; + } else { + system qw'stty echo icanon eol',"\000"; + } +} + + sub send_xx { my $transferfile = shift; my $file = ''; - my (@r,@tar); + my (@r,@tar,$dir); $SIG{PIPE} = $SIG{INT} = sub { unlink $transferfile; @@ -800,7 +1176,6 @@ sub send_xx { print "making tar transfer file $transferfile :\n"; # single file? then add this directly if (scalar @ARGV == 1) { - my ($dir,$file); # strip path if not ending with / if ($ARGV[0] =~ m:(.+)/(.+): and $2 !~ m:/$:) { ($dir,$file) = ($1,$2); @@ -947,49 +1322,54 @@ sub query_settings { # list spool sub list { my (@r,$r); - my ($data,$dkey,$n); + my ($data,$dkey); + my $n = 0; + my $s = 1; + my $a = shift @ARGV || '.'; local $_; female_mode("list spooled files?") if $opt_F; - if ($opt_l and $n = shift @ARGV and $n =~ /^\d+$/) { - open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; - while (<$fexlist>) { - if (/^\s*(\d+)\) (\w+) (.+)/ and $1 eq $n) { - serverconnect($server,$port) unless $SH; - sendheader( - "$server:$port", - "GET $proxy_prefix/fop/$2/$2?LIST HTTP/1.1", - "User-Agent: $useragent", - ); - $_ = <$SH>||''; - s/\r//; - print "<-- $_" if $opt_v; - if (/^HTTP.* 200/) { + if ($opt_l) { + if ($a =~ /^\d+$/) { + open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; + while (<$fexlist>) { + if (/^\s*(\d+)\) (\w+) (.+)/ and $1 eq $a) { + serverconnect($server,$port) unless $SH; + sendheader( + "$server:$port", + "GET $proxy_prefix/fop/$2/$2?LIST HTTP/1.1", + "User-Agent: $useragent", + ); + $_ = <$SH>||''; + s/\r//; print "<-- $_" if $opt_v; - while (<$SH>) { - s/\r//; - if (/^\n/) { - print; - print while <$SH>; + if (/^HTTP.* 200/) { + print "<-- $_" if $opt_v; + while (<$SH>) { + s/\r//; + if (/^\n/) { + print; + print while <$SH>; + } } + } elsif (s:HTTP/[\d\. ]+::) { + die "$0: server response: $_"; + } else { + die "$0: no response from fex server $server\n"; } - } elsif (s:HTTP/[\d\. ]+::) { - die "$0: server response: $_"; - } else { - die "$0: no response from fex server $server\n"; + exit; } - exit; } + die "$0: file \#$a not found in fexlist\n"; } - die "$0: file \#$n not found in fexlist\n"; - } else { - @r = formdatapost( - from => $from, - to => $opt_l ? '*' : $from, - command => $opt_C, - ); } + + @r = formdatapost( + from => $from, + to => $opt_l ? '*' : $from, + command => $opt_C, + ); die "$0: no response from fex server $server\n" unless @r; $_ = shift @r; unless (/^HTTP.* 200/) { @@ -1011,12 +1391,13 @@ sub list { s/&/&/g; s/"/\"/g; s/</) { @@ -1139,6 +1520,37 @@ sub delete { } +sub delete_file { + my ($from,$to,$file) = @_; + local $_; + + unless ($SH) { + serverconnect($server,$port); + query_sid($server,$port) unless $anonymous; + } + + $file = urlencode($file); + sendheader( + "$server:$port", + "GET $proxy_prefix/fop/$to/$from/$file?id=$sid&DELETE HTTP/1.1", + "User-Agent: $useragent", + ); + + while (<$SH>) { + s/\r//; + printf "<-- $_"if $opt_v; + last if /^\s*$/; + } +} + + +sub urlencode { + local $_ = shift; + s/([^_=:,;<>()+.\w\-])/'%'.uc(unpack("H2",$1))/ge; + return $_; +} + + sub send_fex { my @to; my $file = ''; @@ -1194,7 +1606,7 @@ sub send_fex { if ($anonymous) { my $aok; - sendheader("$server:$port","OPTIONS FEX HTTP/1.1"); + sendheader("$server:$port","OPTIONS /FEX HTTP/1.1"); $_ = <$SH>||''; s/\r//; die "$0: no response from fex server $server\n" unless $_; @@ -1287,10 +1699,21 @@ sub send_fex { } if (@ARGV > 1 and not ($opt_a or $opt_s or $opt_d)) { - print "Archive name (name.tar, name.tgz or name.zip) or [ENTER] to send file for file:\n"; + print "Archive name (name.tar, name.tgz or name.zip) or [RETURN] to send file for file:\n"; $opt_a = ; $opt_a =~ s/^\s+//; $opt_a =~ s/\s+$//; + $opt_a =~ s/\//_/g; + } + + if ($macos and not $opt_a and -d "@ARGV") { + my $dir = "@ARGV"; + my $qdir = quote($dir); + if (`du -s $qdir` =~ /^(\d+)/ and $1 < 2**21) { + $opt_a = "$dir.zip"; + } else { + $opt_a = "$dir.tar"; + } } if ($opt_s) { @@ -1317,7 +1740,7 @@ sub send_fex { $opt_a =~ s:.*/::g; } foreach my $file (@ARGV) { - die "$0: cannot read $file\n" unless -l $file or -r $file; + die "$0: cannot read \"$file\"\n" unless -l $file or -r $file; } $opt_a .= ".$atype" if $opt_a !~ /\.$atype$/; $transferfile = "$tmpdir/$opt_a"; @@ -1329,6 +1752,10 @@ sub send_fex { # else { system(qw'7z a -tzip -mm=copy',$transferfile,@ARGV) } system(qw'7z a -tzip',$transferfile,@ARGV); @files = ($transferfile); + } elsif ($macos and scalar(@ARGV) == 1) { + ## ditto-zip is now handled by formdatapost() + system 'true'; + @files = ($opt_a); } else { # zip archives must be < 2 GB, so split as necessary @files = zipsplit($transferfile,@ARGV); @@ -1358,6 +1785,7 @@ sub send_fex { } else { ## tar is now handled by formdatapost() # system(qw'tar cvf',$transferfile,@ARGV); + system 'true'; @files = ($opt_a); } } elsif ($atype eq 'tgz') { @@ -1403,12 +1831,12 @@ sub send_fex { unless ($opt_d) { unless (-f $file) { if (-e $file) { - die "$0: $file is not a regular file, try option -a\n" + die "$0: \"$file\" is not a regular file, try option -a\n" } else { - die "$0: $file does not exist\n"; + die "$0: \"$file\" does not exist\n"; } } - die "$0: cannot read $file\n" unless -r $file; + die "$0: cannot read \"$file\"\n" unless -r $file; } push @files,$file; } @@ -1418,7 +1846,7 @@ sub send_fex { foreach my $file (@files) { my @s = stat($file); unless (@s and ($s[2] & S_IROTH) and -r $file) { - die "$0: $file is not world readable\n"; + die "$0: \"$file\" is not world readable\n"; } } } @@ -1426,7 +1854,7 @@ sub send_fex { foreach my $file (@files) { sleep 1; # do not overrun server! unless (-s $file or $opt_d or $opt_a or $opt_s) { - die "$0: cannot send empty file $file\n"; + die "$0: cannot send empty file \"$file\"\n"; } female_mode("send file $file?") if $opt_F; @r = formdatapost( @@ -1443,15 +1871,32 @@ sub send_fex { if (not @r or not grep /\w/,@r) { die "$0: no response from server\n"; } + next if "@r" eq '0'; # already transfered if (($r) = grep /^ERROR:/,@r) { if ($anonymous and $r =~ /purge it/) { die "$0: file is already on server for $to - use another anonymous recipent\n"; + } elsif ($r =~ /timeout/i) { + close $SH; + retry("timed out"); } else { $r =~ s/.*?:\s*//; $r =~ s/<.+?>//g; die "$0: server error: $r\n"; } } + unless ($opt_d) { + if (scalar(@r) == 1) { + die "$0: server error: @r\n"; + } else { + if ($r[0] !~ /HTTP.1.. 2/) { + if ($r[0] =~ /HTTP.[\s\d.]+(.+)/) { + die "$0: server error: $1\n"; + } else { + die "$0: server error:\n".join("\n",@r)."\n"; + } + } + } + } if (($r) = grep /

    \Q$file/,@r) { $r =~ s/<.+?>//g; print "$r\n"; @@ -1459,7 +1904,8 @@ sub send_fex { if ($opt_a !~ /^afex_\d+\.tar$/ and $file !~ /afex_\d+\.tar$/) { # print grep({s/^(X-Recipient:.*\((.+)\))/Parameters: $2\n/i} @r); my $nonot = 0; - my ($recipient,$location); + my $recipient = ''; + my $location = ''; foreach (@r) { if (/^(X-)?(Recipient.*)/i) { $recipient = $2; @@ -1468,23 +1914,13 @@ sub send_fex { } if (/^(X-)?(Location.*)/i) { $location = $2; - if ($from eq $to or $from =~ /^\Q$to\E@/i - or $nomail or $anonymous or $nonot) { - print "$recipient\n"; - print "$location\n"; - } } } - unless ($opt_d or $location) { - if (scalar(@r) == 1) { - die "$0: server error: @r\n"; - } else { - if ($r[0] !~ /HTTP.1.. 2/ and $r[0] =~ /HTTP.[\s\d.]+(.+)/) { - die "$0: server error: $1\n"; - } else { - die "$0: server error:\n".join("\n",@r)."\n"; - } - } + if ($from eq $to or $from =~ /^\Q$to\E@/i + or $nomail or $anonymous or $nonot) + { + print "$recipient\n" if $recipient; + print "$location\n" if $location; } } } @@ -1518,10 +1954,10 @@ sub forward { open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; while (<$fexlist>) { - if (/^\s*(\d+)\) (\w+) \[\d+ d\] (.+)/ and $1 eq $opt_f) { + if (/^\s*(\d+)\) (\w+) .\s*\d+ d. ([+-] )?(.+)/ and $1 eq $opt_f) { $n = $1; $dkey = $2; - $file = $3; + $file = $4; if ($file =~ s/ "(.*)"$//) { $opt_C ||= $1 if $1 ne 'NOMAIL'; } @@ -1572,7 +2008,7 @@ sub renotify { open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; while (<$fexlist>) { - if (/^\s*(\d+)\) (\w+) \[\d+ d\] (.+)/ and $1 eq $opt_N) { + if (/^\s*(\d+)\) (\w+) .\s*\d+ d. (.+)/ and $1 eq $opt_N) { $n = $1; $dkey = $2; last; @@ -1628,7 +2064,7 @@ sub modify { open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; while (<$fexlist>) { - if (/^\s*(\d+)\) (\w+) \[\d+ d\] (.+)/ and $1 eq $opt_x) { + if (/^\s*(\d+)\) (\w+) .\s*\d+ d. (.+)/ and $1 eq $opt_x) { $n = $1; $dkey = $2; $file = $3; @@ -1738,7 +2174,7 @@ sub get_xx { sub formdatapost { my %P = @_; - my ($boundary,$filename,$filesize,$length,$buf,$file,$fpsize,$resume,$seek); + my ($boundary,$filename,$length,$buf,$file,$fpsize,$resume,$seek); my ($flink); my (@hh,@hb,@r,@pv,$to); my ($bytes,$t,$bt); @@ -1746,9 +2182,11 @@ sub formdatapost { my $bs = 2**16; # blocksize for reading and sending file my $fileid = int(time); my $chunk = 0; + my $filesize = 0; my $connection = ''; my $pct = ''; - my ($tar,$aname,$atype,$tarlist,$tarerror,$location,$transferfile); + my $dittodir = '.'; + my ($tar,$ditto,$aname,$atype,$list,$error,$location,$transferfile); local $_; if (defined($file = $P{file})) { @@ -1771,7 +2209,7 @@ sub formdatapost { $of =~ s/([^_\w\.\-])/\\$1/g; shelldo("gzip <$if>$of"); $filesize = -s $transferfile; - die "$0: cannot gzip $file\n" unless $filesize; + die "$0: cannot gzip \"$file\"\n" unless $filesize; $file = $transferfile; } @@ -1779,12 +2217,12 @@ sub formdatapost { if (not $windoof and $opt_a and $file =~ /(.+)\.(tar|tgz)$/) { $aname = $1; $atype = $2; - $tarlist = "$tmpdir/$aname.list"; - $tarerror = "$tmpdir/$aname.error"; + $list = "$tmpdir/$aname.list"; + $error = "$tmpdir/$aname.error"; $tar = 'tar -cv'; $tar .= 'z' if $atype eq 'tgz'; if (`tar --help 2>/dev/null` =~ /--index-file/) { - $tar .= " --index-file=$tarlist -f-"; + $tar .= " --index-file=$list -f-"; } else { $tar .= " -f-"; } @@ -1794,12 +2232,10 @@ sub formdatapost { } } foreach (@ARGV) { - $file = $_; - $file =~ s/([^\w\-\@\#%,.=+~_:])/\\$1/g; - $tar .= ' '.$file; + $tar .= ' '.quote($_); } # print "calculating archive size... "; - open $tar,"$tar 2>$tarerror|" or die "$0: cannot run tar - $!\n"; + open $tar,"$tar 2>$error|" or die "$0: cannot run tar - $!\n"; $t0 = int(time) if -t STDOUT; while ($b = read $tar,$_,$bs) { $filesize += $b; @@ -1814,12 +2250,12 @@ sub formdatapost { printf "Archive size: %d MB\n",int($filesize/M) if -t STDOUT; unless (close $tar) { $_ = ''; - if (open $tarerror,$tarerror) { + if (open $error,$error) { local $/; - $_ = <$tarerror>; - close $tarerror; + $_ = <$error>; + close $error; } - unlink $tarlist,$tarerror; + unlink $list,$error; die "$0: tar error:\n$_"; } $file = "$aname.$atype"; @@ -1827,6 +2263,58 @@ sub formdatapost { undef $SH; # force reconnect (timeout!) } + # special file: ditto-zip-on-the-fly + # ditto: Can't archive multiple sources + elsif ($macos and $opt_a and $file =~ /(.+)\.(zip)$/ and scalar(@ARGV) == 1) { + $aname = $1; + $atype = $2; + $list = "$tmpdir/$aname.list"; + $error = "$tmpdir/$aname.error"; + $ditto = 'ditto -c -k --sequesterRsrc --keepParent'; + if (-d "@ARGV" and "@ARGV" =~ m:^(.+)/(.+):) { + $dittodir = $1; + $file = $2; + $file =~ s/([^\w\-\@\#%,.=+_:])/\\$1/g; + $ditto .= ' '.$file; + } else { + foreach (@ARGV) { + $file = $_; + $file =~ s/([^\w\-\@\#%,.=+_:])/\\$1/g; + $ditto .= ' '.$file; + } + } + # print "calculating archive size... "; + debug("cd $dittodir;$ditto -"); + open $ditto,"cd $dittodir;$ditto - 2>$error|" + or die "$0: cannot run ditto - $!\n"; + $t0 = int(time) if -t STDOUT; + while ($b = read $ditto,$_,$bs) { + $filesize += $b; + if ($t0) { + $t1 = int(time); + if ($t1>$t0) { + printf "Archive size: %d MB\r",int($filesize/M); + $t0 = $t1; + } + } + } + printf "Archive size: %d MB\n",int($filesize/M) if -t STDOUT; + unless (close $ditto) { + $_ = ''; + if (-s $error and open $error,$error) { + local $/; + $_ = <$error>; + close $error; + } + unlink $list,$error; + die "$0: ditto-zip error:\n$_"; + } + unlink $list,$error; + $file = "$aname.$atype"; + $filename = encode_utf8($file); + undef $SH; # force reconnect (timeout!) + } + # single file else { $filename = encode_utf8(${'opt_='} || $file); @@ -1840,7 +2328,7 @@ sub formdatapost { if ($opt_d) { $filesize = 0; } elsif (not $opt_g and not $opt_s) { - $filesize = -s $file or die "$0: $file is empty or not readable\n"; + $filesize = -s $file or die "$0: \"$file\" is empty or not readable\n"; } } @@ -1880,20 +2368,28 @@ sub formdatapost { $P{id} = $sid; # ugly hack! + $filename =~ s/\\/_/g; # \ is a illegal character for fexsrv + # ask server if this file has been already sent - if ($file and not $xx and not - ($opt_s or $opt_g or $opt_o or $opt_d or $opt_l or $opt_L or ${'opt_/'})) - { - ($seek,$location) = query_file($server,$port,$frecipient||$P{to},$P{from}, - $P{id},$filename,$fileid); - if ($filesize == $seek) { - print "Location: $location\n" if $location and $nomail; - warn "$0: $file has been already transferred\n"; - return $file; - } elsif ($seek and $seek < $filesize) { - $resume = " (resuming at byte $seek)"; - } elsif ($filesize <= $seek) { - $seek = 0; + if ($file and not $xx) { + if (not $opt_d and $opt_o) { + # delete before overwrite + delete_file($from,$to,$filename); + serverconnect($server,$port); + query_sid($server,$port) unless $anonymous; + $P{id} = $sid; # ugly hack! + } elsif (not($opt_s or $opt_g or $opt_d or $opt_l or $opt_L or ${'opt_/'})) { + ($seek,$location) = query_file($server,$port, + $frecipient||$P{to},$P{from},$P{id},$filename,$fileid); + if ($filesize == $seek) { + print "Location: $location\n" if $location and $nomail; + warn "$0: $file has been already transferred\n"; + return 0; + } elsif ($seek and $seek < $filesize) { + $resume = " (resuming at byte $seek)"; + } elsif ($filesize <= $seek) { + $seek = 0; + } } if ($proxy) { sleep 1; # do not overrun proxy @@ -1935,7 +2431,8 @@ sub formdatapost { push @hb,"--$boundary"; push @hb,"Content-Disposition: form-data; name=\"$name\""; push @hb,""; - push @hb,encode_utf8($P{$v}); + # push @hb,encode_utf8($P{$v}); + push @hb,$P{$v}; } } @@ -2027,10 +2524,10 @@ sub formdatapost { $tpid = fork(); if (defined $tpid and $tpid == 0) { sleep 1; - if (open $tarlist,$tarlist) { - # print "\n$tar|\n"; system "ls -l $tarlist"; - while ($tarlist) { - while (<$tarlist>) { + if (open $list,$list) { + # print "\n$tar|\n"; system "ls -l $list"; + while ($list) { + while (<$list>) { print ' 'x(length($file)+40),"\r",$_; } sleep 1; @@ -2044,13 +2541,19 @@ sub formdatapost { print "Fast forward to byte $seek (resuming)\n"; readahead($file,$seek); } + } elsif ($ditto) { + $ditto =~ s/ditto/ditto -V/; + open $file,"cd $dittodir;$ditto -|" or die "$0: cannot run ditto - $!\n"; + if ($seek) { + print "Fast forward to byte $seek (resuming)\n"; + readahead($file,$seek); + } } else { if ($opt_g) { - my $fileq = $file; - $fileq =~ s/([^\w\-\@\#%,.=+~_:])/\\$1/g; + my $fileq = quote($file); open $file,"gpg -e -r $to <$fileq|" or die "$0: cannot run gpg - $!\n"; } else { - open $file,$file or die "$0: cannot read $file - $!\n"; + open $file,$file or die "$0: cannot read \"$file\" - $!\n"; seek $file,$seek,0; } binmode $file; @@ -2072,7 +2575,11 @@ sub formdatapost { alarm(0); $bytes += $b; if ($filesize > 0 and $bytes+$seek > $filesize) { - die "$0: $file filesize has grown while uploading\n"; + if ($tpid) { + kill 9,$tpid; + unlink $list; + } + die "$0: \"$file\" filesize has grown while uploading\n"; } $bt += $b; $t2 = time; @@ -2121,12 +2628,26 @@ sub formdatapost { if ($tpid) { sleep 2; kill 9,$tpid; - unlink $tarlist; + unlink $list; } - + + if ($fileid =~ /[a-z]/ and not ($opt_s or $opt_g)) { + if ($opt_a) { + if ($fileid ne md5_hex(fmd(@ARGV))) { + print "\n" unless $opt_q; + die "$0: files have been modified while uploading\n"; + } + } else { + if ($fileid ne fileid($file)) { + print "\n" unless $opt_q; + die "$0: file has been modified while uploading\n"; + } + } + } + unless ($opt_q) { if (not $chunksize and $bytes+$seek < $filesize) { - die "$0: $file filesize has shrunk while uploading\n"; + die "$0: \"$file\" filesize has shrunk while uploading\n"; } if ($seek or $chunksize and $chunksize < $filesize) { @@ -2270,7 +2791,7 @@ sub zipsplit { $size = -s $file; if ($size > 2147480000) { unlink @zipfiles; - die "$0: $file too big for zip\n"; + die "$0: \"$file\" too big for zip\n"; } if ($zsize + $size > 2147000000) { push @zipfiles,zip($zipbase.'_'.$n.'.zip',@files); @@ -2336,7 +2857,7 @@ sub query_file { my $seek = 0; my $qfileid = ''; my ($head,$location); - my ($response,$fexsrv); + my ($response,$fexsrv,$cc); local $_; $to =~ s/,.*//; @@ -2377,11 +2898,17 @@ sub query_file { if (/^X-File-ID:\s+(.+)/) { $qfileid = $1 } if (/^X-Features:\s+(.+)/) { $features = $1 } if (/^X-Location:\s+(.+)/) { $location = $1 } + if (/^Connection: close/) { $cc = $_ } } # return true seek only if file is identified $seek = 0 if $qfileid and $qfileid ne $fileid; + if ($cc) { + serverconnect($server,$port); + $sid = $id; + } + return ($seek,$location); } @@ -2409,7 +2936,7 @@ sub edit_address_book { print {$ab} $AB{ADDRESS_BOOK}; close $ab; - system $editor,$ab; + system "$editor $ab"; exit unless -s $ab; $opt_o = $opt_A; @@ -2510,14 +3037,12 @@ sub query_sid { $sid = $id; - if ($port eq 443) { + if ($port eq 443 or $proxy) { return if $features; # early return if we know enough - $req = "OPTIONS FEX HTTP/1.1"; - } elsif ($proxy) { - return if $features; # early return if we know enough - $req = "GET $proxy_prefix/SID HTTP/1.1"; + $req = "OPTIONS /FEX HTTP/1.1"; + $req = "HEAD / HTTP/1.1"; } else { - $req = "GET SID HTTP/1.1"; + $req = "GET /SID HTTP/1.1"; } sendheader("$server:$port",$req,"User-Agent: $useragent"); @@ -2529,16 +3054,44 @@ sub query_sid { s/\r//; print "<-- $_" if $opt_v; - if (/^HTTP.* [25]0[01] /) { + if ($req =~ /OPTIONS/ and /^HTTP.* 502 /) { + # (reverse) proxy error + close $SH; + serverconnect($server,$port); + $req = "GET /SID HTTP/1.0"; + sendheader("$server:$port",$req,"User-Agent: $useragent"); + $_ = <$SH>; + unless (defined $_ and /\w/) { + print "\n" if $opt_v; + die "$0: no response from server\n"; + } + s/\r//; + print "<-- $_" if $opt_v; + while (<$SH>) { + s/\r//; + print "<-- $_" if $opt_v; + $features = $1 if /^X-Features: (.+)/; + $timeout = $1 if /^X-Timeout: (\d+)/; + last if /^\n/; + } + close $SH; + serverconnect($server,$port); + } elsif (/^HTTP.* [25]0[01] /) { if (not $proxy and $port ne 443 and /^HTTP.* 201 (.+)/) { $sid = 'MD5H:'.md5_hex($id.$1); } + my $cc; while (<$SH>) { s/\r//; print "<-- $_" if $opt_v; $features = $1 if /^X-Features: (.+)/; $timeout = $1 if /^X-Timeout: (\d+)/; - last if /^\n/; + $cc = $_ if /^Connection: close/; + last if /^\n/; + } + if ($cc) { + serverconnect($server,$port); + $sid = $id; } } elsif (/^HTTP.* 301 /) { while (<$SH>) { last if /Location/ } @@ -2588,15 +3141,15 @@ sub xxget { die "$0: no Content-Length in server-reply\n" unless $cl; - open F,">$save" or die "$0: cannot write to $save - $!\n"; - binmode F; + open $save,">$save" or die "$0: cannot write to $save - $!\n"; + binmode $save; $t0 = $t1 = int(time); $tso = ''; while ($b = read($SH,$_,$bs)) { $B += $b; - print F; + print {$save} $_; if (int(time) > $t1) { $t1 = int(time); $ts = ts($B,$cl); @@ -2609,7 +3162,7 @@ sub xxget { } print STDERR ts($B,$cl),"\n"; - close F; + close $save; } @@ -2745,10 +3298,16 @@ sub readahead { } -# fileid is inode and mtime sub fileid { - my @s = stat(shift); - return @s ? $s[1].$s[9] : int(time); + my $file = shift; + my @s = stat($file); + + if (@s) { + return md5_hex($file.$s[0].$s[1].$s[7].$s[9]); + } else { + warn "$0: $file - $!\n"; + return int(time); + } } @@ -2768,7 +3327,7 @@ sub get_mutt_alias { s/.*\s+//; s/[<>]//g; if (/,/) { - warn "$0: ignoring mutt multi-alias $to = $alias\n"; + warn "$0: ignoring mutt multi-alias $to = $_\n"; last; } if (/@/) { @@ -2783,7 +3342,7 @@ sub get_mutt_alias { } -# collect file meta data (filename, inode, mtime) +# collect (hashed) file meta data sub fmd { my @files = @_; my ($file,$dir); @@ -2796,7 +3355,7 @@ sub fmd { while (defined ($file = readdir($dir))) { next if $file eq '..'; if ($file eq '.') { - $fmd .= $file.fileid($dir); + $fmd .= fileid($dir); } else { $fmd .= fmd("$dir/$file"); } @@ -2804,7 +3363,7 @@ sub fmd { closedir $dir; } } else { - $fmd .= $file.fileid($file); + $fmd .= fileid($file); } } @@ -2862,8 +3421,8 @@ sub http_response { unless (defined $_ and /\w/) { die "$0: no response from server\n"; } - print "<-- $_\n" if $opt_v; s/\r?\n//; + print "<-- $_\n" if $opt_v; # CGI fatalsToBrowser if (/^HTTP.* 500/) { @r = <$SH> unless @r; @@ -2883,7 +3442,6 @@ sub http_response { die "$0: server error: $error\n"; } - print "<-- $_\n" if $opt_v; return $_; } @@ -2901,12 +3459,11 @@ sub update { local $/; open $0,$0 or die "cannot read $0 - $!\n"; - $_ = <$0>; + $cfc = <$0>; close $0; - s/.*\n$cfb\n//s; - $cfc = $_; + $cfc =~ s/.*\n$cfb\n//s; - foreach my $p (qw(fexget sexsend)) { + foreach my $p (qw'fexget sexsend') { open $p,$p or die "cannot read $p - $!\n"; $_ = <$p>; close $p; @@ -2917,7 +3474,7 @@ sub update { close $p; } - exec "l $0 fexget sexsend"; + exec "l fexsend fexget sexsend"; exit; } @@ -3039,6 +3596,7 @@ sub tcpconnect { if ($SH) { autoflush $SH 1; + binmode $SH; } else { die "$0: cannot connect $server:$port - $@\n"; } @@ -3095,6 +3653,18 @@ sub nvtsend { } +sub quote { + local $_ = shift; + s/([^\w\@\/%^,.=+_:+-])/\\$1/g; + return $_; +} + + +sub debug { + print "## DEBUG: @_\n" if $DEBUG; +} + + # from MIME::Base64::Perl sub encode_b64 { my $res = ""; diff --git a/htdocs/download/sexsend b/htdocs/download/sexsend index ff3f1ed..d9fe821 100755 --- a/htdocs/download/sexsend +++ b/htdocs/download/sexsend @@ -19,7 +19,8 @@ use constant M => 2**20; eval 'use Net::INET6Glue::INET_is_INET6'; -our $version = 20150826; +our $version = 20160104; +our $DEBUG = $ENV{DEBUG}; my %SSL = (SSL_version => 'TLSv1'); my $sigpipe; @@ -142,6 +143,8 @@ if ($0 eq 'sexxx') { } } elsif ($0 eq 'sexget' or $0 eq 'fuckme') { + + $opt_g = 0; getopts('hgvVdu:') or die $usage; die $usage if $opt_h; @@ -175,7 +178,7 @@ if ($0 eq 'sexxx') { } else { # sexsend - $opt_g = 1; + $opt_g = 0; getopts('hguvqVTt:') or die $usage; die $usage if $opt_h; @@ -605,15 +608,9 @@ sub serverconnect { my $connect = "CONNECT $server:$port HTTP/1.1"; local $_; - if ($opt_v and $port == 443 and %SSL) { - foreach my $v (keys %SSL) { - printf "%s => %s\n",$v,$SSL{$v}; - } - } - if ($proxy) { tcpconnect(split(':',$proxy)); - if ($port == 443) { + if ($https) { printf "--> %s\n",$connect if $opt_v; nvtsend($connect,""); $_ = <$SH>; @@ -622,14 +619,13 @@ sub serverconnect { unless (/^HTTP.1.. 200/) { die "$0: proxy error : $_"; } - eval "use IO::Socket::SSL"; - die "$0: cannot load IO::Socket::SSL\n" if $@; + &enable_ssl; $SH = IO::Socket::SSL->start_SSL($SH,%SSL); } } else { tcpconnect($server,$port); } -# if ($port == 443 and $opt_v) { +# if ($https and $opt_v) { # printf "%s\n",$SH->get_cipher(); # } } @@ -644,10 +640,9 @@ sub tcpconnect { undef $SH; } - if ($port == 443) { + if ($https) { # eval "use IO::Socket::SSL qw(debug3)"; - eval "use IO::Socket::SSL"; - die "$0: cannot load IO::Socket::SSL\n" if $@; + &enable_ssl; $SH = IO::Socket::SSL->new( PeerAddr => $server, PeerPort => $port, @@ -664,6 +659,7 @@ sub tcpconnect { if ($SH) { autoflush $SH 1; + binmode $SH; } else { die "$0: cannot connect $server:$port - $@\n"; } @@ -672,6 +668,18 @@ sub tcpconnect { } +sub enable_ssl { + eval "use IO::Socket::SSL"; + die "$0: cannot load IO::Socket::SSL\n" if $@; + eval '$SSL{SSL_verify_mode} = 0 if Net::SSLeay::SSLeay() <= 9470143'; + if ($opt_v) { + foreach my $v (keys %SSL) { + printf "%s => %s\n",$v,$SSL{$v}; + } + } +} + + sub sendheader { my $sp = shift; my @head = @_; @@ -708,6 +716,18 @@ sub nvtsend { } +sub quote { + local $_ = shift; + s/([^\w\@\/%^,.=+_:+-])/\\$1/g; + return $_; +} + + +sub debug { + print "## DEBUG: @_\n" if $DEBUG; +} + + # from MIME::Base64::Perl sub encode_b64 { my $res = ""; diff --git a/htdocs/fexit.html b/htdocs/fexit.html new file mode 100644 index 0000000..3bbfeb0 --- /dev/null +++ b/htdocs/fexit.html @@ -0,0 +1,44 @@ + + + fexit + + + + +<<$ENV{FEXIT} = 'http://fex.belwue.de/download/fexit.exe';'';>> + +

    fexit for Windows

    + +fexit is a F*EX +client for sending files of any size to any e-mail address.
    +fexit can also send directories or +download files and resume the upload or download after link failures, +which your webbrowser cannot do. +

    +You can start fexit via Windows explorer or +via command console (cmd).
    +You can also drag files or directories to the fexit icon with the Windows +explorer. +

    +#if $ENV{ID} +When you run fexit for the first time you are +asked for the "F*EX server URL". You can enter your personal URL: +

    + +<<"$ENV{PROTO}://$ENV{HTTP_HOST}/fup/".b64("from=$ENV{USER}&id=$ENV{ID}")>> + +

    +(use your mouse for copy+paste) +

    +<> +#endif +##

    <>
    +
    +
    diff --git a/htdocs/fexitinstaller b/htdocs/fexitinstaller
    new file mode 100644
    index 0000000..3054e57
    --- /dev/null
    +++ b/htdocs/fexitinstaller
    @@ -0,0 +1,34 @@
    +#!/usr/bin/perl -w
    +
    +$user = $ENV{USER};
    +$id = $ENV{ID};
    +$url = "$ENV{PROTO}://$ENV{HTTP_HOST}";
    +$fi = 'fexitinstaller.cmd';
    +$fe = 'http://fex.belwue.de/download/fexit.exe';
    +$ps = '%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe';
    +$cmd = <id
    +  echo $user>>id
    +  echo $id>>id
    +)
    +cd "%USERPROFILE%\\Desktop"
    +$ps -command "& { (New-Object Net.WebClient).DownloadFile('$fe','fexit.exe') }"
    +\@explorer "%USERPROFILE%\\Desktop"
    +\@set /p x="press [ENTER]"
    +EOD
    +$cmd =~ s/\n/\r\n/g;
    +
    +if (chdir "$spooldir/$user" and open $fi,'>',$fi) {
    +  print {$fi} $cmd;
    +  close $fi;
    +  system "$FEXHOME/bin/fexsend ".
    +         "-oKq -C 'fexit for your Windows desktop' $fi $user >/dev/null";
    +  if ($? == 0) {
    +    print "

    \n"; + print "

    A fexit installer has been sent to you. Check your email.

    \n"; + } + unlink $fi; +} diff --git a/htdocs/macfexsend.html b/htdocs/macfexsend.html new file mode 100644 index 0000000..2c17c78 --- /dev/null +++ b/htdocs/macfexsend.html @@ -0,0 +1,65 @@ + + + fexsend for Mac + + + + +

    fexsend for Apple Macintosh OS X

    + +fexsend is a F*EX client for sending files of +any size to any e-mail address.
    +fexsend can also send directories and resume the upload +after a link failure, which your webbrowser cannot do. + +

    To install fexsend:

    +
      +
    1. start a "Terminal":
      + go to Finder, press ⇧⌘U to open the Utility + Application folder and double-click Terminal.app with left + mouse button +

      +

    2. copy this code into the Terminal window: +
      curl http://fex.belwue.de/download/fexsend.command|bash
      + Do not forget to enter [RETURN] +

      + You can use your mouse for copying: +

      +

        +
      1. move your mouse cursor with hold left mouse button over the + code obove (the code will be marked) +
      2. press ⌘C +
      3. move your mouse cursor into the Terminal window +
      4. click left mouse button +
      5. press ⌘V +
      +
    + +

    To run fexsend:

    +
      +
    1. in Finder click Desktop with left mouse button +
    2. double-click fexsend.command with left mouse button +
    +

    +<< + if ($ENV{ID}) { + my $url = "$ENV{PROTO}://$ENV{HTTP_HOST}/fup/" + . b64("from=$ENV{USER}&id=$ENV{ID}"); + qq( + When asked for "F*EX server URL" enter: +

    + $url +

    + (again, use your mouse for copy+paste) + ); + } +>> + + diff --git a/htdocs/tools.html b/htdocs/tools.html index 2f41744..84e377c 100644 --- a/htdocs/tools.html +++ b/htdocs/tools.html @@ -4,29 +4,49 @@

    F*EX tools

    -<<$ENV{TA}='http://fex.belwue.de';''>> +<<$ENV{TA} = 'http://fex.belwue.de';'';>> +#if $ENV{AKEY} +To use one of the following F*EX clients you must configure them. +See user config for your account data. +

    +#endif + +

    UNIX:

    - + +
    fexsend - UNIX CLI client for sending files (with many + client for sending files (with many additional features)
    fexget - UNIX CLI client for receiving files (with many + client for receiving files (with many additional features)
    fexget - Windows CLI client for receiving files
    sexsend, sexget - UNIX CLI clients for sending and receiving streams
    clients for sending and receiving streams
    +

    +

    Windows:

    + + +
    fexit + client for sending and receiving files +
    +

    +

    Macintosh:

    + +
    fexsend.command + client for sending files and directories

    -In opposite to most web browsers all these clients can handle files -greater than 2 GB and are able to resume interrupted up/downloads. +In opposite to many web browsers all these clients can handle files +or directories greater than 2 GB and are able to resume interrupted +up/downloads.

    Hint for UNIX users:

      wget -qO- http://$HTTP_HOST$/xx.tar | tar xvf -
    @@ -41,5 +61,13 @@ also installs the client programs for print "http://fex.rus.uni-stuttgart.de" unless -s "$docdir$a"; print "$a\">anonymous usage"; >> +##
    +##
    +## <<
    +##  #while (($v,$vv) = each %ENV) { printf "%s = %s\n",$v,$vv if $vv !~ /\n/ }
    +##  #foreach $v (qw'AKEY USER ID') { printf "$v = %s\n",$ENV{$v} }
    +##  '';
    +## >>
    +## 
    diff --git a/htdocs/version b/htdocs/version index 056cc38..366b2e9 100644 --- a/htdocs/version +++ b/htdocs/version @@ -1 +1 @@ -fex-20150826 +fex-20160104 diff --git a/install b/install index 6f0bb62..87dc2fe 100755 --- a/install +++ b/install @@ -123,7 +123,14 @@ print "prerequisites checked, ok\n"; unless (getpwnam('fex')) { print "creating user fex\n"; - system 'useradd -s /bin/bash -c "File EXchange" -m fex'; + system 'groupadd -g 80 fex 2>/dev/null || groupadd fex'; + my @g = getgrnam('fex') or die "$0: cannot groupadd fex\n"; + my $gid = $g[2]; + if (getpwuid($gid)) { + system "useradd -s /bin/bash -c 'File EXchange' -g $gid -m fex" + } else { + system "useradd -s /bin/bash -c 'File EXchange' -u $gid -g $gid -m fex" + } exit $? if $?; } @@ -213,6 +220,10 @@ if (-d "$FEXHOME/spool") { mkdir "$FEXHOME/spool",0700 or die "cannot mkdir $FEXHOME/spool - $!\n"; mkdir "$FEXHOME/spool/.error",0700; } +foreach my $dir (qw'.dkeys .ukeys .akeys .skeys .gkeys .xkeys .locks') { + mkdir "$FEXHOME/spool/$dir",0700; +} + chownr('fex',"$FEXHOME/spool/."); # fex-VM? @@ -316,6 +327,7 @@ if (@locales = glob "locale/*/lib/fup.pl") { chownr('fex',"$FEXHOME/locale/$locale"); $hl = "$FEXHOME/htdocs/locale/$locale"; symlink "$FEXHOME/locale/$locale/htdocs",$hl unless -l $hl; + chownr('fex',"$FEXHOME/htdocs/locale/$locale"); } else { push @nlocales,"./install $1\n"; } diff --git a/lib/dop b/lib/dop index 20df28e..b41dbc1 100755 --- a/lib/dop +++ b/lib/dop @@ -12,6 +12,7 @@ use CGI::Carp qw(fatalsToBrowser); use Fcntl qw(:flock :seek :mode); use POSIX qw(strftime locale_h); use Cwd qw(getcwd abs_path); +use utf8; # import from fex.pp our ($bs,$tmpdir,@doc_dirs); @@ -98,9 +99,10 @@ sub http_output { @files = ("$1.tar"); open $file,'-|',qw'gzip -c',@files or http_error(503); } elsif ($file =~ /(.+)\.(tar|tgz|zip)$/ and - @s = lstat($streamfile = "$1.stream") and $s[4] == $<) + @s = lstat($streamfile = "$1.stream") and + ($s[4] == $< or $s[4] == 0)) { - # streaming file (only if it is owned by user fex) + # streaming file chdir dirname($file); security_check($file); if (-l $streamfile and readlink($streamfile) =~ /^:(.+):$/) { diff --git a/lib/fex.ph b/lib/fex.ph index 585e291..8c3ee12 100644 --- a/lib/fex.ph +++ b/lib/fex.ph @@ -34,7 +34,7 @@ $mailmode = 'AUTO'; ## optional: your mail domain ## if set it will be used as domain for every user without domain ## local_user ==> local_user@$mdomain -## if not set, addresses without domains produce an error +## if not set, addresses without domain produce an error # $mdomain = 'MY.MAIL.DOMAIN'; # $admin = 'fexmaster@'.$mdomain; diff --git a/lib/fex.pp b/lib/fex.pp index c6f0562..be911d2 100644 --- a/lib/fex.pp +++ b/lib/fex.pp @@ -1,6 +1,7 @@ # -*- perl -*- use 5.008; +use utf8; use Fcntl qw':flock :seek :mode'; use IO::Handle; use IPC::Open3; @@ -115,13 +116,13 @@ $keep = $keep_default ||= $keep || 5; $fra = $ENV{REMOTE_ADDR} || ''; $sid = $ENV{SID} || ''; -mkdirp($dkeydir = "$spooldir/.dkeys"); # download keys -mkdirp($ukeydir = "$spooldir/.ukeys"); # upload keys -mkdirp($akeydir = "$spooldir/.akeys"); # authentification keys -mkdirp($skeydir = "$spooldir/.skeys"); # subuser authentification keys -mkdirp($gkeydir = "$spooldir/.gkeys"); # group authentification keys -mkdirp($xkeydir = "$spooldir/.xkeys"); # extra download keys -mkdirp($lockdir = "$spooldir/.locks"); # download lock files +$dkeydir = "$spooldir/.dkeys"; # download keys +$ukeydir = "$spooldir/.ukeys"; # upload keys +$akeydir = "$spooldir/.akeys"; # authentification keys +$skeydir = "$spooldir/.skeys"; # subuser authentification keys +$gkeydir = "$spooldir/.gkeys"; # group authentification keys +$xkeydir = "$spooldir/.xkeys"; # extra download keys +$lockdir = "$spooldir/.locks"; # download lock files if (my $ra = $ENV{REMOTE_ADDR} and $max_fail) { mkdirp("$spooldir/.fail"); @@ -283,8 +284,9 @@ sub http_header { nvt_print("Strict-Transport-Security: max-age=2851200; preload"); } if ($use_cookies) { + $akey = md5_hex("$from:$id") if $id and $from; if ($akey) { - nvt_print("Set-Cookie: akey=$akey; Max-Age=9999; Discard"); + nvt_print("Set-Cookie: akey=$akey; path=/; Max-Age=9999; Discard"); } # if ($skey) { # nvt_print("Set-Cookie: skey=$skey; Max-Age=9999; Discard"); @@ -871,12 +873,15 @@ sub debuglog { $debuglog = sprintf("%s/%s_%s_%s.%s", $ddir,time,$$,$ENV{REQUESTCOUNT}||0,$prg); $debuglog =~ s/\s/_/g; + # http://perldoc.perl.org/perlunifaq.html#What-is-a-%22wide-character%22%3f # open $debuglog,'>>:encoding(UTF-8)',$debuglog or return; open $debuglog,'>>',$debuglog or return; + # binmode($debuglog,":utf8"); autoflush $debuglog 1; # printf {$debuglog} "\n### %s ###\n",isodate(time); } while ($_ = shift @_) { + $_ = encode_utf8($_) if utf8::is_utf8($_); s/\n*$/\n/; s/<.+?>//g; # remove HTML print {$debuglog} $_; @@ -948,11 +953,11 @@ sub qqq { my $q = "[\'\"]"; # quote delimiter chars " and ' # remove first newline and look for default indention - s/^(\«(\d+)?)?\n//; + s/^((\d+)?)?\n//; $i = ' ' x ($2||0); # remove trailing spaces at end - s/[ \t]*\»?$//; + s/[ \t]*?$//; @s = split "\n"; @@ -1292,7 +1297,7 @@ sub gpg_encrypt { " -a -e -r $bcc -r $to" ) or return; - print {$po} $plain; + print {$po} "\n",$plain,"\n"; close $po; $enc .= $_ while <$pi>; @@ -1439,14 +1444,17 @@ sub notify { $data = "$dkeydir/$P{dkey}/data"; $size = $bytes = -s $data; return unless $size; - if ($nowarning) { - $warning = ''; - } else { - $warning = - "Please avoid download with Internet Explorer, ". - "because it has too many bugs.\n". - "We recommend Firefox or wget."; - } + $warning = + "We recommend fexget or fexit for download,\n". + "because these clients can resume the download after an interruption.\n". + "See $proto://$hostname/tools.html"; + # if ($nowarning) { + # $warning = ''; + # } else { + # $warning = + # "Please avoid download with Internet Explorer, ". + # "because it has too many bugs.\n\n"; + # } if ($filename =~ /\.(tar|zip|7z|arj|rar)$/) { $warning .= "\n\n". "$filename is a container file.\n". @@ -1543,17 +1551,16 @@ sub notify { or http_die("cannot start sendmail - $!"); } } + $comment .= "\n" if $comment; if ($comment =~ s/^!(shortmail|\.)!\s*//i - or (readlink "$to/\@NOTIFICATION"||'') =~ /short/i + or (readlink("$to/\@NOTIFICATION")||'') =~ /short/i ) { $body = qqq(qq( '$comment' - '' '$download' '$size' )); } else { - $comment = "Comment: $comment\n" if $comment; $disclaimer = slurp("$from/\@DISCLAIMER") || qqq(qq( '$warning' '' @@ -1564,6 +1571,7 @@ sub notify { )); $disclaimer .= "\n" . $::disclaimer if $::disclaimer; $body = qqq(qq( + '$comment' '$from has uploaded the file' ' "$filename"' '($size) for $receiver. Use' @@ -1571,7 +1579,6 @@ sub notify { '$download' 'to download this file within $days.' '' - '$comment' '$autodelete' '' '$disclaimer' @@ -1617,21 +1624,23 @@ sub notify { sub reactivation { my ($expire,$user) = @_; my $fexsend = "$FEXHOME/bin/fexsend"; + my $reactivation = "$FEXLIB/reactivation.txt"; return if $nomail; if (-x $fexsend) { + if ($locale) { + my $lr = "$FEXHOME/locale/$locale/lib/reactivation.txt"; + $reactivation = $lr if -f $lr and -s $lr; + } $fexsend .= " -M -D -k 30 -C" ." 'Your F*EX account has been inactive for $expire days," ." you must download this file to reactivate it." ." Otherwise your account will be deleted.'" - ." $FEXLIB/reactivation.txt $user"; + ." $reactivation $user"; # on error show STDOUT and STDERR - system "$fexsend >/dev/null 2>&1"; - if ($?) { - warn "$fexsend\n"; - system $fexsend; - } + my $fo = `$fexsend 2>&1`; + warn $fexsend.'\n'.$fo if $?; } else { warn "$0: cannot execute $fexsend for reactivation()\n"; } diff --git a/lib/fup.pl b/lib/fup.pl index 25ec8e1..24eccf7 100644 --- a/lib/fup.pl +++ b/lib/fup.pl @@ -24,9 +24,9 @@ After submission you will see an upload progress bar (if you have javascript enabled and popups allowed).

    NOTE: Many web browsers cannot upload files > 2 GB!
    -If your file is larger you have to use a special F*EX client +If your file is larger you have to use a special F*EX client or Firefox or Google Chrome which have no size limit.
    -You also need a F*EX client for resuming interrupted uploads. Your web browser cannot do this. +You also need a F*EX client for resuming interrupted uploads. Your web browser cannot do this.

    If you want to send more than one file, then put them in a zip or tar archive, e.g. with 7-Zip. diff --git a/locale/czech/lib/fup.pl b/locale/czech/lib/fup.pl index 9bf5dd9..82a7a5e 100644 --- a/locale/czech/lib/fup.pl +++ b/locale/czech/lib/fup.pl @@ -1,5 +1,7 @@ # config for F*EX CGI fup +use utf8; + $info_1 = $info_login = <


    F*EX (File EXchange) diff --git a/locale/french/htdocs/FAQ/admin.html b/locale/french/htdocs/FAQ/admin.html index a096645..a3b32d4 100644 --- a/locale/french/htdocs/FAQ/admin.html +++ b/locale/french/htdocs/FAQ/admin.html @@ -1,11 +1,18 @@ -F*EX FAQ + + + F*EX FAQ + ##

     ## << while (($v,$vv) = each %ENV) { print "$v = $vv\n" } >>
     ## 
    +Ce document est périmé. Merci de consulter +la FAQ anglaise +

    + << require "./faq.pl" or print $! >> diff --git a/locale/french/htdocs/FAQ/all.html b/locale/french/htdocs/FAQ/all.html index a096645..a3b32d4 100644 --- a/locale/french/htdocs/FAQ/all.html +++ b/locale/french/htdocs/FAQ/all.html @@ -1,11 +1,18 @@ -F*EX FAQ + + + F*EX FAQ + ##

     ## << while (($v,$vv) = each %ENV) { print "$v = $vv\n" } >>
     ## 
    +Ce document est périmé. Merci de consulter +la FAQ anglaise +

    + << require "./faq.pl" or print $! >> diff --git a/locale/french/htdocs/FAQ/faq.pl b/locale/french/htdocs/FAQ/faq.pl index 7770549..ba09ba8 100644 --- a/locale/french/htdocs/FAQ/faq.pl +++ b/locale/french/htdocs/FAQ/faq.pl @@ -1,3 +1,4 @@ +use utf8; package FAQ; my ($faq,$var,$env,$q,$a,$c,$s,$t,$n); @@ -9,11 +10,11 @@ my @sections = qw'Meta User Admin Misc'; print "\n"; -print '

    F*EX ', - " Frequently Asked Questions

    \n"; +print '

    F*EX '; +printf "Frequently Asked Questions: %s

    \n",ucfirst($faq); if ($faq ne 'local') { - print "

    \n"; + print "

    Sections: "; foreach $s (@sections,'All') { if ($s =~ /$faq/i) { print "$s\n"; @@ -24,6 +25,7 @@ if ($faq ne 'local') { print "

    \n"; } +print "


    \n"; print "\n"; foreach my $faq (@faq) { @@ -40,8 +42,10 @@ foreach my $faq (@faq) { }; ($q,$a) = split /A:\s*/; $q =~ s/[\s\n]+$//; + $q =~ s/^\s+//; $q =~ s! (/\w[\S]+/[\S]+)! $1!g; $a =~ s/[\s\n]+$/\n/; + $a =~ s/^\s+//; while ($a =~ s/^(\s*)\*/$1
      \n$1
    • /m) { while ($a =~ s/(
    • .*\n\s*)\*/$1
    • /g) {} $a =~ s:(.*\n)(\s*)(
    • [^\n]+\n):$1$2$3$2
    \n:s @@ -53,8 +57,8 @@ foreach my $faq (@faq) { # $a =~ s/^\s*
    \s*//mg; $a =~ s/<([^\s<>\@]+\@[\w.-]+)>/<$1><\/a>/g; $a =~ s! (/\w[\S]+/[\S]+)! $1!g; - $a =~ s!(https?://[\w-]+\.[^\s<>]+)![$1]!g or - $a =~ s!(https?://[^\s<>]+)!$1!g; + $a =~ s!(https?://[\w-]+\.[^\s<>()]+)![$1]!g or + $a =~ s!(https?://[^\s<>()]+)!$1!g; push @{$Q{$faq}},$q; push @{$A{$faq}},$a; } @@ -71,12 +75,18 @@ foreach $s (sections($faq)) { $t = $s if $faq eq 'all'; for ($n = 0; $n < scalar(@{$Q{$c}}); $n++) { - printf "\n", - $s,$n+1,$t,$n+1,${Q{$c}[$n]}; + $q = ${Q{$c}[$n]}; + $qa = anchor($q); + printf ''."\n", + $t,$n+1,$s,$n+1,$qa,$q; } } print "
    %s Q%d: %s
    '. + ''. + '%s Q%d:'. + '%s
    \n"; +print "


    \n"; foreach $s (sections($faq)) { @@ -86,14 +96,19 @@ foreach $s (sections($faq)) { $t = $s if $faq eq 'all'; for ($n = 0; $n < scalar(@{$Q{$c}}); $n++) { - print "


    \n"; + $q = ${Q{$c}[$n]}; + $qa = anchor($q); + print "

    \n"; print "\n"; - printf "\n", - $t,$n+1,$s,$n+1,${Q{$c}[$n]}; + printf "\n", + $t,$n+1,$s,$n+1,$qa,$q; printf "\n", $s,$n+1,${A{$c}[$n]}; - print "\n"; print "
    %s Q%d:%s
    ". + "%s Q%d:". + "". + "%s
    %s A%d:\n%s
    [Top]
    \n"; + print "[↑ Questions]\n"; } } @@ -117,3 +132,12 @@ sub pre { s/\s+$//; return "

    $_
    \n"; } + +sub anchor { + local $_ = shift; + s/<.+?>//g; + s/\(.+?\)//g; + s/\W/_/g; + s/_+$//; + return $_; +} diff --git a/locale/french/htdocs/FAQ/local.html b/locale/french/htdocs/FAQ/local.html index a096645..a3b32d4 100644 --- a/locale/french/htdocs/FAQ/local.html +++ b/locale/french/htdocs/FAQ/local.html @@ -1,11 +1,18 @@ -F*EX FAQ + + + F*EX FAQ + ##
     ## << while (($v,$vv) = each %ENV) { print "$v = $vv\n" } >>
     ## 
    +Ce document est périmé. Merci de consulter +la FAQ anglaise +

    + << require "./faq.pl" or print $! >> diff --git a/locale/french/htdocs/FAQ/meta.faq b/locale/french/htdocs/FAQ/meta.faq index 53b9153..0a19172 100644 --- a/locale/french/htdocs/FAQ/meta.faq +++ b/locale/french/htdocs/FAQ/meta.faq @@ -26,7 +26,7 @@ Q: Perl n'est-il pas trop lent pour faire tout ça ? A: fex.rus.uni-stuttgart.de tourne sur un ordinateur de bureau et est capable de gérer des uploads à plus de 300 MB/s. Essayer donc ça avec un serveur web généraliste comme Apache ! -Q: De quoi ais-je besoin de pour installer F*EX ? +Q: De quoi ais-je besoin pour installer F*EX ? A: D'une machine UNIX avec une entrée DNS et un service smtp fonctionnel. Vous devez être root sur la machine. Q: Qu'est-ce que DNS et smtp ? @@ -35,7 +35,7 @@ A: N'installez pas F*EX. Ce n'est pas fait pour vous. Q: Qui est l'auteur ? A: Ulli Horlacher framstag@rus.uni-stuttgart.de -Q: Quel est la licence de F*EX ? +Q: Quelle est la licence de F*EX ? A: Perl Artistic free software Q: Est-ce qu'il y a une mailing list F*EX ? diff --git a/locale/french/htdocs/FAQ/meta.html b/locale/french/htdocs/FAQ/meta.html index a096645..a3b32d4 100644 --- a/locale/french/htdocs/FAQ/meta.html +++ b/locale/french/htdocs/FAQ/meta.html @@ -1,11 +1,18 @@ -F*EX FAQ + + + F*EX FAQ + ##

     ## << while (($v,$vv) = each %ENV) { print "$v = $vv\n" } >>
     ## 
    +Ce document est périmé. Merci de consulter +la FAQ anglaise +

    + << require "./faq.pl" or print $! >> diff --git a/locale/french/htdocs/FAQ/misc.html b/locale/french/htdocs/FAQ/misc.html index a096645..a3b32d4 100644 --- a/locale/french/htdocs/FAQ/misc.html +++ b/locale/french/htdocs/FAQ/misc.html @@ -1,11 +1,18 @@ -F*EX FAQ + + + F*EX FAQ + ##

     ## << while (($v,$vv) = each %ENV) { print "$v = $vv\n" } >>
     ## 
    +Ce document est périmé. Merci de consulter +la FAQ anglaise +

    + << require "./faq.pl" or print $! >> diff --git a/locale/french/htdocs/FAQ/user.html b/locale/french/htdocs/FAQ/user.html index a096645..a3b32d4 100644 --- a/locale/french/htdocs/FAQ/user.html +++ b/locale/french/htdocs/FAQ/user.html @@ -1,11 +1,18 @@ -F*EX FAQ + + + F*EX FAQ + ##

     ## << while (($v,$vv) = each %ENV) { print "$v = $vv\n" } >>
     ## 
    +Ce document est périmé. Merci de consulter +la FAQ anglaise +

    + << require "./faq.pl" or print $! >> diff --git a/locale/french/lib/fup.pl b/locale/french/lib/fup.pl index fb72a49..62c0be3 100644 --- a/locale/french/lib/fup.pl +++ b/locale/french/lib/fup.pl @@ -1,5 +1,7 @@ # config for F*EX CGI fup +use utf8; + $info_1 = $info_login = <


    F*EX (File EXchange) diff --git a/locale/galician/lib/fup.pl b/locale/galician/lib/fup.pl index fb730ce..a20a1b3 100644 --- a/locale/galician/lib/fup.pl +++ b/locale/galician/lib/fup.pl @@ -1,5 +1,7 @@ # config for F*EX CGI fup +use utf8; + $info_1 = $info_login = <


    F*EX (File EXchange) diff --git a/locale/italian/lib/fup.pl b/locale/italian/lib/fup.pl index 7c44cd4..4002667 100644 --- a/locale/italian/lib/fup.pl +++ b/locale/italian/lib/fup.pl @@ -1,5 +1,7 @@ # configurazione per F*EX CGI fup +use utf8; + $info_1 = $info_login = <


    F*EX (File EXchange) diff --git a/locale/translations b/locale/translations index 0b1b6cf..0aed2d0 100644 --- a/locale/translations +++ b/locale/translations @@ -7,6 +7,15 @@ # czech: Michal Simunek # french: Jean-Baptiste Denis +'english' +'german' +'swabian' +'spanish' +'galician' +'italian' +'czech' +'french' + F*EX operation control ERROR F*EX Bedienungssteuerungs-Fehler F*EX Fehler bei dr Bedienongsschdeuerong @@ -232,14 +241,14 @@ Cambia il disclaimer affinchè venga spedito assieme all'e-mail di notifica Změnit odesílání zřeknutí se odpovědnosti u správy s upozorněním Changer la clause de non-responsabilité à envoyer avec le message de notification -Change your auth-ID to -Ändern Sie Ihre auth-ID in -Ändr die auth-ID noch -Cambie su auth-ID en -Cambie o seu auth-ID en -Cambia il tuo auth-ID in -Změnit si ověřovací ID auth-ID na -Changer votre auth-ID pour +Change your auth-ID to +Ändern Sie Ihre auth-ID in +Ändr die auth-ID noch +Cambie su auth-ID en +Cambie o seu auth-ID en +Cambia il tuo auth-ID in +Změnit si ověřovací ID auth-ID na +Changer votre auth-ID pour remember it merken @@ -351,7 +360,7 @@ Les emails de notifications sont maintenant au format simple Downloads will now be saved Downloads werden nun gespeichert -Downloads werdet ab jetzt gschpeichert +Ronderlads werdet ab jetzt gschpeichert Descargas están guardadas Downloads will now be saved I downloads saranno ora salvati @@ -360,7 +369,7 @@ Les téléchargements vont maintenant être sauvés Downloads will now be displayed (if possible) Downloads werden nun angezeigt (wenn möglich) -Downloads werdet ab jetzt ozeigt (wenns ghot) +Ronderlads werdet ab jetzt ozeigt (wenns ghot) Descargas están indicadas ahora (si posible) Downloads will now be displayed (if possible) I downloads saranno mostrati (se possibile) @@ -448,14 +457,14 @@ value="continua" value="pokračovat" value="continuer" ->User: ->Benutzer: ->Benutzr: ->Usuario: ->Usuario: ->Utente: ->Uživatel: ->Utilisateur: +#>User: +#>Benutzer: +#>Benutzr: +#>Usuario: +#>Usuario: +#>Utente: +#>Uživatel: +#>Utilisateur: user config ERROR ERROR Benutzer-Einstellungen @@ -862,6 +871,15 @@ Vedi http://$ENV{HTTP_HOST}/index.html per ulteriori informazioni Více informací o svém účtu získáte na http://$ENV{HTTP_HOST}/index.html Voir http://$ENV{HTTP_HOST}/index.html pour plus d'informations sur +See $proto: +Siehe $proto: +Guck uff $proto: +Vea $proto: +Véxase $proto: +Vedi $proto: +Více $proto: +Voir $proto: + Questions? ==> F*EX admin: $admin Fragen? ==> Kontaktieren Sie den F*EX Administrator: $admin Froga? ==> Belaeschtig ruhig dr F*EX Adminischdrator: $admin @@ -898,14 +916,14 @@ Un compte F*EX a été créé pour vous sur 'Používání 'Utilisez -See http://$ENV{HTTP_HOST}/ for more information about -Siehe http://$ENV{HTTP_HOST}/ fuer mehr Informationen ueber +See http://$ENV{HTTP_HOST}/index.html for more information about +Siehe http://$ENV{HTTP_HOST}/index.html fuer mehr Informationen ueber Guck halt uff http://$ENV{HTTP_HOST}/index.html wenn De meh wisse willsch ieber -Vea http://$ENV{HTTP_HOST}/ para obtener más información sobre -Véxase http://$ENV{HTTP_HOST}/ para obter más información sobre -Vedi http://$ENV{HTTP_HOST}/ per ulteriori informazioni -Informace, jak používat F*EX, naleznete na http://$ENV{HTTP_HOST}/ -Voir http://$ENV{HTTP_HOST}/ pour plus d'informations sur +Vea http://$ENV{HTTP_HOST}/index.html para obtener más información sobre +Véxase http://$ENV{HTTP_HOST}/index.html para obter más información sobre +Vedi http://$ENV{HTTP_HOST}/index.html per ulteriori informazioni +Informace, jak používat F*EX, naleznete na http://$ENV{HTTP_HOST}/index.html +Voir http://$ENV{HTTP_HOST}/index.html pour plus d'informations sur $notify not found in $gf $notify nicht gefunden in $gf @@ -988,15 +1006,6 @@ Edita il gruppo F*EX Upravit F*EX skupinu Éditez le groupe F*EX -A F*EX group is similar to a mailing list, but for files: -Eine F*EX-Gruppe ist einem E-Mail-Verteiler ähnlich, hier geht es jedoch um Daten-Verteilung: -A F*EX-Grupp isch so was wie en E-Mail-Verdoiler, allerdengs werde do Date verdoilt: -Un grupo F*EX es similar a una lista de correo, pero para ficheros: -Un grupo F*EX é semellante a unha lista de correo, pero para ficheiros: -Un gruppo F*EX e' simile ad una lista di distribuzione, ma per i file: -F*EX skupina je podobná poÅ¡tovní konferenci s tím rozdílem, že se odesílají soubory: -Un groupe F*EX est similaire à une liste de diffusion (mailing-list), mais pour des fichiers - When a member fexes a file to this list, Wenn ein Mitglied eine Datei für die Gruppe bereitstellt, Wenn oi Mitglied a Datei fier die reschdlich Grupp nuffläd @@ -1071,7 +1080,7 @@ effacer le fichier après un délai à la suite du téléchargement delete file $autodelete days after download Lösche Datei $autodelete Tage nach dem Download -Lösch Datei $autodelete Dag nochm ronderlada +Lösch Datei $autodelete Dag nochm Ronderlada borrar archivo $autodelete dias despues del descargar delete file $autodelete days after download cancella file $autodelete giorni dopo il download @@ -1093,7 +1102,7 @@ Dei nochgfrogte F*EX auth-ID fir $fup?from=$from isch: Su auth-ID de F*EX solicitada para $fup?from=$from es: O seu auth-ID de F*EX solicitado para $fup?from=$from é: Il tuo auth-ID di F*EX che hai richiesto per $fup?from=$from e': -Požadované ověřovací ID pro $fup?from=$from je: +VaÅ¡e požadované F*EX ověřovací ID pro $fup?from=$from je: Votre auth-ID F*EX pour $fup?from=$from est: Or use: @@ -1102,7 +1111,7 @@ Odr du nemsch: O use: Or use: Oppure usa -Nebo pou¾ijte: +Nebo použijte: Ou utilisez: Your reqested F*EX login is: @@ -1255,7 +1264,7 @@ Fichiers pour $to (*): >reenviar< >forward< >prosegui< ->pøedat< +>přeposlat< >faire suivre< Files for other e-mail addresses you own will not be listed here! @@ -1330,15 +1339,6 @@ Il vostro client sembra essere "$1", che e' incompatibile con F*EX e probabilmen Zřejmě používáte prohlížeč "$1", který není kompatibilní s F*EX a pravděpodobně nebude správně fungovat Votre client semble être "$1" qui est incompatible avec F*EX et ne va sans doute pas fonctionner -We recommend firefox -Wir empfehlen \"Firefox\" -Mir empfehled \"Firefox\" -Recomendamos firefox -Recomendamos firefox -Raccomandiamo firefox -Doporučujeme používat Firefox -Nous recommandons firefox - sender: Absender: Absendr: @@ -1479,55 +1479,55 @@ Alternativer Java Client (für Dateien größer als 2 GB oder z Alternativer Java Client (fier Dateia wo größer send als 2 GB oder zum Sende von meh als oiner Datei) Cliente java alternativo (par ficheros > 2 GB o envío de más de un fichero) Cliente java alternativo (para ficheiros > 2 GB ou envío de más dun fichero) -Client java alternativo (per file > 2 GB o per spedizioni di piu' di un file) +Client java alternativo (per file > 2 GB o per spedizioni di più di un file) Alternativní Java klient (pro soubory větší než 2 GB či pro odesílání více než jednoho souboru) Client Java alternatif (pour les fichiers > 2 GB ou envoyer plusieurs fichiers d'un coup) -Warning: the recipient must not be a mailing list, because after -Warnung: die Empfängeradresse darf keine Mailingliste sein, weil nach dem -Obacht: die Empfängeradress darf koi Mailinglischt sei, weil nochm -Warning: the recipient must not be a mailing list, because after -Warning: the recipient must not be a mailing list, because after -Warning: the recipient must not be a mailing list, because after -Warning: the recipient must not be a mailing list, because after -Warning: the recipient must not be a mailing list, because after - -download the file will be no more available -Download wird die Datei nicht mehr verfügbar sein -Ronderlada isch die Datei nemme verfügbar -download the file will be no more available -download the file will be no more available -download the file will be no more available -download the file will be no more available -download the file will be no more available - -Contact fexmaster -Kontaktieren Sie den fexmaster -Frog dr fexmaster -Contact fexmaster -Contact fexmaster -Contact fexmaster -Contact fexmaster -Contact fexmaster - -if you want to fex to a mailing list -wenn Sie an eine Mailingliste fexen wollen -wenn Du an a Mailinglischt fexa wilsch -if you want to fex to a mailing list -if you want to fex to a mailing list -if you want to fex to a mailing list -if you want to fex to a mailing list -if you want to fex to a mailing list +Warning: the recipient must not be a mailing list +Warnung: die Empfängeradresse darf keine Mailingliste sein +Obacht: die Empfängeradress darf koi Mailinglischt sei +Aviso: el destinatario no debe ser una lista de correo +Warning: the recipient must not be a mailing list +Attenzione: il destinatario non deve essere una lista di distribuzione +Upozornění: příjemce nemůže být poÅ¡tovní konference +Attention: le destinataire ne peut pas être une liste de diffusion + +because after download the file will be no more available +weil nach dem Download wird die Datei nicht mehr verfügbar sein +weil nochm Ronderlada isch die Datei nemme verfügbar +porque tras la descarga del fichero ya no estará disponible +because after download the file will be no more available +siccome dopo il download il file non sarà più disponibile +protože soubor již nebude po stažení dostupný +parce qu'après le téléchargement, le fichier ne sera plus disponible + +Contact fexmaster if you want to fex to a mailing list +Kontaktieren Sie den fexmaster wenn Sie an eine Mailingliste fexen wollen +Frog dr fexmaster wenn Du an a Mailinglischt fexa wilsch +Contacte con fexmaster si desea hacer un envío a una lista de correo +Contact fexmaster if you want to fex to a mailing list +Contatta fexmaster se vuoi fexare ad una lista di distribuzione +Chcete-li poslat soubor do poÅ¡tovní konference, kontaktujte fexmastera +Contacter fexmaster si vous voulez fexer à une liste de diffusion he can allow multiple downloads for specific addresses er kann für bestimmte Adressen einen mehrfachen Download freischalten der ko fir beschtemmte Adressa a mehrfaches Ronderlada erlauba +el puede permitir múltipes descargas para una direcció,nespecífica he can allow multiple downloads for specific addresses -he can allow multiple downloads for specific addresses -he can allow multiple downloads for specific addresses -he can allow multiple downloads for specific addresses -he can allow multiple downloads for specific addresses - +egli puo' permettere download multipli per indirizzi specifici +ten může umožnit vícenásobná stahování pro určité adresy +il peut autoriser plusieurs téléchargements pour des adresses spécifiques + +Use a F*EX client if you want to send more than one file or resume an interrupted upload +Verwenden Sie einen F*EX client wenn Sie mehr als eine Datei versenden wollen oder einen abgebrochenen Upload wiederaufnehmen wollen +Nemm an F*EX client wenn du meh als oi Datei verschicka willsch oder an abbrochona Nufflad wiederaufnehma willsch +Use un cliente F*EX si desea enviar más de un fichero o continuar una subida interrumpida +Use a F*EX client if you want to send more than one file or resume an interrupted upload +Usa F*EX client se vuoi spedire più di un file o riesumare un upload interrotto +Pokud chcete odeslat více než jeden soubor, nebo pokračovat v přeruÅ¡eném nahrávání, použijte klienta pro F*EX +Utilisez un client F*EX si vous voulez envoyer plus d'un fichier ou poursuivre un upload interrompue + You have to fill out this form completely to continue Sie müssen dieses Formular komplett ausfüllen um fortzufahren Du musch des Formular ganz ausffülla sonsch kosch ned weitrmacha @@ -1632,7 +1632,7 @@ Wenn Sie mehr als eine Datei senden möchten, dann erzeugen Sie ein zip oder Wenn De meh als oi Datei verschigge willsch, no mach a zip oddr a tar Archiv Si desea enviar más de un fichero póngalos en un archivo zip De querer enviar más dun fichero póñaos nun arquivo zip -Se vuoi spedire piu' di un file, mettili in un archivio zip o tar +Se vuoi spedire più di un file, mettili in un archivio zip o tar Chcete-li odeslat více jak jeden soubor, zkomprimujte jej do zip nebo tar archivu Si vous voulez envoyer plus d'un fichier, mettez les dans un zip ou une archive tar @@ -2302,18 +2302,45 @@ perche' ha troppi bug protože má příliÅ¡ mnoho chyb parce qu'il a beaucoup trop de problèmes -We recommend Firefox or wget -Wir empfehlen Ihnen Firefox oder wget -Nemm lieber Firefox oder wget -Recomendamos Firefox o wget -Recomendámoslle Firefox ou wget -Raccomandiamo di usare Firefox o wget -Doporučujeme použít Firefox či wget -Nous reconmmandons Firefox ou wget +We recommend +Wir empfehlen +Mir empfehled +Recomendamos +Recomendamos +Raccomandiamo +Doporučujeme používat +Nous recommandons + +#We recommend Firefox or wget +#Wir empfehlen Ihnen Firefox oder wget +#Nemm lieber Firefox oder wget +#Recomendamos Firefox o wget +#Recomendámoslle Firefox ou wget +#Raccomandiamo di usare Firefox o wget +#Doporučujeme použít Firefox či wget +#Nous reconmmandons Firefox ou wget + +We recommend fexget or fexit for download +Wir empfehlen fexget oder fexit fuer den Download +Mir empfehlad fexget odr fexit firs Ronderlada +Recomendamos fexget o fexit para la descarga +We recommend fexget or fexit for download +Raccomandiamo fexget o fexit per il download +Pro stahování doporučujeme fexget nebo fexit, +Nous recommandons fexget ou fexit pour un téléchargement + +because these clients can resume the download after an interruption +weil diese Programme einen unterbrochenen Download wiederaufnehmen koennen +weil Du mit dene Denger an abbrochana Ronderlad wiederaufnehma kosch +porque estos clientes pueden continuar una descarga que ha sido interrumpida +because these clients can resume the download after an interruption +dato che questi clients possono riesumare il download dopo una interruzione +protože tito klienti umožňují pokračovat ve stahování po přeruÅ¡ení +parce que ces clients peuvent poursuivre un téléchargement après une interruption After download (or view with a web browser!), Nach Download (oder Ansicht mit dem Web Browser!) -Nachm Ronderlada (oddr wenn Du se mit Deim Webbrowser oguckt hosch!) +Nochm Ronderlada (odr wenn Du's mitm Webbrowser oguckt hosch!) Tras la descarga, Tras a descarga, Dopo il download (o dopo essere stato visto con un browser WEB!) @@ -2383,41 +2410,32 @@ $receiver = 'te $receiver = 'vy $receiver = 'vous -Comment: -Kommentar: -Kommendar: -Comentario: -Comentario: -Commento: -Komentář: -Commentaire: - -" day" -" Tag" -" Dag" -" día" -" día" -" giorno" -" den" -" jour" - -" days" -" Tagen" -" Dag" -" días" -" días" -" giorni" -" dnů" -" jours" - -> days< -> Tagen< -> Dag< -> días< -> días< -> giorni< -> dnů< -> jours< + day" + Tag" + Dag" + día" + día" + giorno" + den" + jour" + + days" + Tagen" + Dag" + días" + días" + giorni" + dnů" + jours" + + days< + Tagen< + Dag< + días< + días< + giorni< + dnů< + jours< has uploaded the file hat die Datei @@ -2439,7 +2457,7 @@ pour $receiver. Utilisez to download this file within $days um die Datei innerhalb von $days herunterzuladen -damit Du dui Datei ennerhalb von $days ronderlade kosch +damit Du dui Datei ennerhalb von $days ronderlada kosch para descargar este fichero antes de $days para descargar este fichero antes de $days per scaricare questo file entro $days @@ -2671,41 +2689,41 @@ cliccare qui con il tasto destro del mouse e selezionare "salva come" zde klikněte pravým tlačítkem myÅ¡i a vyberte "Uložit jako" cliquez ici avec le bouton droit de la souris et sélectionner "save as" -Meta questions -Meta Fragen -Meta Froga -Meta Preguntas -Meta Preguntas -Meta Domande -VÅ¡eobecné Máte otázky -Questions générales - -User questions -Benutzer Fragen -Benutzr Froga -Usario Preguntas -Usuario Preguntas -Utente Domande -Uživatel Máte otázky -Questions utilisateurs - -Admin questions -Administratoren Fragen -Adminischdrator Froga -Admin Preguntas -Admin Preguntas -Amministratore Domande -Správce Máte otázky -Questions administrateur - -Misc questions -Sonstige Fragen -Vermischte Froga -Misc Preguntas -Misc Preguntas -Misc Domande -Misc Máte otázky -Questions diverses +#Meta questions +#Meta Fragen +#Meta Froga +#Meta Preguntas +#Meta Preguntas +#Meta Domande +#VÅ¡eobecné Máte otázky +#Questions générales + +#User questions +#Benutzer Fragen +#Benutzr Froga +#Usario Preguntas +#Usuario Preguntas +#Utente Domande +#Uživatel Máte otázky +#Questions utilisateurs + +#Admin questions +#Administratoren Fragen +#Adminischdrator Froga +#Admin Preguntas +#Admin Preguntas +#Amministratore Domande +#Správce Máte otázky +#Questions administrateur + +#Misc questions +#Sonstige Fragen +#Vermischte Froga +#Misc Preguntas +#Misc Preguntas +#Misc Domande +#Misc Máte otázky +#Questions diverses Your F*EX account has been inactive for $expire days Ihr F*EX Account ist seit $expire Tagen inaktiv