fex-20130805/0000755000174700017470000000000012177755050010713 5ustar fexfexfex-20130805/bin/0000755000174700017470000000000012177755050011463 5ustar fexfexfex-20130805/bin/xx0000777000174700017470000000000012177755050013421 2fexsendustar fexfexfex-20130805/bin/fexsrv0000755000174700017470000005176612175047130012734 0ustar fexfex#!/usr/bin/perl -wT # fexsrv : web server for F*EX service # # Author: Ulli Horlacher # use 5.008; use Socket; use IO::Handle; use Fcntl qw':flock :seek'; # stunnel workaround BEGIN { $SIG{CHLD} = "DEFAULT" } # use BSD::Resource; # setrlimit(RLIMIT_CPU,999,999) or die "$0: $!\n"; # SSL remote address provided by stunnel if (@ARGV and $ARGV[0] eq 'stunnel' and $ENV{REMOTE_HOST} =~ /(.+)/) { $ssl_ra = $1; } # KEEP_ALIVE <== callback from CGI if ($ENV{KEEP_ALIVE}) { $keep_alive = $ENV{KEEP_ALIVE}; } else { %ENV = (); # clean environment } $ENV{HOME} = (getpwuid($<))[7] or die "$0: no HOME\n"; # fexsrv MUST be run with full path! if ($0 =~ m:^(/.+)/bin/fexsrv:) { $FEXHOME = $1; $FEXHOME =~ s:/+:/:g; $FEXHOME =~ s:/$::; $ENV{FEXHOME} = $FEXHOME; } foreach my $lib ( $FEXHOME, '/usr/local/fex', '/usr/local/share/fex', '/usr/share/fex', ) { $ENV{FEXLIB} = $FEXLIB = $lib and last if -f "$lib/fex.pp"; $ENV{FEXLIB} = $FEXLIB = "$lib/lib" and last if -f "$lib/lib/fex.pp"; } # import from fex.pp our ($hostname,$debug,$timeout,$max_error,$max_error_handler); our ($spooldir,$logdir,$docdir,$xkeydir,$lockdir); our ($force_https,$default_locale,$bs,$adlm); our (@locales); # load common code (local config: $FEXHOME/lib/fex.ph) require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n"; chdir $spooldir or http_die("$0: $spooldir - $!\n"); our $log = "$logdir/fexsrv.log"; our $error = 'F*EX ERROR'; our $htmlsource; our $hid = ''; # header ID our @log; $0 = untaint($0); $ENV{GATEWAY_INTERFACE} = 'CGI/1.1'; $ENV{SERVER_NAME} = $hostname; $ENV{QUERY_STRING} = ''; $ENV{HTTP_COOKIE} = ''; $ENV{PATH_INFO} = ''; $ENV{RANDOM} = randstring(8); $ENV{FEATURES} = 'SID,CHECKRECIPIENT,GROUPS,QUOTA,FILEID,MULTIPOST,XKEY,' .'FILEQUERY,FILESTREAM,JUP,NOSTORE,AXEL,FEXMAIL,FILELINK'; # ignore bullshit requests my $ignore = join('|',( '^GET /w00tw00t\.at\.ISC\.SANS', )); $port = 0; # continue session? if ($keep_alive) { if ($ENV{HTTP_HOST} =~ /(.+):(.+)/) { $hostname = $1; $port = $2; } else { $hostname = $ENV{HTTP_HOST}; if ($ENV{PROTO} eq 'https') { $port = 443 } else { $port = 80 } } $ra = $ENV{REMOTE_ADDR}; $rh = $ENV{REMOTE_HOST}; } # new session else { # HTTPS connect if ($ssl_ra) { $ENV{PROTO} = 'https'; $ENV{REMOTE_ADDR} = $ra = $ssl_ra; $rh = gethostbyaddr(inet_aton($ra),AF_INET); $port = 443; # print {$log} "X-SSL-Remote-Host: $ssl_ra\n"; } # HTTP connect else { $ENV{PROTO} = 'http'; my $sa = getpeername(STDIN) or die "$0: no network stream on STDIN\n"; if (sockaddr_family($sa) == AF_INET) { ($ENV{REMOTE_PORT},$iaddr) = sockaddr_in($sa); $ENV{REMOTE_ADDR} = $ra = inet_ntoa($iaddr); $rh = gethostbyaddr($iaddr,AF_INET); ($port) = sockaddr_in(getsockname(STDIN)); } elsif (sockaddr_family($sa) == AF_INET6) { eval "use Socket6"; http_error(503) if $@; ($ENV{REMOTE_PORT},$iaddr) = unpack_sockaddr_in6($sa); $ENV{REMOTE_ADDR} = $ra = inet_ntop(AF_INET6, $iaddr); $rh = gethostbyaddr($iaddr,AF_INET6); ($port) = unpack_sockaddr_in6(getsockname(STDIN)); } else { die "$0: unknown IP version\n"; } $port = 80 unless $port; } $ENV{REMOTE_HOST} = $rh || ''; $ENV{HTTP_HOST} = ($port == 80 or $port == 443) ? $hostname : "$hostname:$port"; } if ($reverse_proxy_ip and $reverse_proxy_ip eq $ra) { $ENV{FEATURES} =~ s/SID,//; } if (@anonymous_upload and ipin($ra,@anonymous_upload)) { $ENV{FEATURES} .= ',ANONYMOUS'; } $| = 1; $SIG{CHLD} = "DEFAULT"; # stunnel workaround $SIG{ALRM} = sub { # printf {$log} "\nTIMEOUT %s %s\n",isodate(time),$connect; if (@log) { debuglog('TIMEOUT',isodate(time)); fexlog($connect,@log,"TIMEOUT"); } exit; }; REQUEST: while (*STDIN) { if (defined $ENV{REQUESTCOUNT}) { $ENV{REQUESTCOUNT}++ } else { $ENV{REQUESTCOUNT} = 0 } $connect = sprintf "%s:%s %s %s %s [%s_%s]", $keep_alive ? 'CONTINUE' : 'CONNECT', $port, isodate(time), $rh||'-', $ra, $$,$ENV{REQUESTCOUNT}; $hid = sprintf("%s %s\n",$rh||'-',$ra); @header = @log = (); $header = ''; # read complete HTTP header while (defined ($_ = &getaline)) { last if /^\s*$/; $hl += length; $header .= $_; s/[\r\n]+$//; # URL-encode non-printable chars s/([\x00-\x08\x0E-\x1F\x7F-\x9F])/sprintf "%%%02X",ord($1)/ge; if (@header and s/^\s+/ /) { $header[-1] .= $_; } else { push @header,$_; $header{$1} = $2 if /(.+)\s*:\s*(.+)/; push @log,$_; } if (/^(GET \/|X-Forwarded-For|User-Agent)/i) { $hid .= $_."\n"; } # reverse-proxy? if ($reverse_proxy_ip and $reverse_proxy_ip eq $ra and /^X-Forwarded-For: ([\d.]+)/ ) { $ENV{REMOTE_ADDR} = $ra = $1; $ENV{REMOTE_HOST} = $rh = gethostbyaddr(inet_aton($ra),AF_INET) || ''; $ENV{HTTP_HOST} = $hostname; if ($ENV{PROTO} eq 'https') { $port = 443 } else { $port = 80 } } if (/$ignore/) { fexlog($connect,@log,'IGNORED'); exit; } } exit unless @header; exit if $header =~ /^\s*$/; $ENV{HTTP_HEADER} = $header; debuglog($header); # http_die("
$header
"); # multiline header inquisition &$header_hook($connect,$header,$ra) if $header_hook; $ENV{'HTTP_HEADER_LENGTH'} = $hl; $ENV{REQUEST_URI} = $uri = ''; $cgi = ''; # is it a HTTP-request at all? $request = shift @header; if ($request !~ /^(GET|HEAD|POST|OPTIONS).*HTTP\/\d\.\d$/i) { fexlog($connect,$request,"DISCONNECT: no HTTP request"); exit; } if ($force_https and $port != 443 and $request =~ /^(GET|HEAD|POST)\s+(.+)\s+(HTTP\/[\d\.]+$)/i) { $request = $2; nvt_print( "HTTP/1.1 301 Moved Permanently", "Location: https://$hostname$request", "Content-Length: 0", "" ); fexlog($connect,@log); exit; } $request =~ s{^(GET|HEAD|POST) https?://$hostname(:\d+)?}{$1 }i; if ($request =~ m"^(GET|HEAD) /fop/\w+/") { # no header inquisition on regular fop request $header_hook = ''; } else { &$header_hook($connect,$request,$ra) if $header_hook; } unless ($keep_alive) { if ($request =~ m:(HTTP/1.(\d)): and $2) { $ENV{KEEP_ALIVE} = $keep_alive = $ra } else { $ENV{KEEP_ALIVE} = $keep_alive = ''; } } if ($request =~ /^OPTIONS FEX HTTP\/[\d\.]+$/i) { fexlog($connect,@log); nvt_print( "HTTP/1.1 201 OK", "X-Features: $ENV{FEATURES}", "X-Timeout: $timeout", '' ); next REQUEST if $keep_alive; exit; } if ($request =~ m:^GET /?SID HTTP/[\d\.]+$:i) { if ($ENV{FEATURES} !~ /\bSID\b/) { fexlog($connect,@log); nvt_print( "HTTP/1.1 501 Not Available", "X-Features: ".$ENV{FEATURES}, "X-Timeout: ".$timeout, 'Content-Length: 0', '' ); } else { $ENV{SID} = randstring(8); fexlog($connect,@log); nvt_print( "HTTP/1.1 201 ".$ENV{SID}, "X-Features: ".$ENV{FEATURES}, "X-SID: ".$ENV{SID}, "X-Timeout: ".$timeout, 'Content-Length: 0', '' ); } next REQUEST if $keep_alive; exit; } if ($request =~ /^(GET|HEAD|POST)\s+(.+)\s+(HTTP\/[\d\.]+$)/i) { $ENV{REQUEST_METHOD} = uc($1); $ENV{REQUEST_URI} = $uri = $cgi = $2; $ENV{HTTP_VERSION} = $protocol = $3; $ENV{QUERY_STRING} = $1 if $cgi =~ s/\?(.*)//; $ENV{PATH_INFO} = $1 if $cgi =~ m:/.+?(/.+?)(\?|$):; $ENV{KEEP_ALIVE} = $keep_alive = '' if $protocol =~ /1\.0/; $ENV{REQUEST_URL} = "$ENV{PROTO}://$ENV{HTTP_HOST}$ENV{REQUEST_URI}"; if ($uri =~ /<|%3c/i) { badchar("<") } if ($uri =~ />|%3e/i) { badchar(">") } if ($uri =~ /\||%7c/i) { badchar("|") } if ($uri =~ /\\|%5c/i) { badchar("\\") } } while ($_ = shift @header) { # header inquisition! &$header_hook($connect,$_,$ra) if $header_hook; # mega stupid "Download Manager" FlashGet if ($uri =~ m{^/fop/} and m{^Referer: https?://.*\Q$uri$}) { fexlog($connect,@log,"NULL: FlashGet"); debuglog("NULL: FlashGet"); exec qw'cat /dev/zero' or sleep 30; exit; } if (/^User-Agent: (FDM)/ and $header =~ /\nRange:/) { disconnect($1,"499 Download Manager $1 Not Supported",30); } if (/^User-Agent: (Java\/[\d\.]+)/) { disconnect($1,"499 User-Agent $1 Not Supported",30); } if (/^Range:.*,/) { disconnect("Range a,b","416 Requested Range Not Satisfiable",30); } if (/^Range:.*(\d+)-(\d+)/) { if ($1 > $2) { disconnect("Range a>b","416 Requested Range Not Satisfiable",0); } if (($header{'User-Agent'}||'') !~ /$adlm/ ) { disconnect("Range a-b","416 Requested Range Not Satisfiable",30); } } if (/^Range:.*\d+-$/ and $hid) { my $lock = untaint($lockdir.'/'.md5_hex($hid)); if (open $lock,'+>>',$lock) { if (flock($lock,LOCK_EX|LOCK_NB)) { seek $lock,0,0; truncate $lock,0; print {$lock} $hid; } else { disconnect( "multiple Range request", "400 Multiple Requests Not Allowed", 10, ); } } } # client signed int bug if (/^Range:.*-\d+-/) { disconnect("Range -a-","416 Requested Range Not Satisfiable",0); } # if (/^Range:/ and $protocol =~ /1\.0/) { # &$header_hook($connect,$_,$ra) while ($header_hook and $_ = shift @header); # fexlog($connect,@log,"DISCONNECT: Range + HTTP/1.0"); # debuglog("DISCONNECT: Range + HTTP/1.0"); # http_error(416); # exit; # } if (/^Connection:\s*close/i) { $ENV{KEEP_ALIVE} = $keep_alive = ''; } # HTTP header ==> environment variables if (/^([\w\-]+):\s*(.+)/s) { $http_var = $1; $http_val = $2; $http_var =~ s/-/_/g; $http_var = uc($http_var); $http_val =~ s/^\s+//; $http_val =~ s/\s+$//; if ($http_var =~ /^X_(FEX_\w+|CONTENT_LENGTH)$/) { $http_var = $1; } else { $http_val =~ s/\s+/ /g; if ($http_var =~ /^HTTP_(HOST|VERSION)$/) { $http_var = 'X-'.$http_var; } elsif ($http_var !~ /^CONTENT_/) { $http_var = 'HTTP_'.$http_var; } } $ENV{$http_var} = $http_val; } } exit unless $cgi; # extra download request? (request http://fexserver//xkey) if ($cgi =~ m{^//([^/]+)$}) { my $xkey = $1; my $dkey; if ($xkey =~ /^afex_\d/) { $dkey = readlink "$xkeydir/$xkey" and $dkey =~ s/^\.\.\///; } else { $dkey = readlink "$xkeydir/$xkey/dkey" and $dkey .= "/$xkey"; } if ($dkey) { # xkey downloads are only one time possible unlink "$xkeydir/$xkey/xkey"; unlink "$xkeydir/$xkey"; nvt_print( "HTTP/1.1 301 Moved Permanently", "Location: $ENV{PROTO}://$ENV{HTTP_HOST}/fop/$dkey", "Content-Length: 0", "" ); fexlog($connect,@log); exit; } fexlog($connect,@log); http_error(404); exit; } # get locale if (($ENV{QUERY_STRING} =~ /.*locale=([\w-]+)/ or $ENV{HTTP_COOKIE} =~ /.*locale=([\w-]+)/) and -d "$FEXHOME/locale/$1") { $ENV{LOCALE} = $locale = $1; } else { $ENV{LOCALE} = $locale = $default_locale; } # check for name based virtual host $vhost = vhost($ENV{'HTTP_HOST'}); if ($debug) { debuglog("ENV:\n"); foreach $var (sort keys %ENV) { debuglog(sprintf " %s = >%s<\n",$var,$ENV{$var}); } debuglog("\n"); } # locale definitions in fex.ph? if (@locales) { if (@locales == 1) { $locale = $locales[0]; } elsif (not grep /^$locale$/,@locales) { $locale = $default_locale; } } # prepare document file name if ($ENV{REQUEST_METHOD} =~ /^GET|HEAD$/) { $doc = untaint($uri); $doc =~ s/%([\dA-F]{2})/unpack("a",pack("H2",$1))/ge; $doc =~ m:/\.\./: and http_error(403); $doc =~ s:^/+::; $doc =~ s/\?.*//; if ($locale and -e "$docdir/locale/$locale/$doc") { $doc = "$docdir/locale/$locale/$doc"; } else { $doc = "$docdir/$doc"; } } # CGI or document request? if ($cgi =~ s:^/+::) { $cgi =~ s:/.*::; unless ($cgi) { my $login = "$FEXHOME/cgi-bin/login"; if (-x $login) { $cgi = untaint(readlink($login) || $login); $cgi =~ s:.*/::; } } $ENV{SCRIPT_NAME} = $cgi; # locale CGIs? (vhost comes already with own FEXLIB) if ($locale and $locale ne 'english' and -f "$FEXHOME/locale/$locale/cgi-bin/$cgi") { $ENV{SCRIPT_FILENAME} = $cgi = "$FEXHOME/locale/$locale/cgi-bin/$cgi"; $ENV{FEXLIB} = $FEXLIB = "$FEXHOME/locale/$locale/lib" unless $vhost; } else { $ENV{SCRIPT_FILENAME} = $cgi = "$FEXHOME/cgi-bin/$cgi"; $ENV{FEXLIB} = $FEXLIB = "$FEXHOME/lib" unless $vhost; } $status = ''; if (-x $cgi and -f $cgi) { unlink "$logdir/.error/$ra"; # push @log,"DEBUG: locale=$locale locales=(@locales)"; fexlog($connect,@log,"EXEC $cgi"); eval { local $^W = 0; exec $cgi }; $status = "$! or bad interpreter"; } else { if (-f "$doc/.htindex") { require "$FEXLIB/dop"; fexlog($connect,@log); showindex($doc); STDOUT->flush; next REQUEST if $keep_alive; exit; } if (-f "$doc/index.html") { # force redirect if trailing / is missing # this is mandatory for processing further HTTP request! if ($doc !~ m{/$}) { nvt_print( "HTTP/1.1 301 Moved Permanently", "Location: $ENV{REQUEST_URL}/", "Content-Length: 0", "" ); fexlog($connect,@log); next REQUEST if $keep_alive; exit; } $doc .= '/index.html'; $doc =~ s:/+:/:g; } $doc =~ s/#.*//; # ignore HTML anchors (stupid msnbot) # special request for F*EX UNIX clients if ($ENV{SCRIPT_NAME} eq 'xx.tar') { bintar(qw'fexget fexsend xx zz ezz'); } if ($ENV{SCRIPT_NAME} eq 'sex.tar') { bintar(qw'sexsend sexget sexxx'); } if ($ENV{SCRIPT_NAME} eq 'afex.tar') { bintar(qw'afex asex fexget fexsend sexsend sexget'); } if ($ENV{SCRIPT_NAME} eq 'afs.tar') { bintar(qw'afex asex fexget fexsend xx sexsend sexget sexxx zz ezz'); } # URL ends with ".html!" or ".html?!" if ($doc =~ s/(\.html)!$/$1/ or $doc =~ /\.html$/ and $ENV{'QUERY_STRING'} eq '!') { $htmlsource = $doc } else { $htmlsource = '' } if (-f $doc or $doc =~ /(.+)\.(tar|tgz|zip)$/ and lstat("$1.stream")) { unlink "$logdir/.error/$ra"; delete $ENV{SCRIPT_FILENAME}; $ENV{DOCUMENT_FILENAME} = $doc; require "$FEXLIB/dop"; fexlog($connect,@log); dop($doc); STDOUT->flush; next REQUEST if $keep_alive; exit; } elsif (-e $cgi) { $status = 'not executable'; } elsif ($uri eq '/bunny') { fexlog($connect,@log); nvt_print( 'HTTP/1.1 200 OK', 'Server: fexsrv', "Content-Type: text/plain", '', '=:3', ); exit; } elsif ($uri eq '/camel') { fexlog($connect,@log); nvt_print( 'HTTP/1.1 200 OK', 'Server: fexsrv', "Content-Type: text/plain", '', ); local $/; print unpack('u',); exit; } } } # neither document nor CGI ==> error if ($status) { fexlog($connect,@log,"FAILED to exec $cgi : $status"); http_error(555); } else { fexlog($connect,@log,"UNKNOWN URL"); badlog($request); http_error(404); } exit; } # read one text line unbuffered from STDIN sub getaline { my $line = ''; my $c; alarm($timeout); # must use sysread to avoid perl line buffering # (later exec would destroy line buffer) while (sysread STDIN,$c,1) { $line .= $c; last if $c eq "\n"; } alarm(0); return $line; } sub fexlog { my @log = @_; if (open $log,">>$log") { flock $log,LOCK_EX; seek $log,0,SEEK_END; print {$log} "\n",join("\n",@log),"\n"; close $log; } else { http_die("$0: cannot write to $log - $!\n"); } } sub badchar { my $bc = shift; fexlog($connect,@log,"DISCONNECT: bad characters in URL"); debuglog("DISCONNECT: bad characters in URL $uri"); http_die("\"$bc\" is not allowed in URL"); } sub bintar { my $tmpdir = "$FEXHOME/tmp"; my $fs = "$ENV{PROTO}://$ENV{HTTP_HOST}"; if (chdir "$FEXHOME/bin") { fexlog($connect,@log); chdir $fstb if $fstb; mkdir $tmpdir; foreach my $f (@_) { copy($f,"$tmpdir/$f","s#fexserver = ''#fexserver = '$fs'#"); chmod 0755,"$tmpdir/$f"; } chdir $tmpdir or http_die("internal error: $tmpdir - $!"); my $tar = `tar cf - @_ 2>/dev/null`; unlink @_; nvt_print( 'HTTP/1.1 200 OK', 'Server: fexsrv', "Content-Length: ".length($tar), "Content-Type: application/x-tar", '', ); print $tar; exit; } } sub http_error { my $error = shift; my $URL = $ENV{REQUEST_URL}; my $URI = $ENV{REQUEST_URI}; if ($error eq 400) { http_error_header("400 Bad Request"); nvt_print("Your request $URL is not acceptable."); } elsif ($error eq 403) { http_error_header("403 Forbidden"); nvt_print("You have no permission to request $URL"); } elsif ($error eq 404) { http_error_header("404 Not Found"); nvt_print("The requested URI $URI was not found on this server."); } elsif ($error eq 416) { http_error_header("416 Requested Range Not Satisfiable"); } elsif ($error eq 503) { http_error_header("503 Service Unavailable"); # nvt_print("No Perl ipv6 support on this server."); } else { http_error_header("555 Unknown Error"); nvt_print("The requested URL $URL produced an internal error."); } nvt_print( "
", "
fexsrv at $hostname:$port
", "", ); exit; } sub disconnect { my $info = shift; my $error = shift; my $wait = shift||0; # &$header_hook($connect,$_,$ra) while ($header_hook and $_ = shift @header); fexlog($connect,@log,"DISCONNECT: $info"); debuglog("DISCONNECT: $info"); errorlog("$ENV{REQUEST_URI} ==> $error"); badlog("$ENV{REQUEST_URI} ==> $error ($info)"); sleep $wait; nvt_print("HTTP/1.0 $error"); exit; } sub http_error_header { my $error = shift; errorlog("$ENV{REQUEST_URI} ==> $error"); nvt_print( "HTTP/1.1 $error", "Connection: close", "Content-Type: text/html; charset=iso-8859-1", "", '', "", "$error", "", "

$error

", ); } sub badlog { my $request = shift; my $n = 1; my $ed = "$spooldir/.error"; local $_; if (@ignore_error) { foreach (@ignore_error) { return if $request =~ /$_/; } } if ($ra and $max_error and $max_error_handler) { mkdir($ed) unless -d $ed; if (open $ra,"+>>$ed/$ra") { flock($ra,LOCK_EX); seek $ra,0,SEEK_SET; $n++ while <$ra>; printf {$ra} "%s %s\n",isodate(time),$request; close $ra; &$max_error_handler($ra) if $n > $max_error; } } } __END__ M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("PM)R(G+5P*("`@ M("`@("`@("`@("`@("`@("`@("`@("]@8&`M+B`@(&!<("`@("Q=+B`@("`@ M("`@("`@("`@("`@("`@("`L+BY?"B`@("`@("`@("`@("`@("`@("`@("`@ M+&`@("`@(&`B+B`@72X@("`@(&`N("`@("`@("`@("`@("`@7U]?+BY>(&!? M)V`B(B(*("`@("`@("`@("`@("`@("`@("`@("`I("`@("`@("`G+"TG+2T@ M+B`@("!@+B`@("`@(%]?7RPN+2<@("XN("T@("`G("TP("Y?"B`@("`@("`@ M("`@+"X@("`@("`@("`@?%]?+"Y?("!?("`N+5\@("!<("`\("Y@(B # use 5.006; use Getopt::Std; use File::Basename; use Digest::MD5 qw(md5_hex); use constant M => 1024*1024; # do not run as CGI! exit if $ENV{SCRIPT_NAME}; # search for fex lib foreach my $lib ( $ENV{FEXLIB}||'', dirname(dirname($0)), '/usr/local/fex', '/usr/local/share/fex', '/usr/share/fex', ) { $ENV{FEXLIB} = $FEXLIB = $lib and last if -f "$lib/fex.pp"; $ENV{FEXLIB} = $FEXLIB = "$lib/lib" and last if -f "$lib/lib/fex.pp"; } die "$0: no FEXLIB\n" unless $FEXLIB; $0 =~ s:.*/::; # become effective user fex unless ($<) { if (my @pw = getpwnam('fex')) { $) = $pw[3]; $> = $pw[2]; $ENV{HOME} = $pw[7]; } else { die "$0: no such user 'fex'\n"; } } # import from fex.pp our ($FEXHOME,$hostname,$spooldir,$logdir,$akeydir,$docdir); our ($durl,$mdomain,$admin); our ($autodelete,$keep_default,$recipient_quota,$sender_quota); our (@local_rdomains); local $notification = 'full'; # load common code, local config : $HOME/lib/fex.ph require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n"; die "$0: \$admin not configured in $FEXLIB/fex.ph\n" if $admin =~ /example.org/; $EDITOR = $ENV{VISUAL} || $ENV{EDITOR} || (-x '/usr/bin/editor' ? '/usr/bin/editor' : 'vi'); $opt_c = $opt_v = $opt_l = $opt_h = $opt_w = $opt_u = $opt_R = 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 = ''; @__ = @ARGV; while (my $a = shift @__) { if ($a eq '-V') { shift @__; } else { push @_ARGV,$a; } } getopts('hcvlwuRq:r:d:a:n:k:m:y:S:C:A:V:D:') or usage(2); usage(0) if $opt_h; if ($opt_V) { while (my ($hh,$vh) = each (%vhost)) { if ($opt_V eq basename($vh) or $opt_V eq $hh) { $ENV{HTTP_HOST} = $hh; $ENV{VHOST} = "$hh:$vh"; $ENV{FEXLIB} = "$vh/lib"; die "$0: no $ENV{FEXLIB}/fex.ph\n" unless -f "$ENV{FEXLIB}/fex.ph"; exec $0,@_ARGV; die "$0: cannot re-exec\n"; } } die "$0: no virtual host $opt_V defined\n"; } chdir $spooldir or die "$0: no $spooldir\n"; @stat = stat $spooldir or die "$0: cannot access $spooldir - $!\n"; warn "$0: $spooldir with owner=root !?\n" unless $stat[4]; $) = $stat[5]; $> = $stat[4]; $fup = $durl; $fup =~ s:/[^/]+$:/fup:; # maintenance mode if ($opt_m) { if ($opt_m eq 'exit') { if (unlink '@MAINTENANCE') { warn "$0: leaving maintenance mode\n"; } else { warn "$0: no maintenance mode\n"; } } else { unlink '@MAINTENANCE'; symlink $opt_m,'@MAINTENANCE' or die "$0: cannot write $spooldir/\@MAINTENANCE - $!"; warn "$0: entering maintenance mode\n"; } exit; } # list files and download URLs if ($opt_w) { $log = "$logdir/fexsrv.log"; warn "$0: polling $log\n\n"; exec "$FEXHOME/bin/logwatch",$log; die "$0: logwatch not found\n"; } # list files and download URLs if ($opt_l) { my ($file,$dkey); chdir $spooldir or die "$0: $spooldir - $!\n"; foreach $file (glob "*/*/*") { if (-s "$file/data" and $dkey = readlink("$file/dkey") and -l ".dkeys/$dkey") { printf "%s --> %s :\n$durl/$dkey/%s\n",split "/",$file; } } exit; } # delete user if ($opt_d) { $idf = "$spooldir/$opt_d/\@"; die "$0: no such user $opt_d\n" unless -f $idf; unlink $idf or die "$0: cannot remove $idf - $!\n"; unlink "$spooldir/$opt_d/\@ALLOWED_RECIPIENTS"; print "$opt_d deleted\n"; exit; } # set user restriction file if ($opt_R) { $user = shift or usage(2); $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"; exit; } # edit user restriction file if ($opt_r) { if ($opt_r =~ /^r/i) { $opt_r = 'ALLOWED_RECIPIENTS' } elsif ($opt_r =~ /^u/i) { $opt_r = 'UPLOAD_HOSTS' } elsif ($opt_r =~ /^d/i) { $opt_r = 'DOWNLOAD_HOSTS' } else { usage(2) } $user = shift or usage(2); $user .= '@'.$mdomain if $mdomain and $user !~ /@/; die "$0: no user $user\n" unless -d "$spooldir/$user"; my $rf = "$spooldir/$user/\@$opt_r"; unless (-s $rf) { open $rf,'>',$rf or die "$0: cannot open $rf - $!"; if ($opt_r eq 'ALLOWED_RECIPIENTS') { print {$rf}<$fph" or die "$0: cannot write to $fph - $!\n"; print {$fph} $_; close $fph; system "cp $FEXLIB/fup.pl $vhd/lib/fup.pl"; foreach $i (qw'dop fex.pp fup.pl lf.pl reactivation.txt') { # symlink "$FEXLIB/$i","$vhd/lib/$i"; symlink "../../lib/$i","$vhd/lib/$i"; } foreach $i (qw( index.html tools.html SEX.html robots.txt logo.jpg small_logo.jpg action-fex-camel.gif favicon.ico FAQ )) { cpa("$FEXHOME/htdocs/$i","$vhd/htdocs"); } symlink "$FEXHOME/htdocs/version","../../htdocs/version"; symlink "$FEXHOME/htdocs/download","../../htdocs/download"; cpa("$FEXHOME/locale",$vhd); foreach $ld (glob "$vhd/locale/*") { if (not -l $ld and -d "$ld/cgi-bin") { $locale = basename($ld); rmrf("$ld/cgi-bin"); # symlink "../../../locale/$locale/cgi-bin","$ld/cgi-bin"; symlink "../../../locale/$locale/htdocs","$vhd/htdocs/locale/$locale"; unlink "$ld/lib/fex.ph"; symlink "../../../lib/fex.ph","$ld/lib/fex.ph"; symlink "../../../../locale/$locale/lib","$ld/lib/master"; foreach $f (qw'dop fex.pp lf.pl reactivation.txt') { unlink "$ld/lib/$f"; symlink "master/$f","$ld/lib/$f"; } } } $fph = "$FEXLIB/fex.ph"; open $fph,">>$fph" or die "$0: cannot write to $fph = $!\n"; print {$fph} "\n\$vhost{'$hhost'} = '$vhd';\n"; close $fph; print "You must now edit and configure $vhd\n"; print "or execute: $0 -V $vhost -c\n"; exit; } # show config if ($opt_v) { print "config from $FEXLIB/fex.ph :\n"; print "\tspooldir = $spooldir\n"; print "\tlogdir = $logdir\n"; print "\tdocdir = $docdir\n"; print "\tdurl = $durl\n"; print "\tmdomain = $mdomain\n"; print "\tautodelete = $autodelete\n"; print "\tkeep = $keep_default\n"; print "\trecipient_quota = $recipient_quota\n"; print "\tsender_quota = $sender_quota\n"; print "\tadmin = $admin\n"; while (($hh,$vh) = each %vhost) { printf "\tvirtual server %s : %s\n",basename($vh),$hh; } # unless (@ARGV) { # foreach $ph (glob "$ENV{HOME}/*/lib/fex.ph") { # $ENV{FEXLIB} = dirname($ph); # print "\n"; # system $0,'-v',$ph; # } # } if ($m = readlink '@MAINTENANCE') { print "server is in maintenance mode ($m)!\n" ; } exit; } # add user or show user config if ($opt_u) { if ($opt_u = shift @ARGV) { $user = lc $opt_u; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; $id = shift @ARGV; $idf = "$spooldir/$user/@"; if (open $idf,$idf) { chomp($ido = <$idf>||''); close $idf; } unless ($id) { die "$0: $user is not a FEX user\n" unless -f "$spooldir/$user/@"; showuser($user,$ido); exit; } unless ($user =~ /\w@[\w\.\-]+\.[a-z]+$/) { die "$0: $user is not a valid e-mail-address!\n"; } unless (-d "$spooldir/$user") { mkdir "$spooldir/$user",0755 or die "$0: cannot mkdir $spooldir/$user - $!\n"; } open F,">$idf" or die "$0: cannot write $idf - $!\n"; print F $id,"\n"; close F or die "$0: cannot write $idf - $!\n"; showuser($user,$id); } else { print "Users in $spooldir:\n"; foreach $user (glob "$spooldir/*/@") { $user =~ s:.*/(.+)/@:$1:; print "$user\n"; } } exit; } # set user autodelete default if ($opt_a) { $user = lc $opt_a; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; $_ = shift @ARGV || ''; if (/^n/i) { $autodelete = 'no' } elsif (/^y/i) { $autodelete = 'yes' } elsif (/^d/i) { $autodelete = 'delay' } else { usage(2) } mkdir "$spooldir/$user",0755; my $adf = "$spooldir/$user/\@AUTODELETE"; unlink $adf; symlink $autodelete,$adf or die "$0: cannot create symlink $adf - $!\n"; exit; } # set user notification default if ($opt_n) { $user = lc $opt_n; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; $_ = shift @ARGV || ''; if (/^n/i) { $notification = 'no' } elsif (/^s/i) { $notification = 'short' } elsif (/^f/i) { $notification = '' } else { usage(2) } mkdir "$spooldir/$user",0755; my $ndf = "$spooldir/$user/\@NOTIFICATION"; unlink $ndf; if ($notification) { symlink $notification,$ndf or die "$0: cannot create symlink $ndf - $!\n"; } exit; } # set user keep default if ($opt_k) { $user = lc $opt_k; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; my $keep = shift @ARGV || ''; die usage(2) if $keep !~ /^\d+$/; mkdir "$spooldir/$user",0755; my $kf = "$spooldir/$user/\@KEEP"; unlink $kf; symlink $keep,$kf or die "$0: cannot create symlink $kf - $!\n"; exit; } # quota if ($opt_q) { $user = lc $opt_q; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; unless (-d "$spooldir/$user") { die "$0: $user is not a regular FEX user\n"; } quota($user,@ARGV); exit; } if ($opt_C) { $user = lc $opt_C; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; unless (-f "$spooldir/$user/@") { die "$0: $user is not a regular FEX user\n"; } $_ = shift @ARGV || ''; if (/^y/i) { open $user,">>$spooldir/$user/\@CAPTIVE"; close $user; print "$user is now captive\n"; } elsif (/^n/i) { unlink "$spooldir/$user/\@CAPTIVE"; print "$user is no more captive\n"; } else { usage(2); } exit; } if ($opt_y) { $user = lc $opt_y; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; unless (-f "$spooldir/$user/@") { die "$0: $user is not a regular FEX user\n"; } $_ = shift @ARGV || ''; if (/^y/i) { open $user,">>$spooldir/$user/\@FEXYOURSELF"; close $user; print "$user has now \"fex yourself\" default\n"; } elsif (/^n/i) { unlink "$spooldir/$user/\@FEXYOURSELF"; print "$user has no \"fex yourself\" default\n"; } else { usage(2); } exit; } if ($opt_D) { $user = lc $opt_D; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; $_ = shift @ARGV || ''; if (/^y/i) { open $user,">>$spooldir/$user/\@DISABLED"; close $user; print "$user is now disabled\n"; } elsif (/^n/i) { unlink "$spooldir/$user/\@DISABLED"; print "$user is now enabled\n"; } else { usage(2); } exit; } if ($opt_S eq 'fup') { &fupstat; exit; } if ($opt_S eq 'fop') { &fopstat; exit; } usage(3); sub showuser { my $user = shift; my $id = shift; my ($keep,$autodelete,$notification); $user .= '@'.$mdomain if $mdomain and $user !~ /@/; print "[using config $FEXLIB/fex.ph]\n"; print "$fup?from=$user&id=$id\n"; printf "%s/%s\n",$fup,b64("from=$user&id=$id"); printf "%s/%s\n",$fup,b64("from=$user&to=$user&id=$id&submit=."); print "spool: $spooldir/$user/\n"; printf "fex yourself default: %s\n", -e "$spooldir/$user/\@FEXYOURSELF" ? 'yes' : 'no'; printf "captive: %s\n", -e "$spooldir/$user/\@CAPTIVE" ? 'yes' : 'no'; printf "disabled: %s\n", -e "$spooldir/$user/\@DISABLED" ? 'yes' : 'no'; printf "recipients restrictions: %s\n", -e "$spooldir/$user/\@ALLOWED_RECIPIENTS" ? 'yes' : 'no'; printf "upload restrictions: %s\n", -e "$spooldir/$user/\@UPLOAD_HOSTS" ? 'yes' : 'no'; printf "download restrictions: %s\n", -e "$spooldir/$user/\@DOWNLOAD_HOSTS" ? 'yes' : 'no'; $autodelete = lc(readlink "$spooldir/$user/\@AUTODELETE" || $::autodelete); print "autodelete default: $autodelete\n"; $notification = lc(readlink "$spooldir/$user/\@NOTIFICATION" || $::notification); print "notification default: $notification\n"; $keep = readlink "$spooldir/$user/\@KEEP" || $keep_default; print "keep default: $keep\n"; quota($user); } # set or show disk quota sub quota { my $user = shift; my $rquota = ''; my $squota = ''; my $qf = "$spooldir/$user/\@QUOTA"; local $_; if (open $qf,$qf) { while (<$qf>) { s/#.*//; $rquota = $1 if /recipient.*?(\d+)/i; $squota = $1 if /sender.*?(\d+)/i; } close $qf; } if (@_) { while (@_) { $_ = shift; $rquota = $1 if /^r.*:(\d*)/i; $squota = $1 if /^s.*:(\d*)/i; } open $qf,'>',$qf or die "$0: cannot write $qf - $!\n"; print {$qf} "recipient:$rquota\n" if $rquota =~ /\d/; print {$qf} "sender:$squota\n" if $squota =~ /\d/; close $qf; } $rquota = $recipient_quota if $rquota !~ /\d/; $squota = $sender_quota if $squota !~ /\d/; printf "recpient quota (used): %d (%d) MB\n", check_recipient_quota($user); printf "sender quota (used): %d (%d) MB\n", check_sender_quota($user); } sub usage { my $port = ''; my $proto = 'http'; if ($durl =~ /:(\d+)/) { $port = ":$1" } if ($durl =~ /^(https?)/) { $proto = $1 } print <) { if (/^([\d: -]+) (\[[\d_]+\] )?(\w\S*) .* (\d+)$/) { $z = $4; $u = $3; $u .= '@'.$mdomain if $mdomain and $u !~ /@/; $user{$u} += $z; $d = $u; $d =~ s/.*@//; $d =~ s/.*\.(.+\.\w+)/$1/; $domain{$d} += $z; $du{$d}{$u}++; $Z += $z; } } foreach $u (sort {$user{$a} <=> $user{$b}} keys %user) { printf "%s : %d\n",$u,$user{$u}/M; } print "========================================================\n"; foreach $d (sort {$domain{$a} <=> $domain{$b}} keys %domain) { printf "%s : %d MB, %d user\n",$d,$domain{$d}/M,scalar(keys %{$du{$d}}); } printf "Total: %d GB\n",$Z/M/1024; exit; } sub fopstat { my $Z = 0; my ($log,$u,$d,$z); my (%user,%domain,%du); if (-t) { $log = "$logdir/fop.log" } else { $log = '>&=STDIN' } open $log,$log or die "$0: cannot open $log - $!\n"; while (<$log>) { if (/^([\d: -]+) (\[[\d_]+\] )?[\d.]+ (.+?)\/.* (\d+)\/\d+/) { $z = $4; $u = $3; $u .= '@'.$mdomain if $mdomain and $u !~ /@/; $user{$u} += $z; $d = $u; $d =~ s/.*@//; $d =~ s/.*\.(.+\.\w+)/$1/; $domain{$d} += $z; $du{$d}{$u}++; $Z += $z; } } foreach $u (sort {$user{$a} <=> $user{$b}} keys %user) { printf "%s : %d\n",$u,$user{$u}/M; } print "========================================================\n"; foreach $d (sort {$domain{$a} <=> $domain{$b}} keys %domain) { printf "%s : %d MB, %d user\n",$d,$domain{$d}/M,scalar(keys %{$du{$d}}); } printf "Total: %d GB\n",$Z/M/1024; exit; } sub cpa { my $dd = pop @_; die "(cpa): $dd is not a directory" unless -d $dd; system "rsync -a @_ $dd/" ; } fex-20130805/bin/sexsend0000755000174700017470000003234212177755050013066 0ustar fexfex#!/usr/bin/perl -w # client for stream exchange of the FEX service # # Author: Ulli Horlacher # # Copyright: Perl Artistic # sexsend / sexget / sexxx use Getopt::Std; use Socket; use IO::Handle; use IO::Socket::INET; use Digest::MD5 qw(md5_hex); # encypted ID / SID use constant k => 2**10; use constant M => 2**20; eval 'use Net::INET6Glue::INET_is_INET6'; our $version = 20130805; $version = mtime($0) unless $version; $0 =~ s:.*/::; $| = 1; # sexsend is default $usage = "usage: ... | $0 [options] [SEX-URL/]recipient [stream]\n". "options: -v verbose mode\n". " -V show version\n". " -t timeout timeout in s (waiting for recipient)\n". "special: recipient may be \"public\" or \"anonymous\"\n". "see also: sexget, sexxx\n". "example: tail -f /var/log/syslog | $0 fex.flupp.org/admin log\n"; if ($0 eq 'sexget' or $0 eq 'fuckme') { $usage = "usage: $0 [options] [[SEX-URL/]user:ID] [stream]\n". "options: -g show transfer rate\n". " -v verbose mode\n". " -V show version\n". "arguments: user:ID use this user & ID\n". " (ID may be \"public\" or user:ID may be \"anonymous\")\n". " stream name of the stream\n". "see also: sexsend, sexxx\n". "example: $0 log | grep kernel\n"; } if ($0 eq 'sexxx') { $usage = "usage: $0 [-v] [-g] [-c] [-u [SEX-URL/]user] [-s stream] [files...]\n". "usage: $0 [-v] [-g] [-u [SEX-URL/]user] [-s stream] | ...\n". "options: -g show transfer rate\n". " -v verbose mode\n". " -q quiet mode\n". " -c compress files\n". " -u SEX-URL/user SEX-URL and user (default: use FEXID/FEXXX)\n". " -s stream stream name (default: xx)\n". "see also: sexsend, sexget\n". "examples: $0 -s config /etc /usr/local/etc\n". " $0 > backup.tar\n"; } $fexhome = $ENV{FEXHOME} || $ENV{HOME}.'/.fex'; $user = $id = ''; $type = $timeout = $stream = $mode = ''; $idf = "$fexhome/id"; $bs = 2**16; # I/O blocksize # server URL, user and auth-ID if ($FEXID = $ENV{FEXID}) { $FEXID = decode_b64($FEXID) if $FEXID !~ /\s/; ($fexcgi,$user,$id) = split(/\s+/,$FEXID); } else { if (open $idf,$idf) { chomp($fexcgi = <$idf>) or die "$0: no FEX-URL in $idf\n"; chomp($user = <$idf>) or die "$0: no FROM in $idf\n"; chomp($id = <$idf>) or die "$0: no ID in $idf\n"; close $idf; despace($fexcgi,$user,$id); unless ($fexcgi =~ /^[_:=\w\-\.\/\@\%]+$/) { die "$0: illegal FEX-URL \"$fexcgi\" in $idf\n"; } unless ($user =~ /^[_:=\w\-\.\/\@\%\+]+$/) { die "$0: illegal FROM \"$user\" in $idf\n"; } } } $opt_h = $opt_v = $opt_V = $opt_q = 0; $opt_u = $opt_s = $opt_c = $opt_t = ''; if ($0 eq 'sexxx') { # xx server URL, user and auth-ID if ($FEXXX = $ENV{FEXXX}) { $FEXXX = decode_b64($FEXXX) if $FEXXX !~ /\s/; ($fexcgi,$user,$id) = split(/\s+/,$FEXXX); } elsif (open $idf,$idf) { while (<$idf>) { if (/^\[xx\]/) { chomp($fexcgi = <$idf>) or die "$0: no xx FEX-URL in $idf\n"; chomp($user = <$idf>) or die "$0: no xx FROM in $idf\n"; chomp($id = <$idf>) or die "$0: no xx ID in $idf\n"; last; } } close $idf; } getopts('hvcu:s:') or die $usage; die $usage if $opt_h; die $usage unless -t; if ($opt_c) { $opt_c = 'z'; $type = '&type=GZIP'; } if ($opt_u) { $fexcgi = $1 if $opt_u =~ s:(.+)/::; $user = $opt_u; } unless ($fexcgi) { die "$0: no xx user found, use \"$0 -u SEX-URL/user\"\n"; } unless ($user) { die "$0: no xx user found, use \"$0 -u user\"\n"; } } elsif ($0 eq 'sexget' or $0 eq 'fuckme') { getopts('hgvVdu:') or die $usage; die $usage if $opt_h; if ($opt_V) { print "Version: $version\n"; exit unless @ARGV; } if (not $opt_u and @ARGV and $ARGV[0] =~ m{^anonymous|/|:}) { $opt_u = shift @ARGV; } if ($opt_u) { $fexcgi = $1 if $opt_u =~ s:(.+)/::; ($user,$id) = split(':',$opt_u); if ($user =~ /^anonymous/) { $anonymous = $user; } elsif (not $id) { die $usage; } } unless ($fexcgi) { die "$0: no SEX URL found, use \"$0 -u SEX-URL/recipient\" or \"fexsend -I\"\n"; } unless ($user) { die "$0: no recipient found, use \"$0 -u SEX-URL/recipient\" or \"fexsend -I\"\n"; } } else { # sexsend $opt_g = 1; getopts('hguvqVt:') or die $usage; die $usage if $opt_h; if ($opt_V) { print "Version: $version\n"; exit unless @ARGV; } if ($opt_t and $opt_t =~ /^\d+$/) { $timeout = "&timeout=$opt_t"; } my $save_user = $user; $user = shift or die $usage; $fexcgi = $1 if $user =~ s:(.+)/::; if ($user =~ /^anonymous/) { die "$0: need SEX-URL with anonymous SEX\n" unless $fexcgi; $mode = 'anonymous'; } elsif ($user eq 'public') { unless ($id) { die "$0: public SEX not possible without FEXID, set it with \"fexsend -I\"\n"; } $mode = $user; $user = $save_user; } else { unless ($fexcgi) { die "$0: no SEX URL found, use \"$0 SEX-URL/recipient\" or \"fexsend -I\"\n"; } } } $fexcgi =~ s(^http://)()i; $fexcgi =~ s(/fup.*)(); $server = $fexcgi; if ($server =~ s(^https://)()i) { $port = 443 } elsif ($server =~ /:(\d+)/) { $port = $1 } else { $port = 80 } $server =~ s([:/].*)(); ## set up tcp/ip connection # $iaddr = gethostbyname($server) # or die "$0: cannot find ip-address for $server $!\n"; # socket(SH,PF_INET,SOCK_STREAM,getprotobyname('tcp')) or die "$0: socket $!\n"; # connect(SH,sockaddr_in($port,$iaddr)) or die "$0: connect $!\n"; # warn "connecting $server:$port user=$user\n"; if ($port == 443) { eval "use IO::Socket::SSL"; die "$0: cannot load IO::Socket::SSL\n" if $@; $SH = IO::Socket::SSL->new( PeerAddr => $server, PeerPort => $port, Proto => 'tcp', ); } else { $SH = IO::Socket::INET->new( PeerAddr => $server, PeerPort => $port, Proto => 'tcp', ); } die "cannot connect $server:$port - $!\n" unless $SH; warn "TCPCONNECT to $server:$port\n" if $opt_v; # autoflush $SH 1; autoflush STDERR; $SIG{PIPE} = \&sigpipehandler; if ($0 eq 'sexget' or $0 eq 'fuckme') { $stream = "&stream=" . shift if @ARGV; if ($anonymous) { $cid = 'anonymous'; } elsif ($id eq 'public') { $cid = 'public'; } else { $cid = query_sid($server,$port,$id); } request("GET /sex?user=$user&ID=$cid$stream HTTP/1.0"); transfer($SH,STDOUT); # print while sysread $SH,$_,$bs; exit; } if ($0 eq 'sexxx') { $stream = "&stream=" . ($opt_s || 'xx'); if (@ARGV) { warn "streaming:\n"; open my $tar,'-|','tar',"cv${opt_c}f",'-',@ARGV or die "$0: cannot run tar - $!\n"; request("POST /sex?user=$user$type$stream HTTP/1.0"); transfer($tar,$SH); # while (read $tar,$_,$bs) { syswrite $SH,$_ } } else { $cid = query_sid($server,$port,$id); request("GET /sex?user=$user&ID=$cid$stream HTTP/1.0"); $opt_c = 'z' if $H{'CONTENT-TYPE'} =~ /gzip/i; if (-t STDOUT) { print "extracting from stream:\n"; open $out,"|tar xv${opt_c}f -" or die "$0: cannot run tar - $!\n"; } else { if ($opt_c) { open $out,"|gzip -d" or die "$0: cannot run gunzip - $!\n"; } else { $out = *STDOUT; } } print {$out} $_ while sysread $SH,$_,$bs; } exit; } # sexsend $stream = "&stream=" . shift if @ARGV; if ($mode eq 'anonymous') { unless ($opt_q) { print "http://$server:$port/sex?user=$user&ID=anonymous$stream\n"; printf "http://$server:$port/sex?%s\n", encode_b64("user=$user&ID=anonymous$stream"); } $mode = "&mode=anonymous"; } elsif ($mode eq 'public') { die "$0: need user/ID when sending to public, set it with fexsend -I\n" unless $user and $id; unless ($opt_q) { print "http://$server:$port/sex?user=$user&ID=public$stream\n"; printf "http://$server:$port/sex?%s\n", encode_b64("user=$user&ID=public$stream"); } $cid = query_sid($server,$port,$id); $mode = "&ID=$cid&mode=public"; } else { # $user = checkalias($user) unless $opt_d; } request("POST /sex?user=$user$mode$type$timeout$stream HTTP/1.0"); print STDERR "==> (streaming ...)\n" if $opt_v; transfer(STDIN,$SH); exit; sub transfer { my $source = shift; my $destination = shift; my ($t0,$t1,$tt); my ($B,$b,$bt); $t0 = $t2 = time; $tt = $t0-1; $t1 = 0; while ($b = sysread $source,$_,$bs) { syswrite $destination,$_ or die $!; $B += $b; if ($opt_g) { $bt += $b; $t2 = time; if ($t2>$t1) { if ($B>2*M) { printf STDERR "%d MB %d kB/s \r", int($B/M),int($bt/k/($t2-$tt)); } else { printf STDERR "%d kB %d kB/s \r", int($B/k),int($bt/k/($t2-$tt)); } $t1 = $t2; if ($t2-$tt>10) { $bt = 0; $tt = $t2; } } } } die "$0: no stream data\n" unless $B; $tt = (time-$t0)||1; if ($opt_v or $opt_g) { if ($B>2097152) { printf STDERR "transfered: %d MB in %d s with %d kB/s\n", int($B/1048576),$tt,int($B/1024/$tt); } elsif($B>2048) { printf STDERR "transfered: %d kB in %d s with %d kB/s\n", int($B/1024),$tt,int($B/1024/$tt); } else { printf STDERR "transfered: %d B in %d s with %d kB/s\n", $B,$tt,int($B/1024/$tt); } } } sub request { my $req = shift; print STDERR "==> $req\n" if $opt_v; syswrite $SH,"$req\r\n\r\n"; for (;;) { unless (defined($_ = &getline)) { die "$0: server has closed the connection\n"; } if (/^HTTP\/[\d\.]+ 200/) { print STDERR "<== $_" if $opt_v; last; } elsif (/^HTTP\/[\d\.]+ 199/) { print STDERR "<== $_" if $opt_v; } else { if ($opt_v) { print STDERR "<== $_"; exit 3; } else { s:^HTTP/[ \d\.]+::; s/\r//; die "$0: server response: $_"; } } } while (defined($_ = &getline)) { last if /^\s*$/; $H{uc($1)} = $2 if /(.+):\s*(.+)/; print STDERR "<== $_" if $opt_v; } } # check for (mutt) alias sub checkalias { my $to = shift; if ($to !~ /@/ and open F,$ENV{HOME}.'/.mutt/aliases') { while () { next if /,/; if (/^alias $to\s/i) { chomp; s/\s*#.*//; s/\s+$//; s/.*\s+//; s///; $to = $_; warn "$0: found alias, using address $to\n"; die unless $to; last; } } close F; } return $to; } sub despace { foreach (@_) { s/^\s+//; s/\s+$//; } } sub query_sid { my ($server,$port,$id) = @_; my $req; local $_; $req = "GET SID HTTP/1.1"; print STDERR "==> $req\n" if $opt_v; syswrite $SH,"$req\r\n\r\n"; $_ = &getline; unless (defined $_ and /\w/) { print STDERR "\n" if $opt_v; die "$0: no response from server\n"; } s/\r//; if (/^HTTP.* 201 (.+)/) { print STDERR "<== $_" if $opt_v; $id = 'MD5H:'.md5_hex($id.$1); while (defined($_ = &getline)) { s/\r//; last if /^\n/; print STDERR "<== $_" if $opt_v; } } else { die "$0: $server does not support session ID\n"; } return $id; } sub sigpipehandler { local $_ = ''; $SIG{ALRM} = sub { }; alarm(1); $_ = &getline||''; if (/^HTTP.* \d+ (.*)/) { if ($opt_v) { die "\n$0: server error: @_\n"; } else { die "\n$0: server error: $1\n"; } } else { die "\n$0: got SIGPIPE (server closed connection)\n"; } } # read one text line from $SH; sub getline { my $line = ''; my $c; local $SIG{ALRM} = sub { die "$0: timeout while waiting for server reply\n" }; alarm($opt_t||300); # must use sysread to avoid perl line buffering while (sysread $SH,$c,1) { $line .= $c; last if $c eq "\n"; } alarm(0); return $line; } sub mtime { my @d = localtime((stat shift)[9]); return sprintf('%d%02d%02d',$d[5]+1900,$d[4]+1,$d[3]); } # from MIME::Base64::Perl sub decode_b64 { local $_ = shift; my $uu = ''; my ($i,$l); tr|A-Za-z0-9+=/||cd; s/=+$//; tr|A-Za-z0-9+/| -_|; return "" unless length; $l = (length) - 60; for ($i = 0; $i <= $l; $i += 60) { $uu .= "M" . substr($_,$i,60); } $_ = substr($_,$i); if (length) { $uu .= chr(32 + (length)*3/4) . $_; } return unpack ("u",$uu); } sub encode_b64 { my $res = ""; my $eol = $_[1]; my $padding; $eol = "\n" unless defined $eol; pos($_[0]) = 0; $res = join '',map(pack('u',$_)=~ /^.(\S*)/, ($_[0]=~/(.{1,45})/gs)); $res =~ tr|` -_|AA-Za-z0-9+/|; $padding = (3-length($_[0])%3)%3; $res =~ s/.{$padding}$/'=' x $padding/e if $padding; return $res; } fex-20130805/bin/logwatch0000755000174700017470000000527612174156054013227 0ustar fexfex#!/usr/bin/perl -w use Encode; use File::Basename; # add fex lib $ENV{FEXLIB} = $FEXLIB = dirname(dirname($0)).'/lib'; die "$0: no $FEXLIB\n" unless -d $FEXLIB; # import from fex.pp our ($logdir,$debug); # load common code, local config : $HOME/lib/fex.ph require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n"; binmode(STDOUT,":encoding(ISO-8859-1)"); $log = shift || "$logdir/fexsrv.log"; $ignore = join('|',qw( (CONNECT|CONTINUE).*(crawl|msnbot|obertux) DISCONNECT:.no.HTTP.request GET.*(favicon|robots\.txt) GET./organization\.gif GET./small_logo\.jpg GET./10+.B GET.*Arrow\.gif GET./apple-touch User-Agent:.*(Webnote|FeedFetcher|\w+bot|bot/|Website.Watcher|crawler|spider|searchme|Yandex|Slurp|ScoutJet|findlinks|urlmon) User-Agent:.fnb.*quak From:.*(msnbot|yandex|googlebot|webcrawler) Referer:.*sex.*stream Referer:.*stream.*sex X-.*prefetch X-Purpose:.preview )); @weed = qw( .*keep-alive .*no-cache Connection: Cache-Control: Content-Type: Accept TE: UA-CPU: Pragma: DNT: Via: profile: if-modified-since Surrogate-Capability X-Moz X-Wap X-FH X-Nokia X-UCBrowser X-NSN X-OperaMini x-Device x-up X-Behavioral X-Do-Not-Track X-\S*Via x-Mobile X-Country .*:\s*$ ); $/ = "\n\n"; $| = 1; if (-t STDIN or $ENV{GATEWAY_INTERFACE}) { open L,$log or die "$0: $log - $!\n"; seek L,0,2; } else { *L = *STDIN; } for (;;) { while () { next if /(^|\n)($ignore)/i; s/[\x00-\x08\x0B-\x1F\x1F\x80-\x9F]/_/g; s/^\n//; foreach $weed (@weed) { while (s/\n$weed.*\n/\n/i) {} } if (/^\n*(CONNECT|CONTINUE).*\s\[([\d_]+)\]/i) { $pid = $2 } if (/\n(POST|GET)\s+\/(\w+)/i) { $cgi = $2 } if (/Content-Length: (\d+)/i) { $d = $1; while ($d =~ s/(\d)(\d\d\d\b)/$1,$2/) {}; s/Content-Length: \d+/Content-Length: $d/i; } s/\n*$/\n\n/; print or exit; } sleep 1; if ($debug and $pid and $cgi) { sleep 1; &read_debug_log; $pid = $cgi = ''; }; } sub read_debug_log { my (@log,$log); local $/ = "\n"; # no warnings "all"; if (@log = glob "$logdir/.debug/*_$pid.$cgi") { $log = pop @log; if (open $log,$log) { binmode($log,":encoding(UTF-8)"); while (<$log>) { s/\r//; if (/^Content-Disposition:.*name="FILE".*filename="(.+)"/i) { print " FILE=\"$1\"\n"; } elsif (/^Content-Disposition:.*name="(\w+)"/i) { $p = $1; $_ = <$log>; $v = <$log>; $v =~ s/[\r\n]+//; print " $p=\"$v\"\n" if $v; } elsif (/^(Param|Exp): (\w+=".+")/) { print " $2\n"; } } close $log; print "\n"; } } } fex-20130805/bin/fex_cleanup0000755000174700017470000003375012164756512013712 0ustar fexfex#!/usr/bin/perl -w # cleanup for F*EX service # # run this program via cron-job once at night! # # Author: Ulli Horlacher # use Getopt::Std; use File::Basename; use IO::Socket::INET; use Digest::MD5 qw'md5_hex'; use constant DS => 60*60*24; # do not run as CGI! exit if $ENV{SCRIPT_NAME}; unless ($ENV{FEXLIB}) { if ($ENV{FEXHOME}) { $ENV{FEXLIB} = $FEXLIB = $ENV{FEXHOME}.'/lib'; } else { $ENV{FEXLIB} = $FEXLIB = dirname(dirname($0)).'/lib'; } } die "$0: no FEXLIB\n" unless -f "$FEXLIB/fex.pp"; # program name $0 =~ s:.*/::; $| = 1; # use fex.ph for site configuration! our ($FEXHOME); our ($spooldir,$logdir,$docdir); our ($akeydir,$ukeydir,$dkeydir,$skeydir,$gkeydir,$xkeydir,$lockdir); our ($durl,$debug,$autodelete,$hostname,$admin,$admin_pw,$bcc); $keep_default = 5; # load common code, local config : $HOME/lib/fex.ph require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n"; # localized functions # (needed for reminder e-mails and account reactivation) foreach my $lf (glob "$FEXHOME/locale/*/lib/lf.pl") { require $lf } # default locale functions (from fex.pp) $notify{english} = \¬ify; $reactivation{english} = \&reactivation; $opt_v = $opt_d = 0; getopts('vd'); $opt_v = $opt_d if $opt_d; $today = time; $isodate = isodate($today); chdir $spooldir or die "$0: $spooldir - $!\n"; open L,">>$logdir/cleanup.log"; # clean up regular spool opendir $spooldir,'.' or die "$0: $spooldir - $!\n"; while ($to = readdir $spooldir) { next if $to !~ /@/ or -l $to; if (@demo and -f "$to/.demo" and time > mtime("$to/.demo")+$demo[1]*DS) { logdel($to,"demo user $to deleted"); next; } if (-d $to and $to !~ /^\./) { opendir TO,$to or die "$0: $spooldir/$to - $!\n"; 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 !~ /^\./) { opendir FROM,"$to/$from" or die "$0: $spooldir/$to/$from - $!\n"; 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"; } } closedir FROM; rmdir "$to/$from"; } } } closedir TO; @glob = glob "$to/*/* $to/\@MAINUSER/* $to/\@GROUP/*"; unless (@glob or -f "$to/\@") { logdel($to,"$to deleted"); } } } closedir $spooldir; # clean up download key lookup directory if (chdir $dkeydir and opendir D,'.') { while ($file = readdir D) { next if $file eq '.' or $file eq '..'; if ($link = readlink $file and (not -l "$link/dkey" or readlink "$link/dkey" ne $file)) { logdel($file,".dkeys/$file deleted"); } } closedir D; } # clean up upload key lookup directory if (chdir $ukeydir and opendir D,'.') { while ($file = readdir D) { next if $file eq '.' or $file eq '..'; if (($link = readlink $file and not -e "$link/upload" or -f $file and time>mtime($file)+DS)) { logdel($file,".ukeys/$file deleted"); } } closedir D; } # clean up authorization key lookup directory if (chdir $akeydir and opendir D,'.') { while ($file = readdir D) { next if $file eq '.' or $file eq '..'; if (-l $file and time>mtime($file)+DS) { logdel($file,".akeys/$file deleted"); } } closedir D; } # clean up extra download key lookup directory if (chdir $xkeydir and opendir D,'.') { while ($file = readdir D) { next if $file eq '.' or $file eq '..'; if (-l $file and not (-f "$file/upload" or -f "$file/data")) { logdel($file,".xkeys/$file deleted"); } } closedir D; } # clean up lock directory if (chdir $lockdir and opendir D,'.') { while ($file = readdir D) { if (-f $file and time>mtime($file)+DS) { logdel($file,".locks/$file deleted"); } } closedir D; } # clean up error directory if (chdir "$spooldir/.error" and opendir D,'.') { while ($file = readdir D) { next if $file eq '.' or $file eq '..'; if (-f $file) { $mtime = mtime($file); if ($mtime and $today > 5*$keep_default*DS+$mtime) { logdel($file,".error/$file deleted"); } } } closedir D; } # clean up debug directory if (chdir "$logdir/.debug" and opendir D,'.') { while ($file = readdir D) { next if $file eq '.' or $file eq '..'; if (-f $file) { $mtime = mtime($file); if ($mtime and $today > $keep_default*DS+$mtime) { # logdel($file,".debug/$file deleted"); if ($opt_d) { print "unlink .debug/$file\n" } else { unlink $file } } } } closedir D; } # clean up subuser keys directory if (chdir $skeydir and opendir D,'.') { while ($file = readdir D) { next if $file eq '.' or $file eq '..'; if (-f $file and open F,$file) { $delete = 1; $from = $to = $id = ''; while () { if (/^(\w+)=(.+)/) { $from = $2 if $1 eq 'from'; $to = $2 if $1 eq 'to'; $id = $2 if $1 eq 'id'; } } close F; if ($from and $to and $id and open F,"$spooldir/$to/\@SUBUSER") { while () { if (/^\Q$from:$id\E$/) { $delete = 0; last; } } close F; } if ($delete) { logdel($file,".skeys/$file deleted"); } } } closedir D; } # clean up orphan subuser links chdir $spooldir; foreach $subuser (glob '*/@MAINUSER/*') { if ($skey = readlink $subuser and not -f "$skeydir/$skey") { logdel($subuser,"$subuser deleted"); } } foreach $subuser (glob '*/@MAINUSER') { unlink $subuser unless $opt_d; } # clean up old OKEYs chdir $spooldir; foreach my $okey (glob '*/@OKEY/*') { if (time > mtime($okey)+30*DS) { logdel($okey,"$okey deleted"); } } # clean up group keys directory if (chdir $gkeydir and opendir D,'.') { while ($gkey = readdir D) { next if $gkey eq '.' or $gkey eq '..'; if (-f $gkey and open F,$gkey) { $delete = 1; $from = $group = $id = ''; while () { if (/^(\w+)=(.+)/) { $from = $2 if $1 eq 'from'; $group = $2 if $1 eq 'to'; $id = $2 if $1 eq 'id'; } } close F; $group =~ s/^@//; $gf = "$spooldir/$from/\@GROUP/$group"; if ($from and $group and $id and open F,$gf) { while () { if (/^\Q$from:$id\E$/) { $delete = 0; last; } } close F; } if ($delete) { logdel($gkey,".gkeys/$gkey deleted"); logdel($gf,"$gf deleted") if -l $gf; } } } closedir D; } # clean up self registration directory if (chdir "$spooldir/.reg" and opendir D,'.') { while ($file = readdir D) { next if $file eq '.' or $file eq '..'; if (-f $file) { $mtime = mtime($file); if ($mtime and $today > $mtime+DS) { logdel($file,".reg/$file deleted"); } } } closedir D; } # send account expiration warning if ($account_expire and $account_expire =~ /^(\d+):(\w+)/) { my $expire = $1; if (chdir $spooldir and opendir $spooldir,'.') { my $fid = "$FEXHOME/.fex/id"; unless (-f "$admin/\@" and -f $fid) { $admin_pw ||= rand(1000000000000000); warn "create new fex account for $admin\n"; system("$FEXHOME/bin/fac -u $admin $admin_pw"); die "$0: cannot create account for $admin\n" unless -f "$admin/\@"; mkdir "$FEXHOME/.fex"; rename $fid,$fid.'_save' and warn "create new $fid (old saved)\n"; open $fid,'>',$fid or die "$0: cannot create $fid - $!"; $durl =~ m{(https?://.+?)/}; print {$fid} "$1\n"; print {$fid} "$admin\n"; print {$fid} "$admin_pw\n"; close $fid; } while ($user = readdir $spooldir) { next if $user !~ /@/ or -l $user; next if $login_check and &$login_check(readlink("$user/.login")); if (-f "$user/\@" and time > mtime($user)+$expire*DS and not -e "$user/$admin/reactivation.txt") { # print "$spooldir/$user\n"; if ($user !~ /^fexmaster/ and $user ne $admin) { my $locale = readlink "$user/\@LOCALE"; $locale = 'english' unless $locale and $reactivation{$locale}; &{$reactivation{$locale}}($expire,$user); sleep 1; } } } closedir $spooldir; } } close L; if ($notify_newrelease) { $newnew = $new = ''; $snew = $FEXHOME.'/doc/new'; $new = slurp($snew)||''; for (1..3) { $SH = IO::Socket::INET->new( PeerAddr => 'fex.rus.uni-stuttgart.de', PeerPort => 80, Proto => 'tcp', ) and last; sleep rand(10); }; if ($SH) { print {$SH} "GET /new HTTP/1.0\r\n"; print {$SH} "\r\n"; if ((<$SH>||'') =~ /200 OK/) { while (<$SH>) { last if /^\s*$/ } while (<$SH>) { $newnew .= $_ } } close $SH; if ($newnew ne $new) { if (open $sendmail,"|$sendmail $notify_newrelease $bcc") { pq($sendmail,qq( 'From: fex\@$hostname' 'To: $notify_newrelease' 'Subject: new F*EX release' '' '$newnew' )); close $sendmail; if (open $snew,'>',$snew) { print {$snew} $newnew; close $snew; } } } } } exit; # file clean up sub cleanup { my ($to,$from,$file) = @_; my ($data,$download,$notify,$mtime,$warn,$dir,$filename,$dkey,$delay); my $comment = ''; my $keep = $keep_default; my $kf = "$to/$from/$file/keep"; my $ef = "$to/$from/$file/error"; local $_; $keep = readlink $kf || readlink "$to/\@KEEP" || $keep_default; $file = "$to/$from/$file"; $data = "$file/data"; $download = "$file/download"; $notify = "$file/notify"; if ($file =~ /\/ADDRESS_BOOK/) { logdel($file,"$file deleted"); } elsif (-d $file and not -f $data) { if ($mtime = mtime("$file/upload")) { if ($today > $mtime+DS) { verbose("rmrf $file (today=$today mtime_upload=$mtime)"); logdel($file,"$file deleted"); } } elsif ($mtime = mtime("$file/error")) { if ($today > 3*$keep*DS+$mtime) { verbose("rmrf $file (today=$today mtime_error=$mtime keep=$keep)"); logdel($file,"$file deleted"); } } else { logdel($file,"$file deleted"); } } elsif (-s $download and -s $data and autodelete($file) !~ /NO/i) { $delay = autodelete($file); $delay = 1 if $delay !~ /^\d+$/; $delay--; $mtime = mtime($download); if ($mtime and $today > $delay*DS+$mtime and logdel($data,"$data deleted")) { if (open $ef,'>',$ef) { printf {$ef} "%s has been autodeleted after download at %s\n", filename($file),isodate(mtime($download)); close $ef; } } } elsif (-f $data) { my $reactivation = $file =~ m{/\Q$admin/reactivation.txt\E$}; $warn = $reactivation ? $keep-5 : $keep-2; $mtime = mtime("$file/filename") || mtime($data) || 0; if ($today > $mtime+$keep*DS) { if ($account_expire and $reactivation) { if ($account_expire =~ /delete/) { logdel($to,"$to removed - expired"); } else { if (open $sendmail,"|$sendmail $admin $bcc") { $account_expire =~ /(\d+)/; my $expire = $1 || 0; pq($sendmail,qq( 'From: fex\@$hostname' 'To: $admin' 'Subject: user $to expired' '' 'F*EX user $to has been inactive for $expire days' 'and has ignored the account reactivation mail.' 'You may want to delete this account.' )); close $sendmail; unlink $data; } else { warn "$0: cannot send mail - $!\n"; } } } else { if ($file =~ /^anonymous.*\/afex_\d/ or $to =~ /^_.+_/) { # also _fexmail_* logdel($file,"$file deleted") and verbose("rmrf $file (today=$today mtime_upload=$mtime)"); } elsif (logdel($data,"$data deleted")) { verbose("unlink $data (today=$today mtime=$mtime keep=$keep)"); if (open $ef,'>',$ef) { $filename = $file; $filename =~ s:.*/::; print $ef "$filename is expired"; close $ef; } } } } elsif ($file !~ /STDFEX$/ and $mtime+$warn*DS < $today and $dkey = readlink("$file/dkey") and not -s $download and not -f $notify and (readlink("$to/\@REMINDER")||'yes') ne 'no') { my $locale = readlink "$to/\@LOCALE" || readlink "$file/\@LOCALE"; $locale = 'english' unless $locale and $notify{$locale}; if (open my $c,"$file/comment") { chomp ($comment = <$c>||''); close $c; } &{$notify{$locale}}( status => 'remind', dkey => $dkey, filename => filename($file), keep => $keep, comment => $comment, warn => int(($mtime-$today)/DS)+$keep, autodelete => autodelete($file), ); open $notify,'>',$notify; close $notify; } } } sub autodelete { my $file = shift; my $adf = "$file/autodelete"; my $autodelete; if (-l $adf) { $autodelete = readlink $adf || ''; } elsif (open $adf,$adf) { chomp($autodelete = <$adf>||''); close $adf; } return $autodelete||$::autodelete; } sub mtime { my @s = lstat shift; return @s ? $s[9] : undef; } sub logdel { my ($file,$msg) = @_; my $status = 0; if ($opt_d) { print "$msg\n"; } else { if ($status = rmrf($file)) { print L "$isodate $msg\n"; print "$msg\n" if -t or $opt_v; } else { print L "$isodate $file DEL FAILED : $!\n"; die "$file DEL FAILED : $!\n" if -t or $opt_v; } } return $status; } sub verbose { local $_; if ($opt_v) { while ($_ = shift @_) { s/\n//; print "$_\n"; } } } fex-20130805/bin/fexsend0000755000174700017470000020301712177755047013056 0ustar fexfex#!/usr/bin/perl -w # CLI client for the F*EX service (send, list, delete) # # see also: fexget # # Author: Ulli Horlacher # # Copyright: Perl Artistic use 5.006; use strict qw'vars subs'; use Encode; use Config; use Socket; use IO::Handle; use IO::Socket::INET; use Getopt::Std; use File::Basename; use Cwd qw'abs_path'; use Fcntl qw':flock :mode'; use Digest::MD5 qw'md5_hex'; # encrypted ID / SID use Time::HiRes qw'time'; # use Smart::Comments; use constant k => 2**10; use constant M => 2**20; eval 'use Net::INET6Glue::INET_is_INET6'; our ($SH,$fexhome,$idf,$tmpdir,$windoof,$sigpipe,$useragent,$editor,$nomail); our ($anonymous,$public); our ($FEXID,$FEXXX,$HOME); our $chunksize = 0; our $version = 20130805; our $_0 = $0; $version ||= mtime($0); if ($Config{osname} =~ /^mswin/i) { $windoof = $Config{osname}; $HOME = $ENV{USERPROFILE}; $fexhome = $ENV{FEXHOME} || $HOME.'\fex'; $tmpdir = $ENV{FEXTMP} || $ENV{TEMP} || "$fexhome\\tmp"; $idf = "$fexhome\\id"; $editor = $ENV{EDITOR} || 'notepad.exe'; $useragent = sprintf("fexsend-$version (%s %s)", $Config{osname},$Config{archname}); } else { $0 =~ s:.*/::; $HOME = (getpwuid($<))[7]||$ENV{HOME}; $fexhome = $HOME.'/.fex'; $tmpdir = $ENV{FEXTMP} || "$fexhome/tmp"; $idf = "$fexhome/id"; $editor = $ENV{EDITOR} || 'vi'; $_ = `(lsb_release -d||uname -a)2>/dev/null`||''; chomp; s/^Description:\s+//; $useragent = "fexsend-$version ($_)"; } $| = 1; my $from = ''; my $to = ''; my $id = ''; my $skey = ''; my $gkey = ''; my $atype = ''; # archive type my $fexcgi; # F*EX CGI URL my @files; # files to send my $transferfile; # intermediate transport file my %AB = (); # server based address book my ($server,$port,$sid); my $proxy = ''; my $proxy_prefix = ''; my $features = ''; my $timeout = 30; # server timeout my $fexlist = "$tmpdir/fexlist"; my ($usage,$hints); my $xx = $0 =~ /^xx/; if ($xx) { $usage = "usage: send file(s): xx [:slot] file...\n". " or: send STDIN: xx [:slot] -\n". " or: send pipe: ... | xx [:slot] \n". " or: get file(s) or STDIN: xx [:slot] \n". " or: get file(s) no-questions: xx [:slot] --\n". "examples: dmesg | xx\n". " xx project\n". " xx --\n". " xx :conf /etc /boot\n"; } else { $usage = <>',$idf) { print {$idf} "\n[xx]\n", "$fexcgi\n", "$from\n", "$id\n"; close $idf; unlink $idf.'xx'; } } # special xx ID? if ($FEXXX = $ENV{FEXXX}) { $FEXXX = decode_b64($FEXXX) if $FEXXX !~ /\s/; ($fexcgi,$from,$id) = split(/\s+/,$FEXXX); } elsif (open $idf,$idf) { while (<$idf>) { if (/^\[xx\]/) { $proxy = $proxy_prefix = ''; &get_id($idf); last; } } close $idf; } } else { # alternativ ID? if ($opt_i) { $proxy = $proxy_prefix = ''; open $idf,$idf or die "$0: cannot open $idf - $!\n"; while (<$idf>) { if (/^\[$opt_i\]/) { &get_id($idf); last; } } close $idf; die "$0: no [$opt_i] in $idf\n" unless $_; } } if ($opt_I) { if ($xx) { &show_id } else { &init_id } exit; } if (@ARGV > 1 and $ARGV[-1] =~ /(^|\/)anonymous/) { $fexcgi = $1 if $ARGV[-1] =~ s:(.+)/::; die "usage: $0 [options] file FEXSERVER/anonymous\n" unless $fexcgi; $anonymous = $from = 'anonymous'; $sid = $id = 'ANONYMOUS'; } elsif (@ARGV > 1 and $id eq 'PUBLIC') { $public = $sid = $id; } elsif (@ARGV > 1 and $ARGV[-1] =~ m{^(https?://[\w.-]+(:\d+)?/fup\?[sg]key=\w+)}) { $fexcgi = $1; $skey = $1 if $fexcgi =~ /skey=(\w+)/; $gkey = $1 if $fexcgi =~ /gkey=(\w+)/; } else { $fexcgi = $opt_u if $opt_u; if (not -e $idf and not ($fexcgi and $from and $id)) { die "$0: no ID file $idf found, use \"fexsend -I\" to create it\n"; } unless ($fexcgi) { die "$0: no FEX URL found, use \"$0 -u URL\" or \"$0 -I\"\n"; } unless ($from and $id) { die "$0: no sender found, use \"$0 -f FROM:ID\" or \"$0 -I\"\n"; } if ($fexcgi !~ /^http/) { if ($fexcgi =~ /:443/) { $fexcgi = "https://$fexcgi" } else { $fexcgi = "http://$fexcgi" } } } $server = $fexcgi; $port = 80; $port = 443 if $server =~ s{https://}{}; $port = $1 if $server =~ s/:(\d+)//; $server =~ s{http://}{}; $server =~ s{/.*}{}; # $chunksize = 4*k unless $chunksize; $chunksize *= M; if ($proxy) { if ($port == 80) { $proxy_prefix = "http://$server" } elsif ($port != 443) { $proxy_prefix = "http://$server:$port" } } # xx: special file exchange between own accounts if ($xx) { my $transferfile = "$tmpdir/STDFEX"; # slot? if ($0 eq 'xxx') { $transferfile = "$tmpdir/xx:xxx"; } elsif (@ARGV and $ARGV[0] =~ /^:([\w.=+-]+)$/) { $transferfile = "$tmpdir/xx:$1"; shift @ARGV; } open my $lock,'>>',$transferfile or die "$0: cannot write $transferfile - $!\n"; flock($lock,LOCK_EX|LOCK_NB) or die "$0: $transferfile is locked by another process\n"; truncate $transferfile,0; if (not @ARGV and -t) { &get_xx($transferfile); } else { &send_xx($transferfile); } exit; } # regular fexsend &inquire if $windoof and not @ARGV and not ($opt_l or $opt_L or $opt_Q or $opt_A or $opt_U or $opt_I or $opt_f or $opt_x); if (${'opt_.'}) { $opt_C = "!SHORTMAIL! $opt_C"; } if ($opt_n or $opt_C =~ /NOMAIL|!#!/) { $nomail = 'NOMAIL'; } unless ($skey or $gkey or $anonymous) { if ($opt_v) { if ($FEXID) { warn "ID data from \$FEXID: $fexcgi $from $id\n"; } elsif (-f $idf) { warn "ID data from $idf: $fexcgi $from $id\n"; } } warn "Server/User: $fexcgi/$from\n" unless $opt_q; } if ($opt_V and not @ARGV) { exit } if ($opt_f) { &forward } elsif ($opt_x) { &modify } elsif ($opt_Q) { &query_quotas } elsif ($opt_l or $opt_L) { &list } elsif ($opt_U) { &show_URL } elsif ($opt_z or $opt_Z or ${'opt_!'}) { &get_log } elsif ($opt_A) { edit_address_book($from) } elsif (${'opt_@'}) { &show_address_book } elsif ($opt_d and $anonymous) { &purge } elsif ($opt_d and $ARGV[-1] =~ /^\d+$/) { &delete } else { &send_fex } exit; # initialize ID file sub init_id { my $tag; my $proxy = ''; if ($opt_I) { $tag = shift @ARGV; die $usage if @ARGV; } $fexcgi = $from = $id = ''; unless (-d $fexhome) { mkdir $fexhome,0700 or die "$0: cannot create FEXHOME $fexhome - $!\n"; } if (not $tag and open $idf,$idf) { $fexcgi = <$idf>; $from = <$idf>; $id = <$idf>; close $idf; if ($id) { chomp($fexcgi); chomp($from); chomp($id); $FEXID = encode_b64("$fexcgi $from $id"); if (-t STDIN) { print "# hint: to edit the ID file $idf use \"$0 -I .\" #\n"; print "export FEXID=$FEXID\n"; print "history -d \$((HISTCMD-1));history -d \$((HISTCMD-1))\n"; } else { print "FEXID=$FEXID\n"; } exit; } } if ($tag and $tag eq '.') { exec $ENV{EDITOR}||'vi',$idf } if ($tag) { print "F*EX server URL for [$tag]: " } else { print "F*EX server URL: " } $fexcgi = ; $fexcgi =~ s/[\s\n]//g; die "you MUST provide a FEX-URL!\n" unless $fexcgi; if ($fexcgi =~ /\?/) { $from = $1 if $fexcgi =~ /\bfrom=(.+?)(&|$)/i; $id = $1 if $fexcgi =~ /\bid=(.+?)(&|$)/i; $skey = $1 if $fexcgi =~ /\bskey=(.+?)(&|$)/i; $gkey = $1 if $fexcgi =~ /\bgkey=(.+?)(&|$)/i; $fexcgi =~ s/\?.*//; } unless ($fexcgi =~ /^[_:=\w\-\.\/\@\%]+$/) { die "\"$fexcgi\" is not a legal FEX-URL!\n"; } $fexcgi =~ s:/fup/*$::; print "proxy address (hostname:port or empty if none): "; $proxy = ; $proxy =~ s/[\s\n]//g; if ($proxy =~ /^[\w.-]+:\d+$/) { $proxy = "!$proxy"; } elsif ($proxy =~ /\S/) { die "wrong proxy address format\n"; } else { $proxy = ""; } if ($proxy) { print "proxy POST limit in MB (use 2048 if unknown): "; $_ = ; if (/(\d+)/) { $proxy .= "[$1]"; } } if ($skey) { $from = 'SUBUSER'; $id = $skey; } elsif ($gkey) { $from = 'GROUPMEMBER'; $id = $gkey; } else { unless ($from) { print "Your e-mail address as registered at $fexcgi: "; $from = ; $from =~ s/[\s\n]//g; die "you MUST provide your e-mail address!\n" unless $from; } unless ($from =~ /^[_:=\w\-\.\/\@\%\+]+$/) { die "\"$from\" is not a legal e-mail address!\n"; } unless ($id) { print "Your auth-ID for $from at $fexcgi: "; $id = ; $id =~ s/[\s\n]//g; die "you MUST provide your ID!\n" unless $id; } } if (open $idf,'>>',$idf) { print {$idf} "\n[$tag]\n" if $tag and -s $idf; print {$idf} "$fexcgi$proxy\n", "$from\n", "$id\n"; close $idf; print "data written to $idf\n"; } else { die "$0: cannot write to $idf - $!\n"; } } sub show_id { my ($fexcgi,$from,$id); if (open $idf,$idf) { $fexcgi = <$idf>; $from = <$idf>; $id = <$idf>; while (<$idf>) { if (/^\[xx\]/) { $fexcgi = <$idf>; $from = <$idf>; $id = <$idf>; } } close $idf; die "$0: too few data in $idf" unless defined $id; chomp($fexcgi); chomp($from); chomp($id); $FEXXX = encode_b64("$fexcgi $from $id"); if (-t STDIN) { print "export FEXXX=$FEXXX\n"; print "history -d \$((HISTCMD-1));history -d \$((HISTCMD-1))\n"; } else { print "FEXXX=$FEXXX\n"; } } else { die "$0: cannot read $idf - $!\n"; } } sub register { my $fs = shift @ARGV or die $usage; my $mail = shift @ARGV or die $usage; my $port; my ($server,$user,$id); die "$0: $idf does already exist\n" if -e $idf; if ($fs =~ /^https/) { die "$0: cannot handle https at this time\n"; } $fs =~ s{^http://}{}; $fs =~ s{/.*}{}; if ($fs =~ s/:(\d+)//) { $port = $1 } else { $port = 80 } tcpconnect($fs,$port); sendheader("$fs:$port","GET $proxy_prefix/fur?user=$mail&verify=no HTTP/1.1"); http_response(); while (<$SH>) { s/\r//; printf "<-- $_"if $opt_v; last if /^\s*$/; } while (<$SH>) { s/\r//; printf "<-- $_"if $opt_v; if (m{http://(.*)/fup\?from=(.+)&ID=(.+)}) { $server = $1; $user = $2; $id = $3; if (open F,">$idf") { print F "$server\n", "$user\n", "$id\n"; close F; chmod 0600,$idf; print "user data written to $idf\n"; print "you can now fex!\n"; exit; } else { die "$0: cannot write to $idf - $!\n"; } } } die "$0: no account data received from F*EX server\n"; } sub send_xx { my $transferfile = shift; my $file = ''; my (@r,@tar); $SIG{PIPE} = $SIG{INT} = sub { unlink $transferfile; exit 3; }; if ($0 eq 'xxx') { @tar = qw'tar -cv' } else { @tar = qw'tar -cvz' } if (-t) { if ("@ARGV" eq '-') { # store STDIN to transfer file shelldo("cat >> $transferfile"); } elsif (@ARGV) { 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); chdir $dir or die "$0: $dir - $!\n"; } else { $file = $ARGV[0]; } if (-l $file) { shelldo(@tar,qw'--dereference -f',$transferfile,$file); } else { shelldo(@tar,'-f',$transferfile,$file); } } else { shelldo(@tar,'-f',$transferfile,@ARGV); } if ($?) { unlink $transferfile; if ($? == 2) { die "$0: interrupted making tar transfer file\n"; } else { die "$0: error while making tar transfer file\n"; } } } } else { # write input from pipe to transfer file shelldo("cat >> $transferfile"); } die "$0: no transfer file\n" unless -s $transferfile; serverconnect($server,$port); query_sid($server,$port); @r = formdatapost( from => $from, to => $from, id => $sid, file => $transferfile, comment => 'NOMAIL', autodelete => $transferfile =~ /STDFEX/ ? 'NO' : 'DELAY', ); # open P,'|w3m -T text/html -dump' or die "$0: w3m - $!\n"; # print P @r; http_response(@r); if ($transferfile =~ /:/ and $0 ne 'xxx') { if ("@r" =~ /\s(X-)?Location: (http.*)\s/) { print "wget -O- $2 | tar xvzf -\n"; } } unlink $transferfile; } sub query_quotas { my (@r,$r); local $_; female_mode("query quotas?") if $opt_F; @r = formdatapost( from => $from, to => $from, id => $sid, comment => $opt_C, ); die "$0: no response from fex server $server\n" unless @r; $_ = shift @r; unless (/^HTTP.* 2/) { s:HTTP/[\d\. ]+::; die "$0: server response: $_\n"; } if (($_) = grep(/^X-Sender-Quota/,@r) and /(\d+)\s+(\d+)/) { print "sender quota (used): $1 ($2) MB\n"; } else { print "sender quota: unlimited\n"; } if (($_) = grep(/^X-Recipient-Quota/,@r) and /(\d+)\s+(\d+)/) { print "recipient quota (used): $1 ($2) MB\n"; } else { print "recipient quota: unlimited\n"; } } # list spool sub list { my (@r,$r); my ($data,$dkey,$n); 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/) { 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"; } exit; } } die "$0: file \#$n not found in fexlist\n"; } else { @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/) { s:HTTP/[\d\. ]+::; die "$0: server response: $_\n"; } # list sent files if ($opt_l) { open $fexlist,">$fexlist" or die "$0: cannot write $fexlist - $!\n"; foreach (@r) { next unless /
/ or $data;
      $data = 1;
      last if m:
:; if (//) { $dkey = $1 } else { $dkey = '' } # $_ = encode_utf8($_); s/<.*?>//g; if (/^(to .* :)/) { print "\n$1\n"; print {$fexlist} "\n$1\n"; } elsif (m/(\d+) MB (.+)/) { $n++; printf "%4s) %8d MB %s\n","#$n",$1,$2; printf {$fexlist} "%3d) %s %s\n",$n,$dkey,$2; } } close $fexlist; } # list received files if ($opt_L) { foreach (@r) { next unless /
/ or $data;
      $data = 1;
      next if m:
:;
      last if m:
:; if (/(from .* :)/) { print "\n$1\n"; } if (m{(\d+) (MB.*)
(.+)( ".*")?}) { printf "%8d %s%s%s\n",$1,$2,$3,($5||''); } } } } sub show_URL { printf "%s/fup/%s\n",$fexcgi,encode_b64("from=$from&id=$id"); exit; } sub get_log { my (@r); local $_; @r = formdatapost( from => $from, to => $from, id => $sid, comment => $opt_C, ); die "$0: no response from fex server $server\n" unless @r; $_ = shift @r; unless (/^HTTP.* 200/) { s:HTTP/[\d\. ]+::; die "$0: server response: $_\n"; } while (shift @r) {} foreach (@r) { print "$_\n" } } sub show_address_book { my (%AB,@r); my $alias; local $_; %AB = query_address_book($server,$port,$from); foreach $alias (sort keys %AB) { next if $alias eq 'ADDRESS_BOOK'; $_ = sprintf "%s = %s (%s) # %s\n", $alias, $AB{$alias}, $AB{$alias}->{options}, $AB{$alias}->{comment}; s/ \(\)//; s/ \# $//; print; } } sub purge { die "$0: not yet implemented\n"; } sub delete { my ($to,$file); while (@ARGV) { $opt_d = shift @ARGV; die "$usage: $0 -d #\n" if $opt_d !~ /^\d+$/; open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; while (<$fexlist>) { if (/^to (.+\@.+) :/) { $to = $1; } elsif (/^\s*(\d+)\) (\w+) (.+)/ and $1 eq $opt_d) { serverconnect($server,$port) unless $SH; sendheader( "$server:$port", "GET $proxy_prefix/fop/$2/$2?DELETE HTTP/1.1", "User-Agent: $useragent", ); $_ = <$SH>||''; s/\r//; print "<-- $_" if $opt_v; if (/^HTTP.* 200/) { while (<$SH>) { s/\r//; last if /^\n/; # ignore HTML output print "<-- $_" if $opt_v; if (/^X-File:.*\/(.+)/) { printf "%s deleted\n",decode_utf8(urldecode($1)); } } undef $SH; } elsif (s:HTTP/[\d\. ]+::) { die "$0: server response: $_"; } else { die "$0: no response from fex server $server\n"; } last; } } close $fexlist; sleep 1; # do not overrun server } exit; } sub send_fex { my @to; my $file = ''; my @files = (); my ($data,$aname,$alias); my (@r,$r); my $ma = $HOME.'/.mutt/aliases'; my $t0 = time; my @transferfiles; local $_; if ($from =~ /^SUBUSER|GROUPMEMBER$/) { $to = '_'; } else { # look for single @ in arguments for (my $i=1; $i<$#ARGV; $i++) { if ($ARGV[$i] eq '@') { $ARGV[$i] = join(',',@ARGV[$i+1 .. $#ARGV]); $#ARGV = $i; last; } } $to = pop @ARGV or die $usage; if ($to eq '.') { $to = $from; $opt_C ||= 'NOMAIL'; } if ($to eq ':') { $to = $from; $opt_C ||= 'NOMAIL'; } if ($opt_g and $to =~ /,/) { die "$0: encryption is supported to only one recipient\n"; } if ($to =~ m{^https?://.*/fup\?skey=(\w+)}) { $from = 'SUBUSER'; $to = '_'; $id = $1; } if ($to =~ m{^https?://.*/fup\?gkey=(\w+)}) { $from = 'GROUPMEMBER'; $to = '_'; $id = $1; } } @to = split(',',lc($to)); die $usage unless @ARGV or $opt_a or $opt_s; die $usage if $opt_s and @ARGV; # early serverconnect necessary for X-Features info serverconnect($server,$port); if ($anonymous) { my $aok; sendheader("$server:$port","OPTIONS FEX HTTP/1.1"); $_ = <$SH>||''; s/\r//; die "$0: no response from fex server $server\n" unless $_; print "<-- $_" if $opt_v; if (/^HTTP.* 201/) { while (<$SH>) { s/\r//; print "<-- $_" if $opt_v; last unless /\w/; $aok = $_ if /X-Features:.*ANONYMOUS/; } die "$0: no anonymous support on server $server\n" unless $aok; } else { die "$0: bad response from server $server : $_\n"; } } elsif ($public) { } else { query_sid($server,$port); if ($from eq 'SUBUSER') { $skey = $sid; # die "skey=$skey\nid=$id\nsid=$sid\n"; } if ($from eq 'GROUPMEMBER') { $gkey = $sid; } if ($to eq '.') { @to = ($from); $opt_C ||= 'NOMAIL'; } elsif ($to =~ m:^(//.*):) { my $xkey = $1; if ($features =~ /XKEY/) { @to = ($from); $opt_C = $xkey; } else { die "$0: server does not support XKEY\n"; } } elsif (grep /^[^@]*$/,@to and not $skey and not $gkey) { %AB = query_address_book($server,$port,$from); if ($proxy) { serverconnect($server,$port); query_sid($server,$port); } foreach $to (@to) { # alias in server address book? if ($AB{$to}) { # do not substitute alias with expanded addresses because then # keep and autodelete options from address book will get lost # $to = $AB{$to}; } # look for mutt aliases elsif ($to !~ /@/ and $to ne $from and open $ma,$ma) { $alias = $to; while (<$ma>) { if (/^alias \Q$to\E\s/i) { chomp; s/\s*#.*//; s/\(.*?\)//; s/\s+$//; s/.*\s+//; s/[<>]//g; if (/,/) { warn "$0: ignoring mutt multi-alias $to = $alias\n"; last; } if (/@/) { $alias = $_; warn "$0: found mutt alias $to = $alias\n"; last; } } } close $ma; $to = $alias; } } } $to = join(',',@to); if ( not $skey and not $gkey and $features =~ /CHECKRECIPIENT/ and $opt_C !~ /^(DELETE|LIST|RECEIVEDLOG|SENDLOG|FOPLOG)$/ and not($to =~ /@(.+)/ and $from =~ /@$1$/) ) { checkrecipient($from,$to); if ($proxy) { serverconnect($server,$port); query_sid($server,$port); } } } 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"; $opt_a = ; $opt_a =~ s/^\s+//; $opt_a =~ s/\s+$//; } if ($opt_s) { $opt_s =~ s/^=//; $opt_s =~ s:.*/::; $opt_s =~ s/[^\w_.+-]/_/g; @files = ($opt_s); } elsif ($opt_a) { $opt_a =~ s/^=//; $opt_a =~ s:.*/::; $opt_a =~ s/[^\w_.+-]/_/g; if ($opt_a =~ /(.+)\.(zip|tar|tgz|7z)$/) { $aname = $1; $atype = $2; } else { die "$0: archive name must be one of ". "$opt_a.tar $opt_a.tgz $opt_a.zip\n"; } # no file argument left? unless (@ARGV) { # use file name as archive name push @ARGV,$aname; $opt_a =~ s:/+$::g; $opt_a =~ s:.*/::g; } foreach my $file (@ARGV) { die "$0: cannot read $file\n" unless -l $file or -r $file; } $opt_a .= ".$atype" if $opt_a !~ /\.$atype$/; $transferfile = "$tmpdir/$opt_a"; unlink $transferfile; print "Making fex archive ($opt_a):\n"; if ($atype eq 'zip') { if ($windoof) { # if ($opt_c) { system(qw'7z a -tzip',$transferfile,@ARGV) } # else { system(qw'7z a -tzip -mm=copy',$transferfile,@ARGV) } system(qw'7z a -tzip',$transferfile,@ARGV); @files = ($transferfile); } else { # zip archives must be < 2 GB, so split as necessary @files = zipsplit($transferfile,@ARGV); if (scalar(@files) == 1) { $transferfile = $files[0]; $transferfile =~ s/_1.zip$/.zip/; rename $files[0],$transferfile; @files = ($transferfile); } } @transferfiles = @files; } elsif ($atype eq '7z') { # http://www.7-zip.org/ if ($opt_c) { system(qw'7z a',$transferfile,@ARGV) } else { system(qw'7z a -t7z -mx0',$transferfile,@ARGV) } @transferfiles = @files = ($transferfile); } elsif ($atype eq 'tar') { if ($windoof) { system(qw'7z a -ttar',$transferfile,@ARGV); @transferfiles = @files = ($transferfile); } else { ## tar is now handled by formdatapost() # system(qw'tar cvf',$transferfile,@ARGV); @files = ($opt_a); } } elsif ($atype eq 'tgz') { if ($windoof) { die "$0: archive type tgz not available, use tar, zip or 7z\n"; } else { ## tgz is now handled by formdatapost() # system(qw'tar cvzf',$transferfile,@ARGV); @files = ($opt_a); } } else { die "$0: unknown archive format \"$atype\"\n"; } if (@transferfiles) { # error in making transfer archive? if ($?) { unlink @transferfiles; die "$0: $! - aborting upload\n"; } # maybe timeout, so make new connect if (time-$t0 >= $timeout) { serverconnect($server,$port); query_sid($server,$port) unless $anonymous; } } } else { unless (@ARGV) { if ($windoof) { &inquire; } else { die $usage; } } foreach (@ARGV) { my $file = $_; unless ($opt_d) { unless (-f $file) { if (-e $file) { die "$0: $file is not a regular file, try option -a\n" } else { die "$0: $file does not exist\n"; } } die "$0: cannot read $file\n" unless -r $file; } push @files,$file; } } if (${'opt_/'}) { 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"; } } } 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"; } female_mode("send file $file?") if $opt_F; @r = formdatapost( from => $from, to => $to, replyto => $opt_r, id => $sid, file => $file, keep => $opt_k, comment => $opt_C, autodelete => $opt_D, ); if (not @r or not grep /\w/,@r) { die "$0: no response from server\n"; } 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"; } else { $r =~ s/.*?:\s*//; $r =~ s/<.+?>//g; die "$0: server error: $r\n"; } } if (($r) = grep /

\Q$file/,@r) { $r =~ s/<.+?>//g; print "$r\n"; } if ($opt_a !~ /^afex_\d+\.tar$/ and $file !~ /afex_\d+\.tar$/ and ($from eq $to or $from =~ /^\Q$to\E@/i or $nomail or $anonymous)) { print grep({s/^(X-Recipient:.*\((.+)\))/Parameters: $2\n/i} @r); print grep({s/^(X-)?(Location:.*)/$2\n/i} @r); } } # delete transfer tmp file unlink $transferfile if $transferfile; } sub forward { my (@r); my ($to,$n,$dkey,$file,$req); my $status = 1; local $_; # look for single @ in arguments for (my $i=1; $i<$#ARGV; $i++) { if ($ARGV[$i] eq '@') { $ARGV[$i] = join(',',@ARGV[$i+1 .. $#ARGV]); $#ARGV = $i; last; } } # if ($windoof and not @ARGV) { &inquire } $to = pop @ARGV or die $usage; $to = $from if $to eq '.'; open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; while (<$fexlist>) { if (/^\s*(\d+)\) (\w+) \[\d+ d\] (.+)/ and $1 eq $opt_f) { $n = $1; $dkey = $2; $file = $3; if ($file =~ s/ "(.*)"$//) { $opt_C ||= $1; } last; } } close $fexlist; unless ($n) { die "$0: file #$opt_f not found in fexlist\n"; } female_mode("forward file #$opt_f?") if $opt_F; serverconnect($server,$port); query_sid($server,$port); $req = "GET $proxy_prefix/fup?" ."from=$from&ID=$sid&to=$to&dkey=$dkey&command=FORWARD"; $req .= "&comment=$opt_C" if $opt_C; $req .= "&keep=$opt_k" if $opt_k; $req .= "&autodelete=$opt_D" if $opt_D; $req .= "&$opt_X" if $opt_X; $req .= " HTTP/1.1"; sendheader("$server:$port",$req); http_response(); while (<$SH>) { if ($opt_v) { print; } else { print if /\Q"$file"/; $status = 0; } } exit $status; } sub modify { my (@r); my ($n,$dkey,$file,$req); local $_; die $usage if @ARGV; die $usage unless $opt_C or $opt_k or $opt_D; open $fexlist,$fexlist or die "$0: $fexlist - $!\n"; while (<$fexlist>) { if (/^\s*(\d+)\) (\w+) \[\d+ d\] (.+)/ and $1 eq $opt_x) { $n = $1; $dkey = $2; $file = $3; $file =~ s/ "(.*)"$//; last; } } close $fexlist; unless ($n) { die "$0: file #$opt_x not found in fexlist\n"; } female_mode("modify file #$opt_x?") if $opt_F; serverconnect($server,$port); query_sid($server,$port); $req = "GET $proxy_prefix/fup?" ."from=$from&ID=$sid&dkey=$dkey&command=MODIFY"; $req .= "&comment=$opt_C" if $opt_C; $req .= "&keep=$opt_k" if $opt_k; $req .= "&autodelete=$opt_D" if $opt_D; $req .= " HTTP/1.1"; sendheader("$server:$port",$req); http_response(); while (<$SH>) { if ($opt_v) { print "<-- $_"; } else { print if /\Q$file/; } } exit; } sub get_xx { my $transferfile = shift; my $ft = ''; local $_; # get transfer file from FEX server unless ($SH) { serverconnect($server,$port); query_sid($server,$port); } xxget($from,$sid,$transferfile); # empty file? unless (-s $transferfile) { unlink $transferfile; exit; } # no further processing if delivering to pipe exec 'cat',$transferfile unless -t STDOUT; if ($ft = `file $transferfile 2>/dev/null`) { if ($ft =~ /compressed/) { rename $transferfile,"$transferfile.gz"; shelldo(ws("gunzip $transferfile.gz")); } $ft = `file $transferfile`; } # file command failed, so we look ourself into the file... elsif (open $transferfile,$transferfile) { read $transferfile,$_,4; close $transferfile; # gzip magic? if (/\x1F\x8B\x08\x00/) { rename $transferfile,"$transferfile.gz"; shelldo(ws("gunzip $transferfile.gz")); # assuming tar $ft = 'tar archive'; } } if ($ft =~ /tar archive/) { rename $transferfile,"$transferfile.tar"; $transferfile .= '.tar'; if ($opt_q) { $_ = 'y'; } else { print "Files in transfer-container:\n\n"; shelldo(ws("tar tvf $transferfile")); print "\nExtract these files? [Yn] "; $_ = ; } if (/^n/i) { print "keeping $transferfile\n"; } else { system("tar xvf $transferfile && rm $transferfile"); die "$0: error while untaring, see $transferfile\n" if -f $transferfile; } } else { exec 'cat',$transferfile; } exit; } sub formdatapost { my %P = @_; my ($boundary,$filename,$filesize,$length,$buf,$file,$fpsize,$resume,$seek); my ($flink); my (@hh,@hb,@r,@pv,$to); my ($bytes,$t,$bt); my ($t0,$t1,$t2,$tt,$tc); my $bs = 2**16; # blocksize for reading and sending file my $fileid = int(time); my $chunk = 0; my $connection = ''; my $pct = ''; my ($pid,$tar,$aname,$atype,$tarlist,$tarerror,$location); local $_; if (defined($file = $P{file})) { $to = $AB{$P{to}} || $P{to}; # for gpg # special file: stream from STDIN if ($opt_s) { $filename = encode_utf8($file); $filesize = -1; } # compression? if ($opt_c and not $transferfile) { my ($if,$of); $if = $file; $if =~ s/([^_\w\.\-])/\\$1/g; $transferfile = $tmpdir . '/' . basename($file) . '.gz'; $of = $transferfile; $of =~ s/([^_\w\.\-])/\\$1/g; shelldo("gzip <$if>$of"); die "$0: cannot gzip $file\n" unless -s $file; } # special file: tar-on-the-fly if (not $windoof and $opt_a and $file =~ /(.+)\.(tar|tgz)$/) { $aname = $1; $atype = $2; $tarlist = "$tmpdir/$aname.list"; $tarerror = "$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-"; } else { $tar .= " -f-"; } foreach (@ARGV) { $file = $_; $file =~ s/([^\w\-\@\#%,.=+~_:])/\\$1/g; $tar .= ' '.$file; } # print "calculating archive size... "; open $tar,"$tar 2>$tarerror|" or die "$0: cannot run tar - $!\n"; $t0 = int(time) if -t STDOUT; while ($b = read $tar,$_,$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 $tar) { $_ = ''; if (open $tarerror,$tarerror) { local $/; $_ = <$tarerror>; close $tarerror; } unlink $tarlist,$tarerror; die "$0: tar error:\n$_"; } $file = "$aname.$atype"; $filename = encode_utf8($file); undef $SH; # force reconnect (timeout!) } # single file else { $filename = encode_utf8(${'opt_='} || $file); if ($windoof) { $filename =~ s/^[a-z]://; $filename =~ s/.*\\//; } $filename =~ s:.*/::; $filename =~ s:[\r\n]+: :g; 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"; } } $filename .= '.gpg' if $opt_g; unless ($opt_d) { if ($opt_g) { $filesize = -1; $fileid = int(time); } else { if ($opt_a) { $fileid = md5_hex(fmd(@ARGV)); } else { $fileid = fileid($file); } } } } else { $file = $filename = ''; $filesize = 0; } FORMDATAPOST: @hh = (); # HTTP header @hb = (); # HTTP body @r = (); $seek = 0; $resume = ''; $chunk++; unless ($SH) { serverconnect($server,$port); query_sid($server,$port) unless $anonymous; } $P{id} = $sid; # 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,$P{to},$P{from},$P{id}, $filename,$fileid); if ($filesize == $seek) { print "Location: $location\n" if $location and $nomail; die "$0: $file has been already transferred\n"; } elsif ($seek and $seek < $filesize) { $resume = " (resuming at byte $seek)"; } elsif ($filesize <= $seek) { $seek = 0; } if ($proxy) { sleep 1; # do not overrun proxy serverconnect($server,$port); } } # file part size if ($chunksize and $proxy and $port != 443 and $filesize - $seek > $chunksize - $bs) { if ($features !~ /MULTIPOST/) { die sprintf("$0: server does not support chunked multi-POST needed for" ." files > %d MB via proxy\n",$chunksize/M); } $opt_o = 0; # no overwriting mode for next chunks $fpsize = $chunksize - $bs; } else { $fpsize = $filesize - $seek; } $boundary = randstring(48); $P{seek} = $seek; $P{filesize} = $filesize; # send HTTP POST variables if ($skey) { $P{skey} = $skey; @pv = qw'from to skey keep autodelete comment seek filesize'; } elsif ($gkey) { $P{gkey} = $gkey; @pv = qw'from to gkey keep autodelete comment seek filesize'; } else { @pv = qw'from to id replyto keep autodelete comment command seek filesize'; } foreach my $v (@pv) { if ($P{$v}) { my $name = uc($v); push @hb,"--$boundary"; push @hb,"Content-Disposition: form-data; name=\"$name\""; push @hb,""; push @hb,encode_utf8($P{$v}); } } # at last, POST the file if ($file) { push @hb,"--$boundary"; push @hb,"Content-Disposition: form-data; name=\"FILE\"; filename=\"$filename\""; unless ($opt_d) { if ($opt_M) { push @hb,"Content-Type: application/x-mime" } else { push @hb,"Content-Type: application/octet-stream" } if (${'opt_/'}) { $flink = abs_path($file); push @hb,"Content-Location: $flink"; } else { # push @hb,"Content-Length: " . ((-s $file||0) - $seek); # optional header! push @hb,"Content-Length: $fpsize"; # optional header! NOT filesize! push @hb,"X-File-ID: $fileid"; } push @hb,""; } push @hb,""; # prevent proxy chunked mode reply $connection = "close"; } push @hb,"--$boundary--"; if ($fpsize < 0) { $length = $fpsize; } else { $length = length(join('',@hb)) + scalar(@hb)*2 + $fpsize; } if ($file and not $opt_d) { if ($flink) { $hb[-2] = $flink } else { $hb[-2] = '(file content)' } } # any other extra URL arguments my $opt_X = ''; $opt_X = "?$::opt_X" if $::opt_X and $file; # HTTP header push @hh,"POST $proxy_prefix/fup$opt_X HTTP/1.1"; push @hh,"Host: $server:$port"; push @hh,"User-Agent: $useragent"; push @hh,"Content-Length: $length"; push @hh,"Content-Type: multipart/form-data; boundary=$boundary"; push @hh,"Connection: $connection" if $connection; push @hh,''; if ($opt_v) { print "--> $_\n" foreach (@hh,@hb); } $SIG{PIPE} = \&sigpipehandler; # foreach $sig (keys %SIG) { # eval '$SIG{$sig} = sub { print "\n!!! SIGNAL '.$sig.' !!!\n"; exit; }'; # } if ($file) { pop @hb; pop @hb unless $flink; nvtsend(@hh,@hb) or do { warn "$0: server has closed the connection, reconnecting...\n"; sleep 3; goto FORMDATAPOST; # necessary: new $sid ==> new @hh }; unless ($opt_d or $flink) { $t0 = $t2 = int(time); $tt = $t0-1; $t1 = 0; $tc = 0; if ($opt_s) { if ($opt_g) { open $file,"gpg -e -r $to|" or die "$0: cannot run gpg - $!\n"; } else { open $file,'>&=STDIN' or die "$0: cannot open STDIN - $!\n"; } } elsif ($tar) { if ($opt_g) { open $file,"$tar|gpg -e -r $to|" or die "$0: cannot run tar&gpg - $!\n"; } else { open $file,"$tar|" or die "$0: cannot run tar - $!\n"; } if (-t STDOUT) { $pid = fork(); if (defined $pid and $pid == 0) { sleep 1; if (open $tarlist,$tarlist) { # print "\n$tar|\n"; system "ls -l $tarlist"; while ($tarlist) { while (<$tarlist>) { print ' 'x(length($file)+40),"\r",$_; } sleep 1; } } exit; } $SIG{CHLD} = 'IGNORE'; } 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; 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"; seek $file,$seek,0; } binmode $file; } $bytes = 0; autoflush $SH 0; print $rcamel[0] if ${'opt_+'}; while (my $b = read $file,$buf,$bs) { print {$SH} $buf or &sigpipehandler; $bytes += $b; if ($filesize > 0 and $bytes+$seek > $filesize) { die "$0: $file filesize has grown while uploading\n"; } $bt += $b; $t2 = time; if (${'opt_+'} and int($t2*10)>$tc) { print $rcamel[$tc%2+1]; $tc = int($t2*10); } if (not $opt_q and -t STDOUT and int($t2)>$t1) { &sigpipehandler unless $SH->connected; # smaller block size is better on slow links $bs = 4096 if $t1 and $bs>4096 and $bytes/($t2-$t0)<65536; if ($filesize > 0) { $pct = sprintf "(%d%%)",int(($bytes+$seek)/$filesize*100); } if ($bytes>2*M and $bs>4096) { printf STDERR "%s: %d MB of %d MB %s %d kB/s \r", $opt_s||$opt_a||$file, int(($bytes+$seek)/M), int($filesize/M), $pct, int($bt/k/($t2-$tt)); } else { printf STDERR "%s: %d kB of %d MB %s %d kB/s \r", $opt_s||$opt_a||$file, int(($bytes+$seek)/k), int($filesize/M), $pct, int($bt/k/($t2-$tt)); } $t1 = $t2; # time window for transfer rate calculation if ($t2-$tt>10) { $bt = 0; $tt = $t2; } } last if $filesize > 0 and $bytes >= $fpsize; sleep 1 while ($opt_m and $bytes/k/(time-$t0||1) > $opt_m); } close $file; # or die "$0: error while reading $file - $!\n"; $tt = ($t2-$t0)||1; print $rcamel[2] if ${'opt_+'}; # terminate tar verbose output job if ($pid) { sleep 2; kill 9,$pid; unlink $tarlist; } unless ($opt_q) { if (not $chunksize and $bytes+$seek < $filesize) { die "$0: $file filesize has shrunk while uploading\n"; } if ($seek or $chunksize and $chunksize < $filesize) { if ($fpsize>2*M) { printf STDERR "%s: %d MB in %d s (%d kB/s)", $opt_s||$opt_a||$file, int($bytes/M), $tt, int($bytes/k/$tt); if ($bytes+$seek == $filesize) { printf STDERR ", total %d MB\n",int($filesize/M); } else { printf STDERR ", chunk #%d : %d MB\n", $chunk,int(($bytes+$seek)/M); } } else { printf STDERR "%s: %d kB in %d s (%d kB/s)", $opt_s||$opt_a||$file, int($bytes/k), $tt, int($bytes/k/$tt); if ($bytes+$seek == $filesize) { printf STDERR ", total %d kB\n",int($filesize/k); } else { printf STDERR ", chunk #%d : %d kB\n", $chunk,int(($bytes+$seek)/k); } } } else { if ($bytes>2*M) { printf STDERR "%s: %d MB in %d s (%d kB/s) \n", $opt_s||$opt_a||$file, int($bytes/M), $tt, int($bytes/k/$tt); } else { printf STDERR "%s: %d kB in %d s (%d kB/s) \n", $opt_s||$opt_a||$file, int($bytes/k), $tt, int($bytes/k/$tt); } } print STDERR "waiting for server ok..." if -t STDOUT; } } autoflush $SH 1; print {$SH} "\r\n--$boundary--\r\n"; shutdown($SH,1) if $opt_s or $opt_g; if ($flink) { $bytes = -s $flink; if ($bytes>2*M) { printf STDERR "%s: %d MB\n",$flink,int($bytes/M); } else { printf STDERR "%s: %d kB\n",$flink,int($bytes/k); } } } else { autoflush $SH 1; nvtsend(@hh,@hb); } # SuSe: Can't locate object method "BINMODE" via package "IO::Socket::SSL::SSL_HANDLE" # binmode $SH,':utf8'; if (not $opt_q and $file and -t STDOUT) { print STDERR "\r \r"; } while (<$SH>) { s/[\r\n]+//; print "<-- $_\n" if $opt_v; last if @r and $r[0] =~ / 204 / and /^$/ or /<\/html>/i; push @r,decode_utf8($_); } if ($file) { close $SH; undef $SH; if ($proxy and $fpsize+$seek < $filesize) { goto FORMDATAPOST; } } return @r; } sub randstring { my $n = shift; my @rc = ('A'..'Z','a'..'z',0..9 ); my $rn = @rc; my $rs; for (1..$n) { $rs .= $rc[int(rand($rn))] }; return $rs; } sub zipsplit { my $zipbase = shift; my @files = @_; my @zipfiles = (); my $file; my ($zsize,$size,$n); $zipbase =~ s/\.zip$//; map { s/([^_\w\+\-\.])/\\$1/g } @files; open my $ff,"find @files -type f|" or die "$0: cannot search for @_ - $!\n"; @files = (); zipfile: for (;;) { $n++; if ($n eq 10) { unlink @zipfiles; die "$0: too many zip-archives\n"; } $zsize = 0; while ($file = <$ff>) { chomp $file; next if -l $file or not -f $file; $size = -s $file; if ($size > 2147480000) { unlink @zipfiles; die "$0: $file too big for zip\n"; } if ($zsize + $size > 2147000000) { push @zipfiles,zip($zipbase.'_'.$n.'.zip',@files); @files = ($file); next zipfile; } else { push @files,$file; $zsize += $size; } } close $ff; last; } push @zipfiles,zip($zipbase.'_'.$n.'.zip',@files); return @zipfiles; } sub zip { no strict 'refs'; my $zip = shift; my $cmd; local $_; unlink $zip; # if ($opt_c) { $cmd = "zip -@ $zip" } # else { $cmd = "zip -0 -@ $zip" } $cmd = "zip -@ $zip"; print $cmd,"\n" if $opt_v; open $cmd,"|$cmd" or die "$0: cannot create $zip - $!\n"; foreach (@_) { print {$cmd} $_."\n" } close $cmd or die "$0: zip failed - $!\n"; return $zip; } sub getline { my $file = shift; local $_; while (<$file>) { chomp; s/^#.*//; s/\s+#.*//; s/^\s+//; s/\s+$//; return $_ if length($_); } return ''; } sub serverconnect { my ($server,$port) = @_; my $connect = "CONNECT $server:$port HTTP/1.1"; local $_; if ($proxy) { tcpconnect(split(':',$proxy)); if ($port == 443) { printf "--> %s\n",$connect if $opt_v; nvtsend($connect,""); $_ = <$SH>; s/\r//; printf "<-- $_"if $opt_v; unless (/^HTTP.1.. 200/) { die "$0: proxy error : $_"; } eval "use IO::Socket::SSL"; die "$0: cannot load IO::Socket::SSL\n" if $@; $SH = IO::Socket::SSL->start_SSL($SH); } } else { tcpconnect($server,$port); } } # set up tcp/ip connection sub tcpconnect { my ($server,$port) = @_; if ($SH) { close $SH; undef $SH; } if ($port == 443) { eval "use IO::Socket::SSL"; die "$0: cannot load IO::Socket::SSL\n" if $@; $SH = IO::Socket::SSL->new( PeerAddr => $server, PeerPort => $port, Proto => 'tcp', ); } else { $SH = IO::Socket::INET->new( PeerAddr => $server, PeerPort => $port, Proto => 'tcp', ); } if ($SH) { autoflush $SH 1; } else { die "$0: cannot connect $server:$port - $@\n"; } print "TCPCONNECT to $server:$port\n" if $opt_v; } sub query_file { my ($server,$port,$to,$from,$id,$filename,$fileid) = @_; my $seek = 0; my $qfileid = ''; my ($head,$location); local $_; $to =~ s/,.*//; $to =~ s/:\w+=.*//; $to = $AB{$to} if $AB{$to}; $filename =~ s/([^_=:,;<>()+.\w\-])/'%'.uc(unpack("H2",$1))/ge; # urlencode if ($skey) { $head = "HEAD $proxy_prefix/fop/$to/$from/$filename??SKEY=$id HTTP/1.1"; } elsif ($gkey) { $head = "HEAD $proxy_prefix/fop/$to/$from/$filename??GKEY=$id HTTP/1.1"; } else { $head = "HEAD $proxy_prefix/fop/$to/$from/$filename??ID=$id HTTP/1.1"; } sendheader("$server:$port",$head); $_ = <$SH>; unless (defined $_ and /\w/) { die "$0: no response from server\n"; } s/\r//; print "<-- $_" if $opt_v; unless (/^HTTP.* 200/) { s:HTTP/[\d\. ]+::; die "$0: server response: $_" unless /no such file/; } while (<$SH>) { s/\r//; print "<-- $_" if $opt_v; last if /^$/; if (/^Content-Length:\s+(\d+)/) { $seek = $1 } if (/^X-File-ID:\s+(.+)/) { $qfileid = $1 } if (/^X-Features:\s+(.+)/) { $features = $1 } if (/^X-Location:\s+(.+)/) { $location = $1 } } # return true seek only if file is identified $seek = 0 if $qfileid and $qfileid ne $fileid; return ($seek,$location); } sub edit_address_book { my ($user) = @_; my $alias; my $ab = "$fexhome/ADDRESS_BOOK"; my (%AB,@r); local $_; die "$0: address book not available for subusers\n" if $skey; die "$0: address book not available for group members\n" if $gkey; female_mode("edit your address book?") if $opt_F; %AB = query_address_book($server,$port,$user); if ($AB{ADDRESS_BOOK} !~ /\w/) { $AB{ADDRESS_BOOK} = "# Format: alias e-mail-address # Comment\n". "# Example:\n". "framstag framstag\@rus.uni-stuttgart.de\n"; } open $ab,">$ab" or die "$0: cannot write to $ab - $!\n"; print {$ab} $AB{ADDRESS_BOOK}; close $ab; system $editor,$ab; exit unless -s $ab; serverconnect($server,$port); query_sid($server,$port); @r = formdatapost( from => $user, to => $user, id => $sid, file => $ab, ); unlink $ab,$ab.'~'; } sub query_address_book { my ($server,$port,$user) = @_; my ($req,$alias,$address,$options,$comment,$cl,$ab,$b); my %AB; local $_; unless ($SH) { serverconnect($server,$port); query_sid($server,$port); } $req = "GET $proxy_prefix/fop/$user/$user/ADDRESS_BOOK?ID=$sid HTTP/1.1"; sendheader("$server:$port",$req); $_ = <$SH>; unless (defined $_ and /\w/) { die "$0: no response from server\n"; } s/\r//; print "<-- $_" if $opt_v; unless (/^HTTP.* 200/) { if (/^HTTP.* 404/) { while (<$SH>) { last if /^\r?\n/ } return; } else { # s:HTTP/[\d\. ]+::; # die "$0: server response: $_"; close $SH; undef $SH; return (); } } while (<$SH>) { s/\r//; print "<-- $_" if $opt_v; last if /^$/; $cl = $1 if /^Content-Length: (\d+)/; } if ($cl) { while (<$SH>) { $b += length; $ab .= $_; s/[\r\n]//g; s/^\s+//; s/\s+$//; print "<-- $_\n" if $opt_v; s/\s*#\s*(.*)//; if ($_) { $comment = $1||''; ($alias,$address,$options) = split; if ($address) { if ($options) { $options =~ s/[()]//g } else { $options = '' } $AB{$alias} = $address; $AB{$alias}->{options} = $options||''; $AB{$alias}->{comment} = $comment||''; if ($options and $options =~ /keep=(\d+)/i) { $AB{$alias}->{keep} = $1; } if ($options and $options =~ /autodelete=(\w+)/i) { $AB{$alias}->{autodelete} = $1; } } } last if $b >= $cl; } } $AB{ADDRESS_BOOK} = $ab; return %AB; } # sets global $sid $features $timeout sub query_sid { my ($server,$port) = @_; my ($req); local $_; $sid = $id; if ($port eq 443) { 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"; } else { $req = "GET SID HTTP/1.1"; } 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; if (/^HTTP.* [25]0[01] /) { if (not $proxy and $port ne 443 and /^HTTP.* 201 (.+)/) { $sid = 'MD5H:'.md5_hex($id.$1); } while (<$SH>) { s/\r//; print "<-- $_" if $opt_v; $features = $1 if /^X-Features: (.+)/; $timeout = $1 if /^X-Timeout: (\d+)/; last if /^\n/; } } elsif (/^HTTP.* 301 /) { while (<$SH>) { last if /Location/ } die "$0: cannot use $server:$port because server has a redirection to\n".$_; } else { # no SID support - perhaps transparent web proxy? serverconnect($server,$port); $sid = $id; } # warn "proxy: $proxy\n"; if ($proxy) { serverconnect($server,$port); $sid = $id; } } sub xxget { my ($from,$id,$save) = @_; my $bs = 4096; my $xx = $save; my ($url,$B,$b,$t0,$t1,$cl); my ($ts,$tso); local $_; $xx =~ s:.*/::; $url = "$proxy_prefix/fop/$from/$from/$xx?ID=$id"; sendheader("$server:$port","GET $url HTTP/1.1","User-Agent: $useragent"); http_response(); while (<$SH>) { s/\r//; print "<-- $_" if $opt_v; $cl = $1 if /^Content-Length:\s(\d+)/; # $ft = $1 if /^X-File-Type:\s(.+)/; last if /^$/; } die "$0: no Content-Length in server-reply\n" unless $cl; open F,">$save" or die "$0: cannot write to $save - $!\n"; binmode F; $t0 = $t1 = int(time); $tso = ''; while ($b = read($SH,$_,$bs)) { $B += $b; print F; if (int(time) > $t1) { $t1 = int(time); $ts = ts($B,$cl); if ($ts ne $tso) { print STDERR $ts,"\r"; $tso = $ts; } } sleep 1 while ($opt_m and $B/k/(time-$t0||1) > $opt_m); } print STDERR ts($B,$cl),"\n"; close F; } sub sendheader { my $sp = shift; my @head = @_; my $head; push @head,"Host: $sp"; foreach $head (@head) { print "--> $head\n" if $opt_v; print {$SH} $head,"\r\n"; } print "-->\n" if $opt_v; print {$SH} "\r\n"; } sub nvtsend { local $SIG{PIPE} = sub { $sigpipe = "@_" }; $sigpipe = ''; die "$0: internal error: no active network handle\n" unless $SH; die "$0: remote host has closed the link\n" unless $SH->connected; foreach my $line (@_) { print {$SH} $line,"\r\n"; if ($sigpipe) { undef $SH; return 0; } } return 1; } # transfer status sub ts { my ($b,$tb) = @_; return sprintf("transferred: %d MB (%d%%)",int($b/M),int($b/$tb*100)); } sub sigpipehandler { $SIG{ALRM} = sub { }; if (fileno $SH) { alarm(1); @_ = <$SH>; alarm(0); if (@_ and $opt_v) { die "\n$0: server error: @_\n"; } if (@_ and $_[0] =~ /^HTTP.* \d+ (.*)/) { die "\n$0: server error: $1\n"; } } $timeout *= 2; warn "\n$0: connection to $server died\n"; warn "retrying after $timeout seconds...\n"; sleep $timeout; if ($windoof) { exec $^X,$0,@_ARGV } else { exec $_0,@_ARGV } die $!; } sub checkrecipient { my ($from,$to) = @_; my @r; local $_; @r = formdatapost( from => $from, to => $to, id => $sid, command => 'CHECKRECIPIENT', ); $_ = shift @r or die "$0: no reply from server\n"; if (/ 2\d\d /) { foreach (@r) { last if /^$/; if (s/X-(Recipient: .+)/$1\n/) { s/autodelete=\w+/autodelete=$opt_D/ if $opt_D; s/keep=\d+/keep=$opt_k/ if $opt_k; print; } } } else { http_response($_,@r); } } # get ID data from ID file sub get_id { my $idf = shift; $fexcgi = getline($idf) || die "$0: no FEX-URL in $idf\n"; $from = getline($idf) || die "$0: no FROM in $idf\n"; $id = getline($idf) || die "$0: no ID in $idf\n"; if ($fexcgi =~ s/!([\w.-]+:\d+)(:(\d+))?//) { $proxy = $1; $chunksize = $3 || 0; } unless ($fexcgi =~ /^[_:=\w\-\.\/\@\%]+$/) { die "$0: illegal FEX-URL \"$fexcgi\" in $idf\n"; } unless ($from =~ /^[_:=\w\-\.\/\@\%\+]+$/) { die "$0: illegal FROM \"$from\" in $idf\n"; } $fexcgi =~ s:/+$::; } # for windows sub inquire { my ($file,$to); for (;;) { print "file to send: "; chomp($file = ); $file =~ s/^\"//; $file =~ s/\"$//; last if -e $file; warn "$file does not exist\n"; } print "recipient (e-mail address): "; chomp($to = ); die $usage unless $to; unless ($opt_n) { print "comment: "; chomp($opt_C = ); } @ARGV = ($file,$to); } sub shelldo { if (system(@_) < 0) { die "failed: @_\n" } } sub mtime { my @d = localtime((stat shift)[9]); return sprintf('%d%02d%02d',$d[5]+1900,$d[4]+1,$d[3]); } # emulate seek on a pipe sub readahead { my $fh = shift; # filehandle my $ba = shift; # bytes ahead my $bs = 2**16; my $s = 0; my $n; local $_; while ($s < $ba) { $n = $ba-$s; $n = $bs if $n > $bs; $s += read $fh,$_,$n; } } # fileid is inode and mtime sub fileid { my @s = stat(shift); return @s ? $s[1].$s[9] : int(time); } # collect file meta data (filename, inode, mtime) sub fmd { my @files = @_; my ($file,$dir); my $fmd = ''; foreach $file (@files) { if (not -l $file and -d $file) { $dir = $file; if (opendir $dir,$dir) { while (defined ($file = readdir($dir))) { next if $file eq '..'; if ($file eq '.') { $fmd .= $file.fileid($dir); } else { $fmd .= fmd("$dir/$file"); } } closedir $dir; } } else { $fmd .= $file.fileid($file); } } return $fmd; } # from MIME::Base64::Perl sub decode_b64 { local $_ = shift; my $uu = ''; my ($i,$l); tr|A-Za-z0-9+=/||cd; s/=+$//; tr|A-Za-z0-9+/| -_|; return "" unless length; $l = (length)-60; for ($i = 0; $i <= $l; $i += 60) { $uu .= "M" . substr($_,$i,60); } $_ = substr($_,$i); if (length) { $uu .= chr(32+(length)*3/4) . $_; } return unpack("u",$uu); } # from MIME::Base64::Perl sub encode_b64 { my $res = ""; my $eol = "\n"; my $padding; pos($_[0]) = 0; $res = join '',map(pack('u',$_)=~ /^.(\S*)/, ($_[0]=~/(.{1,45})/gs)); $res =~ tr|` -_|AA-Za-z0-9+/|; $padding = (3-length($_[0])%3)%3; $res =~ s/.{$padding}$/'=' x $padding/e if $padding; return $res; } sub female_mode { local $_; if (open my $tty,'/dev/tty') { print "@_\n"; print " [y] yes\n", " [n] no\n", " [p] perhaps - don't know\n", "your choice: "; $_ = <$tty> || ''; close $tty; if (/^y/i) { return } if (/^n/i) { exit } if (/^p/i) { int(rand(2)) ? return : exit } female_mode(@_); } } sub http_response { local $_ = shift || <$SH>; my @r = @_; $_ = <$SH> unless $_; unless (defined $_ and /\w/) { die "$0: no response from server\n"; } s/\r?\n//; # CGI fatalsToBrowser if (/^HTTP.* 500/) { @r = <$SH> unless @r; @r = () unless @r; die "$0: server error: $_\n@r\n"; } unless (/^HTTP.* 200/) { s/HTTP.[\s\d.]+//; die "$0: server error: $_\n"; } print "<-- $_\n" if $opt_v; return $_; } sub urldecode { local $_ = shift; s/\%([a-f\d]{2})/chr(hex($1))/ige; return $_; } sub ws { local $_ = shift; return split; } fex-20130805/bin/mksgkeys0000755000174700017470000000276112022437376013251 0ustar fexfex#!/usr/bin/perl -w # helper script to regenerate missing SKEYs and GKEYs use Digest::MD5 qw(md5_hex); @pw = getpwnam('fex'); $spool = $pw[7].'/spool'; chdir $spool or die "$spool - $!"; foreach $suf (glob "*/\@SUBUSER") { if (-f $suf and open $suf,$suf) { $to = $user = $suf; $to =~ s:/.*::; $user =~ s:/.*::; while (<$suf>) { chomp; s/#.*//; if (/(.+):(.+)/) { $from = $1; $id = $2; $skey = md5_hex("$user:$from:$id"); unless (-f ".skeys/$skey") { if (open $skey,">.skeys/$skey") { warn "creating $spool/.skeys/$skey\n"; print {$skey} "from=$from\n"; print {$skey} "to=$to\n"; print {$skey} "id=$id\n"; close $skey; } } } } close $suf; } } foreach $guf (glob "*/\@GROUP/*") { if (-f $guf and not -l $guf and open $guf,$guf) { $group = $user = $guf; $group =~ s:.*/::; $user =~ s:/.*::; while (<$guf>) { chomp; s/#.*//; if (/(.+):(.+)/) { $from = $1; $id = $2; $gkey = md5_hex("$user:$group:$from:$id"); unless (-f ".gkeys/$gkey") { if (open $gkey,">.gkeys/$gkey") { warn "creating $spool/.gkeys/$gkey\n"; print {$gkey} "from=$from\n"; print {$gkey} "to=\@$group\n"; print {$gkey} "user=$user\n"; print {$gkey} "id=$id\n"; close $gkey; } } } } close $guf; } } fex-20130805/bin/sexget0000777000174700017470000000000012177755050014276 2sexsendustar fexfexfex-20130805/bin/zz0000755000174700017470000000176012132513413012042 0ustar fexfex#!/bin/sh ZZ=${ZZ:-$HOME/.zz} if [ "X$*" = X-h -o "X$*" = X--help ]; then exec cat<>$ZZ fi if [ -t 0 ]; then if [ x"$1"x = xx ]; then exec cat -- $ZZ else test -f $ZZ && mv $ZZ $ZZ~ exec cat -- "$@" >$ZZ fi else test -f $ZZ && mv $ZZ $ZZ~ exec cat >$ZZ fi fex-20130805/bin/ezz0000755000174700017470000000245412116042746012220 0ustar fexfex#!/bin/sh ZZ=${ZZ:-$HOME/.zz} usage() { exec cat<>$ZZ else cat >$ZZ fi fi test -z "$1" && exec ${EDITOR:-vi} $ZZ case "X$*" in X-h) usage;; X-r) exec mv $ZZ~ $ZZ;; esac OUT="$1" test "X$OUT" = X- && shift test -z "$1" && exec cat $ZZ mv $ZZ $ZZ~ case `type "$1" 2>&1` in *not\ found) perl -pe "$@" <$ZZ~>$ZZ || mv $ZZ~ $ZZ;; *) "$@" <$ZZ~>$ZZ || mv $ZZ~ $ZZ;; esac test "X$OUT" = X- && exec cat $ZZ fex-20130805/bin/sexxx0000777000174700017470000000000012177755050014156 2sexsendustar fexfexfex-20130805/bin/asex0000777000174700017470000000000012177755050013211 2afexustar fexfexfex-20130805/bin/afex0000755000174700017470000001027012152046552012325 0ustar fexfex#!/usr/bin/perl -w # client for anonymous FEX or SEX # # Author: Ulli Horlacher # # Copyright: Perl Artistic $fexserver = ''; $0 =~ s:.*/::;; $u = $ENV{AFEX} || $fexserver || &guessserver; $u = "http://$u" if $u !~ /^http/; if (@ARGV and $ARGV[0] eq '-h' or not @ARGV and -t STDIN) { &usage } $opt_v = (@ARGV and $ARGV[0] eq '-v') ? shift @ARGV : ''; if ($0 eq 'asex') { $a = "$u/anonymous"; if (@ARGV and $ARGV[0] =~ /^\d+$/) { $id = shift; if ("@ARGV" eq '-') { exec "sexget $opt_v $a $id | tar xvf -"; } else { exec ws("sexget $opt_v $a $id"); } } else { if (@ARGV and $ARGV[0] =~ /^-(\d)/) { $id = sprintf("%0$1d",rand(10**$1)); shift @ARGV; } else { $id = sprintf("%06d",rand(1000000)); } print "# commands for SEX recipient:\n"; if (@ARGV) { print "wget -qO- $u/sex?anonymous=$id | tar xvf -\n"; print "asex $id -\n"; print "# streaming files and waiting for SEX recipient:\n"; exec "tar cvf - @ARGV | sexsend -q $opt_v $a $id"; } else { print "wget -qO- $u/sex?anonymous=$id\n"; print "asex $id\n"; exec ws("sexsend -q $opt_v $a $id"); } } exit; } if ($0 eq 'afex') { if ("@ARGV" =~/^-(\d+)$/) { $n = $1; $cmd = "wget -qO/dev/null $u/fop/anonymous/anonymous/afex_$n.tar?DELETE"; print "$cmd\n" if $opt_v; system ws($cmd); print "not " if $?; print "deleted\n"; exit; } # download if ("@ARGV" =~ /^(\d+)( -)?$/) { $id = $1; $nq = $2; $u .= "/fop/anonymous/anonymous/afex_$id.tar"; if ($nq) { exec "fexget $opt_v -s- $u | tar xvf -"; } else { $aft = "/tmp/afex_$id.tar"; $cmd = "fexget $opt_v -s- $u >$aft"; print "$cmd\n" if $opt_v; system $cmd; if (`file $aft` =~ /tar archive/) { print "Files in archive:\n"; $cmd = "tar tvf $aft"; print "$cmd\n" if $opt_v; system ws($cmd); print "extract these files (Y/n)? "; if ((||'y') =~ /^[Yy\n]/) { $cmd = "tar xvf $aft"; print "$cmd\n" if $opt_v; system ws($cmd); unlink $aft; } else { print "keeping $aft\n"; } } else { open $aft,$aft or die "$0: cannot open $aft = $!\n"; unlink $aft; print while read($aft,$_,65536); } } exit; } # upload else { if (@ARGV and $ARGV[0] =~ /^-(\d)/) { $id = sprintf("%0$1d",rand(10**$1)); shift @ARGV; } else { $id = sprintf("%06d",rand(1000000)); } $aft = "afex_$id.tar"; @fexsend = ws("fexsend $opt_v -K -k 1"); if (@ARGV) { print "@fexsend -a $aft @ARGV $u/anonymous\n" if $opt_v; system @fexsend,'-a',$aft,@ARGV,"$u/anonymous"; exit $? if $?; } elsif (not -t STDIN) { $aft = "/tmp/$aft"; open $aft,'>',$aft or die "$0: cannot write $aft - $!\n"; print {$aft} $_ while read(STDIN,$_,65536); close $aft; print "@fexsend $aft $u/anonymous\n" if $opt_v; $s = system @fexsend,$aft,"$u/anonymous"; unlink $aft; exit $s if $s; } else { die "say captain, say WHOT?!"; } print "For download use:\n"; print "$u//$aft\n" if -t STDIN; print "afex $id\n"; } exit; } &usage; sub guessserver { my $fexserver = ''; my $rc = '/etc/resolv.conf'; local $_; open $rc,$rc or die "$0: cannot open $rc - $!\n"; while (<$rc>) { if (/^\s*domain\s+([\w.-]+)/) { $fexserver = "http://fex.$1"; last; } if (/^\s*search\s+([\w.-]+)/) { $fexserver = "http://fex.$1"; } } close $rc; return $fexserver; } sub ws { local $_ = shift; return split; } sub usage { if ($0 eq 'afex') { print "file input usage: $0 files...\n"; print "file output usage: $0 ID [-]\n"; print "pipe input usage: ... | $0\n"; print "pipe output usage: $0 ID | ...\n"; print "delete usage: $0 -ID\n"; exit; } if ($0 eq 'asex') { print "file input usage: $0 files...\n"; print "file output usage: $0 ID [-]\n"; print "pipe input usage: ... | $0\n"; print "pipe output usage: $0 ID | ...\n"; exit; } die "program name must be a afex or asex, not $0\n"; } fex-20130805/bin/fexget0000755000174700017470000004273112177755050012702 0ustar fexfex#!/usr/bin/perl -w # CLI client for the FEX service for retrieving files # # see also: fexsend # # Author: Ulli Horlacher # # Copyright: Perl Artistic use 5.006; use strict qw'vars subs'; use Config; use POSIX; use Encode; use Getopt::Std; use Socket; use IO::Handle; use IO::Socket::INET; use Time::HiRes 'time'; use constant k => 2**10; use constant M => 2**20; eval 'use Net::INET6Glue::INET_is_INET6'; our $SH; our ($fexhome,$idf,$tmpdir,$windoof,$useragent); our $bs = 2**16; # blocksize for tcp-reading and writing file our $version = 20130805; our $CTYPE = 'ISO-8859-1'; our $fexsend = $ENV{FEXSEND} || 'fexsend'; # inquire default character set # cannot use "use I18N::Langinfo" because of no windows support! eval { local $^W = 0; require I18N::Langinfo; I18N::Langinfo->import(qw'langinfo CODESET'); $CTYPE = langinfo(CODESET()); }; $version = mtime($0) unless $version; if ($Config{osname} =~ /^mswin/i) { $windoof = $Config{osname}; $ENV{HOME} = $ENV{USERPROFILE}; $fexhome = $ENV{FEXHOME} || $ENV{HOME}.'/fex'; $tmpdir = $ENV{FEXTMP} || $ENV{TMP} || "$fexhome/tmp"; $idf = "$fexhome/id"; $useragent = sprintf("fexget-$version (%s %s)", $Config{osname},$Config{archname}); chdir $ENV{USERPROFILE}.'\Desktop'; # open XX,'>XXXXXX';close XX; } else { $0 =~ s:(.*)/:: and $ENV{PATH} .= ":$1"; $fexhome = $ENV{FEXHOME} || $ENV{HOME}.'/.fex'; $tmpdir = $ENV{FEXTMP} || "$fexhome/tmp"; $idf = "$fexhome/id"; $_ = `(lsb_release -d||uname -a)2>/dev/null`||''; chomp; s/^Description:\s+//; $useragent = "fexget-$version ($_)"; } $| = 1; my $usage = <) { push @ARGV,$1 if /^\s+(\d+)/; } close $ffl; } } else { unless (@ARGV) { if ($windoof) { my $url; for (;;) { print "download-URL: "; chomp($url = ); if ($url =~ /^http/) { @ARGV = ($url); last; } } } else { die $usage; } } } my ($file,%files,$download,$server,$port,$fop); if ($opt_f) { unless ($ENV{FEXID} or -f $ENV{HOME}.'/.fex/id') { die "$0: no local FEXID\n"; } $opt_f = pop(@ARGV); if ($opt_f =~ /^\d+$|^https?:/) { die "$0: $opt_f is not an e-mail address\n"; } } foreach my $url (@ARGV) { # do not overrun server sleep 1 if $fop; if ($url !~ /^http/) { unless (%files) { open $ffl,$ffl or die "$0: no $ffl, use first: $0 -l\n"; my $from = ''; while (<$ffl>) { if (/^from (.+) :$/) { $from = $1; } elsif (/^\s*(\d+)\)\s+\d+ MB.* (http\S+)/) { push @{$files{all}},$2; push @{$files{$from}},$2; } } close $ffl; } if ($url =~ /^(\d+)$/) { $url = ${files{all}}[$1-1] or die "$0: unknown file number\n"; } } if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/.*fop/\S+)}) { $server = $2; $port = $4 || ($1?443:80); $fop = $5; } else { die "$0: unknown F*EX URL $url\n"; } if ($proxy) { if ($port == 80) { $proxy_prefix = "http://$server" } elsif ($port == 443) { $proxy_prefix = "" } else { $proxy_prefix = "http://$server:$port" } } serverconnect($server,$port); if ($opt_f) { forward($url); next; } if ($opt_d) { my @r = del($url); $_ = shift @r; if (/^HTTP.* 200/) { ($file) = grep { $_ = $1 if /^X-File:\s+(.+)/ } @r; $file = $url unless $file; $file =~ s:.*/::; printf "%s deleted\n",urldecode($file); } else { s:HTTP/[\d\. ]+::; die "$0: server response: $_"; } next; } if ($opt_K) { my @r = keep($url); $_ = shift @r; if (/^HTTP.* 200/) { $file = $url; $file =~ s:.*/::; print "$file kept\n"; } else { s:HTTP/[\d\. ]+::; die "$0: server response: $_"; } next; } $download = download($server,$port,$fop); exit if $opt_s eq '-'; unlink $download unless -s $download; exit 2 unless -f $download; if ($windoof) { print "READY\n"; exit; } if (not $opt_X and $download =~ /\.gpg$/) { if (-t) { print "decrypt \"$download\"? "; $_ = ||'y'; unless (/^[y\n]/i) { print "keeping \"$download\"\n"; exit; } } if (system('gpg',$download) == 0) { unlink $download; $download =~ s/\.gpg$//; } } if (not $opt_X and $download =~ /$atype/) { if (-t) { print "Files in archive:\n"; if ($download =~ /\.tgz$/) { system qw'tar tvzf',$download; &cont; system qw'tar xvzf',$download; } elsif ($download =~ /\.tar$/) { system qw'tar tvf',$download; &cont; system qw'tar xvf',$download; } elsif ($download =~ /\.zip$/i) { system qw'unzip -l',$download; &cont; system qw'unzip',$download; } elsif ($download =~ /\.7z$/i) { system qw'7z l',$download; &cont; system qw'7z x',$download; } else { die "$0: unknown archive \"$download\"\n"; } } else { if ($download =~ /\.tgz$/) { system qw'tar xvzf',$download } elsif ($download =~ /\.tar$/) { system qw'tar xvf',$download } elsif ($download =~ /\.zip$/i) { system qw'unzip',$download } elsif ($download =~ /\.7z$/i) { system qw'7z x',$download } else { die "$0: unknown archive \"$download\"\n" } } if ($? == 0) { unlink $download; } else { die "$0: keeping \"$download\"\n"; } } } exit; sub cont { unless ($windoof) { print "extract these files (Y/n)? "; $_ = ||'y'; unless (/^[y\n]/i) { print "keeping \"$download\"\n"; exit; } } } sub del { my $url = shift; my ($server,$port); my $del; my @r; if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/fop/.+)}) { $server = $2; $port = $4 || ($1?443:80); $del = $5.'?DELETE'; } else { die "$0: unknown F*EX URL $url\n"; } sendheader("$server:$port","GET $del HTTP/1.1","User-Agent: $useragent"); while (<$SH>) { s/\r//; last if /^\n/; # ignore HTML output warn "<-- $_" if $opt_v; push @r,$_; } die "$0: no response from fex server $server\n" unless @r; return @r; } sub forward { my $url = shift; my ($server,$port); my ($uri,$dkey,$list,$cmd,$n); my @r; if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/fop/.+)}) { $server = $2; $port = $4 || ($1?443:80); $uri = $5; } else { die "$0: unknown F*EX URL $url\n"; } sendheader( "$server:$port", "GET $uri?COPY HTTP/1.1", "User-Agent: $useragent", ); $_ = <$SH>; die "$0: no reply from fex server $server\n" unless $_; warn "<-- $_" if $opt_v; unless (/^HTTP.*200/) { s/^HTTP.... \d+ //; die "$0: $_"; } while (<$SH>) { s/\r//; last if /^\n/; # ignore HTML output $dkey = $1 if /^Location:.*\/(\w+)\/.+/; warn "<-- $_" if $opt_v; } $cmd = 'fexsend -l >/dev/null 2>&1'; print "$cmd\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"; while (<$list>) { if (/^\s+(\d+)\) (\w+)/ and $2 eq $dkey) { $n = $1; $cmd = "fexsend -b $n $opt_f"; print "$cmd\n" if $opt_v; system $cmd; last; } } close $list; if ($n) { $cmd = "fexsend -d $n >/dev/null 2>&1"; print "$cmd\n" if $opt_v; system $cmd; } else { warn "$0: forwarding failed\n"; } } sub keep { my $url = shift; my ($server,$port); my $keep; my (@hh,@r); if ($url =~ m{^http(s?)://([\w\.\-]+)(:(\d+))?(/fop/.+)}) { $server = $2; $port = $4 || ($1?443:80); $keep = "$5?KEEP=$opt_K"; } else { die "$0: unknown F*EX URL $url\n"; } push @hh,"GET $keep HTTP/1.1", "Host: $server:$port", "User-Agent: $useragent", ""; foreach (@hh) { warn $_,"\n" if $opt_v; print $SH $_,"\r\n"; } while (<$SH>) { s/\r//; last if /^\n/; push @r,$_; } die "$0: no response from fex server $server\n" unless @r; grep { warn "\t$_" } @r if $opt_v; return @r; } sub download { my ($server,$port,$fop) = @_; my ($file,$download,$ssl,$pipe,$filesize); my (@hh,@r); my ($t0,$t1,$t2,$tt,$tm,$ts,$kBs,$b,$bt,$tb,$B,$buf); my $length = 0; my $seek = 0; my $tc = 0; local $_; local *X; if ($opt_s) { $file = $opt_s; if ($opt_s eq '-') { $pipe = $download = $opt_s; } elsif (-p $opt_s or -c $opt_s) { $download = $opt_s; } 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"); my $reply = $_ = <$SH>; unless (defined $_ and /\w/) { die "$0: no response from server\n"; } warn "<-- $_" if $opt_v; unless (/^HTTP\/[\d.]+ 200/) { s:HTTP/[\d. ]+::; die "$0: server response: $_"; } while (<$SH>) { s/\r//; warn "<-- $_" if $opt_v; last if /^\r?\n/; if (/^Content-Disposition: attachment; filename="(.+)"/i) { $file = locale(decode_utf8($1)); $file =~ s:.*/::; } } unless ($file) { $file = $fop; $file =~ s:.*/::; } $download = $file.'.tmp'; $seek = -s $download || 0; } push @hh,"GET $proxy_prefix$fop$opt_k HTTP/1.1", "User-Agent: $useragent", "Connection: close"; push @hh,"Range: bytes=$seek-" if $seek; # HTTPS needs a new connection for actually downloading the file serverconnect($server,$port) if $opt_P and $port == 443; sendheader("$server:$port",@hh); $_ = <$SH>; die "$0: no response from fex server $server\n" unless $_; s/\r//; if (/^HTTP\/[\d.]+ 2/) { warn "<-- $_" if $opt_v; while (<$SH>) { s/\r//; warn "<-- $_" if $opt_v; last if /^\r?\n/; if (/^Content-length:\s*(\d+)/i) { $length = $1; } elsif (/^X-Size: (\d+)/i) { $filesize = $1; } } } else { s/HTTP\/[\d.]+ \d+ //; die "$0: bad server reply: $_"; } if ($pipe) { *X = *STDOUT; } else { if ($opt_s and $opt_s eq $download) { open X,'>',$download or die "$0: cannot write to \"$download\" - $!\n"; } else { if (-e $file and not $opt_o) { die "$0: destination file \"$file\" does already exist\n"; } if ($seek) { open X,'>>',$download or die "$0: cannot write to \"$download\" - $!\n"; } else { open X,'>',$download or die "$0: cannot write to \"$download\" - $!\n"; } } } $t0 = $t1 = $t2 = int(time); $tb = $B = 0; printf STDERR "resuming at byte %s\n",$seek if $seek; print $rcamel[0] if ${'opt_+'}; while ($B < $length and $b = read $SH,$buf,$bs) { syswrite X,$buf; $B += $b; $tb += $b; $bt += $b; $t2 = time; if (${'opt_+'} and int($t2*10)>$tc) { print $rcamel[$tc%2+1]; $tc = int($t2*10); } if (int($t2) > $t1) { $kBs = int($bt/k/($t2-$t1)); $kBs = int($tb/k/($t2-$t0)) if $kBs < 10; $t1 = $t2; $bt = 0; # smaller block size is better on slow links $bs = 4096 if $bs>4096 and $tb/($t2-$t0)<65536; if ($tb<10*M) { printf STDERR "%s: %d kB (%d%%) %d kB/s \r", $download, int(($tb+$seek)/k), int(($tb+$seek)/($length+$seek)*100), $kBs; } else { printf STDERR "%s: %d MB (%d%%) %d kB/s \r", $download, int(($tb+$seek)/M), int(($tb+$seek)/($length+$seek)*100), $kBs; } } if ($opt_m) { if ($t2 == $t0 and $B > $opt_m*k) { print "\nsleeping...\r" if $opt_v; sleep 1; } else { while ($t2 > $t0 and $tb/k/($t2-$t0) > $opt_m) { print "\nsleeping...\r" if $opt_v; sleep 1; $t2 = time; } } } } close $SH; close X; print $rcamel[2] if ${'opt_+'}; $tt = $t2-$t0; $tm = int($tt/60); $ts = $tt-$tm*60; $kBs = int($tb/k/($tt||1)); if ($seek) { printf STDERR "$file: %d MB, last %d MB in %d s (%d kB/s) \n", int(($tb+$seek)/M),int($tb/M),$tt,$kBs; } else { printf STDERR "$file: %d MB in %d s (%d kB/s) \n", int($tb/M),$tt,$kBs; } if ($tb != $length) { if ($windoof) { exec "\"$0\" @ARGV"; exit; } else { die "$0: $server annouced $length bytes, but only $tb bytes has been read\n"; } } unless ($pipe or -p $download or -c $download) { my @s = stat $file if -e $file; rename $download,$file or die "$0: cannot rename \"$download\" to \"$file\" - $!\n"; chmod $s[2],$file if @s; } return $file; } sub list { my $cmd = "$fexsend -L"; $cmd .= " -i $opt_i" if $opt_i; if ($opt_v) { $cmd .= " -v"; warn "$cmd\n"; } open $cmd,"$cmd|" or die "$0: cannot run $cmd : $!\n"; open $ffl,'>',$ffl or die "$0: cannot open $ffl : $!\n"; my $n; while (<$cmd>) { if (/\d MB .*http/) { $n++; printf {$ffl} "%4d) %s",$n,$_; s:http[^\"]*/::; printf "%4d) %s",$n,$_; } else { print; print {$ffl} $_; } } } # set up tcp/ip connection sub tcpconnect { my ($server,$port) = @_; if ($port == 443) { eval "use IO::Socket::SSL"; $SH = IO::Socket::SSL->new( PeerAddr => $server, PeerPort => $port, Proto => 'tcp', ); } else { $SH = IO::Socket::INET->new( PeerAddr => $server, PeerPort => $port, Proto => 'tcp', ); } die "cannot connect $server:$port - $@\n" unless $SH; warn "TCPCONNECT to $server:$port\n" if $opt_v; } sub locale { my $string = shift; if ($CTYPE) { if ($CTYPE =~ /UTF-?8/i) { return $string; } elsif (grep { $CTYPE =~ /^$_$/i } Encode->encodings()) { return encode($CTYPE,$string); } else { return encode('ISO-8859-1',$string); } } return $string; } sub sendheader { my $sp = shift; my @head = @_; my $head; push @head,"Host: $sp"; foreach $head (@head) { warn "--> $head\n" if $opt_v; print {$SH} $head,"\r\n"; } warn "-->\n" if $opt_v; print {$SH} "\r\n"; } sub mtime { my @d = localtime((stat shift)[9]); return sprintf('%d%02d%02d',$d[5]+1900,$d[4]+1,$d[3]); } sub urldecode { local $_ = shift; s/\%([a-f\d]{2})/chr(hex($1))/ige; return $_; } sub serverconnect { my ($server,$port) = @_; my $connect = "CONNECT $server:$port HTTP/1.1"; local $_; if ($proxy) { tcpconnect(split(':',$proxy)); if ($port == 443) { printf "--> %s\n",$connect if $opt_v; nvtsend($connect,""); $_ = <$SH>; s/\r//; printf "<-- $_"if $opt_v; unless (/^HTTP.1.. 200/) { die "$0: proxy error : $_"; } eval "use IO::Socket::SSL"; die "$0: cannot load IO::Socket::SSL\n" if $@; $SH = IO::Socket::SSL->start_SSL($SH); } } else { tcpconnect($server,$port); } } my $sigpipe; sub nvtsend { local $SIG{PIPE} = sub { $sigpipe = "@_" }; $sigpipe = ''; die "$0: internal error: no active network handle\n" unless $SH; die "$0: remote host has closed the link\n" unless $SH->connected; foreach my $line (@_) { print {$SH} $line,"\r\n"; if ($sigpipe) { undef $SH; return 0; } } } fex-20130805/README0000644000174700017470000000243312177755047011603 0ustar fexfexF*EX (File EXchange) is a service to send big (large, huge, giant, ...) files from sender user A to recipient user B by HTTP. Sender and recipient user must have an e-mail-address and a web-browser, that is all (for them). The sender uploads the file to the F*EX-server and the recipient automatically gets a notification e-mail with a download-URL. The sender must have a valid auth-ID, given by the F*EX administrator. This F*EX distribution contains the F*EX server and the optional client programs fexsend, fexget, sexsend, sexget, xx and zz which run on UNIX. Simply run "./install", which installs all files into /home/fex/ Then edit /home/fex/lib/fex.ph and set your local config. Afterwards you can add F*EX users with /home/fex/bin/fac If you want to upgrade from a previous F*EX version, you also can run "./install" which is save, because it will not overwrite: /home/fex/lib/fex.ph /home/fex/lib/fup.pl /home/fex/lib/reactivation.txt /home/fex/htdocs/index.html but will create *_new versions of these files which you then can copy manually if you want. See directory doc for more information. If you have comments, suggestions, requests, etc, send me an e-mail: framstag@rus.uni-stuttgart.de Or fex some nice, funny, interesting videos (eg cute pets) to this address :-) fex-20130805/doc/0000755000174700017470000000000012177755050011460 5ustar fexfexfex-20130805/doc/reverse_proxy0000644000174700017470000000217111720717010014303 0ustar fexfexYou can prosecute F*EX behind a reverse proxy, but then you are limited to the capabilities of this proxy. For example, if you use apache, then you have a 2 GB upload limitation and a throughput penality. Example for apache reverse proxy: On http://tandem-fahren.de:80 there is an apache On http://tandem-fahren.de:488 there is a F*EX server tandem-fahren.de has ip address 78.46.33.142 If you want to contact the F*EX server via alias URL http://tandem-fahren.de/fex/ then you have to put in httpd.conf: Redirect /fex /fex/ ProxyRequests Off ProxyPass /fex/ http://tandem-fahren.de:488/ ProxyPassReverse http://tandem-fahren.de:488/ SetOutputFilter proxy-html ProxyHTMLExtended On ProxyHTMLURLMap http://tandem-fahren.de:488/ /fex/ ProxyHTMLURLMap / /fex/ ProxyHTMLURLMap /fex/fex/fex/ /fex/ And write to lib/fex.ph : $hostname = 'tandem-fahren.de'; $reverse_proxy_ip = '78.46.33.142'; $durl = 'http://tandem-fahren.de/fex/fop'; See also: http://8d.no/fexproxy.html fex-20130805/doc/debugging0000644000174700017470000000070411115711143013321 0ustar fexfexIf your F*EX installation does not work as expected then first look in: $FEXHOME/spool/fexsrv.log (log from fexsrv) $FEXHOME/spool/fup.log (log from fup CGI) $FEXHOME/spool/fop.log (log from fop CGI) If this does not help, set in $FEXHOME/lib/fex.ph : $debug = 1; then you will get in $FEXHOME/spool/.debug/ for each download a log file with detailed debugging output. If this does not help at all, contact me :-) framstag@rus.uni-stuttgart.de fex-20130805/doc/concept0000644000174700017470000006254312175407430013042 0ustar fexfexF*EX (Frams' Fast File EXchange) is a service to send big (large, huge, giant, ...) files from a user A to a user B, anywhere on the internet. The sender uploads the file to the F*EX-server and the recipient automatically gets a notification e-mail with a download-URL. Main features of F*EX * file transfer of virtually unlimited file size * recipient and sender only need an e-mail program and a web browser - of any kind, they do not have to install any software * RESEND and REGET for resuming after link failures at last sent byte * auto-notification of recipient * auto-deletion after download * auto-deletion after expiration date (default: 5 days) * full-users can create one time upload URLs for foreign users * full-users can create subusers, who can send only to this full-user * full-users can create groups, an analogy to mailing lists, but for files * self registration possible for internal and external users * maintenance-free: no admin interaction necessary * sending to multiple recipients needs storage on the server only once * quotas for sending and receiving * F*EX is a HTTP web-service and needs no firewall-tunnels * support for (personal or public) streams, too (SEX : Stream EXchange) * for real UNIX users, there are the shell programs fexsend and fexget to avoid annoying web browser usage and for full scripting support * adminstration by CLI or Web * about 10 times faster than apache * authentification modules for LDAP, RADIUS, POP, mailman * server based user address books * (reverse) proxy support * "public upload" similar to "anonymous ftp" possible * "anonymous upload" without registration for enabled IP addresses possible * localization for many languages * authentification by local user database, RADIUS, LDAP, mailman or POP * user and admin can throttle bandwith usage * admin can restrict access based on e-mail or IP addresses * server available for UNIX and Windows hosts * protocol and source-code free available The end user normally uses F*EX with his web browser and the URLs http://YOURFEXSERVER/fup (file upload) and http://YOURFEXSERVER/fop (file download). F*EX is not an anonymous service (exception: "public upload" and "anonymous upload", see later). The admin must register the user with his e-mail address and auth-ID string (low security password). This task can be done either with the CLI program "fac" (F*EX admin control) or http://YOURFEXSERVER/fac Alternativly the users can register theirselves with http://YOURFEXSERVER/fur (F*EX user registration), if the admin allows them to do so. This is done by setting the variables @local_domains and @local_hosts in FEXHOME/lib/fex.ph Example: @local_hosts = qw(127.0.0.1 10.10.100.0-10.10.255.255); @local_domains = qw(rus.uni-stuttgart.de flupp.org); In addition the administrator can allow external users to fex (only) to internal users. The F*EX functioning scheme is close related to e-mail where any external user can send e-mail to an internal user. This is also possible with F*EX. These users are then called "restricted users". The administrator has to define via configuration variable @local_rdomains the local recipient domains. For example: @local_rdomains = qw(YOURDOMAIN *.YOURDOMAIN OTHERDOMAIN); F*EX full users can create one time upload URLs with http://YOURFEXSERVER/fuc With such a URL a foreign user can send this F*EX full user a single file. F*EX full users can theirselves register "subusers" with http://YOURFEXSERVER/fuc Subusers can only fex to their full-user, not to any others, and they cannot create other subusers. F*EX full users also can create groups, an analogy to mailing lists, but for files: every member of a group can send files to the group address. The administrator can set with fac the CAPTIVE flag for a full user. Then he cannot change anymore his default settings (KEEP, AUTODELETE, etc) The F*EX user is the same as the "sender" in the fup CGI and the "from" parameter in the F*EX URL. The (confusing) naming scheme is historically based :-) The recipient (normally) does not need any registration. He authenticates himself with his unique download-URL which he gets in the notification e-mail. You do not need to build F*EX URLs manually, they are generated by the F*EX programs. A F*EX session is based on unique URL parameters or POST variables (FROM, TO, ID, etc). For security reasons the URL parameters FROM and ID become a MD5-hashed access key link (AKEY for regular users, SKEY for subusers, GKEY for groupusers), generated by the CGIs, to prevent that a third person could easily read these parameters from the user webbrowser URL address field. AKEY and SKEY are used as optional cookies, too, for extending the session life. A SKEY is made of md5_hex("$mainuser:$subuser:$subuserid") A GKEY is made of md5_hex("$mainuser:$groupname:$groupuser:$groupuserid") Note: the AKEY, SKEY and GKEY always can be stolen by a network sniffer! If you need true security, then you have to use https (SSL) instead of http! After download the file will be deleted after a grace time of 1 minute. This grace time allows a recipient to get the file again if he had problems in saving it. With the fexsend client the sender can change this behavior: option -D means "delay autodelete": do not delete the the file directly after download, but with the nightly fex_cleanup cronjob. More downloads are possible only from the same client (identified by cookie). option -K means "keep file": do not delete the file after download, but only after expiration date (normally 5 days). More downloads are possible only from the same client (identified by cookie). If you fex a file to yourself (sender = recipient), then the resulting download link is valid for any client and can be downloaded everywhere and more than once (until expiration date). If you want "delay autodelete" to be the default behaviour for all users and each transfer then set $autodelete = 'DELAY'; # or 'NO' for no autodelete in FEXHOME/lib/fex.ph In addition, you can add to the "Recipient(s)" field of the fup CGI: ":autodelete=delay" or ":autodelete=no" or ":keep=x" (where x is the number of days). Example: Recipient(s): framstag@rus.uni-stuttgart.de:keep=10 These options are also possible in the server address book (see CGI fuc). If you need more security, then set in fex.ph: $fop_auth = 1; $force_https = 1; With $fop_auth upload is restricted to registered users and download requires (HTTP) authorization. The credentials are the F*EX user e-mail and auth-ID. See extra documentation SSL for using https. "Public upload" is a feature similar to anonymous ftp: the sender does not to be registered, but may send only to predefined recipients via http://YOURFEXSERVER/pup The administrator has to define via configuration variable @public_recipients the e-mail addresses for which anyone can upload files without registration (auth-ID is not necessary). For example: @public_recipients = qw(fexmaster@YOURDOMAIN bunny@OTHERDOMAIN); With "anonymous upload" one can use F*EX without registration or authentication. The administrator has to define via configuration variable @anonymous_upload for which IP addresses this feature is available. The administrator can globally forbid certain recipient address via fex.ph configuration (example): @forbidden_recipients = qw(nobody@* *@microsoft.com); The administrator can also forbid a user to fex to any recipient address, but the allowed ones with: fac -r USER By standard installation the base directory FEXHOME is the same as the login HOME of user fex, but you can move it if you want. FEXHOME is determined by the full path of fexsrv as configured in /etc/xinetd.d/fex . Change this when you move FEXHOME! You can also add (name based) virtual hosts with fac. Do not give write permission to any other user to any file in FEXHOME or below! FEXHOME contains: spool/ spool directory and user data htdocs/ directory for generic download files bin/ directory for programs cgi-bin/ directory for CGI programs lib/ directory for library and config files doc/ additional documentation locale/ alternative language installation Files in spool: cleanup.log log of daily cleanup cronjob dkey.log log of download keys dop.log log of HTTP document output error.log log of errors fexsrv.log log of all HTTP requests fop.log log of file downloads fup.log log of file uploads fur.log log of user self registrations sex.log log of stream exchanges $from/@ regular user auth-ID $from/@SUBUSER subuser addresses and IDs $from/@ALLOWED_RECIPIENTS recipients restrictions for this user $from/@ADDRESS_BOOK users recipient address book $from/@GROUP directory of F*EX user groups $from/@OKEY directory with one time upload keys $from/@QUOTA sender and recipient quotas $from/@AUTODELETE autodelete default $from/@KEEP keep default $from/@LOCALE locale default $user/@CAPTIVE user must not change his settings $to/$from/$file/upload file data in upload progress $to/$from/$file/filename original file name $to/$from/$file/size original file size $to/$from/$file/data file data after complete upload $to/$from/$file/keep keep time (autoexpire) in days $to/$from/$file/autodelete autodelete option: YES NO or DELAY $to/$from/$file/comment comment in notification e-mail $to/$from/$file/notify notify flag $to/$from/$file/error error message if file has gone $to/$from/$file/download log of successful downloads $to/$from/$file/restrictions IP based download restrictions $to/$from/$file/dkey download key $to/$from/$file/locale locale As you see, the first directory sometimes means sender and sometimes means recipient! It depends on the case of usage (up/download). A registered full F*EX user is identified by the file $spooldir/$from/@ Only if this file contains his auth-ID this user is able to send files to others. Otherwise he is just an unpriviledged recipient. You can customize the upload CGI fup by editing FEXHOME/lib/fup.pl Additional directories in spool: .dkeys/ download keys lookup directory .ukeys/ upload keys lookup directory .akeys/ authentication keys lookup directory .skeys/ subuser keys lookup directory .gkeys/ groupuser keys lookup directory .xkeys/ extra download keys lookup directory .debug/ directory for debug output (optional) .reg/ temporary data for user selfregistration The upload keys (UKEY) are necessary to synchronize the file upload by HTTP POST with the javascript upload status bar which is an asynchronous HTTP GET. The GET process needs to know the corresponding POST process. This is done via UKEY, a unique upload identifier. The download key (DKEY) is a unique identifier for - guess what - downloading. It also prevents an attacker to get the file, because only the recipient knows the DKEY as part of the download URL from the notification e-mail. XKEY is an optional extra download key to have a short download URL in shape http://YOURFEXSERVER//XKEY The XKEY always starts with // and is provided as a COMMENT by the client. Example: fexsend schwuppdiwupp.jpg // The user has to realize that such URLs have very low security. If you need to trace a F*EX request, then set $debug = 1; in fex.ph and look in ~/spool/.debug/ for the correspondening files. The user fex also gets a Bcc of all sent notification e-mails. This is a help for debugging purposes. If you want these Bcc mails to another address then set in fex.ph: $bcc = 'other@address'; The sender also get a Bcc if he put the string "!bcc!" in the comment field. If you have users within another domain with its own MTA and those users want to fex each other, then their MTA probably will reject the notification e-mail. To prevent this problem you can set in fex.ph @remote_domains = qw(other_domain1 other_domain2 ...); In this case "From: $admin" will be used in the notification e-mails. F*EX comes with its own web server: fexsrv Standard web servers like apache have been proven problematic, either in speed or because of a 2-GB-limit. It is not possible to use the F*EX CGIs with an alternative web server, because the F*EX CGIs need special fexsrv features. xinetd starts fexsrv for every new connection, which then executes the CGIs fup (file upload), fop (file output), fuc (fex user control), foc (fex operation control), fac (fex admin control), fur (fex user registration) and sex (stream exchange). SEX has the opposite authorization model of FEX: The sender does not need any registration. He can send a stream to any registered SEX user, who must identify himself with his auth-ID. This is because a stream does not cost resources when it is not bound to a recipient. It will block otherwise. The client programs for sexing are sexsend and sexget. You can call them also fuckyou and fuckme :-) With the F*EX client fexsend you can have a streaming file transfer with spooling: on client side there is no temporary buffer file (archive), but the data is sent directly to the F*EX server. This saves time and disk space on the client. Example for a streaming archive upload: fexsend -a music+video.tar *mp3 *avi webmaster@flupp.org Example for a streaming data upload: fpg fex /var/log/* | fexsend -s logs fexmaster@flupp.org The data streaming is implemented via a HTTP extension: the header Content-Length is given -1 which means: unknown length, read until EOF. For streaming receiving you can use "fexget -s-" or "wget -O-". fexsrv also can do generic document output (via dop) like a normal web server. For this, your files must be under FEXHOME/htdocs and they must not have the same name as the CGIs under FEXHOME/cgi-bin, because the CGIs have priority. For security reasons, documents to be delivered by dop: - the file must be readable by group or world - the file must be in FEXHOME/htdocs or a directory specified by @doc_dirs - the filename must not start with a "." - the filename must not contain a "@" - the filename must not end with "~" To restrict the access to specific client IP addresses, put these IPs into a file named .htaccessfrom which will protect all files below this directory. You can name single IPs, also as IP ranges (example: 129.69.0.0-129.69.255.255) dop is not a regular CGI program (like fup or fop), but a sub-program of fexsrv. *.html files may contain $VARIABLES$ which will be substituted with the value of the corresponding environment variable. See example $SERVER_ADMIN$ in FEXHOME/htdocs/index.html *.html files may contain <> (even multiline) which will be evaluated. See example FEXHOME/htdocs/dynamic.html This perl-code must not contain '>>' strings itself! Pay attention: do not place security relevant data inside << >> because it will be delivered to the client if the URL ends with '!'! See example: http://fex.rus.uni-stuttgart.de/index.html http://fex.rus.uni-stuttgart.de/index.html! If you want to hide your code, then you have to write a CGI script and place it into the cgi-bin directory. Files there will never be delivered by dop. You also can do "chmod o-r file.html" to prevent source code delivery. *.html files may contain conditional blocks: #if (perl-expression) HTML... #elseif (perl-expression) HTML... #else HTML... #endif which will be evaluated at run-time (#else and #elseif are optional). *.html files may contain: #include "FILE" which means: load FILE from current directory at this place in code. dop also can display a directory listing if this directory contains a file named .htindex To restrict the listing to specific files, put a matching regular expression into .htindex Example: echo 'pdf$' > /home/fex/htdocs/doc/.htindex dop can output tar, tgz or zip archives on-the-fly as a streaming document. Just create a symbolic link with files (or directories) you want in this archive and enclose them with ":". The symlink name mus end with ".stream". Example: http://fex.rus.uni-stuttgart.de:8080/download/sex.tar fex@fex:~/htdocs/download: ls -l sex* lrwxrwxrwx 1 fex fex 7 2011-01-26 11:46 sexget -> sexsend -rwxr-xr-x 1 fex fex 12110 2012-08-22 09:55 sexsend lrwxrwxrwx 1 fex fex 22 2012-09-01 12:13 sex.stream -> :sexsend:sexget:sexxx: lrwxrwxrwx 1 fex fex 7 2012-09-01 11:28 sexxx -> sexsend It is also possible to create this stream file as a regular file. Then the content must be the file names you want in the streaming archive. Note: you may only use relative paths and without "../" elements. cronjob fex_cleanup is run once a day and deletes expired uploads and does some other spool houskeeping. See: crontab -l To detect inactive users you can put in fex.ph: $account_expire = "365:notify"; This sends an e-mail to $admin when an user is inactive for 365 days. Or to delete inactive users you can put in fex.ph: $account_expire = "365:delete"; This deletes user accounts automatically which have been inactive for 365 days. Of course you can use any number of days. The address book may contain the optional parameters autodelete and keep. Address book example entry: flupp framstag@flupp.org keep=99 autodelete=no BUT: these address book parameters are only accepted when using the fexsend or schwuppdiwupp client! They will be ignored when using a webbrowser! Nevertheless you may add autodelete and keep parameters using a webbrowser, but then they are valid for ALL addresses in the "Recipient" field! The clients fexsend and schwuppdiwupp can MD5-encrypt the auth-ID together with a session-ID. The session-ID itself is provided by the server after an initial "GET SID" HTTP request. This is not possible through a proxy, because most proxies do not support persistant tcp sessions. See fex-client_2.pdf for the F*EX protocol specification. To understand and trace the F*EX protocol you can use fexsend with the -v option. Example (--> means send to server, <-- means receive from server): framstag@fex:~: fexsend -v X.png framstag@flupp.org ID data from /home/framstag/.fex/id: http://fex.rus.uni-stuttgart.de framstag@rus.uni-stuttgart.de XXXX Server/User: http://fex.rus.uni-stuttgart.de/framstag@rus.uni-stuttgart.de TCPCONNECT to fex.rus.uni-stuttgart.de --> GET SID HTTP/1.1 --> <-- HTTP/1.1 201 8p2Y2qa2 <-- X-Features: SID,CHECKRECIPIENT,GROUPS,QUOTA,FILEID,MULTIPOST,XKEY <-- X-SID: 8p2Y2qa2 <-- X-Timeout: 30 <-- Content-Length: 0 <-- --> HEAD /fop/framstag@flupp.org/framstag@fex.rus.uni-stuttgart.de/X.png??ID=MD5H:226e896d0adab86892957aa8158b37ba HTTP/1.1 --> <-- HTTP/1.1 200 OK <-- Content-Length: 0 <-- X-Size: 0 <-- X-Features: SID,CHECKRECIPIENT,GROUPS,QUOTA,FILEID,MULTIPOST,XKEY <-- --> POST /fup HTTP/1.1 --> Host: fex.rus.uni-stuttgart.de --> User-Agent: fexsend (Ubuntu 8.04.4 LTS) --> Content-Length: 149935162 --> Content-Type: multipart/form-data; boundary=JhUOtQ3sgV5ZcHJzrTny523nBFqgUNvSAOUHoRMTdZfGpAjs --> --> --JhUOtQ3sgV5ZcHJzrTny523nBFqgUNvSAOUHoRMTdZfGpAjs --> Content-Disposition: form-data; name="FROM" --> --> framstag@fex.rus.uni-stuttgart.de --> --JhUOtQ3sgV5ZcHJzrTny523nBFqgUNvSAOUHoRMTdZfGpAjs --> Content-Disposition: form-data; name="TO" --> --> framstag@flupp.org --> --JhUOtQ3sgV5ZcHJzrTny523nBFqgUNvSAOUHoRMTdZfGpAjs --> Content-Disposition: form-data; name="ID" --> --> MD5H:226e896d0adab86892957aa8158b37ba --> --JhUOtQ3sgV5ZcHJzrTny523nBFqgUNvSAOUHoRMTdZfGpAjs --> Content-Disposition: form-data; name="FILESIZE" --> --> 149934400 --> --JhUOtQ3sgV5ZcHJzrTny523nBFqgUNvSAOUHoRMTdZfGpAjs --> Content-Disposition: form-data; name="FILE"; filename="X.png" --> Content-Type: application/octet-stream --> Content-Length: 149934400 --> X-File-ID: 1283077463 --> --> (file content) --> --JhUOtQ3sgV5ZcHJzrTny523nBFqgUNvSAOUHoRMTdZfGpAjs-- <-- Location: http://fex.rus.uni-stuttgart.de/fop/CoVhikzk/X.png <-- X-Recipient: framstag@flupp.org (autodelete=YES,keep=5) <-- Comment on the HEAD request above: The client fexsend sends it to request whether the file has been sent before and if it was successful or not. On the later case, the server would reply how many bytes has already been received and the client then can send only the missing part. Normally the answer to the HEAD request is 0 (see above), which means: nothing of this file has been received so far. But this is only half of the truth :-) I have omitted in the example above the requests CHECKRECIPIENT and GET ADDRESS_BOOK, to keep it simple in the first run. CHECKRECIPIENT is a HTTP POST request to check whether the recpient's e-mail address is valid to the server. GET ADDRESS_BOOK is a HTTP GET request to check if the recipient with a short address (= address without @) is an alias in the senders server address book. Please use "fexsend -v" by yourself to see the whole protocol dialoge. Many HTTP proxies have a POST limit, which is often at 2 GB, but sometimes lower. To overcome this limitation a F*EX client (like fexsend) may include in the POST the HTTP MIME part "filesize" which indicates the full file size. All incoming file POSTs with this file name will be appended until the full file size is reached. Of course the client has to POST all parts of this file, in the correct order, in asking the server how many bytes has already been received. Example: framstag@fex:/tmp: fexsend -vP wwwproxy.uni-stuttgart.de.de:8080:1024 2GB.tmp . ID data from /home/framstag/.fex/id: http://fex.rus.uni-stuttgart.de:8080 framstag@rus.uni-stuttgart.de xxxxxx Server/User: http://fex.rus.uni-stuttgart.de:8080/framstag@rus.uni-stuttgart.de TCPCONNECT to wwwproxy.uni-stuttgart.de.de:8080 --> HEAD http://fex.rus.uni-stuttgart.de:8080/fop/framstag@rus.uni-stuttgart.de/framstag@rus.uni-stuttgart.de/2GB.tmp??&ID=xxxxxx HTTP/1.1 --> <-- HTTP/1.1 200 OK <-- X-Size: 0 <-- Content-Length: 0 <-- Proxy-Connection: Keep-Alive <-- Connection: Keep-Alive <-- Date: Tue, 08 Jun 2010 15:04:13 GMT <-- TCPCONNECT to wwwproxy.uni-stuttgart.de.de:8080 --> POST http://fex.rus.uni-stuttgart.de:8080/fup HTTP/1.1 --> Host: fex.rus.uni-stuttgart.de:8080 --> User-Agent: fexsend (Ubuntu 8.04.4 LTS) --> Content-Length: 1073677143 --> Content-Type: multipart/form-data; boundary=gqhqeU7FCHMl4ohxJ5knK1y9rF75xYTvabPvZTeWnAhaoDsK --> --> --gqhqeU7FCHMl4ohxJ5knK1y9rF75xYTvabPvZTeWnAhaoDsK --> Content-Disposition: form-data; name="FROM" --> --> framstag@rus.uni-stuttgart.de --> --gqhqeU7FCHMl4ohxJ5knK1y9rF75xYTvabPvZTeWnAhaoDsK --> Content-Disposition: form-data; name="TO" --> --> framstag@rus.uni-stuttgart.de --> --gqhqeU7FCHMl4ohxJ5knK1y9rF75xYTvabPvZTeWnAhaoDsK --> Content-Disposition: form-data; name="ID" --> --> xxxxxx --> --gqhqeU7FCHMl4ohxJ5knK1y9rF75xYTvabPvZTeWnAhaoDsK --> Content-Disposition: form-data; name="COMMENT" --> --> NOMAIL --> --gqhqeU7FCHMl4ohxJ5knK1y9rF75xYTvabPvZTeWnAhaoDsK --> Content-Disposition: form-data; name="FILESIZE" --> --> 2147483748 --> --gqhqeU7FCHMl4ohxJ5knK1y9rF75xYTvabPvZTeWnAhaoDsK --> Content-Disposition: form-data; name="FILE"; filename="2GB.tmp" --> Content-Type: application/octet-stream --> Content-Length: 1073676288 --> X-File-ID: 1275549886 --> --> (file content) --> --gqhqeU7FCHMl4ohxJ5knK1y9rF75xYTvabPvZTeWnAhaoDsK-- 2GB.tmp : 1023 MB in 73 s (14363 kB/s), chunk #1 : 1023 MB <-- HTTP/1.1 206 Partial OK <-- X-Message: Partial OK <-- Server: fexsrv <-- Expires: 0 <-- Cache-Control: no-cache <-- Content-Type: text/html; charset=UTF-8 <-- Connection: close <-- Date: Tue, 08 Jun 2010 15:05:29 GMT <-- TCPCONNECT to wwwproxy.uni-stuttgart.de.de:8080 --> HEAD http://fex.rus.uni-stuttgart.de:8080/fop/framstag@rus.uni-stuttgart.de/framstag@rus.uni-stuttgart.de/2GB.tmp??&ID=xxxxxx HTTP/1.1 --> <-- HTTP/1.1 200 OK <-- X-Size: 2147483748 <-- X-File-ID: 1275549886 <-- Content-Length: 1073676288 <-- Proxy-Connection: Keep-Alive <-- Connection: Keep-Alive <-- Date: Tue, 08 Jun 2010 15:05:29 GMT <-- TCPCONNECT to wwwproxy.uni-stuttgart.de.de:8080 --> POST http://fex.rus.uni-stuttgart.de:8080/fup HTTP/1.1 --> Host: fex.rus.uni-stuttgart.de:8080 --> User-Agent: fexsend (Ubuntu 8.04.4 LTS) --> Content-Length: 1073677254 --> Content-Type: multipart/form-data; boundary=LofreCkx1GmgWNCHZ9exBQoQhiEF7pXSaPp2KUQVPlnarPAw --> --> --LofreCkx1GmgWNCHZ9exBQoQhiEF7pXSaPp2KUQVPlnarPAw --> Content-Disposition: form-data; name="FROM" --> --> framstag@rus.uni-stuttgart.de --> --LofreCkx1GmgWNCHZ9exBQoQhiEF7pXSaPp2KUQVPlnarPAw --> Content-Disposition: form-data; name="TO" --> --> framstag@rus.uni-stuttgart.de --> --LofreCkx1GmgWNCHZ9exBQoQhiEF7pXSaPp2KUQVPlnarPAw --> Content-Disposition: form-data; name="ID" --> --> xxxxxx --> --LofreCkx1GmgWNCHZ9exBQoQhiEF7pXSaPp2KUQVPlnarPAw --> Content-Disposition: form-data; name="COMMENT" --> --> NOMAIL --> --LofreCkx1GmgWNCHZ9exBQoQhiEF7pXSaPp2KUQVPlnarPAw --> Content-Disposition: form-data; name="SEEK" --> --> 1073676288 --> --LofreCkx1GmgWNCHZ9exBQoQhiEF7pXSaPp2KUQVPlnarPAw --> Content-Disposition: form-data; name="FILESIZE" --> --> 2147483748 --> --LofreCkx1GmgWNCHZ9exBQoQhiEF7pXSaPp2KUQVPlnarPAw --> Content-Disposition: form-data; name="FILE"; filename="2GB.tmp" --> Content-Type: application/octet-stream --> Content-Length: 1073676288 --> X-File-ID: 1275549886 --> --> (file content) --> --LofreCkx1GmgWNCHZ9exBQoQhiEF7pXSaPp2KUQVPlnarPAw-- 2GB.tmp : 0 MB in 1 s (128 kB/s), total 2048 MB The default character set for F*EX is UTF-8, because most clients seem to use it. The problem is, it is nowhere defined which character set HTTP uses itself. Important for programmers: The perl variables of the F*EX CGI's (fup, fop, etc) have their UTF-8 flag turned off. This means, they contain UTF-8 data in binary representation. I have additional authentication modules for RADIUS, LDAP, mailman and POP. Please e-mail me if you are interested. framstag@rus.uni-stuttgart.de fex-20130805/doc/xx0000664000174700017470000000552311461232571012042 0ustar fexfexWith xx you have a network wide shell based clip board for files and STDIN/STDOUT: easy data exchange between different accounts on different hosts. usage: send file(s): xx file... or: send STDIN: xx - or: send pipe: ... | xx or: get file(s) or STDIN: xx or: get file(s) quickly: xx -- Pipe example: framstag@tandem:~: uname -a | xx /home/framstag/.fex/tmp/STDFEX : 0 kB in 1 s (0 kB/s) framstag@fex:~: xx transfered: 0 MB (100%) Linux tandem 2.6.24-28-server #1 SMP Wed Aug 18 22:01:20 UTC 2010 i686 GNU/Linux File transfer example: framstag@tandem:~: xx /boot/ making tar transfer file /home/framstag/.fex/tmp/STDFEX : /boot/ /boot/initrd.img-2.6.24-27-generic /boot/vmlinuz-2.6.24-28-generic (...) /boot/System.map-2.6.24-27-generic /home/framstag/.fex/tmp/STDFEX : 34 MB in 2 s (17605 kB/s) framstag@fex:/tmp: xx transfered: 34 MB (100%) Files in transfer-container: drwxr-xr-x root/root 0 2010-10-20 07:37 boot/ -rw-r--r-- root/root 7905085 2010-05-25 15:38 boot/initrd.img-2.6.24-27-generic -rw-r--r-- root/root 1927544 2010-10-16 20:38 boot/vmlinuz-2.6.24-28-generic (...) -rw-r--r-- root/root 906803 2010-03-24 14:33 boot/System.map-2.6.24-27-generic Extract these files? One problem are shared system accounts like root where different persons use them: xx (like fexsend and fexget) uses $HOME/.fex/id which contains personal data. But you can put the ID authorization in the environment variable FEXID. fexsend on your local account gives you a string for "cut and paste", example: framstag@moep:~: fexsend -I export FEXID='fex.rus.uni-stuttgart.de:8080 framstag jmBhf9ht' history -d $(history 1);history -d $(history 1) You then copy these two lines with your mouse into the root account: root@tandem:~# export FEXID'=fex.rus.uni-stuttgart.de:8080 framstag jmBhf9ht' root@tandem:~# history -d $(history 1);history -d $(history 1) (The second line deletes these two lines from the bash history) Now you can use xx (or fexsend and fexget) as normal. Example: root@tandem:~# grep sshd /var/log/daemon | xx transfered: 265 kB in 1 s (265 kB/s) framstag@moep:~: xx | wc -l 434279 After logging out from root@tandem the F*EX authorization data has gone. Internal details: The intermediate transfer file container is $HOME/.fex/tmp/STDFEX When transfering files tar/gzip format is used, whereas STDIN (pipe) will be transfered uncompressed. Tip: If you want to transfer files uncompress, then use: tar cvf - your files... | xx With default usage only one "storage slot" is available: STDFEX But you can use as many "storage slots" as you want by using "xx :TAG" Examples: uname -a | xx grep sshd /var/log/daemon | xx :log xx :log | grep obertux xx :config /boot /etc /root xx :config -- fex-20130805/doc/Changes0000644000174700017470000011723712175052445012762 0ustar fexfex2013-07-28 dop: added .htaccessfrom support 2013-07-27 fex.ph,dop: security enhancement: static documents must be in @doc_dirs dop: documents with leading . are not allowed 2013-07-25 fexsend: added option -= to upload a file with another name 2013-07-21 fixed bug environment variables are cut at newline 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-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-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-26 fop: allow multiple downloads from same ip fup,fac: extended "fex yourself" support 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 fex.rus.uni-stuttgart.de for new release and sends mail 2013-06-12 fac(CGI): fixed bug wrong spooldir for virtual server 2013-06-11 fex.ph: new config variable $usage_conditions for registrations mails fop: fixed bug fexmail download possible only once 2013-06-10 fac: added option -D to disable a user (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 e-mails 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 e-mail header added support for $max_fail_handler() 2013-05-18 fac: fixed bug option -rd does not work 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 @anonymous_upload list 2013-05-07 fup: fixed bug multiple Location HTTP headers generate an error with some web browsers 2013-05-03 added support for axel download accelerator (multiple HTTP Range) 2013-05-02 add X-FEX-File-ID header to notification e-mails 2013-04-23 dop: fixed bug HTTP 301 redirection timeout on symlinks 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-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-11 fur: fixed bug insecure dependency with exuser 2013-01-31 receiving of reminder e-mails is user configurable 2013-01-24 fup: decode UTF8 comment 2013-01-07 added X-Frame-Options header to prevent clickjacking 2012-12-26 fup,fexsend: added replyto option 2012-12-21 dop: download manager prevention: no concurrent downloads from same client with HTTP Range 2012-12-17 fop: fixed bug ip based download restriction 2012-12-16 added name based virtual host server 2012-12-15 fexsrv: HTTP error logging to error.log 2012-12-07 fex.ph: added optional config variable @durl 2012-12-04 new feature forward a file from incoming spool 2012-11-21 fac: show more user information 2012-11-20 added CAPTIVE user mode 2012-11-19 fup: with comment NOSTORE file will not be stored ==> benchmarking 2012-11-14 fexsend: fixed bug gkey and skey URL recipients not working 2012-11-12 fexsend: 7z archives without compression 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-05 added HTTP Strict Transport Security if $force_https is enabled 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-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-18 fexsend: added options -. and -n fup: added shortmail option in comment 2012-09-17 added mailmode configuration option in fex.ph 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 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 downloads 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-01 fexsend: optional argument '@' as files/recipients separator fexsend: fixed bug notification e-mail 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) 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-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-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-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 2011-12-31 fex_cleanup: fixed bug notification e-mails not localized 2011-12-30 fup: additional dkey.log 2011-12-05 fup: respect @throttle config for all clients 2011-11-29 dop: delivers text files (scripts!) without x-bit as "text/plain" 2011-11-15 fup: fixed bug with $autodelete = $NUMBER; 2011-11-08 fac: added option -S statistics 2011-11-02 fup: show remaining keep time in files listing 2011-10-28 fup: fixed bug uninitialized value when using copy-forward 2011-10-13 fup: FILESIZE hack for firefox 7 to support uploads > 4 GB 2011-10-05 fup: fixed bug wrong sender quota calculation 2011-10-03 fex.ph: added configuration variables @upload_hosts @download_hosts 2011-09-30 fexsend: added option -g for sending encrypted files 2011-09-21 fexsrv: use $default_locale if client sends illegal locale cookie 2011-09-20 fex.ph: added optional config variable $boring for unhumorous mode 2011-09-19 fur: $USER/.auto contains additional info about account creation 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-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 non-GNU 2011-08-26 added one time upload OKEY 2011-08-13 fex_cleanup: fixed bug comment missing in reminder e-mail 2011-08-11 dop: #if ... #else ... #elseif ... #endif inside HTML documents dop: 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-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-07 fup: subusers and groupusers can also select a locale fup: if user selects a locale login, save it as default locale (does not affect fexsend and schwuppdiwupp) notification e-mails come in default locale 2011-08-03 fexsend: fixed bug uninitialized value when using chunked mode fexsend: added undocumented option -F female mode 2011-07-31 fexsend: added option -s streaming data 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-27 fup: if comment contains "!bcc!" then sender will get a bcc of notification e-mail 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 e-mail 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-16 added doc/reverse_proxy 2011-07-14 added optional czech localization 2011-07-01 FAQ.html reformated 2011-06-30 translate install job 20 times faster 2011-06-27 added robots.txt to disallow web robots indexing 2011-06-22 fup: disable HTML code in file listing (filename & comment) 2011-06-21 added optional italian localization 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-15 fup: fixed bug always keep_default days in notification e-mail 2011-06-14 fexsend: transparent proxy detection (and support) fixed bug $docdir ignored 2011-06-10 fex.ph: new config variable $bcc for notification e-mails 2011-06-09 set Reply-To in all notification e-mails 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-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-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 ==> 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-04-27 fexsend: fixed bug archiv.zip not working on Windows 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 2011-04-01 fexsend: continue without SID if SID is not available 2011-03-26 fexsrv: deactivate header_hook (inquisition) if request is a regular fop request 2011-03-18 fexsend: base64 support for $FEXID and $FEXXX 2011-03-09 fexget,fexsend: fixed bug no file listing for https 2011-03-04 removed "use Switch" because of warnings with perl 5.12 2011-02-28 sexsend: added option -g show transfer rate 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 e-mails 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 e-mail 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 e-mail 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-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-25 fuc: fixed bug cannot delete all subusers schwuppdiwupp: fixed bug 7-zip not found 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 e-mails 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-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-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-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-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-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 2010-10-12 fup: fixed bug wrong interpretation of SKEY parameter+cookie 2010-10-05 fexend,fup: support of http reverse proxy 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-12 fexsend,fop: fixed bug resuming upload does not work with alias 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-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-15 fex.ph: optional fix address $sender_from (instead of F*EX user) in notification e-mail From 2010-08-14 added optional spanish localization 2010-08-12 fup: speedup 90% fop: speedup 20% 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-08 sex: support for compressed streams sex,sexsend: removed unneccesary text mode (option -t) sex,sexsend: speedup factor 5 added sexxx 2010-08-06 sex: fixed various bugs in client and server 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-16 added cookie support (for AKEY and SKEY) 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 2010-07-03 fex.ph,fex.pp: new config variable @remote_domains 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-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-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-11 schwuppdiwupp: (chunked) multi-POST for proxy with 4 GB limit 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 reliable resume function 2010-06-02 schwuppdiwupp: added proxy support 2010-05-31 fexsend: fixed bug windows path elements in filename 2010-05-30 better server proxy support: AKEY and SKEY no longer rely on client ip 2010-05-29 fexsend: added proxy support 2010-05-28 fur: allow registration confirmation more than once 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-17 fexsend: added option -H for hints 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-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-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-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-20 fexsrv,fexsend: HTTP header X-Timeout (info server->client) 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 e-mail 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 "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-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-16 fup,fuc: fixed bug mixed case in F*EX group names and addresses 2010-03-14 fex.pp: do not send notification e-mails on empty files 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-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-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) 2009-12-09 FIX.jar: can send more than one file (in zip archive) 2009-12-04 fex_cleanup: fixed bug send unnecessary reminder on AUTODELETE=NO 2009-11-26 fexsend,fexget,fup: added -z option for logfile inquiry 2009-11-13 fup,fuc: keep and autodelete options in server address book 2009-11-12 fexsrv: support for HTTP/1.0 persistant connections (for proxys) PID:SID in fexsrv.log CONNECT string (debugging help) 2009-11-06 added error.log 2009-11-03 fex_cleanup: also cleanup $SPOOL/.reg directory 2009-10-23 fup: added X-FEX-Filesize header in notification e-mail 2009-10-18 fup: also test if $FROM is a valid e-mail address 2009-10-11 fex_cleanup: fixed bug no cleanup at all on AUTODELETE=NO 2009-09-25 fex.pp: added X-Mailer in sent mails to please stupid spamfilter at hotmail or gmail 2009-09-02 fur,fex.pp: fixed bug not removing quote chars in qqq strings 2009-08-28 rup: fixed bug UTF-8 file names 2009-08-25 FIX.jar: accepts parameters TO, AKEY and SKEY (for subusers) 2009-08-24 fex_cleanup: fixed bug warning unitialized variable 2009-08-17 fex_cleanup: fixed bug typo mitime --> mtime 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-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-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-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-06 fup: substitute all control characters in file name and comment with "_" 2009-07-02 better install script, guesses IP 2009-06-29 changed spool directory layout $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-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 2009-06-10 default timeout 10 s --> 30 s 2009-06-01 fexsend: show transfer status on STDERR (also for xx) 2009-05-31 fexsend,fexget: show transfer rate (kB/s) 2009-05-29 fexsend: auto-reconnect after SIGPIPE (link failure, etc) 2009-05-26 fexsrv: ignore HTML anchors in GET requests (from stupid msnbot) 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-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-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) 2009-02-27 fuc: send information e-mails to sub-users by click-on-address 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-17 fup,fuc: better linking 2009-02-14 fup: first send notification e-mails, then send HTTP 200 OK to client 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-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) ==> 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 2009-02-09 fexsrv: fixed bug wrong log sequence in debug files 2009-02-04 fup: fixed bug cannot delete files by web interface 2009-02-03 fexsrv: fixed bug wrong download URL by HTTP_HOST from client request 2009-01-31 fexsrv: fixed bug handling of missing trailing / in doc requests 2009-01-30 rup: fixed bug wrong download URL in notification e-mail 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-21 fuc: URL for subusers with KEY parameter 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-13 fup,fop: support for MIME-file types 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 process 2008-12-23 sexsend,sexget: added HTTPS/SSL support 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-12 fexget: better responsiveness on slow links (modem, ISDN) 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 e-mail 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-11-28 fexserv: added special FlashGet (download sucker) brake 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-26 fop: with URL parameter ?KEEP file can be downloaded more than once 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-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 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-19 use md5-hash of $from:$id instead of URL parameters FROM=$from&ID=$id 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-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. 2008-11-10 fexget: fixed bug query <> instead of 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-27 install: do not overwrite existing htdoc/index.html 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-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 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-02 dop: declare exectuable scripts as application/octet-stream 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 2008-09-05 fexsend: added rudimentary windows support 2008-09-03 dop: redirect on relative non-parent symlinks 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-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 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-08 fup: eliminate superfluous newlines in logfile on error handling 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-30 fup: fixed bug when account is a symlink 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-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-05-30 added missing sex to distribution 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-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-04-28 added support for HTTP keep_alive fexsrv: added SID (session ID) support 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 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 e-mail 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-11 fup: fixed bug in upload bar with 8-bit file names 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-08 renamed confusing ID to auth-ID (request by chris@citecs.de) 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-06 fup: use Net::DNS instead of external host command fup: more debuglog, fixed wrong error messages added doc/concept doc/FAQ 2008-04-02 install: better error handling (patch by chris@citecs.de) 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-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-28 xx: changed syntax, now compatible to zz 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-23 fup: fixed bug in using multiple recipients 2008-03-22 first public release 2006-11-?? first code fex-20130805/doc/fex-client_2.pdf0000644000174700017470000003000111140065743014414 0ustar fexfex%PDF-1.4 %쏢 5 0 obj <> stream xX]s}_z4쑠7V7Hte9;t+.IX`"e C ~!%et-ƆQ# fD *$HYRUJb[*[a*LTL1jmD R"r 5 |`TqR@<5\&29QɺJXAEU2llFXƨAXi)a֘nEg=>&AأOUDJ\. T HX1нb6Q ;S> *J|l5#H ""p\vO 5 ҇}Ro}AܖթP\'TJڲz-b*(.SkHu­KnI-ΆƓs{VVȈ(*.<j c^:X*ۅZKrhҮPq:?]]qq;`gDNÐv?;Knn'q4y;UْZN?ˇNMs>6zٝ!/t7;eO7RJ;C,wr{h~'ؒ$ 6tF~@[%;3q#*n׿9h۴]Cwd^vEF-O/j}v49;rѝ-^]TϏ.SUy,Mpi\~P endstream endobj 6 0 obj 1980 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 10 0 obj <> endobj 11 0 obj <> endobj 8 0 obj <> endobj 13 0 obj <> endobj 9 0 obj <> endobj 12 0 obj <>stream xux XS׺!ٻ֡%ݚMhkZB hPa@F0-0d0 (jjОt!////#xd$ĥx,cĒ䘔̷=bqQ8<5>#رce$ TIK/{]zJc#Y3;/G n ݷMrlwjL;>i~vdLܕ;;8z,zm۫,۸vKWJy"x!U xXJ;ċDXC,#]r"MND o/:"%$ۈAb?M61XL70yyS:i/Y~os:.X \೅/ 6 Ջ/mџ\` 1e'_?=ZKe>hE*S?$.6uEI&M~9eG=2Ѣ۩i?W(!OmySC`;}TW 0WR.:6ًir 2f'åZn'8|՜jJ*HW胋($հ$tB 992L8X b%67'X` +| zi#*5N[\T/ےkRdUZL DW.3)ʔJ3҇><}.=/R?1.>>ZyP*e @ ͧ0F)͠'݀k]'a3.bN}P&O;>f8ly{?n~kV**% hm7]~j}X4`d'@WAɁ^a[=jY'ߩWh+/5LS 1 a.v肌ZPAz֠kǐ4o> _<\ՖHB PVG Ƈc.OY5?bO|DO$F!춓UVpb05-[$J.A9L ɸY4`5 dFNc'7)/eӧ8Vp1dvwyɅ:\MFN晵``ZY@eKwq#q{r[yO9KCus4Ah }EFzxcG3GA7́SM8!9vcpJɬuڿٰ֯тկ"!Z2 ׾GψzWѳsxc"ɹp?uusd=I6QG8*N_3*b> J AYY\*W;"BɘԚB*̒3߀.;N%!  V.Mץ3S8rnywPNuB &\[ֲ2 FFXmUUGiqfwX}$/ߡY_juŃ=E`ȅٜl1;G#@Y=XyxObV4 Xw6ob~~oٝ  4&@6w /^:}t@ؕdP.JSaw$zWW#Dƒ ;zkl3;lK3n.HГK~Cw'ވp$:($x$$\A;7&@岎~~sЊ@]4+#=RU Usm͜VnX~4?8Jfl>.P2:&eNy(-AKQʮE_^z.0⧔AE76 FI:W$S+33˃A8\2 F .^Xf^ξԈ4QZ>m+s!lj]e^py<]`??9za8B{|p p Sۏ\˫B_v6KR|dLmpCK_;H$S8AX/{f2FZ= Ra `+-up9-TTfr GZZ!YӹΊ6!\ߨ[Cp i'W3_ G361hkiUP-U9"TJ^ F,U% f]g*t5ZUf[;ۑ& qpVO&>&(wmN6H)V4)ZZU[W\Kr1/1E-Rm J}BRA,|/Z ;@?rhhk)+%U8{*LE^h)}`3=IE!"q PVo>84,CgD[=ghg"VXoǨw |L_<sh y[|# r"K "wOyg DŽ)_$?uJ[XFYP7>Z[|pJD[N*o: \4#bAd$4Ali [rԗ5U`yUZ؄l˯_|dt+BZe h t:G/u$m>Εϳ>qk?Cu'u%n`No|,T+ G/:!D&h9T=',+.G0Uz^l#+tf~&0#v5ݩv:TZr-V8}i1mNj-y\xfˉ;pWK`.u\^t8vTǣV̎ #⍯X59F#{ FrpVd( I&OFC.#c‘+mE0&;!MmO5q05l9ra[DaCEܶ墟?Y!O P0-<ة;r<XŒwcVRАk5bs)h[ K )ލwyu 5 ]*$/\| ޣ7]~ޮlZGCR\3$N%:\_/$yL(̦S33%Lg{Sc3)[̻,7B/ yK@lLV˂GJmLZ")by4oB7ciRg jmk}/yi|fm1V|_I?X ɯyUĿ)z~$h<]`U N~wM8<$yeg5gwb1Ă&). Zk'Wʂ퍩V`~{kWF+2k (6(*U4xg<M?G #̔#63 k?Q{,9,-5w\Q2}"S/{FLmJyMu aP(Kt5l;A\'jNi$8R*hmo\~C1QR8ov|3pPi4XGD\^97[|3ҦGcYQyITXUT LT[WX[~ڧGdIU DN 6,!كsO?>^ARPIr/9>,*ò8 <3 |Y36U2Qh`u|YXSk2s٬%; C6-}@TIQЂv2XUG|_^.#yƂ `+Zzsm]Z$; 'MV8Ϩ*_2$?,j1ucUVVy;+ΐX PmDSn0,}8ȣXbF]e$u}󴥴j*'\*\+062DYNP%&SKp]F'㨯>F+ T)Bq$ $L+I.Q׃x]@(vDӗMJBe +KY7&olrj#WLR R\顢 5P-%?Gp|qaRaۉSو!v^M-,rNs_cfHw{us]S~M ^Y❋^r~ chה|)IHs>gs4ݥ׎ǍG_h YMjT]FY}fLc{n82j,trz8%35Y;\ ٰYp ' SB|lH\\s~ó}6)!LpFWS'InbZB(jb%ʛG)C,>;D cǿ$o;ͽN 8 {5TI7){yQFoX#C*vnT4 Ag992u&! QWa*.KL/0$bE=hroe5-?,ѓъxD@nĩȳ,Џp8ѫsh <8(Dz['<OBCc#zz;!^(ZQ򚲲zS]6*eV1QUD:Fn(Ω)G7\M.o߇k-ⅼS&g: R}3Fȇ׻Zꜝ MM :z<.,0>+RȳF_FܞK :1\Nf=])En?uiłf$YZ]= HυWߞ ~~ A!YGcI $OC]75y)`ƈU׊0,O,fʡsv&O898L-uNctNct'F|}^{q05\jۮ8t~<O'wg7lX=N^5f_ݛtPmy.j4+Dk^F;.JtaE=trfFRJcVGWScGGzKLMS]5\H?d}7'|&9ҥҼf3X^P{&yD>} w30[ JJM_sMl]^6%XHWT@ kB2}%[6JdaRSf5&=TɏΞleD4 ;lhgC#s.VdS <_Vao7TX,Bu;446-:M=n)UYiH2cNi_a-T6[PK2YYC>Κ {Y-rjRR)Wd  R1 ^i2P2e4á:+3tHz1"^TUX[UnwWL=XJKjhQ_`E+Z&V&Y)Zh? PЇ>pV93!Q|(ʫ[XN ".ꈓNF ? v c';*yP?g.A?g endstream endobj 14 0 obj <>stream UnknownApplication Untitled endstream endobj 2 0 obj <>endobj xref 0 15 0000000000 65535 f 0000002295 00000 n 0000011712 00000 n 0000002236 00000 n 0000002085 00000 n 0000000015 00000 n 0000002065 00000 n 0000002360 00000 n 0000002461 00000 n 0000003006 00000 n 0000002401 00000 n 0000002431 00000 n 0000003466 00000 n 0000002919 00000 n 0000010348 00000 n trailer << /Size 15 /Root 1 0 R /Info 2 0 R /ID [<56C093A3A4E46A0AE015D16FB8906053><56C093A3A4E46A0AE015D16FB8906053>] >> startxref 11835 %%EOF fex-20130805/doc/SEX0000644000174700017470000000663011430750754012044 0ustar fexfexSEX is a F*EX companion: Stream EXchange You can imagine SEX as network wide UNIX pipes with a relay between. This can be usefull for piping data from A to B where A and B cannot establish a direct connection, but both can connect by HTTP to the SEX-server. SEX is a synchronous service in conjuction to F*EX which is asynchronous. For seamless integration into the UNIX tool chain, there are the shell-tools sexsend and sexget. Using web browsers for sexing will not work, because they cannot handle streams in a pipe. So far, there are only the UNIX clients. Feel free to implement other clients for other operating systems :-) Authentication is the same as with F*EX. Example: root@lanldap:/var/log: tail -f syslog | sexsend framstag@rus.uni-stuttgart.de framstag@blubb:/tmp: sexget | grep ldap If you need encryption, then use the standard UNIX toolbox and add a appropriate program to the pipe, for example: openssl bf Tips for using SEX for file exchange: I have a lot of (administrative) accounts on even more hosts, where I have to exchange a lot or big files. These hosts often cannot make direct tcp-connects to each other, because of IP-filters, firewalls or missing server software. Only outgoing connections are possible. Therefore NFS, ssh or even ftp are no option. Since today my solution was F*EX: 1) on source host send the files within a container to the F*EX-server: fexsend -a container.tar file1 file2 ... . 2) read or copy the FEXURL with mouse 3) on destination host get container.tar from F*EX-server and extract it: fexget FEXURL tar xvf container.tar rm container.tar Backdraws: - a lot of manually work - creation of container.tar needs (a lot of) time - container.tar needs (too much) disk space on source and destination host and on the F*EX-Server Small solution: Usage of xx (wrapper for fexsend) eliminates manually handling of container.tar. But it will be still created, only automatically. The ressource problems are still there. The new sexy solution: I use SEX (Stream EXchange) instead of FEX (File EXchange)! There is no more a temporary container.tar, but the files are transfered as a stream with the new client sexxx! An example (*): On the source host: root@obertux:~/bin# sexxx . streaming: ./ ./autopatch ./subsys ./pwsync ./cspread ./fspread ./spread ./iptconf ./esxbackup ./esxlist ./getxx ./rscreen On the destination host: framstag@flupp:/tmp: sexxx extracting from stream: drwxr-xr-x root/root 0 2010-08-06 12:48 ./ -rwxr-xr-x framstag/users 170 2010-01-20 13:26 ./autopatch -rwxr-xr-x root/root 336 2006-02-02 15:15 ./subsys -rwxr-xr-x root/root 278 2010-01-18 23:38 ./pwsync lrwxrwxrwx root/root 0 2009-11-03 15:49 ./cspread -> spread lrwxrwxrwx root/root 0 2009-11-03 15:49 ./fspread -> spread -rwxr-xr-x root/root 10354 2010-02-12 14:49 ./spread -rwxr-xr-x root/root 1380 2010-01-14 08:54 ./iptconf -rwxr-xr-x root/root 116 2010-05-04 18:36 ./esxbackup -rwxr-xr-x root/root 344 2010-05-06 13:33 ./esxlist -rwxr-xr-x root/root 93 2010-08-06 12:32 ./getxx -rwxr-xr-x 1000/users 173 2009-11-26 13:40 ./rscreen Now I can transfer any files from a new installed (VM) server to my admin workstation behin a firewall. Or the other direction. (*) The example above has only a few kB, but one can use sexxx for many GB or even TB! On my VMs I get a throughput of 90 MB/s. fex-20130805/doc/SSL0000644000174700017470000000256412160646612012046 0ustar fexfex# http://www.stunnel.org/faq/certs.html # execute this as root! mkdir /home/fex/etc cd /home/fex/etc/ openssl req -new -x509 -days 9999 -nodes -out stunnel.pem -keyout stunnel.pem # see http://www.infodrom.org/Debian/tips/stunnel.html dd if=/dev/urandom count=2 | openssl dhparam -rand - 1024 >> stunnel.pem openssl x509 -text -in stunnel.pem chmod 600 stunnel.pem cat <stunnel.conf cert = /home/fex/etc/stunnel.pem sslVersion = all TIMEOUTclose = 1 exec = perl execargs = perl -T /home/fex/bin/fexsrv stunnel EOD chown -R fex . stunnel=$(which stunnel4) if [ -z "$stunnel" ]; then echo "no stunnel found" >&2 else cat </etc/xinetd.d/fexs # default: on # description: fex web server with SSL # note: only possible on port 443! service fexs { socket_type = stream wait = no type = unlisted protocol = tcp port = 443 cps = 5 10 user = fex groups = yes server = $stunnel server_args = /home/fex/etc/stunnel.conf nice = 0 disable = no } EOD /etc/init.d/xinetd restart echo 'To enforce https, add to fex.ph:' echo '$force_https = 1;' fi # Hint: on some systems stunnel works not well with xinetd # you can also run stunnel without xinetd, in server daemon mode fex-20130805/doc/fex-client_1.pdf0000644000174700017470000002227611140066003014420 0ustar fexfex%PDF-1.4 %쏢 5 0 obj <> stream xWMoF؛e#G.(6idVdrΒd6 XǙyogg=aB? >4H%W j(nBH":A%bL2M)vX <%C7,z>.hoyOf'A4yZC H R9 VCMt<_W8Ya,: Aa%Y&W/Gꭔ"R;l!R H#`sHEaTzsDM+=#s~?!HW+RI}Ȕs QHrD3*qH$X:bݨʉ)TȄ6)sS=JF,KjD}:Y$hWiytךQGLJZM:;% &~n*_k8 0qoS)B 06- F-3X?AD8cPm7 Ag@GrqBX!Gez`oԑド#4ݙ$D"a|FDH3Dd*dBtsSH9.j߹@ a~1;sP>4|bPi4F(훪7܀ω&TlT4pI53h5/J׉ B8 CGzmؓs+8=e%EDq\ĔG2A:1gXZd v7 aU)؈h J$6tMl7Ds Ñe 2rv:LVVҹAuLV)էpYw~e#3FQ0̿ro*؞er/bP{ZOϗ@ 68u١A>;Y~hO5~w9_:WݭEnWMs{g[y|s\qTZ2^Ɨw捏]rÄt2]* ڇ-uڕCqlI%c;RXEoOE~<}.֭SUc-7+n:7oWkAIsV+B0ݳŮ:<8pWfe54_@1۷׫laLVc(&~endstream endobj 6 0 obj 1181 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 10 0 obj <> endobj 11 0 obj <> endobj 8 0 obj <> endobj 13 0 obj <> endobj 9 0 obj <> endobj 12 0 obj <>stream xmW TS׺>1s@+i؄:թjm @A)$̙'0m$0&LQuVի^}}wvuZuVV~hs37D @|2Pҗtاm‘N]qQNVvIК֭[6MPXfqN?hRgK EycAY<^ZA!AAQY~az1XAЂCa#ve)Ύ*9\,/Κ^[CXm" ,ۃmVbQ^l3 ;}Ƣ}X !bqX8vۅB@9,sa E [m@c>;  \ǧ;4Ì!| >J?<ܓ ,\Y%{| ;^?,5,X7~dz( 92E-]phY+-6xaxw]e@U -Y@pIT$:P^n%@ŹEc7\+sFrԩg| Z3 ܍D.U(MY 8V*ޫ@3&ܶXSuE%E̯ (X)zI W~v[ܴ;:ԓ,Q*/?? .{GEBz=wG2stO_u 4c(ß,o .UҘ'xE]$[_–Z0bQΥ6c(P/ \v>ݏCjjXX"8|NSGb(*g9/roL,c"Iզ!dGP)EpV7f>"EvcX5G83_!gZȃ;䯣47$s"c9,-cʤJ!(2̐ؒ`:B@0@l}󣨫~@_drkBܺ3l_~0`)w /9ҹcҙeL'g%3KQ>[~|B?,sMIʊG7kL` TỨ?@qB)*y μ w]#9_ܴ_ayk`\v YVNKaGk'Ё؂Bna&]"$!uv^1 &ȏ³^<6 ^.Y6"…ںF8~6.c?YFS } F!),D02\!hlE @bm̾bTW} f-:"yr.09?}'O3t#˪omDW4KqW"6|^bXu+fNܬfw9s%a|Ɩf)"Dn| uܑ79sd.ن  B@l)ܕy#+%\BYyRW S~{{g#c;[WZs`ej1聣RcC`pYS!'(K }@=}#gh;ma]qNuK[8 8N>v'γę&+EYH7"ED#"(wU^>͝mp~A@>\ wJ'ѩh |s= dU*FuumT n*-/ |/*>pGI˹B{1S9φGh>jA%,Tx {on6OPpA6KfϾvz-Ѿ2M,2U{J4M AI2VAI@^hqt,:Idc(es9yU2FeJ%jܶ`X7I.?'Nq݉'s]2PL|kK)aRپ fj DVТdã@կS\N cN9}y–D_$߱˭gt};Y|UHV! ~Y JA\*()wb˴ïUrLU LC#-.g|7gWuzYO g8pJe)R/ e'Mqjm ͷ i胊5g6G"C|ꙵK5kZfTѬBe]\$C=TqQUeSPW+k怕QgFEzEjzr\LZ 6h | `ϸl=D?Gg$m@";_YUUW6\X{A6 auH_YWUWbz uJH6FHcz\o\1m:TM6*U1W9ДJ`.SDJ_ fMIH6ls&L׵ efJ v0YpZܯz/qfxљUˠίC6H;sq#a``kko#{Z"&p @獓dH}. |uo$re uZ\EԓĆ%NaGgȭn1#orc8qj&5T(3>|"ezd۹iZv2hkFבU)2@d Nsqp.@Z@Q~ >tj-zn&q)5E62s*UW]JlxThĥւ`.k&R lxa]~a:f\__qŀ wQ'/BPϰڭ(7̽ϪKh(|o}0# FӸ-8Q0 WX}02+Qȉ99wEOw >ZHd +*+R?(f/;fV4?;uLɊh`(QXn_Ro/h-*4,A#`|>/Ӈݬ;gz&o|l~4A+۽v.8( Et:ԑ1ZI]akŕ"-G[PepaSFX^&v岻xve+ ڬn905hq`1.CR&(ŜR2ofM"dBePim@M3D-a$H&;gʹC^CaIuG5%("J3`265ۑ2ѣsJF1SLus4J9]\au<cmL3Ph24y1ǹ~B'NFGzM?j] endstream endobj 14 0 obj <>stream UnknownApplication Untitled endstream endobj 2 0 obj <>endobj xref 0 15 0000000000 65535 f 0000001496 00000 n 0000008830 00000 n 0000001437 00000 n 0000001286 00000 n 0000000015 00000 n 0000001266 00000 n 0000001561 00000 n 0000001662 00000 n 0000002163 00000 n 0000001602 00000 n 0000001632 00000 n 0000002512 00000 n 0000002076 00000 n 0000007466 00000 n trailer << /Size 15 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 8953 %%EOF fex-20130805/doc/Contribs0000644000174700017470000000242412167031504013156 0ustar fexfexBeate Herrmann : - artwork Sebastian Zaiser : - upload status window Bernd Strehhuber : - dynamic protocol detection Kurt Jaeger : - ipv6 support Andre Hafner : - web admin interface fac - VM Martin Lauer : - FAQ Javascript Code Dominik Greibl : - java client F*IX Sebastian Roth : - many bugfixes and extensions (zip, proxy-support, etc) for F*IX Daniel Dieckmann - fexget proxy support Hanno Hirsch : - bug hunting Nicola Fioravanti (http://revshell.com): - Penetration tests and security debugging Waldemar Bronsch : - German localization Tobias Gunkel : - German localization Hans-Georg Bickel : - Swabian localization Francisco Ruiz : - Spanish localization Anton Meixome : - Galician localization Vanni Piagno : - Italian localization Michal Simunek : - Czech localization Jean-Baptiste Denis : - French localization fex-20130805/doc/Licence0000644000174700017470000001414012171333506012735 0ustar fexfexF*EX (Frams' Fast File EXchange) is a service to send big (large, huge, giant, ...) files from a user A to a user B via internet. Copyright (C) 2006-2013 Ullrich Horlacher YOU ARE NOT ALLOWED TO USE THIS SOFTWARE FOR MILITARY PURPOSES OR WITHIN MILITARY ORGANIZATIONS! THIS INCLUDES ALSO MILITARY RESEARCH AND EDUCATION, PARAMILITARY AND TERRORISTIC ORGANIZATIONS! This program is free software: you can redistribute it and/or modify it under the terms of the Perl Artistic Licence: "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder as specified below. "Copyright Holder" is whoever is named in the copyright or copyrights for the package. "You" is you, if you're thinking about copying or distributing this Package. "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as uunet.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) give non-standard executables non-standard names, and clearly document the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. You may embed this Package's interpreter within an executable of yours (by linking); this shall be construed as a mere form of aggregation, provided that the complete Standard Version of the interpreter is so embedded. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whoever generated them, and may be sold commercially, and may be aggregated with this Package. If such scripts or library files are aggregated with this Package via the so-called "undump" or "unexec" methods of producing a binary executable image, then distribution of such an image shall neither be construed as a distribution of this Package nor shall it fall under the restrictions of Paragraphs 3 and 4, provided that you do not represent such an executable image as a Standard Version of this Package. 7. C subroutines (or comparably compiled subroutines in other languages) supplied by you and linked into this Package in order to emulate subroutines and variables of the language defined by this Package shall not be considered part of this Package, but are the equivalent of input as in Paragraph 6, provided these subroutines do not change the language in any way that would cause it to fail the regression tests for the language. 8. Aggregation of this Package with a commercial distribution is always permitted provided that the use of this Package is embedded; that is, when no overt attempt is made to make this Package's interfaces visible to the end user of the commercial distribution. Such use shall not be construed as a distribution of this Package. 9. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. fex-20130805/doc/new0000644000174700017470000000051212157267321012167 0ustar fexfexNew release on http://fex.rus.uni-stuttgart.de/fex.html Important changes: - security update: new fac -D option to disable a user - new fex.ph variable $usage_conditions adds a "terms of usage" text to the registration e-mail - new fex.ph variable $notify_newrelease checks for new release and informs the admin by e-mail fex-20130805/doc/installation0000644000174700017470000000511212154142613014071 0ustar fexfexPrerequisites: ============== To install the F*EX server, you need a UNIX system with perl, xinetd and /usr/lib/sendmail (either original or a clone like postfix or exim). Your perl must have the following standard core modules: CGI CGI::Carp Digest::MD5 Encode Fcntl File::Basename Getopt::Std IO::Handle POSIX Optional are the non-standard perl modules: Net::DNS (for better domain error handling) Socket6 (for ipv6 support) Net::INET6Glue (for ipv6 support) IO::Socket::INET6 (for ipv6 support) On Debian or Ubuntu Linux simply execute as root: apt-get install xinetd perl-modules libnet-dns-perl libnet-inet6glue-perl test -x /usr/lib/sendmail || apt-get install postfix Do not forget to open port 80 on your firewalls and routers for incoming connections! To install F*EX, simply run "./install", then edit lib/fex.ph and set your local config. If you want to upgrade from a previous F*EX version, you also can run "./install", no old config files will be overwritten. Also index.html is kept. Alternativly use "./install -p 8888" to install F*EX on port 8888 instead on default port 80. Run "./install" again for installing optional localizations (languages). If the install-script does not work for you (no xinetd, no GNU tools, etc) here is what is to be done manually for installing: echo "fex 80/tcp" >> /etc/services echo "fex stream tcp nowait fex /home/fex/bin/fexsrv fexsrv" >> /etc/inetd.conf # now restart inetd useradd -s /bin/bash -c "File EXchange" -m fex pwd # --> FEXSOURCEDIR su - fex cd FEXSOURCEDIR cp -av bin cgi-bin lib etc htdocs doc $HOME cd $HOME mkdir spool chmod 700 spool vi lib/fex.ph # set your config crontab -e 3 3 * * * exec /home/fex/bin/fex_cleanup Hints: ====== F*EX runs with its own uid (default: fex), which will be created by the install script. F*EX uses a directory (FEXHOME) containing anything needed to run fex. Default is FEXHOME=/home/fex, the home directory of the "fex" user. If you want fex to be installed elsewhere create a new "fex" user account BEFORE running ./install, e.g.: adduser --system --group \ --gecos "File EXchange" \ --home /srv/fex \ --shell /bin/bash \ fex ./install If you run F*EX behind a HTTP reverse proxy, then write to lib/fex.ph : $reverse_proxy_ip = 'internal-IP.address.of.proxy'; $durl = 'http://your.proxy.with.domain/fop'; Be aware that most proxies have a 2 GB file size limit (signed int 32 bit bug)! Of course you have to configure your reverse proxy correctly, especially the URL rewrite rules. See the manual of your reverse proxy. On problems contact the author: framstag@rus.uni-stuttgart.de fex-20130805/upgrade0000777000174700017470000000000012177755050013653 2installustar fexfexfex-20130805/lib/0000755000174700017470000000000012177755050011461 5ustar fexfexfex-20130805/lib/dop0000711000174700017470000003125312176135615012163 0ustar fexfex#!/usr/bin/perl -wT # F*EX document output # # is a subprogram of fexsrv! do not run it directly! # # Author: Ulli Horlacher # use File::Basename; use CGI::Carp qw(fatalsToBrowser); use Fcntl qw(:flock :seek :mode); use POSIX qw(strftime locale_h); use Cwd qw(getcwd abs_path); # import from fex.pp our ($bs,$tmpdir,@doc_dirs); my $log = "$logdir/dop.log"; # POSIX time format needed for HTTP header setlocale(LC_TIME,'POSIX'); sub dop { my $doc = shift; my $source = shift; my $seek = 0; my $stop = 0; my ($link,$host,$path,$range); our $error = 'F*EX document output ERROR'; # reget? if ($range = $ENV{HTTP_RANGE}) { $seek = $1 if $range =~ /^bytes=(\d+)-/i; $stop = $1 if $range =~ /^bytes=\d*-(\d+)/i; } # redirect on relative symlinks without "../" if ($link = readlink($doc) and $link !~ m:^/: and $link !~ m:\.\./: and $link !~ /^:.+:$/) { $path = $ENV{REQUEST_URI}; $path =~ s:[^/]*$::; $doc = "$path/$link"; $doc =~ s:/+:/:g; $doc =~ s:^/::; $host = $ENV{HTTP_HOST} || $hostname; nvt_print( "HTTP/1.1 301 Moved Permanently", "Location: $ENV{PROTO}://$host/$doc", "Content-Length: 0", "Connection: close", "" ); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } # watchdog documents if (@wdd and $wdd and grep { $doc =~ /$_/ } @wdd) { &$wdd($doc) } my $dir = untaint(getcwd()); chdir(dirname($doc)); http_output($doc,$seek,$stop); chdir($dir); } sub http_output { my ($file,$seek,$stop) = @_; my ($filename,$files,$streamfile,$size,$total_size); my ($data,$type); my ($var,$env,$con); my @files; my $htmldoc = ''; my @s; my $s = 0; my $b = 0; my $http_client = $ENV{HTTP_USER_AGENT} || ''; local $_; # extra security check: document must not be in lib or spool directory if (path_match($file,$FEXLIB) or path_match($file,$spooldir)) { http_error(403); } security_check($file); if (-f $file) { # normal file open $file,'<',$file or http_error(400); security_check($file); } elsif ($file =~ /(.+)\.(tar|tgz|zip)$/ and @s = lstat($streamfile = "$1.stream") and $s[4] == $<) { # streaming file (only if it is owned by user fex) chdir dirname($file); security_check($file); if (-l $streamfile and readlink($streamfile) =~ /^:(.+):$/) { # special symlink pointer file for streaming @files = split(/:/,$1); } elsif (open $streamfile,$streamfile) { # special streaming file while (<$streamfile>) { chomp; if (/^(\/.*):/) { chdir $1; security_check($1); } else { push @files,$_; } } } else { http_error(503); } close $streamfile; foreach (@files) { if (/^\// or /\.\.\//) { # absolute path or relative path with parent directory is not allowed http_error(403); } if (@s = stat($_) and not($s[2] & S_IRGRP) or not -r $_) { # file must be readable by user and group http_error(403); } } http_error(416) if $ENV{HTTP_RANGE}; close STDERR; my @a; if ($file =~ /\.tar$/) { @a = qw'tar --exclude *~ -cf -' } elsif ($file =~ /\.tgz$/) { @a = qw'tar --exclude *~ -czf -'} elsif ($file =~ /\.zip$/) { @a = qw'zip -x *~ -rq -' } else { http_error(400) } open $file,'-|',@a,@files or http_error(503); } else { http_error(404); } $type = 'application/octet-stream'; if ($file =~ /\.html$/) { $type = 'text/html' } elsif ($file =~ /\.txt$/) { $type = 'text/plain' } elsif ($file =~ /\.css$/) { $type = 'text/css' } elsif ($file =~ /\.js$/) { $type = 'text/javascript' } elsif ($file =~ /\.ps$/) { $type = 'application/postscript' } elsif ($file =~ /\.pdf$/) { $type = 'application/pdf' } elsif ($file =~ /\.jpg$/) { $type = 'image/jpeg' } elsif ($file =~ /\.png$/) { $type = 'image/png' } elsif ($file =~ /\.gif$/) { $type = 'image/gif' } elsif ($file !~ /\.(tar|tgz|zip|jar|rar|arj|7z|bz2?|gz)$/) { my $qfile = untaint(abs_path($file)); $qfile =~ s/([^\/\.\+\w!=,_-])/\\$1/g; $_ = `file $qfile`; if (/HTML/) { $type = 'text/html'; } elsif (/text/i and not -x $file) { $type = 'text/plain'; } } # show sourcecode if URL ends with '!' # to avoid this for a HTML file, simple do a: chmod o-r file if ($type eq 'text/html') { if ($htmlsource) { if (@s = stat($file) and $s[2] & S_IROTH) { $type = 'text/plain'; } else { http_error(403); } } } elsif ($ENV{'QUERY_STRING'} eq '!') { $type = 'text/plain'; } if ($type eq 'text/html') { $seek = $stop = 0; local $^W = 0; local $/; $htmldoc = <$file>; while ($htmldoc =~ s/\n##.*?\n/\n/) {}; # evaluate #if ... #else ... #elseif ... #endif blocks my $mark = randstring(16); while ($htmldoc =~ s/\n(#if\s+(.+?)\n.+?\n)#endif/\n$mark/s) { $_ = $1; # if block if (eval $2) { s/#if.*\n//; s/\n#else.*//s; $htmldoc =~ s/$mark/$_/; } else { # elseif blocks while (s/.*?\n#elseif\s+(.+?)\n//s) { if (eval $1) { s/\n#else.*//s; $htmldoc =~ s/$mark/$_/; } } # else block left? if ($htmldoc =~ /$mark/) { s/.*\n#else\s*\n//s or $_ = ''; $htmldoc =~ s/$mark/$_/; } } }; # evaluate #include while ($htmldoc =~ s/\n#include "(.*?)"/\n$mark/s) { my $file = $1; my $include = ''; if (open $file,$file) { $include = <$file>; close $file; } $dynamic = $htmldoc =~ s/$mark/$include/; } # evaluate <> while ($htmldoc =~ /<<(.+?)>>/s) { local $pc = $1; local $__ = ''; tie *STDOUT => "Buffer",\$__; $__ .= eval $pc; untie *STDOUT; $dynamic = $htmldoc =~ s/<<(.+?)>>/$__/s; }; # substitute $variable$ with value from environment while ($htmldoc =~ /\$([\w_]+)\$/) { $var = $1; $env = $ENV{$var} || ''; $htmldoc =~ s/\$$var\$/$env/g; }; $total_size = $size = $s = length($htmldoc); } else { if (@files) { $size = 0; } else { $total_size = -s $file || 0; $size = $total_size - $seek - ($stop ? $total_size-$stop-1 : 0); } } if ($size < 0) { http_header('416 Requested Range Not Satisfiable'); exit; } alarm($timeout*10); if ($seek or $stop) { my $range; if ($stop) { $range = sprintf("bytes %s-%s/%s",$seek,$stop,$total_size); } else { $range = sprintf("bytes %s-%s/%s",$seek,$total_size-1,$total_size); } nvt_print( 'HTTP/1.1 206 Partial Content', 'Server: fexsrv', "Content-Length: $size", "Content-Range: $range", "Content-Type: $type", '', ); } else { # streaming? if (@files) { nvt_print( 'HTTP/1.1 200 OK', 'Server: fexsrv', "Expires: 0", "Content-Type: $type", '', ); } else { # Java (clients) needs Last-Modified header! # if there are locale versions, use actual time for Last-Modified # to enforce reload of page $file =~ m{/htdocs/(.+)}; my @lfiles = glob("$FEXHOME/locale/*/htdocs/$1"); my $date = ($dynamic or @lfiles > 1) ? strftime("%a, %d %b %Y %T GMT",gmtime(time)) : http_date($file); nvt_print( 'HTTP/1.1 200 OK', 'Server: fexsrv', "Last-Modified: $date", "Expires: 0", "Content-Length: $size", "Content-Type: $type", '', ); } } if ($ENV{REQUEST_METHOD} eq 'GET') { if ($type eq 'text/html') { alarm($timeout*10); print $htmldoc; } else { # binary data # can be stream! seek $file,$seek,0 if $seek; while ($b = read($file,$data,$bs)) { if ($stop and $s+$b > $size) { $b = $size-$s; $data = substr($data,0,$b) } $s += $b; alarm($timeout*10); print $data or last; } } fdlog($log,$file,$s,$size) if $s; } alarm(0); close $file; exit if @files; # streaming end return $s; } # show directory index sub showindex { my $dir = shift; my ($htmldoc,$size); my @links = (); my @dirs = (); my @files = (); my $uri = $ENV{REQUEST_URI}; my $allowed; local $_; $uri =~ s:/+$::; $dir =~ s:/+$::; security_check($dir); open my $htindex,"$dir/.htindex" or http_error(403); # .htindex may contain listing regexp chomp ($allowed = <$htindex>||'.'); close $htindex; opendir $dir,$dir or http_error(503); while (defined($_ = readdir $dir)) { next if /^[.#]/ or /~$/; if (-l "$dir/$_") { push @links,$_ } elsif (-d "$dir/$_") { push @dirs,$_ } elsif (-f "$dir/$_") { push @files,$_ } } closedir $dir; # parent directory listable? if ($uri =~ m:(/.+)/.+: and -f "$dir/../.htindex") { unshift @dirs,$1; } # first the (sub)directories $htmldoc = "\n

$uri/

\n"; foreach my $d (sort @dirs) { if ($d =~ m:^/: and -f "$d/.htindex") { $htmldoc .= "

$d/

\n"; } elsif (-f "$dir/$d/.htindex") { $htmldoc .= "

$uri/$d/

\n"; } } # # then the symlinks # $htmldoc .= "\n
\n";
#  my $link;
#  foreach my $l (sort @links) {
#    if ($l =~ /$allowed/ and $link = readlink "$dir/$l" and $link =~ /^[^.\/]/) {
#      $htmldoc .= "$l -> $dir/$link\n";
#    }
#  }
  
  # then the files
  $htmldoc .= "\n
\n";
  foreach my $f (sort @files) {
    if ($f =~ /$allowed/) {
      $htmldoc .= sprintf "%20s %20s %s\n",
                          isodate(mtime("$dir/$f")),
                          d3(-s "$dir/$f"||0),
                          $uri,urlencode($f),$f;
    }
  }
  $htmldoc .= "
\n\n"; $size = length($htmldoc); nvt_print( 'HTTP/1.1 200 OK', 'Server: fexsrv', "Content-Length: $size", "Content-Type: text/html", '', ); print $htmldoc; fdlog($log,"$dir/",$size,$size); } sub mtime { return (lstat shift)[9]; } sub d3 { local $_ = shift; while (s/(\d)(\d\d\d\b)/$1,$2/) {}; return $_; } sub http_date { my $file = shift; my @stat; if (@stat = stat($file)) { return strftime("%a, %d %b %Y %T GMT",gmtime($stat[9])); } else { return 0; } } sub path_match { my $p1 = abs_path(shift); my $p2 = abs_path(shift); if (defined $p1 and defined $p2) { return 1 if $p1 =~ /^\Q$p2/; return 2 if dirname($p1) =~ /^\Q$p2/; } return 0; } # return real file name (from symlink) sub realfilename { my $file = shift; return '' unless -e $file; if (-l $file) { return realfilename(readlink($file)); } else { return $file; } } sub security_check { my $file = shift; # can be directory, too my @s; # client ip allowed? access_check($file); # documents with leading . are not allowed if (abs_path($file) =~ /\/\./) { errorlog("$file with leading ."); http_error(403); } if (-f $file) { # document filename must not contain @ if (realfilename($file) =~ /@/) { errorlog("$file contains @"); http_error(403); } # document filename must not end with ~ if (realfilename($file) =~ /~$/) { errorlog("$file ends with ~"); http_error(403); } # file must be group or world readable if (@s = stat($file) and not($s[2] & (S_IRGRP|S_IROTH))) { errorlog("$file not group or world readable"); http_error(403); } # symlink to regular file and symlink owned by root or fex? ==> ok! if (-l $file and path_match(dirname($file),$docdir)) { @s = lstat($file); return if $s[4] == 0 or $s[4] == $<; } } # file in allowed directory? ==> ok! foreach my $dir (@doc_dirs) { return if path_match($file,$dir); } errorlog("$file not in \@doc_dirs"); http_error(403); } # security check: client ip allowed? sub access_check { my $file = abs_path(shift); my $dir = $file; my $af; local $_; $dir .= '/x' if -d $dir; while ($dir = dirname($dir) and $dir ne '/') { $af = "$dir/.htaccessfrom"; if (open $af,$af) { while (<$af>) { s/\s//g; if (ipin($ra,$_)) { close $af; return; } } errorlog("no access to $file by $af"); http_error(403); } } } # function for <> inside HTML documents sub out { $__ .= join('',@_); return ''; } # tie STDOUT to buffer variable (redefining print) package Buffer; sub TIEHANDLE { my ($class,$buffer) = @_; bless $buffer,$class; } sub PRINT { my $buffer = shift; $$buffer .= $_ foreach @_; } 1; fex-20130805/lib/fup.pl0000644000174700017470000000265512142673265012617 0ustar fexfex# config for F*EX CGI fup $info_1 = $info_login = <

F*EX (File EXchange) is a service to send big (large, huge, giant, ...) files.

The sender (you) uploads the file to the F*EX server and the recipient automatically gets a notification e-mail with a download-URL.
After download or after $keep_default days the server deletes the file. F*EX is not an archive!

See also questions & answers and use cases.


$ENV{SERVER_ADMIN}
EOD $info_2 = <

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 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.

If you want to send more than one file, then put them in a zip or tar archive, e.g. with 7-Zip.

See also the FAQ and use cases.


$ENV{SERVER_ADMIN}
EOD fex-20130805/lib/fex.ph0000644000174700017470000001223612174675133012600 0ustar fexfex## your F*EX server host name (with domain) $hostname = 'MYHOSTNAME.MYDOMAIN'; ## admin e-mail address used in notification e-mails $admin = 'fex@'.$hostname; ## password for http://$hostname/fac admin web interface $admin_pw = ''; ## optional: restrict web administration to ip range(s) # @admin_hosts = qw(127.0.0.1-127.1.1.254 129.69.13.139); ## server admin e-mail address shown on web page $ENV{SERVER_ADMIN} = $admin; ## Bcc address for notification e-mails $bcc = 'fex'; ## send notifications about new F*EX releases $notify_newrelease = $admin; ## optional: download-URLs as sent in notification e-mails # @durl = qw(http://MYFEXSERVER/fop https://MYFEXSERVER/fop http://MYPROXY/fex/fop); ## On AUTO mode the fexserver sends notification e-mails automatically. ## On MANUAL mode the user must notify the recipients manually. # $mailmode = 'MANUAL'; $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 # $mdomain = 'MY.MAIL.DOMAIN'; # $admin = 'fexmaster@'.$mdomain; ## optional: static address (instead of F*EX user) in notification e-mail From ## BEWARE: if set, mail error bounces will not go to the real sender, but ## to this address! # $sender_from = $admin; ## optional HTML header extra link and logo # @H1_extra = qw(http://www.MY.ORG http://www.MY.ORG/logo.gif); # locales to present (must be installed!) # if empty, present all installed locales # @locales = qw(english swabian); ## default locale: which languange is used in first place # $default_locale = 'swabian'; ## where to store the files and logs $spooldir = "$ENV{HOME}/spool"; $logdir = $spooldir; ## Default quota in MB for recipient; 0 means "no quota" $recipient_quota = 0; ## Default quota in MB for sender; 0 means "no quota" $sender_quota = 0; ## Expiration: keep files that number of days (default) $keep = 5; ## Expiration: keep files that number of days (maximum) $keep_max = 99; ## Autodelete: delete files after download (automatically) ## YES ==> immediatelly (1 minute grace time) ## DELAY ==> after download at next fex_cleanup cronjob run ## 2 ==> 2 days after download (can be any number!) ## NO ==> after expiration date (see $keep) $autodelete = 'YES'; ## if the file has been already downloaded then subsequentials ## downloads are only allowed from the same client (uses cookies) ## to prevent file sharing $limited_download = 'YES'; ## Allow or disallow overwriting of files $overwrite = 'YES'; ## optional: from which hosts and for which mail domains users may ## register themselves as full users # @local_hosts = qw(127.0.0.1 ::1 10.10.100.0-10.10.200.255 129.69.1.11); # @local_domains = qw(uni-stuttgart.de flupp.org); # @local_domains = qw(*); # special: allow ALL domains ## optional: external users may register themselves as restricted users ## for local receiving domains and hosts (must set both!) # @local_rdomains = qw(flupp.org *.flupp.org); # @local_rhosts = qw(10.0.0.0-10.0.255.255 129.69.1.11); ## optional: allow restricted user registration only by certain domains # @registration_domains = qw(belwue.de ietf.org); ## optional: allow restricted user registration only by certain hosts # @registration_hosts = qw(129.69.0.0-129.69.255.255 176.9.84.26); ## optional: for certain remote domains do not use sender address in ## notfication e-mail From, because their MTA will probably ## reject it if From and To contain their domain name. ## Instead use $admin for From. # @remote_domains = qw(flupp.org); ## optional: allow public upload via http://$hostname/pup for # @public_recipients = qw(fexmaster@rus.uni-stuttgart.de); ## optional: allow anonymous upload without authentication for these IP ranges # @anonymous_upload = qw(127.0.0.1 ::1 10.10.100.0-10.10.200.255 129.69.1.11); ## optional: forbidden addresses # @forbidden_recipients = qw(nobody@* *@microsoft.com); ## optional: restrict upload to these IP ranges # @upload_hosts = qw(127.0.0.1 ::1 10.10.100.0-10.10.200.255 129.69.1.11); ## optional: restrict download to these address ranges # @download_hosts = qw(127.0.0.1 10.10.100.0-10.10.200.255 129.69.1.11); ## optional: throttle bandwith for certain addresses (in kB/s) ## 0 means : full speed ## first match wins # @throttle = qw( # framstag@*:0 microsoft.com:100 # 127.0.0.1:0 202.0.0.0-211.255.255.255:1024 # [::1]:0 [fe00::0-fe00::ffff]:0 # ); ## optional: expire user accounts after x days of inactivity ## delete=wipe out, notify=send mail to fex admin # $account_expire = "100:delete"; # $account_expire = "365:notify"; ## optional: allowed directories for file linking (see fexsend) # @file_link_dirs = qw(/sw /nfs/home/exampleuser); ## optional: allow additional directories with static documents ## (/home/fex/htdocs is always allowed implicitly) # @doc_dirs = qw(/sw /nfs/home/exampleuser/htdocs); ## optional: suppress funny messages # $boring = 1; ## optional: text file with your conditions of using ## will be append to registrations request replies. # $usage_conditions = "$docdir/usage_conditions"; fex-20130805/lib/reactivation.txt0000600000174700017470000000006511705314646014701 0ustar fexfexYour F*EX account has been successfully reactivated. fex-20130805/lib/fex.pp0000600000174700017470000006634312174604467012612 0ustar fexfex# -*- perl -*- use 5.008; use Fcntl qw':flock :seek :mode'; use IO::Handle; use Encode; use Digest::MD5 qw'md5_hex'; use File::Basename; use Sys::Hostname; # set and untaint ENV if not in CLI (fexsrv provides clean ENV) unless (-t) { foreach my $v (keys %ENV) { ($ENV{$v}) = ($ENV{$v} =~ /(.*)/s); } $ENV{PATH} = '/usr/local/bin:/bin:/usr/bin'; $ENV{IFS} = " \t\n"; $ENV{BASH_ENV} = ''; } unless ($FEXLIB = $ENV{FEXLIB} and -d $FEXLIB) { die "$0: found no FEXLIB - fexsrv needs full path\n" } $FEXLIB =~ s:/+:/:g; $FEXLIB =~ s:/$::; # $FEXHOME is top-level directory of F*EX installation # $ENV{HOME} is login-directory of user fex # in default-installation both are equal, but they may differ $FEXHOME = $ENV{FEXHOME} or $ENV{FEXHOME} = $FEXHOME = dirname($FEXLIB); umask 077; # defaults $hostname = gethostname(); $tmpdir = $ENV{TMPDIR} || '/var/tmp'; $spooldir = $ENV{HOME}.'/spool'; $docdir = $FEXHOME.'/htdocs'; $logdir = $spooldir; $autodelete = 'YES'; $overwrite = 'YES'; $limited_download = 'YES'; # multiple downloads only from same client $keep = 5; # days $recipient_quota = 0; # MB $sender_quota = 0; # MB $timeout = 30; # seconds $bs = 2**16; # I/O blocksize $use_cookies = 1; $sendmail = '/usr/lib/sendmail'; $sendmail = '/usr/sbin/sendmail' unless -x $sendmail; $mailmode = 'auto'; $bcc = 'fex'; $default_locale = ''; # allowed download managers (HTTP User-Agent) $adlm = '^(Axel|fex)'; # allowed multi download recipients $amdl = '^(anonymous|_fexmail_)'; # local config require "$FEXLIB/fex.ph" or die "$0: cannot load $FEXLIB/fex.ph - $!"; push @doc_dirs,$docdir; # check for name based virtual host vhost($ENV{'HTTP_HOST'}); $nomail = ($mailmode =~ /^MANUAL|nomail$/i); if (not $nomail and not -x $sendmail) { http_die("found no sendmail\n"); } http_die("cannot determine the server hostname") unless $hostname; $ENV{PROTO} = 'http' unless $ENV{PROTO}; $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 if (my $ra = $ENV{REMOTE_ADDR} and $max_fail) { mkdirp("$spooldir/.fail"); $faillog = "$spooldir/.fail/$ra"; } unless ($admin) { $admin = $ENV{SERVER_ADMIN} ? $ENV{SERVER_ADMIN} : 'fex@'.$hostname; } # $ENV{SERVER_ADMIN} may be set empty in fex.ph! $ENV{SERVER_ADMIN} = $admin unless defined $ENV{SERVER_ADMIN}; $mdomain ||= ''; if ($use_cookies) { if (my $cookie = $ENV{HTTP_COOKIE}) { if ($cookie =~ /\bakey=(\w+)/) { $akey = $1 } # elsif ($cookie =~ /\bskey=(\w+)/) { $skey = $1 } } } if (@locales) { if ($default_locale and not grep /^$default_locale$/,@locales) { push @locales,$default_locale; } if (@locales == 1) { $default_locale = $locales[0]; } } unless ($durl) { my $host = ''; my $port = 0; ($host,$port) = split(':',$ENV{HTTP_HOST}||''); $host = $hostname; unless ($port) { $port = 80; if (open my $xinetd,'<',"/etc/xinetd.d/fex") { while (<$xinetd>) { if (/^\s*port\s*=\s*(\d+)/) { $port = $1; last; } } close $xinetd; } } # use same protocal as uploader for download if ($ENV{PROTO} eq 'https' and $port == 443 or $port == 80) { $durl = "$ENV{PROTO}://$host/fop"; } else { $durl = "$ENV{PROTO}://$host:$port/fop"; } } @durl = ($durl) unless @durl; sub debug { print header(),"
\n";
  print "file = $file\n";
  foreach $v (keys %ENV) {
    print $v,' = "',$ENV{$v},"\"\n";
  }
  print "

\n"; } sub nvt_print { foreach (@_) { syswrite STDOUT,"$_\r\n" } } sub html_quote { local $_ = shift; s/&/&/g; s/' '' ' ' ' ' ' $title' '' )); # '' if ($0 =~ /fexdev/) { $head .= "\n" } else { $head .= "\n" } $title =~ s:F\*EX:F*EX:; if (open $header,'<',"$docdir/$header") { $head .= $_ while <$header>; close $header; } if (@H1_extra) { $head .= sprintf( '

%s

', $H1_extra[0],$H1_extra[1]||'',$title ); } else { $head .= "

$title

"; } $head .= "\n"; return $head; } sub html_error { my $error = shift; my $msg = "@_"; my @msg = @_; my $isodate = isodate(time); $msg =~ s/[\s\n]+/ /g; $msg =~ s/<.+?>//g; # remove HTML map { s///gi } @msg; errorlog($msg); # cannot send standard HTTP Status-Code 400, because stupid # Internet Explorer then refuses to display HTML body! http_header("666 Bad Request - $msg"); print html_header($error); print 'ERROR: ',join("

\n",@msg),"\n"; pq(qq( '


' '

' $ENV{HTTP_HOST}' ' $isodate' ' $ENV{SERVER_ADMIN}' '
' '' )); exit; } sub http_die { # not in CGI mode die "$0: @_\n" unless $ENV{GATEWAY_INTERFACE}; debuglog(@_); # create special error file on upload if ($uid) { my $ukey = "$spooldir/.ukeys/$uid"; $ukey .= "/error" if -d $ukey; unlink $ukey; if (open $ukey,'>',$ukey) { print {$ukey} join("\n",@_),"\n"; close $ukey; } } html_error($error||'',@_); } sub check_maint { if (my $status = readlink '@MAINTENANCE') { my $isodate = isodate(time); http_header('666 MAINTENANCE'); print html_header($head); pq(qq( "
" "

Server is in maintenance mode

" "

($status)

" "
" "


" "

$ENV{HTTP_HOST} $isodate
" "" )); exit; } } sub check_status { my $user = shift; $user = lc $user; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; if (-e "$user/\@DISABLED") { my $isodate = isodate(time); http_header('666 DISABLED'); print html_header($head); pq(qq( "

$user is disabled

" "Contact $ENV{SERVER_ADMIN} for details" "


" "

$ENV{HTTP_HOST} $isodate
" "" )); exit; } } sub isodate { my @d = localtime shift; return sprintf('%d-%02d-%02d %02d:%02d:%02d', $d[5]+1900,$d[4]+1,$d[3],$d[2],$d[1],$d[0]); } sub encode_Q { my $s = shift; $s =~ s{([\=\x00-\x20\x7F-\xA0])}{sprintf("=%02X",ord($1))}eog; return $s; } # from MIME::Base64::Perl sub decode_b64 { local $_ = shift; my $uu = ''; my ($i,$l); tr|A-Za-z0-9+=/||cd; s/=+$//; tr|A-Za-z0-9+/| -_|; return '' unless length; $l = (length)-60; for ($i = 0; $i <= $l; $i += 60) { $uu .= "M" . substr($_,$i,60); } $_ = substr($_,$i); $uu .= chr(32+(length)*3/4) . $_ if $_; return unpack ("u",$uu); } # short base64 encoding sub b64 { local $_ = ''; my $x = 0; pos($_[0]) = 0; $_ = join '',map(pack('u',$_)=~ /^.(\S*)/, ($_[0]=~/(.{1,45})/gs)); tr|` -_|AA-Za-z0-9+/|; $x = (3 - length($_[0]) % 3) % 3; s/.{$x}$//; return $_; } # simulate a "rm -rf", but never removes '..' # return number of removed files sub rmrf { my @files = @_; my $dels = 0; my ($file,$dir); local *D; local $_; foreach (@files) { next if /(^|\/)\.\.$/; /(.*)/; $file = $1; if (-d $file and not -l $file) { $dir = $file; opendir D,$dir or next; while ($file = readdir D) { next if $file eq '.' or $file eq '..'; $dels += rmrf("$dir/$file"); } closedir D; rmdir $dir and $dels++; } else { unlink $file and $dels++; } } return $dels; } sub gethostname { my $hostname = hostname; my $domain; local $_; unless ($hostname) { $_ = `hostname 2>/dev/null`; $hostname = /(.+)/ ? $1 : ''; } if ($hostname !~ /\./ and open my $rc,'/etc/resolv.conf') { while (<$rc>) { if (/^\s*domain\s+([\w.-]+)/) { $domain = $1; last; } if (/^\s*search\s+([\w.-]+)/) { $domain = $1; } } close $rc; $hostname .= ".$domain" if $domain; } if ($hostname !~ /\./ and $admin and $admin =~ /\@([\w.-]+)/) { $hostname .= '.'.$1; } return $hostname; } # strip off path names (Windows or UNIX) sub strip_path { local $_ = shift; s/.*\\// if /^([A-Z]:)?\\/; s:.*/::; return $_; } # substitute all critcal chars sub normalize { local $_ = shift; return '' unless defined $_; # we need perl native utf8 (see perldoc utf8) $_ = decode_utf8($_) unless utf8::is_utf8($_); s/[\r\n\x09]+/ /g; s/[\x00-\x1F\x80-\x9F]/_/g; s/^\s+//; s/\s+$//; return encode_utf8($_); } # substitute all critcal chars with underscore sub normalize_filename { local $_ = shift; return $_ unless $_; # we need native utf8 $_ = decode_utf8($_) unless utf8::is_utf8($_); $_ = strip_path($_); # substitute all critcal chars with underscore s/[^a-zA-Z0-9_=.+-]/_/g; s/^\./_/; return encode_utf8($_); } sub untaint { local $_ = shift; /(.*)/s; return $1; } sub checkchars { my $input = shift; local $_ = shift; if (/^([<>|+.])/) { http_die(sprintf("\"&#%s;\" is not allowed at beginning of %s", ord($1),$input)); } if (/([\/\"\'\\<>;])/) { http_die(sprintf("\"&#%s;\" is not allowed in %s",ord($1),$input)); } if (/([<>|])$/) { http_die(sprintf("\"&#%s;\" is not allowed at end of %s",ord($1),$input)); } } sub checkaddress { my $a = shift; my $re; local $_; local ($domain,$dns); $a =~ s/:\w+=.*//; # remove options from address return $a if $a eq 'anonymous'; $re = '^[.@]|@.*@|local(host|domain)$|["\'\`\|\s()<>/;,]'; if ($a =~ /$re/i) { debuglog("$a has illegal syntax ($re)"); return ''; } $re = '^[!^=~#_:.+*{}\w\-\[\]]+\@(\w[.\w\-]*\.[a-z]+)$'; if ($a =~ /$re/i) { $domain = $dns = $1; { local $SIG{__DIE__} = sub { die "\n" }; eval q{ use Net::DNS; $dns = Net::DNS::Resolver->new->query($domain)||mx($domain); unless ($dns or mx('uni-stuttgart.de')) { http_die("Internal error: bad resolver"); } } }; if ($dns) { return untaint($a); } else { debuglog("no A or MX DNS record found for $domain"); return ''; } } else { debuglog("$a does not match e-mail regexp ($re)"); return ''; } } # check forbidden addresses sub checkforbidden { my $a = shift; if (@forbidden_recipients) { foreach my $fr (@forbidden_recipients) { $fr = quotemeta $fr; $fr =~ s/\\\*/.*/g; # allow wildcard * $a .= '@'.$mdomain if $mdomain and $a !~ /@/; # skip public recipients if (@public_recipients) { foreach my $pr (@public_recipients) { if ($a eq lc $pr) { $fr = ''; last; } } } return '' if $a =~ /^$fr$/i; } } return $a; } sub randstring { my $n = shift; my @rc = ('A'..'Z','a'..'z',0..9 ); my $rn = @rc; my $rs; for (1..$n) { $rs .= $rc[int(rand($rn))] }; return $rs; } # emulate mkdir -p sub mkdirp { my $dir = shift; my $pdir; return if -d $dir; $dir =~ s:/+$::; http_die("cannot mkdir /\n") unless $dir; $pdir = $dir; if ($pdir =~ s:/[^/]+$::) { mkdirp($pdir) unless -d $pdir; } unless (-d $dir) { mkdir $dir,0770 or http_die("mkdir $dir - $!\n"); } } # hash with SID sub sidhash { my ($rid,$id) = @_; if ($rid and $ENV{SID} and $id =~ /^MD5H:/) { $rid = 'MD5H:'.md5_hex($rid.$ENV{SID}); } return $rid; } # test if ip is in iplist (ipv4/ipv6) # iplist is an array with ips and ip-ranges sub ipin { my ($ip,@list) = @_; my ($i,$ia,$ib); $ipe = lc(ipe($ip)); map { lc } @list; foreach $i (@list) { if ($ip =~ /\./ and $i =~ /\./ or $ip =~ /:/ and $i =~ /:/) { if ($i =~ /(.+)-(.+)/) { ($ia,$ib) = ($1,$2); $ia = ipe($ia); $ib = ipe($ib); return $ip if $ipe ge $ia and $ipe le $ib; } else { return $ip if $ipe eq ipe($i); } } } return ''; } # ip expand (ipv4/ipv6) sub ipe { local $_ = shift; if (/^\d+\.\d+\.\d+\.\d+$/) { s/\b(\d\d?)\b/sprintf "%03d",$1/ge; return $_; } elsif (/^[:\w]+:\w+$/) { s/\b(\w+)\b/sprintf "%04s",$1/ge; s/^:/0000:/; while (s/::/::0000:/) { last if length > 39 } s/::/:/; return $_; } else { return ''; } } # doted ip to ip integer sub ipn { local $_ = shift; if (/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { return $1*256**3+$2*256**2+$3*256+$4; } else { return undef; } } sub filename { my $file = shift; my $filename; if (open $file,'<',"$file/filename") { $filename = <$file>||''; close $file; chomp $filename; } return $filename ? $filename : '???'; } sub urlencode { local $_ = shift; s/(^[.~]|[^\w.,=:~^+-])/sprintf "%%%X",ord($1)/ge; return $_; } # file and document log sub fdlog { my ($log,$file,$s,$size) = @_; my $ra; if (open $log,'>>',$log) { flock $log,LOCK_EX; seek $log,0,SEEK_END; $ra = $ENV{REMOTE_ADDR}||'-'; $ra .= '/'.$ENV{HTTP_X_FORWARDED_FOR} if $ENV{HTTP_X_FORWARDED_FOR}; $ra =~ s/\s//g; $file =~ s:/data$::; printf {$log} "%s [%s_%s] %s %s %s/%s\n", isodate(time),$$,$ENV{REQUESTCOUNT},$ra,encode_Q($file),$s,$size; close $log; } } # extra debug log sub debuglog { my $prg = $0; local $_; return unless $debug and @_; unless ($debuglog and fileno $debuglog) { mkdir "$logdir/.debug",0770 unless -d "$logdir/.debug"; $prg =~ s:.*/::; $prg = untaint($prg); $debuglog = sprintf("%s/.debug/%s_%s_%s.%s", $logdir,time,$$,$ENV{REQUESTCOUNT}||0,$prg); $debuglog =~ s/\s/_/g; open $debuglog,'>>',$debuglog or return; autoflush $debuglog 1; # printf {$debuglog} "\n### %s ###\n",isodate(time); } while ($_ = shift @_) { s/\n*$/\n/; s/<.+?>//g; # remove HTML print {$debuglog} $_; print "DEBUG: $_" if -t; } } # extra debug log sub errorlog { my $prg = $0; my $log = "$logdir/error.log"; my $msg = "@_"; $prg =~ s:.*/::; $msg =~ s/[\r\n]+$//; $msg =~ s/[\r\n]+/ /; $msg =~ s/\s*

.*//; if (open $log,'>>',$log) { flock $log,LOCK_EX; seek $log,0,SEEK_END; $ra = $ENV{REMOTE_ADDR}||'-'; $ra .= '/'.$ENV{HTTP_X_FORWARDED_FOR} if $ENV{HTTP_X_FORWARDED_FOR}; $ra =~ s/\s//g; printf {$log} "%s %s %s %s\n",isodate(time),$prg,$ra,$msg; close $log; } } # failed authentification log sub faillog { my $request = shift; my $n = 1; my $ra = $ENV{REMOTE_ADDR}; if ($faillog and $max_fail_handler and open $ra,"+>>$faillog") { flock($ra,LOCK_EX); seek $ra,0,SEEK_SET; $n++ while <$ra>; printf {$ra} "%s %s\n",isodate(time),$request; close $ra; &$max_fail_handler($ra) if $n > $max_fail; } } # remove all white space sub despace { local $_ = shift; s/\s//g; return $_; } # superquoting sub qqq { local $_ = shift; my ($s,$i,@s); my $q = "[\'\"]"; # quote delimiter chars " and ' # remove first newline and look for default indention s/^(\(\d+)?)?\n//; $i = ' ' x ($2||0); # remove trailing spaces at end s/[ \t]*\?$//; @s = split "\n"; # first line have a quote delimiter char? if (/^\s+$q/) { # remove heading spaces and delimiter chars foreach (@s) { s/^\s*$q//; s/$q\s*$//; } } else { # find the line with the fewest heading spaces (and count them) # (beware of tabs!) $s = length; foreach (@s) { if (/^( *)\S/ and length($1) < $s) { $s = length($1) }; } # adjust indention foreach (@s) { s/^ {$s}/$i/; } } return join("\n",@s)."\n"; } # print superquoted sub pq { my $H = STDOUT; if (@_ > 1 and defined fileno $_[0]) { $H = shift } print {$H} qqq(@_); } # check sender quota sub check_sender_quota { my $sender = shift; my $squota = $sender_quota||0; my $du = 0; my ($file,@file,$size,%size,$qf,$qs); local $_; if (open $qf,'<',"$sender/\@QUOTA") { while (<$qf>) { s/#.*//; $squota = $1 if /sender.*?(\d+)/i; } close $qf; } $qs = "*/$sender/*"; if (glob $qs and open $qs,untaint("du $qs 2>/dev/null|")) { while (<$qs>) { $du += $1 if /^(\d+)/; } close $qs; } return($squota,int($du/1024)); } # check recipient quota sub check_recipient_quota { my $recipient = shift; my $rquota = $recipient_quota||0; my $du = 0; local $_; if (open my $qf,'<',"$recipient/\@QUOTA") { while (<$qf>) { s/#.*//; $rquota = $1 if /recipient.*?(\d+)/i; } close $qf; } foreach my $data (glob("$recipient/*/*/data $recipient/*/*/upload")) { unless (-l $data) { $du += -s $data||0; } } return($rquota,int($du/1024/1024)); } sub getline { my $file = shift; local $_; chomp($_ = <$file>||''); return $_; } # (shell) wildcard matching sub wcmatch { local $_ = shift; my $p = quotemeta shift; $p =~ s/\\\*/.*/g; $p =~ s/\\\?/./g; $p =~ s/\\\[/[/g; $p =~ s/\\\]/]/g; return /$p/; } sub logout { my $logout; if ($skey) { $logout = "/fup?logout=skey:$skey" } elsif ($gkey) { $logout = "/fup?logout=gkey:$gkey" } elsif ($akey) { $logout = "/fup?logout=akey:$akey" } else { $logout = "/fup?logout" } return qqq(qq( '

' '

' ' ' '
' '

' )); } # print data dump of global or local variables in HTML # input musst be a string, eg: '%ENV' sub DD { my $v = shift; local $_; $n =~ s/.//; $_ = eval(qq(use Data::Dumper;Data::Dumper->Dump([\\$v]))); s/\$VAR1/$v/; s/&/&/g; s/\n$_\n

\n"; } # make symlink sub mksymlink { my ($file,$link) = @_; unlink $file; return symlink untaint($link),$file; } # copy file (and modify) or symlink # returns chomped file contents or link name # preserves permissions and time stamps sub copy { my ($from,$to,$mod) = @_; my $link; local $/; local $_; $to .= '/'.basename($from) if -d $to; if (defined($link = readlink $from)) { mksymlink($to,$link); return $link; } else { open $from,'<',$from or return; open $to,'>',$to or return; $_ = <$from>; close $from; eval $mod if $mod; print {$to} $_; close $to or http_die("internal error: $to - $!"); if (my @s = stat($from)) { chmod $s[2],$to; utime @s[8,9],$to; } chomp; return $_; } } sub slurp { my $file = shift; local $_; local $/; if (open $file,$file) { $_ = <$file>; close $file; } return $_; } # name based virtual host? sub vhost { my $hh = shift; # HTTP_HOST my $vhost; my $locale = $ENV{LOCALE}; # memorized vhost? (default is in fex.ph) %vhost = split(':',$ENV{VHOST}) if $ENV{VHOST}; if (%vhost and $hh and $hh =~ s/^([\w\.-]+).*/$1/) { if ($vhost = $vhost{$hh} and -f "$vhost/lib/fex.ph") { $ENV{VHOST} = "$hh:$vhost"; # memorize vhost for next run $ENV{FEXLIB} = $FEXLIB = "$vhost/lib"; $logdir = $spooldir = "$vhost/spool"; $docdir = "$vhost/htdocs"; if ($locale and -e "$vhost/locale/$locale/lib/fex.ph") { $ENV{FEXLIB} = $FEXLIB = "$vhost/locale/$locale/lib"; } require "$FEXLIB/fex.ph" or die "$0: cannot load $FEXLIB/fex.ph - $!"; $ENV{SERVER_NAME} = $hostname; return $vhost; } } } # extract locale functions into hash of subroutine references # e.g. \&german ==> $notify{german} sub locale_functions { my $locale = shift; local $/; local $_; if ($locale and open my $fexpp,"$FEXHOME/locale/$locale/lib/fex.pp") { $_ = <$fexpp>; s/.*\n(\#\#\# locale functions)/$1/s; # sub xx {} ==> xx{$locale} = sub {} s/\nsub (\w+)/\n\$$1\{$locale\} = sub/gs; s/\n}\n/\n};\n/gs; eval $_; close $fexpp; } } ### locale functions ### # will be extracted by install process and saved in $FEXHOME/lib/lf.pl # you cannot modify them here without re-installing! sub notify { # my ($status,$dkey,$filename,$keep,$warn,$comment,$autodelete) = @_; my %P = @_; my ($to,$from,$file,$mimefilename,$receiver,$warn,$comment,$autodelete); my ($size,$bytes,$days,$header,$data,$replyto); my ($mfrom,$mto,$dfrom,$dto); my $index; my $fileid = 0; my $fua = $ENV{HTTP_USER_AGENT}||''; my $warning = ''; my $download = ''; return if $nomail; $warn = $P{warn}||2; $comment = $P{comment}||''; $autodelete = $P{autodelete}||$::autodelete; $index = $durl; $index =~ s/fop/index.html/; (undef,$to,$from,$file) = split('/',untaint(readlink("$dkeydir/$P{dkey}"))); $filename = strip_path($P{filename}); $mfrom = $from; $mto = $to; $mfrom .= '@'.$mdomain if $mdomain and $mfrom !~ /@/; $mto .= '@'.$mdomain if $mdomain and $mto !~ /@/; $to = '' if $to eq $from; $replyto = $P{replyto}||$mfrom; $header = "From: <$mfrom> ($mfrom via F*EX service $hostname)\n". "Reply-To: <$replyto>\n". "To: <$mto>\n"; $data = "$dkeydir/$P{dkey}/data"; $size = $bytes = -s $data; return unless $size; $warning = "Please avoid download with Internet Explorer, ". "because it has too many bugs.\n". "We recommend Firefox or wget."; if ($filename =~ /\.(tar|zip|7z|arj|rar)$/) { $warning .= "\n\n". "$filename is a container file.\n". "You can unpack it for example with 7zip ". "(http://www.7-zip.org/download.html)"; } if ($limited_download =~ /^y/i) { $warning .= "\n\n". 'This download link only works for you, you cannot distribute it.'; } if ($size < 2048) { $size = "$size Bytes"; } elsif ($size/1024 < 2048) { $size = int($size/1024)." kB"; } else { $size = int($size/1024/1024)." MB"; } if ($autodelete eq 'YES') { $autodelete = "WARNING: After download (or view with a web browser!), " . "the file will be deleted!"; } elsif ($autodelete eq 'DELAY') { $autodelete = "WARNING: When you download the file it will be deleted " . "soon afterwards!"; } else { $autodelete = ''; } $mimefilename = $filename; if ($mimefilename =~ s{([_\?\=\x00-\x1F\x7F-\xFF])}{sprintf("=%02X",ord($1))}eog) { $mimefilename =~ s/ /_/g; $mimefilename = '=?UTF-8?Q?'.$mimefilename.'?='; } unless ($fileid = readlink("$dkeydir/$P{dkey}/id")) { my @s = stat($data); $fileid = @s ? $s[1].$s[9] : 0; } if ($P{status} eq 'new') { $days = $P{keep}; $header .= "Subject: F*EX-upload: $mimefilename\n"; } else { $days = $warn; $header .= "Subject: reminder F*EX-upload: $mimefilename\n"; } $header .= "X-FEX-Client-Address: $fra\n" if $fra; $header .= "X-FEX-Client-Agent: $fua\n" if $fua; foreach my $u (@durl) { my $durl = sprintf("%s/%s/%s",$u,$P{dkey},normalize_filename($filename)); $header .= "X-FEX-URL: $durl\n"; $download .= "$durl\n"; } $header .= "X-FEX-Filesize: $bytes\n". "X-FEX-File-ID: $fileid\n". "X-Mailer: F*EX\n". "MIME-Version: 1.0\n". "Content-Type: text/plain; charset=UTF-8\n". "Content-Transfer-Encoding: 8bit\n"; if ($comment =~ s/^\[(\@(.*?))\]\s*//) { $receiver = "group $1"; if ($_ = readlink "$from/\@GROUP/$2" and m:^../../(.+?)/:) { $receiver .= " (maintainer: $1)"; } } else { $receiver = 'you'; } if ($days == 1) { $days .= " day" } else { $days .= " days" } # explicite sender set in fex.ph? if ($sender_from) { map { s/^From: $mfrom/From: $sender_from/ } $header; open $sendmail,'|-',$sendmail,$mto,$bcc or http_die("cannot start sendmail - $!\n"); } else { # for special remote domains do not use same domain in From, # because remote MTA will probably reject this e-mail $dfrom = $1 if $mfrom =~ /@(.+)/; $dto = $1 if $mto =~ /@(.+)/; if ($dfrom and $dto and @remote_domains and grep { $dfrom =~ /(^|\.)$_$/ and $dto =~ /(^|\.)$_$/ } @remote_domains) { map { s/^From: $mfrom/From: $admin/ } $header; open $sendmail,'|-',$sendmail,$mto,$bcc or http_die("cannot start sendmail - $!\n"); } else { open $sendmail,'|-',$sendmail,'-f',$mfrom,$mto,$bcc or http_die("cannot start sendmail - $!\n"); } } print {$sendmail} $header,"\n"; if ($comment =~ s/^!(shortmail|\.)!\s*//i or (readlink "$to/\@NOTIFICATION"||'') =~ /short/i ) { pq($sendmail,qq( '$comment' '' '$download' '$size' )); } else { $comment = "Comment: $comment\n" if $comment; pq($sendmail,qq( '$from has uploaded the file' ' "$filename"' '($size) for $receiver. Use' '' '$download' 'to download this file within $days.' '' '$comment' '$autodelete' '$warning' '' 'F*EX is not an archive, it is a transfer system for personal files.' 'For more information see $index' '' 'Questions? ==> F*EX admin: $admin' )); } close $sendmail or $! and http_die("cannot send notification e-mail (sendmail error $!)\n"); } sub reactivation { my ($expire,$user) = @_; my $fexsend = "$FEXHOME/bin/fexsend"; return if $nomail; if (-x $fexsend) { $fexsend .= " -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"; # on error show STDOUT and STDERR system "$fexsend >/dev/null 2>&1"; if ($?) { warn "$fexsend\n"; system $fexsend; } } else { warn "$0: cannot execute $fexsend for reactivation()\n"; } } 1; fex-20130805/cgi-bin/0000755000174700017470000000000012177755050012223 5ustar fexfexfex-20130805/cgi-bin/pup0000755000174700017470000001054312126745460012756 0ustar fexfex#!/usr/bin/perl -wT # F*EX CGI for public upload # # Author: Ulli Horlacher # use CGI::Carp qw(fatalsToBrowser); # add fex lib (our $FEXLIB) = $ENV{FEXLIB} =~ /(.+)/; die "$0: no $FEXLIB\n" unless -d $FEXLIB; $| = 1; our $error = 'F*EX public upload ERROR'; our $head = "$ENV{SERVER_NAME} F*EX public upload"; our $locale = ''; # import from fex.ph our (@public_recipients); # import from fex.pp our ($FEXHOME); # load common code, local config: $FEXLIB/fex.ph require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n"; $from = $to = ''; chdir $spooldir or http_die("$spooldir - $!\n"); &check_maint; my $qs = $ENV{QUERY_STRING}; (my $multi) = $qs =~ s/(^|&)multi//; # parse HTTP QUERY_STRING (parameter=value pairs) if ($qs) { foreach (split '&',$qs) { if (s/^(\w+)=//) { my $x = $1; # decode URL-encoding s/%([a-f0-9]{2})/chr(hex($1))/gie; if (/([<>])/) { $_ = sprintf("\"&#%s;\" is not allowed in URL parameter",ord($1)); http_die($_); } setparam($x,$_); } } } # parse HTTP POST body if ($ENV{REQUEST_METHOD} eq 'POST') { if ($ENV{CONTENT_TYPE} =~ /boundary=\"?([\w\-\+\/_]+)/) { $boundary = $1; } else { http_die("malformed HTTP POST (no boundary found)"); } binmode(STDIN,':raw'); READPOST: while (&nvt_read) { if (/^Content-Disposition:\s*form-data;\s*name="([a-z]\w*)"/i) { my $x = $1; while (&nvt_read) { last if /^\s*$/ } &nvt_read; setparam($x,$_); NEXTPART: while (&nvt_read) { last READPOST if /^--\Q$boundary--/; last NEXTPART if /^--\Q$boundary/; } } } } unless (@public_recipients) { html_error($error,"No public recipients defined by administrator"); } if ($to and not grep /^\Q$to\E$/i,@public_recipients) { html_error($error,"$to is not a public recipient"); } if ($to and $from and checkaddress($from)) { nvt_print( "HTTP/1.1 302 Found", "Location: $ENV{PROTO}://$ENV{HTTP_HOST}/fup?from=$from&to=$to&id=PUBLIC", 'Content-Length: 0', "" ); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } http_header('200 ok'); print html_header($head); my @locales; foreach my $locale (glob "$FEXHOME/locale/*") { if (-f "$locale/cgi-bin/pup") { my $langf = "$locale/lang.html"; $locale =~ s:.*/::; $lang = $locale; if (open $langf,'<',$langf) { $lang = getline($langf); close $langf; } push @locales,"$lang"; } } print "

@locales

\n" if @locales > 1; pq(qq( '
' ' ' ' ' ' ' )); if ($from) { pq(qq( ' ' ' ' )); } else { pq(qq( ' ' )); } if ($to) { pq(qq( ' ' ' ' )); } else { if ($multi) { foreach my $pr (@public_recipients) { push @pr,qq() ."$pr
"; } pq(qq( ' ' )); } else { foreach my $pr (@public_recipients) { push @pr,""; } pq(qq( ' ' )); } } pq(qq( '
your e-mail address:$from
your e-mail address:
recipient:$to
recipient:@pr
recipient:
' '

' ' ' '

' )); # set parameter variables sub setparam { my ($v,$vv) = @_; $v = uc(despace($v)); if ($v eq 'LOCALE' and $vv =~ /^(\w+)$/) { $locale = $1; } elsif ($v eq 'FROM') { $from = lc(normalize(despace($vv))); $from =~ s:/:_:g; $from =~ s:^\.:_:; $from =~ s:\s::g; } elsif ($v eq 'TO') { $to = lc(normalize(despace($vv))); $to =~ s:/:_:g; $to =~ s:^\.:_:; } } # read one line from STDIN (net socket) and assign it to $_ # returns number of read bytes sub nvt_read { my $len = 0; if (defined ($_ = )) { debuglog($_); $len = length; s/\r?\n//; } return $len; } fex-20130805/cgi-bin/sex0000755000174700017470000001275612150350402012742 0ustar fexfex#!/usr/bin/perl -wT # CGI for stream exchange # # Author: Ulli Horlacher use Fcntl qw':flock :seek :mode'; use POSIX qw'mkfifo'; use Digest::MD5 qw'md5_hex'; # add fex lib (our $FEXLIB) = $ENV{FEXLIB} =~ /(.+)/; die "$0: no $FEXLIB\n" unless -d $FEXLIB; $| = 1; # import from fex.pp our ($tmpdir,$logdir,$timeout,$fra,$bs); # load common code, local config: $HOME/lib/fex.ph require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n"; chdir $spooldir or error(500,"$spooldir - $!"); my $debuglog = "$tmpdir/sex.log"; my $ra = $ENV{REMOTE_ADDR}||0; $fra .= '/'.$ENV{HTTP_X_FORWARDED_FOR} if $ENV{HTTP_X_FORWARDED_FOR}; $timeout *= 10; # normal / public : # in normal mode the recipient needs authentification, not the sender # in public mode the sender needs authentification, not the recipient $user = $id = $pmode = $type = ''; $stream = 'STDSTR'; $mode = $ENV{REQUEST_METHOD} eq 'POST' ? 'PUSH' : 'POP'; # parse HTTP QUERY_STRING if (my $qs = $ENV{QUERY_STRING}) { $qs = decode_b64($qs) if $qs =~ /^\w+=*$/; foreach (split '&',$qs) { setparam(split '=',"$_=") }; } unless ($user) { error(400,"Missing user") } if ($mdomain and $user !~ /@/) { $user .= '@'.$mdomain } if ($user =~ /^anonymous/) { if (@anonymous_upload and ipin($ra,@anonymous_upload)) { mkdirp($user); } else { error(403,"Forbidden"); } } else { unless (-f "$user/@") { error(404,"Unknown user $user") } } chdir $user or error(500,"$user - $!"); $stream = "STREAM/$stream"; if ($mode eq 'PUSH') { if ($pmode eq 'PUBLIC') { &authentificate; $stream =~ s:/STDSTR:/PUBLIC:; } mkdirp($stream); my $fifo = "$stream/fifo"; unless (-p $fifo) { mkfifo($fifo,0600) or error(503,"Cannot create $fifo : $!"); } my $lock = "$stream/lock"; open $lock,'>>',$lock or error(503,"Cannot open $lock : $!"); flock $lock,LOCK_EX|LOCK_NB or error(409,"$stream already in use"); chmod 0600,$fifo; unlink "$stream/mode"; unlink "$stream/type"; symlink $pmode,"$stream/mode" if $pmode; symlink $type, "$stream/type" if $type; $SIG{PIPE} = sub { sleep 1; rmrf($stream); exit; }; $SIG{ALRM} = sub { syswrite STDOUT,"."; exit if $!; $ALARM = 1; }; syswrite STDOUT,"HTTP/1.9 199 Hold on"; for (my $i=0;$i<$timeout;$i++) { alarm(1); $ALARM = 0; # will hang until $stream is opend for reading by another process open $fifo,'>',$fifo and last; unless ($ALARM) { error(503,"Cannot open $fifo : $!") } } alarm(0); syswrite STDOUT,"\r\n"; unless (fileno $fifo) { rmrf($stream); error(504,"Timeout"); } header('200 OK'); sexlog($mode); $SIG{PIPE} = sub { sleep 1; rmrf($stream); exit; }; # syswrite $fifo,$data if $data; while (sysread(STDIN,$_,$bs)) { syswrite $fifo,$_; } rmrf($stream); exit; } elsif ($mode eq 'POP') { $stream =~ s:/STDSTR:/PUBLIC: if $id eq 'public'; unless ($id eq 'public' and (readlink "$stream/mode"||'') eq 'PUBLIC' or $user =~ /^anonymous/) { &authentificate; } error(503,"No $stream for $user") unless -d $stream; $type = readlink "$stream/type" || ''; $SIG{ALRM} = sub { error(504,"Timeout") }; alarm($timeout); my $fifo = "$stream/fifo"; if (-e $fifo and not -r $fifo) { error(503,"$stream already in use") } open $fifo,'<',$fifo or error(503,"Cannot open $fifo : $!"); chmod 0,$fifo; alarm(0); header('200 OK',$type); sexlog($mode); while (sysread($fifo,$_,$bs)) { syswrite STDOUT,$_; } exit; } else { error(405,"Unknown Request"); } exit; sub setparam { my ($v,$vv) = @_; $v = uc(despace($v)); $vv = untaint(normalize($vv)); # $param{$v} = $vv; if ($v eq 'USER') { $user = lc(despace($vv)) } elsif ($v eq 'ID') { $id = despace($vv) } elsif ($v eq 'MODE') { $pmode = uc(despace($vv)) } elsif ($v eq 'TYPE') { $type = uc(despace($vv)) } elsif ($v eq 'STREAM') { $stream = normalize_filename($vv) } elsif ($v eq 'BS' and $vv =~ /(\d+)/) { $bs = $1 } elsif ($v eq 'TIMEOUT' and $vv =~ /(\d+)/) { $timeout = $1 } elsif ($v eq 'ANONYMOUS') { $id = $user ='anonymous'; $stream = $vv; } } sub sexlog { if (open my $log,'>>',"$logdir/sex.log") { flock $log,LOCK_EX; seek $log,0,SEEK_END; printf {$log} "%s [%s_%s] %s (%s) %s\n", isodate(time),$$,$ENV{REQUESTCOUNT},$user,$fra,"@_"; close $log; } } sub sigdie { local $_ = shift; chomp; sigexit('DIE',$_); } sub sigexit { my ($sig) = @_; if (open my $log,'>>',"$logdir/sex.log") { printf {$log} "%s %s (%s) caught SIGNAL %s\n", isodate(time),$user||'-',$fra||'-',"@_"; close $log; } if ($sig eq 'DIE') { shift; die "@_\n"; } else { die "SIGNAL @_\n"; } } sub error { nvt_print("HTTP/1.1 @_"); exit; } sub header { my ($status,$type) = @_; return if $HTTP_HEADER; $HTTP_HEADER = $status; nvt_print("HTTP/1.1 $status"); if ($mode eq 'POP') { nvt_print("Server: sexsrv"); if ($type eq 'GZIP') { nvt_print("Content-Type: application/gzip"); } else { nvt_print("Content-Type: application/binary"); } nvt_print("Expires: 0"); nvt_print("Cache-Control: no-cache"); nvt_print("Connection: close"); } nvt_print(""); } sub authentificate { my $rid; error(400,"Missing auth-ID") unless $id; open $id,'<','@' or error(401,"$user/@ - $!"); chomp($rid = <$id>||''); close $id; if ($rid and $sid and $id =~ /^(MD5H:)/) { $rid = $1 . md5_hex($rid.$sid); } error(401,"Wrong auth-ID") if $rid ne $id; } fex-20130805/cgi-bin/fuc0000755000174700017470000006473312156015134012730 0ustar fexfex#!/usr/bin/perl -wT # FEX CGI for user control # (subuser, groups, address book, one time upload key, auth-ID) # # Author: Ulli Horlacher # use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); use Fcntl qw(:flock); use Digest::MD5 qw(md5_hex); # add fex lib ($FEXLIB) = $ENV{FEXLIB} =~ /(.+)/; die "$0: no $FEXLIB\n" unless -d $FEXLIB; # import from fex.pp our ($FEXHOME); our ($mdomain,$admin,$hostname,$sendmail,$akeydir,$skeydir,$docdir,$durl,$bcc); our ($nomail,$faillog); our $akey = ''; # load common code, local config : $HOME/lib/fex.ph require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n"; my ($CASE,$ESAC); my $error = 'F*EX user config ERROR'; my $head = "$ENV{SERVER_NAME} F*EX user config"; my $fup = $durl; $fup =~ s:/fop:/fup:; chdir $spooldir or die "$spooldir - $!\n"; my $user = my $id = my $nid = my $ssid = my $comment = ''; my $notification = my $reminder = ''; my $qs = $ENV{QUERY_STRING}; if ($qs) { if ($qs =~ /akey=(\w+)/i) { $akey = $1 } if ($qs =~ /ab=load/) { $ab = 'load' } } # look for CGI POST parameters foreach my $v (param) { my $vv = param($v); debuglog("Param: $v=\"$vv\""); $CASE = $v =~ /^user$/i ? $user = fuc_normalize(lc $vv): $v =~ /^subuser$/i ? $subuser = fuc_normalize(lc $vv): $v =~ /^otuser$/i ? $otuser = fuc_normalize(lc $vv): $v =~ /^notify$/i ? $notify = fuc_normalize(lc $vv): $v =~ /^notification$/i ? $notification = $vv: $v =~ /^reminder$/i ? $reminder = $vv: $v =~ /^comment$/i ? $comment = decode_utf8(normalize($vv)): $v =~ /^id$/i ? $id = $vv: $v =~ /^nid$/i ? $nid = $vv: $v =~ /^ssid$/i ? $ssid = $vv: $v =~ /^group$/i ? $group = fuc_normalize($vv): $v =~ /^ab$/i ? $ab = $vv: $v =~ /^gm$/i ? $gm = $vv: $v =~ /^show$/i ? $tools = $vv: $ESAC; } $group = lc $group if $group and $group ne 'NEW'; $group = '' if $nomail; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; if ($akey) { # sid is not set with web browser my $idf = "$akeydir/$akey/@"; if (open $akey,'<',$idf and $id = getline($akey)) { close $akey; $idf =~ /(.*)\/\@/; $user = readlink $1 or http_die("internal server error: no $akey symlink $1"); $user =~ s:.*/::; $user = untaint($user); if ($akey ne md5_hex("$user:$id")) { $user = $id = ''; } } } &check_status($user) if $user; if ($user and $akey and $qs and $qs =~ /info=(.+?)&skey=(.+)/) { $subuser = $1; $skey = $2; notify_subuser($user,$subuser,"$fup?skey=$skey",$comment); http_header("200 OK"); print html_header($head); pq(qq( 'An information e-mail has been sent to your subuser $subuser' '

Go back' '' )); exit; } if ($user and $id) { if (-e "$user/\@CAPTIVE") { html_error($error,"captive user") } unless (open $idf,'<',"$user/@") { faillog("user $from, id $id"); html_error($error,"wrong user or auth-ID"); } $rid = getline($idf); close $idf; if ($id eq $rid) { unless ($akey) { $akey = untaint(md5_hex("$user:$id")); unlink "$akeydir/$akey"; symlink "../$user","$akeydir/$akey"; } } else { faillog("user $from, id $id"); html_error($error,"wrong user or auth-ID"); } } else { my $login = -x "$FEXHOME/login" ? 'login' : 'fup'; nvt_print( "HTTP/1.1 302 Found", "Location: $ENV{PROTO}://$ENV{HTTP_HOST}/$login", 'Expires: 0', 'Content-Length: 0', '' ); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } # 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)) { nvt_print( "HTTP/1.1 302 Found", "Location: $ENV{PROTO}://$ENV{HTTP_HOST}/foc", 'Expires: 0', 'Content-Length: 0', '' ); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } unlink $faillog if $faillog; http_header("200 OK"); print html_header($head); # foreach $v (keys %ENV) { print $v,' = "',$ENV{$v},"\"
\n" }; if ($gm and not $group) { pq(qq( '

ERROR: no group name specified

' '' )); 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; } # create one time upload key if ($subuser and $otuser) { $otuser = $subuser; if ($otuser !~ /^[^@]+@[\w.-]+[a-z]$/) { pq(qq( '$otuser is not a valid e-mail address' '

Go back' '' )); exit; } my $okey = randstring(8); my $okeyd = "$user/\@OKEY"; mkdir $okeyd; symlink $otuser,"$okeyd/$okey" or http_die("cannot create OKEY $okeyd/$okey : $!\n"); my $url = "$fup?to=$user&okey=$okey"; pq(qq( 'A one time upload URL for $otuser has been created:' '

' '$url' )); unless ($nomail) { ¬ify_otuser($user,$otuser,$url,$comment); pq(qq( '

' 'and an information e-mail has been sent to this address.' '

' )); } print "\n"; exit; } # direct single subuser entry if ($subuser and not $otuser) { if (-f "$subuser/@") { pq(qq( '$subuser is already a registered F*EX full user' '

Go back' '' )); exit; } if ($subuser !~ /^[^@]+@[\w.-]+[a-z]$/) { pq(qq( '$subuser is not a valid e-mail address' '

Go back' '' )); exit; } $skey = ''; if (open $idf,'<',"$user/\@SUBUSER") { while (<$idf>) { chomp; if (/^\Q$subuser:/) { $skey = md5_hex("$user:$_"); last; } } close $idf; } if ($skey) { my $url = "$fup?skey=$skey"; if ($nomail) { pq(qq( '$subuser is already your subuser and has access URL:' '

' '$url' )); } else { pq(qq( '$subuser' 'is already your subuser and has access URL:' '

' '$url' '

' "Click on the subuser's e-mail address link to send him an" "information e-mail by the F*EX server.

" )); } } else { my $sid = randstring(8); my $skey = mkskey($user,$subuser,$sid); $url = "$fup?skey=$skey"; open $idf,'>>',"$user/\@SUBUSER" or die "$user/\@SUBUSER - $!\n"; print {$idf} "$subuser:$sid\n"; close $idf; pq(qq( 'Your subuser upload URL is:' '

' '$url' )); unless ($nomail) { ¬ify_subuser($user,$subuser,$url,$comment); pq(qq( '

' 'An information e-mail has been sent to $subuser' )); } } print "\n"; exit; } # modify addressbook if ($user and $akey and defined $ab) { if ($ab eq 'load') { $ab = ''; if (open $ab,'<',"$user/\@ADDRESS_BOOK") { undef $/; $_ = <$ab>; s/\s*$/\n/; close $ab; $ab = $_; } my $rows = ($ab =~ tr/\n//) + 5; pq(qq( '

Edit address book

' '' ' ' ' ' '
Entry:aliase-mail address# optional comment
Example:Framstagframstag\@rus.uni-stuttgart.de# Ulli Horlacher
' '
' '
' ' ' '
' '

' 'You may use these alias names as F*EX recipient addresses on ' 'fup' '

' 'Alternatively you can fex a file ADDRESS_BOOK to yourself ' '($user) containing your alias definitions.' '

' 'back to F*EX operation control' '' )); } else { $ab =~ s/[\r<>]//g; $ab =~ s/\s*$/\n/; foreach (split(/\n/,$ab)) { s/^\s+//; s/\s+$//; if (s/\s*(#.*)//) { $comment = $1 } else { $comment = '' } next if /^\s*$/; @options = (); push @options,$1 if s/(autodelete=\w+)//i; push @options,$1 if s/(keep=\d+)//i; s/[,\s]+$//; if (s/([\S]+)\s+(\S+)//) { $alias = $1; $address = $2; $options = join(',',@options); push @abt,"$alias$address$options$comment\n"; } else { push @badalias,$_; } } if (@badalias) { print "

ERROR: bad aliases:

\n
    "; foreach my $ba (@badalias) { print "
  • $ba" } pq(qq( '
' '

' 'Not in format: alias e-mail-address' '

' 'Go back' '' )); exit; } open my $AB,'>',"$user/\@ADDRESS_BOOK" or http_die("cannot open $user/\@ADDRESS_BOOK - $!\n"); print {$AB} $ab; close $AB; pq(qq( '

address book

' '' '' '@abt' '
aliase-mail addressoptionscomment
' '

' 'back to F*EX operation control' '

' 'back to fup (F*EX upload)' '' )); } exit; } if ($user and $notification eq 'detailed') { unlink "$user/\@NOTIFICATION"; pq(qq( '

Notification e-mails now come in detailed format.

' '

' 'back to F*EX operation control' '' )); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit: } if ($user and $notification eq 'short') { unlink "$user/\@NOTIFICATION"; symlink "short","$user/\@NOTIFICATION"; pq(qq( '

Notification e-mails now come in short format.

' '

' 'back to F*EX operation control' '' )); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit: } if ($user and $reminder eq 'yes') { unlink "$user/\@REMINDER"; pq(qq( '

You will now get reminder notification e-mails.

' '

' 'back to F*EX operation control' '' )); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit: } if ($user and $reminder eq 'no') { unlink "$user/\@REMINDER"; symlink "no","$user/\@REMINDER"; pq(qq( '

You will now get no reminder notification e-mails.

' '

' 'back to F*EX operation control' '' )); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit: } if ($nid) { $nid =~ s/^\s+//; $nid =~ s/\s+$//; checkchars('auth-ID',$nid); $nid = randstring(6) if $nid eq '?'; open $idf,'>',"$user/@" or die "$user/@ - $!\n"; print {$idf} $nid,"\n"; close $idf; $akey = untaint(md5_hex("$user:$nid")); unlink "$akeydir/$akey"; symlink "../$user","$akeydir/$akey"; pq(qq( '

new auth-ID "$nid" for $user saved

' 'back to F*EX operation control' '' )); exit; } # empty subuser list POST if (defined(param('ssid')) and $ssid =~ /^\s*$/) { unlink "$user/\@SUBUSER"; pq(qq( '

All subusers deleted

\n
    ' 'back to F*EX operation control' '' )); exit; } # update sub-users if ($ssid) { my ($subuser,$subid,$skey); # delete old skeys if (open $idf,'<',"$user/\@SUBUSER") { while (<$idf>) { s/#.*//; if (/(.+\@.+):(.+)/) { ($subuser,$subid) = ($1,$2); $skey = md5_hex("$user:$subuser:$subid"); unlink "$skeydir/$skey"; unlink "$subuser/\@MAINUSER/$user"; } } close $idf; } $ssid = strip($ssid); # collect (new) subusers foreach (split("\n",$ssid)) { s/#.*//; s/\s//g; if (/(.+\@[\w.-]+)/) { $subuser = lc $1; push @badaddress,$subuser unless checkaddress($subuser); } } if (@badaddress) { print "

    ERROR: bad addresses:

    \n
      "; foreach my $ba (@badaddress) { print "
    • $ba" } pq(qq( '
    ' 'Go back' '' )); exit; } if ($ssid =~ /\S\@\w/) { open $idf,'>',"$user/\@SUBUSER" or die "$user/\@SUBUSER - $!\n"; print "Your subusers upload URLs are:

    \n"; print "\n"; foreach (split("\n",$ssid)) { s/#.*//; s/\s//g; if (/(\S+\@[\w.-]+)/) { $subuser = lc $1; if (/:(.+)/) { $subid = $1 } else { $subid = randstring(8) } print {$idf} "$subuser:$subid\n"; $skey = mkskey($user,$subuser,$subid); print " \n"; } } pq(qq( "
    $subuser :", "$fup?skey=$skey
    \n

    " "You have to give these URLs to your subusers for fexing files to you." "
    " "Or click on the subuser's e-mail address link to send him an" "information e-mail by the F*EX server.

    " )); } print "back to F*EX operation control\n"; print "\n"; close $idf; exit; } if (open my $subuser,'<',"$user/\@SUBUSER") { local $/; $ssid = <$subuser> || ''; close $subuser; } # display HTML form and request user data pq(qq( '

    ' )); # pq(qq( # ' ' # ' ' # ' Your F*EX account: $user:$id

    ' # ' New auth-ID: ' # ' (Remember your auth-ID when you change it!)' # )); if (-s "$user/\@ALLOWED_RECIPIENTS") { pq(qq( '

    ' ' ' '

    ' '' )); exit; } $ssid = strip($ssid) if $ssid; pq(qq( '


    ' ' Allow special senders (= subusers) to fex files to you:
    ' '
    ' ' ' '' '

    ' '' ' ' ' ' '
    This list has entries in format:<e-mail address>:<encryption-ID>
    Example:framstag\@rus.uni-stuttgart.de:schwuppdiwupp
    ' '

    ' 'These special senders may fex files only to you!
    ' 'It is not necessary to add regular fex users to your list,' 'because they already can fex.' '

    ' 'The encryption-ID is necessary to generate a unique upload URL for this subuser.
    ' 'If you omit the encryption-ID a random one will be used.' )); unless ($nomail) { pq(qq( '


    ' '

    ' 'Edit your F*EX groups:

    ' '
      ' )); foreach $group (glob "$user/\@GROUP/*") { if (-f $group and not -l $group and $group !~ /~$/) { $group =~ s:.*/::; print "
    • \@$group\n"; } } pq(qq( '
    • new group' '
    ' )); } pq(qq( '


    ' 'back to F*EX operation control' '' )); exit; sub strip { local $_ = shift; s/[ \t]+//g; s/\s*[\r\n]+\s*/\n/g; return $_; } sub notify_otuser { my ($user,$otuser,$url,$comment) = @_; my $server = $hostname || $mdomain; my $sf; return if $nomail; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; $sf = $sender_from ? $sender_from : $user; open my $mail,'|-',$sendmail,'-f',$sf,$otuser,$bcc or http_die("cannot start sendmail - $!\n"); pq($mail,qq( 'From: $sf ($user via F*EX service $server)' 'To: $otuser' 'Subject: Your upload URL' 'X-Mailer: F*EX' '' 'This is an automatically generated e-mail.' '' 'Use' '' '$url' '' 'to upload one file to $user' '' '$comment' '' 'Questions? ==> F*EX admin: $admin' )); close $mail or http_die("cannot send notification e-mail (sendmail error $!)\n"); } sub notify_subuser { my ($user,$subuser,$url,$comment) = @_; my $server = $hostname || $mdomain; my $sf; return if $nomail; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; $sf = $sender_from ? $sender_from : $user; open my $mail,'|-',$sendmail,'-f',$sf,$subuser,$user,$bcc or http_die("cannot start sendmail - $!\n"); pq($mail,qq( 'From: $sf ($user via F*EX service $server)' 'To: $subuser' 'Cc: $user' 'Subject: Your F*EX account on $server' 'X-Mailer: F*EX' '' 'This is an automatically generated e-mail.' '' 'A F*EX (File EXchange) account has been created for you on $server' 'Use' '' '$url' '' 'to upload files to $user' '' 'See http://$ENV{HTTP_HOST}/index.html for more information about F*EX.' '' '$comment' '' 'Questions? ==> F*EX admin: $admin' )); close $mail or http_die("cannot send notification e-mail (sendmail error $!)\n"); } sub notify_groupmember { my ($user,$gm,$group,$id,$url) = @_; my $server = $hostname || $mdomain; my $sf; $user .= '@'.$mdomain if $mdomain and $user !~ /@/; $sf = $sender_from ? $sender_from : $user; open my $mail,'|-',$sendmail,'-f',$sf,$gm,$user,$bcc or http_die("cannot start sendmail - $!\n"); pq($mail,qq( 'From: $sf ($user via F*EX service $hostname)' 'To: $gm' 'Cc: $user' 'Subject: Your F*EX account on $server' 'X-Mailer: F*EX' '' 'A F*EX (File EXchange) account has been created for you on $server' 'Use' '' '$url' '' 'to upload files to F*EX group "$group"' '' 'See http://$ENV{HTTP_HOST}/ for more information about F*EX.' '' 'Questions? ==> F*EX admin: $admin' )); close $mail or http_die("cannot send notification e-mail (sendmail error $!)\n"); } sub fuc_normalize { local $_ = shift; s/\s//g; s/[^\w_.+=\@\-]//g; s/^\./_/; /(.*)/; return $1; } sub mkskey { my ($user,$subuser,$id) = @_; my $skey = md5_hex("$user:$subuser:$id"); open my $skf,'>',"$skeydir/$skey" or die "$skeydir/$skey - $!\n"; print {$skf} "from=$subuser\n", "to=$user\n", "id=$id\n"; close $skf or die "$skeydir/$skey - $!\n"; mkdirp("$subuser/\@MAINUSER"); symlink $skey,"$subuser/\@MAINUSER/$user"; return $skey; } sub mkgkey { my ($user,$group,$gm,$id) = @_; my $gkey = md5_hex("$user:$group:$gm:$id"); open my $gkf,'>',"$gkeydir/$gkey" or die "$gkeydir/$gkey - $!\n"; print {$gkf} "from=$gm\n", "to=\@$group\n", "user=$user\n", "id=$id\n"; close $gkf or die "$gkeydir/$gkey - $!\n"; return $gkey; } sub handle_group { my ($gf,$gd,$gl,$gid,$gkey); $group =~ s/^@+//; # $notify is group member if ($notify) { $gf = "$notify/\@GROUP/$group"; unless ($_ = readlink $gf) { pq(qq( '

    ERROR: cannot read $gf - $!

    ' '' )); exit; } if (m{([^/]+\@[\w.-]+)/}) { $user = lc $1; } else { pq(qq( '

    INTERNAL ERROR: groupfile = $gf

    ' '' )); exit; } if (open $gf,'<',$gf) { while (<$gf>) { if (/\Q$notify\E:(\S+)/i) { $gid = $1; last; } } close $gf; } else { pq(qq( '

    ERROR: cannot open $gf - $!

    ' '' )); exit; } unless ($gid) { pq(qq( '

    ERROR: $notify not found in $gf

    ' '' )); exit; } $gkey = md5_hex("$user:$group:$notify:$gid"); notify_groupmember( $user, $notify, $group, $gid, # "$ENV{PROTO}://$ENV{HTTP_HOST}/fup?from=$notify&to=\@$group" "$fup?gkey=$gkey" ); pq(qq( '

    Notification e-mail to $notify has been sent

    ' '

    Go back' '' )); exit; } $gf = "$user/\@GROUP/$group"; if (defined $gm) { if ($gm =~ /\S/) { foreach (split /\n/,$gm) { s/#.*//; s/\s//g; next if /^\w+=./; next if /^$/; if (s/:.+//) { if (/(.+@[\w\.-]+)/ and checkaddress($_)) { push @gm,lc $1; } else { push @badaddress,$_; } } else { push @badformat,$_; } } if (@badformat) { print "

    ERROR: lines not in format <e-mail address>:<encryption-ID>

    \n
      "; foreach my $ba (@badformat) { print "
    • $ba" } print "
    \n"; } if (@badaddress) { print "

    ERROR: bad addresses:

    \n
      "; foreach my $ba (@badaddress) { print "
    • $ba" } print "
    \n"; } if (@badformat or @badaddress) { pq(qq( 'Go back' '' )); exit; } $gd = "$user/\@GROUP"; unless (-d $gd or mkdir $gd,0700) { print "

    ERROR: cannot create $gd - $!

    \n"; print "\n"; exit; } if (-l $gf) { if ($_ = readlink $gf and m{([^/]+\@[\w.-]+)/}) { $user = $1; pq(qq( '

    ERROR: you are already in group \@$group owned by $user

    ' 'Go back' 'and enter another group name' '' )); } else { print "

    INTERNAL ERROR: $gf is a symlink. but not readable

    \n"; print "\n"; } exit; } # delete old gkeys if (open $gf,'<',$gf) { # delete old group links and gkeys while (<$gf>) { s/#.*//; if (/(.+\@.+):(.+)/) { $gkey = md5_hex("$user:$group:$1:$2"); unlink "$gkeydir/$gkey"; unlink "$1/\@GROUP/$group" if -l "$1/\@GROUP/$group"; } } close $gf; } # write new group file and gkeys if (open $gf,'>',$gf) { $gm =~ s/[\r\n]+/\n/g; foreach (split /\n/,$gm) { print {$gf} "$_\n"; s/#.*//; s/\s//g; if (/^\s*([^\/]+):(.+)/) { mkgkey(lc $user,$group,lc $1,$2); } } close $gf; } else { print "

    ERROR: cannot write $gf - $!

    \n"; print "\n"; exit; } if (@gm) { foreach $gm (@gm) { next if $gm eq $user; unless (-d $gm or mkdir $gm,0700) { print "

    ERROR: cannot create $gm - $!

    \n"; print "\n"; exit; } $gd = "$gm/\@GROUP"; unless (-d $gd or mkdir $gd,0700) { print "

    ERROR: cannot create $gd - $!

    \n"; print "\n"; exit; } $gl = "$gm/\@GROUP/$group"; unless (-l $gl or symlink "../../$user/\@GROUP/$group",$gl) { print "

    ERROR: cannot create $gl - $!

    \n"; print "\n"; exit; } } pq(qq( '

    Group \@$group has members:

    ' '
      ' )); foreach $gm (@gm) { if ($gm ne $user) { print "
    • $gm\n"; } } pq(qq( '
    ' '(click address to send a notification e-mail to this user)' )); } else { print "

    Group \@$group has no members

    \n"; } pq(qq( '

    ' 'back to F*EX operation control' )); print end_html(); exit; } else { # no group members -> delete group file unlink $gf; } } else { $gm = ''; pq(qq( '

    Edit F*EX group

    ' 'A F*EX group is similar to a mailing list, but for files:
    ' 'When a member fexes a file to this list, ' 'then all other members will receive it.' '

    ' '

    ' )); if ($group eq 'NEW') { pq(qq( ' ' ' New group name: (You MUST fill out this field!)' ' ' )); } else { if (open $gf,'<',$gf) { local $/; $gm = <$gf>||''; } close $gf; pq(qq( ' ' ' F*EX group \@$group:' )); } my $rows = ($gm =~ tr/\n//) + 5; pq(qq( '

    ' ' ' '
    ' '

    ' '' ' ' ' ' '
    This list must have entries in format:<e-mail address>:<encryption-ID>
    Example:framstag\@rus.uni-stuttgart.de:schwuppdiwupp
    ' '

    ' 'The encryption-ID is necessary to generate a unique upload URL for this subuser.' 'You can name any existing e-mail address.' )); if (open my $ab,'<',"$user/\@ADDRESS_BOOK") { pq(qq( "


    " "

    Your address book:

    " "
    "
          ));
          while (<$ab>) {
            s/#.*//;
            print "$1\n" if /([\S]+\@[\S]+)/;
          }
          close $ab;
          print "
    \n"; } print "\n"; exit; } } fex-20130805/cgi-bin/fop0000755000174700017470000006661212172214032012731 0ustar fexfex#!/usr/bin/perl -wT # F*EX CGI for download # # Author: Ulli Horlacher # use CGI qw':standard'; use CGI::Carp qw'fatalsToBrowser'; use Fcntl qw':flock :seek'; use Cwd qw'abs_path'; use File::Basename; use IO::Handle; use Encode; # add fex lib ($FEXLIB) = $ENV{FEXLIB} =~ /(.+)/; die "$0: no $FEXLIB\n" unless -d $FEXLIB; our $error = 'F*EX download ERROR'; our $head = "$ENV{SERVER_NAME} F*EX download"; # import from fex.pp our ($spooldir,$tmpdir,$logdir,$skeydir,$dkeydir,$durl); our ($bs,$fop_auth,$timeout,$keep_default); our ($limited_download,$admin,$akey,$adlm,$amdl); our (@file_link_dirs); # load common code, local config : $HOME/lib/fex.ph require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n"; my $ra = $ENV{REMOTE_ADDR}||0; if (@download_hosts and not ipin($ra,@download_hosts)) { http_die( "Downloads from your host ($ra) are not allowed.", "Contact $ENV{SERVER_ADMIN} for details." ); } &check_maint; # call localized fop if available if ($0 !~ m{/locale/.*/fop} and my $lang = $ENV{HTTP_ACCEPT_LANGUAGE}) { if ($lang =~ /^de/ and $0 =~ m{(.*)/cgi-bin/fop}) { my $fop = "$1/locale/deutsch/cgi-bin/fop"; exec $fop if -x $fop; } } my $log = "$logdir/fop.log"; chdir $spooldir or die "$spooldir - $!\n"; my $http_client = $ENV{HTTP_USER_AGENT} || ''; $file = $ENV{PATH_INFO} || ''; http_die('no file name') unless $file; $file =~ s:%3F:/?/:g; # escape '?' for URL-decoding $file =~ s/%([\dA-F]{2})/unpack("a",pack("H2",$1))/ge; $file =~ s:/\?/:%3F:g; # deescape '?' $file =~ s:/\.\.:/__:g; $file =~ s:^/+::; $file = untaint($file); # secure mode with HTTP authorization? if ($fop_auth) { @http_auth = (); if ($ENV{HTTP_AUTHORIZATION} and $ENV{HTTP_AUTHORIZATION} =~ /Basic\s+(.+)/) { @http_auth = split(':',decode_b64($1)); } if (@http_auth != 2) { &require_auth; } &check_auth($file,@http_auth); } # download-URL-scheme /$dkey/$file ? if ($file =~ m:^([^/]+)/[^/]+$:) { $dkey = $1; if ($link = readlink("$dkeydir/$dkey")) { if ($link !~ s:^\.\./::) { http_die("internal error on dkey for $link"); } $file = untaint($link); } else { http_die("no such file $file"); } } else { $file =~ s/\?.*//; # add mail-domain to addresses if necessary if ($mdomain and $file =~ s:(.+)/(.+)/(.+):$3:) { $to = lc $1; $from = lc $2; $to .= '@'.$mdomain if -d "$to\@$mdomain"; $from .= '@'.$mdomain if -d "$from\@$mdomain"; $file = "$to/$from/$file"; } } # afex! if ($file and $file =~ m:(.+)/(.+)/.+:) { $to = $1; $from = $2; if ($from =~ s/^(anonymous).*/$1/) { if (@anonymous_upload and ipin($ra,@anonymous_upload) or $dkey) { $anonymous = $from; } else { http_header('403 Forbidden'); print html_header($head), "You have no permission to request the URI $ENV{REQUEST_URI}\n", "\n"; exit; } } } else { http_die("unknown query format"); } $data = "$file/data"; # request with ?query-parameter ? if ($qs = $ENV{QUERY_STRING}) { http_die("\"$1\" is not allowed in URL") if $qs =~ /([<>%])/; # workaround for broken F*IX $qs =~ s/&ID=skey:\w+//; # subuser with skey? if ($qs =~ s/&*SKEY=([\w:]+)//i) { $skey = $1; # encrypted skey? if ($skey =~ s/^MD5H:(.+)/$1/) { # lookup real skey foreach my $s (glob "$skeydir/*") { $s =~ s:.*/::; if ($skey eq md5_hex($s.$ENV{SID})) { $skey = $s; last; } } } if (open $skey,'<',"$skeydir/$skey") { $from = $to = ''; while (<$skey>) { $from = lc($1) if /^from=(.+)/; $to = lc($1) if /^to=(.+)/; } close $skey; if ($from and $to) { $file =~ s:.*/:$to/$from/:; } else { http_die("INTERNAL ERROR: missing data in $skeydir/$skey"); } } else { debuglog("SKEY=$skey"); http_die("wrong SKEY authentification"); } } # group member with gkey? if ($qs =~ s/&*GKEY=([\w:]+)//i) { $gkey = $1; # encrypted gkey? if ($gkey =~ s/^MD5H:(.+)/$1/) { # lookup real gkey foreach my $g (glob "$gkeydir/*") { $g =~ s:.*/::; if ($gkey eq md5_hex($g.$ENV{SID})) { $gkey = $g; last; } } } if (open $gkey,'<',"$gkeydir/$gkey") { $from = $to = ''; while (<$gkey>) { $from = lc($1) if /^from=(.+)/; $group = lc($1) if /^to=\@(.+)/; } close $gkey; if ($from and $group and open $group,'<',"$from/\@GROUP/$group") { while (<$group>) { s/#.*//; s/\s//g; if (/(.+):/) { my $to = $1; $file =~ s:.*/:$to/$from/:; last; } } close $group; } else { http_die("INTERNAL ERROR: missing data in $gkeydir/$gkey"); } } else { debuglog("GKEY=$gkey"); http_die("wrong GKEY authentification"); } } # regular user: check for ID in query elsif ($qs =~ s/\&*\bID=([^&]+)//i) { $id = $1; $fop_auth = 0; if ($file =~ m:^(.+)/(.+)/(.+):) { $to = $1; $from = $2; $to =~ s/,+/,/g; $to =~ s/\s//g; $from =~ s/\s//g; if ($from ne 'anonymous') { $to .= '@'.$mdomain if $mdomain and $to !~ /@/; $from .= '@'.$mdomain if $mdomain and $from !~ /@/; } $to = lc $to; $from = lc $from; } else { http_die("unknown file query format"); } if (-e "$to/\@CAPTIVE") { http_die("$to is CAPTIVE"); } # public or anonymous recipient? (needs no auth-ID for sender) if ($anonymous or $id eq 'PUBLIC' and @public_recipients and grep /^\Q$to\E$/i,@public_recipients) { $rid = $id; } else { open my $idf,'<',"$from/@" or http_die("unknown user $from"); $rid = getline($idf); close $idf; $rid = sidhash($rid,$id); } unless ($id eq $rid) { debuglog("real id=$rid, id sent by user=$id"); http_die("wrong auth-ID"); } # 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")); unlink "$akeydir/$akey"; symlink "../$from","$akeydir/$akey"; } my %to; COLLECTTO: foreach my $to (split(',',$to)) { if ($to !~ /.@./ and open my $AB,'<',"$from/\@ADDRESS_BOOK") { while (<$AB>) { s/\s*#.*//; s/^\s+//; next unless $_; if (/^\s*([\S]+)\s+([\S]+)/) { my ($alias,$address) = ($1,$2); if ($to =~ /^\Q$alias\E$/i) { foreach my $to (split(",",$address)) { $to .= '@'.$mdomain if $mdomain and $to !~ /@/; $to{$to} = lc $to; # ignore dupes } next COLLECTTO; } } } } elsif ($to =~ /^\@(.+)/) { my $group = "$from/\@GROUP/$1"; if (not -l $group and open $group) { while (<$group>) { s/#.*//; s/\s//g; if (/(.+\@[w.-]+):.+/) { $to{$1} = lc $1; # ignore dupes } } close $group; } } else { $to .= '@'.$mdomain if $mdomain and $to !~ /.@./; $to{$to} = lc $to; # ignore dupes } } foreach $to (keys %to) { if (-e "$to/\@CAPTIVE") { http_die("$to is CAPTIVE"); } unless (-d $to or checkaddress($to)) { http_die("$to is not a legal e-mail address"); } } } if ($qs =~ /\&?KEEP=(\d+)/i) { $keep = $1; $filename = filename($file); check_captive($file); if (-f $data) { unlink "$file/keep"; if (symlink $keep,"$file/keep") { http_header('200 OK'); print html_header($head), "

    set keep=$keep for $filename

    \n", "\n"; } else { http_header('599 internal error'); print html_header($head), "

    $filename - $!

    \n", "\n"; } } else { http_header('404 File not found'); print html_header($head), "

    $filename not found

    \n", "\n"; } exit; } elsif ($qs =~ s/\&?KEEP//i) { check_captive($file); $autodelete = 'NO'; } if ($qs =~ s/\&?FILEID=(\w+)//i) { $fileid = $1 } if ($qs =~ s/\&?IGNOREWARNING//i) { $ignorewarning = 1 } if ($qs eq 'LIST') { http_header('200 OK','Content-Type: text/plain'); print "$file :\n"; chdir $file and exec '/client/bin/l'; exit; } # copy file to yourself if ($qs eq 'COPY') { unless (-f "$file/data") { http_die("File not found."); } ($to,$from,$file) = split('/',$file); unless ("$to/@") { # http_header('403 Forbidden'); # print html_header($head), # "You have no permission to copy a file.\n", # "\n"; http_die("You have no permission to copy a file."); } if (-e "$to/$to/$file/data") { # http_header('409 File Exists'); # print html_header($head), # "File $file already exists in your outgoing spool.\n", # "\n"; http_die("File $file already exists in your outgoing spool."); } mkdirp("$to/$to/$file"); link "$to/$from/$file/data","$to/$to/$file/data" or http_die("cannot link to $to/$to/$file/data - $!\n"); my $fkey = copy("$to/$from/$file/filename","$to/$to/$file/filename"); open my $notify,'>',"$to/$to/$file/notify"; close $notify; my $dkey = randstring(8); unlink "$to/$to/$file/dkey","$dkeydir/$dkey"; symlink "../$to/$to/$file","$dkeydir/$dkey"; symlink $dkey,"$to/$to/$file/dkey"; http_header('200 OK',"Location: $durl/$dkey/$fkey"); print html_header($head), "File $file copied to yourself.\n", "\n"; exit; } # ex and hopp? if ($qs =~ s/(^|&)DELETE//i) { if (unlink $data) { $filename = filename($file); if (open my $log,'>',"$file/error") { printf {$log} "%s has been deleted by %s at %s\n", $filename,$ENV{REMOTE_ADDR},isodate(time); close $log; } if (open $log,'>>',$log) { printf {$log} "%s [%s_%s] %s %s deleted\n", isodate(time),$$,$ENV{REQUESTCOUNT},$ra,encode_Q($file); close $log; } http_header('200 OK',"X-File: $file"); print html_header($head), "

    $filename deleted

    \n", "\n"; exit; } else { http_die("no such file") } exit; } # wipe out!? (for anonymous upload) if ($qs =~ s/(^|&)PURGE//i) { $filename = filename($file); if (@anonymous_upload and ipin($ra,@anonymous_upload)) { unlink "$dkeydir/$dkey" if $dkey; if (rmrf($file)) { if (open $log,'>>',$log) { printf {$log} "%s [%s_%s] %s %s purged\n", isodate(time),$$,$ENV{REQUESTCOUNT},$ra,encode_Q($file); close $log; } http_header('200 OK',"X-File: $file"); print html_header($head), "

    $filename purged

    \n", "\n"; } else { http_die("no such file") } } else { http_die("you are not allowed to purge $filename") } exit; } # request for file size? if ($qs eq '?') { sendsize($file); # control back to fexsrv for further HTTP handling exec($ENV{FEXHOME}.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } # fallback if ($qs) { http_die("unknown query format $qs"); } } unless ($id and $rid and $id eq $rid or $dkey or $anonymous) { http_die("wrong parameter $file"); } unless ($to) { http_die("internal error: unknown recipient"); } unless ($from) { http_die("internal error: unknown sender"); } &check_status($from); # server based ip restrictions if (@download_hosts and not ipin($ra,@download_hosts)) { http_die( "Downloads from your host ($ra) are not allowed.", "Contact $ENV{SERVER_ADMIN} for details." ); } # user based ip restrictions unless (check_rhosts("$to/\@DOWNLOAD_HOSTS")) { http_die("You are not allowed to download from IP $ra"); } # file based ip restrictions unless (check_rhosts("$file/restrictions")) { http_die("Download of files from external user $from is restricted " ."to internal hosts. Your IP $ra is not allowed."); } # set time mark for this access if ($file =~ m:(.+?)/:) { my $user = $1; my $time = untaint(time); utime $time,$time,$user; } # reget or range? if ($range = $ENV{HTTP_RANGE}) { $seek = $1 if $range =~ /^bytes=(\d+)-/i; $stop = $1 if $range =~ /^bytes=\d*-(\d+)/i; } else { $seek = 0; $stop = 0; } if (not $autodelete or $autodelete ne 'NO') { $autodelete = readlink "$file/autodelete" || 'YES'; } if ($from and $file eq "$from/$from/ADDRESS_BOOK") { if (open my $AB,'<',"$from/\@ADDRESS_BOOK") { my $ab = ''; while (<$AB>) { s/^\s+//; s/\s+$//; s/[\r\n]//g; $ab .= $_."\r\n"; } close $AB; nvt_print( 'HTTP/1.1 200 OK', 'Content-Length: ' . length($ab), 'Content-Type: text/plain', '' ); print $ab; } else { nvt_print( 'HTTP/1.1 404 No address book found', 'Content-Length: 0', '' ); } # control back to fexsrv for further HTTP handling exec($ENV{FEXHOME}.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } if (-f $data) { # already downloaded? if ($limited_download and $limited_download !~ /^n/i and $from ne $to # fex to yourself is ok! and $to !~ /$amdl/ # allowed multi download recipients and $from !~ /^fexmail/ # fexmail is ok! and $to !~ /^anonymous/ # anonymous fex is ok! and $http_client !~ /$adlm/ # allowed download managers and $file !~ m:/STDFEX$: and not($dkey and ($ENV{HTTP_COOKIE}||'') =~ /dkey=$dkey/) and open $file,'<',"$file/download") { $_ = <$file> || ''; close $file; chomp; $_ = '' if $ra and /$ra/; # allow downloads from same ip if ($_) { s/(.+) ([\w.:]+)$/by $2 at $1/; $file = filename($file); http_die("$file has already been downloaded $_"); } } $sb = sendfile($file,$seek,$stop); shutdown(STDOUT,2); } elsif (-l $data) { # $file =~ s:.*/::; http_die("$file has been withdrawn"); } elsif (open $errf,'<',"$file/error" and $err = getline($errf)) { fdlog($log,$file,0,0); http_die($err); } else { fdlog($log,$file,0,0); if ($file =~ /^anonymous.*afex_\d+\.tar$/) { # should be extra handled... } http_die("no such file $file"); } debuglog(sprintf("%s %s %d %d %d", isodate(time),$file,$sb||0,$seek,-s $data||0)); if ($sb+$seek == -s $data) { # note successfull download $download = "$file/download"; if (open $download,'>>',$download) { printf {$download} "%s %s\n",isodate(time),$ENV{REMOTE_ADDR}; close $download; } # delete file after grace period if ($autodelete eq 'YES') { $grace_time = 60 unless defined $grace_time; for (;;) { my $utime = (stat $data)[8] || 0; my $dtime = (stat $download)[8] || 0; exit if $utime > $dtime; last if time > $dtime+$grace_time; sleep 10; } unlink $data; my $error = "$file/error"; if (open $error,'>',$error) { printf {$error} "%s has been autodeleted after download from %s at %s\n", filename($file),$ENV{REMOTE_ADDR},isodate(time); close $error; } } } exit; sub sendfile { my ($file,$seek,$stop) = @_; my ($filename,$size,$total_size,$fileid,$filetype); my ($data,$download,$header,$buf,$range,$s,$b,$t0); my $type = ''; $data = $file.'/data'; $download = $file.'/download'; $header = $file.'/header'; # fallback defaults, should be set later with better values $filename = filename($file); $total_size = -s $data || 0; # file link? if (-l $data) { unless (-f $data and -r $data) { http_die("$file has been withdrawn"); } $data = abs_path($data); my $fok; foreach my $dir (@file_link_dirs) { $dir = abs_path($dir); $fok = $data if $data =~ /^\Q$dir\//; } unless ($fok) { http_die("no permission to download $file"); } } else { unless (-f $data and -r $data) { http_die("$file has gone"); } } if ($ENV{REQUEST_METHOD} eq 'GET') { debuglog("Exp: FROM=\"$from\"","Exp: TO=\"$to\""); # lock for fup open $data,$data and flock($data,LOCK_EX|LOCK_NB); # security check if (-l $data) { http_die("no permission to download $file"); } # HTTP Range download suckers are already rejected by fexsrv unless ($range = $ENV{HTTP_RANGE}) { # download lock open $download,'>>',$download or die "$download - $!\n"; if ($file =~ m:(.+?)/(.+?)/: and $1 ne $2) { # only one concurrent download is allowed if sender <> recipient flock($download,LOCK_EX|LOCK_NB) or http_die("$file locked: a download is already in progress"); } } $size = $total_size - $seek - ($stop ? $total_size-$stop-1 : 0); } elsif ($ENV{REQUEST_METHOD} eq 'HEAD') { $size = -s $data || 0; } else { http_die("unknown HTTP request method $ENV{REQUEST_METHOD}"); } # read MIME entity header (what the client said) if (open $header,'<',$header) { while (<$header>) { if (/^Content-Type: (.+)/i) { $type = $1; last; } } close $header; $type =~ s/\s//g; } $fileid = readlink "$file/id" || ''; # determine own MIME entity header for download my $mt = $ENV{FEXHOME}.'/etc/mime.types'; if ($http_client !~ /MSIE/ and $type =~ /x-mime/i and open $mt,'<',$mt) { $type = 'application/octet-stream'; MIMETYPES: while (<$mt>) { chomp; s/#.*//; s/^\s+//; my ($mt,@ft) = split; foreach my $ft (@ft) { if ($filename =~ /\.\Q$ft\E$/i) { $type = $mt; last MIMETYPES; } } } close $mt; } # reset to default MIME type else { $type = 'application/octet-stream' } # HTML is not allowed for security reasons! (embedded javascript, etc) $type =~ s/html/plain/i; debuglog("download with $http_client"); if ($seek or $stop) { if ($size < 0) { http_header('416 Requested Range Not Satisfiable'); exit; } if ($stop) { $range = sprintf("bytes %s-%s/%s",$seek,$stop,$total_size); } else { $range = sprintf("bytes %s-%s/%s",$seek,$total_size-1,$total_size); } nvt_print( 'HTTP/1.1 206 Partial Content', "Content-Length: $size", "Content-Range: $range", "Content-Type: $type", ); if ($http_client !~ /MSIE/) { nvt_print("Cache-Control: no-cache"); if ($type eq 'application/octet-stream') { nvt_print("Content-Disposition: attachment; filename=\"$filename\""); } } nvt_print(''); } else { # another stupid IE bug-workaround # http://drupal.org/node/163445 # http://support.microsoft.com/kb/323308 if ($http_client =~ /MSIE/) { # $type = 'application/x-msdownload'; if ($ignorewarning) { $type .= "; filename=$filename"; nvt_print( 'HTTP/1.1 200 OK', "Content-Length: $size", "Content-Type: $type", # "Pragma: no-cache", # "Cache-Control: no-store", "Content-Disposition: attachment; filename=\"$filename\"", "Connection: close", ); # nvt_print('','HTTP/1.1 200 OK',"Content-Length: $size","Content-Type: $type"); exit; } else { http_header('200 OK'); print html_header($head); pq(qq( '

    Internet Explorer warning

    ' 'Using Microsoft Internet Explorer for download will probably' 'lead to problems, because it is not Internet compatible (RFC 2616).' '

    ' 'We recommend Firefox' '

    ' 'If you really want to continue with Internet Explorer, then' '' 'click here with your right mouse button and select "save as"' '' '

    ' 'See also F*EX user FAQ.' '' )); exec($ENV{FEXHOME}.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } } else { nvt_print( 'HTTP/1.1 200 OK', "Content-Length: $size", "Content-Type: $type", "Cache-Control: no-cache", "Connection: close", ); if ($type eq 'application/octet-stream') { nvt_print(qq'Content-Disposition: attachment; filename="$filename"'); } } nvt_print("X-Size: $total_size"); nvt_print("X-File-ID: $fileid") if $fileid; # if ((`file "$file/data" 2>/dev/null` || '') =~ m{.*/data:\s(.+)}) { # nvt_print("X-File-Type: $1"); # } if ($dkey = $dkey||readlink "$file/dkey") { my $ma = (readlink "$file/keep"||$keep_default)*60*60*24; nvt_print("Set-Cookie: dkey=$dkey; Max-Age=$ma; Path=$ENV{REQUEST_URI}"); } nvt_print(''); } if ($ENV{REQUEST_METHOD} eq 'HEAD') { # control back to fexsrv for further HTTP handling exec($ENV{FEXHOME}.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } if ($ENV{REQUEST_METHOD} eq 'GET') { if (@throttle) { my $to = $file; $to =~ s:/.*::; foreach (@throttle) { if (/(.+):(\d+)$/) { my $throttle = $1; my $limit = $2; # throttle ip address? if ($throttle =~ /^[\d.-]+$/) { if (ipin($ra,$throttle)) { $bwl = $limit; last; } } # throttle e-mail address? else { # allow wildcard *, but not regexps $throttle =~ quotemeta $throttle; $throttle =~ s/\*/.*/g; if ($to =~ /$throttle$/) { $bwl = $limit; last; } } } } } foreach my $sig (keys %SIG) { local $SIG{$sig} = \&sigexit } local $SIG{ALRM} = sub { die "TIMEOUT\n" }; seek $data,$seek,0; $t0 = time; $s = $b = 0; # sysread/syswrite because of speed while ($s < $size and $b = sysread($data,$buf,$bs)) { # last chunk for HTTP Range? if ($stop and $s+$b > $size) { $b = $size-$s; $buf = substr($buf,0,$b) } $s += $b; alarm($timeout*10); syswrite STDOUT,$buf or last; # client still alive? if ($bwl) { alarm(0); sleep 1 while $s/(time-$t0||1)/1024 > $bwl; } } close $data; alarm(0); fdlog($log,$file,$s,$size); } close $download; return $s; } sub sendsize { my ($path) = @_; my ($file,$upload,$to,$from,$dkey); my $size = 0; local $_; $path =~ s:^/::; ($to,$from,$file) = split('/',$path); $to =~ s/,.*//; $to = lc $to; $from = lc $from; $to .= '@'.$mdomain if -d "$to\@$mdomain"; $from .= '@'.$mdomain if -d "$from\@$mdomain"; $file =~ s/%([A-F0-9]{2})/chr(hex($1))/ge; $file = urlencode($file); if ($to eq '*' and $fileid) { foreach my $fd (glob "*/$from/$file") { if (-f "$fd/data" and -l "$fd/id" and readlink "$fd/id" eq $fileid and $dkey = readlink "$fd/dkey") { $to = $fd; $to =~ s:/.*::; last; } } } elsif ($to !~ /@/ and open my $AB,'<',"$from/\@ADDRESS_BOOK") { while (<$AB>) { s/\s*#.*//; $_ = lc $_; my ($alias,$address) = split; if ($address) { $address =~ s/,.*//; $address .= '@'.$mdomain if $mdomain and $address !~ /@/; if ($to eq $alias) { $to = $address; last; } } } close $AB; } if (-f "$to/$from/$file/data") { $dkey = readlink "$to/$from/$file/dkey"; $fkey = slurp("$to/$from/$file/filename")||$file; } $upload = -s "$to/$from/$file/upload" || -s "$to/$from/$file/data" || 0; $size = readlink "$to/$from/$file/size" || 0; $fileid = readlink "$to/$from/$file/id" || ''; nvt_print('HTTP/1.1 200 OK'); nvt_print("Content-Length: $upload"); nvt_print("X-Original-Recipient: $to"); nvt_print("X-DKEY: $dkey") if $dkey; nvt_print("X-Location: $durl/$dkey/$fkey") if $dkey and $fkey; nvt_print("X-Size: $size"); nvt_print("X-File-ID: $fileid") if $fileid; nvt_print("X-Features: $ENV{FEATURES}"); nvt_print(''); } sub check_rhosts { my $ipr = shift; my @hosts; local $_; if (open $ipr,$ipr) { while (<$ipr>) { chomp; s/#.*//; s/\s//g; if ($_ eq '@LOCAL_RHOSTS') { push @hosts,@local_rhosts if @local_rhosts; } elsif (/\w/) { push @hosts,$_; } } close $ipr; if (@hosts and not ipin($ra,@hosts)) { return 0; } } return 1; } sub require_auth { http_header( '401 Authorization Required', 'WWW-Authenticate: Basic realm="'.$ENV{SERVER_NAME}.' F*EX download"', 'Content-Length: 0', ); # control back to fexsrv for further HTTP handling exec($ENV{FEXHOME}.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } sub check_auth { my ($path,$user,$auth) = @_; my ($to,$from,$file,$dkey); my ($id,$idf); my ($subuser,$subid); my $auth_ok = 0; local $_; if ($path =~ m:(.+)/(.+)/(.+):) { ($to,$from,$file) = ($1,$2,$3); } elsif ($path =~ m:(.+)/(.+):) { ($dkey,$file) = ($1,$2); $path = readlink "$dkeydir/$dkey" or http_die('no such file'); (undef,$to,$from,$file) = split('/',$path); } else { http_die("wrong URL format for download") } $to .= '@'.$mdomain if $mdomain and $to !~ /@/; $from .= '@'.$mdomain if $mdomain and $from !~ /@/; $to = lc $to; $from = lc $from; # auth user match to in download URL? if ($to ne $user and "$to\@$mdomain" ne $user and $to ne "$user@$mdomain") { debuglog("mismatch: to=$to, auth user=$user"); &require_auth; } # check for real user if (open $idf,'<',"$to/@") { $id = getline($idf); close $idf; unless ($id and $id eq $auth) { debuglog("$user mismatch: id=$id, auth=$auth"); &require_auth; } } # check for sub user elsif (open $idf,'<',"$from/\@SUBUSER") { while (<$idf>) { chomp; s/#.*//; ($subuser,$subid) = split ':'; if ($subid and $subid eq $auth and ($user eq $subuser or $subuser eq '*@*' or $subuser =~ /^\*\@(.+)/ and $user =~ /\@\Q$1\E$/i or $subuser =~ /(.+)\@\*$/ and $user =~ /^\Q$1\E\@/i)) { $auth_ok = 1; last; } } close $idf; unless ($auth_ok) { debuglog("no matching $user in $from/\@SUBUSER"); &require_auth; } } else { debuglog("no $to/@ and no $from/@"); &require_auth; } } sub check_captive { my $to = shift; $to =~ s:/.*::; $to .= '@'.$mdomain if $mdomain and -d "$to\@$mdomain"; if (-e "$to/\@CAPTIVE") { http_die("$to is CAPTIVE - no URL parameters allowed"); } } sub sigexit { my ($sig) = @_; my $msg; $msg = @_ ? "@_" : '???'; $msg =~ s/\n/ /g; $msg =~ s/\s+$//; errorlog("$file caught SIGNAL $msg"); # sigpipe means: client has terminated # this event will be handled further by sendfile(), do not terminate here if ($sig ne 'PIPE') { $SIG{__DIE__} = ''; if ($sig eq 'DIE') { shift; die "$msg\n"; } else { die "SIGNAL $msg\n"; } } } fex-20130805/cgi-bin/foc0000755000174700017470000001406312155367673012732 0ustar fexfex#!/usr/bin/perl -wT # FEX CGI for (user) operation control # # Author: Ulli Horlacher # use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); use Fcntl qw(:flock); use Digest::MD5 qw(md5_hex); # add fex lib ($FEXLIB) = $ENV{FEXLIB} =~ /(.+)/; die "$0: no $FEXLIB\n" unless -d $FEXLIB; our ($FEXHOME,$mdomain,$nomail,$faillog); our $akey = ''; # load common code, local config : $HOME/lib/fex.ph require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n"; my $error = 'F*EX operation control ERROR'; chdir $spooldir or die "$spooldir - $!\n"; $akeydir = "$spooldir/.akeys"; $user = $id = ''; # look for CGI parameters foreach my $v (param) { my $vv = param($v); $vv =~ s/[ \t\000]//g; $vv =~ s/[<>%]/_/g; debuglog("Param: $v=\"$vv\""); if ($v =~ /^akey$/i) { $vv =~ s:/::g; next if $vv eq '.' or $vv eq '..'; $akey = untaint($vv); } elsif ($v =~ /^(from|user)$/i) { $vv =~ s:/::g; next if $vv eq '.' or $vv eq '..'; $user = untaint($vv); $user .= '@'.$mdomain if $mdomain and $user !~ /@/; } elsif ($v =~ /^id$/i) { $id = $vv; } } if ($akey and not $user and not $id) { if (open $akey,'<',"$akeydir/$akey/@" and $id = getline($akey)) { close $akey; $user = readlink "$akeydir/$akey" or http_die("internal server error: no $akey symlink"); $user =~ s:.*/::; $user = untaint($user); if ($akey ne md5_hex("$user:$id")) { $user = $id = ''; } } } $head = "$ENV{SERVER_NAME} F*EX operation control"; # display HTML form and request user data if ($user and $id) { my $idf; unless (open $idf,'<',"$user/@") { faillog("user $from, id $id"); html_error($error,"wrong user or auth-ID"); } &check_status($user); if (-e "$user/\@CAPTIVE") { html_error($error,"captive user") } $rid = getline($idf); close $idf; if ($id eq $rid) { unless ($akey) { $akey = untaint(md5_hex("$user:$id")); unlink "$akeydir/$akey"; symlink "../$user","$akeydir/$akey"; } } else { faillog("user $from, id $id"); html_error($error,"wrong user or auth-ID"); } unlink $faillog if $faillog; http_header("200 OK"); print html_header($head); # authorized login URL my $url = "$ENV{PROTO}://$ENV{HTTP_HOST}/fup/".b64("from=$user&id=$id"); pq(qq( '

    for user $user

    ' '' )); ($quota,$du) = check_sender_quota($user); if ($quota) { pq(qq( )); } ($quota,$du) = check_recipient_quota($user); if ($quota) { pq(qq( )); } pq(qq( '
    sender quota (used):$quota ($du) MB
    recipient quota (used):$quota ($du) MB
    ' '


    ' '' 'Retrieve a list of all your received files in F*EX spool.' '


    ' '' 'Show download URLs of files you have sent.' '


    ' '

    ' ' ' ' ' ' ' ' Change your auth-ID to' ' ' ' ' )); if (-s "$user/\@ALLOWED_RECIPIENTS") { # pq(qq( # ' (You are a restricted user)'; # '

    ' # )); } else { pq(qq( '


    ' '' 'Forward a copy of a file you already have uploaded to another recipient.' '


    ' '' 'Redirect files you have uploaded to a wrong or misspelled recipient.' '


    ' ' Create a subuser who can send you files. Enter his e-mail address:
    ' ' ' ' for only one upload
    ' )); if ($nomail) { pq(qq( ' ' )); } else { pq(qq( ' Comment to send with information e-mail:
    ' '
    ' ' ' )); } pq(qq( '


    ' ' Manage your subusers and groups' '


    ' ' Edit your address book' )); } if ((readlink "$user/\@NOTIFICATION"||'') =~ /short/i) { pq(qq( '


    ' ' Get detailed notification e-mails (current setting: brief).' )); } else { pq(qq( '


    ' ' Get brief notification e-mails (current setting: detailed).' )); } if ((readlink "$user/\@REMINDER"||'') =~ /no/i) { pq(qq( '


    ' ' Get reminder notification e-mails (current setting: no reminders).' )); } else { pq(qq( '


    ' ' Get no reminder notification e-mails (current setting: send reminders).' )); } pq(qq( '


    ' ' Back to fup (upload page)' '

    ' )); print &logout; print "\n"; exit; } my $login = -x "$FEXHOME/login" ? 'login' : 'fup'; nvt_print( "HTTP/1.1 302 Found", "Location: $ENV{PROTO}://$ENV{HTTP_HOST}/$login", 'Expires: 0', 'Content-Length: 0', '' ); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; fex-20130805/cgi-bin/fac0000755000174700017470000006155712156057064012715 0ustar fexfex#!/usr/bin/perl -w # F*EX CGI for administration # # Author: Andre Hafner # use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); $| = 1; # add fex lib (our $FEXLIB) = $ENV{FEXLIB} =~ /(.+)/; die "no \$FEXLIB\n" unless -d $FEXLIB; # import from fex.pp and fex.ph our ($FEXHOME,$spooldir,$logdir,$docdir,$durl,$mdomain); our ($bs,$hostname,$keep_default,$recipient_quota,$sender_quota,$autodelete); our ($admin,$admin_pw,$admin_hosts); our ($sendmail,$bcc); our $error = 'FAC error'; # load common code, local config : $HOME/lib/fex.ph require "$FEXLIB/fex.pp" or http_die("cannot load $FEXLIB/fex.pp - $!\n"); my @http_auth = (); my $ra = $ENV{REMOTE_ADDR}||0; $admin or http_die("\$admin not configured in $FEXLIB/fex.ph\n"); $admin_pw or http_die("\$admin_pw not configured in $FEXLIB/fex.ph\n"); if (@admin_hosts and not ipin($ra,@admin_hosts)) { html_error($error,"Administration from your host ($ra) is not allowed."); } # redirect to https if configured if (0 and open my $x,'/etc/xinetd.d/fexs') { while (<$x>) { if (/^\s*disable\s*=\s*no/) { nvt_print( "HTTP/1.1 301 Moved Permanently", "Location: https://$hostname$ENV{REQUEST_URI}", 'Content-Length: 0', '' ); exit; } } close $x; } # authentication &require_auth; chdir $spooldir or http_die("$spooldir - $!"); my $fup = $durl; $fup =~ s:/fop:/fup:; my $http_client = $ENV{HTTP_USER_AGENT} || ''; # here is chosen which files to save with backup function my @backup_files = qw( htdocs/index.html lib/fex.ph lib/fup.pl spool/*@*/@* ); # backup goes first if (defined param("action") and param("action") eq "backup") { &backup } http_header('200 OK'); print html_header("F*EX Admin Control for $hostname"); my $nav_user = li("Create new user") . "\n" . li("Change user auth-ID") . "\n" . li("Edit user restrictions file") . "\n" . li("Delete existing user") . "\n" . li("Manage disk quota") . "\n"; my $nav_log = li("Get fup.log") . "\n" . li("Get fop.log") . "\n" . li("Get error.log") . "\n"; if (-f 'fexsrv.log') { $nav_log = li("Watch logfile") . "\n" . li("Get fexsrv.log") . "\n" . $nav_log; } my $nav_backup = li("Download backup
    (config only)
    ") . "\n" . li("Restore backup") . "\n"; my $nav_show = li("List spooled files") . "\n" . li("Show quotas (sender/recipient)") . "\n" . li("Show server config") . "\n" . li("Show user config") . "\n"; my $nav_edit = li("Edit config") . "\n" . li("Edit index.html") . "\n"; #print table({-border=>"0"},Tr({-valign=>"top"},[td([ul($nav_user), ul($nav_log), ul($nav_backup), ul($nav_other)])])), "\n"; #print "\n", hr, "\n" ; print table({-border=>"0"}, th({},["manage user","show","log files","edit","backup"]), Tr({-valign=>"top"},[td([ ul($nav_user), ul($nav_show), ul($nav_log), ul($nav_edit), ul($nav_backup) ])])), "\n"; print "
    \n"; my @user_items = &userList; if (my $action = param("action")) { if ($action eq "create") { &createUserForm } elsif ($action eq "change-auth") { &changeAuthForm } elsif ($action eq "edit") { &editRestrictionsForm } elsif ($action eq "delete") { &deleteUserForm } elsif ($action eq "quota") { &changeQuotaForm } elsif ($action eq "list") { &listFiles } elsif ($action eq "showquota") { &showQuota } elsif ($action eq "showconfig") { &showConfig } elsif ($action eq "userconfig") { &userConfigForm } elsif ($action eq "watch") { &watchLog } elsif ($action eq "fexsrv.log") { &getlog("fexsrv.log") } elsif ($action eq "fup.log") { &getlog("fup.log") } elsif ($action eq "fop.log") { &getlog("fop.log") } elsif ($action eq "error.log") { &getlog("error.log") } elsif ($action eq "editconfig") { &editFile("$FEXLIB/fex.ph") } elsif ($action eq "editindex") { &editFile("$docdir/index.html") } elsif ($action eq "backup") { &backup } elsif ($action eq "restore") { &restoreForm } else { http_die("STOP TRYING TO CHEAT ME!\n") } } if (defined param("createUser")) { createUser(param("createUser"), param("authID")); } elsif (defined param("changeAuthUser")) { if (param("changeAuthUser") =~ /^#.*/) { &changeAuthForm; } else { changeUser(param("changeAuthUser"), param("authID")); } } elsif (defined param("showUserConfig")) { if (param("showUserConfig") =~ /^#.*/) { &userConfigForm; } else { showUserConfig(param("showUserConfig")); } } elsif (defined param("deleteUser")) { if (param("deleteUser") =~ /^#.*/) { &deleteUserForm; } else { deleteUser(param("deleteUser")); } } elsif (defined param("userQuota")) { if (param("userQuota") =~ /^#.*/) { &changeQuotaForm; } else { if (defined param("remove quota")) { $user = param("userQuota"); deleteFiles("$spooldir/$user/\@QUOTA"); } else { alterQuota(param("userQuota"), param("recipientQuota"), param("senderQuota")); } } } elsif (defined param("editUser")) { if (param("editUser") =~ /^#.*/) { &editRestrictionsForm; } else { if (defined param("delete file")) { $user = param("editUser"); deleteFiles("$spooldir/$user/\@ALLOWED_RECIPIENTS"); } else { editUser(param("editUser")); } } } elsif (defined param("contentBox") && defined param("ar")) { saveFile(param("contentBox"), param("ar")); } elsif (defined param("upload_archive")) { restore(param("upload_archive")); } print end_html(); exit; ####### # declaration of formular functions ####### # formular for creating new users # required arguments: - sub createUserForm { my $nameRow = "\n" . td(["user:", textfield(-size=>80, -name=>"createUser")]); my $authRow = "\n" . td(["auth-ID:", textfield(-size=>80, -name=>"authID")]); print "\n", h3("Create new user"); print "\n", start_form(-name=>"create", -method=>"POST"); print "\n", table(Tr([$nameRow, $authRow])); print "\n", submit('create user'), br; print "\n", end_form; } # formular for changing auth-id of an user # required arguments: - sub changeAuthForm { my $nameRow = "\n" . td(["user:", popup_menu(-name=>"changeAuthUser", -values=>\@user_items)]); my $authRow = "\n" . td(["new auth-ID:", textfield(-size=>80, -name=>"authID")]); print "\n", h3("change auth-ID"); print "\n", start_form(-name=>"change-auth", -method=>"POST"); print "\n", table(Tr([$nameRow, $authRow])); print "\n", submit('change'), br; print "\n", end_form; } # formular choosing user, whose config files shall be shown # required arguments: - sub userConfigForm { my $nameRow = "\n". td(["user:", popup_menu(-name=>"showUserConfig", -values=>\@user_items)]); print "\n", h3("Show user config files"); print "\n", start_form(-name=>"showUserConfig", -method=>"POST"); print "\n", table(Tr([$nameRow])); print "\n", submit('show config files'), br; print "\n", end_form; } # formular for choosing user, whose restriction file shall be edited # required arguments: - sub editRestrictionsForm { my $nameRow = "\n" . td(["user:", popup_menu(-name=>"editUser", -values=>\@user_items)]); print "\n", h3("Edit user restriction file"); print "\n", start_form(-name=>"edit", -method=>"POST"); print "\n", table(Tr([$nameRow])); print "\n", submit('edit file'); print "\n", submit('delete file'), br; print "\n", end_form; } # formular for choosing user, who shall be removed # required arguments: - sub deleteUserForm { my $nameRow = "\n". td(["user:", popup_menu(-name=>"deleteUser", -values=>\@user_items)]); print "\n", h3("Delete existing user"); print "\n", start_form(-name=>"deleteUser", -method=>"POST"); print "\n", table(Tr([$nameRow])); print "\n", submit('delete user'), br; print "\n", end_form; } # formular for changing an user's quota file # required arguments: - sub changeQuotaForm { my ($rquota,$squota) = ''; $rquota = param("rquota") if defined param("rquota"); $squota = param("squota") if defined param("squota"); my $dropdownMenu; if (defined param("user")) { $dropdownMenu = "\n"; } else { $dropdownMenu = popup_menu(-name=>"userQuota", -values=>\@user_items); } my $nameRow = "\n" . td(["user:", $dropdownMenu]); my $recipientRow = "\n" . td(["new quota for recipient:", textfield(-size=>20, -name=>"recipientQuota", -value=>$rquota). " MB (optional)"]); my $senderRow = "\n" . td (["new quota for sender:", textfield(-size=>20, -name=>"senderQuota", -value=>$squota). " MB (optional)"]); print "\n", h3("Manage disk quota"); print "\n", start_form(-name=>"manageQuota", -method=>"POST"); print "\n", table(Tr([$nameRow, $recipientRow, $senderRow])); print "\n", submit('change quota'); print "\n", submit('remove quota'), br; print "\n", end_form; } # formular for choosing backup file to restore # required arguments: - sub restoreForm { print h2("restore config"); print "please specify the backup-archive you want to restore:"; print "\n", start_form(-name=>"restoreFile", -method=>"POST"); print "\n", filefield(-name=>"upload_archive", -size=>"80"), br; print "\n", submit('restore'); print "\n", end_form; } ####### # declaration user functions ####### # function for creating new users # required arguments: username, auth-id sub createUser { my ($user,$id) = @_; my $idf; $id or http_die("not enough arguments in createUser"); $user = lc $user; $user =~ s:/::g; $user =~ s:^[.@]+::; $user =~ s:@+$::; if ($user !~ /@/) { if ($mdomain) { $user .= '@'.$mdomain; } else { error("Missing domain part in user address"); } } unless (-d "$spooldir/$user") { mkdir "$spooldir/$user",0755 or http_die("cannot mkdir $spooldir/$user - $!\n"); } $idf = "$spooldir/$user/@"; if (-f $idf) { error("There is already an user $user!"); } open $idf,'>',$idf or http_die("cannot write $idf - $!\n"); print {$idf} $id,"\n"; close $idf or http_die("cannot write $idf - $!\n"); print "\n"; printf "%s?from=%s&ID=%s
    \n",$fup,$user,$id; printf "%s/%s

    \n",$fup,b64("from=$user&id=$id"); print "\n"; notifyUser($user,$id); print "An information e-mail to $user has been sent.\n"; } # function for changing an user's auth-ID # required arguments: username, auth-id sub changeUser { my ($user,$id) = @_; defined($id) or http_die("not enough arguments in changeUser.\n"); $user .= '@'.$mdomain if $mdomain and $user !~ /@/; my $idf = "$spooldir/$user/@"; print "\n"; print "$idf

    "; open $idf,'>',$idf or http_die("cannot write $idf - $!\n"); print {$idf} $id,"\n"; close $idf or http_die("cannot write $idf - $!\n"); printf "%s?from=%s&ID=%s
    \n",$fup,$user,$id; printf "%s/%s\n",$fup,b64("from=$user&id=$id"); print "

    \n"; notifyUser($user,$id,"change-auth"); print "An information e-mail to $user has been sent.\n"; } # function for showing an user's config files # required arguments: username sub showUserConfig { http_die("not enough arguments in showUserConfig!\n") unless (my $user = $_[0]); chdir "$spooldir/$user" or http_die("could not change directory $spooldir/$user - $!"); print h2("Config files of $user"); foreach my $file (glob('.auto @* @GROUP/*')) { if (-f $file and not -l $file and $file !~ /.*~$/) { print h3($file), "\n"; open $file,'<',$file or http_die("cannot open $file - $!"); # print "
    \n"; dumpfile($file); # print "
    \n"; close $file; } } } # function for editing an user's recipient/sender restrictions # required arguments: username sub editUser { http_die("not enough arguments in editUser.\n") unless (my $user = $_[0]); my @content; http_die("no user $user") unless -d "$spooldir/$user"; my $ar = "$spooldir/$user/\@ALLOWED_RECIPIENTS"; unless (-f $ar) { print "yeah!"; open F,">$ar" or http_die("cannot open $ar - $!"); print F<) { push @content, $_; } close $file or http_die("cannot write $file - $!\n"); print "\nedit file:", br; print "\n", start_form(-name=>"editRestrictions", -method=>"POST"); print "\n", textarea(-name=>'contentBox', -default=>join('',@content), -rows=>10, -columns=>80), br; print "\n", hidden(-name=>'ar', -default=>"$ar",); print "\n", submit('save changes'); print "\n", end_form; } # function for deleting files # required arguments: list of Files sub deleteFiles { http_die("not enough arguments in deleteFiles.\n") unless (my @files = @_); foreach (@files) { if (-e $_) { if (unlink $_) { print "file has been deleted: $_\n", br; } else { print "file could not be deleted: $_ - $!\n", br; } } else { print "file does not exists: $_\n", br; } } } # function for saving a single file # required arguments: content, location sub saveFile { http_die("not enough arguments in saveFile.\n") unless (my ($rf,$ar) = @_); if ($ar eq "$FEXLIB/fex.ph") { open my $conf,">${ar}_new" or http_die("cannot open ${ar}_new - $!"); print {$conf} $rf; close $conf or http_die("cannot write $conf - $!\n");; my $status = `perl -c $FEXLIB/fex.ph_new 2>&1`; if ($status =~ /syntax OK/ ) { unlink "${ar}_new"; } else { pq(qq( 'No valid syntax in configuration file:' '

    ' '

    $status
    ' )); &editFile("$FEXLIB/fex.ph_new"); exit; } } open my $file,">$ar" or http_die("cannot open $ar - $!"); print {$file} $rf; close $file or http_die("cannot write $file - $!\n");; print "The following data has been saved:\n

    \n"; open $file,'<',$ar or http_die("cannot open $ar - $!"); if ($ar =~ /\.html$/) { print while <$file>; } else { print "

    \n";
    	print while <$file>;
        }
        close $file or http_die("cannot write $file - $!\n");;
    }
    
    # function for deleting existing user
    # required arguments: username
    sub deleteUser {
        http_die("not enough arguments in createUser.\n") unless (my $user = $_[0]);
    
        $idf = "$spooldir/$user/\@";
        http_die("no such user $user\n") unless -f $idf;
        unlink $idf or http_die("cannot remove $idf - $!\n");
        unlink "$spooldir/$user/\@ALLOWED_RECIPIENTS";
        print "$user deleted\n";
    }
    
    # function for saving quota information for one single user
    # required arguments: username, recipient-quota, sender-quota
    sub alterQuota {
        http_die("not enough arguments in createUser.\n") unless (my ($user,$rq,$sq) = @_);
    
        $user .= '@'.$mdomain if $mdomain and $user !~ /@/;
        unless (-d "$spooldir/$user") {
            http_die("$user is not a regular FEX user\n");
        }
    
        $rquota = $squota = '';
        $qf = "$spooldir/$user/\@QUOTA";
        if (open $qf,'<',$qf) {
            while (<$qf>) {
                s/#.*//;
                $rquota = $1 if /recipient.*?(\d+)/i;
                $squota = $1 if /sender.*?(\d+)/i;
            }
            close $qf or http_die("cannot write $qf - $!\n");
        }
    
        open $qf,'>',$qf or http_die("cannot open $qf - $!\n");
        if(defined($rq) && $rq ne "") {
            $rquota = $1 if $rq =~ /(\d+)/i;
        }
        if(defined($sq) && $sq ne "") {
            $squota = $1 if $sq =~ /(\d+)/i;
        }    
        print {$qf} "recipient:$rquota\n" if $rquota =~ /\d/;
        print {$qf} "sender:$squota\n" if $squota =~ /\d/;
        close $qf or http_die("cannot write $qf - $!\n");
    
        $rquota = $recipient_quota if $rquota !~ /\d/;
        $squota = $sender_quota    if $squota !~ /\d/;
        print h3("New quotas for $user");
        print "recipient quota: $rquota MB\n", br;
        print "sender quota:   $squota MB\n", br;
    }
    
    # function for listing f*exed files
    # required arguments: -
    sub listFiles {
        print h3("List current files"),"\n";
        my ($file,$dkey);
        chdir $spooldir or http_die("$spooldir - $!\n");
        print "\n";
        foreach $file (glob "*/*/*") {
            if (-s "$file/data" and  $dkey = readlink("$file/dkey") and -l ".dkeys/$dkey") {
              ($to,$from,$file) = split "/",$file;
              $file = html_quote($file);
              print "$from --> $to : $durl/$dkey/$file
    \n"; } } print "
    \n"; } # function for watching the fex-logfile # required arguments: - sub watchLog { if (-f 'fexsrv.log') { print h2("polling fexsrv.log"),"\n"; open my $log,"$FEXHOME/bin/logwatch|" or http_die("cannot run $FEXHOME/bin/logwatch - $!\n"); dumpfile($log); } else { print h2("no fexsrv.log"),"\n"; } } # function for showing logfiles # required arguments: logfile-name sub getlog { my $log = shift or http_die("not enough arguments in getLog"); print h2("show $log"),"\n"; if (open $log,"$logdir/$log") { dumpfile($log); close $log; } else { http_die("cannot open $logdir/$log - $!\n"); } } # function for creating a new backup file # required arguments: - sub backup { my @d = localtime time; my $date = sprintf('%d%02d%02d',$d[5]+1900,$d[4]+1,$d[3]); my $backup = "backup/config-$date.tar"; my $http_client = $ENV{HTTP_USER_AGENT} || ''; my $size; my $home = $FEXHOME; $home = $1 if $ENV{VHOST} and $ENV{VHOST} =~ /:(.+)/; chdir $home or http_die("$home - $!\n"); unless (-d "backup") { mkdir "backup",0700 or http_die("cannot mkdir backup - $!\n"); } system "tar -cf $backup @backup_files 2>/dev/null"; $size = -s $backup or http_die("backup file empty\n"); open $backup,'<',$backup or http_die("cannot open $backup - $!\n"); nvt_print( 'HTTP/1.1 200 OK', "Content-Length: $size", "Content-Type: application/octet-stream; filename=fex-backup-$date.tar", "Content-Disposition: attachment; filename=\"fex-backup-$date.tar\"", "", ); while (read($backup,my $b,$bs)) { print $b or last; } exit; } # function for restoring an old configuration file # required arguments: uploaded archive sub restore { http_die("not enough arguments in restore!\n") unless (my $archive_file = $_[0]); my $restore = "backup.tar"; my $home = $FEXHOME; $home = $1 if $ENV{VHOST} and $ENV{VHOST} =~ /:(.+)/; chdir $home or http_die("$home - $!\n"); open $restore,'>',$restore or http_die("cannot open $restore - $!"); my $data; while(read $archive_file,$data,$bs) { print {$restore} $data; } close $restore or http_die("cannot write $restore - $!"); if (-s $restore) { print "file upload successful, saving actual config in $home/backup/failsave.tar\n", br; system "tar -cf $home/backup/failsave.tar @backup_files 2>/dev/null"; print "starting restore:\n

    \n";
            system "tar -xvf $restore";
            unlink $restore;
        } else {
    	http_die("upload error - no file data received\n");
        }
    }
    
    # function for editing a text-file
    # required arguments: filepath, filename
    sub editFile {
        my $ar = shift;
        my $file;
        local $/;
      
        open $ar,'<',$ar or http_die("cannot open $ar - $!");
        $file = <$ar>;
        close $ar;
    
        print start_form(-name=>"editFile", -method=>"POST"),"\n";
        print textarea(-name=>'contentBox', -default=>$file, -rows=>26, -columns=>80), br,"\n";
        print hidden(-name=>'ar', -default=>"$ar"),"\n";
        print submit('save changes'),"\n";
        print end_form(),"\n";
    }
    
    # function for showing all users' quotas
    # required arguments: -
    sub showQuota {
        my @table_content;
        my $table_head;
    
        print h2("Show quotas (domain sorted, values in MB)");
        foreach (@user_items) {
    	if (s/###\s*//g) {
    	    $table_head = th({}, ["\@$_","sender","sender (used)","recipient","recipient (used)"]);
    	    if (@table_content) {
    		print table({-border=>1},Tr([@table_content])), "\n

    \n"; @table_content = ''; } push @table_content, $table_head; } else { my $rquota = $recipient_quota; my $squota = $sender_quota; my $rquota_used = 0; my $squota_used = 0; my $user = $_; ($squota,$squota_used) = check_sender_quota($user); ($rquota,$rquota_used) = check_recipient_quota($user); s/\@.*//; push @table_content, "$_". "$squota". "$squota_used". "$rquota". "$rquota_used"; } } print table({-border=>1},Tr([@table_content])), "\n"; } # function for showing fex-server configuration # required arguments: - sub showConfig { print h3("Show config"); print table({},Tr([ td(["spooldir:", $spooldir ]), td(["logdir:", $logdir ]), td(["docdir:", $docdir ]), td(["durl:", $durl ]), td(["mdomain:", $mdomain||'' ]), td(["autodelete:", $autodelete ]), td(["keep:", $keep_default ]), td(["recipient_quota:", $recipient_quota]), td(["sender_quota:", $sender_quota ]), td(["admin:", $admin ]) ])); } # function for checking authentication # required arguments: - sub require_auth { if ($ENV{HTTP_AUTHORIZATION} and $ENV{HTTP_AUTHORIZATION} =~ /Basic\s+(.+)/) { @http_auth = split(':',decode_b64($1)) } if ( @http_auth != 2 or $http_auth[0] !~ /^(fexmaster|admin|\Q$admin\E)$/ or $http_auth[1] ne $admin_pw ) { http_header( '401 Authorization Required', "WWW-Authenticate: Basic realm=$admin F*EX admin authentification", 'Content-Length: 0', ); # control back to fexsrv for further HTTP handling exec($ENV{FEXHOME}.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } } # function for sending notification mails to an user # required arguments: username, auth-id, message-type sub notifyUser { http_die("not enough arguments in createUser.\n") unless (my ($user,$id) = @_); my $type = $_[2]; my $message = 'A F*EX account has been created for you. Use'; if (defined($type) and $type eq "change-auth") { $message = 'New auth-ID for your F*EX account has been set. Use' } $user .= '@'.$mdomain if $mdomain and $user !~ /@/; open my $mail,"|$sendmail -f '$admin' '$user' '$bcc'" or http_die("cannot start sendmail - $!\n"); pq($mail,qq( 'From: $admin' 'To: $user' 'Subject: your F*EX account on $hostname' 'X-Mailer: F*EX' '' '$message' '' '$ENV{PROTO}://$ENV{HTTP_HOST}/fup?from=$user' 'auth-ID: $id' '' 'See http://$ENV{HTTP_HOST}/index.html for more information about F*EX.' '' 'Questions? ==> F*EX admin: $admin' )); close $mail or http_die("cannot send notification e-mail (sendmail error $!)\n"); } # sort key is the (inverse) domain # required arguments: list of usernames (e-mail addresses) sub domainsort { # http_die("not enough arguments in domainsort.\n") unless (my @d = @_); my @d = @_; local $_; foreach (@d) { s/ //g; s/^/ /; s/\./,/ while /\..*@/; s/@/@./; $_ = join('.',reverse(split /\./)); } @d = sort { lc $a cmp lc $b } @d; foreach (@d) { $_ = join('.',reverse(split /\./)); s/,/./g; s/@\./@/; } return @d; } # function for creating a sorted list of all users # required arguments: - sub userList { my @u; my $d = ''; foreach (domainsort(grep { s:/@:: } glob('*@*/@'))) { s/ //g; /@(.+)/; if ($1 ne $d) { push @u,"### $1 ###"; } push @u,$_; $d = $1; } return @u; } sub dumpfile { my $file = shift; print "

    \n";
      while (<$file>) {
        s/&/&/g;
        s/\n";
    }
    
    
    sub error {
        print join("\n",@_),"\n";
        print end_html();
        exit;
    }
    fex-20130805/cgi-bin/fur0000755000174700017470000002420612156015136012740 0ustar  fexfex#!/usr/bin/perl -wT
    
    # FEX CGI for user registration
    #
    # Author: Ulli Horlacher 
    #
    
    use CGI         qw(:standard);
    use CGI::Carp	qw(fatalsToBrowser);
    use Fcntl 	qw(:flock :seek :mode);
    
    # import from fex.ph
    our (@local_hosts,@local_domains,@local_rhosts,@local_rdomains);
    our (@registration_hosts,@registration_domains);
    our ($usage_conditions);
    
    # import from fex.pp
    our ($mdomain,$logdir,$spooldir,$fra,$hostname,$sendmail,$admin,$bcc);
    
    our $error = "F*EX user registration ERROR";
    
    my $ra = $ENV{REMOTE_ADDR}||0;
    
    my ($CASE,$ESAC);
    
    # add fex lib
    (our $FEXLIB) = $ENV{FEXLIB} =~ /(.+)/;
    die "$0: no $FEXLIB\n" unless -d $FEXLIB;
    
    # load common code, local config: $HOME/lib/fex.ph
    require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n";
    
    my $log = "$logdir/fur.log";
    my $head = "$ENV{SERVER_NAME} F*EX user registration";
    
    chdir $spooldir or die "$spooldir - $!\n";
    
    my $user = my $id = my $verify = '';
    
    &check_maint;
    
    # look for CGI parameters
    foreach my $v (param) {
      my $vv = strip(param($v));
      debuglog("Param: $v=\"$vv\"");
      $CASE =
        $v =~ /^user$/i	? $user		= normalize_address($vv):
        $v =~ /^exuser$/i	? $exuser	= normalize_address($vv):
        $v =~ /^demouser$/i	? $demouser	= normalize_address($vv):
        $v =~ /^verify$/i	? $verify	= lc($vv):
        $v =~ /^confirm$/i	? $confirm	= $vv:
        $v =~ /^domain$/i	? $domain	= lc($vv):
      $ESAC;
    }
    
    if ($confirm) {
      if ($confirm =~ /^(\w+)$/i) {
        $confirm = $1;
      } else {
        http_die("illegal registration key");
      }
      open $confirm,"<.reg/$confirm" or http_die("no registration key $confirm");
      $user = untaint(getline($confirm));
      $id   = getline($confirm);
      close $confirm;
      # unlink ".reg/$confirm";
      unless ($user and $id) {
        http_die("no registration data for key $confirm");
      }
      unless (-d $user) {
        mkdir $user,0770 or http_die("mkdir $user - $!\n");
      }
      # if (-f "$user/@") { http_die("$user is already activated") }
      open $user,'>',"$user/@" or http_die("open $user/@ - $!\n");
      print {$user} $id,"\n";  
      close $user or http_die("close $user/@ - $!\n");
      
      http_header("200 OK");
      print html_header($head);
      my $url = "$ENV{PROTO}://$ENV{HTTP_HOST}/fup/" . b64("from=$user&id=$id");
      pq(qq(
        '

    Your registration was successful. Your new F*EX account is:

    ' '

    ' '$url' '

    ' '(bookmark this URL!)' '

    ' 'or you can use:' '

    ' ' ' ' ' ' ' ' '
    URL:$ENV{PROTO}://$ENV{HTTP_HOST}/fup/
    Sender:$user
    auth-ID:$id
    '' )); furlog("confirm: account $user created"); exit; } unless ($user or $exuser or $demouser) { http_header("200 OK"); print html_header($head); pq(qq( '

    ' )); if (@local_domains and @local_hosts and ipin($ra,@local_hosts)) { $reg = $ra; if ("@local_domains" eq "*") { pq(qq( ' new user (may send to internal or external users):
    ' ' ' )); } else { if ($mdomain and not grep /^\Q$mdomain\E$/i,@local_domains) { unshift @local_domains,$mdomain; } my @mydomains = map { "\t\n" } @local_domains; pq(qq( ' new user (may send to internal or external users):
    ' ' \@' )); } } if (@local_rdomains and @local_rhosts and (not @registration_hosts or ipin($ra,@registration_hosts))) { print "

    or

    \n" if $reg; $reg = $ra; pq(qq( ' new external user (may send only to internal users):
    ' ' ' '

    ' )); } if (@demo) { print "

    or

    \n" if $reg; $reg = $ra; local $_ = sprintf "with %d MB quota and %d day%s account life time", @demo,$demo[1]>1 ? 's' : ''; pq(qq( ' new demo user ($_):
    ' ' ' '

    ' )); } if ($reg) { pq(qq( '

    ' ' you must enter your e-mail address and ' '

    ' '

    ' )); if (@local_rdomains) { pq(qq( '


    ' 'internal domains are:' '

    '
          ));
          foreach my $lrd (@local_rdomains) {
            print "  $lrd\n";
          }
        }
        print "
    \n"; } else { html_error($error, "Registrations from your host ($ra) are not allowed.", "Contact $ENV{SERVER_ADMIN} for details." ); } exit; } if ($exuser) { unless (@local_rdomains) { http_die("no \@local_rdomains"); } if (@registration_hosts and not ipin($ra,@registration_hosts)) { html_error($error, "Registrations from your host ($ra) are not allowed.", "Contact $ENV{SERVER_ADMIN} for details." ); } if ($exuser =~ /\@(.+)/) { my $exd = $1; if (@registration_domains and not grep /^\Q$exd\E$/i,@registration_domains) { html_error($error, "Your domain $exd is not allowed for registration.", "Contact $ENV{SERVER_ADMIN} for details." ); } } else { html_error($error,"no domain for $exuser"); } if (-f "$exuser/@") { html_error($error,"$exuser does already exist"); } $user = $exuser; } elsif ($demouser) { $user = $demouser; } else { my $mydomains = join('|',@local_domains); $mydomains .= "|$mdomain" if $mdomain; $mydomains =~ s/\./\\./g; $user .= '@'.$domain if $domain and $user !~ /@/; # $user .= '@'.$mdomain if $mdomain and $user !~ /@/; unless (@local_hosts and ipin($ra,@local_hosts)) { html_error($error, "Registrations from your host ($ra) are not allowed.", "Contact $ENV{SERVER_ADMIN} for details." ); } if ("@local_domains" ne "*" and $user !~ /[@.]($mydomains)$/i) { html_error($error, "Illegal domain for username.", "Contact $ENV{SERVER_ADMIN} for details." ); } } unless (checkforbidden($user)) { html_error($error,"$user is not allowed"); } unless (checkaddress($user)) { html_error($error,"$user is not a valid e-mail address"); } $user = untaint($user); if (-f "$user/@") { html_error( $error, "you are already registered". " (I have lost my auth-ID)" ); } unless (-d $user) { mkdir $user,0770 or http_die("mkdir $user - $!\n"); } if ($exuser) { my $rf; # recipients e-mail address restrictions $rf = "$exuser/\@ALLOWED_RECIPIENTS"; open $rf,'>',$rf or http_die("cannot write $rf - $!\n"); print {$rf} "\@LOCAL_RDOMAINS\n"; close $rf; # recipients ip restrictions $rf = "$exuser/\@ALLOWED_RHOSTS"; open $rf,'>',$rf or http_die("cannot write $rf - $!\n"); print {$rf} "\@LOCAL_RHOSTS\n"; close $rf; if (open $user,'>',"$user/.auto") { print {$user} "fur:external\n"; close $user; } } elsif ($demouser) { my $quota = "$demouser/\@QUOTA"; open $quota,'>',$quota or http_die("cannot write $quota - $!\n"); print {$quota} "recipient:10\n","sender:10\n"; close $quota; if (open $user,'>',"$user/.auto") { print {$user} "fur:demo\n"; close $user; } open $demouser,'>',"$demouser/.demo" and close $demouser; } else { if (open $user,'>',"$user/.auto") { print {$user} "fur:internal\n"; close $user; } } $id = randstring(6); if ("@local_domains" eq "*") { open $id,'>',"$user/@" or http_die("open $user/@ - $!\n"); print {$id} $id,"\n"; close $id or http_die("close $user/@ - $!\n"); http_header("200 OK"); print html_header($head); $uid = "from=$user&id=$id"; $b64 = b64($uid); pq(qq( 'Account created:' '
    '
        '$ENV{PROTO}://$ENV{HTTP_HOST}/fup?$uid'
        '$ENV{PROTO}://$ENV{HTTP_HOST}/fup/$b64'
        '
    ' '' )); exit; } if ($verify eq 'no') { open $id,'>',"$user/@" or http_die("open $user/@ - $!\n"); print {$id} $id,"\n"; close $id or http_die("close $user/@ - $!\n"); http_header("200 OK",'Content-Type: text/plain'); print "$ENV{PROTO}://$ENV{HTTP_HOST}/fup?from=$user&ID=$id\n"; furlog("direct: account $user created"); if ($bcc and open my $mail,"|$sendmail '$bcc' 2>>$log") { pq($mail,qq( 'From: fex' 'To: $bcc' 'Subject: F*EX user registration' '' '$user has been auto-registrated with verify=no' )); close $mail; } else { furlog("ERROR: cannot run sendmail - $!\n"); } exit; } unless (-d '.reg') { mkdir '.reg',0770 or http_die("mkdir .reg - $!\n"); } $reg = randstring(8); open $reg,'>',".reg/$reg" or http_die("open .reg/$reg - $!\n"); print {$reg} $user,"\n",$id,"\n"; close $reg or http_die("close .reg/$reg - $!\n"); open my $mail,'|-',$sendmail,$user,$bcc or http_die("cannot start sendmail - $!\n"); pq($mail,qq( 'From: $admin' 'To: $user' 'Subject: F*EX user registration request' '' 'To activate your new F*EX account go to this URL:' '' '$ENV{PROTO}://$ENV{HTTP_HOST}/fur?confirm=$reg' '' )); if ($usage_conditions and open $usage_conditions,$usage_conditions) { print {$mail} "The conditions of usage are:\n\n"; print {$mail} $_ while <$usage_conditions>; close $usage_conditions; } close $mail or http_die("cannot send mail - $!\n"); http_header("200 OK"); print html_header($head); print "confirmation e-mail has been sent to $user\n"; print "\n"; furlog("confirmation request mailed to $user"); exit; sub strip { local $_ = shift; s/[ \t]+//g; s/\s*[\r\n]+\s*/\n/g; return $_; } # standard log sub furlog { my $msg = "@_"; $msg =~ s/\n/ /g; $msg =~ s/\s+$//; if (open $log,'>>',$log) { flock $log,LOCK_EX; seek $log,0,SEEK_END; printf {$log} "%s [%s_%s] %s %s\n", isodate(time),$$,$ENV{REQUESTCOUNT},$fra,$msg; close $log; } } sub normalize_address { my $a = shift; $a = lc(normalize(despace($a))); checkchars('address',$a); $a =~ s:/:_:g; $a =~ s:^\.:_:; return untaint($a); } fex-20130805/cgi-bin/fup0000755000174700017470000023652012173014415012740 0ustar fexfex#!/usr/bin/perl -wT # F*EX CGI for upload # # Author: Ulli Horlacher # # Contribs: # Sebastian Zaiser (upload status) # use Encode; use Fcntl qw':flock :seek :mode'; use IO::Handle; use Digest::MD5 qw'md5_hex'; use CGI::Carp qw'fatalsToBrowser'; use Cwd qw'abs_path'; # add fex lib (our $FEXLIB) = $ENV{FEXLIB} =~ /(.+)/; die "$0: no $FEXLIB\n" unless -d $FEXLIB; $| = 1; our $debug; our $ndata = 0; our $error = 'F*EX upload ERROR'; our $head = "$ENV{SERVER_NAME} F*EX upload"; our $autodelete = 'YES'; our $locale; # import from fex.ph our (@locales,@throttle,$bcc,$keep_max,$nomail,$nostore,$overwrite); our (@local_domains,@local_rdomains,@local_hosts,@local_rhosts,); our (@registration_hosts,@demo,@file_link_dirs); # import from fex.pp our ($FEXHOME); our ($spooldir,$durl,$tmpdir,$logdir,$docdir,$hostname,$admin,$fra); our ($keep_default,$recipient_quota,$sender_quota); our ($sendmail,$mdomain,$fop_auth,$faillog); our ($dkeydir,$ukeydir,$akeydir,$skeydir,$gkeydir,$xkeydir); our $akey = ''; our $dkey = ''; our $skey = ''; our $gkey = ''; our $seek = 0; # already sent bytes (from previous upload) our $filesize = 0; # total file size our $fpsize = 0; # file part size (MIME-part) my $data; my $boundary; my $rb = 0; # read bytes, totally my $rid = ''; # real ID my @header; # HTTP entity header my $fileid; # file ID my $captive; # load common code, local config: $FEXLIB/fex.ph require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n"; # load fup local config our ($info_1,$info_2,$info_login); $locale = $ENV{LOCALE} || 'english'; foreach my $pl ( "/var/lib/fex/locale/$locale/lib/fup.pl", "$FEXLIB/fup.pl", ) { if (-f $pl) { require $pl or die "$0: cannot load $FEXLIB/fup.pl - $!\n"; last; } } &check_camel unless $sid; chdir $spooldir or http_die("$spooldir - $!\n"); my $log = "$logdir/fup.log"; my $http_client = $ENV{HTTP_USER_AGENT} || ''; my $cl = $ENV{X_CONTENT_LENGTH} || $ENV{CONTENT_LENGTH} || 0; $fra .= '/'.$ENV{HTTP_X_FORWARDED_FOR} if $ENV{HTTP_X_FORWARDED_FOR}; $from = $to = $id = $file = $fkey = $comment = $command = $bwlimit = ''; $filename = $okey = $addto = $replyto = $submit = ''; @to = (); $data = ''; $locale = untaint($ENV{LOCALE}||''); my $ra = $ENV{REMOTE_ADDR}||0; if (@upload_hosts and not ipin($ra,@upload_hosts)) { http_die( "Uploads from your host ($ra) are not allowed.", "Contact $ENV{SERVER_ADMIN} for details." ); } &check_maint; &parse_request; # showstatus will not come back! if ($addto) { my %to; foreach $to (@to) { $to{$to} = 1 } push @to,$addto unless $to{$addto}; if ($submit and @to == 1) { $addto = '' } } $to = join(',',@to); $uid = randstring(8) unless $uid; # upload ID # user requests for forgotten ID $id_forgotten = $id if $id =~ /^"?\?"?/; if ($from and $id_forgotten and not $fop_auth and not $nomail) { &check_status($from); &id_forgotten; exit; } # public recipients? (needs no auth-ID for sender) if ($to and $id and $id eq 'PUBLIC' and @public_recipients) { unless ($from) { http_die("missing sender e-mail address"); } # must use $param{FROM} for checking because $from is expanded with $mdomain unless (checkaddress(despace($param{FROM}))) { http_die("$param{FROM} is not a valid e-mail address"); } foreach my $to (@to) { unless (grep /^\Q$to\E$/i,@public_recipients) { http_die("$to is not a valid recipient"); } } $public = $rid = $id; } # anonymous upload from enabled IP? if (($from eq 'anonymous' or $mdomain and $from eq 'anonymous@'.$mdomain) and @anonymous_upload and ipin($ra,@anonymous_upload)) { $id = $rid = $anonymous = 'anonymous'; if ($to =~ /^anonymous/) { @to = ($to); $autodelete{$to} = $autodelete = 'NO'; } $nomail = $anonymous; } if ($to and (readlink "$to/\@NOTIFICATION"||'') =~ /^no/i) { $nomail = 'recipient'; } $comment = 'NOMAIL' if $nomail and not $comment; # one time token if ($okey) { $to = "@to" or http_die("no recipient"); $from = readlink "$to/\@OKEY/$okey" or http_die("no upload key \"$okey\" - ". "request another one from $to"); $from = untaint($from); } &check_status($from) if $from; # look for regular sender ID if ($id and $from and not ($public or $anonymous or $okey)) { if (open $from,'<',"$from/\@") { # chomp($rid = <$from> || ''); $rid = getline($from); close $from; $rid = sidhash($rid,$id); # set time mark for successfull access if ($id eq $rid) { my $time = untaint(time); utime $time,$time,$from; } } else { my $error = $!; # if recipient (to) is specified, we have to look for subusers later, too unless (@to) { fuplog("ERROR: $spooldir/$from/\@ $error"); debuglog("cannot open $spooldir/$from/\@ : $error"); faillog("user $from, id $id"); http_die("Wrong user or auth-ID"); } } } # check regular ID if ($from and $id and not ($gkey or $skey or $public or $okey)) { if ($rid and $rid eq $id) { # 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 '*') { mksymlink("$akeydir/$akey","../$from"); } } $captive = -e "$from/\@CAPTIVE"; } else { fuplog("ERROR: wrong auth-ID for $from"); debuglog("id sent by user $from=$id, real id=$rid"); faillog("user $from, id $id"); http_die("Wrong user or auth-ID"); } } # forward a copy of a file to another recipient if ($akey and $dkey and $command eq 'FORWARD') { my $file = untaint(readlink "$dkeydir/$dkey"||''); http_die("unknown dkey $dkey>") unless $file; $file =~ s:^\.\./::; forward($file); exit; } # modify file parameter if ($akey and $dkey and $command eq 'MODIFY') { my $file = untaint(readlink "$dkeydir/$dkey"||''); http_die("unknown dkey $dkey") unless $file; $file =~ s:^\.\./::; modify($file); exit; } # copy file from incoming to outgoing spool if ($akey and $dkey and $command eq 'COPY') { unless ($file = readlink "$dkeydir/$dkey") { http_die("No such file with DKEY=$dkey"); } if ($file =~ m:../(.+)/(.+)/(.+):) { ($to,$from,$file) = ($1,$2,$3); } else { http_die("Bad DKEY $dkey -> $file"); } unless (-f "$to/$from/$file/data") { http_die("File not found"); } if (-e "$to/$to/$file/data") { http_die("File $file already exists in your outgoing spool") if (readlink("$to/$to/$file/id")||$to) ne (readlink("$to/$from/$file/id")||$from); } else { mkdirp("$to/$to/$file"); link "$to/$from/$file/data","$to/$to/$file/data" or http_die("cannot link to $to/$to/$file/data - $!\n"); copy("$to/$from/$file/filename","$to/$to/$file/filename"); copy("$to/$from/$file/id","$to/$to/$file/id"); open $file,'>',"$to/$to/$file/notify"; close $file; open $file,'>',"$to/$to/$file/download"; print {$file} "$to\n"; close $file; $dkey = randstring(8); unlink "$to/$to/$file/dkey","$to/$to/$file/keep","$dkeydir/$dkey"; symlink "../$to/$to/$file","$dkeydir/$dkey"; symlink $dkey,"$to/$to/$file/dkey"; } nvt_print( "HTTP/1.1 302 Found", "Location: $ENV{PROTO}://$ENV{HTTP_HOST}/rup?akey=$akey&oto=$to&file=$file", 'Content-Length: 0', '' ); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } # delete file without download if ($akey and $dkey and $command eq 'DELETE') { $del = untaint(readlink "$dkeydir/$dkey"||''); http_die("unknown dkey $dkey") unless $del; $del =~ s:^\.\./::; $filename = filename($del); if (unlink("$del/data") or unlink("$del/upload")) { if (open F,'>',"$del/error") { printf F "%s has been deleted by %s at %s\n", $filename,$ENV{REMOTE_ADDR},isodate(time); close F; } # http_header('200 OK'); # print html_header($head); # print "

    $filename deleted

    \n"; nvt_print( "HTTP/1.1 302 Found", "Location: $ENV{PROTO}://$ENV{HTTP_HOST}/fup?akey=$akey&command=LISTRECEIVED", 'Content-Length: 0', "" ); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } else { my $s = $!; http_header('404 Not Found'); print html_header($head); print "

    $filename not deleted ($s)

    \n"; print "continue\n" if $akey; print "\n"; } exit; } # special commands if (($from and $id and $rid eq $id or $gkey or $skey) and $command) { if ($command eq 'CHECKQUOTA') { http_die("illegal command \"$command\"") if $public or $anonymous; my ($quota,$du); nvt_print('HTTP/1.1 204 OK'); # nvt_print("X-SID: $ENV{SID}") if $ENV{SID}; ($quota,$du) = check_sender_quota($from); nvt_print("X-Sender-Quota: $quota $du") if $quota; ($quota,$du) = check_recipient_quota($from); nvt_print("X-Recipient-Quota: $quota $du") if $quota; nvt_print(''); exit; } if ($command =~ /^LIST(RECEIVED)?$/) { http_die("illegal command \"$command\"") if $public or $anonymous; # list sent files if ($to and $param{'TO'} eq '*') { http_header('200 OK'); print html_header($head); # "(Format: [size] [rest keep time] [filename] [comment])

    \n", print "

    Files from $from:

    \n", "
    \n";
          foreach $file (glob "*/$from/*") {
            next if $file =~ m:/STDFEX$:;
            next if $file =~ m:(.+?)/: and -l $1;
            $size = -s "$file/data";
            next unless $size;
            $size = int($size/1024/1024+0.5);
            $filename = $comment = '';
            my $rto = $file;
            $rto =~ s:/.*::;
            if ($dkey = readlink "$file/dkey") {
              if ($rto ne $to) {
                $to = $rto;
                print "\nto $to :\n";
              }
              if (open $file,'<',"$file/filename") {
                $filename = <$file>;
                close $file;
              }
              if ($filename and length $filename) { 
                $filename = html_quote($filename);
              } else { 
                $filename = '???';
              }
              if (open $file,'<',"$file/comment") {
                $comment = untaint(html_quote(getline($file)));
                close $file;
              }
              my $rkeep = (readlink "$file/keep"||$keep_default) 
                          - int((time-mtime("$file/filename"))/24/3600);
              printf "%8s MB [%s d] %s%s\n",
                     $size,
                     $rkeep,
                     untaint("/fup?akey=$akey&dkey=$dkey&command=FORWARD"),
                     $filename,
                     $comment?qq( "$comment"):'';
            }
          }
          pq(qq(
            '
    ' '

    back to F*EX operation control' '' )); } # list received files else { $to = $from; http_header('200 OK'); print html_header($head); # "(Format: [size] [rest keep time] [URL] [comment])

    \n", print "

    Files for $to (*):

    \n", "
    \n";
          foreach $from (glob "$to/*") {
            next if $from =~ /[A-Z]/;
            $from =~ s:.*/::;
            $url = '';
            foreach $file (glob "$to/$from/*") {
              next if $file =~ /\/STDFEX$/;
              $filename = $comment = '';
              $size = -s "$file/data";
              next unless $size;
              $size = int($size/1024/1024+0.5);
              if ($dkey = readlink "$file/dkey") {
                print "\nfrom $from :\n" unless $url;
                $file =~ m:.*/(.+):;
                $url = "$durl/$dkey/$1";
                unless (-l "$dkeydir/$dkey") {
                  symlink untaint("../$file"),untaint("$dkeydir/$dkey");
                }
                if (open $file,'<',"$file/filename") {
                  $filename = <$file>;
                  close $file;
                }
                if ($filename and length $filename) { 
                  $filename = html_quote($filename);
                } else { 
                  $filename = '???';
                }
                if (open $file,'<',"$file/comment") {
                  $comment = untaint(html_quote(getline($file)));
                  $comment = ' "'.$comment.'"';
                  close $file;
                }
                my $rkeep = (readlink "$file/keep"||$keep_default) 
                            - int((time-mtime("$file/filename"))/24/3600);
                printf "[delete] ",
                       $akey,$dkey;
                printf "[forward] ",
                       $akey,$dkey;
                printf "%8s MB (%s d) %s%s\n",
                       $size,$rkeep,$url,$filename,$comment;
              }
            }
          }
          pq(qq(
            '
    ' '(*) Files for other e-mail addresses you own will not be listed here!

    ' 'back to F*EX operation control' '' )); } exit; } if ($command eq 'LISTSENT') { http_die("illegal command \"$command\"") if $public or $anonymous; # show download URLs http_header('200 OK'); print html_header($head); print "

    Download URLs of files you have sent\n"; foreach $to (glob "*/$from") { if (@files = glob "$to/*/data") { $to =~ s:/.*::; print "

    to $to :

    \n"; print "
    \n";
            foreach $file (@files) {
              $file =~ s:/data::;
              next if $file =~ /\/STDFEX$/;
              $dkey = readlink "$file/dkey" or next;
              $file =~ s:.*/::;
              print "$ENV{PROTO}://$ENV{HTTP_HOST}/fop/$dkey/$file\n";
            }
            print "
    \n"; } } pq(qq( '
    ' '

    back to F*EX operation control' '' )); exit; } if ($command eq 'FOPLOG') { http_die("illegal command \"$command\"") if $public or $anonymous; if (open my $log,"$logdir/fop.log") { http_header('200 OK'); while (<$log>) { next if /\/STDFEX\s/; if (s:^([^/]+)/$from/:$1 :) { if (s:(\d+)/(\d+)$:$1: and $1 and $1 == $2) { s/ \[[\d_]+\]//; print; } } } } exit; } if ($command eq 'RECEIVEDLOG') { http_die("illegal command \"$command\"") if $public or $anonymous; if (open my $fuplog,"$logdir/fup.log") { http_header('200 OK'); while (<$fuplog>) { next if /\sSTDFEX\s/; if (/\d+$/) { my @F = split; if ($F[5] eq $to) { s/ \[[\d_]+\]//; print; } } } } exit; } if ($command eq 'SENDLOG') { http_die("illegal command \"$command\"") if $public or $anonymous; if (open my $fuplog,"$logdir/fup.log") { http_header('200 OK'); while (<$fuplog>) { next if /\sSTDFEX\s/; if (/(\S+\@\S+)/ and $1 eq $from) { s/ \[[\d_]+\]//; print; } } } exit; } if (@to and $command eq 'CHECKRECIPIENT') { http_die("illegal command \"$command\"") if $public or $anonymous; nvt_print('HTTP/1.1 204 OK'); nvt_print("X-SID: $sid") if $sid; foreach my $to (@group?@group:@to) { # my $options = sprintf "(autodelete=%s,keep=%s,locale=%s)", # readlink "$to/\@LOCALE"||$locale||$locale{$to}||$default_locale; my $options = sprintf "(autodelete=%s,keep=%s)", $autodelete{$to}||$autodelete, $keep{$to}||$keep_default; nvt_print("X-Recipient: $to $options"); } nvt_print(''); # control back to fexsrv for further HTTP handling exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } if ($file and @to and $command eq 'DELETE') { http_die("illegal command \"$command\"") if $public or $anonymous; foreach $to (@group?@group:@to) { $to =~ s/:\w+=.*//; # remove options from address $del = "$to/$from/$fkey"; $del =~ s:^/+::; if ($del =~ /\/\./) { http_die("illegal parameter $del"); } $del = untaint($del); if (unlink("$del/data") or unlink("$del/upload")) { if (open F,'>',"$del/error") { print F "$file has been deleted by $from\n"; close F; } http_header('200 OK',"X-File: $del"); print html_header($head); print "

    $file deleted

    \n"; } else { http_header("404 Not Found"); print html_header($head); print "

    $file not deleted

    \n"; } if ($akey) { printf "continue\n", $akey,$to; } print "\n"; } exit; } } # ip restrictions if ($from and $id and $rid eq $id and open my $ipr,"$from/\@UPLOAD_HOSTS") { my @hosts; while (<$ipr>) { chomp; s/#.*//; push @hosts,$_ if /\w/; } close $ipr; unless (@hosts and ipin($ra,@hosts)) { http_die("$from is not allowed to upload from IP $ra"); } } # quotas if ($from and $id and $rid eq $id and @to and not $flink) { my ($quota,$du); # check sender quota ($quota,$du) = check_sender_quota($from); if ($quota and $du+$cl/1024/1024 > $quota) { http_die("you are overquota"); } # check recipient quota foreach my $to (@to) { ($quota,$du) = check_recipient_quota($to); if ($quota and $du+$cl/1024/1024 > $quota) { http_die("$to cannot receive files: is overquota"); } } } # check recipients restriction if ($id and $id eq $rid and $from and @to and not $public) { check_rr($from,@to); } # on secure mode "fop authorization" also check if recipient(s) exists # (= has a F*EX ID) if (not $addto and $fop_auth and $id and $id eq $rid and $from and @to) { my ($to_reg,$idf,$subuser); foreach my $to (@to) { $to =~ s/:\w+=.*//; # remove options from address $to_reg = 0; # full user? if (open $idf,'<',"$to/@") { $to_reg = getline($idf); close $idf; } # sub user? elsif (open $idf,'<',"$from/\@SUBUSER") { while (<$idf>) { s/#.*//; next unless /:/; chomp; ($subuser) = split ':'; if ($subuser eq $to or $subuser eq '*@*' or $subuser =~ /^\*\@(.+)/ and $to =~ /\@\Q$1\E$/i or $subuser =~ /(.+)\@\*$/ and $to =~ /^\Q$1\E\@/i) { $to_reg = $_; last; } } close $idf; } unless ($to_reg) { http_die("recipient $to is not a registered F*EX full or sub user"); } } } $to = join(',',@to); if ($to =~ /^@(.+)/) { if ($nomail) { http_die("server runs in NOMAIL mode - groups ($to) are not allowed"); } my $gf = "$from/\@GROUP/$1"; if (open $gf,'<',$gf) { while (<$gf>) { s/#.*//; push @group,$1 if /(.+@.+):/; } } close $gf; $group = $to; } if ($redirect) { nvt_print( "HTTP/1.1 302 Found", "Location: $ENV{PROTO}://$ENV{HTTP_HOST}/$redirect?akey=$akey", 'Content-Length: 0', "" ); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } if ($from and $id and $id eq $rid and $faillog) { unlink $faillog; } # display HTML form and request user data unless ($file) { if ($test) { $cgi = $test } else { $cgi = $ENV{SCRIPT_NAME} } $cgi = 'fup'; # delete old cookies on logout referer 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"; } } # save default locale for this user if (($akey or $skey or $gkey) and $from and -d $from) { if (not $locale and ($ENV{HTTP_COOKIE}||'') =~ /\blocale=(\w+)/) { $locale = $1; } mksymlink("$from/\@LOCALE",$locale) if $locale; } http_header('200 OK',@cookies); # print html_header($head,''); print html_header($head); if ($http_client =~ /(Konqueror|w3m)/) { pq(qq( '


    ' '

    ' '

    Your client seems to be "$1" which is incompatible with F*EX and will probably not work!

    ' 'We recommend firefox.' '
    ' '


    ' )); } # default "fex yourself" setting? if ($from and $id and $id eq $rid and not $addto and not ($gkey or $skey or $okey or $public or $anonymous) and (not @to or "@to" eq $from) and -f "$from/\@FEXYOURSELF") { @to = ($from); $nomail = 'fexyourself'; } # ask for recipient address(es) elsif ($from and $id and $id eq $rid and ($addto or not $submit or not @to) and not ($gkey or $skey or $okey or $public or $anonymous)) { @ab = (""); # select menu from server address book if (open my $ab,'<',"$from/\@ADDRESS_BOOK") { while (<$ab>) { s/#.*//g; if (/(\S+)[=\s]+(\S+@[\w.-]+\S*)/) { $_ = "$1 <$2>"; s/,.*/,.../g; push @ab,""; } } close $ab; } unless (@to) { unless ($nomail) { foreach (glob "$from/\@GROUP/*") { s:.*/::; push @ab,"" unless /~$/; } } } my $ab64 = b64("from=$from&id=$id"); # '

    ' ' ' ' ' ' ' ' ' ' ' '
    sender: $from
    recipient(s):' '
    ' )); if (grep /@/,@ab) { pq(qq( ' or select from your address book:' ' ' ' and' ' ' )); } pq(qq( '
    ' '

    ' )); my $rr = "$from/\@ALLOWED_RECIPIENTS"; if (-s $rr and open $rr,'<',$rr) { pq(qq( 'You are a restricted user and may only fex to these recipients:

    ' '

    '
          ));
          while (<$rr>) {
            chomp;
            s/#.*//;
            s/\s//g;
            next unless $_;
            if (/^\@LOCAL_RDOMAINS/) {
              foreach my $rd (@local_rdomains) {
                print "*\@$rd\n";
              }
            } else {
              print "$_\n";
            }
          }
          print "

    \n"; close $rr; } pq(qq( ' ' ' or ' '

    ' '

    ' )); if ($akey and -f "$from/\@" and not $captive ) { pq(qq( 'user config & operation control' )); } if (0 and -f "$FEXHOME/htdocs/FIX.jar") { print "

    \n"; if ($public) { print "" } elsif ($skey) { print "" } elsif ($gkey) { print "" } else { print "" } print "Alternate Java client (for files > 2 GB or sending of more than one file)\n"; } print &logout; if (-x "$FEXHOME/cgi-bin/login") { print $info_login||$info_1; } print "\n"; exit; } # ask for filename if ($from and ($id or $okey)) { $to = $group if $group; present_locales($ENV{REQUEST_URI}) if $skey or $gkey or $okey; pq(qq( '' '' )); pq(qq( '

    ' ' ' ' ' ' ' )); if ($public) { my $toh = join('
    ',@to); pq(qq( ' ' ' ' ' ' ' ' ' ' )); } elsif ($okey) { pq(qq( ' ' ' ' '
    sender: $from
    recipient:$toh
    ' ' ' ' ' )); } elsif ($skey) { pq(qq( ' ' '
    sender: $from
    recipient:$to
    ' ' ' ' ' )); } elsif (@group) { if ($gkey) { pq(qq( ' ' )); } my $toh = "group $group:
      "; foreach my $gm (@group) { $toh .= "
    • $gm" } $toh .= "
    "; pq(qq( ' ' '
    sender: $from
    recipient:$to
    ' ' ' ' ' )); } else { my $toc = join(',',@to); my $toh = join('
    ',@to); pq(qq( ' ' '
    sender:$from
    recipient(s):$toh
    ' ' ' )); if ($anonymous) { pq(qq( ' ' )); } else { pq(qq( ' ' )); } } $autodelete = lc $autodelete; $keep = $keep_default unless $keep; my ($quota,$du) = check_sender_quota($from); $quota = $quota ? "" : ''; $bwl = qq''; $ktr = qq'$keep days'; } else { $ctr = qq''; } if ($captive) { $ktr = qq'$keep days'; } pq(qq( ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
    sender:$from
    recipient:' ' $toh
    recipient(s):' ' $toh
    sender quota (used):$quota ($du) MB
    kB/s'; if (@throttle) { foreach (@throttle) { if (/\[?(.+?)\]?:(\d+)$/) { my $throttle = $1; my $limit = $2; # throttle ip address? if ($throttle =~ /^[\w:.-]+$/) { if (ipin($ra,$throttle)) { $bwl = qq' $limit kB/s'; last; } } # throttle e-mail address? else { # allow wildcard *, but not regexps $throttle =~ quotemeta $throttle; $throttle =~ s/\*/.*/g; if ($from =~ /^$throttle$/i) { $bwl = qq' $limit kB/s'; last; } } } } } $autodelete = $autodelete{$to} if $autodelete{$to}; my $adt = ''; if ($autodelete =~ /yes/i) { $adt = 'delete file after download'; } elsif ($autodelete =~ /no/i) { $adt = 'do not delete file after download'; } elsif ($autodelete =~ /delay/i) { $adt = 'delete file after download with delay', } elsif ($autodelete =~ /^\d+$/) { $adt = "delete file $autodelete days after download", } my $ctr = my $ktr = ''; if ($nomail) { $ctr = qq'' .qq'no notification e-mail will be send'; $ktr = qq' days
    '; $ktr = qq'$keep days
    autodelete:$adt
    keep:' ' $ktr' ' $quota' '
    bandwith limit:' ' $bwl' '
    comment:' ' $ctr' '
    file:' ' ' '
    file size:
    ' '

    ' '

    ' '

    ' )); if ($akey and -f "$from/\@" and not $captive) { print "

    \n", "user config & operation control\n"; } if (0 and -f "$FEXHOME/htdocs/FIX.jar" and not $okey) { print "

    \n"; if ($public) { print "" } elsif ($skey) { print "" } elsif ($gkey) { print "" } else { print "" } print "Alternate Java client (for files > 2 GB or sending of more than one file)\n"; } print &logout; print $info_2; # printf "


    %s
    \n",$ENV{HTTP_HEADER}; print "\n"; exit; } present_locales('fup'); if ($ENV{REQUEST_METHOD} eq 'POST') { pq(qq( '

    ' ' You have to fill out this form completely to continue.' '

    ' )); } pq(qq( '
    ' ' ' ' ' ' ' '
    sender:' '
    auth-ID: ' '
    ' )); unless ($fop_auth or $nomail) { # pq(qq( # 'If you have lost your auth-ID use "?"' # 'and your auth-ID will be sent by e-mail to you.' # '

    ' # )); pq(qq( ' ' ' I have lost my auth-ID! Send it to me by e-mail! ' ' (you must fill out sender field above)' )); } pq(qq( '

    ' )); if (not $nomail and ( @local_domains and @local_hosts and ipin($ra,@local_hosts) or @local_rdomains and @local_rhosts and (not @registration_hosts or ipin($ra,@registration_hosts)) or @demo )) { pq(qq( 'You can register yourself ' 'if you do not have a F*EX account yet.

    ' )); } if (@anonymous_upload and ipin($ra,@anonymous_upload)) { my $a = 'anonymous'.int(rand(999999)); pq(qq( 'You may also use anonymous upload' )); } print "

    \n"; print $info_1; if ($debug and $debug>1) { print "
    \n
    \n";
        foreach $v (sort keys %ENV) {
          print "$v = $ENV{$v}\n";
        }
        print "
    \n"; } print "\n"; exit; } if ($from and $file and not @to) { check_rr($from,$from); @to = ($from); $sup = 'fexyourself'; } # all these variables should be defined here, but just to be sure... http_die("no file specified") unless $file; http_die("no sender specified") unless $from; http_die("no recipient specified") unless @to; unless ($okey and -l "$to/\@OKEY/$okey") { http_die("no auth-ID specified") unless $id; unless ($rid eq $id or $gkey or $skey) { faillog("user $from, id $id"); http_die("wrong auth-ID specified"); } } &check_status($from); if (@throttle) { foreach (@throttle) { if (/(.+):(\d+)$/) { my $throttle = $1; my $limit = $2; if (not $bwlimit or $limit < $bwlimit) { # throttle ip address? if ($throttle =~ /^[\d.-]+$/) { if (ipin($ra,$throttle)) { $bwlimit = $limit; last; } } # throttle e-mail address? else { # allow wildcard *, but not regexps $throttle =~ quotemeta $throttle; $throttle =~ s/\*/.*/g; if ($from =~ /^$throttle$/i) { $bwlimit = $limit; last; } } } } } } # address rewriting for storage if (not ($skey or $gkey) and $from =~ /^(anonymous|fexmail)/) { my $to = "@to"; @to = ($from); $from = $to; } if (not $anonymous and $overwrite =~ /^n/i) { foreach $to (@to) { if (-f "$to/$from/$fkey/data") { http_die("$file already exists for $to"); } } } $to = join(',',@to); # file overwriting for anonymous is only possible if his client has the # download cookie - else request purging if ($anonymous and not $seek and my $dkey = readlink "$to/$from/$fkey/dkey") { if ($overwrite =~ /^n/i) { http_die("$file already exists for $to"); } if ($ENV{HTTP_COOKIE} !~ /$dkey/) { my $purge = "/fop/$dkey/$dkey?purge"; # http_die("$file already exists $dkey:$ENV{HTTP_COOKIE}:"); http_die("$file already exists - purge it?!"); } } if (@group) { @to = @group; $comment = "[$group] $comment"; } elsif ($public) { $comment .= ' (public upload)'; } # file data still waits on STDIN ... get it now! &get_file; if ($to eq $from and $file eq 'ADDRESS_BOOK') { unlink "$from/\@ADDRESS_BOOK"; rename "$from/$from/ADDRESS_BOOK/upload","$from/\@ADDRESS_BOOK" or http_die("cannot save $from/\@ADDRESS_BOOK - $!\n"); http_header('200 OK'); print html_header($head); print "address book updated", "\n"; exit; } # finalize upload unless ($nostore) { foreach my $to (@group?@group:@to) { $to =~ s/:\w+=.*//; # remove options from address $filed = "$to/$from/$fkey"; $save = "$filed/data"; $upload = "$filed/upload"; $dkey{$to} = readlink "$filed/dkey"; unlink $save unless -s $save; unlink $save and $overwrite{$to}++; rename $upload,$save or http_die("cannot rename $upload to $save - $!\n"); # log dkey my $dlog = "$logdir/dkey.log"; if (open $dlog,'>>',$dlog) { flock $dlog,LOCK_EX; seek $dlog,0,SEEK_END; printf {$dlog} "%s %s %s %s %s\n", isodate(time),$dkey{$to},$from,$to,$fkey; close $dlog; } # send notification e-mails if necessary if (not $nomail and ($comment or not $overwrite{$to})) { my $locale = readlink "$to/\@LOCALE" || readlink "$filed/locale" || $default_locale; my $lf = untaint("$FEXHOME/locale/$locale/lib/lf.pl"); require $lf if -f $lf; unless ($notify{$locale}) { $locale = 'english'; $lf = "$FEXHOME/lib/lf.pl"; if (-f $lf) { require $lf } else { $notify{$locale} = \¬ify } } &{$notify{$locale}}( # notify( status => "new", dkey => $dkey{$to}, filename => $filename, keep => $keep{$to}||$keep||$keep_default, comment => $comment, replyto => $replyto, autodelete => $autodelete{$to}||$autodelete, ); debuglog("notify $filed [$filename] '$comment'"); } } } # send HTTP status $HTTP_HEADER = 'HTTP/1.1 200 OK'; if ($nostore) { nvt_print($HTTP_HEADER,'Content-Type: text/html',''); exit if $http_client =~ /^fexsend/; } elsif ($file eq 'STDFEX') { nvt_print($HTTP_HEADER,''); exit; } else { nvt_print($HTTP_HEADER); if ($xkey) { my $x = "$durl//$xkey"; $x =~ s:/fop::; nvt_print("X-Location: $x"); } if ($anonymous) { my $dkey = $dkey{$to}; my $cookie = $dkey; $cookie = $1 if $ENV{HTTP_COOKIE} =~ /anonymous=([\w:]+)/; $cookie .= ':'.$dkey if $cookie !~ /$dkey/; nvt_print("Set-Cookie: anonymous=$cookie"); } foreach my $to (@group?@group:@to) { $to =~ s/:\w+=.*//; # remove options from address my $options = sprintf "(autodelete=%s,keep=%s,locale=%s)", readlink "$to/$from/$fkey/autodelete"||$autodelete, readlink "$to/$from/$fkey/keep"||$keep_default, readlink "$to/$from/$fkey/locale"||$locale; nvt_print("X-Recipient: $to $options"); nvt_print("X-Location: $durl/$dkey{$to}/$fkey"); } if ($http_client =~ /^(fexsend|schwuppdiwupp)/) { nvt_print(''); exit; } else { nvt_print('Content-Type: text/html',''); } } # send HTML report print html_header($head); if ($nostore) { printf "%s (%s MB) received\n",$file,$ndata/1024/1024; } elsif ($anonymous or $nomail or $from eq $to) { my $size = $ndata<2*1024 ? sprintf "%s B",$ndata: $ndata<2*1024*1024 ? sprintf "%s kB",int($ndata/1024): sprintf "%s MB",int($ndata/1024/1024); pq(qq( '$file ($size) received and saved

    ' 'Download URL for copy & paste:' )); if ($xkey) { my $x = "$durl//$xkey"; $x =~ s:/fop::; print "

    $x

    \n"; } else { print "

    $durl/$dkey{$to}/$fkey

    \n"; } print "Link is valid for $keep days!

    \n"; } else { if ($ndata<2*1024) { print "$file ($ndata B) received and saved

    \n"; if (not $boring and not $seek) { print "Ehh... $ndata BYTES?! You are kidding?

    \n"; } } elsif ($ndata<2*1024*1024) { $ndata = int($ndata/1024); print "$file ($ndata kB) received and saved

    \n"; if ($ndata<1024 and not ($boring or $seek)) { print "Using F*EX for less than 1 MB: ", "ever heard of MIME e-mail? :-)

    \n"; } } else { $ndata = int($ndata/1024/1024); print "$file ($ndata MB) received and saved

    \n"; } foreach $to (@to) { if ($overwrite{$to}) { print "(old $file for $to overwritten)

    \n" } else { print "$to notified

    \n" } } } if ($okey) { unlink "$to/\@OKEY/$okey"; } elsif (not $anonymous and not $sup) { print ""; print "send another file\n"; print &logout; } print "\n"; exit; # parse GET and POST requests sub parse_request { my %to; my ($to,$dkey); my ($x,$k,$v); my $qs = $ENV{QUERY_STRING}; local $_; # get JUP parameters from environment (HTTP headers) while (($k,$v) = each %ENV) { if ($k =~ s/^FEX_//) { setparam($k,$v); } } # decode base64 PATH_INFO to QUERY_STRING if ($ENV{PATH_INFO} =~ m:^/(\w+=*)$:) { if ($qs) { $qs = sprintf("%s&%s",decode_b64($1),$qs); } else { $qs = decode_b64($1); } } # parse HTTP QUERY_STRING (parameter=value pairs) if ($qs) { foreach (split '&',$qs) { if (s/^(\w+)=//) { my $x = $1; # decode URL-encoding s/%([a-f0-9]{2})/chr(hex($1))/gie; if (/([<>])/) { $_ = sprintf("\"&#%s;\" is not allowed in URL parameter",ord($1)); http_die($_); } setparam($x,$_); } } } # HTTP redirect does not work correctly with opera! # ==> locale handling is now done by fexsrv if (0 and $locale) { nvt_print( "HTTP/1.1 302 Found", "Location: $ENV{PROTO}://$ENV{HTTP_HOST}/fup", "Set-Cookie: locale=$locale", 'Expires: 0', 'Content-Length: 0', '' ); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } if ($showstatus) { &showstatus; exit; } # check for akey, gkey and skey (from HTTP GET) &check_keys; if ($ENV{REQUEST_METHOD} eq 'POST' and $cl) { foreach $sig (keys %SIG) { if ($sig !~ /^(CHLD|CLD)$/) { $SIG{$sig} = \&sigexit; } } $SIG{__DIE__} = \&sigdie; http_die("invalid Content-Length header \"$cl\"") if $cl !~ /^-?\d+$/; debuglog($0); debuglog(sprintf("awaiting %d bytes from %s %s", $cl,$ENV{REMOTE_ADDR}||'',$ENV{REMOTE_HOST}||''),"\n"); &check_space($cl) if $cl > 0; $SIG{ALRM} = sub { die "TIMEOUT\n" }; alarm($timeout); binmode(STDIN,':raw'); if (defined($ENV{FEX_FILENAME})) { # JUP via HTTP header $file = $param{'FILE'} = $ENV{FEX_FILENAME}; $fileid = $ENV{FEX_FILEID} || 0; $fpsize = $ENV{X_CONTENT_LENGTH} || 0; $boundary = ''; } elsif ($contentlength) { # JUP via URL parameter $fpsize = $contentlength; $boundary = ''; } else { # FUP if ($ENV{CONTENT_TYPE} =~ /boundary=\"?([\w\-\+\/_]+)/) { $boundary = $1; } else { http_die("malformed HTTP POST (no boundary found)"); } READPOST: while (&nvt_read) { # the file itself - *must* be last part of POST! if (/^Content-Disposition:\s*form-data;\s*name="file";\s*filename="(.+)"/i) { push @header,$_; $file = $param{'FILE'} = $1; while (&nvt_read) { last if /^\s*$/; $fileid = $1 if /^X-File-ID:\s*(.+)/; $fpsize = $1 if /^Content-Length:\s*(\d+)/; $flink = $1 if /^Content-Location:\s*(\/.+)/; push @header,$_; } # STDIN is now at begin of file, will be read later with get_file() last; } # all other parameters if (/^Content-Disposition:\s*form-data;\s*name="([a-z]\w*)"/i) { my $x = $1; nvt_skip_to('^\s*$'); &nvt_read; setparam($x,$_); NEXTPART: while (&nvt_read) { last READPOST if /^--\Q$boundary--/; last NEXTPART if /^--\Q$boundary/; } } } } if (length($file)) { $file =~ s/%(\d+)/chr($1)/ge; $file = untaint(strip_path(normalize($file))); $file =~ s/[\\\/<>]/_/g; # filter out dangerous chars $file =~ s/^\|//; # filter out dangerous chars $file =~ s/\|$//; # filter out dangerous chars $filename = $file; $fkey = urlencode($file); } # check for akey, gkey and skey (from HTTP POST) &check_keys; } if ($from) { $from .= '@'.$mdomain if $mdomain and $from !~ /@/; if ($from ne 'anonymous' and not checkaddress($from)) { http_die("$from is not a valid e-mail address"); } $from = untaint($from); } # collect multiple addresses and check for aliases (not group) if (@to and "@to" !~ /^@[\w-]+$/ and not ($gkey or $addto or $command =~ /^LIST(RECEIVED)?$/)) { # read address book if ($from and open my $AB,'<',"$from/\@ADDRESS_BOOK") { my ($alias,$address,$autodelete,$locale,$keep); while (<$AB>) { s/#.*//; $_ = lc $_; if (s/^\s*(\S+)[=\s]+(\S+)//) { ($alias,$address) = ($1,$2); $autodelete = $locale = $keep = ''; $autodelete = $1 if /autodelete=(\w+)/; $locale = $1 if /locale=(\w+)/; $keep = $1 if /keep=(\d+)/; foreach my $address (split(",",$address)) { $address .= '@'.$mdomain if $mdomain and $address !~ /@/; push @{$ab{$alias}},$address; $autodelete{$alias} = $autodelete; $keep{$alias} = $keep; $locale{$alias} = $locale; } } } close $AB; } # look for recipient's options and eliminate dupes %to = (); foreach $to (@to) { # address book alias? if ($ab{$to}) { foreach my $address (@{$ab{$to}}) { $address .= '@'.$mdomain if $mdomain and $address !~ /@/; $to{$address} = $address; # ignore dupes if ($specific{'autodelete'}) { $autodelete{$address} = $specific{'autodelete'}; } elsif ($autodelete{$to}) { $autodelete{$address} = $autodelete{$to}; } else { $autodelete{$address} = readlink "$address/\@AUTODELETE" || $autodelete; } if ($_ = readlink "$address/\@LOCALE") { $locale{$address} = $_; } elsif ($locale{$to}) { $locale{$address} = $locale{$to}; } else { $locale{$address} = $locale ; } unless ($locale{$address}) { $locale{$address} = $default_locale || 'english'; } if ($specific{'keep'}) { $keep{$address} = $specific{'keep'} } elsif ($keep{$to}) { $keep{$address} = $keep{$to} } } } else { $to .= '@'.$mdomain if $mdomain and $to !~ /@/; $to{$to} = $to; # ignore dupes unless ($autodelete{$to}) { $autodelete{$to} = readlink "$to/\@AUTODELETE" || $autodelete; } $autodelete{$to} = $specific{'autodelete'} if $specific{'autodelete'}; $keep{$to} = $keep_default; $keep{$to} = $keep if $keep; $keep{$to} = readlink "$to/\@KEEP" if -l "$to/\@KEEP"; $keep{$to} = $specific{'keep'} if $specific{'keep'}; # recipient specific parameters $keep{$to} = $1 if $to =~ /:keep=(\d+)/i; $autodelete{$to} = $1 if $to =~ /:autodelete=(\w+)/i; } if (-e "$to/\@CAPTIVE") { my $v; $v = readlink "$to/\@AUTODELETE" and $autodelete{$to} = $v; $v = readlink "$to/\@KEEP" and $keep{$to} = $v; } } @to = keys %to; if (scalar(@to) == 1) { $to = "@to"; $keep = $keep{$to} if $keep{$to}; $autodelete = $autodelete{$to} if $autodelete{$to}; } # check recipients and eliminate dupes %to = (); foreach $to (@to) { if ($to eq 'anonymous') { $to{$to} = $to; } else { if ($to =~ /^@(.+)/) { http_die("You cannot send to more than one group") if @to > 1; http_die("Group $to does not exist") unless -f "$from/\@GROUP/$1"; } else { $to .= '@'.$mdomain if $mdomain and $to !~ /@/; if (checkaddress($to)) { $to{$to} = untaint($to); } else { http_die("$to is not a valid e-mail address"); } } } } @to = values %to; } foreach $to (@to) { unless (checkforbidden($to)) { http_die("$to is not allowed"); } } } # show the status progress bar sub showstatus { my $wclose; my ($upload,$data,$sfile,$ukey,$file); my ($nsize,$tsize); my ($t0,$t1,$t2,$tt,$ts,$tm); my ($osize,$percent,$npercent); local $_; $wclose = '

    close'."\n". ''."\n"; $ukey = "$ukeydir/$uid"; $upload = "$ukey/upload"; $data = "$ukey/data"; $sfile = "$ukey/size"; for (1..16) { sleep 1; $tsize = readlink $sfile and last; # upload error? # remark: stupid Internet Explorer *needs* the error represented in this # asynchronous popup window, because it cannot display the error in the # main window on HTTP POST! if (-f $ukey and open $ukey,'<',$ukey or -f "$ukey/error" and open $ukey,'<',"$ukey/error") { undef $/; unlink $ukey; html_error($error,<$ukey> || 'unknown'); } } # unlink $sfile; if (defined $tsize and $tsize == 0) { print "\n"; exit; } unless ($tsize) { html_error($error, "no file data received - does your file exist or is it >2GB?") } html_error($error,"file size unknown") unless $tsize =~ /^\d+$/; http_header('200 OK'); if (open $ukey,'<',"$ukey/filename") { local $/; $file = <$ukey>; close $ukey; } http_die("no filename?!") unless $file; my $ssize = $tsize; if ($ssize<2097152) { $ssize = sprintf "%d kB",int($ssize/1024); } else { $ssize = sprintf "%d MB",int($ssize/1048576); } pq(qq( "" "

    " "

    Upload Status for
    $file ($ssize)

    " '' "
    " "" "
    " "
    " "
    " )); # wait for upload file for (1..9) { last if -f $upload or -f $data; sleep 1; } unless (-f $upload or -f $data) { print "

    ERROR: no upload received

    \n"; print $wclose; exit; } $SIG{ALRM} = sub { die "TIMEOUT in showstatus: no (more) data received\n" }; alarm($timeout*2); $t0 = $t1 = time; $osize = $percent = $npercent = 0; for ($percent = 0; $percent<100; sleep(1)) { $t2 = time; $nsize = -s $upload; if (defined $nsize) { if ($nsize<$osize) { print "

    ABORTED

    \n"; print $wclose; exit; } if ($nsize>$osize) { alarm($timeout*2); $osize = $nsize; } $npercent = int($nsize*100/$tsize); $showsize = calcsize($tsize,$nsize); } else { $npercent = 100; $showsize = calcsize($tsize,$tsize); } # hint: for ISDN (or even slower) links, 5 s tcp delay is minimum # so, updating more often is contra-productive if ($t2>$t1+5 or $npercent>$percent) { $percent = $npercent; $t1 = $t2; $tm = int(($t2-$t0)/60); $ts = $t2-$t0-$tm*60; $tt = sprintf("%d:%02d",$tm,$ts); pq(qq( "" )) or last; } } alarm(0); if ($npercent == 100) { print "

    file successfully transferred

    \n"; } else { print "

    file transfer aborted

    \n"; } pq(qq( "" )); print $wclose; unlink $ukey; exit; } # get file from post request sub get_file { my ($to,$filed,$upload,$nupload,$speed,$data); my ($b,$n,$uss); my $dkey; my ($fh,$filesize); my ($t0,$tt); my $fb = 0; # file bytes my $ebl = 0; # end boundary length # FUP, not JUP if ($boundary) { $ebl = length($boundary)+8; # 8: 2 * CRLF + 2 * "--" } unless ($nostore) { # download already in progress? foreach $to (@to) { $to =~ s/:\w+=.*//; # remove options from address $filed = "$to/$from/$fkey"; $data = "$filed/data"; if (-f $data and open $data,'>>',$data) { unless (flock($data,LOCK_EX|LOCK_NB)) { http_die("$filed locked: a download is currently in progress"); } } } # prepare upload foreach $to (@to) { $to =~ s/:\w+=.*//; # remove options from address $filed = "$to/$from/$fkey"; $nupload = "$filed/upload"; # upload for next recipient mkdirp($filed); # upload already prepared (for first recipient)? if ($upload) { # link upload for next recipient unless ($upload eq $nupload or -r $upload and -r $nupload and (stat $upload)[1] == (stat $nupload)[1]) { unlink $nupload; link $upload,$nupload; } } # first recipient => create upload else { $upload = $nupload; unlink "$ukeydir/$uid"; if ($flink) { if ($seek) { http_die("cannot resume on link upload"); } &nvt_read and $flink = $_; if ($flink !~ /^\//) { http_die("no file link name ($flink)"); } $flink = abs_path($flink); my $fok; foreach my $dir (@file_link_dirs) { $dir = abs_path($dir); $fok = $flink if $flink =~ /^\Q$dir\//; } unless ($fok) { http_die("$flink not allowed for linking"); } my @s = stat($flink); unless (@s and ($s[2] & S_IROTH) and -r $flink) { http_die("cannot read $flink"); } unless (-f $flink and not -l $flink) { http_die("$flink is not a regular file"); } # http_die("DEBUG: flink = $flink"); &nvt_read; &nvt_read if /^$/; unless (/^--\Q$boundary--/) { http_die("found no MIME end boundary in upload ($_)"); } unlink $upload; symlink untaint($flink),$upload; } else { unlink $upload if -l $upload; open $upload,'>>',$upload or http_die("cannot create $upload - $!"); unless (flock($upload,LOCK_EX|LOCK_NB)) { http_die("$file locked: a transfer is already in progress"); } unless ($seek) { seek $upload,0,0; truncate $upload,0; } # already uploaded file data size $uss = -s $upload; # provide upload ID symlink for showstatus symlink "../$filed","$ukeydir/$uid"; } } unlink "$filed/autodelete", "$filed/error", "$filed/download", "$filed/restrictions", "$filed/locale", "$filed/keep", "$filed/header", "$filed/id", "$filed/speed", "$filed/comment", "$filed/notify"; unlink "$filed/size" unless $seek; # showstatus needs file name and size # fexsend needs full file size (+$seek) $fh = "$filed/filename"; open $fh,'>',$fh or die "cannot write $fh - $!\n"; print {$fh} $filename; close $fh; if ($::filesize > 0 or $cl > 0) { if ($::filesize > 0) { $filesize = $fpsize || $::filesize } else { $filesize = $cl-$rb-$ebl+$seek } # new file unless ($seek) { if ($::filesize > 0) { # total file size as reported by POST mksymlink("$filed/size",$::filesize) or die "cannot write $filed/size - $!\n"; } else { # file size as counted mksymlink("$filed/size",$filesize) or die "cannot write $filed/size - $!\n"; } } } $autodelete{$to} = $autodelete unless $autodelete{$to}; if ($autodelete{$to} =~ /^(DELAY|NO|\d+)$/i) { mksymlink("$filed/autodelete",$autodelete{$to}); } if (my $keep = $keep{$to} || $::keep) { mksymlink("$filed/keep",$keep); } mksymlink("$filed/id",$fileid) if $fileid; if ($_ = readlink "$to/\@LOCALE") { mksymlink("$filed/locale",$_); } elsif ($locale{$to}) { mksymlink("$filed/locale",$locale{$to}); } elsif ($locale) { mksymlink("$filed/locale",$locale); } my $arh = "$from/\@ALLOWED_RHOSTS"; if (-s $arh) { copy($arh,"$filed/restrictions"); } if (@header and open $fh,'>',"$filed/header") { print {$fh} join("\n",@header),"\n"; close $fh; } if ($nomail) { open $fh,'>',"$filed/notify" and close $fh; } if ($comment) { if (open $fh,'>',"$filed/comment") { print {$fh} encode_utf8($comment); close $fh; } } # provide download ID key unless ($dkey = readlink("$filed/dkey") and -l "$dkeydir/$dkey") { $dkey = randstring(8); unlink "$dkeydir/$dkey"; symlink "../$filed","$dkeydir/$dkey" or die "cannot symlink $dkeydir/$dkey"; unlink "$filed/dkey"; symlink $dkey,"$filed/dkey"; } } # extra download (XKEY)? if ($anonymous and $fkey =~ /^afex_\d/ or $from eq "@to" and $comment =~ s:^//(.*)$:NOMAIL:) { $xkey = $1||$fkey; $nomail = $comment; my $x = "$xkeydir/$xkey"; unless (-l $x and readlink($x) eq "../$from/$from/$fkey") { if (-e $x) { http_die("extra download key $xkey already exists"); } symlink "../$from/$from/$fkey",$x or http_die("cannot symlink $x - $!\n"); unlink "$x/xkey"; symlink $xkey,"$x/xkey"; } } } # file link? if ($flink) { # upload link has been already created, no data to read any more $to = join(',',@to); fuplog($to,$fkey,0); debuglog("upload successfull, dkey=$dkey"); } # regular file else { # at last, read (real) file data $t0 = time(); # streaming data? if ($cl == -1) { alarm($timeout*2); # read until EOF, including MIME end boundary while ($n = read(STDIN,$_,$bs)) { $rb += $n; $fb += $n; syswrite $upload,$_ unless $nostore; alarm($timeout*2); } # size of transferred file, without end boundary $ndata = untaint($fb-$ebl); } # normal file with known file size else { if ($fpsize) { debuglog(sprintf("still awaiting %d+%d = %d bytes", $fpsize,$ebl,$fpsize+$ebl)); $cl = $rb+$fpsize+$ebl; # recalculate CONTENT_LENGTH } else { if ($::filesize) { $cl = $rb+$::filesize+$ebl; # recalculate CONTENT_LENGTH } debuglog(sprintf("still awaiting %d-%d = %d bytes", $cl,$rb,$cl-$rb)); } # read until end boundary, not EOF while ($rb < $cl-$ebl) { $b = $cl-$ebl-$rb; $b = $bs if $b > $bs; # max wait for 1 kB/s, but at least 10 s # $timeout = $b/1024; # $timeout = 10 if $timeout < 10; alarm($timeout); if ($n = read(STDIN,$_,$b)) { $rb += $n; $fb += $n; # syswrite is much faster than print syswrite $upload,$_ unless $nostore; if ($bwlimit) { alarm(0); $tt = (time-$t0) || 1; while ($rb/$tt/1024 > $bwlimit) { sleep 1; $tt = time-$t0; } } # debuglog($_); } else { last; } } # read end boundary - F*IX is broken! if ($ebl and $http_client !~ /F\*IX/) { $_ = ; $_ = ||''; unless (/^--\Q$boundary--/) { http_die("found no MIME end boundary in upload ($_)"); } } $rb += $ebl; $ndata = untaint($fb); } alarm(0); unless ($nostore) { close $upload; # or die "cannot close $upload - $!\n";; # throuput in kB/s $tt = (time-$t0) || 1; mksymlink("$filed/speed",int($fb/1024/$tt)); unless ($ndata) { http_die( "No file data received!". " File name correct?". " File too big (browser-limit: 2 GB!)?" ); } $to = join(',',@to); # streaming upload? if ($cl == -1) { open $upload,'<',$upload or http_die("internal error - cannot read upload"); seek $upload,$ndata+2,0; $_ = <$upload>||''; unless (/^--\Q$boundary--/) { http_die("found no MIME end boundary in upload ($_)"); } close $upload; truncate $upload,$ndata; } else { # truncate boundary string # truncate $upload,$ndata+$uss if -s $upload > $ndata+$uss; # incomplete? if ($cl != $rb) { fuplog($to,$fkey,$ndata,'(aborted)'); if ($fpsize) { http_die("read $rb bytes, but Content-Length announces $fpsize bytes"); } else { http_die("read $rb bytes, but CONTENT_LENGTH announces $cl bytes"); } } # multipost, not complete if ($::filesize > -s $upload) { http_header('206 Partial OK'); exit; } # save error? if (-s $upload > ($::filesize||$filesize)) { fuplog($to,$fkey,$ndata,'(write error: upload > filesize)'); http_die("internal server error while writing file data"); } } fuplog($to,$fkey,$ndata); debuglog("upload successfull, dkey=$dkey"); } } } # check recipients restriction sub check_rr { my $from = shift; my @to = @_; my $rr = "$from/\@ALLOWED_RECIPIENTS"; my ($allowed,$to,$ar,$rd); if (-s $rr and open $rr,'<',$rr) { foreach $to (@to) { $allowed = 0; seek $rr,0,0; while (<$rr>) { chomp; s/#.*//; s/\s//g; if (/^\@LOCAL_RDOMAINS/) { $ar = '(@'; foreach $rd (@local_rdomains) { # allow wildcard *, but not regexps $rd =~ s/\./\\./g; $rd =~ s/\*/[\\w.-]+/g; $ar .= '|[^\@]+\@' . $rd; } $ar .= ')'; } else { # allow wildcard *, but not regexps $ar = quotemeta $_; $ar =~ s/\\\*/[^@]*/g; } if ($to =~ /^$ar$/i or $to !~ /@/ and $mdomain and "$to\@$mdomain" =~ /^$ar$/i) { $allowed = 1; last; } } unless ($allowed) { fuplog("ERROR: $from not allowed to fex to $to"); debuglog("$to not in $spooldir/$from/\@ALLOWED_RECIPIENTS"); http_die("You ($from) are not allowed to fex to $to"); } } close $rr; } } # forward-copy an already uploaded file sub forward { my $file = shift; my ($nfile,$to,$AB); my ($filename); my (%to); http_die("no file data for $file") unless -f "$file/data"; if (@to) { # check recipients restriction check_rr($from,@to); # read aliases from address book if (open $AB,'<',"$from/\@ADDRESS_BOOK") { while (<$AB>) { s/#.*//; $_ = lc $_; if (s/^\s*(\S+)[=\s]+(\S+)//) { my ($alias,$address) = ($1,$2); foreach my $address (split(",",$address)) { $address .= '@'.$mdomain if $mdomain and $address !~ /@/; push @{$ab{$alias}},$address; } } } close $AB; } # collect addresses foreach $to (@to) { if ($ab{$to}) { foreach my $address (@{$ab{$to}}) { $to{$address} = $address; } } else { $to .= '@'.$mdomain if $mdomain and $to !~ /@/; $to{$to} = $to; } } http_header('200 OK'); print html_header($head); @to = keys %to; foreach $to (@to) { $to =~ s/:\w+=.*//; # remove options from address $nfile = $file; $nfile =~ s:.*?/:$to/:; next if $nfile eq $file; mkdirp($nfile); http_die("cannot create directory $nfile") unless -d $nfile; unlink "$nfile/data", "$nfile/upload", "$nfile/autodelete", "$nfile/error", "$nfile/download", "$nfile/restrictions", "$nfile/keep", "$nfile/header", "$nfile/id", "$nfile/speed", "$nfile/comment", "$nfile/notify"; if ($comment) { open $comment,'>',"$nfile/comment"; print {$comment} $comment; close $comment; } if ($autodelete =~ /^(DELAY|NO|\d+)$/i) { symlink($autodelete,"$nfile/autodelete"); } symlink($keep||$keep_default, "$nfile/keep"); copy("$file/id", "$nfile/id"); $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); unlink "$dkeydir/$dkey"; symlink "../$nfile","$dkeydir/$dkey" or die "cannot symlink $dkeydir/$dkey"; unlink "$nfile/dkey"; symlink $dkey,"$nfile/dkey"; } if ($nomail) { if ($filename) { my $url = "$durl/$dkey/".normalize_filename($filename); pq(qq( 'Download-URL for $to:
    ' '$url' '

    ' )); } } else { my $locale = readlink "$to/\@LOCALE" || $::locale || readlink "$file/locale" || 'english'; my $lf = untaint("$FEXHOME/locale/$locale/lib/lf.pl"); require $lf if -f $lf; if ($notify{$locale}) { mksymlink("$nfile/locale",$locale); } else { $locale = 'english'; $notify{$locale} = \¬ify unless $notify{$locale}; } &{$notify{$locale}}( status => "new", dkey => $dkey, filename => $filename, keep => $keep||$keep_default, comment => $comment||'', autodelete => $autodelete, ); fuplog($to,urlencode($filename),"(forwarded)"); if ($filename) { pq(qq( 'File "$filename" copy-forwarded to $to and notified.' '

    ' )); } } } pq(qq( 'back to F*EX operation control' '' )); } else { $filename = filename($file); http_header('200 OK'); print html_header($head); pq(qq( '

    ' ' ' ' ' ' ' ' forward a copy of "$filename" to:
    ' ' ' '
    ' '' )); } } # modify file parameter sub modify { my $file = shift; my $filename = filename($file); my $to; my @parameter; http_die("no file data for $file") unless -f "$file/data"; $to = $file; $to =~ s:/.*::; if ($specific{'keep'}) { mksymlink("$file/keep",$keep); utime time,time,"$file/filename"; push @parameter,'KEEP'; } if ($specific{'autodelete'}) { mksymlink("$file/autodelete",$autodelete); push @parameter,'AUTODELETE'; } if ($comment) { if (open $comment,'>',"$file/comment") { print {$comment} $comment; close $comment; } notify( status => "new", dkey => $dkey, filename => $filename, keep => $keep||$keep_default, comment => $comment, autodelete => $autodelete, ); push @parameter,'COMMENT'; } http_header('200 OK'); print "Parameter ".join(',',@parameter)." modified for $filename for $to\n"; } sub calcsize { my ($tsize,$nsize) = @_; if ($tsize<2097152) { return sprintf "%d kB",int($nsize/1024); } else { return sprintf "%d MB",int($nsize/1048576); } } # read one line from STDIN (net socket) and assign it to $_ # returns number of read bytes sub nvt_read { my $len = 0; if (defined ($_ = )) { debuglog($_); $len = length; $rb += $len; s/\r?\n//; } return $len; } # read forward to given pattern sub nvt_skip_to { my $pattern = shift; while (&nvt_read) { return if /$pattern/ } } # set parameter variables sub setparam { my ($v,$vv) = @_; my ($idf,$to); $v = uc(despace($v)); $param{$v} = $vv; if ($v eq 'LOGOUT') { $logout = $v; # skey and gkey are persistant! $akey = $1 if $ENV{QUERY_STRING} =~ /AKEY:(\w+)/i; unlink "$akeydir/$akey"; $login = $FEXHOME.'/cgi-bin/login'; if (-x $login) { $login = readlink $login || 'login'; nvt_print( "HTTP/1.1 302 Found", "Location: $ENV{PROTO}://$ENV{HTTP_HOST}/$login", 'Content-Length: 0', "" ); exec($FEXHOME.'/bin/fexsrv') if $ENV{KEEP_ALIVE}; exit; } } elsif ($v eq 'LOCALE' and $vv =~ /^(\w+)$/) { $locale = $vv; } elsif ($v eq 'REDIRECT' and $vv =~ /^([\w?=]+)$/) { $redirect = $vv; } elsif (($v eq 'KEY' or $v eq 'SKEY') and $vv =~ /^([\w:]+)$/) { $skey = $1; } elsif ($v eq 'GKEY' and $vv =~ /^([\w:]+)$/) { $gkey = $1 unless $nomail; } elsif ($v eq 'DKEY' and $vv =~ /^(\w+)$/) { $dkey = $1; } elsif ($v eq 'AKEY' and $vv =~ /^(\w+)$/) { $akey = $1; } elsif ($v eq 'FROM' or $v eq 'USER') { $from = lc(normalize(despace($vv))); checkchars('from address',$from); $from =~ s:/:_:g; $from =~ s:^\.:_:; $from = untaint($from); } elsif ($v eq 'REPLYTO') { $replyto = lc(normalize(despace($vv))); checkchars('replyto address',$replyto); $replyto = untaint($replyto); } elsif ($v eq 'ADDTO') { $vv =~ s/\s.*//; $vv =~ s/[<>]//g; $addto = untaint(lc($vv)); # if checkaddress($vv); } elsif ($v eq 'SUBMIT') { $submit = $vv; } elsif ($v eq 'FEXYOURSELF') { $submit = $vv; @to = ($from); } elsif ($v eq 'TO') { # extract AUTODELETE and KEEP options if ($vv =~ s/[\s,]+AUTODELETE=(\w+)//i) { $specific{'autodelete'} = $autodelete = uc($1); } if ($vv =~ s/[\s,]+KEEP=(\d+)//i) { $keep = $1; $keep = $keep_max if $keep_max and $keep > $keep_max; $specific{'keep'} = $keep; } $to = normalize(lc($vv)); $to =~ s/[\n\s;,]+/,/g; if ($from) { if ($to eq '.') { $to = $from; } if ($to eq '//') { $to = $from; $comment = '//'; } } checkchars('to address',$to); push @to,split(',',$to); } elsif ($v eq 'ID') { $id = despace($vv); checkchars('auth-ID',$id); } elsif ($v eq 'TCE') { $test = despace($vv); } elsif ($v eq 'OKEY' and $vv =~ /^(\w+)$/) { $okey = $1; } elsif ($v eq 'FILEID' and $vv =~ /^(\w+)$/) { $fileid = $1; } elsif ($v eq 'CONTENTLENGTH' and $vv =~ /^(\d+)$/) { $contentlength = $1; } elsif ($v eq 'FILE' or $v eq 'FILENAME') { $file = strip_path(normalize($vv)); } elsif ($v eq 'UID' and $vv =~ /^(\w+)$/) { $uid = $1; } elsif ($v eq 'ID_FORGOTTEN') { $id_forgotten = $vv; } elsif ($v eq 'SHOWSTATUS' and $vv =~ /^(\w+)$/) { $showstatus = $uid = $1; } elsif ($v eq 'COMMENT') { $comment = decode_utf8(normalize($vv)); $comment =~ s/^\s*!\.!/!SHORTMAIL!/; $comment =~ s/^!#!/!NOMAIL!/; $comment =~ s/^!-!/!NOSTORE!/; $nomail = $comment if $comment =~ /NOMAIL/; $nostore = $nomail = $comment if $comment =~ /NOSTORE/; $bcc .= " $from" if $comment =~ s/\s*!bcc!?\s*//i; # backward compatibility foreach my $cmd (qw( DELETE LIST CHECKQUOTA CHECKRECIPIENT RECEIVEDLOG SENDLOG FOPLOG FORWARD )) { $command = $comment if $comment eq $cmd } } elsif ($v eq 'COMMAND') { $command = normalize($vv); } elsif ($v eq 'BWLIMIT' and $vv =~ /^(\d+)$/) { $bwlimit = $1; } elsif ($v eq 'SEEK' and $vv =~ /^(\d+)$/) { $seek = $1; } elsif ($v eq 'FILESIZE' and $vv =~ /^(\d+)$/) { $filesize = $1; # complete filesize! &check_space($filesize-$seek); } elsif ($v eq 'AUTODELETE' and $vv =~ /^(\w+)$/) { $specific{'autodelete'} = $autodelete = uc($1); } elsif ($v eq 'KEEP' and $vv =~ /^(\d+)$/) { $keep = $1; $keep = $keep_max if $keep_max and $keep > $keep_max; $specific{'keep'} = $keep; } elsif ($v eq 'TIMEOUT' and $vv =~ /^(\d+)$/) { $specific{'timeout'} = $timeout = $1; } } sub id_forgotten { my ($id,$to,$subuser,$gm,$skey,$gkey,$url,$fup); return if $nomail; $fup = $durl; $fup =~ s:/fop:/fup:; # full user if (open $from,'<',"$from/\@") { $id = getline($from); close $from; } if ($id) { $url = "$fup/".b64("from=$from&id=$id"); mail_forgotten($from,qqq(qq( 'Your reqested F*EX auth-ID for $fup?from=$from is:' '$id' '' 'Or use:' '$url' ))); exit; } # sub user foreach my $skey (glob("$skeydir/*")) { if (-f $skey and open $skey,'<',$skey) { while (<$skey>) { $_ = lc; if (/^(\w+)=(.+)/) { $subuser = $2 if $1 eq 'from'; $to = $2 if $1 eq 'to'; } } close $skey; } if ($from and $to and $from eq $subuser) { $skey =~ s:.*/::; mail_forgotten($subuser,qqq(qq( 'Your reqested F*EX login is:' '' '$fup?skey=$skey' ))); exit; } } # group user foreach my $gkey (glob("$gkeydir/*")) { if (-f $gkey and open $gkey,'<',$gkey) { while (<$gkey>) { $_ = lc; if (/^(\w+)=(.+)/) { $gm = $2 if $1 eq 'from'; $to = $2 if $1 eq 'to'; } } close $gkey; } if ($gm and $to and $from eq $gm) { $gkey =~ s:.*/::; mail_forgotten($gm,qqq(qq( 'Your reqested F*EX login is:' '' '$fup?gkey=$gkey' ))); exit; } } http_die("$from is not a F*EX user on this server"); } sub mail_forgotten { my $user = shift; my @msg = @_; local *P; return if $nomail; open P,'|-',$sendmail,$user,$bcc or http_die("cannot start sendmail - $!\n"); pq(P,qq( 'From: $admin' 'To: $user' 'Subject: F*EX service $hostname' 'X-Mailer: F*EX' '' )); print P @msg; close P or http_die("cannot send mail - $!\n"); http_header('200 OK'); print html_header($head); print "

    Mail has been sent to you ($from)

    \n"; print "\n"; } # lookup akey, skey and gkey (full and sub user and group) sub check_keys { # only one key can be valid $akey = $gkey = '' if $skey; $akey = $skey = '' if $gkey; if ($skey) { # encrypted SKEY? if ($skey =~ s/^MD5H:(.+)/$1/) { # search real SKEY foreach my $s (glob "$skeydir/*") { $s =~ s:.*/::; if ($skey eq md5_hex($s.$sid)) { $skey = $s; last; } } } if (open $skey,'<',"$skeydir/$skey") { $akey = $gkey = ''; while (<$skey>) { if (/^(\w+)=(.+)/) { $from = $2 if lc($1) eq 'from'; @to = ($2) if lc($1) eq 'to'; $rid = $id = $2 if lc($1) eq 'id'; } } close $skey; } else { # $skey = ''; http_die("invalid SKEY $skey"); } } if ($gkey) { # encrypted GKEY? if ($gkey =~ s/^MD5H:(.+)/$1/) { # search real GKEY foreach my $g (glob "$gkeydir/*") { $g =~ s:.*/::; if ($gkey eq md5_hex($g.$sid)) { $gkey = $g; last; } } } if (open $gkey,'<',"$gkeydir/$gkey") { $akey = $skey = ''; while (<$gkey>) { if (/^(\w+)=(.+)/) { $from = $2 if lc($1) eq 'from'; $to = $2 if lc($1) eq 'to'; $rid = $id = $2 if lc($1) eq 'id'; # $user = $2 if lc($1) eq 'user'; } } close $gkey; @to = ($to); } else { # $gkey = ''; http_die("invalid GKEY $gkey"); } } if ($akey and not $id) { my $idf; # sid is not set with web browser # akey with sid is set with schwuppdiwupp & co $idf = "$akeydir/$akey/@"; if (open $idf,'<',$idf and $id = getline($idf)) { close $idf; $from = readlink "$akeydir/$akey" or http_die("internal server error: no $akey symlink"); $from =~ s:.*/::; $from = untaint($from); if ($akey ne md5_hex("$from:$id")) { $from = $id = ''; } } else { $akey = ''; } } } # check if there is enough space on spool sub check_space { my $req = shift; my ($df,$free,$uprq); local *P; if (open $df,"df -k $spooldir|") { while (<$df>) { if (/^.+?\s+\d+\s+\d+\s+(\d+)/ and $req/1024 > $1) { $free = int($1/1024); $uprq = int($req/1024/1024); if (not $nomail and open P,"|$sendmail -t") { pq(P,qq( 'From: $admin' 'To: $admin' 'Subject: F*EX spool out of space' '' 'F*EX spool $spooldir on $ENV{SERVER_NAME} is out of space.' '' 'Current free space: $free MB' 'Upload request: $uprq MB' )); close P; } debuglog("aborting because not enough free space in spool ($free MB)"); http_die("not enough free space for this upload"); } } close $df; } } # global substitution as a function like in gawk sub gsub { local $_ = shift; my ($p,$r) = @_; s/$p/$r/g; return $_; } # standard log sub fuplog { my $msg = "@_"; $msg =~ s/\n/ /g; $msg =~ s/\s+$//; if (open $log,'>>',$log) { flock $log,LOCK_EX; seek $log,0,SEEK_END; printf {$log} "%s [%s_%s] %s (%s) %s\n", isodate(time),$$,$ENV{REQUESTCOUNT},$from,$fra,$msg; close $log; } } sub sigdie { local $_ = shift; chomp; sigexit('DIE',$_); } sub sigexit { my ($sig) = @_; my $msg; my $to = join(',',@to); $msg = @_ ? "@_" : '???'; $msg =~ s/\n/ /g; $msg =~ s/\s+$//; if (open $log,'>>',$log) { printf {$log} "%s %s (%s) %s %s caught SIGNAL %s %s\n", isodate(time), $from||'-', $fra||'-', $to||'-', encode_Q($file||'-'), $msg, $rb?"(after $rb bytes)":""; close $log; } $SIG{__DIE__} = ''; if ($sig eq 'DIE') { shift; die "$msg\n"; } else { die "SIGNAL $msg\n"; } } sub mtime { my @s = lstat shift; return @s ? $s[9] : undef; } sub present_locales { my $url = shift; my @locales = @::locales; if ($url =~ /\?/) { $url .= "&"; $url =~ s/locale=\w+&//g; } else { $url .= "?"; } if (@locales) { map { $_ = "$FEXHOME/locale/$_" } @locales; } else { @locales = glob "$FEXHOME/locale/*"; } print "

    "; foreach my $locale (@locales) { if (-x "$locale/cgi-bin/fup") { my $lang = "$locale/lang.html"; $locale =~ s:.*/::; # offer only those locales defined in fex.ph (default=all) if (@locales) { grep /^$locale$/,@locales or next; next if @locales == 1; } if (open $lang,'<',$lang and $lang = getline($lang)) { close $lang; } else { $lang = $locale; } print "$lang "; } } print "

    \n"; } sub check_camel { my ($logo,$camel); local $\; if (open $logo,"$docdir/logo.jpg") { $camel = md5_hex(<$logo>) eq 'ad8a95bba8dd1a61d70bd38611bc2059'; } if ($camel and open $logo,"$docdir/action-fex-camel.gif") { $camel = md5_hex(<$logo>) eq '1f3d7acc70377496f95c5adddaf4ca7b'; } http_die("Missing camel") unless $camel; } fex-20130805/cgi-bin/rup0000755000174700017470000001515212057663751012766 0ustar fexfex#!/usr/bin/perl -wT # FEX CGI for redirect uploaded files # # Author: Ulli Horlacher # use Fcntl qw(:flock :seek :mode); use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); use Fcntl qw(:flock); use Digest::MD5 qw(md5_hex); # add fex lib (our $FEXLIB) = $ENV{FEXLIB} =~ /(.+)/; die "$0: no $FEXLIB\n" unless -d $FEXLIB; our ($keep_default,$dkeydir,$akeydir,$mdomain,$logdir,$fra); our $akey = ''; # load common code, local config : $HOME/lib/fex.ph require "$FEXLIB/fex.pp" or die "$0: cannot load $FEXLIB/fex.pp - $!\n"; our $error = 'F*EX redirect ERROR'; chdir $spooldir or die "$spooldir - $!\n"; my $log = "$logdir/rup.log"; $from = $id = $oto = $nto = $file = ''; # look for CGI parameters foreach my $v (param) { $vv = param($v); $vv =~ s/[<>]//g; if ($v =~ /^akey$/i) { $vv =~ s:[/.]::g; $akey = untaint($vv); } elsif ($v =~ /^(from|user)$/i) { $from = normalize_address($vv); $from .= '@'.$mdomain if $mdomain and $from !~ /@/; } elsif ($v =~ /^id$/i) { $id = despace($vv); } elsif ($v =~ /^file$/i) { $file =~ s:/:_:g; $file = untaint(normalize($vv)); } elsif ($v =~ /^oto$/i) { $oto = normalize_address($vv); $oto .= '@'.$mdomain if $mdomain and $oto !~ /@/; } elsif ($v =~ /^nto$/i) { $nto = normalize_address($vv); } } if ($akey and not $from) { if (open $akey,'<',"$akeydir/$akey/@" and $id = getline($akey)) { close $akey; $from = readlink "$akeydir/$akey"; $from =~ s:.*/::; $from = untaint($from); if ($akey ne md5_hex("$from:$id")) { $from = $id = ''; } } } if ($from and -s "$from/\@ALLOWED_RECIPIENTS") { http_die("You are a restricted user"); } if ($from and $id) { open F,'<',"$from/@" or http_die("wrong user or auth-ID"); chomp($rid = ); close F; http_die("wrong user or auth-ID") if $id ne $rid; unless ($akey) { $akey = untaint(md5_hex("$from:$id")); unlink "$akeydir/$akey"; symlink "../$from","$akeydir/$akey"; } } if ($oto and not glob("$oto/$from/*")) { http_die("$oto has no no files in spool from you ($from)"); } # display HTML form and request user data unless ($from and $id and $file and $oto and $nto) { $head = "$ENV{SERVER_NAME} F*EX redirect"; http_header("200 OK"); print html_header($head); pq(qq( '
    ' ' ' )); if ($akey) { print "\n"; } else { pq(qq( ' ' ' ' )); } if ($oto) { pq(qq( ' ' ' ' )); } else { pq(qq( ' ' )); } if ($from and $oto) { pq(qq( ' ' ' \n"; } pq(qq( '
    sender:' '
    auth-ID:' '
    old (wrong) recipient:$oto
    old (wrong) recipient:' '
    new recipient:' '
    filename:
    ' '

    ' ' ' '

    '

    'back to F*EX operation control' '' )); exit; } if ($nto) { # read aliases from address book if (open my $AB,'<',"$from/\@ADDRESS_BOOK") { while (<$AB>) { s/#.*//; $_ = lc $_; if (s/^\s*(\S+)[=\s]+(\S+)//) { my ($alias,$address) = ($1,$2); if ($nto eq $alias) { $nto = $address; last; } } } close $AB; } $nto .= '@'.$mdomain if $mdomain and $nto !~ /@/ and $nto =~ /\w/; checkaddress($nto) or http_die("$nto is not a valid e-mail address"); } else { http_die("no new recipient given"); } if ($oto and $nto and $oto eq $nto) { http_die("new recipient must be other than old recipient"); } $fkey = urlencode($file); unless (-s "$oto/$from/$fkey/data") { http_die("no upload data found for $file for $oto"); } if (my $download = slurp("$oto/$from/$fkey/download")) { chomp $download; http_die("$file already downloaded by $oto") if $download ne $oto; } mkdirp("$nto/$from"); rmrf("$nto/$from/$fkey"); if (rename "$oto/$from/$fkey","$nto/$from/$fkey") { mkdirp("$oto/$from/$fkey"); if (open $fkey,'>',"$oto/$from/$fkey/error") { print {$fkey} "$from has removed $file\n"; close $fkey; } unlink "$nto/$from/$fkey/dkey"; unlink "$nto/$from/$fkey/notify"; unlink "$nto/$from/$fkey/error"; unlink "$nto/$from/$fkey/download"; $dkey = randstring(8); symlink $dkey,"$nto/$from/$fkey/dkey"; symlink "../$nto/$from/$fkey","$dkeydir/$dkey"; if (open $fkey,'<',"$nto/$from/$fkey/filename") { chomp($filename = <$fkey>||''); close $fkey; } $filename = $fkey unless $filename; $keep = readlink "$nto/$from/$fkey/keep" || 0; if (not $keep and open $fkey,'<',"$nto/$from/$fkey/keep") { chomp($keep = <$fkey>||''); close $fkey; } if (open $fkey,'<',"$nto/$from/$fkey/comment") { chomp($comment = <$fkey>||''); close $fkey; } notify( status => "new", dkey => $dkey, filename => $filename, keep => $keep||$keep_default, comment => $comment||'', ); ruplog("$oto/$from/$fkey ==> $nto"); http_header("200 OK"); print html_header('F*EX redirect'); pq(qq( '

    F*EX redirect

    ' 'notification of file upload \"$filename\" sent to $nto' '

    ' 'back to F*EX operation control' '' )); } else { http_die("redirect $nto/$from/$fkey failed : $!") } exit; sub normalize_address { local $_ = shift; s/[<>;,\s\|\/]//g; $_ = untaint($_); } # standard log sub ruplog { my $msg = "@_"; $msg =~ s/\n/ /g; $msg =~ s/\s+$//; if (open $log,'>>',$log) { flock $log,LOCK_EX; seek $log,0,SEEK_END; printf {$log} "%s [%s_%s] (%s) %s\n", isodate(time),$$,$ENV{REQUESTCOUNT},$fra,$msg; close $log; } } fex-20130805/htdocs/0000755000174700017470000000000012177755050012177 5ustar fexfexfex-20130805/htdocs/index.html0000644000174700017470000001214412155327312014166 0ustar fexfex F*EX - File EXchange

    F*EX - Frams' Fast File EXchange

    F*EX (Frams' Fast File EXchange) is a service to send big (large, huge, giant, ...) files from a user A to a user B.

    The sender uploads the file to the F*EX server using a WWW upload form and the recipient automatically gets a notification e-mail with a download-URL.

    You say:

    Why do I need another service for file transfer?!
    I have e-mail, ftp, ssh and even sendfile!

    I say:

    You still need F*EX :-)

    For example, you want to send your friend your last holiday video (1 GB). You have the following possibilities (and problems):

    • sending a DVD by postal service

      Out of the question - we live in the year <> after invention of the internet! Sending media (hardware) is for grandpas.

    • using e-mail

      Most e-mail servers have a limit of 10 MB per e-mail and a storage-quota of a few 100 MB per user or even less.

    • uucp

      Why not cuneiform writing on stone plates?

    • ssh

      You have your friends password or you are willing to give him yours - just for a file transfer?

    • ftp

      • Using which ftp server?
      • Using which account, which password?
      • You do not mind sending unencrypted passwords and files over the insecure internet?
      • Your proxy supports passive-ftp?
      • In case of anonymous ftp:
        • Does it allow 1 GB uploads?
        • Does it allow to delete the upload afterwards?
        • Who else can download your file?
        • Who else can delete your file?
        • You have to send your friend the download-URL, he has to inform you about the successful download, you have to delete it afterwards.
          All in all: a pain in the ass.

    • http

      • No default upload and user management - must be programmed
      • No auto-notification
      • No auto-deletion
      • Very few http servers can handle files greater than 2 GB

    • sendfile

      • You run UNIX and have sendfile installed?
      • Your recipient runs UNIX and has sendfile installed?
      • Neither you nor your recipient has a firewall blocking port 487?

    • commercial services like DropLoad, ALLPeers, YouSendIt, etc

      • What limit do they have (most: < 2 GB)?
      • What about security and privacy: will your files be save and secure?
      • Are they open source based or closed proprietary?
      • Are they accessible with any browser or do you need java, active-X, flash or other evil plugins?
      • Will they exist longer than a few months?
        (DropLoad, ALLPeers and drop.io already have terminated their business)

    If you have answered only once "no" to the questions above, then you need F*EX.

    Main features of F*EX

    • file transfer of virtually unlimited file size
    • recipient and sender only need an e-mail program and a web browser - of any kind, they do not have to install any software
    • RESEND and REGET for resuming after link failures at last sent byte
    • auto-notification of recipient
    • auto-deletion after download
    • auto-deletion after expiration date (default: 5 days)
    • full-users can create one time upload URLs for foreign users
    • full-users can create sub-users, who can send only to this full-user
    • full-users can create groups, an analogy to mailing lists, but for files
    • maintenance-free: no admin interaction necessary besides creating new F*EX accounts
    • Sending to multiple recipients needs storage on the server only once
    • F*EX is a HTTP web-service and needs no firewall-tunnels
    • support for streams, too
    • for real UNIX users, there are the shell programs fexsend and fexget to avoid annoying web browser usage
    • protocol and source-code free available

    Let's talk about SEX

    F*EX has a companion: Stream EXchange (SEX).

    You can imagine SEX as network wide UNIX pipes with a relay between. This can be useful for piping data from user A to user B where A and B cannot establish a direct connection, but both can connect by HTTP to the SEX server. For seamless integration into the UNIX tool chain, there are the shell-tools sexsend and sexget.

    Authentication is the same as with F*EX.

    Still questions?

    See the FAQ and the use cases.

    contact: fexmaster
    fex-20130805/htdocs/favicon.ico0000644000174700017470000000000011361161207014273 0ustar fexfexfex-20130805/htdocs/action-fex-camel.gif0000644000174700017470000010160211406365450015775 0ustar fexfexGIF89a@,?"J&S,V*X+X,S-^/[2\2$a2e0!a3 g1h3$e6#b8#j6g7k5 P?6c8*h8&l;#p9$k;)o9)u<t@Ȁ@ !@1|[cC&,!03})_μУ3GHu'Im   4`\~ꌙOel@&W!` 0hP",>9h(,3d 4  8؀#!`PwtSL>Xf\vXs 4,d@ 0 X1ϗF Ё0d@ ,&PidGhh 7Tx{ЃHHy80 Whrh.Ё l`K8 xQchPB T+D@eH }HҐ40As1P_* {uRƈ0B PЀ@&<`!JL` : ;@|ޮF }<f, *00  @ 0 HWD/D$DHDBVPq"tGZØ@0`P 4L pMHT?QѼ N@D1& 0Mt #L:M@' 4/y -xH'@c& B C,bhr E ]zhFoAZ D z) _&D*P Q5Qč.fpl3t-SM7 읁|;Q4H1"0&{PhgN%obD\+ HsՄ( Hu31Fc0@ik8'$q1@P L]:/@A:wt [ 9Ў @M`ⵀlT& u; "np#! A qy2H+;ɞ \_Pw1Ёה 4`N`HbJ!!62q04:d!0.|.B ПA1htd7Q=K5QnnzȴCK7YdVpI< ]k }d/9oE6"|~sr F RH6,UA2h( @'746H'p-]+2[Vo^u[h\ pm sKMp UqS@3(3pL_nE`u7hv^1@#2c&sJ%`e((0JGb{4c^ vssxQa#)2>'0 #p3P'6bW"@5`k5h1e!Ƕ#C8Zm2OP*'7c@dIVaV hUd%B M`gxsb͐cO4 P€ X(p yUmq ^Q`  ȅQ)*h$ @ &PnYw*p^ `HHL"0 uY^$[~1*Jos^7Pu 0^ ]a`Q n`WxyBz* @WVa7' js(uQus/q&WK1 ryi ]M&){@ 5P:t3RwXAiS/#$d2PX*#MTxR2U'bbapiK0ay`^p9` 2rx0qiq ψyx a'Qcq`(`^`0UE&W%W]0NdsJ`-2]j_1]vڥ!zgR|]DB-M&&}bG XT &Ԅ$&cA"' M8 22 7nq`eB0 D"W4hV^i)Qpu`Pas@ag\tgɞvW0@[+'{E73d)0Bu P5B-`B2B"ÁGU/,`!bJ!:R pV2КVBVp14r{*2+G${V@jMM J2 zs_JQayyfaisd~gY8`|*]ߑta @+ (R7H'28cdraW𴢿Wep%, VWǤ[H"/" 0  7047: iV٦ @Wm4Yq3p^&4  }huRU'?f@; fkfW'6G5P5 ]|+3b+P5 GU¿ۃpHjmd%6`4\(BagyVw>avyajqy7>h}5W(`pp2(YSRPpk `) 0* s"JQE`*3sS¿\La3;4__Ǵi9pQɞesQ`s~kHmQ@p 1G6$f"2]Db+A$42 6 u|1J0 +gt3B$pLlne2ĒK=Qsg@zJqfs`ENG2l9xSv@&δ8 ,|  'aS7= g@QTa>ax28, n'W&5&a01`=Vur'Lud J QFh%Ȟ_ڻs2߹jIEW;wM2*P{uPM&#(3`7de @V+aMj L18pE]s_7疽sys v\}\sn~c"@o 'q/_U#7!@q#UlP s|`Kafz\KՖQmv\J p(o iE2Xzy23 *xC` Ь\pEky' Kp\:mK\QhdV\UAy$@8:O!'@0 `Yv&`g3g > p m<'Wэ :s=wgjO jiթ x@"#:RY ,eT(&#{b!0c\La1lY)x^Y  s9o% nmQp\y ( )0)0>ħ4Ĝ ϻ]L<,.APk}| p 0 ɀ KrQyȞNacsa]#| ` = _b# q|L܃F@! @ @ 뛐 `a\JQy ` <6DS .8;X0`bo0|z=Kqΰ ` SHp @ } p  0쩆 Mm6o @ (? } ~@T@kdpF6`qJd@ p@4plpl[]Q ِ Y `Q0wQS]p n  P P z`ZA=ӦC"C 1=  O 0 p  ` nmuԝ'Wn1HҠAŠRTBŮ);f R IoL3?R0R<-~\cR˙-cΔy_~:glSPEk3:Ԝ{3gnZdd"GO)^ТI&*ݖtII .@( I]1hl,yd -\pI& R ΠI*N[L[QFmS:uƒG-AT1D[ӼJc l-6 RH<6&Ls ٭K +PTŐ1[kFB%bzqj(p6 /$ QsQR?cL.9o*&lBc[1QDO&$O$4P6d]chh>6 gYi{|Z[ >iCM<1TegqpǜV(aUxc9@^qSiLeGV*eKDKV#V;ŠAxJPƍ4jihd,ؐ#3X!)~q{`gm9I;:[ [@5GuV(1cL C! %a@UF\41-_DH<1а"8" _Xqc/A$dEJ(GyRGoi]}3> %:6j'sqb!U\h&^DaZKD&I)dIe8 1@8Bcd,dP>D6#YrA? pq!rC_&" tЉB{!ў]1ǟ|t)g*mgLl@NiNdB$4 3fBC&"-bL7Ic.%*sNsvaYQEpIzP9q] 6v' _AE) mxE1 1x/Z" Q!`*`,!:\Gmc*@oP"F w8ChT8m<hɠf\kVj^6کwt>arPpoJ8^\b@ 2 !7kC2p +erH@*@> yН< Vx蠅6%QuE)gCNMZayc6<4D.<ޑ6A p)/N1MaH2 >j/i!C!p8X`D(aL@W(2P(B2qvt,9bP*j Y@I;a-1, mp06Ce! a6'o]4a"PEj&}`C% fe |M8&ԏu` d B,76Dgtax1Y{@F/Q~_Ss4PPV_1{7rpT1JBP/=cFT]#9r%X%Qg=c|{xF\hdmpP<SGl*́FM8>INs\i<fM܅:Dm@qp(KBp?A r1!s;<ԓ!h/JaDDa3XF%/2 )nSC,a I@7TEqCA\}r1Am4e8'X~؄iiւGзmCiK+ ɰ&0xG¡jb0 P t $Na<p,?` f'3h뵁q$= eX(luZB֡)7馦68هN'ZH'JNariЅPP*GpN(lSOhMN=(B0lo0,6|D/Ry~xd0M8e^HA8P`ށDuȜP"#@ZZl؄g`SqЄadP> HhdOPTkK_`MPJPgxbX  Ǔ4ɹzЦ4c6B;jJ[0ONx{`C&jЄb؆d=n.L[Kf@_XKpSL;CIP?Xg$@bx,<{J1Oo+{HH[}HiJTHOoxrh@G Rp{,bbN`L`g`J`n:M]Hg)\QN\SL;lJc` *bC{Gd I9v]e?(QHgȆ{px>b{~ԟmX6vYn]0;?AIMO؄TmcFHIjkLA,`5 - Pć&v;ucPSOp0IKZS8k`~z *gm Qr yptmV,r^`]8I=[^N@?\fnJeہ؅5j)D=|k@dr]0Cxi<C!QP4bk#| }p8qp؇V6ʛQAxf\IM̠wuzhHH>(d%`*X@}uVl &g.AF0S&k ӖҸkVhvniІZ]p3dd0S0 gy2ЂR:u&(WW]? Y9`x={ܷdXaON^(lXM&J&bl:hJp]qK(u+[]NE>(GcȖȸDsGri(Sp \EUІ\z|gVg Y:ͦ/eU1bPMҦ]ywX{:pmheE 7Y)k2i9p0 3CFpJ@UHeOBj x o:YHA#r]𐝸 sK&} m+꥜TMW%cڅp/XtrMUM8# رЉb9wȖ*V؅rU}\d%)34$ vb;I zt!fE6u17~ЇfR|T0-y2{a43bЮckiU9ǂ r?nZ`zrRPNpЃ2kg\qkgh*cm2op+n #maYp&Y'qyjyhck  %pXx dh%wb"ONN|/7c`&xp0ߝphspچ24m +k`ޡҠpg`. `uVo 7Zoyށgc| aG1~7?g'V鷐! ,"/ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝ+7fҥGwjEC2Ȑ D euZJ &JL@PD !DXi>@Ȁ@ !@1|[cC&,!03})_μУ3GHu'Im   4`\~ꌙOel@&W!` 0hP",>9h(,3d 4  8؀#!`PwtSL>Xf\vXs 4,d@ 0 X1ϗF Ё0d@ ,&PidGhh 7Tx{ЃHHy80 Whrh.Ё l`K8 xQchPB T+D@eH }HҐ40As1P_* {uRƈ0B PЀ@&<`!JL` : ;@|ޮF }<f, *00  @ 0 HWD/D$DHDBVPq"tGZØ@0`P 4L pMHT?QѼ N@D1& 0Mt #L:M@' 4/y -xH'@c& B C,bhr E ]zhFoAZ D z) _&D*P Q5Qč.fpl3t-SM7 읁|;Q4H1"0&{PhgN%obD\+ HsՄ( Hu31Fc0@ik8'$q1@P L]:/@A:wt [ 9Ў @M`ⵀlT& u; "np#! A qy2H+;ɞ \_Pw1Ёה 4`N`HbJ!!62q04:d!0.|.B ПA1htd7Q=K5QnnzȴCK7YdVpI< ]k }d/9oE6"|~sr F RH6,UA2h( @'746H'p-]+2[Vo^u[h\ pm sKMp UqS@3(3pL_nE`u7hv^1@#2c&sJ%`e((0JGb{4c^ vssxQa#)2>'0 #p3P'6bW"@5`k5h1e!Ƕ#C8Zm2OP*'7c@dIVaV hUd%B M`gxsb͐cO4 P€ X(p yUmq ^Q`  ȅQ)*h$ @ &PnYw*p^ `HHL"0 uY^$[~1*Jos^7Pu 0^ ]a`Q n`WxyBz* @WVa7' js(uQus/q&WK1 ryi ]M&){@ 5P:t3RwXAiS/#$d2PX*#MTxR2U'bbapiK0ay`^p9` 2rx0qiq ψyx a'Qcq`(`^`0UE&W%W]0NdsJ`-2]j_1]vڥ!zgR|]DB-M&&}bG XT &Ԅ$&cA"' M8 22 7nq`eB0 D"W4hV^i)Qpu`Pas@ag\tgɞvW0@[+'{E73d)0Bu P5B-`B2B"ÁGU/,`!bJ!:R pV2КVBVp14r{*2+G${V@jMM J2 zs_JQayyfaisd~gY8`|*]ߑta @+ (R7H'28cdraW𴢿Wep%, VWǤ[H"/" 0  7047: iV٦ @Wm4Yq3p^&4  }huRU'?f@; fkfW'6G5P5 ]|+3b+P5 GU¿ۃpHjmd%6`4\(BagyVw>avyajqy7>h}5W(`pp2(YSRPpk `) 0* s"JQE`*3sS¿\La3;4__Ǵi9pQɞesQ`s~kHmQ@p 1G6$f"2]Db+A$42 6 u|1J0 +gt3B$pLlne2ĒK=Qsg@zJqfs`ENG2l9xSv@&δ8 ,|  'aS7= g@QTa>ax28, n'W&5&a01`=Vur'Lud J QFh%Ȟ_ڻs2߹jIEW;wM2*P{uPM&#(3`7de @V+aMj L18pE]s_7疽sys v\}\sn~c"@o 'q/_U#7!@q#UlP s|`Kafz\KՖQmv\J p(o iE2Xzy23 *xC` Ь\pEky' Kp\:mK\QhdV\UAy$@8:O!'@0 `Yv&`g3g wKEQэ :s=wgjO jiթ x@"#:RY ,eT(&#{b!0c\La1h@P  0 P p s9o% nmQp\y A%[D2 NMeT˳2 @ [r 0 p Ȁ 0  ŎȞNacsa]#,W p+ZlUKOb# q|L܃F>@ڠ | P P rw6gF~a yPIks 0 m<FR@RPZ+= [dbo0|z=e p ` ` P S `|OkQۚVٚ 0 k@TpdtA)Jb@ @<)` p 0 P xQ=QJ;s)Wu p 0 i ,Y>H0y@kʓ-"A I4eK'93ʙ=}gP#i<|)S7QpS$]H%KR IWM^hHު$I%_.5ĈQ[+4hɒb$BĵCFCoEYfϕ8_%h֭KO:{Z>s™&ٯ_Ȑ=6XSNխ+T IuFҔ7;ر4F` d' *dhe ,URUãn^&Ղb#tB m*(uܡ] u!'oiG(D.$\f\LJOFSLHD DM<$L$HH8pK FĈ" 19K2R/Q4[" +Ұ4Q-+6AƗI% c >დ3X=yF@@@V9ԧ4TPB) *{~xoMwIDF%Z2A8PN%a$DNQeO0C 4"(ru4BID ET`B$ÒKÑ?i| ywXjx]Uz'pq6zgcn!S aI4idIn#1 4 ;$`#0 2lAK.QDQ%j@"Yhb|C;s0]XͥrsԦJU>&{f_sW}d&i ƔCIzO$aIFI4 »d(a iVXBR'Ȑ0LX)rQ[B2@2`u˰=AOJJd( .t=H$L#_p%}k-| \$(5t! 9er):F\BWPȘ%AB0R=aJ"f`BAЀ2m<01Ї?pf4(jnbO rI$;?,Pe$# %ԡnېF8F4@P1It ~B؅.ljE 80a  d 9w7p( І^a-NVE1ltb<@gxDiZr]a (!а7xx g0ІC$P,DHCrv!VDp2ܡ 9Aci5A ccI|KT-xbzD;XA{l=Z;ꤠlmk1 PB2*7 pC.G8a sp:p9 -.h]``,;C"9b xFG'я{hi1 hc+n^؅Za5ރo +(k'0%z5qԺ mJ>|3,uɀf>́F:v<]ڇ6ъUcDD=aH% |XX$,q@SI0E(( tlC 8a|lsқq)F7> ?>lAĩ+ c۸p'|\㡎qF4qsTD4r@ P#D=ᎦrsD}8RPbC0iP0,? ᐇ? r@k2ݕ(> */>b؆3N$F!JdG;:I%6 6$L%Vn.NP; ӘF2p BЄ0A ztT;ԑ{4$}dz]L2j@-yy@)dq GF*6#lE%04X"ġ KdXF$6l@+%|'j9rXCFjggb;Xqo1zO+>~h#l ?z0 MM5|-bl @x(E97i,YڧBU 8<#K-*jaID"T>HaJ |Np~| #†`UJQȄBQ` z8'{bJ8K0}pZH/(nQG`MHh[MFkNpOh0K>0gH:g92HH{x0xsr`N qmh~hvȆMeЅJkmzwyr cD+p8i(#eЄQli_>`DOce8LNd9^x$ c ؁CY#s0{9ob؅p] ~p؆}`*n?XBsEx,{ k~'EGNV0kV8SX/TcSTFxIbMȅOhF'i]g>Bc g{k? qqpca9G`_0E}0>gGsǫ9]76c SgSqa@_>8QAZiI0I@U_I:RІ<pCig |pN`>J1o ]0cSЅM_`b7}wPy'g4B>ϸ.~`zɹbhЄ`h?Ȇ@0\@U@[@KH\A^pSG0Bx-r.46#~36l T@C~Pf@P@X؄”CFzhl.bL ̶z cmapiKnHdPNc8iTXHjٴ_Z@heLDP9nڹlfN {2FxST@Q Cty0l (x{i臽L<`TpYTxJ\!L>2cOhiY-Yxtw>x{o$q?(<"Ļy9g0*x Am"DBgFu'VHѤU`MI`ZiTJ`,Ei l@J`I(:XdH:o0R{Xzهbp|5|`2Kt]U m(7vgKm|gԵSp}مipzkOc;RJf i2rh}g`t>d(>X\L| uh~(w؆ac@iS?8Aa`jz4g0aGs0iעs|g:k8qwix?[0rKPk]mІ!g5ZP73yDwq0J˯]XXNK?PalHs1@Jv'b91Zq ڂ:%݇pgцmc{Hnbv?Kryou]xpJІt5ZwCnji Kan_LZ Ն\*DUDP2jVݨ^Hu>KAhL~]xO0zc؇82g ӔdO MNpz_OU@IeW夛p|(+|_$O݅Շ̚Nh}z]Wpx~ʼ$ |0?E(d>0A<;PP@PSȆ {P+o8~RF3aEyWzD+d%pg  #%+qU$(J_-p 48hK`iTr4|% `070XSV&H)@u-j}cbp} M7^5PDhdپ|n`@}4s D0m}KS^{# ZF!wئ{x]}y1p_jN +,pf@\PM`q8A}rm d>sq{0es6ڟZ&Wk/脇rm05o ,o G;;Ь`%_(Q<1?q416⚴xxUjg=k0i9[~v ~I複Egt'&^peהIH?dmZXlre >D":# ~1K!s˒ЍϠmspi{CPlXiA82jQB_p-[m=nMl| 4BečեsЗC2Fye=r+^@XmdЅHI[HlkxI^=f.Z~hYm:}pzh5 J^lJ_X,J0l&i{mCpgz8Wa&ps5|:+Q|Xi>' )r5,: _KVz\Loƥ?˰9s}k~=&?sxVb =&F쬺q:}rBo'@O,XOɃfRug8NpeEs@yD9wfWM]u ,oȗw{7agFܛ3ngX>hg*WRpVcW{z%WJMGd`V\G{qFa1p'<&5 u@;q7;I7ہ$~^ڨ^GsT:JkJ4Hy8=ᓠ a${ p|!L7m }mh+J> Y|Wgb@mQ!{ ^b`x VH.)YmNZ6-Jwӳ8Au='{nz/{W*[ءMIwVhgcXڳ{ntvbP)X4r:ɧʷ̏?hN|ɏ'7 |cVJP@Ȁ@ !@1|[cC&,!03})_μУ3GHu'Im   4`\~ꌙOel@&W!` 0hP",>9h(,3d 4  8؀#!`PwtSL>Xf\vXs 4,d@ 0 X1ϗF Ё0d@ ,&PidGhh 7Tx{ЃHHy80 Whrh.Ё l`K8 xQchPB T+D@eH }HҐ40As1P_* {uRƈ0B PЀ@&<`!JL` : ;@|ޮF }<f, *00  @ 0 HWD/D$DHDBVPq"tGZØ@0`P 4L pMHT?QѼ N@D1& 0Mt #L:M@' 4/y -xH'@c& B C,bhr E ]zhFoAZ D z) _&D*P Q5Qč.fpl3t-SM7 읁|;Q4H1"0&{PhgN%obD\+ HsՄ( Hu31Fc0@ik8'$q1@P L]:/@A:wt [ 9Ў @M`ⵀlT& u; "np#! A qy2H+;ɞ \_Pw1Ёה 4`N`HbJ!!62q04:d!0.|.B ПA1htd7Q=K5QnnzȴCK7YdVpI< ]k }d/9oE6"|~sr F RH6,UA2h( @'746H'p-]+2[Vo^u[h\ pm sKMp UqS@3(3pL_nE`u7hv^1@#2c&sJ%`e((0JGb{4c^ vssxQa#)2>'0 #p3P'6bW"@5`k5h1e!Ƕ#C8Zm2OP*'7c@dIVaV hUd%B M`gxsb͐cO4 P€ X(p yUmq ^Q`  ȅQ)*h$ @ &PnYw*p^ `HHL"0 uY^$[~1*Jos^7Pu 0^ ]a`Q n`WxyBz* @WVa7' js(uQus/q&WK1 ryi ]M&){@ 5P:t3RwXAiS/#$d2PX*#MTxR2U'bbapiK0ay`^p9` 2rx0qiq ψyx a'Qcq`(`^`0UE&W%W]0NdsJ`-2]j_1]vڥ!zgR|]DB-M&&}bG XT &Ԅ$&cA"' M8 22 7nq`eB0 D"W4hV^i)Qpu`Pas@ag\tgɞvW0@[+'{E73d)0Bu P5B-`B2B"ÁGU/,`!bJ!:R pV2КVBVp14r{*2+G${V@jMM J2 zs_JQayyfaisd~gY8`|*]ߑta @+ (R7H'28cdraW𴢿Wep%, VWǤ[H"/" 0  7047: iV٦ @Wm4Yq3p^&4  }huRU'?f@; fkfW'6G5P5 ]|+3b+P5 GU¿ۃpHjmd%6`4\(BagyVw>avyajqy7>h}5W(`pp2(YSRPpk `) 0* s"JQE`*3sS¿\La3;4__Ǵi9pQɞesQ`s~kHmQ@p 1G6$f"2]Db+A$42 6 u|1J0 +gt3B$pLlne2ĒK=Qsg@zJqfs`ENG2l9xSv@&δ8 ,|  'aS7= g@QTa>ax28, n'W&5&a01`=Vur'Lud J QFh%Ȟ_ڻs2߹jIEW;wM2*P{uPM&#(3`7de @V+aMj L18pE]s_7疽sys v\}\sn~c"@o 'q/_U#7!@q#UlP s|`Kafz\KՖQmv\J p(o iE2Xzy23 *xC` Ь\pEky' Kp\:mK\QhdV\UAy$@8:O!'@0 `Yv&`g3g wKEQэ :s=wgjO jiթ x@"#:RY ,eT(&#{b!0c\La1h L U0ǝSV% yjǝWA MTC|N+P!NMeT˳2>URGn ǵ+zQ x)6?U=‡`BTA_b# q|L܃FBfp P лdXm1刬3n. c`@+p ~@P ̒ac8Q|NkQۚ&Zf "@=3bJdJ K} lQ` P P;suS]ruQ k@R*`+Pz I@w{mj>4 BP[V 0Cjq W2p ~ ԉVGyu`U- =7~ 0 L? k@6_ N sF^3.ij6?`"@ PNž  p 0 ~H$M$ I$I $(AM$AThP@2eJ%ɓ%SA٦K#*P!%di?~;ӧ?EIthQ@6=4QU^5 t)|3l*0u_ϞIFX.Qr4 PH F0R_O-.TPR b}NFIBzA3؄@> TpfSLIEJ8Dk!'5+" +Ұ.9P6|YI%؂%&vGCopyɷݞʪPQ7}@\Q`^"d%Nd)Q QF1i$K*S&ADL +#,hB>3EQP8ڐ"vh{om D w[7Fw}̹5 I> eA!CSBFQSR@&YHL(8B &+HJ(Z$)e,zHŒB`C8s|!sf|M6.4jpS47E%UL/ qpPD-a[>!-T@C'D }0= u@N-vQ5wHUK^.7(mgG=6q 6a]T$fZXt yG }8#i01_Eه iy = {<0gK:",&Q ftq~ @pc@?A|<Û .Vhp|$X؅;Tq4P)6a# .jf؃J)?'`i5F;͎XF/Rq NL"4e3;AuPGʪdc ]82pл>Rȭ38E &j@3"GR! }R)S C(f٫=bB~H$, T BňF*|QET8< b܃hڕq4UCUG!0"Т>z.ݓ6 hP5oX`G+,kvoVˡN6M lEv=gPƸhLb}(R[Ѓ 4x0Mp; P>$t?Z}lc8*Pq_c&2QmP:Jc/>x(/4MQVTiNsG S¹n!>M?a HʃO4=2jN'@Z(aܴ+.C?;AkΚpچ0}rqchP@Ybl?Pr0Bh-/ 3YJY>EmL[dKKf*r]?`'fm(O!uD~Rxmz0| 9kEw@NOQ \Tw{,-}І׋zȶmH)Yhck\F]%^HT]Q_(HJgp`c8آ]G :?[q1.wpm}pcGrJI`Z@Zan-B*Kp h)pdX>@^Oi8F``T(a8HxF0IWPPm܅L(VT=Vx *J[6svgkhcXBf@$Wd$~ H:.SYЀ50, gZbIOhN,\X@ShB؁d!pb؅wyD".gzhyVs͢+qJJhxAʤKˤ,p? PR($pIbxIL8AzH0z0|sGz}G8룆+0>6Z,3hvRP\9?A#.qa{h0p8R&4Ju/V;=c ~@3Ȃx6PFS\O}$rنn SmNxjg&?_J@2*{A6r Թzن~(1rX J"qddgXK8yh|cqr!㉡vH>0ZXQH8mnmlKDDmpbU)Ђ堁):Ѐoحz%{37A$zJ6L:oZ@m@_f`e[G8k8R!ħ'κ6̢xHw8p}pV$ko,> ̓ NOL22{p Dza\Є@0n?c-sXH=ۀPb0vx᪩~`m@+6x$g؅Nyy(1ٷn"JM";KƝޅp9x,Ȃ7xCNƤ"Ko\pLp؅~Uo0`L?(Tw =hbluh?nyQw?o&| qEoȓNĤq=uBJcp:qG2s)Lb>qA骋&W=Z,.4b@.,׻Ҵ&wV5`HbߖM_ 5o7S3:Sc]H_w:nm913)%H~]HWJ;6;7i3!cxp(iyBAr0i3ni$9!mP5bhk.sv6Xu?bwL0=60=.i8RKA2R]e# >!y |)z(x0M5$ }`g}=&mic9C Ö*cZL_(pp$R)fp(`JG` wclmv3fɒ7GytI],pJ`"4)B(C $HtVHg)v v=Ϭpv)61Fu?'7'?؅N؅g R` `p P$G''~{J{wjNHbJiZ3؝D|Y'mJ؅Xh^_cXרX_Zg!J*‹G!ԯ,ԙw und?|+/GA^bM+~Vwr50X'~G͢m jM~k ܶ-^?#Jh"ƌ7r쨑:cƈ,9$ʔ*Wcrd? .zXB #` (LF\:S+bĞ tΜ;z Stream EXchange

    Stream EXchange (SEX)

    You can imagine SEX as network wide UNIX pipes with a relay between or as network based FIFOs.
    This can be useful for piping data from A to B where A and B cannot establish a direct connection, but both can connect to the SEX-server by HTTP.
    SEX is a synchronous service in conjuction to F*EX which is asynchronous.

    For seamless integration into the UNIX tool chain, there are the shell-tools sexsend and sexget.

    Using web browsers for sexing will not work, because they cannot handle streams in a pipe. So far, there are only the UNIX clients. Feel free to implement other clients for other operating systems :-)

    Authentication is the same as with F*EX.

    Example:

      root@lanldap:/var/log: tail -f syslog | sexsend framstag@rus.uni-stuttgart.de
    
      framstag@blubb:/tmp: sexget | grep ldap
    

    If you need encryption, then use the standard UNIX toolbox and add an appropriate program to the pipe, for example: openssl bf

    public SEX

    The recipient of regular SEX must be a registered F*EX user.
    But you can also offer streams to non-registered user.
    This is called "public SEX", example:

      framstag@flupp: cal | sexsend public
      http://fex.rus.uni-stuttgart.de/sex?user=framstag@rus.uni-stuttgart.de&ID=public
      http://fex.rus.uni-stuttgart.de/sex?dXNlcj1mcmFtc3RhZ0BydXMudW5pLXN0dXR0Z2FydC5kZSZJRD1wdWJsaWM=
    

    sexsend then displays two URLs onder which one can get the stream.

    SEX - all inclusive

    To transfer files by streaming you can use xx-rated SEX:

      root@vms2:/data/VM# sexxx flupp
      streaming:
      flupp/
      flupp/vmware.log
      flupp/flupp.nvram
      flupp/flupp.vmxf
      flupp/flupp.vmx
      flupp/flupp.vmdk
      4976 MB 11640 kB/s
    
    fex-20130805/htdocs/sup.html0000644000174700017470000000324712163054456013677 0ustar fexfex F*EX simple upload

    F*EX simple upload


    your e-mail address:
    your auth-ID:
    your file:


    After "submit" you will see an upload progress bar (if you have javascript enabled and popups allowed).

    If you have lost your auth-ID use "?" as auth-ID and select a small dummy file. Your auth-ID will be sent by e-mail to you.

    You can also use the regular upload form (with more features).

    NOTE: Only Firefox or Google Chrome can upload files > 2 GB!


    Contact: fexmaster
    fex-20130805/htdocs/features.html0000644000174700017470000000643612170456166014713 0ustar fexfex F*EX feature list

    F*EX feature list

    • file transfer of virtually unlimited file size
    • recipient and sender only need an e-mail program and a web browser - of any kind, they do not have to install any software
      (the F*EX server itself is UNIX based)
    • RESEND and REGET for resuming after link failures at last sent byte
    • auto-notification of recipient
    • auto-deletion after download
    • auto-deletion after expiration date (default: 5 days)
    • full-users can create one time upload URLs for foreign users
    • full-users can create sub-users, who can send only to this full-user
    • full-users can create groups, an analogy to mailing lists, but for files
    • admin can allow (internal or external) user self-registration
    • admin can allow upload to public recipients without authentification
    • admin can allow upload for LAN users without registration (anonymous upload)
    • user can forward a file to a second recipient without re-uploading it
    • adminstration by CLI or Web
    • server based user address books
    • user and admin can throttle bandwith usage
    • admin can restrict access based on e-mail or ip addresses
    • sending to multiple recipients needs storage on the server only once
    • quotas for sending and receiving
    • support for named based virtual hosts (multiple server instances with different hostnames on same IP)
    • support for streams, including streaming recursive file transfer
    • support for file linking (upload just a link, not the file itself)
    • integrated web server with special features:
      • HTML with inline perl code
      • HTML with conditional if..then..elseif..end blocks
      • HTML with include statement
      • on-the-fly zip, tar and tgz streaming output
      • (restricted) directory file viewer
    • for real UNIX users, there are the shell programs fexsend and fexget
      to avoid annoying web browser usage and with a lot of additional features,
      also there is an Internet clipboard and anonymous usage
    • protocol and source-code free available
    • localization for many languanges available
    • optional authentification by LDAP, RADIUS, POP, IMAP, mailman
    • server available for UNIX and Windows hosts
    • about 10 times faster than apache
    • (reverse) proxy support
    • F*EX is a HTTP web-service and needs no firewall-tunnels
    • works with NAT or DHCP clients, too
    • postfix filter available to send e-mails with attachments of any size
    • maintenance-free: no admin interaction necessary
    • minimal software & hardware requirements for the server
    • easy server installation, no installation necessary on client side
    • great FAQ, use cases and detailed internal documentation
    fex-20130805/htdocs/logo.jpg0000644000174700017470000003364010777060530013643 0ustar fexfexJFIFMCreated with GIMP CREATOR: XV Version 3.10af Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222@" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( (+_ǧYIu2G2d@I*>/Z~(r{pE|j濘v=t|){s/fۀ~v g=}:sǹѮmu7 "G-s7τL5oY98=G=yVj2IuytZ-M^ b1T^߼_-kmcC p{^sy&˫mG TzƼOLo2  rRuvUjse\Kiw Mhw^I>jkK.RpȭM/cԠkf̱Мrq{u]uݵfK[@v}2>*;40xx~~4+J |rn GPO,N7b$:RF@7^N{JU/en:m6TUb0CyUHmaY3Z  Ѿ?X`_CVPӮ)NXZћ7P..q+xVml,v&Au'ߟ\")fc&ZlNB. =P= \QEyQEQEQEQEQEQEQEQEQEQEdY=vK)0&{ k׎]uo*~^g|K|; /Ya%E A8*H8kW?5QWܓ%G]Fs׌sa^\qRvЭII_SKӡt謠gh O$z4"JY*i '$=+sz*Vm3G_V+մ[jE{(pHKhaK }Ts_/kƠKwI+E2IiaG%$".qT+Ƭn~Ũ[]lʲm33Wm;4KBSH:##= :O2X_wFN=2;W]iGxeuÁ~x={·e?`s~rq]41{V}_R Wtz7?iwrA c8b3V`/E+/ij.6E|oCDk3ZfA:>zok8zcj̳k(8B(((((((((( Z&~ O>$o)-$ 2$!o ɻ>>8[s],U9#9HّԆVSA_5o*;PRUa`50b/'Z^dn3ٮyI!lᑾa3GlWK^aO[ܷ]Nނp2jZ, >Jd:X>O?v3CqzW+wҵ5n }{iq$7P>Rhz`y+۴B?zH VsdBq0Wc9˩{sܐCIg!^/;Q-!Oy={6HAש·%V:>쵉A + $QDE ~+#B!MIc#q_A1UJEF22xʜp[q[ӨlU`NVf\jRC ":$U5?N&%?5pe\?{+5XntdH*99;ɞjhwٕ] vݗqU#X58+%YFr֠hAq;]W-<[@iƛ䅹VPqON9]qA޾X[ ,D<=qN:tog pw nT׼pՠӼÑ_WV+[ICF9$AR[裊Lpߧ{]D,F!(!@=O5c/ֹkIKqbt&Y['=o?IJxg^ԡnW˹(Xd=!\ @~VyrcpXӯnԓi5f}-yiiCʛ?cڸ9}=+P_٘Io39ϯ]鿽/ qw|)xqZ: +eja3o&$0yNzV|=Է25I;erOsӯ^QrŬIs|3ݹq$V0ަ]EsZXnN1?isLV0st'9Ǖ:*+<%ˌ\fܭ0GɒM}H,/RIIDP_Qz(/1DZӏߴr=>^~%uSYe1- a7M^H1Ǽgʠ8 n36=Iǧfě`~nltj\ܥ ^@^,y8sҟ#+?t#/9=s=sA#$p独HE,rT)$O+{LYumf 8*@ֽƊDxc_?41s}i׋V<}Mv9W^E$y*폮*'J1w4VRVGhrɺks. OkT.@r=*d|N;GvҤ<%Swcx̹=p<agF•lu=;zz%ASj’ҢL@ʀ:~iwڪ nf'8}1@G =eC󘱹=?҅`Aܚ7Yj+8#$g3OpyU.Cv<haydE zz_C TP-j../z7ڕ;H mџBpByӾj٦K0\q/^:vUP] ^ 06[946`IdOYwqIcGwnA*]N ᅰ[S!\m$?cwi*FQ@UP0:qn[QTHQEQEQEQEW(G+c,G;sM&Bm-Yb{ ZOjN4( Z2ۉӧ. -2`1r$s=)F)b/=cmz.1ZȊ$nlnaڋm:XGĀd>W(1IKvQAZs((L -QEQEQEQEQ\_ٯSvwokiqϯNs55nơ}2uҰYfu&aA$cԅIaA,1i&i3*AgS;D`@6?tH%]Uƹj|5o[CC^HmUo/n9V;\s߷gR+oԆ@ՂW q#a s~:K&r>b]OEZ޿R;u` d8<#NV2NrFm1:v1-oNpFqm7A[MNP[*@mf@JAHNO pչE> 0G8@R6zGzi>t2\2˟8ڹy XGiʣ}?#I5{TZv8|tߐ. mH=OsۥeoZ{7M1M#/n:Wo3Y٬W釙1b]PɌzxY.i;^/R劽FVQm4r[#0uIzslįeDn m_kU?[#BW#$]pw24i"dJ!)3!ʻNn\’//c79g] #5w7okW ko"Ҭ_>.=r*Zqvպ!V 1>|c}snLן\$>bYFy s]ax<;f =8y>_*%"Fuprpx8y&j5~!V"gvK0zon:K#$hD?<K뫈ۓyۀ XIbz{[BяDJ+g1iѯ&CnW-.bI;H;w$.䕵 ±q6f'`}Ol84{3KH `HlYvx$|ư/`R$'bJw1Sߡ n{[X&1a 2I/vM{-.EԄ[pC(q8=TMJ >[Un|@wO][q:Uwst0@G88O< մ1dX,6H`H%'ߍcc_"yP`%PT }}kGH,!5,* ajK,W(#]̍2,k `݂T\w8| z3%r(u8A%R4KN"4HꋼS NsKڊ(((((((|Qq #n^ =+zC[ vO)` җ,3h4ej)6,NAAq(m7`Ӥ1.w\}p~-[>+xǝl猞̧#:FE1e.O.[t|,۞W3t7es_7A,P>`6wdG# =2E-CLY%cTx^ q⮲AuhK픕iN^̪GX$SY U%',rF<<}*φ-AOU9GCz7$n#&t-~)T?08$$5$fRDt/bP'9p÷OZr} 73"kt-М(-Cp41W5ô/<[!k{ɭd,w,e%V'$1##B.o\Y1 48;>TM d]Kgy/Ѯ0J&өgt50^xW$,emrUyᘁ>PƗ]CѯP1V(s``_Xa IFv10K<8ͻ>XzE1Rߟ~c\]Iogy<+\FQ vA ]jۆ4JQ+hij`z1nkB+K7[~-RRcwcIck~2Vp*m/ސ nlg<&اֻ:#DXTE UJuWQEQEQEQEQEQTu uMkz*8)(⺸ʐG4¹k`xc?Yµf^>s#{>gڰuv?W]g'c ={x3kW]g'c ?uv?K_>s"֥h:ϻ1O_ݾ1AwQ\a"W'3&jzGea dT-6:ȍnP}ⲂHG͑צ4PVm}̜{{MG ) n@,SeupiXa'3̠wPǬkQoi$Z'GGAuA8ZycׇWQRH}[rKf2[BNsRkx k$X=:fTXce}cW:p1QuQ^6ROH5-BԳ5OlgW@KK =TO3N3X(GunΤ=1q"DTctugvbjZPN4V#)SsA{55Tf[y?d<=|XJB+֯gj,GBN}/Hڮhh\V~^meү\8`83G?uv?W]g'c $_1Jqo_\NMwrH隩47F!#Yo,  0\g.K& r.۞x s*z\zV=w8kJKC!uyc%T10y9GNߝM&{u,utsK3Ex$bcsJ]rZlM<7\" G:[ 7Sk7mɎEv:PÚGyc`nv 'X`6zo\N9=k%a/%Qw=$ Rd?w!8uvo˿.~wy#4 Y'9f v!ze `tP;zm,Rn^M7aVDҌvG\ =[ (5 ( ( ( ( (21{=?m'yS9,Bh% bȝ8DZSUkAMWE֪1թv_ j?? >WԻ! 4kAMWE}jթvC-)@h2&(_R(eeo=LHը5oC]1cQI*?k=gVO A(j:9VE?LE%^كM o j?(^.e5_MZSUEZ>KmAMWG! 4QG֪R[SU]}OT>WԻռmyvtE ~QPT}JTit(2R =nun*E-(0((((((fex-20130805/htdocs/robots.txt0000644000174700017470000000003211602077055014235 0ustar fexfexUser-agent: * Disallow: / fex-20130805/htdocs/fup_template.html0000644000174700017470000000336712163054456015560 0ustar fexfex F*EX upload template

    F*EX upload template


    sender: (e-mail address)
    auth-ID:
    recipient(s):(e-mail address)
    comment: (optional)
    file name:


    After "submit" you will see an upload progress bar (if you have javascript enabled and popups allowed).

    NOTE: Most web browsers cannot upload files > 2 GB!
    If your file is greater you have to use a special F*EX client.
    You also need one for resuming interrupted uploads. Your web browser cannot do this.


    Contact: fexmaster
    fex-20130805/htdocs/download/0000755000174700017470000000000012177755046014013 5ustar fexfexfex-20130805/htdocs/FAQ/0000755000174700017470000000000012177755050012606 5ustar fexfexfex-20130805/htdocs/FAQ/index.html0000644000174700017470000000330312163353545014600 0ustar fexfex F*EX FAQ

    F*EX FAQ

    #if not -s "local.faq" #endif <> #if -s "local.faq"
    <>
    #else
    <>
    <>
    <>
    <>
    <>
    #endif ## << faq($ENV{QUERY_STRING}) >> fex-20130805/htdocs/FAQ/all.html0000644000174700017470000000200712163354375014243 0ustar fexfex F*EX FAQ << my ($n,$f); local $/ = "Q:"; local $_; print qq(

    F*EX FAQ All

    \n); foreach $faq (qw(meta user admin misc)) { $n = 0; open $faq,"$faq.faq" or return; $f = $faq; $f =~ s/(.)/uc $1/e; print "

    $f\n"; print "\n"; $_ = <$faq>; while (<$faq>) { chomp; while (/\$([\w_]+)\$/) { $var = $1; $env = $ENV{$var} || ''; s/\$$var\$/$env/g; }; ($Q,$A) = split /A:s*/; $A =~ s/([^>\n\\])\n/$1
    \n/g; $A =~ s/\\\n/\n/g; $A =~ s/<([^\s<>\@]+\@[\w.-]+)>/<$1><\/a>/g; $A =~ s: (/\w[\S]+/[\S]+): $1:g; $A =~ s/(https?:[^\s<>]+)/[$1]<\/a>/g; $n++; print "\n"; print "\n"; print "\n"; } print "
    Q$n:$Q
    A$n:$A
    \n"; close $faq; } >> fex-20130805/htdocs/FAQ/FAQ.html0000644000174700017470000000000012163353545021440 1fex-20130805/htdocs/FAQ/index.htmlustar fexfexfex-20130805/htdocs/FAQ/cat.pl0000644000174700017470000000225312163375311013705 0ustar fexfex$ENV{PATH_INFO} =~ /(\w+)/ and $ENV{faq} = $faq = $title = $1; $title =~ s/(\w)/uc($1)/e; print qq(

    F*EX FAQ $title

    \n); print "

    "; foreach (qw'Meta User Admin Misc All') { print sprintf('%s ',lc($_),$_); } print "

    \n"; $ENV{QUERY_STRING} =~ /(\d+)/ and $q = $1; my $n = 0; local $/ = "Q:"; local $_; $faq .= '.faq'; open $faq,"$docdir/locale/$locale/FAQ/$faq" or open $faq,$faq or return; print "\n"; $_ = <$faq>; while (<$faq>) { chomp; while (/\$([\w_]+)\$/) { $var = $1; $env = $ENV{$var} || ''; s/\$$var\$/$env/g; }; ($Q,$A) = split /A:s*/; $A =~ s/([^>\n\\])\n/$1
    \n/g; $A =~ s/\\\n/\n/g; $A =~ s/<([^\s<>\@]+\@[\w.-]+)>/<$1><\/a>/g; $A =~ s: (/\w[\S]+/[\S]+): $1:g; $A =~ s/(https?:[^\s<>]+)/[$1]<\/a>/g; $n++; if ($q) { if ($q == $n) { print "\n"; print "\n"; } } else { print "\n"; print "\n"; print "\n"; } } print "
    Q$n:$Q
    A$n:$A
    Q$n:$Q
    A$n:$A
    \n"; fex-20130805/htdocs/FAQ/upArrow.gif0000644000174700017470000000007611620513343014724 0ustar fexfexGIF89a AAA!, @bS,IX8cZ]ȕ;fex-20130805/htdocs/FAQ/admin.faq0000644000174700017470000001114212170455606014363 0ustar fexfex

    Admin questions

    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/ * http://freshmeat.net/projects/eventh/ * http://www.schaarwaechter.de/sp/projekte/dateiaustausch.html (German only!) which implement a file exchange as pure CGIs, but with a 2 GB file size limit, which F*EX does not have. Q: I have already a webserver (apache) running. How can I install F*EX parallel? A: You have to use another port or ip for F*EX, because you cannot run two services on the same ip:port combination. For example port 88, use "./install -p 88" For another ip you can create a new virtual interface or use a virtual machine. See the documentation of your UNIX. Q: F*EX is not working at all! I cannot connect to it with my web browser! A: Check your routing, ipfilters and firewall setup. Also check whether your xinetd is linked with tcp-wrapper and configure it correctly (hosts.allow). F*EX needs port 80/tcp for HTTP and optional port 443/tcp for HTTPS. Q: What is the difference between all these user types (full, sub, group, external, ...)? A: See http://fex.rus.uni-stuttgart.de/users.html Q: How can I integrate F*EX in the existing user management at my site? A: F*EX has several authentification modules: local, RADIUS, LDAP, mailman and POP. For the last 4 please contact Q: I want that all of my local users can use F*EX. How? A: Let them register themselves with http://YOURFEXSERVER/fur You have to edit /home/fex/lib/fex.ph and set (example):
         @local_hosts = qw(127.0.0.1 10.10.100.0-10.10.255.255);\
         @local_domains = qw(flupp.org ulm.sub.net);\
       
    Or you can allow anonymous upload for your LAN users with fex.ph variable @anonymous_upload Example:
         @anonymous_upload = qw(10.10.100.0-10.10.200.255 129.69.1.11);
       
    (Of course you have to use your real local hosts/networks!) Q: I want that external users can fex to my local users. How? A: Let them register themselves with http://YOURFEXSERVER/fur You have to edit /home/fex/lib/fex.ph and set (example):
         # your local receiving domains\
         @local_rdomains = qw(flupp.org *.flupp.org);\
    	     \
         # your local receiving hosts\
         @local_rhosts = qw(127.0.0.1 129.69.0.0-129.69.255.255 176.9.84.26);\
       
    Or you can manually create a restricted external user with (example):
         fac -u framstag@rus.uni-stuttgart.de hoppla\
         fac -R framstag@rus.uni-stuttgart.de\
       
    Q: I have BIG files already on the fexserver host. Can I upload just a link instead of the whole file? A: Set in fex.ph:
       @file_link_dirs = qw(/directory/with/big/files);
       
    and use:
       fexsend -/ /directory/with/big/files/BIG.file recipient@wherever
       
    Q: I want the Bcc mails to fex (admin user) to be sent to another address. A: Set variable $bcc in /home/fex/lib/fex.ph Q: I need more security! How can I enable HTTPS? A: Read doc/SSL and also look for "fop_auth" in doc/concept Q: I need a corporate identity look. How can I configure F*EX in this way? A: * See variable @H1_extra in /home/fex/lib/fex.ph and you can add HTML code to /home/fex/htdocs/header.html * See /home/fex/htdocs/fup_template.html, modify it to your needs and use it as your start-page. * Contact http://www.nepustil.net/ if you need more customization. Q: F*EX is too complicated for my tie users. I need a simplified upload form. A: See /home/fex/htdocs/fup_template.html and /home/fex/htdocs/sup.html or use public upload, see http://fex.rus.uni-stuttgart.de/usecases/foreign.html Q: F*EX is still too complicated! I need something more simplified. A: Try http://www.home.unix-ag.org/simon/woof.html Q: Can I integrate F*EX in my users MUAs (thunderbird, outlook, etc)? A: See http://fex.rus.uni-stuttgart.de/usecases/BIGMAIL.html Q: Can I get a localized version in my native languange? A: With your help, yes. Please contact Q: I need ACLs for group access, a file browser and integration in my native file system. A: This is beyond the scope of F*EX, which is designed for file transfer. Q: Feature/design XY is missing. A: Contact the author Q: How can I use my own local FAQ? A: Put your FAQ into file /home/fex/htdocs/FAQ/local.faq fex-20130805/htdocs/FAQ/misc.html0000644000174700017470000000026712163376473014437 0ustar fexfex F*EX FAQ ##
    ## << while (($v,$vv) = each %ENV) { print "$v = $vv\n" } >>
    ## 
    <> fex-20130805/htdocs/FAQ/misc.faq0000644000174700017470000000141612167571146014235 0ustar fexfex

    Misc questions

    Q: F*EX is great! Can I join the developing team? What needs to be done? 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
    • a F*EX plugin for thunderbird or outlook see thunderbird's filelink https://support.mozillamessaging.com/en-US/kb/filelink-large-attachments https://developer.mozilla.org/en/Thunderbird/Filelink_Providers
    • more (other) languange support (japanese, bavarian, klingon ...)
    Q: Can I donate something for F*EX? A: If you have a pet animal, fex a cute video of it to the author fex-20130805/htdocs/FAQ/faq.pl0000644000174700017470000000236512163312624013707 0ustar fexfexsub faq { my ($faq,$var,$env,$q,$a,$c,$n); local $/ = "Q:"; local $_; foreach $faq (@_) { $c = $faq; $c =~ s/(.)/uc $1/e; $c = '' if $c eq 'Local'; open $faq,"$faq.faq" or return; $_ = <$faq>; $n = 0; while (<$faq>) { chomp; while (/\$([\w_]+)\$/) { $var = $1; $env = $ENV{$var} || ''; #s/\$$var\$/$env<\/tt>/g; s/\$$var\$/$env/g; }; ($q,$a) = split /A:s*/; $a =~ s/[\s\n]+$/\n/; 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 } $a =~ s/\n\n/\n

    \n/g; $a =~ s/([^>\n\\])\n/$1
    \n/g; $a =~ s/\\\n/\n/g; $a =~ s/^\s*
    \s*//mg; $a =~ s/<([^\s<>\@]+\@[\w.-]+)>/
    <$1><\/a>/g; $a =~ s: (/\w[\S]+/[\S]+): $1:g; $a =~ s/(https?:[^\s<>]+)/[$1]<\/a>/g; $n++; print qq(

    \n); print qq(

    $c A$n:

    \n); print qq(
    $a
    \n); } close $faq; } } fex-20130805/htdocs/FAQ/downArrow.gif0000644000174700017470000000007611620513356015253 0ustar fexfexGIF89a AAA!, @R΋vtM;fex-20130805/htdocs/FAQ/admin.html0000644000174700017470000000000012163376473021752 1fex-20130805/htdocs/FAQ/misc.htmlustar fexfexfex-20130805/htdocs/FAQ/user.html0000644000174700017470000000000012163376473021640 1fex-20130805/htdocs/FAQ/misc.htmlustar fexfexfex-20130805/htdocs/FAQ/tmp/0000755000174700017470000000000012177755050013406 5ustar fexfexfex-20130805/htdocs/FAQ/tmp/index.html0000644000174700017470000000513312163232166015376 0ustar fexfex F*EX FAQ

    F*EX FAQ

    << sub faq { my $faq = shift; my ($var,$env,$q,$a); my $n = 0; local $/ = "Q:"; local $_; open $faq,"$faq.faq" or return; $_ = <$faq>; while (<$faq>) { chomp; while (/\$([\w_]+)\$/) { $var = $1; $env = $ENV{$var} || ''; #s/\$$var\$/$env<\/tt>/g; s/\$$var\$/$env/g; }; ($q,$a) = split /A:s*/; $a =~ s/[\s\n]+$/\n/; 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 } $a =~ s/\n\n/\n

    \n/g; $a =~ s/([^>\n\\])\n/$1
    \n/g; $a =~ s/\\\n/\n/g; $a =~ s/^\s*
    \s*//mg; $a =~ s/<([^\s<>\@]+\@[\w.-]+)>/<$1><\/a>/g; $a =~ s: (/\w[\S]+/[\S]+): $1:g; $a =~ s/(https?:[^\s<>]+)/[$1]<\/a>/g; $n++; print qq(

    \n); print qq(

    A$n:

    \n); print qq(
    $a
    \n); } } >>
    <>
    <>
    <>
    <>
    ## << faq($ENV{QUERY_STRING}) >> fex-20130805/htdocs/FAQ/tmp/FAQ.html0000644000174700017470000000000012163232166023033 1fex-20130805/htdocs/FAQ/tmp/index.htmlustar fexfexfex-20130805/htdocs/FAQ/tmp/upArrow.gif0000644000174700017470000000007611620513343015524 0ustar fexfexGIF89a AAA!, @bS,IX8cZ]ȕ;fex-20130805/htdocs/FAQ/tmp/admin.faq0000644000174700017470000001011012162657436015163 0ustar fexfex

    Admin questions

    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/ * http://freshmeat.net/projects/eventh/ * http://www.schaarwaechter.de/sp/projekte/dateiaustausch.html (German only!) which implement a file exchange as pure CGIs, but with a 2 GB file size limit, which F*EX does not have. Q: I have already a webserver (apache) running. How can I install F*EX parallel? A: You have to use another port or ip for F*EX, because you cannot run two services on the same ip:port combination. For example port 88, use "./install -p 88" For another ip you can create a new virtual interface or use a virtual machine. See the documentation of your UNIX. Q: F*EX is not working at all! I cannot connect to it with my web browser! A: Check your routing, ipfilters and firewall setup. Also check whether your xinetd is linked with tcp-wrapper and configure it correctly (hosts.allow). F*EX needs port 80/tcp for HTTP and optional port 443/tcp for HTTPS. Q: How can I integrate F*EX in the existing user management at my site? A: F*EX has several authentification modules: local, RADIUS, LDAP, mailman and POP. For the last 4 please contact Q: I want that all of my local users can use F*EX. How? A: Let them register themselves with http://YOURFEXSERVER/fur You have to edit /home/fex/lib/fex.ph and set (example):
         @local_hosts = qw(127.0.0.1 10.10.100.0-10.10.255.255);\
         @local_domains = qw(flupp.org ulm.sub.net);\
       
    Or you can allow anonymous upload for your LAN users with fex.ph variable @anonymous_upload Example:
         @anonymous_upload = qw(10.10.100.0-10.10.200.255 129.69.1.11);
       
    (Of course you have to use your real local hosts/networks!) Q: I want that external users can fex to my local users. How? A: Let them register themselves with http://YOURFEXSERVER/fur You have to edit /home/fex/lib/fex.ph and set (example):
         # your local receiving domains\
         @local_rdomains = qw(flupp.org *.flupp.org);\
    	     \
         # your local receiving hosts\
         @local_rhosts = qw(127.0.0.1 129.69.0.0-129.69.255.255 176.9.84.26);\
       
    Or you can manually create a restricted external user with (example):
         fac -u framstag@rus.uni-stuttgart.de hoppla\
         fac -R framstag@rus.uni-stuttgart.de\
       
    Q: I want the Bcc mails to fex (admin user) to be sent to another address. A: Set variable $bcc in /home/fex/lib/fex.ph Q: I need more security! How can I enable HTTPS? A: Read doc/SSL and also look for "fop_auth" in doc/concept Q: I need a corporate identity look. How can I configure F*EX in this way? A: * See variable @H1_extra in /home/fex/lib/fex.ph and you can add HTML code to /home/fex/htdocs/header.html * See /home/fex/htdocs/fup_template.html, modify it to your needs and use it as your start-page. * Contact http://www.nepustil.net/ if you need more customization. Q: F*EX is too complicated for my tie users. I need a simplified upload form. A: See /home/fex/htdocs/fup_template.html and /home/fex/htdocs/sup.html or use public upload, see http://fex.rus.uni-stuttgart.de/usecases/foreign.html Q: F*EX is still too complicated! I need something more simplified. A: Try http://www.home.unix-ag.org/simon/woof.html Q: Can I integrate F*EX in my users MUAs (thunderbird, outlook, etc)? A: See http://fex.rus.uni-stuttgart.de/usecases/BIGMAIL.html Q: Can I get a localized version in my native languange? A: With your help, yes. Please contact Q: I need ACLs for group access, a file browser and integration in my native file system. A: This is beyond the scope of F*EX, which is designed for file transfer. Q: Feature/design XY is missing. A: Contact the author fex-20130805/htdocs/FAQ/tmp/misc.html0000644000174700017470000000250612146006505015220 0ustar fexfex F*EX FAQ ##
    ## << while (($v,$vv) = each %ENV) { print "$v = $vv\n" } >>
    ## 
    << $ENV{PATH_INFO} =~ /(\w+)/ and $ENV{faq} = $faq = $f = $1; $faq =~ s/(\w)/uc($1)/e; $f = lc $f; print qq(

    F*EX FAQ $faq

    \n); print "

    "; foreach (qw(Meta User Admin Misc)) { print '',$_,' '; } print "

    \n"; $ENV{QUERY_STRING} =~ /(\d+)/ and $q = $1; my $n = 0; local $/ = "Q:"; local $_; open $faq,"$f.faq" or return; print "\n"; $_ = <$faq>; while (<$faq>) { chomp; while (/\$([\w_]+)\$/) { $var = $1; $env = $ENV{$var} || ''; s/\$$var\$/$env/g; }; ($Q,$A) = split /A:s*/; $A =~ s/([^>\n\\])\n/$1
    \n/g; $A =~ s/\\\n/\n/g; $A =~ s/<([^\s<>\@]+\@[\w.-]+)>/<$1><\/a>/g; $A =~ s: (/\w[\S]+/[\S]+): $1:g; $A =~ s/(https?:[^\s<>]+)/[$1]<\/a>/g; $n++; if ($q) { if ($q == $n) { print "\n"; print "\n"; } } else { print "\n"; print "\n"; print "\n"; } } print "
    Q$n:$Q
    A$n:$A
    Q$n:$Q
    A$n:$A
    \n"; >> fex-20130805/htdocs/FAQ/tmp/misc.faq0000644000174700017470000000120712146005213015013 0ustar fexfex

    Misc questions

    Q: F*EX is great! Can I join the developing team? What needs to be done? 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
    • a F*EX plugin for thunderbird or outlook see thunderbird's filelink https://support.mozillamessaging.com/en-US/kb/filelink-large-attachments https://developer.mozilla.org/en/Thunderbird/Filelink_Providers
    • more (other) languange support (japanese, bavarian, klingon ...)
    fex-20130805/htdocs/FAQ/tmp/downArrow.gif0000644000174700017470000000007611620513356016053 0ustar fexfexGIF89a AAA!, @R΋vtM;fex-20130805/htdocs/FAQ/tmp/admin.html0000644000174700017470000000000012146006505023335 1fex-20130805/htdocs/FAQ/tmp/misc.htmlustar fexfexfex-20130805/htdocs/FAQ/tmp/user.html0000644000174700017470000000000012146006505023223 1fex-20130805/htdocs/FAQ/tmp/misc.htmlustar fexfexfex-20130805/htdocs/FAQ/tmp/tmp/0000755000174700017470000000000012163233040014167 5ustar fexfexfex-20130805/htdocs/FAQ/tmp/tmp/index.html0000644000174700017470000000513312163232166016176 0ustar fexfex F*EX FAQ

    F*EX FAQ

    << sub faq { my $faq = shift; my ($var,$env,$q,$a); my $n = 0; local $/ = "Q:"; local $_; open $faq,"$faq.faq" or return; $_ = <$faq>; while (<$faq>) { chomp; while (/\$([\w_]+)\$/) { $var = $1; $env = $ENV{$var} || ''; #s/\$$var\$/$env<\/tt>/g; s/\$$var\$/$env/g; }; ($q,$a) = split /A:s*/; $a =~ s/[\s\n]+$/\n/; 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 } $a =~ s/\n\n/\n

    \n/g; $a =~ s/([^>\n\\])\n/$1
    \n/g; $a =~ s/\\\n/\n/g; $a =~ s/^\s*
    \s*//mg; $a =~ s/<([^\s<>\@]+\@[\w.-]+)>/<$1><\/a>/g; $a =~ s: (/\w[\S]+/[\S]+): $1:g; $a =~ s/(https?:[^\s<>]+)/[$1]<\/a>/g; $n++; print qq(

    \n); print qq(

    A$n:

    \n); print qq(
    $a
    \n); } } >>
    <>
    <>
    <>
    <>
    ## << faq($ENV{QUERY_STRING}) >> fex-20130805/htdocs/FAQ/tmp/tmp/FAQ.html0000644000174700017470000000000012163232166024433 1fex-20130805/htdocs/FAQ/tmp/tmp/index.htmlustar fexfexfex-20130805/htdocs/FAQ/tmp/tmp/upArrow.gif0000644000174700017470000000007611620513343016324 0ustar fexfexGIF89a AAA!, @bS,IX8cZ]ȕ;fex-20130805/htdocs/FAQ/tmp/tmp/admin.faq0000644000174700017470000001011012162657436015763 0ustar fexfex

    Admin questions

    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/ * http://freshmeat.net/projects/eventh/ * http://www.schaarwaechter.de/sp/projekte/dateiaustausch.html (German only!) which implement a file exchange as pure CGIs, but with a 2 GB file size limit, which F*EX does not have. Q: I have already a webserver (apache) running. How can I install F*EX parallel? A: You have to use another port or ip for F*EX, because you cannot run two services on the same ip:port combination. For example port 88, use "./install -p 88" For another ip you can create a new virtual interface or use a virtual machine. See the documentation of your UNIX. Q: F*EX is not working at all! I cannot connect to it with my web browser! A: Check your routing, ipfilters and firewall setup. Also check whether your xinetd is linked with tcp-wrapper and configure it correctly (hosts.allow). F*EX needs port 80/tcp for HTTP and optional port 443/tcp for HTTPS. Q: How can I integrate F*EX in the existing user management at my site? A: F*EX has several authentification modules: local, RADIUS, LDAP, mailman and POP. For the last 4 please contact Q: I want that all of my local users can use F*EX. How? A: Let them register themselves with http://YOURFEXSERVER/fur You have to edit /home/fex/lib/fex.ph and set (example):
         @local_hosts = qw(127.0.0.1 10.10.100.0-10.10.255.255);\
         @local_domains = qw(flupp.org ulm.sub.net);\
       
    Or you can allow anonymous upload for your LAN users with fex.ph variable @anonymous_upload Example:
         @anonymous_upload = qw(10.10.100.0-10.10.200.255 129.69.1.11);
       
    (Of course you have to use your real local hosts/networks!) Q: I want that external users can fex to my local users. How? A: Let them register themselves with http://YOURFEXSERVER/fur You have to edit /home/fex/lib/fex.ph and set (example):
         # your local receiving domains\
         @local_rdomains = qw(flupp.org *.flupp.org);\
    	     \
         # your local receiving hosts\
         @local_rhosts = qw(127.0.0.1 129.69.0.0-129.69.255.255 176.9.84.26);\
       
    Or you can manually create a restricted external user with (example):
         fac -u framstag@rus.uni-stuttgart.de hoppla\
         fac -R framstag@rus.uni-stuttgart.de\
       
    Q: I want the Bcc mails to fex (admin user) to be sent to another address. A: Set variable $bcc in /home/fex/lib/fex.ph Q: I need more security! How can I enable HTTPS? A: Read doc/SSL and also look for "fop_auth" in doc/concept Q: I need a corporate identity look. How can I configure F*EX in this way? A: * See variable @H1_extra in /home/fex/lib/fex.ph and you can add HTML code to /home/fex/htdocs/header.html * See /home/fex/htdocs/fup_template.html, modify it to your needs and use it as your start-page. * Contact http://www.nepustil.net/ if you need more customization. Q: F*EX is too complicated for my tie users. I need a simplified upload form. A: See /home/fex/htdocs/fup_template.html and /home/fex/htdocs/sup.html or use public upload, see http://fex.rus.uni-stuttgart.de/usecases/foreign.html Q: F*EX is still too complicated! I need something more simplified. A: Try http://www.home.unix-ag.org/simon/woof.html Q: Can I integrate F*EX in my users MUAs (thunderbird, outlook, etc)? A: See http://fex.rus.uni-stuttgart.de/usecases/BIGMAIL.html Q: Can I get a localized version in my native languange? A: With your help, yes. Please contact Q: I need ACLs for group access, a file browser and integration in my native file system. A: This is beyond the scope of F*EX, which is designed for file transfer. Q: Feature/design XY is missing. A: Contact the author fex-20130805/htdocs/FAQ/tmp/tmp/misc.html0000644000174700017470000000250612146006505016020 0ustar fexfex F*EX FAQ ##
    ## << while (($v,$vv) = each %ENV) { print "$v = $vv\n" } >>
    ## 
    << $ENV{PATH_INFO} =~ /(\w+)/ and $ENV{faq} = $faq = $f = $1; $faq =~ s/(\w)/uc($1)/e; $f = lc $f; print qq(

    F*EX FAQ $faq

    \n); print "

    "; foreach (qw(Meta User Admin Misc)) { print '',$_,' '; } print "

    \n"; $ENV{QUERY_STRING} =~ /(\d+)/ and $q = $1; my $n = 0; local $/ = "Q:"; local $_; open $faq,"$f.faq" or return; print "\n"; $_ = <$faq>; while (<$faq>) { chomp; while (/\$([\w_]+)\$/) { $var = $1; $env = $ENV{$var} || ''; s/\$$var\$/$env/g; }; ($Q,$A) = split /A:s*/; $A =~ s/([^>\n\\])\n/$1
    \n/g; $A =~ s/\\\n/\n/g; $A =~ s/<([^\s<>\@]+\@[\w.-]+)>/<$1><\/a>/g; $A =~ s: (/\w[\S]+/[\S]+): $1:g; $A =~ s/(https?:[^\s<>]+)/[$1]<\/a>/g; $n++; if ($q) { if ($q == $n) { print "\n"; print "\n"; } } else { print "\n"; print "\n"; print "\n"; } } print "
    Q$n:$Q
    A$n:$A
    Q$n:$Q
    A$n:$A
    \n"; >> fex-20130805/htdocs/FAQ/tmp/tmp/misc.faq0000644000174700017470000000120712146005213015613 0ustar fexfex

    Misc questions

    Q: F*EX is great! Can I join the developing team? What needs to be done? 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
    • a F*EX plugin for thunderbird or outlook see thunderbird's filelink https://support.mozillamessaging.com/en-US/kb/filelink-large-attachments https://developer.mozilla.org/en/Thunderbird/Filelink_Providers
    • more (other) languange support (japanese, bavarian, klingon ...)
    fex-20130805/htdocs/FAQ/meta.html0000644000174700017470000000000012163376473021610 1fex-20130805/htdocs/FAQ/misc.htmlustar fexfexfex-20130805/htdocs/FAQ/meta.faq0000644000174700017470000000671612163305372014230 0ustar fexfex

    Meta questions

    Q: What is so special with F*EX? A: See feature list http://fex.rus.uni-stuttgart.de/features.html and use cases http://fex.rus.uni-stuttgart.de/usecases/ Q: Why not use one of the commercial services like DropLoad, ALLPeers, YouSendIt, etc? A: * They have a limit of 2 GB or even less. * Their security and privacy status is unknown. * They are not open source based. * There are no UNIX (CLI) clients for them. * They need java, active-X, flash or other evil plugins. * 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" on freshmeat.net. 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.rus.uni-stuttgart.de/Vortrag/tosa.html Q: Who is the author? A: The main author is Ulli Horlacher
    But there are also a lot of contributors. Q: What do I need to install F*EX? A: A UNIX or Windows host with a DNS entry, smtp for outgoing e-mail and one open and free incoming tcp port. And you must have administrative rights (UNIX: root) on this host. Q: What means DNS and smtp? What is a tcp port? A: Do not install F*EX. It is beyond your horizon. Q: Can I run F*EX on Windows? A: On client side all operating systems are supported, even Windows. If you want to run a F*EX server on Windows, then see http://fex.rus.uni-stuttgart.de/fexwix.html Q: Where can I get the F*EX sources? A: F*EX server for UNIX: http://fex.rus.uni-stuttgart.de/fex.html Q: I do not want to install an own F*EX server, but where can I use it? A: Contact http://www.nepustil.net/ Q: Isn't Perl too slow for this job? A: fex.rus.uni-stuttgart.de runs on an office PC and F*EX is able to handle uploads with more than 300 MB/s. 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.rus.uni-stuttgart.de/doc/Licence "I want peace on earth and goodwill towards men" http://www.youtube.com/watch?v=JHU0HinVhYc Q: Is there a F*EX mailing list? 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: Who else is using F*EX? A: For example: * German Aerospace Center http://fex.dlr.de/ * European Commission Institute for Energy and Transport http://fex.jrc.nl/ * High Performance Computing Center Stuttgart http://fex.hlrs.de/ * Swiss National Supercomputing Centre http://fex.cscs.ch/ * Institut Pasteur http://dl.pasteur.fr/ * Deutsche Kinemathek Museum für Film und Fernsehen http://upload.deutsche-kinemathek.de/ Q: Is F*EX secure? A: F*EX is written in Perl which does not have common security problems with buffer overruns, segmentation faults, heap and stack corruption. F*EX does not use an extra web server or a (SQL) database, so no typical web attacks are possible. F*EX was analysed by security company revshell.com and labeled as "secure". Q: Feature/design XY is missing. A: Contact the author Q: I have more/other questions than in this document! A: Ask the author fex-20130805/htdocs/FAQ/user.faq0000644000174700017470000001326012173325740014252 0ustar fexfex

    User questions

    Q: What is the "auth-ID"? A: The auth-ID is an internal identification which authentificates the user. It will be first generated by the admin or the automatic registration process and can later be modified by you, the user. Think of some kind of a low security password. Q: Can I use a HTTP proxy? A: Yes, but pay attention: Some HTTP proxies like privoxy delay the upload progress bar! You may want to disable proxying $SERVER_NAME$ if you run into this problem. Q: I have uploaded a HUGE file but misspelled my recipient's address. Now I have got an error bounce e-mail. Must I re-upload the HUGE file? A: No, it is not necessary. You can redirect the file with "user config & operation control" Q: I have uploaded a HUGE file but forgot another recipient. Must I re-upload the HUGE file? A: No, it is not necessary. You can forward-copy the file with "user config & operation control" Q: My recipient has lost the notification e-mail with the download-URL. What can I do? A: Go to "user config & operation control" and see "Show download URLs of files you have sent" Q: How can I upload several files at once? A: Put your files in an archive file (ZIP), first. Your web browser cannot do that. Or you can use a F*EX client, see http://$HTTP_HOST$/tools.html Q: I cannot upload files > 2 GB with my web browser!? A: Many web browsers have bugs in their HTML-FORM implementation. The limit mostly is 2 GB, sometimes 4 GB. You have to use a special F*EX client to upload files > 2 GB, see http://$HTTP_HOST$/tools.html One exception is Firefox: F*EX has a workaround to handle its buggy upload implementation, so you can upload files of any size. Also Google Chrome has no limitation at all. But remember: No web browser is able to resume an interrupted upload. You need a special F*EX client like fexsend or schwuppdiwupp for resuming. Q: Why is the upload status window empty and I cannot see the progress bar? A: Most probably you are using a (enforced) web proxy, which cannot handle dynamic HTML pages. A workaround is using Google Chrome, which shows the upload status by itself. Q: My download was aborted before it was finished. Can I resume the download? A: F*EX supports resuming at download, but your client also has to support this feature. Firefox eg is missing this HTTP feature, you need an other client like opera, wget or fexget. Q: My upload was aborted before it was finished. Can I resume the upload? A: F*EX supports resuming at upload, but your client also has to support it. No web browser has this feature, you need a special F*EX client like fexsend or schwuppdiwupp, see http://$HTTP_HOST$/tools.html Q: Can I integrate F*EX in my mail program (thunderbird, outlook, etc)? A: Yes, if your mail admin has set up a "fexmail" smtp relay. http://fex.rus.uni-stuttgart.de/usecases/BIGMAIL.html Q: Can I use a download manager/accelerator? A: Generally, no, because they suck: they are not RFC compliant and produce a LOT of unnecessary server load. But there is one exception: axel [http://axel.alioth.debian.org/] Q: When I hit [ESC] in firefox the upload is canceled. Why? A: This is a built-in feature of firefox: ESC terminates the current operation. Simple solution: do not hit ESC in Firefox. Complex solution: ask the Firefox developers to add keyboard configuration. 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 an one-time upload key with "user config & operation control" See also http://fex.rus.uni-stuttgart.de/usecases/foreign.html 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 requests the file several times at once. Otherwise they would report an error to the user. Your fexmaster has set AUTODELETE=DELAY as default, which means that the autodelete cleanup process is called once a day. Power users (use the source, Luke!) can set a "do not delete after download" flag. Q: I have uploaded a file to a list of recipients. Will the file be deleted after the first recipient has dowloaded it? A: No. Every recipient gets his own copy of the file which is independant from the others. Q: The default keep time is too short for me, I need more. How can I set it? A: Use fexsend, ask your fexmaster or read the source code :-) Q: I have sent a second file with the same name, but the recpient has not received a second notification e-mail. 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 e-mail of the same file(name) is not suggestive. Q: How can I sent a more compact notification e-mail? A: Let your comment start with "!.!", then the notification e-mail will contain only download-URL, size and comment. Q: How can I suppress the automatic notification e-mail? A: Use "!#!" as comment, then no notification e-mail will be sent. Of course you then have to inform the recipient manually. Q: Can I get a notification e-mail on download? A: No. Such a feature is in conflict with German and European privacy laws and will not be implemented. With e-mail you also have no acknowledgement of receipt. Q: I cannot download files with Internet Explorer, it tells me "Cannot open Internet site". What shall I do? A: Use Firefox or any other Internet-compatible web browser, that Internet Explorer is not. This is one of the many bugs of Internet Explorer. See also http://support.microsoft.com/kb/323308 fex-20130805/htdocs/FAQ/jquery.js0000644000174700017470000026741411622435175014476 0ustar fexfex/*! * jQuery JavaScript Library v1.6.2 * http://jquery.com/ * * Copyright 2011, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * Date: Thu Jun 30 14:16:56 2011 -0400 */ (function(a,b){function cv(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cs(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"":"")+""),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
    a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
    ",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
    t
    ",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

    ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
    ";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/",""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div
    ","
    "]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
    ").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
    ";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); /*! * idTabs ~ Sean Catchpole - Version 2.2 - MIT/GPL * http://www.sunsean.com/idTabs/jquery.idTabs.min.js */ (function(){var dep={"jQuery":"http://code.jquery.com/jquery-latest.min.js"};var init=function(){(function($){$.fn.idTabs=function(){var s={};for(var i=0;i
    • <>
    • <<$y+1>>
    • <>

    <<`date +"%Y-%m-%d %H:%M:%S"`>>
    

    #if $y>2

    xxx

    #elseif 0

    000

    #elseif 4>3

    ###############

    #else

    zzz

    #endif


    $PATH=$PATH$
    URL parameter=$QUERY_STRING$
    


    <<`env`>>
    


    see >">sourcecode fex-20130805/htdocs/version0000644000174700017470000000001512177755050013603 0ustar fexfexfex-20130805 fex-20130805/htdocs/tools.html0000644000174700017470000000313112061470071014210 0ustar fexfex F*EX tools

    F*EX tools

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

    In opposite to most web browsers all these clients can handle files greater than 2 GB and resume interrupted up/downloads.

    Hint for UNIX users:

      wget -qO- http://$HTTP_HOST$/xx.tar | tar xvf -
    installs fexsend fexget and xx.
      wget -qO- http://$HTTP_HOST$/afs.tar | tar xvf -
    also installs the client programs for Stream EXchange and anonymous usage. fex-20130805/htdocs/small_logo.jpg0000644000174700017470000001176011361154160015023 0ustar fexfexJFIFMCreated with GIMP CREATOR: XV Version 3.10af Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222c" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( (9?xEHV?؏A\,-_x UКceamkɉcv3Qa*|U]NTZ6a"2(l@=d;ġu$o.7[&Ү;BS4`XH܇h'=8෾-[5MU`BG}c \C kk[:sQN.ŷzMVIk,2۬Ђ0c煗UXZc }~7ĪFL P?<.p޴ӥTDzes<^$vG3* 眞~57qa`׮GEb ʜgi͖:=>8S˶qA`l<9ީ%ĉsa_I_ҴX/#Uȩ>przcּF> k [;X[ 0>cst :[~1=:vbIHmfLoKpFь88Ae☾ iKnn?0POFIχ{@1 =vuӜJxxNsqUUk>oH2J{x٘$ɮǿd܋#>Xz^iqhtbZ|];c+!ۀ9_|p8Ǡ\8VUeW5Ƨ*Q[xXMׇ;5bl̋ "1+MsӃGx#5a%Yv>Tr.nwOAz%$ӠXdvKuU u‘eFnRrxATS,2W g9O֪SrVb% 6O.}ow$SA*|1FR qh>.SS. {d$ 89?5 Op.7_W]p#5$˴r}8_SPBQ7.8`e8Hu;_Xi#VVٞC6y8dߎ vK+{ؼM=Kqёb2@-G57r^9z8`@8 w$Sh pXs9<V\ltWIw뺰X OlЄAݸ>+"!Ohv8c7Wr\,ܪ7Gq:` frNzwQEnbG4Kki9hg(^1J)=R4x$9dGs4F9?Lžl傌9vp푚Ҷ,,fnB4[,ŁrT``!b = */.b}B1Z\4Hpzv◳c_m ^Q>n8Ay88|CF [lm@|R :+O>u1p38lHWA[F?+1n&[rX{|" F~i 1,Y7rDŃ9}ޛ8/`z]՛ݜ3|TɥEр-١BOlm<3#鹉 {tJ)O4Š($*ز$(MYp39: Bw^>u)wa7es]M=ݐ\ X3۔IRG˃ξl$#lc8!r˖X =/H$trғ):Uk-sF (I#hZ+ģi3ۅ2&f͑`̹ r1#I'$s![rvg~YT4oᘁw] ~9)%B7et\y'yNSX\:? ksd#tsT/GGS*IH`{@`;tn` 'Cz4-g$F?|>CFpx!l8utC3}2LmA $2rhF#o l%İH} \mPH3]Kqw1i*Aۜl.ZIm յr7Mm0<ōPF@jABqiy,,[/+I@`ep>L$ֽed1g~>prcH%柧Gkm C}'g$O$i77pӜ~5,fj\%76.X$! Քs{T+erlg( ŷ 9{f ]ZD7-S U9^Hy q3Dj8+rrkc)MGɄ[*ZHmdmvTwWi4'$:t $mO;n #'ɬtޭqsu,yrfq!ܥ _-@!X B,`In^U)rBVF"Ɗ uW)QEQESDK!U9%dEQ{MKQEi-H-7/G#o.?*_**>HG\TU:?$XĄ~EqFDQ)>^FٝqRTQB{#o.?*_*G\TUS.HGt,?*_*[F!b?ڕ(KPov!*$Lڠf͝ `) ((fex-20130805/etc/0000755000174700017470000000000012177755050011466 5ustar fexfexfex-20130805/etc/xinetd_fex0000644000174700017470000000044412177755047013556 0ustar fexfex# default: on # description: F*EX web server # service fex { socket_type = stream wait = no type = unlisted protocol = tcp bind = ADDRESS port = PORT cps = 10 2 user = fex groups = yes server = FEXHOME/bin/fexsrv nice = 0 disable = no } fex-20130805/etc/mime.types0000644000174700017470000000155512172324417013503 0ustar fexfexapplication/ogg ogg ogx application/pdf pdf application/postscript ps ai eps application/x-dvi dvi audio/basic au snd audio/mpeg mpga mpega mp2 mp3 m4a audio/ogg oga spx audio/x-ms-wma wma audio/x-wav wav image/gif gif image/jpeg jpeg jpg jpe image/pcx pcx image/png png image/svg+xml svg svgz image/tiff tiff tif image/x-ms-bmp bmp image/x-portable-anymap pnm image/x-portable-bitmap pbm image/x-portable-graymap pgm image/x-portable-pixmap ppm image/x-rgb rgb image/x-xbitmap xbm image/x-xpixmap xpm image/x-xwindowdump xwd text/plain asc txt text pot video/3gpp 3gp video/dl dl video/dv dif dv video/fli fli video/gl gl video/mpeg mpeg mpg mpe video/mp4 mp4 video/ogg ogv video/quicktime qt mov video/x-msvideo avi video/x-sgi-movie movie fex-20130805/locale/0000755000174700017470000000000012163007711012137 5ustar fexfexfex-20130805/locale/french/0000755000174700017470000000000012177755050013417 5ustar fexfexfex-20130805/locale/french/lib/0000755000174700017470000000000012177755050014165 5ustar fexfexfex-20130805/locale/french/lib/fup.pl0000644000174700017470000000245211777534141015320 0ustar fexfex# config for F*EX CGI fup $info_1 = $info_login = <

    F*EX (File EXchange) est un service pour envoyer des fichiers très volumineux (grand, énorme, géant, ...).

    L'expéditeur (vous) upload le fichier vers un serveur F*EX et le destinataire reçoit automatiquement un message de notification par mail avec l'URL de téléchargement.
    Après un téléchargement ou après $keep_default jours, le serveur efface le fichier. F*EX n'est pas un système d'archivage!

    Voir les questions & réponses.


    $ENV{SERVER_ADMIN}
    EOD $info_2 = <

    Après soumission de votre fichier pour l'upload, vous verrez une barre de progression (si vous avez javascript activé et que les popups sont autorisés)

    REMARQUE: La plupart des navigateurs ne peuvent pas uploader des fichiers > 2 GB!
    Si votre fichier est plus gros, vous devez utiliser un client F*EX spécial.
    Vous devez aussi en utiliser un pour la reprise d'upload interrompu. Votre navigateur ne peut pas le faire.

    Pour les utilisateurs de Firefox : ne pas appuyer sur [ESC] parce que cela stoppera l'upload !

    Voir aussi la FAQ. EOD fex-20130805/locale/french/lib/reactivation.txt0000644000174700017470000000006011713446544017412 0ustar fexfexVotre compte F*EX a été activé avec succès. fex-20130805/locale/french/htdocs/0000755000174700017470000000000012177755050014703 5ustar fexfexfex-20130805/locale/french/htdocs/index.html0000644000174700017470000001334512031360371016671 0ustar fexfex F*EX - File EXchange

    F*EX - Frams' Fast File EXchange

    F*EX (Frams' Fast File EXchange) est un service pour envoyer des fichiers volumineux d'un utilisateur A à un utilisateur B.

    L'expéditeur upload le fichier au server F*EX en utilisant un formulaire WWW et le destinataire reçoit automatiquement une notification.

    Vous vous dîtes:

    Pourquoi aurais -je besoin d'un autre service de transfert de fichier ?!
    J'ai déja l'e-mail, le ftp, ssh et même sendfile !

    Je réponds:

    Vous avez toujours besoin de F*EX :-)

    Par exemple, vous voulez envoyer à vos amis la dernière vidéo de vos vacances (1 GB). Vous avez les possibilités suivantes (et les problèmes):

    • envoyer un DVD par la voie postale

      Hors de question - nous vivons en <> après l'invention d'Internet. C'est pour les grand-pères.

    • utiliser l'e-mail

      La plupart des serveurs e-mail ont une limite de 10 MB par message et très souvent un quota d'utilisation de quelques centaines de méga-octets.

    • uucp

      Et pourquoi pas du marbre et un burin ?

    • ssh

      Vous avez le mot de passe de vos amis ou bien vous êtes prêts à leur donne le votre, juste pour un transfert de fichier ?

    • ftp

      • Quel serveur ?
      • Quel compte, quel mot de passe ?
      • Vous ne vous souciez pas d'envoyer des mots de passes non chiffrés et des fichiers sur un Internet non sécurisé ?
      • Est-ce que votre proxy support le ftp passif ?
      • Dans le cas d'un ftp anonyme :
        • Est-ce qu'il permet des uploads de 1GB ?
        • Est-ce qu'il permet de supprimer le fichier uploadé ?
        • Qui peut télécharger votre fichier ?
        • Qui peut supprimer votre fichier ?
        • Vous devez envoyer à votre ami l'URL de téléchargement, il doit vous informer que le download s'est bien passé et vous devez supprimer le fichier .
          C'est plutôt pénible.

    • http

      • Pas d'upload par défaut et de gestion des utilisateurs. Cela doit être programmé
      • Pas de notification automatique
      • Pas d'effacement automatique
      • Peu de serveur http peuvent gérer des fichiers de plus de 2GB

    • sendfile

      • Vous utilisez UNIX et sendfile est installé ?
      • Votre destinataire utilise UNIX et a sendfile d'installé ?
      • Ni vous ou votre destinataire n'a le port 487 bloqué par un firewall ?

    • Des services commerciaux comme DropLoad, ALLPeers, YouSendIt, etc

      • Quel limite ont-ils (le plupart: < 2 GB)?
      • Quid de la sécurité et de la confidentialité : est-ce vos fichiers seront entre de bonnes mains ?
      • Est-ce qu'ils sont opensource ou propriétaire ?
      • Est-ce qu'ils sont accessibles avec n'importe quel navigateur ou bien avez-vous besoin de java, active-X, flash ou d'autres plugins ésotériques ?
      • Est-ce qu'ils vont encore exister d'ici quelques mois?
        (DropLoad, ALLPeers et drop.io ont déja mis la clé sous la porte)

    Si vous avez répondu "non" à une seule de ces questions, alors vous avez besoin de F*EX

    Principales fonctionnalités de F*EX

    • transfert de fichier de taille virtuellement infini
    • le destinataire et l'expéditeur ont uniquement besoin d'un e-mail et d'un navigateur web, ils n'ont pas besoin d'installer de logiciels.
    • reprise d'upload et de téléchargement en cas de défaillance
    • notification automatique du destinataire
    • suppression automatique après un téléchargement
    • suppression automatique après un délai ajustable (par défaut: 5 jours)
    • les utilisateurs F*EX peuvent créer des URLs d'upload à usage unique pour des utilisateurs extérieurs
    • les utilisateurs F*EX peuvent créer des sous-utilisateurs qui ne pourront envoyer des fichiers uniquement à cet utilisateur
    • les utilisateurs F*EX peuvent créer des groups, similaire à des listes de diffusions, mais pour des fichiers
    • maintenance réduite au minimum : pas d'interventation de l'administrateur nécessaires mise à part la création des nouveaux utilisateurs
    • l'envoi à plusieurs destinataires ne nécessite pas le stockage d'autant de fichiers sur le serveur
    • F*EX est un service web HTTP qui ne néccessite pas de contourner les parre-feux.
    • support des flux
    • pour les vrais utilisateurs UNIX, il existe les programmes shell fexsend et fexget afin d'éviter l'utilisation ennuyeuse de l'interface web
    • protocol et code source librement disponible (Perl Artistic)

    Parlons de SEX

    F*EX a un ami : Stream EXchange (SEX).

    Vous pouvez imager SEX comme un tube UNIX réseau s'appuyant sur un relais. Cela peut s'avérer utile pour envoyer des données d'un utilisateur A à un utilisateur B lorsque A et B ne peuvent établir une connexion directe, mais que chacun peut accéder en HTTP au serveur SEX. Pour une intégration sans peine avec les outils UNIX, il y a les commandes shell sexsend et sexget.

    L'authentifaction est la même qu'avec F*EX

    Encore des questions?

    Voir la FAQ

    contact: fexmaster
    fex-20130805/locale/french/htdocs/FAQ/0000755000174700017470000000000012177755050015312 5ustar fexfexfex-20130805/locale/french/htdocs/FAQ/all.html0000644000174700017470000000200712163375610016742 0ustar fexfex F*EX FAQ << my ($n,$f); local $/ = "Q:"; local $_; print qq(

    F*EX FAQ All

    \n); foreach $faq (qw(meta user admin misc)) { $n = 0; open $faq,"$faq.faq" or return; $f = $faq; $f =~ s/(.)/uc $1/e; print "

    $f\n"; print "\n"; $_ = <$faq>; while (<$faq>) { chomp; while (/\$([\w_]+)\$/) { $var = $1; $env = $ENV{$var} || ''; s/\$$var\$/$env/g; }; ($Q,$A) = split /A:s*/; $A =~ s/([^>\n\\])\n/$1
    \n/g; $A =~ s/\\\n/\n/g; $A =~ s/<([^\s<>\@]+\@[\w.-]+)>/<$1><\/a>/g; $A =~ s: (/\w[\S]+/[\S]+): $1:g; $A =~ s/(https?:[^\s<>]+)/[$1]<\/a>/g; $n++; print "\n"; print "\n"; print "\n"; } print "
    Q$n:$Q
    A$n:$A
    \n"; close $faq; } >> fex-20130805/locale/french/htdocs/FAQ/FAQ.html0000644000174700017470000000331012177755047016612 0ustar fexfex F*EX FAQ

    F*EX FAQ

    #if not -s "local.faq" #endif <> #if -s "local.faq"
    <>
    #else
    <>
    <>
    <>
    <>
    <>
    #endif ## << faq($ENV{QUERY_STRING}) >> fex-20130805/locale/french/htdocs/FAQ/admin.faq0000644000174700017470000000516411777535152017105 0ustar fexfex
    
    Q: Je ne peux pas installer un serveur web comme fexsrv parce que je n'ai pas les permissions root. Est-ce qu'il existe une version pure CGI de F*EX qui puisse tourner avec un server Apache ?
    A: F*EX est fortement lié à fexsrv pour plusieurs raisons (performance, limite de la taille des fichiers, session, etc...) et ne peut pas tourner comme un CGI sous Apache. Mais vous pouvez jeter un oeil à 
    
    • http://gpl.univ-avignon.fr/filez/
    • http://freshmeat.net/projects/eventh/
    • http://www.schaarwaechter.de/sp/projekte/dateiaustausch.html (en Allemand)
    qui implementent le transfert de fichier avec des CGIs pures, mais avec une limite de 2GB. Q: F*EX ne fonctionne pas du tout ! Je ne peux pas m'y connecter avec mon navigateur web ! A: Vérifier votre routage, ipfilters et la configuration de votre pare-feux. Vérifier également si votre xinetd est linké à tcp-wrapper et configuré convenablement (hosts.allow). F*EX a besoin du port 80/tcp pour HTTP et optionnellement du port 443/tcp pour HTTPS. Q: F*EX est trop complexe ! J'ai besoin de quelque chose encore plus simple. A: Essayez http://www.home.unix-ag.org/simon/woof.html Q: Comment puis-je intégrer F*EX à un système d'annuaire ou de gestion d'identité ? A: F*EX a plusieurs modules d'authentification: local, RADIUS, LDAP, mailman et POP. Pour les quatre derniers, contacter framstag@rus.uni-stuttgart.de Q: Je veux que tous mes utilisateurs locaux puissent utiliser F*EX. Comment je fais ? A: Ils doivent s'enregistrer eux-mêmes avec http://$HTTP_HOST$/fur

    Il faut éditer lib/fex.ph et configurer (exemple):

     @local_hosts = qw(127.0.0.1 10.10.100.0-10.10.255.255);
     @local_domains = qw(flupp.org ulm.sub.net);
    
    (Bien entendu, vous devez utiliser les paramètres propres à votre réseau !) Q: J'ai besoin de plus de sécurité ! Comment activer HTTPS ? A: Lisez doc/SSL and jetez un oeil à "fop_auth" dans doc/concept Q: J'ai besoin d'un look adapté à mon image. Comment puis-je configurer F*EX en ce sens ? A: Voir la variable @H1_extra dans fex.ph et aussi l'ajout possible de code HTML à htdocs/header.html

    Voir htdocs/fup_template.html, le modifier selon vos besoins et l'utiliser comme page de démarrage. Q: F*EX est trop compliqué pour mes utilisateurs. J'ai besoin d'un formulaire d'upload simplifié. A: Voir htdocs/fup_template.html Q: Je veux que les mails Bcc destinés à F*EX (utilisateur admin) soient envoyés à une autre adresse. A: Positionnez la variable $bcc dans fex.ph Q: Puis-je avoir une version localisé dans ma langue ? A: Avec votre aide, oui. Merci de contacter framstag@rus.uni-stuttgart.de fex-20130805/locale/french/htdocs/FAQ/misc.faq0000644000174700017470000000065611713227453016741 0ustar fexfex

    
    Q: F*EX est un très bon logiciel ! Est-ce que je peux rejoindre l'équipe de développement ? Qu'est-ce qu'il y a à faire ?
    A: Contacter l'auteur

    Les fonctionnalités souhaitées sont :

    • des testeurs pour MacOS, AIX et les autres UNIX
    • un nouveau mainteneur pour le client Java F*EX
    • un plugin F*EX pour thunderbird ou outlook
    • plus de langages supportés (japonais, klingon ...)
    fex-20130805/locale/french/htdocs/FAQ/meta.faq0000644000174700017470000000376712031360521016726 0ustar fexfex
    
    Q: Pourquoi "F*EX" comme nom et pas simplement "FEX"
    A: À l'époque de l'annonce du logiciel, il existait déja un programme (plus ancien) nommé "FEX" sur 
       freshmeat.net.
    
    Q: Pourquoi ne pas utiliser un service commercial comme DropLoad, ALLPeers, YouSendIt, etc ?
    A: 
    • Ils ont une limite de 2GB ou moins.
    • Leur politique de sécurité et de confidentialité est inconnue.
    • Ils ne sont pas opensource.
    • Il n'y a pas d'interface en ligne de commande (CLI) UNIX.
    • Ils ont besoin de java, active-X, flash ou d'autres plugins esotériques.
    • On ne sait pas combien de temps ils vont exister - DropLoad and ALLPeers ont déja cessé leur activité.
    Q: Pourquoi un chameau comme logo ? A: Le logo est inspiré du chameau de Perl, mais il est basé sur un chameau "Steiff plush" qui courent avec nous lors de nos courses de tandem. Le logo a été dessiné par mon "chauffeur" Beate. http://fex.rus.uni-stuttgart.de/Vortrag/tosa.html Q: Où puis-je récupérer les sources de F*EX ? A: http://fex.rus.uni-stuttgart.de/fex.html 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 ? 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 ? 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 ? A: Perl Artistic free software Q: Est-ce qu'il y a une mailing list F*EX ? A: https://listserv.uni-stuttgart.de/mailman/listinfo/fex Q: Où puis-je avoir un support commercial pour F*EX ? A: Contacter fex@nepustil.net http://www.nepustil.net/ Q: J'ai encore des questions ! A: Demandez directement à l'auteur framstag@rus.uni-stuttgart.de fex-20130805/locale/french/htdocs/FAQ/user.faq0000644000174700017470000001176311777534634017001 0ustar fexfex
    
    Q: Qu'est-ce que l'auth-ID ?
    A: L'auth-ID est un moyen d'authentification interne qui permet d'authentifier l'utilisateur. Il sera d'abord généré par l'admin ou le processus d'enregistrement automatique et pourra être modifié plus tard par vous, l'utilisateur. Vous pouvez y penser comme à un mot de passe à faible sécurité.
    
    Q: Puis-je utiliser un proxy HTTP ?
    A: Oui, mais attention:
       Certain proxy http comme HTTP introduise un délai dans l'affichage de la barre de progression lors d'un upload !
       Vous pouvez essayer de désactiver le proxy pour $SERVER_NAME si vous rencontrez ce problème.
    
    Q: J'ai uploadé un fichier très volumineux mais j'ai fait une faute dans l'adresse du destinataire. J'ai reçu un message d'erreur par mail. Dois-je uploader à nouveau ce fichier ?
    A: Non, cela n'est pas nécessaire. Vous pouvez rediriger un fichier via le menu "Configuration utilisateur & Gestion"
    
    Q: Mon destinataire a perdu son e-mail de notification avec l'URL de téléchargement. Que puis-je faire ?
    A: Vous pouvez vous faire suivre une nouvelle copie du fichier via le menu "Configuration utilisateur & Gestion".
       Vous recevrez un nouveau message de notification que vous pourrez envoyer à votre destinataire par la poste ou un fax :-)
    
    Q: Je ne peux pas uploader de fichiers > 2 GB avec mon navigateur internet !?
    A: Tous les navigateurs web que je connais ont des bugs dans leur implémentation de HTML-FORM. La plupart du temps, la limite est de 2 GB, parfois 4 GB.
       Vous devez utiliser un client F*EX spécial pour uploader des fichiers > 2 GB, voir http://$HTTP_HOST$/tools.html
       Firefox 7 (et suivant) est une exception : F*EX contourne des failles dans l'implémentation de l'upload afin de pouvoir uploader des fichiers de n'importe quelle taille.
    
    Q: Mon téléchargement a été interrompu avant la fin. Puis-je reprendre le téléchargement là où il s'est arrêté ?
    A: F*EX support la reprise de téléchargement, mais votre client doit aussi le supporter.
       Firefox ne possède pas cette capacité HTTP, vous devez utiliser une autre client comme opera, wget ou fexget.
    
    Q: Mon upload a été interrompu avant la fin. Puis-je reprendre l'upload là où il s'est arrêté ?
    A: F*EX supporte la reprise d'upload, mais votre client doit aussi le supporter.
       Aucun navigateur web n'a cette capacité, vous devez utiliser un autre client comme fexsend, schwuppdiwupp ou F*IX,
       voir http://$HTTP_HOST$/tools.html
    
    Q: Mon nvaigateur web ne peut pas démarrer le client java F*IX, avec comme message d'erreur : "found no java runtime environment, cannot start F*IX upload applet"
    A: un plugin java pour votre navigateur est manquant. Sur Debian et Ubuntu, vous pouvez l'installer avec :
       sudo aptitude install sun-java6-plugin
    
    Q: Lorsque j'appuie sur [ESC] dans firefox, l'upload est annulé. Pourquoi ?
    A: C'est une fonctionnalité intégré à Firefox. ESC termine l'opération courante.
       Solution simple: ne pas appuyer sur ESC dans Firefox.
       Solution complexe: demander aux développeurs de Firefox d'ajouter la configuration du clavier.
    
    Q: Firefox 3 se bloque lors de l'upload d'un fichier et je ne vois pas la barre de progression ?
    A: C'est un bug connu dans Firefox 3.6.23. Solution: passer à Firefox 7.
    
    Q: Envoyer un fichier en tant qu'utilisateur F*EX est facile, mais comment recevoir des fichiers de personnes extérieures ?
    A: Vous pouvez les enregistrer comme sous-utilisateurs ou créer un group F*EX via le menu "Configuration utilisateur & Gestion"
    
    Q: Parfois je peux télécharger un fichier plus d'une fois, surtout lorsque je le fais rapidement. Est-ce que la fonction de suppression automatique est défectueuse ?
    A: Le serveur F*EX a un délai d'une minute après le premier téléchargement réussi pendant lequel le fichier reste disponible. Cela est nécessaire
    car certains "gestionnaires de téléchargements" lancent plusieurs téléchargements du même fichier à la fois. Sinon, ils afficheraient une erreur à l'utilisateur. Votre administrateur F*EX a laissé AUTODELETE=DELAY par défaut, ce qui signifie que le nettoyage automatique est appelé une fois par jour.

    Les utilisateurs avancés (use the source, Luke !) peuvent activer l'option "ne pas supprimer après téléchargement". Q: La rétentation par défaut est trop courte pour moi, j'ai besoin de plus. Comment puis-je l'augmenter ? A: Utilisez fexsend, demandez à votre fexmaster ou bien lisez le code source :-) Q: J'ai envoyé un second fichier avec le même nom, mais le destinataire n'a pas reçu deuxième message de confirmation. Pourquoi ? A: Un fichier avec le même nom et le même destinataire écrase le premier si il est toujours présent, un deuxième e-mail de notification pour un même fichier n'a pas tellement de sens. Q: Je ne peux pas télécharger des fichiers avec Internet Explorer, il me dit : "Cannot open Internet site". Que dois-je faire ? A: Utilisez Firefox ou tout autre navigateur compatible Internet, ce qui n'est pas le cas d'Internet Explorer. Cela fait parti des nombreux bugs d'Internet Explorer. fex-20130805/locale/french/lang.html0000644000174700017470000000002011713455631015213 0ustar fexfexfrançais fex-20130805/locale/translate0000755000174700017470000001001012157201542014053 0ustar fexfex#!/usr/bin/perl -w # translate english F*EX files into locale languange use File::Basename; use File::Copy; @trfiles = qw( lib/fex.pp cgi-bin/foc cgi-bin/fop cgi-bin/fuc cgi-bin/fup cgi-bin/fur cgi-bin/rup cgi-bin/pup htdocs/FAQ/FAQ.html ); # htdocs/FAQ/meta.faq # htdocs/FAQ/user.faq # htdocs/FAQ/admin.faq # htdocs/FAQ/misc.faq @cpfiles = qw( lang.html htdocs/index.html htdocs/FAQ htdocs/FAQ.html lib/fup.pl ); @FEX = getpwnam('fex') or die "$0: no user fex\n"; $> = $FEX[2]; $) = $FEX[3]; $FEXHOME = $ENV{FEXHOME} || $FEX[7]; # require "$FEXHOME/lib/fex.pp" # or die "$0: cannot load $FEXHOME/lib/fex.pp - $!\n"; $tr = "locale/translations"; $lang = shift or &usage; exit if $lang eq 'english'; open $tr,$tr or die "$0: cannot open $tr - $!\n"; while (<$tr>) { $n++; last if /^\s*$/; if (/^#\s*([\w-]+):/ and $lang eq $1) { $ll = $n; } } &usage unless $ll; while (<$tr>) { next if /^#/; next if /^\s*$/; chomp; unless (/[a-z]/i) { die "$0: syntax error in $tr line $. : no text\n"; } $e = $_; for my $l (2 .. $ll) { $_ = <$tr>||''; chomp; unless (/[a-z]/i) { die "$0: syntax error in $tr line $. : no text\n"; } } $T{$e} = $_; while (<$tr>) { last if /^\s*$/ } } close $tr; @E = sort {length $b <=> length $a} keys %T; mkdir "$FEXHOME/locale"; $_ = "$FEXHOME/locale/english"; symlink '..',$_ unless -e; foreach $file (@trfiles) { local $/; mkdirp("$FEXHOME/locale/$lang/".dirname($file)); $fe = "$FEXHOME/$file"; $ft = "$FEXHOME/locale/$lang/$file"; open $fe,"<$fe" or die "$0: cannot read $fe - $!\n"; unlink $ft; # beware symlink! open $ft,">$ft" or die "$0: cannot write $ft - $!\n"; $_ = <$fe>; close $fe; foreach $e (@E) { s/\Q$e/$T{$e}/g; } print {$ft} $_; close $ft; chmod((stat $fe)[2],$ft); print "$ft written\n"; } foreach $file (@cpfiles) { my $fs = "locale/$lang/$file"; if (-e $fs) { my $fd = "$FEXHOME/$fs"; mkdirp(dirname($fd)); if (-f $fs) { $fd .= '_new' if -e $fd; if (copy($fs,$fd)) { chmod((stat $fs)[2],$fd); print "$fd written\n"; } } else { if (-f $fd) { my $fds = $fd.'_save'; my $fdn = $fd.'_new'; system "rm -rf $fds $fdn"; rename $fd,$fds; system "tar cf - $fs | (cd $FEXHOME; tar xf -)"; rename $fd,$fdn; rename $fds,$fd; print "$fdn written\n"; } else { system "tar cf - $fs | (cd $FEXHOME; tar xf -)"; print "$fd written\n"; } } } } foreach $fs (qw(fex.ph dop)) { $fd = "$FEXHOME/locale/$lang/lib/$fs"; symlink "../../../lib/$fs",$fd and print "$fd linked\n"; } unless (-f "$FEXHOME/locale/$lang/htdocs/FAQ/meta.faq") { unlink "$FEXHOME/locale/$lang/htdocs/FAQ/FAQ.html"; rmdir "$FEXHOME/locale/$lang/htdocs/FAQ"; } make_lf($lang); make_lf('english'); # unless -f "$FEXHOME/lib/lf.pl"; exit; sub make_lf { my $lang = shift; my $fexpp = "$FEXHOME/locale/$lang/lib/fex.pp"; my $lf = "$FEXHOME/locale/$lang/lib/lf.pl"; open $fexpp,$fexpp or die "$0: no $fexpp - $!\n"; unlink $lf; open $lf,'>',$lf or die "$0: cannot write $lf - $!\n"; print {$lf} "### auto-generated by install/translate - DO NOT EDIT! ###\n\n"; local $/; $_ = <$fexpp>; s/.*\n(\#\#\# locale functions)/$1/s; s/\nsub (\w+)/\n\$$1\{$lang\} = sub/gs; s/\n\}\n/\n\};\n/gs; print {$lf} $_; close $lf; close $fexpp; } # emulate mkdir -p sub mkdirp { my $dir = shift; my $pdir; return if -d $dir; $dir =~ s:/+$::; die "$0: cannot mkdir /\n" unless $dir; $pdir = $dir; if ($pdir =~ s:/[^/]+$::) { mkdirp($pdir) unless -d $pdir; } unless (-d $dir) { mkdir $dir,0770 or die "$0: mkdir $dir - $!\n"; } } sub usage { my @langs; open $tr,$tr or die "$0: cannot open $tr - $!\n"; while (<$tr>) { last if /^\s*$/; push @langs,$1 if /^#\s*([\w-]+):/; } foreach my $lang (@langs) { if (not -l "locale/$lang" and -f "locale/$lang/lib/fup.pl") { print "usage: $0 $lang\n"; } } exit 1; } fex-20130805/locale/spanish/0000755000174700017470000000000012177755050013617 5ustar fexfexfex-20130805/locale/spanish/lib/0000755000174700017470000000000012177755050014365 5ustar fexfexfex-20130805/locale/spanish/lib/fup.pl0000644000174700017470000000270711615070623015512 0ustar fexfex# config for F*EX CGI fup $info_1 = $info_login = <


    F*EX (File EXchange) es un servicio para enviar ficheros (grandes, enormes, gigantes, ...).

    El remitente (usted) sube el fichero al servidor F*EX y el destinatario recibe automáticamente una notificación por correo electrónico con una URL de descarga.
    Tras la descarga o tras $keep_default días el servidor borra el fichero. ¡F*EX no es un archivador!

    Vea también preguntas y respuestas.


    $ENV{SERVER_ADMIN}
    EOD $info_2 = <

    Tras pulsar el botón de enviar verá una barra de progreso de la subida (si tiene javascript activado y permite las ventanas emergentes)

    NOTE: ¡La mayoría de los navegadores web no pueden subir ficheros > 2 GB!
    Si su fichero es más grande tiene que usar un cliente de F*EX especial.
    También necesita uno para poder continuar con una subida interrumpida. Su navegador no puede hacerlo.

    Aviso: ¡algunos proxys HTTP como privoy retrasan la barra de progreso de la subida!
    Quizá quiera desabilitar el proxy para $ENV{SERVER_NAME} si se encuentra con problemas.

    Usuarios de firefox: ¡no pulse [ESC] porque aborta la subida!

    Vea también la FAQ. EOD fex-20130805/locale/spanish/lib/reactivation.txt0000644000174700017470000000006011626277145017614 0ustar fexfexSu cuenta de F*EX ha sido reactivado con exito. fex-20130805/locale/spanish/htdocs/0000755000174700017470000000000012177755050015103 5ustar fexfexfex-20130805/locale/spanish/htdocs/index.html0000644000174700017470000001412712031360371017070 0ustar fexfex F*EX - File EXchange

    F*EX - Frams' Fast File EXchange

    F*EX (Frams' Fast File EXchange) es un servicio para enviar ficheros (grandes, enormes, gigantes, ...) de un usuario A a otro B.

    El remitente sube el fichero al servidor F*EX usando el formulario de subida WWW y el destinatario automáticamente recibe una notifiación por correo electrónico con la URL de desacarga.

    Usted dirá:

    ¡¿Por qué necesito de otro servicio de transferencia de ficheros?!
    ¡Tengo el correo electrónico, ftp, ssh e incluso sendfile!

    Yo le respondo:

    Aun así necesita F*EX :-)

    Por ejemplo, quiere enviar a un amigo su último video de las vacaciones (1 GB). Tiene las siguientes posibilidades (y problemas):

    • enviar un DVD por correo postal

      Sin comentarios - ¡vivimos en el año <> tras la invención de internet! Enviar DVDs/CDs es para los abuelos.

    • usando el correo electrónico

      La mayoría de los servidores de correo tienen una límite de 10 MB por mensaje de correo electrónico y una cuota de almacenamiento de uno 100 MB por usuario e incluso menos.

    • uucp

      ¿Por qué no escritura cuneiforme sobre planchas de piedra?

    • ssh

      ¿Tiene la contraseña de su amigo o está deseando darle la suya tan sólo para la transferencia de un fichero?

    • ftp

      • Usando ¿qué servidor FTP?
      • Usando ¿qué cuenta y con qué contraseña?
      • ¿No le importa enviar contraseñas sin cifrar y ficheros a través de internet que no es seguro?
      • ¿Su proxy soporta ftp pasivo?
      • En caso de usar ftp anónimo:
        • ¿Permite subi 1 GB?
        • ¿Permite borrar los ficheros subidos después?
        • ¿Quién más puede descargar su fichero?
        • ¿Quién más puede borrar su fichero?
        • Tiene que enviarle a su amigo la URL de descarga, él tiene que informarle de que la descarga ha finalizado sin problemas y tiene que borrar el fichero después.
          En resumen: un grano en el culo.

    • http

      • No hay una administración de ficheros subidos y usuarios - hay que programarla
      • No hay autonotificación
      • No hay autoborrado
      • Muy pocos servidores http pueden manejar ficheros de más de 2 GB

    • sendfile

      • ¿Tiene UNIX y tiene sendfile instalado?
      • ¿Su destinatario tiene UNIX y tiene sendfile instalado?
      • ¿Ni usted ni su destinatario tiene un cortafuegos que bloquee el puerto 487?

    • servicios comerciales como DropLoad, ALLPeers, YouSendIt, etc.

      • ¿Qué limite tienen (la mayoría: < 2 GB)?
      • ¿Qué pasa con la seguridad y la privacidad: estarán sus ficheros a salvo?
      • ¿Están basados en software abierto o propietario?
      • ¿Son accesible con cualquier navegador o necesita java, active-X, flash u otro plugins?
      • ¿Sobrevirá más de unos cuantos meses?
        (DropLoad y ALLPeers ya han finalizado su actividad)

    Si ha contestado sólo una vez "no" a las preguntas anteriores, entonces necesita F*EX.

    Principales características de F*EX

    • transferencia de ficheros de tamaño virtualmente ilimitado
    • el destinatario y el remitente solo necesitan un programa de correo electrónico y un navegador web - de cualquier tipo, no necesitan instalar ningún software
    • RESEND y REGET para continuar las descargas interrumpidas por fallos en el enlace
    • autonotificación al destinatario
    • autoborrado tras la descarga
    • autoborrado tras la fecha de expiración (por defecto: 5 días)
    • los usuarios normales pueden crear subusuarios, que pueden enviar solo al usuario normal que lo definió
    • los usuarios normales puede crear grupos, una anología de las listas de correo, pero para ficheros
    • sin mantenimiento: no es necesaria la intervención del administrador más allá de crear la cuentas en F*EX
    • para enviar a múltiples destinatarios solo es necesario subir el fichero una vez
    • F*EX es un servicio web HTTP y no necesita que se creen túneles en los cortafuegos
    • también soporta streams
    • los usuarios UNIX reales, puede usar los programas para el shell fexsend y fexget para evitar el uso del navegador web
    • el protocolo y código fuente están disponibles (Perl Artistic)

    Hablemos de SEX

    F*EX tiene un acompañante: Stream EXchange (SEX).

    Puede imaginar SEX como si fueran tubería de UNIX a través de la red con un relay en medio. Esto puede ser útil para entubar datos del usuario A a otro B, donde A y B no pueden establecer una conexión directa, per ambos puede conectar por HTTP a servidor SEX. Las herramientas del shell sexsend y sexget permiten integrarlo fácilmente entre el conjunto de herramientas de UNIX.

    La autenticación es igual que en F*EX.

    ¿Todavía tiene más preguntas?

    Vea la FAQ

    contacto: Administrador de F*EX
    fex-20130805/locale/spanish/htdocs/FAQ.html0000644000174700017470000002216412031353706016374 0ustar fexfex
    Meta preguntas:
    ===============
    
    P: ¿Por qué el nombre de F*EX y no uno más corto?
    
    R: En el momento de la publicación había ya un programa llamado "FEX" activo 
       (más viejo) freshmeat.net.
    
    
    P: ¿Por qué no emplear un servicio comercial
       DropLoad, ALLPeers, YouSendIt, etc?
       
    R: Tienen un límite de 2GB e incluso menos.
       Su estado de privacidad y seguridad es desconocido.
       No están basados en software abierto.
       No existe ningún cliente UNIX (CLI) para ellos.
       Necesita java, active-X, flash u otros plugins endemeniados.
       Se desconoce cuanto durarán - DropLoad y ALLPeers
       ha finalizado sus asuntos.
    
    
    P: ¿Por qu el camello como logo?
    
    R: El logo fue inspirado por el camello de Perl, pero est basado en un Steiff
       el camello de peluche, que correo con con nosotros on nuestro tamdem de 
       carrelas.  El logo fue dibujado por Beate.
    
    
    P: ¿Dónde puedo conseguir los fuentes de F*EX?
    
    R: http://fex.rus.uni-stuttgart.de/fex.html
    
    
    P: ¿Que hace falta para instalar F*EX?
    
    R: Un servidor UNIX con una entrega DNS y smtp para correo saliendo.
       Y hace falta estar root en este ordenador.
    
    
    P: ¿Que es DNS y smtp?
    
    R: Que no instale F*EX. Es allende de su horizonte.
    
    
    P: ¿Quién es el autor?
    
    A: Ulli Horlacher <framstag@rus.uni-stuttgart.de>
    
    
    P: ¿Qué licencia tiene F*EX?
    
    R: Software libre Perl Artistic, vea http://fex.rus.uni-stuttgart.de/doc/Licence
    
    
    P: ¿Hay una lista de correo de F*EX?
    
    A: https://listserv.uni-stuttgart.de/mailman/listinfo/fex
    
    
    P: ¿Dónde puede conseguir apoyo comercial para F*EX?
    
    R: Contacte con fex@nepustil.net http://www.nepustil.net/
    
    
    P: ¡Tengo más/otras preguntas de las que aparecen en este documento!
    
    R: Pregunte al autor <framstag@rus.uni-stuttgart.de>
    
    
    Preguntas de los usuarios:
    ==========================
    
    P: ¿Qué es el "auth-ID"?
    
    R: El auth-ID es una identificación interna que autentica al usuario.
       La primera vez es generado por el administrador o por el proceso de registro
       automático y pude modificarlo más tarde. Piense en él como
       una especie de clave poco segura.
    
    
    P: ¿Puedo usar un proxy HTTP?
    
    R: Sí
    
    
    P: He subido un fichero ENORME pero me he confundido al escribir la dirección 
       de correo electrónico del destinatario.
       Acabo de recibir un correo de error de rebote. 
       ¿Tengo que volver a subir el fichero ENORME?
    
    R: No, no es necesario. Puede redirigir el fichero con
       http://$HTTP_HOST$/rup
    
    
    P: He subido un fichero ENORME pero olvidé poner a un destinatario.
       ¿Tengo que volver a subir el fichero ENORME?
    
    R: No, no es necesario. Puede reenviar una copia del fichero con
       http://$HTTP_HOST$/foc
    
    
    P: ¿¡No puede subir ficheros > 2 GB con mi navegador web!?
    
    R: Todos los navegadores web que conozco tienen errores en su implementación
       de HTML-FORM. El límite en la mayoría es de 2 GB, algunas veces 4 GB.
       Tiene que usar un cliente especial de F*EX para subir ficheros > 2 GB, vea
       http://$HTTP_HOST$/tools.html
    
    
    P: Mi descarga abortó antes de que acabara. ¿Puedo continuar la descarga?
    
    R: F*EX soporta la continuación de la descarga, pero su cliente debe soportar
       también esta característica. Firefox, por ejemplo, no tiene esta 
       característica HTTP, necesita otro cliente como opera, wget o fexget
    
    
    P: Mi subida abortó antes de que finalizara. ¿Puedo continuar la subida?
    
    R: F*EX soporta la continuación de la subida, pero su cliente también debe 
       soportarla. Ningún navegador web tiene esta característica, necesita un 
       cliente de F*EX especial como fexsend, schwuppdiwupp o F*IX
       Vea http://$HTTP_HOST$/tools.html
    
    
    P: Cuando pulso [ESC] en firefox la subida se cancela. ¿Por qué?
    
    R: Esta es una característica de firefox: ESC finaliza la operación en curso.
       Solución sencilla: no pulse ESC en Firefox
       Solución compleja: pida a los desarrolladores de Firefox que añadan una 
                          configuración del teclado
    
    
    P: Enviar como usario F*EX es fácil, pero ¿como pueden recibirse fichero de 
       otros desde fuera?
    
    R: Registrelos como su subusuarios o cre un grupo F*EX
    
    
    P: A veces puedo descargar un fichero más de una vez, especialmente cuando
       lo repito rápidamente. ¿Tiene errores la caracter de autoborrado?
    
    R: El servidor F*EX tiene un tiempo de gracia de 1 minuto tras la primera
       descarga con exito durante el cual el fichero está disponible todavía.  
       Este es necesario porque algunos "administradores de descargas" estúpidos 
       solicitan el fichero varias al mismo tiempo.  De otra manera, informan al 
       usuario de un error.
    
    R: Su fexmaster ha establecido AUTODELETE=DELAY por defecto, lo que significa 
       que el proceso de limpieza del autoborrado se ejecuta una vez al día
    
    R: Los usuario normales (use los fuentes, Luke!) pueden establecer una bandera
       de "no borrar tras la descarga"
    
    
    P: El tiempo por defecto para mantener el fichero en el sistema es desmasiado 
       corto para mí, necesito más. ¿Cómo puedo cambiarlo?
    
    R: Use fexsend, pregunte a su fexmaster o lea el código fuente
    
    
    P: No puede descargar ficheros con Internet Explorer, me dice "No puedo
       abrir el sistio de Internet". ¿Qué debería hacer?
    
    R: Use Firefox o cualquier otro navegador web compatible con Internet, puesto 
       que Internet Explorer no lo es. Este es uno de los muchos errores de 
       Internet Explorer.
    
    
    Preguntas del administrador:
    ============================
    
    P: No puedo instalar un servidor web como fexsrv, porque no tengo permisos
       de root. ¿Existe una versión CGI pura de F*EX que funcione con un
       servidor web apache?
    
    R: F*EX está íntimamente unido a fexsrv por varias razones (prestaciones,
       limitación en el tamaño del fichero, el concepto de sesión, etc.) y no 
       puede ejecutarse como CGI desde apache.
       Pero puede echar un vistazo a
       
       http://gpl.univ-avignon.fr/filez/
       http://freshmeat.net/projects/eventh/
    
       que implementa un intercambio de ficheros con CGIs puros, pero ambos están 
       limitados a 2 GB.
       
    
    P: ¡F*EX no funciona en absoluto! 
       ¡No puedo conectarme a él con mi navegador web!
    
    R: Compruebe el encaminamiento, los filtros IP y la configuración del 
       cortafuegos. Compruebe también si su xinetd está enlazado con tcp-wrapper 
       y configúrelo correctamente (hosts.allow).
    
       F*EX necesita el puerto 80/tcp (HTTP) y opcionalmente el puerto 443/tcp
       (HTTPS).
    
    
    P: ¡F*EX es muy complicado! Necesito algo más sencillo.
    
    R: Pruebe http://www.home.unix-ag.org/simon/woof.html
    
    
    P: ¿Como puedo integrar F*EX la administración de usuario existente de mi 
       sitio?
    
    R: F*EX tiene varios módulos de autenticación:
       local, RADIUS, LDAP, mailman y POP
       Para los últimos 4 póngase en contacto con el autor por favor.
       
    
    P: Quiero que todos mis usuarios locales use F*EX automáticamente. 
       ¿Cómo puedo hacerlo?
    
    R: Déjelos autoregistrarse.
       Tiene que editar el fichero lib/fex.ph y establecer (ejemplo):
    
       @local_hosts = qw(127.0.0.1 10.10.100.0-10.10.255.255);
       @local_domains = qw(flupp.org ulm.sub.net);
    
       ¡Desde luego tiene que añadir su hosts/redes locales reales!
    
    
    P: ¡Necesito más seguridad! ¿Cómo activo HTTPS?
    
    R: Lea doc/SSL y mire busque también "fop_auth" e doc/concept
    
    
    P: ¡Necesito que tenga una imagen corporativa. ¿Como configuro F*EX para que 
       la tenga?
    
    R: Vea la variable @H1_extra en fex.ph y puede añadir htdocs/header.html
    
    R: Vea fup_template.html, modifíquela según sus necesidades y usela como 
       página de inicio
    
    
    Otras preguntas:
    ================
    
    P: ¡F*EX es estupendo! ¿Puedo unirme al equipo de desarrollo? 
       ¿Qué hay que hacer?
    
    R: Contacte con el autor
    
       Características no presente:
    
       - otro cliente de subida que se integre mejor en Windows
         arrastrar y soltar, libro de direcciones de Outlook, etc.
    
    fex-20130805/locale/spanish/lang.html0000644000174700017470000000001711725126335015420 0ustar fexfexespañol fex-20130805/locale/debian_translate0000755000174700017470000000503712062743423015376 0ustar fexfex#!/usr/bin/perl -w # translate english F*EX files into locale languange, debian special use File::Basename; use File::Copy; @trfiles = qw( lib/fex.pp cgi-bin/foc cgi-bin/fop cgi-bin/fuc cgi-bin/fup cgi-bin/fur cgi-bin/rup cgi-bin/pup ); @cpfiles = qw( htdocs/index.html htdocs/FAQ.html lib/fup.pl lang.html ); $source = shift; $FEXHOME = shift; $dest = shift; $tr = "$source/locale/translations"; mkdirp($dest); unless (-l "$dest/english") { symlink '..',"$dest/english" or die "$0: cannot symlink $dest/english - $!\n"; } foreach $lang (glob "$source/locale/*/lib/fup.pl") { $lang =~ s:.*/locale/::; $lang =~ s:/.*::; next if $lang eq 'english'; next if $lang =~ /_$/; print "\n$lang:\n"; open $tr,$tr or die "$0: cannot open $tr - $!\n"; %T = (); $n = $ll = 0; while (<$tr>) { $n++; last if /^\s*$/; if (/^#\s*([\w-]+):/ and $lang eq $1) { $ll = $n; } } next unless $ll; while (<$tr>) { next if /^#/; next if /^\s*$/; chomp; unless (/[a-z]/i) { die "$0: syntax error in $tr line $. : no text\n"; } $e = $_; for my $l (2 .. $ll) { $_ = <$tr>||''; chomp; unless (/[a-z]/i) { die "$0: syntax error in $tr line $. : no text\n"; } } $T{$e} = $_; while (<$tr>) { last if /^\s*$/ } } close $tr; @E = sort {length $b <=> length $a} keys %T; foreach $file (@trfiles) { local $/; mkdirp("$dest/$lang/".dirname($file)); $fe = "$source/$file"; $ft = "$dest/$lang/$file"; open $fe,"<$fe" or die "$0: cannot read $fe - $!\n"; open $ft,">$ft" or die "$0: cannot write $ft - $!\n"; $_ = <$fe>; close $fe; foreach $e (@E) { s/\Q$e/$T{$e}/g; } print {$ft} $_; close $ft; chmod((stat $fe)[2],$ft); print "$ft written\n"; } foreach $file (@cpfiles) { $fs = "$source/locale/$lang/$file"; $fd = "$dest/$lang/$file"; mkdirp(dirname($fd)); $fd .= '_new' if -f $fd; if (copy($fs,$fd)) { chmod((stat $fs)[2],$fd); print "$fd written\n"; } } foreach $fs (qw(dop fex.ph)) { $fd = "$dest/$lang/lib/$fs"; symlink "$FEXHOME/lib/$fs",$fd or die "$0: cannot symlink $fd - $!\n"; print "$fd linked\n"; } } # emulate mkdir -p sub mkdirp { my $dir = shift; my $pdir; return if -d $dir; $dir =~ s:/+$::; die "$0: cannot mkdir /\n" unless $dir; $pdir = $dir; if ($pdir =~ s:/[^/]+$::) { mkdirp($pdir) unless -d $pdir; } unless (-d $dir) { mkdir $dir,0755 or die "$0: mkdir $dir - $!\n"; } } fex-20130805/locale/galician/0000775000174700017470000000000012177755050013723 5ustar fexfexfex-20130805/locale/galician/lib/0000775000174700017470000000000012177755050014471 5ustar fexfexfex-20130805/locale/galician/lib/fup.pl0000644000174700017470000000255211615070650015612 0ustar fexfex# config for F*EX CGI fup $info_1 = $info_login = <

    F*EX (File EXchange) é un servizo para enviar (grandes, enormes, xigantes, ...) ficheiros.

    O remitente (vostede) carga o ficheiro no servidor F*EX e o receptor obtén automaticamente unha notificación vía correo cun enderezo URL para descargalo.
    Despois de descargalo ou tras $keep_default días o servidor elimina o ficheiro. F*EX non é un arquivo!

    Vexa máis información en preguntas e respostas.


    $ENV{SERVER_ADMIN}
    EOD $info_2 = <

    Despois de remitilo verá unha barra de progreso de carga (se ten o javascript activado e permite as xanelas emerxentes).

    NOTA: A maior parte dos navegadores non poden cargar ficheiros > 2 GB!
    Se o seu ficheiro é maior, ten que usar un cliente F*EX especial.
    Tamén pode necesitalo para retomar cargas interrompidas. O seu navegador non pode facelo.

    Aviso: algúns proxies HTTP como privoxy retardan a barra de progreso de carga!
    Pode querer desactivar a intermediación do proxy $ENV{SERVER_NAME} se se encontra con este problema.

    Usuarios do Firefox: non prema en [ESC] porque isto abortará a carga!

    Vexa máis información na FAQ. EOD fex-20130805/locale/galician/lib/reactivation.txt0000644000174700017470000000005311632223410017677 0ustar fexfexA sa conta F*EX reactivouse correctamente fex-20130805/locale/galician/htdocs/0000775000174700017470000000000012177755050015207 5ustar fexfexfex-20130805/locale/galician/htdocs/index.html0000644000174700017470000001355012031360371017171 0ustar fexfex F*EX - File EXchange

    F*EX - Frams' Fast File EXchange

    F*EX (Frams' Fast File EXchange) un servizo para enviar voluminosos (grandes, enormes, xigantes, ...) ficheiros dun usuario A a un usuario B.

    O remisor carga o ficheiro no servidor F*EX usando un formulario WWW e o receptor automaticamente obtn unha notificacin va correo cun enderezo URL para descargar.

    Vostede dir:

    Por que necesito outro servizo para transferencia de ficheiros?!
    Teo correo, ftp, ssh e mesmo sendfile!

    Ao que respondo:

    Anda as necesita F*EX :-)

    Por exemplo, quere enviar ao seu amigo o video das ltimas vacacins (1 GB).  Ten as seguintes posibilidades (e problemas):

    • o envo dun DVD va correo postal

      Nin o vou considerar - vivimos na poca actual <> despois da invencin da Internet! O envo de soportes multimedia (fsicos) para avoas.

    • o uso do correo

      A maior parte dos servidores de correo teen un lmite de 10 MB por mensaxe e unha cota de uso de disco duns poucos 100 MB por usuario ou mesmo menor.

    • uucp

      E por que non escritura cuneiforme en laxes de pedra?

    • ssh

      Ou ben tes os contrasinais dos teus amigos ou ben ters que darlles a ta - fai falta iso s para transferir un ficheiro?

    • ftp

      • Usando que servidor ftp?
      • Usando que conta, que contrasinal?
      • Non se lle pasar pola cabeza enviar contrasinais sen cifrar e ficheiros na incerta Internet?
      • O seu proxy permite o ftp pasivo?
      • No caso de ftp annimo:
        • Permite cargas de 1 GB?
        • Permite eliminar a carga despois?
        • Quen pode descargar ademais o seu ficheiro?
        • Quen pode eliminar o seu ficheiro?
        • Ten que enviarlle ao seu amigo/a o URL de descarga, el ten que informarte de que o descargou correctamente, despois ten vostede que eliminalo.
          Definitivamente: unha merda pinchada nun pao.

    • http

      • Nin carga predeterminada nin xestin de usuario - debe ser programada
      • Sen autonotificacin
      • Sen autoeliminado
      • Moi poucos servidores http poden xestionar ficheiros superiores a 2 GB

    • sendfile

      • Executas un UNIX e tes o sendfile instalado?
      • O teu receptor executa UNIX e ten o sendfile instalado?
      • Nin ti nin o teu receptor ten unha devasa que bloquee o porto 487?

    • servizos comerciais como DropLoad, ALLPeers, YouSendIt, etc

      • Que lmite teen (maiormente: < 2 GB)?
      • Como andan de seguranza e privacidade: estarn os seus ficheiros gardados e seguros?
      • Estn baseados en software aberto ou en privativo?
      • Estn accesbeis con calquera outro navegador ou cmpre usar java, active-X, flash ou outros complementos endemoados?
      • Funcionarn aln duns poucos meses?
        (DropLoad, ALLPeers e drop.io xa pecharon as sas portas)

    Se respondeu s unha vez "non" s cuestins anteriores, entn necesita F*EX.

    Principais funcionalidades de F*EX

    • transferencia de ficheiro ou  tamao virtualmente ilimitada
    • receptor e remitente s necesitan un programa de correo e un navegador web - de calquer clase, non teen que instalar ningn software
    • REENVIAR and REOBTER para retomar despois de fallos de ligazn ata que se enve o ltimo byte
    • autonotificacin de receptor
    • autoeliminacin despois da descarga
    • autoeliminacin despois dunha data de expiracin (predeterminada: 5 das)
    • os usuarios con plenos dereitos poden crear subusuarios, que poden envar soamente a este usuario pleno
    • os usuarios con plenos dereitos poden crear grupos, en analoxa coas listas de correo, pero para ficheiros
    • sen mantemetno: non se necesita interaccin acompaando a creacin de novas contas con F*EX
    • o envo a mltiples receptores necesita capacidade de almacenamento no servidor s unha vez
    • F*EX un servizo web por HTTP e non necesita tneles nin devasas
    • permite a distribucin de fluxos, tamn
    • para usuarios reais de UNIX, hai aplicativos da shell como fexsend e fexget que evitan o uso impertinente de navegador
    • o protocolo e o cdigo fonte estn dispobeis libremente (Perl Artistic)

    Falemos de SEX

    F*EX ten un compaeiro: Stream EXchange (SEX).

    Pode imaxinar SEX como unha rede de tubaras UNIX cun reenviador (relay) entre elas. Isto pode ser moi prctico para intercambiar datos entre o usuario A e o usuario B al onde A e B non poden establecer unha conexin directa, pero ambos poden conectar va HTTP ao servidor SEX. Para unha integracin perfecta na cadea de ferramentas UNIX, hai ferramentas de shell como sexsend e sexget.

    A autenticacin a mesma que con F*EX.

    Quedanlle preguntas?

    Vexa a FAQ

    contacto: fexmaster
    fex-20130805/locale/galician/htdocs/FAQ.html0000644000174700017470000002610712031354051016471 0ustar fexfex
    Cuestións meta:
    ===============
    
    Q: Por que o nome "F*EX" e non directamente "FEX"?
    
    A: No momento de facerse público xa había unha (antigo) aplicativo chamado "FEX" en
       freshmeat.net.
    
    
    Q: Por que non usar un servizo comercial como
       DropLoad, ALLPeers, YouSendIt, etc?
    
    A: Teñen un límite de 2 GB ou menor.
       A súa seguranza e privacidade son descoñecidas.
       Non se basean en código fonte aberto.
       Non hai clientes de UNIX (CLI) para eles.
       Necesitan java, active-X, flash ou outros endemoñados complementos.
       Descoñécese canto tempo van funcionar - DropLoad e ALLPeers xa pecharon
       as súas portas.
    
    
    Q: Por que un camelo no logo?
    
    A: O logo inspirouse no camelo de Perl, pero baseáse en Steiff, un camelo de peluxe,
       co cal constituímos o noso tándem. O logo foi debuxado
       por Beate
       http://fex.rus.uni-stuttgart.de/Vortrag/tosa.html
    
    
    Q: Onde podo eu obter as fontes de F*EX?
    
    A: http://fex.rus.uni-stuttgart.de/fex.html
    
    
    Q: Que necesito para instalar F*EX?
    
    A: Un servidor UNIX con entrada no DNS e smtp para o correo de saída.
       E debe ser root nese servidor.
    
    
    Q: Que é o DNS e smtp?
    
    A: Non instale F*EX. Está alén das súas posibilidade.
    
    
    Q: Quen e o autor?
    
    A: Ulli Horlacher <framstag@rus.uni-stuttgart.de>
    
    
    Q: Que licenza ten F*EX?
    
    A: De software libre, Perl Artistic, vexa http://fex.rus.uni-stuttgart.de/doc/Licence
    
    
    Q: Hai unha lista de correo de F*EX?
    
    A: https://listserv.uni-stuttgart.de/mailman/listinfo/fex
    
    
    Q: Onde podo obter asistencia comercial para F*EX?
    
    A: Contacto fex@nepustil.net http://www.nepustil.net/
    
    
    Q: Teñeo máis/outras preguntas diferentes!
    
    A: Preguntarlle ao autor <framstag@rus.uni-stuttgart.de>
    
    
    
    Preguntas de usuario:
    =====================
    
    Q: Que é o "auth-ID"?
    
    A: O auth-ID é unha identificación interna que autentica o usuario.
       Será a primeira xerada polo admin ou o proceso de rexistro automático
       e pode despois modificalo vostede, o usuario. Trátase dun contrasinal
       de baixa seguranza.
    
    
    Q: Podo usar un proxy HTTP?
    
    A: Si.
    
    
    Q: Carguei un ficheiro ENORME pero equivoqueime ao escribir o enderezo do destinatario. Agora teño
       un erro de entrega de correo. Debo volver cargar ese ENORME ficheiro?
    
    A: Non, non fai falta. Pode redirixir o ficheiro con
       http://$HTTP_HOST$/rup
    
    
    Q: Cargue un ficheiro ENORME pero esquecín outro destinatario.
       Debo volver cargar ese ENORME ficheiro?
    
    A: Non, non é necesario. Pode reenviar copia do ficheiro con
       http://$HTTP_HOST$/foc
    
    
    Q: Non podo cargar ficheiros > 2 GB co meu navegador web!?
    
    A: Todos os navegadores teñen defectos na implementación dos
       seus formularios HTML. O límite máis frecuente é de 2 GB, ás veces 4 GB.
    
       Debe usar un cliente especial de F*EX para cargar ficheiros > 2 GB, vexa
       http://$HTTP_HOST$/tools.html
    
    
    Q: A miña descarga abortouse antes de rematar. Podo retomar esa descarga?
    
    A: F*EX permite retomar e descargar, pero o seu cliente tamén debe permitir
       esta funcionalidade. Firefox por exemplo carece desta funcionalidade HTTP, necesitará
       outro cliente como Opera, wget ou fexget.
    
    
    Q: A miña carga foi abortada antes de rematar. Podo retomar esa carga?
    
    A: F*EX permite retomar a carga, pero o seu cliente debe permitir vbnm, 1tupports resuming at upload, but your client also has to support it.
       No web browser has this feature, you need a special F*EX client like
       fexsend, schwuppdiwupp or F*IX.
       See http://$HTTP_HOST$/tools.html
    
    
    Q: O meu navegador non pode iniciar o cliente java F*IX, que indica:
       "non se atopou un entorno de execución java, non se pode iniciar F*IX o miniaplicativo de carga"
    
    A: Non se localiza un complemento java do navegador. En Debian e Ubuntu pode
       instalalo con: "sudo aptitude install sun-java6-plugin"
    
    
    Q: Cando premo[ESC] no Firefox a carga cancélase. Por que?
    
    A: Esta é unha funcionalidade interna do Firefox: ESC termina a operación actual.
       Solución simple: non prema ESC no Firefox.
       Solución complexa: pídalles aos desenvolvedores do Firefox que engadan un atallo de teclado.
    
    
    Q: O envío como un usuario F*EX é doado, pero como recibir ficheiros doutros,
       de fóra?
    
    A: Rexístreos como subusuarios ou cree un grupo F*EX
       con http://$HTTP_HOST$/fuc
    
    
    Q: Ás veces podo descargar un ficheiro máis dunha vez, especialamente cando
       o repito rapidamente. Está a funcionalidade de auteliminación defectuosa?
    
    A: O servidor F*EX ten un períod de gracia de 1 minuto despois da primeira
       descarga correcta no cal o ficheiro aínda está dispoñíbel. Isto é necesario
       porque algúns "xestores de descargas" estúpidos solicitan o ficheiro
       varias veces á vez. Caso contrario poderían indicar un erro ao usuario.
    
    A: O seu fexmaster ten un conxunto AUTODELETE=DELAY como predeterminado, o que significa que
       o proceso de autolimpeza realízase unha vez ao día.
    
    A: Os "Power users" ou usuarios con permisos (usa a forza, Luke!) poden establecer unha marca "non eliminar ata
       despois da descarga".
    
    
    Q: O período de reserva predeterminado é demasiado curto para min, cómpreme máis. Como podo estabelecelo?
    
    A: Use fexsend, pídallo ao seu fexmaster ou lea o código fonte :-)
    
    
    Q: Non podo descargar ficheiros con Internet Explorer, dime "Non se pode
       abrir o sitio da Internet". Que debería facer?
    
    A: Use Firefox ou calquera outro navegador compatíbel con Internet, xa que Internet
       Explorer non o é. Este é un de tanto defectos do Internet Explorer.
    
    
    
    
    Preguntas de administrador:
    ===========================
    
    Q: Non podo instalar un servidor web como fexsrv, porque non teño permisos de root
       Hai algunha versión en puro CGI de F*EX que funcione cun servidor web Apache?
    
    A: F*EX está intimamente unido a fexsrv por varias razóns (rendemento, límite de
       tamaño de ficheiro, concepto de sesiónt, etc.) e non se pode executar como CGI
       con Apache.
       Pero pódelle botar un ollo a
       http://gpl.univ-avignon.fr/filez/
       http://freshmeat.net/projects/eventh/
       http://www.schaarwaechter.de/sp/projekte/dateiaustausch.html (só en alemán!)
       que implementa un intercambio de ficheiros como puros CGI, pero cun tamaño límite de 2 GB por ficheiro.
    
    
    Q: F*EX non funciona! Non podo conectarme co meu navegador web!
    
    A: Comprobe o seu enrutamento, filtros ip e configuración de devasa.
       Tamén comprobe se o seu xinetd está ligado cun tcp-wrapper e configúreo
       correctamente (hosts.allow).
       F*EX necesita o porto 80/tcp (HTTP) e o porto opcional 443/tcp (HTTPS).
    
    
    Q: F*EX é complicado de máis! Necesito algo máis simplificado.
    
    A: Probe http://www.home.unix-ag.org/simon/woof.html
    
    
    Q: Como podo integrar F*EX no xestor de usuarios do meu sitio?
    
    A: F*EX ten varios módulos de autenticación:
       local, RADIUS, LDAP, mailman e POP
       Para os 4 últimos, contacte por favor co autor framstag@rus.uni-stuttgart.de
    
    
    Q: Que que todos os meus usuarios locais poidan usar F*EX automatimente. Como?
    
    A: Permítaos rexistrarse a si mesmos con http://yourfexserver/fur
       Ten que editar lib/fex.ph e establecer (exemplo):
       @local_hosts = qw(127.0.0.1 10.10.100.0-10.10.255.255);
       @local_domains = qw(flupp.org ulm.sub.net);
       (Por suposto, ten que engadir os seus servidores/redes locais reais!)
    
    
    Q: Necesito máis seguranza! Como podo activar HTTPS?
    
    A: Lea doc/SSL e busque "fop_auth" en doc/concept
    
    
    Q: Necesito un aspecto corporativo. Como podo configurar F*EX neste sentido?
    
    A: Vexa a variábel @H1_extra en fex.ph e pode engadir o código HTML a
       htdocs/header.html
    
    A: Vexa htdocs/fup_template.html, modifíqueo ás súas necesidades e úseo como a súa
       páxina de inicio.
    
    
    Q: F*EX é demasiado complicado para os meus pobres usuarios. Necesito un formulario de
       carga simmplificado.
    
    A: Vexa htdocs/fup_template.html
    
    
    Q: Quero que os correos Ccc a (ao usuario admin) se envíen a outro enderezo.
    
    A: Use procmail ou escriba OTHERADDRESS en /home/fex/.forward
    
    
    Q: Podo obter unha versión localizada no meu idioma?
    
    A: Sempre coa súa axuda, si. Contacte co autor framstag@rus.uni-stuttgart.de
    
    
    Preguntas en miscelánea:
    ========================
    
    Q: F*EX é fantástico! Podo unirme ao equipo de desenvolvemento? Que hai que facer?
    
    A: Contacte co autor framstag@rus.uni-stuttgart.de
       As funcionalidades buscadas son:
    
         - un complemento F*EX para o Thunderbird ou o Outlook
         - máis (outras) idiomas dispoñíbeis
    
    
    fex-20130805/locale/galician/lang.html0000644000174700017470000000000711605620540015513 0ustar fexfexgalego fex-20130805/locale/italian/0000755000174700017470000000000012177755050013573 5ustar fexfexfex-20130805/locale/italian/lib/0000755000174700017470000000000012177755050014341 5ustar fexfexfex-20130805/locale/italian/lib/fup.pl0000644000174700017470000000261111615070636015464 0ustar fexfex# configurazione per F*EX CGI fup $info_1 = $info_login = <

    F*EX (File EXchange) e' un servizio per spedire grossi (grandi, enormi, giganti, ...) file.

    Il mittente (tu) carica il file nel server F*EX ed automaticamente il destinatario si vede recapitare una e-mail di notifica con il link per effettuare il download.
    Dopo il download o dopo $keep_default giorni, il server cancella il file. F*EX non e' un sistema di archiviazione!

    Guardate anche domande e risposte (Q&A).


    $ENV{SERVER_ADMIN}
    EOD $info_2 = <

    Dopo il caricamento del file vedrete una barra di avanzamento (bisogna avere javascript abilitato ed i popup abilitati).

    NOTA: Parte dei browser-WEB non possono caricare file > 2 GB!
    Se il tuo file e' piu' grande devi usare un client F*EX particolare.
    Hai bisogno anche di un tool per recuperare i download interrotti. Il tuo browser-WEB non puo' farlo.

    Attenzione: alcuni proxy HTTP come privoxy ritardano lo stattttto della barra di avanzamento!
    Potresti voler disabilitare il proxying $ENV{SERVER_NAME} se ti capita di incorrere in questo problema.

    Utenti Firefox: non digitare [ESC] perche' questo interrompera' il caricamento!

    Vedere anche FAQ. EOD fex-20130805/locale/italian/lib/reactivation.txt0000644000174700017470000000006511627130362017563 0ustar fexfexIl tuo account F*EX stato riattivato con successo. fex-20130805/locale/italian/htdocs/0000755000174700017470000000000012177755050015057 5ustar fexfexfex-20130805/locale/italian/htdocs/index.html0000644000174700017470000001342012031360371017037 0ustar fexfex F*EX - File EXchange

    F*EX - Frams' Fast File EXchange

    F*EX (Frams' Fast File EXchange) e' un servizio per spedire grossi (grandi, enormi, giganti, ...) file da un utente A ad un utente B.

    Il mittente carica il file nel server F*EX usando una form WWW di carico mentre al destinatario viene recapitata una e-mail di notifica con un link per effettuare il download.

    Direte:

    Per quale motivo ho bisogno di un altro servizio per effettuare il trasferimento dei files?!
    Per questo ho gia' la posta elettronica(e-mail), l'ftp, l'ssh ed anche il comando sendfile!

    Io dico:

    Nonostante tutto hai bisogno di F*EX :-)

    Supponiamo, per esempio, che tu voglia spedire ai tuoi amici il video delle tue ultime vacanze (1 GB). Hai le seguenti possibilita' (e problemi):

    • spedire un DVD con il servizio postale

      Fuori discussione - viviamo nell'anno <> dopo l'invenzione di Internet! Spedire supporti hardware e' da trogloditi.

    • usare la posta elettronica (e-mail)

      Gran parte dei server di posta elettronica hanno un limite di 10 MB per ognuna delle e-mail e la quota totale e' di meno di 100 MB per utente.

    • uucp

      Perche' non usare la scrittura cuneiforme su una lastra di pietra?

    • ssh

      Avete la password dei vostri amici oppure siete disposti a dargli la vostra? - solo per trasferire un file?

    • ftp

      • Quale server ftp usare?
      • Quale utente usare, quale password?
      • Non vi dispiace mandare password e files non crittografati su Internet (insicura per definizione)?
      • Il vostro proxy supporta l'ftp passivo?
      • In caso di ftp anonimo:
        • Permette di caricare file da 1 GB?
        • Permette di cancellare il file caricato subito dopo?
        • Chi altri puo' fare il download del vostro file?
        • Chi altri puo' cancellare il vostro file?
        • Dovete mandare ai vostri amici il link per lo scarico, loro devono informarvi di avere effettuato il download del file e voi dovete cancellarlo subito dopo.
          In poche parole: una rottura di scatole.

    • http

      • Non esiste un programma di default - deve essere costruito.
      • Non esiste l'auto-notifica.
      • Non esiste l'auto-cancellazione.
      • Pochissimi server HTTP possono trattare file piu' grandi di 2 GB.

    • sendfile

      • Avete UNIX ed avete sendfile installato?
      • Il vostro destinatario ha UNIX ed ha sendfile installato?
      • Sicuri che ne' voi, ne' il vostro destinatario avete un firewall che blocca la porta 487?

    • servizi commerciali come DropLoad, ALLPeers, YouSendIt, eccetera

      • Quale limite hanno (gran parte: < 2 GB)?
      • Cosa dire di sicurezza e privacy: i vostri file saranno salvi e sicuri?
      • Sono basati su servizi open source o su proprietari?
      • Sono accessibili con qualsiasi browser oppure hanno bisogno di java, active-X, flash o qualche altro plug-in?
      • Sopravviveranno per piu' di qualche mese?
        (Per esempio servizi quali DropLoad, ALLPeers e drop.io hanno gia' terminato la loro attivita')

    Se avete risposto "no" ad almeno ad una delle domande, avete bisogno di F*EX.

    Principali caratteristiche di F*EX

    • trasferimento file di dimensioni virtualmente illimitate.
    • il destinatario ed il mittente hanno bisogno solo di un programma di posta elettronica e di un browser WEB di qualsiasi tipo: non devono installare nulla.
    • funzioni RESEND e REGET per riprendere l'esecuzione dopo un blocco della connessione all'ultimo byte.
    • auto-notifica del destinatario.
    • auto-cancellazione dopo il download.
    • auto-cancellazione dopo un periodo di 5 giorni (per default).
    • gli utenti "full" possono creare "sottoutenti" o utenti "limitati" i quali possono spedire solo a questo server.
    • gli utenti "full" possono creare gruppi in analogia a quanto succede per le liste di distribuzione, solo che viene fatto per i file.
    • manutenzione semplice: non e' necessario l'intervento dell'amministratore per la creazione di nuovi utenti F*EX.
    • l'invio di file a piu' destinatari occupa nel server solo lo spazio di una sola spedizione.
    • F*EX e' un web-service di tipo HTTP e non ha bisogno di "tunnels" nel firewall.
    • sono supportati anche i flussi (stream).
    • per gli utenti che conoscono UNIX, ci sono gli script-shell fexsend e fexget che evitano l'uso di un browser-WEB.
    • i protocolli ed il codice sorgente sono liberamente disponibili (Perl Artistic).

    Parliamo di SEX

    F*EX ha un compagno: Stream EXchange (SEX).

    Potete immaginare che SEX sia una specie di lunga pipe UNIX con un relay in mezzo. Questo servizio puo' essere utilizzato per il travaso di dati da un utente A ad un utente B quando A e B non possono stabilire una connessione diretta ma entrambi possono stabilire una connessione HTTP con il server SEX. Per una completa integrazione con i tool di concatenazione dei comandi di UNIX, ci sono gli script-shell sexsend and sexget.

    L'autenticazione e' la stessa utilizzata da F*EX.

    Altre domande?

    Vedi le FAQ

    contattate: fexmaster
    fex-20130805/locale/italian/htdocs/FAQ.html0000644000174700017470000002546712031354003016350 0ustar fexfex
    Domande Generiche:
    ==================
    
    Q: Perche' il nome e' "F*EX" invece del piu' corto "FEX"?
    
    A: Al momento della pubblicazione c'era gia' un (vecchio) programma
       nominato "FEX" su freashmeat.net
    
    
    Q: Perche' non usare un servizio commerciale come
       DropLoad, ALLPeers, YouSendIt, ecc. ?
    
    A: Tutti hanno un limite di 2 GB o meno.
       I loro livelli di sicurezza e privacy sono sconosciuti.
       Non sono servizi basati su software open-source.
       Non ci sono client UNIX (a linea di comando) per loro.
       Hanno bisogno di java, Active-X, Flash o altri plug-in.
       Non si sa quanto tempo sopravviveranno - DropLoad e ALLPeers hanno
       gia' concluso la loro attivita'.
    
    
    Q: Perche' c'e' un cammello nel logo?
    
    A: Il logo e' stato ispirato al cammello del Perl, ma e' basato sul
       cammello di peluche della Steiff che ci portiamo insieme con noi
       nelle nostre corse con il tandem.
       Il logo e' stato disegnato dal mio "fuochista" Beate
       http://fex.rus.uni-stuttgart.de/Vortrag/tosa.html
    
    
    Q: Dovo posso prendere i sorgenti di F*EX ?
    
    A: http://fex.rus.uni-stuttgart.de/fex.html
    
    
    Q: Dove posso installare F*EX ?
    
    A: In un host UNIX con una entry DNS ed un SMTP per la spedizione
       delle e-mail. Su questo server bisogna avere i privilegi di root.
    
    
    Q: Cosa sono DNS e SMTP?
    
    A: Lascia perdere F*EX. E' al di la' delle tue possibilita'.
    
    
    Q: Chi e' l'autore ?
    
    A: Ulli Horlacher <framstag@rus.uni-stuttgart.de>
    
    
    Q: Che tipo di licenza ha F*EX ?
    
    A: Perl Artistic free software, vedete http://fex.rus.uni-stuttgart.de/doc/Licence
    
    
    Q: C'e' una mailing list per F*EX ?
    
    A: https://listserv.uni-stuttgart.de/mailman/listinfo/fex
    
    
    Q: Dove posso trovare un servizio commerciale per F*EX ?
    
    A: Contattate fex@nepustil.net http://www.nepustil.net/
    
    
    Q: Ho altre domande che non trovo in questo documento.
    
    A: Chiedete all'autore <framstag@rus.uni-stuttgart.de>
    
    
    
    Domande Utente:
    ===============
    
    Q: Cos'e' il campo "auth-ID" ?
    
    A: Il campo auth-ID e' un identificativo interno che individua l'utente;
       e' lo username.
       E' creato la prima volta o dall'amministratore o attraverso il processo
       di registrazione automatico e puo' essere successivamente modificato
       da te (che sei l'utente).
       Pensa come se fosse una password a bassa sicurezza.
    
    Q: Posso usare un proxy HTTP ?
    
    A: Si'.
    
    
    Q: Ho caricato un file ENORME, ma ho fatto un errore di battitura
       nell'indirizzo del destinatario. Ora mi trovo con una e-mail
       di errore.
       Devo effettuare di nuovo il caricamento di questo ENORME file?
    
    A: No, non e' necessario. Puoi ridirigere il file con
       http://$HTTP_HOST$/rup
    
    
    Q: Ho caricato un file ENORME ma ho dimenticato uno dei destinatari.
       Devo ricaricarlo?
    
    
    A: No, non e' necessario. Puo' inoltrare il file con
       http://$HTTP_HOST$/foc
    
    
    Q: Posso caricare file di dimensioni > di 2 GB con il mio browser !?
    
    A: Tutti i browser che conosco hanno dei bug nella loro implementazione
       delle FORM HTML.
       Il limite e' per lo piu' di 2 GB, molto spesso e' di 4 GB.
       Dovete usare uno speciale client F*EX per caricare file > 2GB,
       vedete http://$HTTP_HOST$/tools.html
    
    
    Q: Il mio download si e' bloccato prima di finire.
       Posso riprenderlo?
    
    A: F*EX supporta il recupero del download ma anche il vostro client deve
       supportare questa funzione. Firefox, per esempio, non ha questa funzione,
       serve un'altro client come Opera, Wget o Fexget.
    
    
    Q: Il caricamento del mio file si e' interrotto prima di finire.
       Posso riprenderlo?
    
    A: F*EX supporta la ripresa del caricamento interrotto di un file ma anche
       il client deve supportarlo. Nessun browser WEB ha questa funzionalita',
       avete bisogno di uno speciale client F*EX come fexsend, schwuppdiwupp o F*IX.
       Vedete http://$HTTP_HOST$/tools.html
    
    
    Q: Il mio browser WEB non puo' eseguire il client java F*IX
       in quanto non trova l'ambiente java runtime e quindi
       non puo' caricare la applet F*IX
    
    
    A: Manca il plug-in java per il vostro browser WEB. Sui sistemi Debian e
       Ubuntu potete installarlo con questo comando:
       "sudo aptitude install sun-java6-plugin"
    
    
    Q: Quando schiaccio [ESC] in firefox il caricamento si cancella. Perche'?
    
    A: Si tratta di una caratteristica di firefox: il tasto ESC termina
       l'operazione corrente.
       Soluzione semplica: non schiacciate ESC in Firefox.
       Soluzione complessa: chiedete agli sviluppatori di Firefox di aggiungere
       la configurazione della tastiera.
    
    
    Q: Spedire come utente F*EX e' facile, ma come posso
       ricevere i file da altri utenti all'esterno?
    
    A: Registrali come tuoi "sotto-utenti" oppure crea un gruppo F*EX
       con http://$HTTP_HOST$/fuc
    
    
    Q: Qualche volta posso scaricare un file piu' di una volta,
       specialmente quando ripeto l'operazione velocemente.
       La funziona di autodelete e' poco affidabile?
    
    A: Il server F*EX rende disponibile il file scaricato ancora per un
       periodo di 1 minuto. Questo e' necessario per evitare che alcuni
       "download managers" piuttosto stupidi diano errore in quanto
       richiedono il file parecchie volte di seguito.
    
    A: Il vostro fexmaster ha impostato la variabile AUTODELETE=DELAY
       come default, il che significa che il processo di
       autocancellazione e' eseguita una volta al giorno.
    
    A: Certi utenti (usate i sorgenti!!!) possono impostare il flag
       "non cancellare dopo il download".
    
    
    Q: La finestra temporale prima che il file sia cancellato e' troppo
       stretta per me, ho bisogno di allargarla. Come posso fare?
    
    A: Usate fexsend, chiedete al vostro fexmaster oppure leggete il
       codice sorgente :-)
    
    
    Q: Durante il download di un file con Internet Explorer
       mi dice "Non posso aprire il sito Internet". Cosa posso fare?
    
    A: Usate Firefox o qualsiasi altro browser WEB compatibile con Internet,
       dato che Internet Explorer non lo e'. Questo e' uno dei tanti bug di
       Internet Explorer.
    
    
    
    
    Domande Amministrative:
    =======================
    
    Q: Non posso installare un server web come fexsrv perche'
       non ho i permessi di root. Esiste una pura versione CGI
       di F*EX eseguibile con un web server Apache ?
    
    A: F*EX e' rigidamente vincolato a fexsrv per diverse ragioni (performance,
       limite dimensione file, concetto di sessione, etc) e non puo' essere
       eseguito come una CGI sotto apache.
       Potete dare un'occhiata a
       http://gpl.univ-avignon.fr/filez/
       http://freshmeat.net/projects/eventh/
       http://www.schaarwaechter.de/sp/projekte/dateiaustausch.html (Solo in Tedesco!)
       il quale implementa uno scambio file come pura CGI, ma ha il limite dei 2 GB.
    
    
    Q: F*EX non funziona per nulla!
       Non mi posso connettere con il mio browser web!
    
    A: Controllate il routing, le impostazioni del firewall e di ipfilters.
       Controllate anche che il vostro xinetd sia collegato con il
       wrapper-tcp e sia configurato correttamente (hosts.allow).
       F*EX necessita della porta 80/tcp (HTTP) e opzionalmente
       della 443/tcp (HTTPS).
    
    
    Q: F*EX e' troppo complicato!
       Mi serve qualcosa di piu' semplice.
    
    A: Provate http://www.home.unix-ag.org/simon/woof.html
    
    
    Q: Come posso integrare F*EX nell'ambiente di gestione
       dell'utente esistente nel mio sito?
    
    A: F*EX ha diversi moduli di autenticazione:
       locale, RADIUS, LDAP, mailman e POP
       Per gli ultimi 4 si prega di contattare l'autore
       framstag@rus.uni-stuttgart.de
    
    
    Q: Vorrei che i miei utenti locali usassero
       F*EX automaticamente. Come??
    
    A: Lasciate che si registrino da soli con http://yourfexserver/fur
       Dovete editare il file lib/fex.ph ed impostare (esempio):
       @local_hosts = qw(127.0.0.1 10.10.100.0-10.10.255.255);
       @local_domains = qw(flupp.org ulm.sub.net);
       (Ovviamente dovete iunserire i vostri dati reali!)
    
    
    Q: Ho bisogno di maggior sicurezza! Come posso abilitare HTTPS??
    
    A: Leggete la documentazione doc/SSL ed anche cercate "fop_auth" in doc/concept
    
    
    Q: Ho bisogno di un look aziendale.
       Come posso configurare F*EX per questo?
    
    A: Potete Guardare la variabile @H1_extra nel file fex.ph ed aggiungere
       codice HTML al file htdocs/header.html
    
    A: Guardate il file htdocs/fup_template.html, modificatelo secondo i vostri
       bisogni ed utilizzatelo come start-page.
    
    
    Q: F*EX e' troppo complicato per i miei utenti.
       Ho bisogno di una form semplificata.
    
    A: Guardate il file htdocs/fup_template.html
    
    
    Q: Vorrei che le e-mail BCC indirizzate all'amministratore
       fex fossero spedite ad altro indirizzo.
    
    A: Usate procmail o scrivete OTHERADDRESS in /home/fex/.forward
    
    
    Q: Posso avere una versione localizzata
       nella mia lingua??
    
    A: Con il vostro aiuto, si'. Per favore contattate l'autore a
       framstag@rus.uni-stuttgart.de
    
    
    Domande varie:
    ==============
    
    Q: F*EX e' ottimo! Posso lavorare con
       il team di sviluppo?
       Che cosa c'e' bisogno di fare?
    
    A: Contattate l'autore framstag@rus.uni-stuttgart.de
       Funzionalita' richieste:
    
         - Un plug-in F*EX per thunderbird o outlook
         - Supporto in altre lingue
    
    
    fex-20130805/locale/italian/lang.html0000644000174700017470000000001111605620477015371 0ustar fexfexitaliano fex-20130805/locale/translations0000644000174700017470000026725612163007711014625 0ustar fexfex# english: Ulli Horlacher # german: Waldemar Bronsch # swabian: Hans-Georg Bickel # spanish: Francisco Ruiz # galician: Anton Meixome # italian: Vanni Piagno # czech: Michal Simunek # french: Jean-Baptiste Denis F*EX operation control ERROR F*EX Bedienungssteuerungs-Fehler F*EX Fehler bei dr Bedienongsschdeuerong Error del control de operaciones de F*EX Erro do control de operacións do F*EX Errore di controllo delle operazioni di F*EX Chyba při řízení provozu F*EX Erreur de gestion F*EX back to F*EX operation control Zurück zur F*EX-Bedienungssteuerung Zrigg zur Bedienongsschdeuerong Volver al control de operaciones de F*EX Volver ao control de operacións do F*EX Torna al controllo delle operazioni di F*EX Zpět na řízení provozu F*EX Retour à la gestion de F*EX wrong user or auth-ID Falscher Benutzer oder falsche auth-ID Benutzr odr auth-ID isch falsch usuario o auth-ID erróneo o usuario ou o auth-ID son incorrectos utente o auth-ID sbagliato chybný uživatel nebo ověřovací ID utilisateur ou auth-ID invalide operation control Bedienungssteuerung Bedienongsschdeuerong control de operaciones control de operacións controllo delle operazioni Řízení provozu gestion for user Für Benutzer Fir dr Benutzr para el usuario para o usuario per l'utente pro uživatele pour l'utilisateur You as the sender have a server disk quota of $quota MB and currently using Sie als Absender haben auf dem Server insgesamt $quota MB Speicherplatz und Sie benutzen momentan Du als Absender hosch uffm Server alles en allem $quota MB Platz zom Schbeichra ond Du benutzsch dovo grad Usted como emisario tiene una cuota de disco en el servidor de $quota MB y actualmente en uso Vostede como remitente ten unha cota de disco do servidor que está utilizando actualmente de $quota MB Tu in qualita' di mittente hai una quota disco nel server di $quota MB ed attualmente stai usando Jako odesilatel máte na serveru k dispozici $quota MB. Nyní využíváte Vous disposez de $quota MB d'espace disque en tant qu'expéditeur et vous utilisez actuellement sender quota (used) Absender Speicherplatz (benutzt) Absender Platz zom Schbeichra (benutzt) cuota de envío (usada) cota de remitente (usada) quota mittente (in uso) limit pro odesilatele (využito) quota expéditeur (utilisé) recipient quota (used): Empänger Speicherplatz (benutzt): Empfänger Platz zom Schbeichra (benutzt): quota de recepción (usada): cota de destinatario (usada): quota destinatario (in uso): limit pro příjemce (využito): quota destinataire (utilisé): Retrieve a list of all your received files in F*EX spool Zeige die Liste aller empfangenen Dateien Zeig mol a Lischde von älle empfangene Dateia Ver la lista de todos los ficheros recibidos en la cola de F*EX Ver a lista de todos os ficheiros recibidos na cola de F*EX Richiama una lista di tutti i tuoi file ricevuti nello spool di F*EX Načíst seznam všech souborů čekajících ve frontě Récupérer une liste de tous les fichiers que vous avez reçus Show download URLs of files you have sent Liste Download URLs von gesendeten Dateien auf Zoig Ronderlad URLs von verschickte Dateia Mostrar direcciones URL de los archivos enviados Amosar os URL dos ficheiros enviados Mostra scarica gli URL dei file inviati Zobrazit URL pro stažení souborů, které jste odeslali Lister les URLs des fichiers que vous avez envoyés Forward a copy of a file you already have uploaded to another recipient Eine Kopie der Datei weiterleiten, welche Sie bereits für einen anderen Empfänger hochgeladen haben A Kobie von der Datei weiderloide, die Du scho fier en andra Empfänger nuffglade hosch Reenviar una copia de un fichero que ha subido a otro destinatario Reenviar unha copia dun ficheiro que cargou a outro destinatario Inoltra una copia di un file che hai gia' caricato per un altro destinatario Přidat příjemce k již nahranému souboru Reexpédier une copie d'un fichier que vous avez déja uploadé à un autre destinataire Redirect files you have uploaded to a wrong or misspelled recipient Leite Dateien weiter, die an eine falsche oder ungültige E-Mail Adresse gegangen sind Dateia weiderloide, die an a falsche oder ogildige E-Mail-Adress gange send Redirigir ficheros que ha subido y enviado a un destinatario equivocado o mal escrito Redirixir ficheiros que cargou e enviou a un destinatario equivocado ou mal escrito Inoltra file che hai caricato ad un destinatario sbagliato o di cui hai sbagliato l'indirizzo Přesměrovat nahrané soubory pro nesprávného či chybně uvedeného příjemce Rediriger un fichier que vous avez déja uploadé vers un mauvais destinataire Create a subuser who can send you files. Enter his e-mail address: Subuser anlegen, der Ihnen Dateien schicken kann. Geben Sie seine E-Mail Adresse ein: Subuser olega, der dir Dateia schicka ko. Gib sei E-Mail Adress ei: Crear un subuser que pueda enviar archivos. Escriba su dirección de correo electrónico: Crear un subusuario que poida enviarlle ficheiros. Escriba o seu enderezo de correo: Crea un sottoutente che possa spedirti dei file. Inserisci il suo indirizzo e-mail: Vytvořit poduživatele, který vám může zasílat soubory. Zadejte jeho e-mailovou adresu: Créer un utilisateur qui peut vous envoyer des fichiers. Saisir son adresse électronique: for only one upload nur für einen Upload bloss fir oimal Nufflada por sólo una carga Soamente para un envío per un solo upload pouze pro jedno nahrání pour un upload unique Comment to send with information e-mail: Kommentar, der mit der Informations E-Mail mitgeschickt wird: Kommentar, der mit dr Enformations E-Mail mitgschickt wird: Comentario para enviar la información por e-mail: Comentario que se enviará xunto coa información do correo: Commenta per spedire con un'e-mail di notifica: V informačním e-mailu odeslat komentář: Commentaire à envoyer avec le message d'information: create subuser and send e-mail Subuser anlegen und E-Mail verschicken Subuser olegea ond E-Mail verschicka crear subuser y enviar e-mail Crear un subusuario en enviar un correo crea un sottoutente se spedisci l'e-mail vytvořit poduživatele a odeslat e-mail créer un utilisateur et envoyer un message électronique You can register yourself Sie können sich selbst registrieren Du kosch De selber regischdriera Puede autoregistrarse Podo autorexistrarse Puoi registrarti Můžete se zaregistrovat Vous pouvez vous enregistrer if you do not have a F*EX account yet wenn Sie noch keinen F*EX Account haben wenn De no koi F*EX Konto hosch si no tiene todavía una cuenta en F*EX se non ten aínda unha conta no F*EX se non hai ancora il tuo account F*EX pokud ještě nemáte svůj F*EX účet si vous n'avez pas déjà un compte F*EX You may also use anonymous upload Sie können auch anonymen Upload verwenden. Du kosch au anonymes Nufflada nemma. Se tambien puede usar anonymous upload Tamén pode usar o envío anónimo Potresti anhe utilizzare anonymous upload Můžete také využít anonymnínahrávání Vous pouvez aussi utiliser l'upload anonyme $file already exists for $file existiert bereits für $file gibts scho fir $file ya existe para xa existe $file para $file esiste giàper $file již existuje pro Le fichier $file existe déjàpour $file already exists - purge it?! $file existiert bereits - entfernen?! $file gibts scho - wegschmeissa?! $file ya existe - ¡¿Purgarlo?! xa existe $file - purgalo?! $file esiste già - lo vuoi eliminare?! $file již existuje - odstranit jej?! Le fichier $file existe déjà - Effacer?! Manage your subusers and groups Subusers und Gruppen verwalten Onderbenutzr ond Grubba verwalde Gestione sus subusuarios y grupos Xestione os seus subusuarios e grupos Gestisci i tuoi sotto-utenti e gruppi Spravovat své poduživatele a skupiny Gérer vos sous-utilisateurs et vos groupes 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 aber ned vergessa, gell recuerden recórdeo ricordati zapamatovat souvenez-vous en Edit your address book Ihr Adressbuch editieren Dei Adressbüchle bearbeide Edite su libro de direcciones Edite a súa axenda de enderezos Edita la tua rubrica Upravit adresář Éditez votre carnet d'adresses Get detailed notification e-mails (current setting: brief) Ausfürliche Benachrichtigungs E-Mails bekommen (aktuelle Einstellung: kurz) Langs Gschwätz en de Benochrichtigongs E-Mails (aktuelle Eischtellong: kurz) Recibir detallado e-mails de notificación (configuración actual: corto) Obter unha detallada notificación para os correos (axuste actual: breve) Avere dettagliata di notifica e-mail (impostazione attuale: breve) Dostávat podrobné e-maily s oznámením (současné nastavení: zkrácené) Recevoir des emails de notifications détaillés (configuration courante: simple) Get brief notification e-mails (current setting: detailed) Kurze Benachrichtigungs-E-Mails bekommen (aktuelle Einstellung: detailliert) Machs kurz en de Benochrichtigongs-E-Mails (aktuelle Eischtellong: langs Gschwätz) Recibir corto e-mails de notificación (configuración actual: detallado) Obter unha breve notificación para os correos (axuste actual: detallado) Avere breve notifica e-mail (impostazione attuale: dettagliata) Dostávat e-maily s upozorněním v zkráceném formátu (současné nastavení: detailed) Recevoir des emails de notifications simple (configuration courante: détaillé) Get reminder notification e-mails (current setting: no reminders) Erinnerungs E-Mails erhalten (aktuelle Einstellung: keine) Drodenka E-Mails erhalta (aktuelle Eischtellong: koine) Get reminder notification e-mails (current setting: no reminders) Get reminder notification e-mails (current setting: no reminders) Get reminder notification e-mails (current setting: no reminders) Get reminder notification e-mails (current setting: no reminders) Get reminder notification e-mails (current setting: no reminders) Get reminder notification e-mails (current setting: no reminders) Get no reminder notification e-mails (current setting: send reminders) Keine Erinnerungs E-Mails erhalten (aktuelle Einstellung: Erinnerungs E-Mails werden verschickt) Koine Drodenka E-Mails erhalta (aktuelle Eischtellong: Drodenka E-Mails werdad verschickt) Get no reminder notification e-mails (current setting: send reminders) Get no reminder notification e-mails (current setting: send reminders) Get no reminder notification e-mails (current setting: send reminders) Get no reminder notification e-mails (current setting: send reminders) Get no reminder notification e-mails (current setting: send reminders) Get no reminder notification e-mails (current setting: send reminders) You will now get no reminder notification e-mails Sie werden nun keine Erinnerungs E-Mails erhalten Du wirsch jetzt koine Drodenka E-Mails meh bekomma You will now get no reminder notification e-mails You will now get no reminder notification e-mails You will now get no reminder notification e-mails You will now get no reminder notification e-mails You will now get no reminder notification e-mails You will now get reminder notification e-mails Sie werden nun Erinnerungs E-Mails erhalten Du wirsch jetzt Drodenka E-Mails bekomma You will now get reminder notification e-mails You will now get reminder notification e-mails You will now get reminder notification e-mails You will now get reminder notification e-mails You will now get reminder notification e-mails Notification e-mails now come in detailed format Benachrichtigungs-E-Mails kommen ab jetzt in detailliertem Format Benochrichtigongs-E-Mails kommet ab jetzt mit langem Gschwätz E-mails de notificación desde ahora datallados Os correos de notificación virán a partir de agora en formato detallado Notifica e-mail ora sono disponibili in formato dettagliato E-maily s upozorněním jsou nyní odesílány v podrobném formátu Les emails de notifications sont maintenant au format détaillé Notification e-mails now come in short format Benachrichtigungs-E-Mails kommen ab jetzt in kurzem Format Benochrichtigongs-E-Mails kommet ab jetzt em kurzem Format E-mails de notificación desde ahora cortos Os correo de notificación virán a partir de agora en formato curto Notifica e-mail ora sono disponibili in formato breve E-maily s upozorněním jsou nyní odesílány ve zkráceném formátu Les emails de notifications sont maintenant au format simple Back to fup (upload page) Zurück zu fup (Upload Seite) Zrigg zu fup (Nufflad-Seite) Volver a fup (p´gina de carga) Volver a fup (p´xina de carga) Indietro a fup (pagina di caricamento) Zpět na fup (stránku pro nahrávání) Retour à fup (page d'upload) Download URLs of files you have sent Download URLs von gesendeten Dateien Ronderlad URLs von verschickte Dateia URLs de descarga de los archivos enviados Descargar os URL dos ficheiros enviados Scarica URL dei file che sono stati inviati URL pro stažení souborů, které jste odeslali URLs de téléchargement que vous avez envoyés

    to

    an

    an

    vez

    para

    per

    pro

    pour reminder F*EX-upload Erinnerung F*EX-upload Ned vergessa F*EX-upload recuerdo del F*EX-upload recordatorio do envío F*EX ricordo F*EX-upload Oznámení o nahraném souboru na F*EX Pense-bête F*EX-upload value="continue" value="weiter" value="weidr ghods" value="continuar" value="continuar" value="continua" value="pokračovat" value="continuer" > user: > Benutzer: > Benutzr: > usuario: > usuario: > utente: > uživatel: > utilisateur: user config ERROR ERROR Benutzer-Einstellungen ERROR Benutzr-Eischdellunga ERROR en la confiuración del usuario Produciuse un ERRO na configuación do usuario ERRORE di configurazione utente CHYBA nastavení uživatele ERREUR de configuration utilisateur F*EX user config F*EX Benutzer-Einstellungen F*EX Benutzr-Eischdellunga configuración del usuario F*EX configuración do usuario F*EX Configurazione utente F*EX Nastavení F*EX uživatele Configuration utilisateur F*EX An information e-mail has been sent to your subuser Eine Benachrichtiguns-E-Mail wurde gesendet zu Ihrem Subuser Dein Onderbenutzr isch per E-Mail benochrichdigt worde Un correo electrónico informativo se ha enviado a su subusuario Un correo electrónico informativo enviouse ao seu subusuario Una e-mail di informazione e' stata spedita al tuo sotto-utente Vašemu poduživateli byl odeslán informační e-mail Un message d'information a été envoyé à votre sous-utilisateur A one time upload URL for $otuser has been created Eine einmal gültige upload URL für $otuser wurde angelegt A oimol giltig nufflad URL fir $otuser isch oglegt worda Un URL para subir una vez $otuser ha sido creado Un enderezo URL de nico uso para $otuser acaba de se crear E' stato creato un URL di caricamento utilizzabile una sola volta per l'utente $otuser Jednorázová URL pro nahrání pro $otuser byla vytvořena Une URL d'upload à usage unique pour $otuser a été créée and an information e-mail has been sent to this address und eine Informations-E-Mail wurde an diese Adresse verschickt ond a Was-macha-musch-E-Mail isch do no verschickt worda y un email de informacin ha sido enviado a esta direccin e un correo informativo acaba de se enviar a este enderezo e una e-mail di informazioni stata spedita a questo indirizzo a informační e-mail byl odeslán na tuto adresu et un message d'information a été envoyé à cette adresse wrong user or auth-ID Falscher Benutzer oder falsche auth-ID Benutzr oddr auth-ID send falsch usuario o auth-ID erróneo o usuario ou o auth-ID son incorrectos utente o auth-ID sbagliato chybný uživatel nebo ověřovací ID utilisateur ou auth-ID invalide no group name specified kein Gruppen-Name angegeben Seggl, Du hosch koin Grubbenoma ogebe nombre de grupo sin especificar non se especificou o nome do grupo nome gruppo non specificato nebyl uveden žádný název skupiny pas de nom de groupe spécifié is already a registered F*EX full user ist bereits ein registrierter F*EX Voll-Benutzer isch scho längscht als Vollbenutzr bei F*EX regischdriert ya es un usuario normal registrado en F*EX xa é un usuario completo rexistrado en F*EX e' gia' un utente F*EX completo registrato je již zaregistrovaným plnohodnotným F*EX uživatelem est déja enregistré en tant qu'utilisateur F*EX Your subuser upload URL is: Ihr Subuser Upload-URL ist: Dei Onderbenutzr Nufflad-URL isch: La URL de subida de su subusuario es: O seu enderezo URL de carga como subusuario: L'URL per il caricamento del tuo sotto-utente e': URL pro nahrání pro vašeho poduživatele je: L'URL d'upload de votre sous-utilisateur est: Your subusers upload URLs are: Die Upload-URLs für Ihre Subusers sind: Dui Nufflad-URLs fier Deine Onderbenutzr send: Las URLs de sus subusuarios son: Os URL de carga dos seus subusuarios Gli URL per il caricamento dei tuoi sotto-utenti sono: URL pro nahrání pro vaše poduživatele jsou: Les URLs d'upload de vos sous-utilisateurs sont: An information e-mail has been sent to Eine Benachrichtigungs-E-Mail wurde gesendet an A Benochrichdigongs-E-Mail isch gschickt worde an Un correo electrónico informativo se ha enviado a Enviouse un correo electrónico informativo Una e-mail di informazione e' stata spedita a Informační e-mail byl odeslán na Un message d'information a été envoyé à add more subusers weitere Subusers hinzufügen no meh Onderbenutzr drzudo añadir más subusuarios engadir más subusuarios aggiungi ulteriori sotto-utenti přidat více poduživatelů ajouter plus de sous-utilisateurs Edit address book Adressbuch editieren Adressbüchle bearbeita Editar el libro de direcciones Editar a axenda de enderezos Edita la rubrica Upravit adresář Éditez le carnet d'adresse Entry:aliase-mail address# optional comment Eintrag:AliasE-Mail Adresse# optionaler Kommentar Eidrag:AliasE-Mail Adress# Kommendar (kosch macha oddr bleiba lassa) Entrada:aliasdirección de correo electrónico# comentario opcional Entrada:aliasenderezo de correo electrónico# comentario opcional Entrata:aliasindirizzo e-mail# commento opzionale Položka:aliase-mailová adresa volitelný komentář Entrée:aliasadresse e-mail# comment optionnel Example: Beispiel: Beischbiel: Ejemplo: Exemplo: Esempio: Příklad Exemple: value="submit" value="Absenden" value="Verschicke" valor="enviar" valor="enviar" value="sottometti" value="potvrdit" value="soumettre" You may use these alias names as F*EX recipient addresses on Sie können diese Alias-Namen als F*EX Empfänger-Adressen auf Du kosch selle Alias-Nome als F*EX Empfänger-Adresse uff Puede usar estos alias como direcciones de destinatarios en F*EX en Pode usar estes alias como enderezos de destinatarios do F*EX en Potresti usare questo alias come destinatario di F*EX Tyto aliasy můžete používat jako adresy F*EX příjemce na Vous pouvez utiliser ces alias comme destinataires F*EX sur 'fup' 'fup benutzen.' 'fup nemme.' 'fup' 'fup' 'fup' 'fup' 'fup' Alternatively you can fex a file ADDRESS_BOOK to yourself Alternativ können Sie die Datei ADDRESS_BOOK an sich selbst Du kosch au dui Datei ADDRESS_BOOK an De selber También puede enviar vía fex un fichero ADDRESS_BOOK a si mismo Tamén pode enviar vía fex un ficheiro ADDRESS_BOOK a si mesmo Alternativamente puoi inviare un file ADDRESS_BOOK a te stesso Nebo si můžete poslat soubor sami sobě Vous pouvez aussi vous envoyer un fichier ADDRESS_BOOK containing your alias definitions fexen, welche Ihre Alias-Definitionen enthält fexe, wo Deine Alias-Definitione dren send que contenga sus definiciones de alias que conteña as súas definicións de alias contiene le tue definizioni degli alias obsahuje definované aliasy contenant vos alias aliase-mail addressoptionscomment AliasE-Mail AdresseOptionenKommentar AliasE-Mail AdresseOptionenKommendar aliasdirección de correo electrónicoopcionescomentar aliasenderezo de correo electrónicoopciónscomentar aliasindirizzo e-mailopzionicommento aliase-mailová adresavolbykomentář aliasadresse e-mailoptionscommentaire back to fup (F*EX upload) zurück zu fup (F*EX Upload) zrigg zu fup (F*EX Nufflade) volver a fup (subida a F*EX) volver a fup (subida a F*EX) torna a fup (caricamento F*EX) zpět na fup (F*EX nahrání) retour à fup (F*EX upload) FEX config updated for FEX Konfiguration aktualisiert für Konfiguratio von F*EX uffm neieschte Schdand fier Actualización de la configuración de F*EX para Actualización da configuración de F*EX para Configurazione F*EX aggiornata per Nastavení FEX aktualizováno pro Configuration de FEX mise à jour pour You have to give these URLs to your subusers for fexing files to you Sie müssen diese URLs Ihren Subusers geben, damit sie Dateien an Sie fexen können Du musch selle URLs Deine Onderbenutzr gebba, damit se Dateia an Di fexe kenne Tiene que dar estas URLs a sus subusuarios para que puedan enviarle ficheros vía F*EX Ten que dar estes URL aos seus subusuarios para que poidan enviarlle ficheiros vía F*EX Devi dare questi URL ai tuoi sotto-utenti per spedirti file Aby vám mohli poduživatelé odesílat soubory, sdělte jim tyto URL Vous devez donner ces URLs à vos utilisateurs pour qu'ils puissent vous envoyer des fichiers Or click on the subuser's e-mail address link to send him an Oder klicken Sie auf den E-Mail Adressen-Link des Subusers, um ihm eine Oddr klick halt uff de E-Mail Adresse-Link von Deim Onderbenutzr, no kosch ihm a O pinche en el enlace a la dirección de correo electrónico del subusuario para enviarle un Ou prema sobre a ligazón do enderezo de correo do subusuario para enviarlle un O clicca nel link dell'indirizzo e-mail del sotto-utente per spedirgli un Nebo klikněte na odkaz s e-mailovou adresou poduživatele k odeslání Ou cliquer sur l'adresse de messagerie de votre sous-utilisateurs pour lui envoyer un information e-mail by the F*EX server Benachrichtigungs-E-Mail mit Hilfe des F*EX-Servers zu senden Benochrichdigongs-E-Mail ieber de F*EX-Server schicke correo electrónico informativo del servidor de F*EX correo electrónico informativo vía servidor do F*EX informazione spedita dal server F*EX informačního e-mailu pomocí F*EX serveru message d'information du server F*EX Beware! On the next page, all IDs will be displayed in clear text Vorsicht! Auf der nächsten Seite werden alle Passwörter in Klartext dargestellt Uffpasse! Uff dr nägschde Seit werdet älle Passwörter em Klartext ozeigt ¡Cuidado! En la página siguiente, todos los IDs se mostrarán sin cifrar Atención! Na vindeira páxina, todos os ID se amosarán en texto limpo Attenzione! Nella pagina successiva, tutti gli ID saranno mostrati in chiaro Pozor! Všechna ID se na další stránce zobrazí jako prostý text Attention! Sur la prochaine page, tous les IDs seront affichés en clair Your F*EX account: Ihr F*EX Account: Dei F*EX Konto: Su cuenta en F*EX: A súa conta no F*EX: Il tuo utente F*EX: Váš F*EX účet: Votre compte F*EX: New auth-ID: Neue auth-ID: Neie auth-ID: Nuevo auth-ID: Novo auth-ID: Nuovo auth-ID: Nové ověřovací ID: Nouvel auth-ID: (Remember your auth-ID when you change it!) (Unbedingt die auth-ID merken wenn sie geändert wird!) (Merk Dir obedingd Dei auth-ID wenn Du se gändert hosch!) (Recuerde su auth-ID cuando lo cambie) (Lembre o seu auth-ID cando o cambie) (Ricordati il tuo auth-ID quando lo cambi!) (Zapamatujte si své ověřovací ID, pokud jej změníte!) (Vous devez vous souvenir de votre auth-ID lorsque vous le changez) Allow special senders (= subusers) to fex files to you: Ihren ausgewählten Partnern (= Subusers) erlauben, Daten an Sie zu senden: Deim erlesene Freindeskreis (= Onderbenutzr) erlaube, Data an Di zom schicka: Permitir a remitentes especiales (= subusuario) que le envín vía F*EX ficheros a usted: Permitirlles a remitentes especiais (= subusuarios) enviarlle a vostede ficheiros por F*EX: Permetti a utenti speciali (= sotto-utenti) di spedirti file: Povolit speciální odesilatele (= poduživatelé), kteří vám mohou zasílat soubory: Autoriser des expéditeurs particuliers (= sous-utilisateurs) à vous envoyer des fichiers: Allow Erlaube Erlaub Permitir Permitir Permetti Povolit Autoriser "submit and continue" "Speichern und weiter" "Sbeichra ond weidermache" "enviar y continuar" "remitir e continuar" "sottometti e continua" "potvrdit a pokračovat" "soumettre et continuer" save and show upload URLs speichern und upload URLs anzeigen abschpeichra ond nufflad URLs ozeiga guardar y mostrar las direcciones URL de carga gardar e amosar URL enviado salva e mostra gli indirizzi di upload uložit a zobrazit URL pro nahrání sauvegarder et lister les URLs d'upload This list has entries in format:<e-mail address>:<encryption-ID> Diese Liste besteht aus Einträgen im Format:<E-Mail Adresse>:<encryption-ID> Sell Lischt beschdoht aus Eidragonge vom Format:<E-Mail Adress>:<encryption-ID> Esta lista tiene las entradas en formato:<e-mail address>:<encryption-ID> Esta lista ten entradas co formato :<enderezo de correo>:<ID-cifrado> Questa lista ha i contenuti nel formato: <e-mail address>:<encryption-ID> Položky seznamu jsou ve formátu:<e-mailová adresa>:<Å¡ifrovacíID> Les entrées de cette liste ont comme format:<adresse e-mail>:<encryption-ID> These special senders may fex files only to you! Diese besonderen Sender können Dateien nur an Sie fexen! Selle Absender send was Bsonders ond kenne Dateia bloß an dich fexe! ¡Estos remitentes especiales pueden enviar ficheros vía F*EX solo a usted! Estes remitentes especiais poden enviar ficheiros vía F*EX a vostede! Questi utenti speciali potrebbero spedire file solo a te! Tito speciální odesilatelé mohou odesílat soubory pouze vám! Ces expéditeurs particuliers peuvent seulement vous envoyer des fichiers It is not necessary to add regular fex users to your list, Es ist nicht notwendig, reguläre FEX Benutzer zu Ihrer Liste hinzuzufügen 'S isch net nedich, daß de reguläre F*EX Benutzr uff Dei Lischde setzsch No es necesario añadir usarios de F*EX normales a su lista, Non é necesario engadir usuarios de F*EX normais á súa lista, Non e' necessario aggiungere utenti regolari fex alla tua lista, Do tohoto seznamu není třeba přidávat běžné F*EX uživatele, Il n'est pas nécessaire d'ajouter des utilisateurs de F*EX à votre liste, because they already can fex weil diese bereits auch so fexen können weil dui kenned sowieso scho fexe porque ellos ya pueden enviar vía F*EX porque eles xa poden enviar vía F*EX perche' possono gia' spedire con F*EX protože ti vždy mohou odesílat soubory parce qu'ils peuvent déja utiliser fex The encryption-ID is necessary to generate a unique upload URL for this subuser Die encryption-ID wird für um eine eindeutige upload URL für diesen Subuser zu erzeugen Die encryption-ID isch notwendig um a eindeutig upload URL für den Subuser zom macha Hace falta una ID de codificación para generarle a este sub-usuario un inequívoco URL para subir Fai falta un ID de codificación para xerarlle a este subusuario un inequívoco URL para subir L'encryption-ID e' necessario per generare un unico URL di caricamento per questo sotto-utente Poduživatel musí mít k vytvoření unikátní URL pro nahrávání šifrovací ID L'encryption-ID est nécessaire pour générer une URL d'upload unique pour cet utilisateur If you omit the encryption-ID a random one will be used Wenn Sie die encryption-ID weglassen, wird eine zufällige gewählt Wenn Du die encryption-ID wegläscht, no wird a zufälliga gnomma Si se omite el cifrado-ID un nombre cualquiera se utilizará Se omite o ID-cifrado, utilizarase un aleatorio Se tu ometti l'ID crittato uno casuale verrà utilizzato Vynecháte-li šifrovací ID, použije se náhodně vygerenrované Si vous ne mentionnez pas l'encryption-ID, il sera généré aléatoirement A F*EX group is similar to a mailing list, but for files Eine F*EX Gruppe ist einem E-Mail-Verteiler ähnlich, allerdings eben für Dateien A F*EX Grupp isch so was wie en E-Mail-Verdoiler, halt fier Dateia Un grupo F*EX es similar a una lista de correo, pero para ficheros Un grupo F*EX seméllase 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 adresse de diffusion (mailing-list), mais pour les fichiers Edit your F*EX groups: Editieren Sie Ihre F*EX Gruppen: Bearbeit Deine F*EX-Gruppa: Edite sus grupos F*EX: Edite os seus grupos F*EX: Edita i tuoi gruppi F*EX: Upravit F*EX skupiny: Éditez vos groupes F*EX: new group Neue Gruppe Neie Grupp Grupo nuevo Novo grupo nuovo gruppo nová skupina nouveau groupe Your F*EX account on Ihr F*EX Account auf Dei F*EX Konto auf Su cuenta F*EX A súa conta F*EX Il tuo utente F*EX Váš účet pro F*EX Votre compte F*EX sur Your upload URL Ihre upload URL Dei nufflad URL su URL de subir O seu enderezo URL de carga Il tuo URL di caricamento URL pro nahrání Votre URL d'upload to upload one file to $user um eine Datei an $user zu schicken om a Datei an $user zom schicka para subir un fichero a $user para cargarlle un ficheiro a $user per caricare un file per $user jednoho souboru uživateli $user pour uploader un fichier à $user to upload files to $user um Dateien an $user zu schicken om Dateia an $user zom schicka para subir ficheros a $user para subir ficheiros a $user per caricare file a $user pro nahrávání souborů uživateli $user pour uploader des fichiers à $user to upload files to F*EX group $group um Dateien fuer F*EX-Gruppe $group bereitzustellen wenn De Dateia fier dui F*EX-Grupp $group nufflade willsch para subir ficheros al grupo F*EX $group para subir ficheiros ao grupo de F*EX $group per caricare file al gruppo F*EX $group pro nahrávání souborů F*EX skupině $group pour uploader des fichiers au groupe F*EX $group 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}/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 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 Questions? ==> F*EX admin: $admin Fragen? ==> Kontaktieren Sie den F*EX Administrator: $admin Froga? ==> Belaeschtig ruhig dr F*EX Adminischdrator: $admin Preguntas? ==> Administrador de F*EX: $admin Preguntas? ==> Administrador do F*EX: $admin Domande? ==> Amministratore F*EX: $admin Máte otázky? ==> Kontaktujte F*EX správce: $admin Questions? ==> Administrateur F*EX: $admin Your F*EX account on Ihr F*EX Account auf Dei F*EX Konto auf Su cuenta F*EX en A sú conta F*EX en Il tuo account F*EX su Váš F*EX účet na Votre compte F*EX sur A F*EX (File EXchange) account has been created for you on Ein F*EX (File EXchange) Account ist fuer Sie angelegt worden auf Du hosch jetzt a F*EX (File EXchange) Konto auf Una cuenta F*EX (File EXchange) se ha creado para usted en Creóuselle a vostede unha conta F*EX (File EXchange) Un account F*EX (File EXchange) e' stato creato per te su Byl vám vytvořen F*EX (File EXchange) účet na Un compte F*EX a été créé pour vous sur 'Use 'Bitte benutzen Sie 'Nemm 'Usa 'Use 'Usa 'Používání 'Utilisez See http://$ENV{HTTP_HOST}/ for more information about Siehe http://$ENV{HTTP_HOST}/ 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 $notify not found in $gf $notify nicht gefunden in $gf $notify net gfonda in $gf $notify no se encontró en $gf $notify non se atopou en $gf $notify non trovato in $gf $notify nebyl v $gf nalezen $notify non trouvé dans $gf Notification e-mail to $notify has been sent Benachrichtigungs-E-Mail an $notify wurde gesendet Benochrichdigongs-E-Mail an $notify isch verschickt worda Correo electrónico de notificación enviado a $notify Enviouse un correo de notificación a $notify E-mail di notifica e' stata spedita a $notify E-mail s oznámením pro $notify byl odeslán Un message d'information a été envoyé à $notify bad addresses:

    \n
      Fehlerhafte Adressen:

    \n
      Was send au des fier Adresse? Die send grottefalsch::

    \n
      dirección errónea:

    \n
      Os enderezos son incorrectos:

    \n
      indirizzo errato:

    \n
      chybné adresy:

    \n
      mauvaises adresses:

    \n
      you are already in group \@$group owned by $user Sie sind bereits in der Gruppe \@$group welche dem Benutzer $user gehört Du bisch doch scho längscht in derra Grupp \@$group von dem Benutzr $user ya pertenece al grupo \@$group propiedad de $user xa pertence ao grupo \@$group propiedade de $user sei gia' nel gruppo \@$group di proprieta' di $user ve skupině \@$group vlastněné uživatelem $user se již nacházíte vous êtes déja dans le groupe \@$group de l'utilisateur $user Go back Zurück No mol von vorne Volver Volver Torna indietro Vrátit se Retour and enter another group name und geben Sie einen anderen Namen für die Gruppe ein ond geb en andra Noma fier dui Grupp ei y introduzca un nuevo grupo e introduza un novo grupo e inserisci un'altro nome del gruppo a zadat jiný název skupiny et saisissez un autre nom de groupe Group \@$group has members: Die Gruppe \@$group hat folgende Mitglieder: Zur Grupp \@$group ghered: Los miembros del grupo \@$group son: Os membros do grupo \@$group son: Il gruppo \@$group ha i componenti: Členové skupiny \@$group: Le groupe \@$group a comme membres: (click address to send a notification e-mail to this user) (Klicken Sie auf die Adresse um eine Benachrichtigungs-E-Mail an diesen Benutzer zu senden) (Schieb Dei Maus uff d' Adress ond klick. Dann wird a Benochrichdigongs-E-Mail an den Benutzr gschickt) (pinche en la dirección para enviar correo electrónico de notificación a este usuario) (prema sobre o enderezo de correo electrónico de notificación a este usuario) (clicca l'indirizzo per spedire una e-mail di notifica a questo utente) (pro odeslání oznamovacího e-mailu uživateli, klikněte na jeho adresu) (cliquer sur l'adresse pour prevenir l'utilisateur avec un message) Edit F*EX group F*EX-Gruppe editieren F*EX-Grupp bearbeide Editar el grupo F*EX Editar o grupo F*EX 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 Cuando un miembro envía vía F*EX un fichero a esta lista, Cando un membro envía vía F*EX un ficheiro a esta lista, Quando un componente spedisce un file a questa lista, Odešle-li člen soubor do konference, Lorsque un membre envoie un fichier à cette liste then all other members will receive it dann werden alle anderen Mitglieder diese Datei erhalten no krieget älle andere wo in derre Grupp send, selle Datei entonces todos los demás miembros lo recibirán entón todos os demáis membros o recibirán allora tutti gli altri componenti la riceveranno obdrží jej všichni členové tous les autres membres vont le recevoir New group name: (You MUST fill out this field!) Neuer Name für die Gruppe: (Sie MÜSSEN dieses Feld ausfüllen!) Neier Nome fier d' Grupp: (Des Feld MUSCH Du ausfille!) Nuevo nombre de grupo: (¡DEBE rellenar este campo!) Novo nome de grupo: (DEBE cubrir este campo!) Nuovo nome del gruppo: (DEVI compilare questo campo!) Název nové skupiny: (Toto políčko MUSÍTE vyplnit!) Nouveau nom du groupe: (Ce champ ne peut pas être vide) This list has entries in format:<e-mail address> Diese Liste besteht aus Einträge in folgendem Format haben:<E-Mail Adresse> Die Lischde bschdohd aus Eiträg em Format:<E-Mail Adresse> Esta lista debe tener las entradas en el formato: <dirección de correo electrónico> Esta lista debe ter as entradas no formato: enderezo de correo electrónico> Questa lista deve avere le righe in questo formato:<indirizzo e-mail> Položky seznamu musí být ve formátu:<e-mailová adresa> Cette liste doit avoir des entrées de la forme:<Adresse e-mail> You define the auth-ID for this group member, which may not be a regular F*EX user Sie legen selbst die auth-ID für dieses Gruppen-Mitglied fest, das aber kein regulärer F*EX-Benutzer sein sollte Du beschdimmsch selber d' auth-ID von dem Gruppemitglied. Seller sodd abbr koin regulärer F*EX-Benutzr sei Usted establece el auth-ID para este miembro del grupo, que no puede ser un usuario normal de F*EX Vostede estabelece o auth-ID para este membro do grupo, que non pode ser un usuario normal de F*EX Definisci l'auth-ID per il membro di questo gruppo, il quale potrebbe non essere un utente F*EX regolare Definujete ověřovací ID pro člena skupiny, který zřejmě není běžným F*EX uživatelem Vous définissez l'auth-ID pour le membre de ce groupe, qui ne peut pas être un utilisateur F*EX ordinaire You can name any existing e-mail address Sie können hier eine beliebige gültige E-Mail Adresse angeben Du kosch do a giltige E-Mail-Adress nach Deim Guschto eigebba Puede nombrar cualquier dirección de correo electrónico Pode nomear calquera enderezo de correo electrónico Puoi nominare qualsiasi indirizzo e-mail esistente Jakoukoli existující e-mailovou adresu můžete pojmenovat Vous pouvez désigner n'importe quelle adresse e-mail existante delete file after download Datei nach dem Download löschen Datie nachm Ronderlada lösche borrar el fichero tras su descarga borrar o ficheiro trala súa descarga cancella il file dopo il download smazat soubor po stažení effacer le fichier après le téléchargement do not delete file after download Datei nach dem Download nicht löschen Datei nachm Ronderlada net lösche no borrar el fichero tras su descarga non eliminar o ficheiro despois da descarga non cancellare il file dopo il download nemazat soubor po stažení ne pas supprimer le fichier après le téléchargement delete file after download with delay Datei nach dem Download mit Verzögerung löschen Datei nachm Ronderlada erscht schpäter lösche borrar el fichero tras su descarga con retardo borrar o ficheiro tras a súa descarga con atraso cancella il file dopo il download con ritardo smazat soubor po stažení až po effacer le fichier après un délai à la suite du téléchargement F*EX service F*EX-Service F*EX-Dienscht Servicio F*EX Servizo F*EX servizio F*EX Služba F*EX Service F*EX Your reqested F*EX auth-ID for $fup?from=$from is: Ihre angefragte F*EX auth-ID fuer $fup?from=$from ist: 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: Votre auth-ID F*EX pour $fup?from=$from est: Or use: Oder Sie verwenden: Odr du nemsch: Or use: Or use: Or use: Or use: Or use: Your reqested F*EX login is: Ihr angefragter F*EX login ist: Dei agfragte F*EX login isch: Su solicitada login de F*EX es: A seu login solicitado de de F*EX é: Il tuo login F*EX richiesto e': Požadované přihlašovací údaje pro F*EX: Votre login F*EX est: Mail has been sent to you Mail wurde gesendet an Sie Mail isch an Dich gschickt worde El mensaje de correo se le ha enviado A mensaxe de correo xa se lle enviou Ti e' stata spedita una e-mail Zpráva vám byla odeslána Le message vous a été envoyé is not a regular F*EX user ist kein regulärer F*EX Benutzer isch koin ordnongsgemäßer F*EX-Benutzr no es un usuario normal de F*EX non é un usuario normal de F*EX non e' un utente regolare F*EX není běžným F*EX uživatelem n'est pas un utilisateur F*EX ordinaire You are not in this group Sie sind nicht in dieser Gruppe Du ghersch net zu derra Grupp Nos es miembro de este grupo Non é membro deste grupo Non sei in questo gruppo Nejste členem této skupiny Vous n'êtes pas dans ce groupe Recipient group has no members Empfänger-Gruppe hat keine Mitglieder Dui Grupp wo des no soll hot koine Miglieder El grupo destinatario no tiene miembros O grupo de destinatarios non ten membros I gruppi di distribuzione non hanno membri Skupina příjemců nemá žádné členy Le groupe destinataire n'a pas de membre No such group Diese Gruppe existiert nicht Selle Grupp gibt's net. Huatsempel No existe tal grupo Non existe tal grupo Non esiste questo gruppo Tato skupina neexistuje Groupe non trouvé unknown dkey Unbekannter dkey Den dkey kenn i net dkey desconocido dkey descoñecido dkey sconosciuto neznámý dkey dkey inconnue has been deleted by %s at %s wurde gelöscht von %s um %s isch glöscht worde von %s um %s ha sido borrado por %s a las %s eliminado por %s és %s e' stato cancellato da %s a %s byl smazán uživatelem %s dne %s a été effacé par %s le %s $filename deleted $filename gelöscht $filename glöscht $filename borrado $filename eliminado $filename cancellato $filename byl smazán $filename effacé $filename not deleted ($s) $filename nicht gelöscht ($s) $filename net glöscht $filename no borrado ($s) $filename non eliminado ($s) $filename non cancellato ($s) $filename nebyl smazán ($s) $filename non effacé ($s) > continue > weiter > Weiterschaffe > continuar > continuar > continua > pokračovat > continuer Files from Dateien von Dateia von Ficheros de Ficheiros de File da Soubory od Fichiers de Files for $to (*): Dateien für $to (*): Dateia fier $to (*): Ficheros para %to (*): Ficheiros para %to (*): File per $to (*): Soubory pro $to (*): Fichiers pour $to (*): \nfrom $from \nVon $from \nVon $from \nde $from \nde $from \nda $from \nod $from \nde $from >delete< >löschen< >löscha< >borrar< >eliminar< >cancella< >smazat< >effacer< >forward< >weiterleiten< >weiterleita< >forward< >forward< >forward< >forward< >forward< Files for other e-mail addresses you own will not be listed here! Dateien für Ihre andere E-Mail Adressen werden hier nicht aufgelistet! Dateia fier Deine andre E-Mail Adressa werded dohanne net uffglischtet! ¡Los ficheros para otras direcciones de correo electrónico suyas no son listadas aquí! Os ficheiros para outros enderezos de correo electrónico que teñ non se listan aquí! File per altri indirizzi di e-mail che ti appartengono non saranno elencati qui! Soubory pro další e-mailové adresy, které vlastníte, zde nebudou uvedeny! Les fichiers associés à vos autres adresses ne vont pas être listés ici! you are overquota Sie haben Ihr Speichervolumen überzogen Dei Schbeicherplatz isch rappelvoll ha excedido su cuota sobrepasou a sú cota Hai superato la quota překročili jste limit vous avez dépassé votre quota cannot receive files: is overquota Kann Dateien nicht annehmen: Speichervolumen überzogen I ko die Dateia net onemme: Dein Schbeicher isch scho vollgschdopft no puede recibir ficheros: ha excedido su cuota non pode recibir ficheiros: sobrepasou a súa cota non e' possibile ricevere il file: eccede la quota assegnata soubory nelze přijmout: překračují limit ne peut pas recevoir de fichiers: quota dépassé You ($from) are not allowed to fex to $to Sie ($from) dürfen nicht fexen an $to Du ($from) derfsch net fexa an $to Usted ($from) no puede enviar vía F*EX a $to Vostede ($from) non está autorizado para enviar, vía F*EX, a $to Tu ($from) non hai il permesso di spedire via F*EX a $to Vy ($from), nemáte dovoleno odesílat soubory pro $to Vous ($from) n'êtes pas autorisé à envoyer un fichier à $to recipient $to is not a registered F*EX full or sub user Empänger $to ist kein registrierter F*EX Voll- oder Subuser Dr Empfänger $to isch koin regischtrierder F*EX Voll- oddr Onderbenutzr el destinatario $to no es un usuario normal de F*EX registrado o un subusuario o destinatario $to non é un usuario normal de F*EX rexistrado ou un subusuario il destinatario $to non e' un utente o sotto-utente F*EX registrato příjemce $to není zaregistrovaným plnohodnotným uživatelem či poduživatelem F*EX le destinataire $to n'est pas un utilisateur ou un sous-utilisateur F*EX no upload key kein upload-Einmalschlüssel koi nufflad-Oimolschlissel ningun llave para subir non se cargou a chave no chiave di caricamento žádný klíč pro nahrání pas de clé d'upload request another one from fordern Sie einen neuen an von frog noch'm Neua bei pida otro de solicitar outra en richiedine un altro da požádat o jiný uživatele demander un autre de value="register" value="registrieren" value="regischtrier" value="registrado" value="rexistrado" value="registrato" value="zaregistrovat" value="inscription" Your client seems to be "$1" which is incompatible with F*EX and will probably not work Ihr Client scheint "$1" zu sein, das ist aber inkompatibel mit F*EX und wird vermutlich nicht funktionieren Dein Client isch scheints "$1", des isch abbr inkomatibel mit F*EX ond so wird des wahrscheinlich nix Su cliente parece ser "$1" que es incompatible con F*EX y probablemente no funcionará O seu cliente parece ser "$1" que é incompatíbel con F*EX e probablemente non funcionará Il vostro client sembra essere "$1", che e' incompatibile con F*EX e probabilmente non funzionera' 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: remitente: remitente: mittente: odesilatel: expéditeur: recipient: Empfänger: Empfängr: destinatario: destinatario: destinatario: příjemce: destinataire: recipient(s): Empfänger: Empfängr: destinatario(s): destinatario(s): destinatario(i): příjemce(i): destinataire(s): recipient(s)< Empfänger< Empfängr< destinatario(s)< destinatario(s)< destinatario(i)< příjemce(i)< destinataire(s)< e-mail address or alias E-Mail Adresse oder Alias E-Mail Adress oddr Alias dirección de correo electrónico o alias enderezo de correo electrónico ou alias indirizzo e-mail o alias e-mailová adresa či alias adresse e-mail ou alias or select from your address book oder aus Ihrem Adressbuch wählen oddr aus Deim Adressbüchle raussuche o seleccione de su libro de direcciones ou seleccione da súa axenda de enderezos o seleziona dal tuo rubrica nebo si vyberte ze svého adresáře ou sélectionner de votre carnet d'adresses and' und' ond' y' e' e a' et' add to recipients list zur Empfänger-Liste hinzufügen uff d' Empfängerlischte setze añada a la lista de destinatarios engadir á lista de destinatarios aggiungi alla lista di distribuzione přidejte jej (je) do seznamu příjemců ajouter à la liste des destinataires check recipient(s) and continue Empfänger überprüfen und fortsetzen Empfänger ieberpriafe ond weitermache compruebe el/los destinatario(s) y continúe comprobe o/os destinatario(s) e continúe controlla i/il destinatari(o) e continua zkontrolovat příjemce a pokračovat vérifier le ou les destinataires et continuer or < oder < odr < or < or < or < or < or < fex yourself eigene Adresse verwenden fex dir selbr fex yourself fex yourself fex yourself fex yourself fex yourself > user config & operation control > Benutzer Bedienungssteuerung > Benutzr Bdienongssteierong > configuración de usuario y control de operación > configuración de usuario e control de operación > configurazion utente & controllo operazioni > nastavení uživatele a řízení provozu > configuration utilisateur et gestion Alternate Java client (for files > 2 GB or sending of more than one file) Alternativer Java Client (für Dateien größer als 2 GB oder zum Senden von mehr als einer Datei) 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) 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) 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 Hace falta cumplimentar este formulario completamente antes de continuar Fai falta cubrir este formulario completamente antes de continuar Devi riempire completamente questo form per continuare Pro pokračování musíte kompletně vyplnit formulář Merci de compléter ce formulaire pour continuer sender quota (used):$quota ($du) MB Absender Quota (benutzt):$quota ($du) MB Absendr Quota (benutzt):$quota ($du) MB cuota de remitente (usada):$quota ($du) MB cota de remitente (usada):$quota ($du) MB quota utente (usata):$quota ($du) MB limit pro odesílání (used):$quota ($du) MB quota expéditeur (utilisé):$quota ($du) MB autodelete: Automatisches Löschen: Automadischs Lösche: autoborrar: autoeliminación: autocancellazione: automatické mazání: suppression automatique keep file max $keep days, then delete it">keep:$keep days Behalte die Datei für max. $keep Tage, dann lösche sie">Bleibt auf Server:$keep Tage Bhalt die Datei fier höchschdens $keep Tage, dann kosch se lösche">Bleibt uffm Server:$keep Dag conserve el fichero un máximo de $keep días, a continuación borrelo">keep:$keep días conserve o ficheiro un máximo de $keep días, a seguir bórreo">gardar:$keep días conserva il file al massimo per $keep giorni, quindi cancellalo">mantieni:$keep giorni uchovat soubor maximálně $keep dnů, pak jej smazat">uchovat:$keep dnů garder les fichiers au maximum $keep jours et les supprimer">keep:$keep jours comment: Kommentar: Kommendar: comentario: comentario: commento: komentář: commentaire: bandwith limit Bandbreitenbeschränkung Bandbroidebschränkong anchura de banda largo de banda limite di banda omezení rychlosti limite de bande passante optional, full speed if empty optional, volle Geschwindigkeit wenn leer optional, volle Lotte wenn leer opcional, velocidad maximal en caso de vacia opcional, velocidade máxima cando baleira opzionale, massima velocita' se vuoto volitelné, je-li prázdné, využije se plná rychlost optionnel, pas de limite si non renseignée optional, will be included in notification e-mail optional, wird in Benachrichtigungs-E-Mail mitgeschickt optional, isch no en dr Benochrichtigongs-Mail mit drbei optional, will be included in notification e-mail optional, will be included in notification e-mail optional, will be included in notification e-mail optional, will be included in notification e-mail optional, will be included in notification e-mail no notification e-mail will be send es wird keine Benachrichtigungs-E-Mail verschickt s\'wird koi Benochrichtigongs-Mail verschickt No se enviará ningún correo de notificación non se enviará notificación de correo nessuna notificazione via e-mail verrà spedita žádný e-mail s upozorněním se neodešle aucun message de notification ne sera envoyé (optional (optional (optional (opcional (opcional (opzionale (volitelné (optionnel If you want to send more than one file, then put them in a zip or tar archive Wenn Sie mehr als eine Datei senden möchten, dann erzeugen Sie ein zip oder tar Archiv 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 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 file: Datei: Datei: fichero: ficheiro: file: soubor: fichier: user config & operation control Benutzer Konfigurations- und Bedienungssteuerung Benutzr Konfigurations- ond Bedienongssteierong configuración de usuario & control de operaciones configuración de usuario e control de operacións configurazione utente & controllo operazioni nastavení uživatele a řízení provozu configuration utilisateur & gestion I have lost my auth-ID! Send it to me by e-mail! Habe meine auth-ID vergessen! Bitte mir diese per E-Mail zuschicken! I hann mei auth-ID vrschlampt! Schick se mir no mol per E-Mail! ¡He perdido mi auth-ID! ¡Envíemelo por correo electrónico! Perdín o meu auth-ID! ¡Envíemo por correo electrónico! Ho perso il mio auth-ID! Spediscimelo via e-mail! Zapomněl jsem své ověřovací ID! Odešli mi jej na e-mail! J'ai perdu mon auth-ID ! Le recevoir par e-mail ! I have lost my auth-ID Habe meine auth-ID vergessen I hann mei auth-ID vrschlampt He perdido mi auth-ID Perdín o meu auth-ID Ho perso il mio auth-ID Zapomněl jsem své ověřovací ID J'ai perdu mon auth-ID you must fill out sender field above Sie müssen oben dazu das \"Absender\"-Feld ausfüllen Du musch drzu do obe des \"Absendr\"-Feld ausfille debe rellenar el campo remitente anterior debe cubrir o campo remitente anterior devi riempire il campo mittente sopra musíte vyplnit políčko odesilatel výše vous devez renseigner le champ expéditeur check ID and continue weiter weider comprobar el ID y continuar comprobar o ID e continuar controlla ID e continua ověřit ID a pokračovat vérifier l'ID et continuer no file specified Keine Datei angegeben Koi Datei ogebbe no se espcificó el fichero non se espcificóu o ficheiro nessun file specificato nebyl uveden soubor aucun fichier spécifié no sender specified Kein Absender angegeben Koin Absendr ogebbe no se especificó el remitente non se especificóu o remitente nessun mittente specificato nebyl uveden odesilatel aucun expéditeur spécifié no recipient specified Kein Empfänger angegeben Koin Empfängr ogebbe no se especificó el destinatario non se especificó o destinatario nessun destinatario specificato nebyl uveden příjemce aucun destinataire spécifié wrong auth-ID specified Falsche auth-ID angegeben Falsch auth-ID ogebbe auth-ID especificado erróneo o auth-ID especificado é incorrecto auth-ID indicato sbagliato bylo uvedeno chybné ověřovací ID auth-ID erroné address book updated Adressbuch aktualisiert Adressbüchle isch uffm neueschte Schdand libro de direcciones actualizado axenda de enderezos actualizada rubrica aggiornata adresář byl aktualizován carnet d'adresses mis à jour cannot rename $filed/upload to Konnte $filed/upload nicht umbenennen in I hab $filed/upload net umbenenne könne in no se puede renombrar $filed/upload a non se pode renomear $filed/upload como non posso rinominare $filed/upload in nepodařilo se přejmenovat $filed/upload na ne peut pas renommer $filed/upload en No file data received Keine Daten erhalten Koine Date kriegt No se ha recibido ningún fichero de datos Non se recibiu ningún ficheiro de datos Nessun file di dati ricevuto Data souboru nebyla přijata aucune donnée reçue File name correct? Stimmt der Dateiname? Isch der Dateinome richdig? ¿Nombre de fichero correcto? Nome de ficheiro correcto? Nome file corretto? Je název souboru správný? Est-ce que le nom du fichier est correct ? File too big (browser-limit: 2 GB!)? Datei zu groß (Browser-Limit: 2 GB!)? Die Datei isch zu groß (Browser-Limit: 2 GB!)? ¿Fichero demasiado grande (límite del navegador: ¡2GB!)? Ficheiro demasiado grande (límite do navegador: 2GB!)? File troppo grande (limite-browser: 2 GB!)? Není soubor příliš velký (limit prohlížeče: 2 GB!)? Fichier trop volumineux (limite du navigateur: 2GB!)? is not allowed at beginning of ist nicht erlaubt am Anfang von des derfsch net mache am Ofang von no se permite al principio de non se permite ao principio de non e' consentito all'inizio di není povoleno na začátku n'est pas autorisé au début de is not allowed in ist nicht erlaubt in des derfsch net mache in no se permite en non se permite en non e' consentito in není povoleno v n'est pas autorisé dans is not allowed ist nicht erlaubt des derfsch net mache no se permite non se permite non e' consentito není povoleno n'est pas autorisé is not allowed at end of ist nicht erlaubt am Ende von des derfsch net mache am End von no se permite al final de non se permite ao final de non e' consentito alla fine di není povoleno na konci n'est pas autorisé à la fin de invalid Content-Length Ungültiger Content-Length Ungültiger Content-Length Content-Length inválido O Content-Length é incorrecto Content-Length non valido Content-Length není platné Content-Length invalide not enough free space for this upload Nicht genug freier Speicher für diesen Upload 'S isch net gnug Schbeicher frei om des nuffzulade no hay espacio libre suficiente para la subida non hai espazo libre suficiente para a subida non c'e' abbastanza spazio per questo caricamento pro nahrání není dost místa pas assez d'espace libre pour cet upload missing sender e-mail address E-Mail Adresse vom Sender fehlt koi E-Mail Adress vom Sender falta la dirección del remitente falt o enderezo do remitente manca l'indirizzo e-mail del mittente chybí e-mailová adresa odesilatele e-mail de l'expéditeur manquant is not a valid e-mail address ist keine gültige E-Mail Adresse des isch koi giltige E-Mail Adress no es una dirección de correo electrónico válido non é un enderezo de correo electrónico correcto non e' un indirizzo e-mail di posta valido není platná e-mailová adresa n'est pas une adresse e-mail valide no file data received - does your file exist or is it >2GB Keinen Datensatz erhalten - existiert die Datei wirklich oder ist es größer als 2 GB I hab koine Date kriegt - Gibt's dui Datei ieberhaupt oddr isch se größer als 2 GB no se ha recibido ningún fichero - existe su fichero o es >2GB non se recibiu ningún ficheiro - existe o seu ficheiro ou é >2GB non e' stato ricevuto nessun file - il tuo file esiste o e' >2GB data souboru nebyla přijata - zkontrolujte, zda soubor existuje nebo není větší než 2 GB pas de donnée reçue - est-ce que votre fichier existe or est-il >2GB file size unknown Dateigröße unbekannt Koi Ohnung, wie groß dui Datei isch tamaño del fichero desconocido tamaño do ficheiro descoñecido dimensione file sconosciuta neznámá velikost souboru taille du fichier inconnue file size Dateigröße So fett isch des Doil tamaño del fichero tamaño do ficheiro dimensione file velikost souboru taille du fichier no filename?! Kein Dateiname?! Koin Dateinome?! ¡¿no hay nombre de fichero?! non hai nome de ficheiro?! manca il nome del file ?! zadali jste název souboru?! pas de nom de fichier ?! transfer is already in progress ein Transfer läuft gerade 'S isch grad en Transfer am laufe la transferencia ya está en curso a transferencia xa está en marcha il trasferimento e' gia' in corso přenos již probíhá le transfert est déjà en cours. a download is currently in progress ein Download läuft gerade 'S wird grad was ronderglade una descarga está ahora en curso unha descarga está agora en marcha un download e' al momento in corso probíhá stahování un téléchargement est en cours no file data for Keine Datei-Daten für Koine Datei-Date fier no ha fichero para non hai ficheiro para nessun file per žádná data souboru pro pas de données pour File "$filename" copy-forwarded to $to and notified Datei "$filename" wurde kopiert und an $to weitergeleitet. $to wurde benachrichtigt Datei "$filename" isch kopiert ond an $to weitergleided worde. $to isch benochrichdigt Fichero "$filename" copiada reenviada a $to y notificado Ficheiro "$filename" copiada reenviada a $to e notificada File "$filename" copia inoltrata a $to e notificata Soubor "$filename" kopie byla předána na $to a oznamovací e-mail byl odeslán Le fichier "$filename" a été retransmis à $to et un message a été envoyé forward a copy of "$filename" to: Eine Kopie von "$filename" weiterleiten an: A Kopie von "$filename" weiterschicke an: reenviada una copia de "$filename" a: reenviada unha copia de "$filename" a: inoltra una copia di "$filename" a: předat kopii souboru "$filename" na: Transmettre une copie de "$filename" à: F*EX user registration ERROR F*EX-Benutzer Registrierungsfehler F*EX-Benutzr Regischdrierongsfehler ERROR en el registro del usuario F*EX ERRO no rexistro do usuario F*EX ERRORE di registrazione utente F*EX Chyba při registraci F*EX uživatele ERREUR lors de l'enregistrement de l'utilisateur F*EX F*EX user registration F*EX-Benutzer Registrierung F*EX-Benutzr Regischdrierong registro del usuario de F*EX rexistro do usuario de F*EX registrazione utente F*EX registrace F*EX uživatele Enregistrement d'un utilisateur F*EX illegal registration key Illegaler Registrierungs-Schlüssel Der Regischdrierongsschlissel gildet net clave de registro ilegal chave de rexistro ilegal chiave di registrazione illegale neplatný registrační klíč Clé d'enregistrement illégale no registration key Kein Registrierungs-Schlüssel Koin Regischdrierongsschlissel sin clave de registro sen chave de rexistro non c'e' la chiave di registrazione žádný registrační klíč pas de clé d'enregistrement no registration data for key Keine Registrierungs-Daten für Schlüssel Koine Regischdrierongsdate fier den Schlissel no hay datos de registro para la clave non hai datos de rexistro para a chave non ci sono dati di registrazione per la chiave žádná registrační data pro klíč pas de données d'enregistrement pour la clé Your registration was successful. Your new F*EX account is: Ihre Registrierung war erfolgreich. Ihr neuer F*EX-Account ist: Du hoschs gschafft. Dein neies F*EX-Konto isch: Su registro tuvo existo. Su nueva cuenta F*EX es: O rexistro foi correcto. A súa nova conta F*EX é: La tua registrazione e' stata eseguita con successo. Il tuo nuovo utente F*EX e': Registrace proběhla úspěšně. Váš nový F*EX účet je: Votre enregistrement s'est bien déroulé. Votre nouveau compte F*EX est: bookmark this URL nehmen Sie diese URL in ihre Bookmarks auf des musch en deine Bookmarks aufnehma Crear marcador de este URL engadir este enderezo URL aos marcadores inserisci questo URL nei preferiti přidat URL k oblíbeným sauvegarder cette URL or you can use oder Sie verwenden oder du nemsch o puede usar ou pode utilizar o puoi usare nebo můžete ou vous pouvez utiliser Your domain $exd is not allowed for registration Ihre Domain $exd ist nicht zugelassen für Registrierung Dei Domain $exd ghod ned for d'Regischtrierong Your domain $exd is not allowed for registration Your domain $exd is not allowed for registration Your domain $exd is not allowed for registration Your domain $exd is not allowed for registration Your domain $exd is not allowed for registration Registrations from your host ($ra) are not allowed Registrierungen von Ihrem Host ($ra) sind nicht erlaubt Regischdrieronga von Deim Host ($ra) send net geschdaddet Los registros desde su equipo ($ra) no están permitidos Os rexistros desde o seu equipo ($ra) non están permitidos Registrazioni dal tuo host ($ra) non sono permesse Registrace z vašeho počítače ($ra) nejsou povoleny Les enregistrements à partir de votre poste ($ra) ne sont pas autorisés Contact $ENV{SERVER_ADMIN} for details Kontaktieren Sie $ENV{SERVER_ADMIN} für Details Wend De an $ENV{SERVER_ADMIN}, wenn De Näheres wisse willsch Contacte con $ENV{SERVER_ADMIN} para obtner más detalles Contacte con $ENV{SERVER_ADMIN} para obter más detalles Contatta $ENV{SERVER_ADMIN} per i dettagli Pro více informací kontaktujte $ENV{SERVER_ADMIN} Contacter $ENV{SERVER_ADMIN} pour des détails supplémentaires $user is disabled $user ist gesperrt $user isch gschperrt $user is disabled $user is disabled $user is disabled $user is disabled $user is disabled new user: Neuer Benutzer: Neier Benutzr: nuevo usuario: novo usuario: nuovo utente: nový uživatel: nouvel utilisateur: new external user: Neuer externer Benutzer: Neier externer Benutzr: nuevo usuario externo: novo usuario externo: nuovo utente esterno: nový externí uživatel: nouvel utilisateur externe: or

      oder

      odr

      o

      ou

      o

      nebo

      ou

      must be a valid e-mail address! Muß eine gültige E-Mail Adresse sein! des muss a giltige E-Mail-Adress sei! ¡debe ser una dirección de correo electrónico! debe ser un enderezo de correo electrónico! deve essere un indirizzo e-mail valido! musí být platná e-mailová adresa! doit être une adresse e-mail valide ! You are already registered Sie sind bereits registriert Du bisch doch scho längscht regischdriert ya está registrado xa está rexistrado sei gia' registrato již jste zaregistrovaní Vous êtes déjà enregistré new user (may send to internal or external users) neuer Benutzer (darf an interne oder externe Benutzer senden) neur Benutzr (darf an intern odr extern Benutzr senda) nuevo usuario (permitido a enviar a usuarios internos o externos) novo usuario (permitido enviar a usuarios internos ou externos) nuovo utente (potresti spedire ad utenti interni o esterni) nový uživatel (může odesílat interním či externím uživatelům) nouvel utilisateur (peut envoyer à des utilisateurs internes ou externes) new external user (may send only to internal users) neuer externer Benutzer (darf nur an interne Benutzer senden) neur externer Benutzr (darf bloss an interne Benutzr senda) nuevo usuario externo (solamente permitido a enviar a usuarios internos) novo usuario externo (soamente pode enviar a usuarios internos) nuovo utente esterno (potrebbe spedire solo a utenti interni) nový externí uživatel (může odesílat pouze interním uživatelům) nouvel utilisateur externe (peut seulement envoyer à des utilisateurs internes) internal domains are interne Domains sind interne Domains senn dominio internos son dominios internos domini interni sono interní domény jsou les domaines internes sont you must enter your e-mail address and Sie müssen Ihre E-Mail Adresse eingeben Du musch dei E-Mail Adress ogeba hace falta introducir su dirección de correo electrónico debe escribir o seu enderezo de correo electrónico e devi inserire un indirizzo e-mail e musíte zadat svou e-mailovou adresu a vous devez donner votre adresse e-mail et your e-mail address Ihre E-Mail Adresse dei E-Mail Adresss sú dirección de correo electrónico o séu enderezo de correo electrónico il tuo indirizzo e-mail vaše e-mailová adresa votre adresse e-mail Subject: F*EX user registration Subject: F*EX-Benutzer Registrierung Subject: F*EX-Benutzrregischdrierong Sujeto: Registro del usuario de F*EX Suxeito: Rexistro do usuario de F*EX Oggetto: registrazione utente F*EX Předmět: Registrace F*EX uživatele Sujet: Enregistrement F*EX $user has been auto-registrated with $user wurde auto-registriert mit $user isch auto-regischdriert worde mit $user ha sido autoregistrado con $user foi autorexistrado con $user e' stato autoregistrato con $user byl automaticky zaregistrován s l'utilisateur $user a été automatiquement enregistré avec Subject: F*EX user registration request Subject: F*EX-Benutzer Registrierungs-Anfrage Subject: F*EX-Benutzrregischdrierongsofrog Sujeto: Petición de registro de usuario F*EX Suxeito: Petición de rexistro de usuario F*EX Oggetto: richiesta registrazione utente F*EX Předmět: Požadavek na zaregistrování F*EX uživatele Sujet: Demande d'enregistrement d'utilisateur F*EX To activate your new F*EX account go to this URL: Um Ihren neuen F*EX-Account zu aktivieren oeffnen Sie diese URL: Om Die neis F*EX-Konto zu aktiviere, gang uff die URL: Para activar su nueva cuenta en F*EX vaya a esta URL: Para activar a súa nova conta en F*EX vaia a este URL: Per attivare il tuo nuovo utente F*EX vai a questo URL: Pro aktivaci svého nového F*EX účtu přejděte na tuto URL: Pour activer votre nouveau compte F*EX, rendez vous à cette URL: The conditions of usage are: Die Benutzungsbedingungen sind: Die Mitmachregla senn: The conditions of usage are: The conditions of usage are: The conditions of usage are: The conditions of usage are: The conditions of usage are: confirmation e-mail has been sent to $user Bestätigungs-E-Mail wurde gesendet an Benutzer $user Beschdädigongs-E-Mail isch gschickt worde an Benutzr $user Un correo electrónico de confirmación se le ha enviado a $user Envióuselle un correo electrónico de confirmación a $user e-mail di conferma e' stata spedita a $user potvrzovací e-mail byl odeslán uživateli $user Un message de confirmation a été envoyé à $user This is an automatically generated e-mail Dies ist eine maschinell generierte E-Mail Des isch a Automata-E-Mail Este e-mail ha sido generado automaticamente Este correo foi xerado automaticamente Questa e' una e-mail generata automaticamente Toto je automaticky vytvořený e-mail Ceci est un message généré automatiquement illegal domain for username illegale Domain fuuml;r Benutzernamen illegale Domain fier de Benutzrnome dominio ilegal para el nombre de usuario o dominio deste nome de usuario é irregular dominio illegale per l'utente neplatná doména pro uživatelské jméno domaine invalide pour l'utilisateur F*EX redirect ERROR F*EX Umadressierungs-FEHLER F*EX Bei der Omadressierong isch was schiefgloffe ERROR de redirección de F*EX Produciuse un ERRO de redirección de F*EX ERRORE di inoltro F*EX CHYBA při přesměrování F*EX ERREUR de redirection F*EX wrong user or auth-ID Falscher Benutzer oder falsche auth-ID Benutzr oddr auth-ID send falsch usuario o auth-ID erróneo o usuario ou o auth-ID son incorrectos utente o auth-ID sbagliato chybný uživatel nebo ověřovací ID utilisateur ou auth-ID invalide has no no files in spool from you hat keine Dateien in spool von Ihnen hat von Dir koine Dateia em spool no hay ficheros en la cola que haya enviado usted non hai ficheiros na cola da súa parte non ci sono file nello spool per te nemá od vás ve frontě žádné soubory n'a pas de fichiers venant de vous F*EX redirect F*EX Umadressierung F*EX Omadressierong redirección F*EX redirección F*EX inoltro F*EX Přesměrování F*EX Redirection F*EX old (wrong) recipient: Alter (falscher) Empfänger: Alder (falscher) Empfängr: viejo (erróneo) destinatario: antigo (incorrecto) destinatario: vecchio (sbagliato) destinatario: původní (chybný) příjemce: ancien (invalide) destinataire: new recipient: Neuer Empfänger: Neier Empfängr: nuevo destinatario: novo destinatario: nuovo destinatario: nový příjemce: nouveau destinataire: filename: Dateiname: Nome von der Datei: nombre de fichero: nome de fichero: nome file: název souboru: nom de fichier: no upload data found for $file for $oto Keine bereitgestellen Daten gefunden für $file für $oto Koine nuffgladene Date gefonde fierr $file fier $oto no hay datos subidos para $file para $oto non se cargaron datos de $file para $oto nessun file di dati da caricare per $file per $oto u $oto nebyla pro soubor $file nalezena žádná nahraná data pas de données trouvées pour le fichier $file pour $oto notification of file upload \"$filename\" sent to $nto Benachrichtigung vom Datei-Upload \"$filename\" gesendet an $nto Benochrichdigong iber die nuffgladene Datei \"$filename\" gschickt an $nto notificación de las subida del fichero \"$filename\" enviado a $nto enviada a notificación da carga do ficheiro \"$filename\" enviado a $nto notifica del file caricato \"$filename\" spedita a $nto oznámení o nahrání souboru \"$filename\" odesláno na $nto un message d'information concernant le fichier uploadé \"$filename\" a été envoyé à $nto redirect $nto/$from/$fkey failed Umadressierung $nto/$from/$fkey fehlgeschlagen Bei dr omadressierung $nto/$from/$fkey isch was schiefgloffe redirección a $nto/$from/$fkey falló fallou a redirección a $nto/$from/$fkey inoltro $nto/$from/$fkey fallito přesměrování $nto/$from/$fkey selhalo la redirection vers $nto/$from/$fkey a échouée Please avoid download with Internet Explorer, Falls Sie zum Download Internet Explorer benutzen, koennte es Falls Du zom Ronderlada Internet Explorer nemmsch, waer's meglich, dass Por favor, evite usar Internet Explorer para las descargas, Por favor, evite usar Internet Explorer para as descargas, Per favore evita di fare il download con Internet Explorer Nestahujte prosím pomocí prohlížeče Internet Explorer, Merci d'éviter d'utiliser Internet Explorer, because it has too many bugs unter Umstaenden zu Problemen kommen Du a Problem hosch porque tiene demasiados errores porque ten demasiados defectos 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 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!) Tras la descarga, Tras a descarga, Dopo il download (o dopo essere stato visto con un browser WEB!) Po stažení (či zobrazení v prohlížeči!), Après le téléchargement (ou visualisation avec un navigateur web) the file will be deleted! wird die Datei geloescht! wird dui Datei gloescht! ¡el fichero se borrará! o ficheiro borrarase! il file sara' cancellato bude soubor smazán! le fichier a été effacé ! When you download the file it will be deleted Wenn Sie die Datei herunterladen dann wird diese eine kurze Zeit Wenn Du die Datei ronderlaedsch, wird se bald drnoch Cuando descargue el fichero se borrará Cando descargue o fichero, este borrarase; Quando scarichi il file sara' cancellato Jakmile si soubor stáhnete, bude po té Lorsque vous téléchargez un fichier, celui-ci sera effacé soon afterwards! danach geloescht werden! gloescht! en breve! moi axiña! poco dopo! ihned smazán! dans les instants qui suivent ! is a container file ist ein Container isch a Schachtel es un archivo contenedor é un ficheiro contedor e' un archivio je soubor archivu est une archive You can unpack it for example with 7zip Sie koennen es z.B. mit 7zip oeffnen Du kosch's z.B. mit 7zip aufmacha Se puede descompactarlo con 7zip Pódese descomprimir con 7zip Puoi decomprimerlo con 7zip Rozbalit jej můžete pomocí programu 7zip Vous pourrez l'ouvrir avec 7zip par exemple This download link only works for you, you cannot distribute it Dieser Download Link funktioniert nur fuer Sie, Sie koennen ihn nicht weitergeben Sell Ronderlad Link isch fei bloss fir Di, du kosch\'n ned weitergaeba Este hipervínculo funciona solamente para tí, no puedes compartirlo Esta ligazón de descarga só funciona para vostede, non a difunda Questo link di download funziona solo per voi, non è possibile distribuire Odkaz je určen pouze vám, nemůžete jej dále šířit le lien de téléchargement ne fonctionnera que vous pour vous, vous ne pourrez pas le diffuser $receiver = 'you $receiver = 'Sie $receiver = 'Di $receiver = 'usted $receiver = 'vostede $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< has uploaded the file hat die Datei hod dui Datei ha subido el fichero cargou o ficheiro ha caricato il file nahrál soubor a uploadé un fichier for $receiver. Use fuer $receiver bereitgestellt. Verwenden Sie die URL fier $receiver bereitgschdellt. Nemm para $receiver. Use para $receiver. Use per $receiver. Usa pro $receiver. Stáhnout si jej můžete zde 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 para descargar este fichero antes de $days para descargar este fichero antes de $days per scaricare questo file entro $days během $days pour télécharger ce fichier d'ici $days F*EX is not an archive, it is a transfer system for personal files F*EX ist kein Archiv, sondern ein Dateien-Uebertragungssystem F*EX isch koi Archiv sondern a Syschtem zom Dateia iebertraga F*EX no es un archivo, es un sistema personal de transferencia de ficheros F*EX non é un arquivo, é un sistema persoal de transferencia de ficheiros F*EX non e' un sistema di archiviazione, e' un sistema personale di trasferimento di file F*EX není archiv, je to systém pro přenos souborů pro osobní použití F*EX n'est pas un système d'archivage, c'est un système de transfert de fichiers personnels For more information see $index Weitere Informationen finden Sie unter $index Gugsch au do: $index Para más informaciones vir a $index Para máis información, vexa $index Per ulteriori informazioni, vedere $index Pro více informací se podívejte na $index Voir $index pour plus d'informations Ehh... $ndata BYTES?! You are kidding Moment... $ndata BYTES?! Das ist wohl ein Witz Moment amole $ndata BYTES?! Wilsch me verarsche Un momento... ¡¿$ndata BYTES?! Está bromeando Un intreo... BYTES?! Está de broma Ehh... $ndata BYTES?! Stai scherzando Moment... $ndata BYTŮ?! Děláte si legraci Eh... $ndata BYTES?! Vous rigolez Using F*EX for less than Verwendung von F*EX für weniger als Du nemsch F*EX fir wenigr als Usar F*EX por menos de Usar F*EX para menos de Usare F*EX per meno di Používat F*EX pro tak malý soubor Utiliser F*EX pour moins de ever heard of MIME e-mail Schon mal was von MIME E-Mail gehört Hosch scho mol was von MIME E-Mail ghört ha oído hablar del correo electrónico MIME non lle será mellor usar o correo electrónico MIME? mai sentito parlare delle e-mail MIME určitě jste někdy slyšeli o e-mailu Vous avez déja entendu parlé de l'e-mail received and saved empfangen und abgespeichert empfanga ond abgschpeichert recibido y guardado recibido e gardado ricevuto e salvato přijato a uloženo reçu et sauvegardé Download URL for copy & paste Download URL zum Kopieren Nonderlad URL zom Kopiera URL de descarga para copiar y pegar Descargar o URL para copiar e pegar Scarica l'URL per il copia ed incolla URL pro stažení okopírovat a vložit URL de téléchargement pour copier/coller Link is valid for $keep days Dieser Link ist für $keep Tage gültig Sell Link isch fir $keep Dag giltig El enlace es válido durante $keep días A ligazón é válida durante $keep días Il link è valido per $keep giorni Odkaz je platný $keep dny(ů) Le lien restera valide $keep jours old $file for $to overwritten vorhandenes $file für $to überschrieben alts $file fir $to iberschrieba El anterior $file para $to se ha sobreescrito Sobrescribiuse o anterior $file para $to vecchio file $file per $to sovrascritto původní soubor $file pro $to byl nahrazen $file pour $to reécrit. $to notified $to benachrichtigt $to bscheid gsagt $to ha sido notificado $to foi notificado $to notificato $to byl informován $to prévenu send another file eine weitere Datei schicken a weitere Datei schicka enviar otro fichero enviar outro fichero spedire un altro file odeslat další soubor envoyer un autre fichier Upload Status for Upload Status für Nufflad Schtatus fier Estado del proceso de subida para Estado do proceso de carga de Stato del processo di caricamento per Stav nahrávání pro Status d'upload pour file successfully transferred Datei erfolgreich übertragen Datei nufflada hot klappt fichero transferido con &ecaute;xito o ficheiro transferiuse correctamente file trasferito con successo soubor byl úspěšně přenesen fichier transféré avec succès >close< >schließen< >fertig< >cerrar< >cerrar< >chiudi< >zavřít< >fermer< "upload" "upload" "nufflada" "subir" "cargar" "caricamento" "nahrát" "upload" value="logout" value="logout" value="adele" value="salir" value="saír" value="uscita" value="odhlásit" value="déconnexion" Using Microsoft Internet Explorer for download will probably Die Verwendung von Microsoft Internet Explorer für den Download wird wahrscheinlich Des Verwenda vom Microsoft Internet Explorer fier dr Download wird wahrscheinlich Usar Microsoft Internet Explorer para realizar las descargas probablemente Usar Microsoft Internet Explorer para realizar as descargas probablemente Usare Microsoft Internet Explorer per il download probabilmente Používání aplikace Microsoft Internet Explorer pro stahování pravděpodobně Utiliser Microsoft Internet Explorer pour le téléchargement lead to problems, because it is not Internet compatible (RFC 2616) zu Problemen führen, weil er nicht Internet kompatibel (RFC 2616) ist zu Problem fiehra, weil der hald ned Internet kompatibel (RFC 2616) isch le puede dar problemas, porque no es compatible con el estándar de Internet (RFC 2616) traerá problemas porque non é compatíbel co estándar de Internet (RFC 2616) genera problemi in quanto non e' compatibile con Internet (RFC 2616) povede k problémům, protože není Internetově kompatibilní (RFC 2616) entraînera probablement des problèmes, parce qu'il n'est pas compatible avec Internet (RFC 2616) We recommend Wir empfehlen Mir empfehlad Recomendamos Recomendámoslle Si raccomanda Doporučujeme Nous recommandons WARNING: WARNUNG: OBACHT: ADVERTIMIENTO: ATENCIÓN: ATTENZIONE: UPOZORNĚNÍ: ATTENTION: If you really want to continue with Internet Explorer, then Wenn Sie wirklich mit Internet Explorer weitermachen wollen, dann Wenn wirklich mitm Internet Explorer weiterwurschtla wilsch, no Si de verdad quiere continuar con Internet Explorer, Si de todas maneiras quere continuar co Internet Explorer, Se vuoi davvero continuare con Internet Explorer allora, Chcete-li skutečně pokračovat s aplikací Internet Explorer, potom Si vous souhaitez vraiment continuer avec Internet Explorer, alors click here with your right mouse button and select "save as" klicken Sie hier mit der rechten Maustaste und wählen Sie an "speichern unter" klicksch hier mit dr rechta Maustascht ond wählsch "speichern unter" aus pulse aquí con el botón derecho del ratón y seleccione "guardar como" prema aquí co botón dereito do ratón e seleccione "gardar como" 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 Your F*EX account has been inactive for $expire days Ihr F*EX Account ist seit $expire Tagen inaktiv Du hosch dei F*EX Konto seit $expire Tag nemme bnutzt Su cuenta de F*EX ha estado inactivo $expire dias A sa conta F*EX estivo inactiva durante $expire da Il tuo account F*EX stato inattivo per $expire giorni Váš F*EX účet byl neaktivní $expire dnů Votre compte F*EX a été inactif pendant $expire days you must download this file to reactivate it Sie müssen diese Datei herunterladen um es zu reaktivieren Du musch sell Datei ronderlada drmit weiter mitmacha derfsch hace falta descargar este fichero para reactivarla debe descargar este ficheiro para reactivala devi scaricare questo file per riattivarlo pro jeho opětovnou aktivaci si musíte stáhnout tento soubor vous devez télécharger ce fichier pour le réactiver Otherwise your account will be deleted Ansonsten wird Ihr Account geloescht Ansoschda bisch den Account los De lo contrario, su cuenta será eliminada Otherwise your account will be deleted Otherwise your account will be deleted Otherwise your account will be deleted Otherwise your account will be deleted Account created: Account angelegt: Konto oglegt: Account created: Account created: Account created: Account created: Account created: fex-20130805/locale/german/0000755000174700017470000000000012177755050013423 5ustar fexfexfex-20130805/locale/german/lib/0000755000174700017470000000000012177755050014171 5ustar fexfexfex-20130805/locale/german/lib/fup.pl0000644000174700017470000000332312142673550015315 0ustar fexfex# lokale Konfiguration fuer F*EX CGI fup $info_1 = $info_login = <


      F*EX (File EXchange) ist ein Dienst um große (sehr große, riesige, gigantische, ...) Dateien zu senden.

      Der Absender (Sie) lädt eine Datei auf den F*EX Server hoch und der Empfänger bekommt automatisch eine Benachrichtigungs-E-Mail mit der Download-URL.
      Nach dem Download oder nach $keep_default Tagen löscht der Server die Datei.
      F*EX ist kein Archiv!

      Um es zu nutzen, geben Sie Ihre Empfänger E-Mail Adresse(n) in die Felder oben ein.

      Noch immer verwirrt?
      Testen Sie F*EX, indem Sie eine Datei an sich selbst senden (Absender = Empfänger = Ihre E-Mail Adresse).

      Siehe auch Fragen & Antworten.


      $ENV{SERVER_ADMIN}
      EOD $info_2 = <

      Nach dem Abschicken sehen Sie einen Upload Fortschrittsbalken (wenn Sie Javascript aktiviert haben und Popups erlauben).

      Bemerkung: Viele Webbrowser können keine Dateien hochladen, die größer als 2 GB sind!
      Wenn Ihre Datei größer ist, müssen Sie einen speziellen F*EX client nutzen.
      Sie brauchen ihn außerdem, wenn Sie abgebrochene Uploads wiederaufnehmen wollen. Ihr Webbrowser ist dazu nicht in der Lage.

      Wenn Sie mehr als eine Datei verschicken wollen, dann verpacken Sie sie vorher in ein zip oder tar Archiv, z.B. mit 7-Zip.

      Siehe auch FAQ.


      $ENV{SERVER_ADMIN}
      EOD fex-20130805/locale/german/lib/reactivation.txt0000644000174700017470000000006011626030514017403 0ustar fexfexIhr F*EX Account wurde erfolgreich reaktiviert. fex-20130805/locale/german/htdocs/0000755000174700017470000000000012177755050014707 5ustar fexfexfex-20130805/locale/german/htdocs/index.html0000644000174700017470000001344512114162360016676 0ustar fexfex F*EX - File EXchange

      F*EX - Frams' Fast File EXchange

      F*EX (Frams' Fast File EXchange) ist ein Dienst, um große (sehr große, riesige, gigantische, ...) Dateien von User A zu User B zu senden.

      Der Absender lädt die Datei über ein WWW upload Formular auf den F*EX Server hoch und der Empfänger bekommt automatisch eine Benachrichtigungs-E-Mail mit der Download-URL.

      Sie fragen vielleicht:

      Warum brauche ich noch einen Service für Dateitranfer?!
      Ich habe E-Mail, FTP, SSH und sogar sendfile!

      Ich sage:

      Sie brauchen F*EX trotzdem :-)

      Sie möchten zum Beispiel einem Freund das letztes Urlaubsvideo senden (1 GB). Sie haben dazu folgende Möglichkeiten (und Probleme):

      • eine DVD per Briefpost verschicken

        Steht außer Frage - wir leben im Jahr <> nach der Erfindung des Internet! Versand von (Hardware-)Medien ist etwas für Opas.

      • E-Mail benutzen

        Die meisten E-Mail Server haben ein Limit von 10 MB pro E-Mail und ein Speicherkontingent von wenigen 100 MB pro User oder sogar weniger.

      • UUCP

        Warum nicht gleich Keilschrift-Zeichen in Tonplatten eindrücken?

      • SSH

        Sie haben das Passwort Ihres Freundes oder sind gewillt, ihm Ihres zu geben - nur für einen Datei-Transfer?

      • FTP

        • Welchen FTP Server benutzen?
        • Welchen Account benutzen, welches Passwort?
        • Stört es Sie unverschlüsselte Passwörter über das unsichere Internet zu übertragen?
        • Unterstützt Ihr Proxy passives FTP?
        • Im Fall von anonymen FTP:
          • Erlaubt es 1 GB Uploads?
          • Kann man den Upload nach dem Transfer wieder löschen?
          • Wer kann Ihre Datei noch downloaden?
          • Wer noch kann Ihre Datei löschen?
          • Sie müssen Ihrem Freund die Download-URL zukommen lassen und er muss Sie über den erfolgreichen Download informieren, danach müssen Sie die Datei löschen.
            Alles in Allem: eine nervige Sache.

      • HTTP

        • Es gibt keine standardmäßige Upload- und User-Verwaltung (muss erst programmiert werden)
        • Keine Auto-Benachrichtigung
        • Kein automatisches Löschen
        • Sehr wenige HTTP Server können mit Dateien größer 2 GB umgehen

      • sendfile

        • Sie benutzen UNIX und haben sendfile installiert?
        • Ihr Empfänger benutzt UNIX und hat sendfile installiert?
        • Weder Ihr Empfänger noch Sie selbst haben eine Firewall die Port 487 blockiert?

      • Kommerzielle Dienste wie DropLoad, ALLPeers, YouSendIt, etc

        • Welche Beschränkungen haben sie? (meist: < 2 GB)?
        • Was ist mit Sicherheit und Privatsphäre: werden Ihre Dateien sicher und geschützt sein?
        • Basieren sie auf Open Source- oder proprietärer Software?
        • Sind sie mit jedem Browser benutzbar oder braucht man Java, Active-X, Flash oder andere üble Plugins?
        • Werden sie länger als ein paar Monate existieren?
          (DropLoad und ALLPeers haben ihren Betrieb schon eingestellt)

      Wenn Sie auch nur eine der Fragen von oben mit "Nein" beantwortet haben, dann brauchen Sie F*EX.

      Hauptmerkmale von F*EX

      • Datei-Transfer mit praktisch unbegrenzter Dateigröße
      • Empfänger und Absender brauchen lediglich ein E-Mail Programm und einen Web-Browser - es muss keine zusätzliche Software installiert werden
      • RESEND und REGET für Wiederaufnahme bei Link Fehlern beim letzten gesendeten Byte
      • Auto-Benachrichtigung der Empfänger
      • automatisches Löschen nach Download
      • automatisches Löschen nach Ablaufdatum (Standard: 5 Tage)
      • Full-User können Sub-User erstellen, die dann nur an den Full-User senden dürfen
      • Full-User können Gruppen erstellen, eine Analogie zu Mailinglisten, aber für Dateien
      • wartungsfrei: bis auf die Erstellung neuer F*EX Accounts ist keine Interaktion eines Admins erforderlich
      • Für das Senden an mehrere Empfänger wird auf dem Server nur einmal Speicherplatz verbraucht
      • F*EX ist ein HTTP-Web-Dienst und benötigt keine Firewall-Tunnel
      • Unterstützung für Streams
      • für UNIX Benutzer gibt es die Shell-Programme fexsend und fexget, um den lästigen Gebrauch von Webbrowsern zu umgehen
      • Protokoll und Quellcode sind frei verfügbar (Perl Artistic)

      Lassen Sie uns über SEX sprechen

      F*EX hat einen Begleiter: Stream EXchange (SEX).

      Man kann sich SEX als netzwerkweite UNIX Pipes mit einem Relay dazwischen vorstellen. Das kann hilfreich sein, wenn man Daten von User A zu User B leiten will, ohne dass A und B eine direkte Verbindung zueinander aufbauen können, aber beide sich über HTTP zum SEX Server verbinden können. Für eine nahtlose Integration in die UNIX Programm Reihe, gibt es die Shell-Programme sexsend und sexget.

      Die Authentifizierung ist dieselbe wie bei F*EX.

      Noch Fragen?

      Siehe FAQ (Fragen und Antworten)

      Kontakt: fexmaster
      fex-20130805/locale/german/htdocs/FAQ.html0000644000174700017470000002276712031353624016210 0ustar fexfex
      Allgemeine Fragen:
      ==================
      
      F: Warum der Name "F*EX" und nicht einfach "FEX"?
      
      A: Zur Zeit der Veröffentlichung existierte bereits ein (älteres) Programm 
         namens "FEX" auf freshmeat.net.
         
      
      F: Warum nicht einen kommerziellen Dienst benutzen wie
         DropLoad, ALLPeers, YouSendIt, etc?
         
      A: Solche Dienste haben ein Limit von 2 GB oder sogar weniger.
         Es ist unklar wie es bei ihnen mit Sicherheit und Datenschutz aussieht.
         Sie basieren nicht auf Open Source.
         Es gibt keine UNIX (CLI) Clients für sie.
         Sie brauchen Java, Active-X, Flash oder andere bösartige Plugins.
         Es ist unklar wie lange sie noch existieren werden - DropLoad und ALLPeers
         haben bereits aufgehört zu existieren.
      
      
      F: Warum ein Kamel als Logo?
      
      A: Das Logo war inspiriert durch das Perl Kamel, zu Grunde liegt aber ein 
         Plüschkamel von Steiff welches auf unserem Renn-Tandem mitfährt. 
         Das Logo wurde von meiner Stokerin Beate gezeichnet, siehe
         http://fex.rus.uni-stuttgart.de/Vortrag/tosa.html
      
      
      F: Wo kann ich die F*EX Sourcen bekommen?
      
      A: http://fex.rus.uni-stuttgart.de/fex.html
      
      
      F: Was braucht man um F*EX installieren zu können?
      
      A: Ein UNIX Server mit DNS Eintrag und smtp für ausgehende E-Mail.
         Und Sie müssen root auf diesem Server sein.
         
      
      F: Was ist DNS und smtp?
      
      A: Installieren Sie kein F*EX. Es ist jenseits Ihres Horizonts.
      
      
      F: Wer ist der Autor?
      
      A: Ulli Horlacher <framstag@rus.uni-stuttgart.de>
      
      
      F: Unter welcher Lizenz läuft F*EX?
      
      A: Perl Artistic Freie Software, siehe http://fex.rus.uni-stuttgart.de/doc/Licence
      
      
      F: Gibt es eine F*EX Mailing Liste?
      
      A: https://listserv.uni-stuttgart.de/mailman/listinfo/fex
      
      
      F: Wo kann ich einen kommerziellen Support für F*EX bekommen?
      
      A: Nehmen Sie Kontakt auf mit fex@nepustil.net http://www.nepustil.net/
      
      
      F: Ich habe noch weitere Fragen bezüglich dieses Dokuments!
      
      A: Fragen Sie den Autor <framstag@rus.uni-stuttgart.de>
      
      
      Benutzerfragen:
      ===============
      
      Q: Was ist die "auth-ID"?
      
      A: Mit Hilfe der auth-ID werden Sie auf dem Server als ein authorisierter 
         Benutzer identifiziert. Die auth-ID wird zuerst vom Administrator oder 
         durch automatische Registrierung vergeben und kann später durch Sie 
         geändert werden. Bitte beachten Sie dass man hier keine wertvollen
         Passwörter verwenden sollte weil diese unverschlüsselt auf dem 
         Server liegen.
      
      
      F: Kann ich einen HTTP-Proxy verwenden?
      
      A: Ja
      
      
      F: Ich habe eine RIESIGE Datei an eine falsche Adresse versendet. Jetzt 
         bekomme ich eine Fehler-Meldung vom System. Muß ich die RIESIGE Datei
         noch mal hochhladen?
      
      A: Nein, das ist nicht nötig. Sie können die Datei einfach weiterleiten 
         mit Hilfe von http://$HTTP_HOST$/rup
      
      
      F: Ich habe eine RIESIGE Datei versendet doch leider habe ich noch einen 
         Empfänger vergessen. Muß ich die RIESIGE Datei noch mal hochladen?
      
      A: Nein, das ist nicht nötig. Sie können die Datei einfach kopieren und
         weiterleiten mit Hilfe von http://$HTTP_HOST$/foc
      
      
      F: Warum kann ich keine Dateien größer als 2 GB mittels Web-Browser 
         hochladen?
      
      A: Alle Web-Browser die mir bekannt sind haben Fehler in ihrer HTML-FORM
         Implementierung. Dadurch ergibt sich der Limit von 2 GB, manchmal 4 GB.
      
         Sie müssen einen speziellen F*EX Client benutzen um Dateien größer 
         als 2 GB hochzuladen, siehe http://$HTTP_HOST$/tools.html
      
      
      F: Mein Download brach frühzeitig ab. Kann ich ihn wieder aufnehmen?
      
      A: F*EX unterstützt Download-Wiederaufnahme, aber Ihr Client muss es ebenso 
         unterstützen. Firefox zB fehlt diese HTTP Eigenschaft, daher benötigen 
         Sie einen anderen Client wie opera, wget oder fexget.
      
      
      F: Mein Upload brach frühzeitig ab. Kann ich ihn wieder aufnehmen?
      
      A: F*EX unterstützt Upload-Wiederaufnahme, aber Ihr Client muss es ebenso 
         unterstützen. Kein Web-Browser hat diese Unterstützung, Sie 
         benötigen dfür einen speziellen F*EX Client wie
         fexsend, schwuppdiwupp oder F*IX.
         Siehe http://$HTTP_HOST$/tools.html
      
      
      F: Wenn ich die Taste [ESC] in Firefox drücke, dann wird der Upload 
         abgebrochen. Warum?
      
      A: Das ist die eingebaute Funktion von Firefox: ESC unterbricht die 
         laufende Operation. 
         Einfache Lösung des Problems: 
         [ESC] sollte man nicht drücken.
         Komplizierte Lösung: 
         bitten Sie die Firefox-Entwickler, eine Tastatur-Konfiguration hinzuzufügen
      
      
      F: Daten mit F*EX zu versenden ist einfach, wie kann ich aber Daten
         von anderen (von der Aussenwelt) empfangen?
      
      A: Registrieren Sie sie als Ihre Subuser oder legen Sie eine F*EX Gruppe an.
         
      
      F: Es kommt manchmal vor dass ich eine Datei mehrmals herunterladen kann, 
         insbesondere wenn ich die Downloads schnell wiederhole. Ist etwa das 
         automatische Löschen fehlerhaft?
      
      A: Der F*EX-Server wartet 1 Minute lang nach dem ersten erfolgreichen Download.
         In dieser Zeit kann man die Datei nochmal herunterladen. Diese Wartezeit 
         ist notwendig weil manche idiotische "Download Manager" die Datei gleich 
         mehrmals anfordern. Ohne die Wartezeit würden sie dem Benutzer einen
         Fehler melden.
      
      A: Ihr Fexmaster hat die Variable AUTODELETE auf DELAY gesetzt. Das hat
         zur Folge dass das automatische Löschen nur einmal täglich stattfindet.
      
      A: Power-Benutzer (sehen Sie die Software-Quelltexte!) können den Flag
         "nach dem Download nicht löschen" setzen.
      
      
      F: Die Standard Aufbewahrungszeit ist mir zur kurz. Wie kann ich diesen Wert 
         erhöhen?
      
      A: Benutzen Sie fexsend, fragen Sie Ihren Fexmaster oder lesen Sie die 
         Quelltexte :-)
      
      
      F: Ich kann Dateien mit dem Internet Explorer nicht herunterladen, es
         meldet mir "Die Internet-Seite ist nicht verfügbar". Was soll ich tun?
      
      A: Benutzen Sie Firefox oder anderen Internet-kompatiblen Web-Browser, was der 
         Internet Explorer eben nicht ist. Das ist nur einer seiner vielen Bugs.
      
      
      Administrator Fragen:
      =====================
      
      F: Ich kann keinen Web-Server wie fexsrv aufsetzen, mir fehlen dazu die
         Rechte. Gibt es vielleicht eine reine CGI-Version von F*EX die
         unter dem Apache Web-Server läuft?
      
      A: fexsrv ist ein fester Bestandteil von F*EX, dazu gibt es viele Gründe 
         (Leistung, maximale Dateigröße, Session Konzept usw). So kann F*EX nicht 
         als CGI unter Apache laufen, Sie könnten sich aber das hier anschauen:
         
         http://gpl.univ-avignon.fr/filez/
         http://freshmeat.net/projects/eventh/
         http://www.schaarwaechter.de/sp/projekte/dateiaustausch.html
         
         Das sind einfache CGI-Implementierungen von Daten-Übertragungssystemen,
         jedoch begrenzt auf 2 GB.
         
      
      F: F*EX funktioniert überhaupt nicht! Es kommt keine Verbindung zum Server mit 
         meinem Web-Browser zustande!
      
      A: Prüfen Sie Ihr Routing, IP-Filter und die Firewall-Einstellungen.
         Prüfen Sie auch ob Ihr xinetd mit dem TCP-Wrapper verlinkt ist und
         konfigurieren Sie es richtig (hosts.allow).
         F*EX braucht den Port 80/tcp (HTTP) und optional den Port 443/tcp
      
      
      F: F*EX ist mir zu kompliziert! Ich brauche was einfacheres!
      
      A: Probieren Sie http://www.home.unix-ag.org/simon/woof.html
      
      F: Wie kann ich F*EX in das bestehende Benutzer-Management in meinem Netzwerk 
         integrieren?
      
      A: F*EX hat verschiedene Authentifizierungs-Module:
         lokal, RADIUS, LDAP, mailman und POP
         Bezüglich der letzten 4 kontaktieren Sie bitte den Autor.
      
      
      F: Ich möchte dass alle meine lokalen Benutzer automatisch F*EX benutzen 
         können. Wie geht das?
      
      A: Lassen Sie sie sich selbst registrieren.
         Dazu müssen Sie lib/fex.ph editieren (Beispiel):
         
         @local_hosts = qw(127.0.0.1 10.10.100.0-10.10.255.255);
         @local_domains = qw(flupp.org ulm.sub.net);
      
         Natürlich müssen Sie Ihre echten Hosts/Networks eigeben!
      
      
      F: Ich brauche mehr Sicherheit! Wie kann ich HTTPS benutzen?
      
      A: Lesen Sie doc/SSL und schauen Sie auch nach "fop_auth" in doc/concept 
      
      
      F: Die F*EX-Startseite sollte an unsere Firmen-Seiten angepaßt werden. 
         Wie kann ich F*EX entsprechend konfigurieren?
      
      A: Siehe Variable @H1_extra in fex.ph, ausserdem können Sie htdocs/header.html
         hinzufügen.
      
      A: Nehmen Sie fup_template.html, modifizieren Sie die Vorlage nach Ihren 
         Wünschen und nutzen Sie diese als Ihre Startseite.
      
      
      Sonstige Fragen:
      ================
      
      F: F*EX ist großartig! Wie kann ich mich dem Entwicklungs-Team anschließen? 
         Was muß noch gemacht werden?
      
      A: Kontaktieren Sie den Autor wegen:
      
         - ein F*EX plugin für Outlook
         
         - weiteren Übersetzungen in andere Sprachen - Latein wäre toll! :-) 
      
      fex-20130805/locale/german/lang.html0000644000174700017470000000001011605620225015207 0ustar fexfexdeutsch fex-20130805/locale/czech/0000755000174700017470000000000012177755050013246 5ustar fexfexfex-20130805/locale/czech/lib/0000755000174700017470000000000012177755050014014 5ustar fexfexfex-20130805/locale/czech/lib/fup.pl0000644000174700017470000000270411615070605015136 0ustar fexfex# config for F*EX CGI fup $info_1 = $info_login = <

      F*EX (File EXchange) je služba pro odesílání velkých souborů.

      Odesilatel (vy) nahraje soubor na F*EX server a ten příjemci autimaticky odešle e-mail s oznámením a s URL ke stažení.
      Po jeho stažení, nebo po uplynutí $keep_default dnů, server soubor smaže. F*EX není archiv!

      Přečtěte si také Otázky a odpovědi (FAQ).


      $ENV{SERVER_ADMIN}
      EOD $info_2 = <

      Po potrzení uvidíte lištu s průběhem nahrávání (pouze, pokud máte povolen javascript a povolené automatické otevírání oken).

      POZNÁMKA: Většina webových prohlížečů neumožňuje nahrávat soubory větší než 2 GB!
      Pokud je váš soubor větší, použíjte speciálního klienta pro F*EX.
      Potřebuvoat budete také klient pro obnovení nahrávání v případě přerušení. Váš webový prohlížeč toto neumožňuje.

      UPOZORNĚNÍ: Některé HTTP proxy servery, jako je třeba privoxy, spomalují průběh nahrávání!
      V případě, že se s tímto pborlémem setkáte, bude zřejmě třeba zakázat používání proxy pro $ENV{SERVER_NAME}.

      Pro uživatele Firefoxu: Nemačkejte klávesu ESC, protože jinak se stahování přeruší!

      Přečtěte si také FAQ. EOD fex-20130805/locale/czech/lib/reactivation.txt0000644000174700017470000000006311626705134017240 0ustar fexfexVáš F*EX účet byl úspěšně znovu aktivován fex-20130805/locale/czech/htdocs/0000755000174700017470000000000012177755050014532 5ustar fexfexfex-20130805/locale/czech/htdocs/index.html0000644000174700017470000001335012031360371016514 0ustar fexfex F*EX - File EXchange

      F*EX - Frams' Fast File EXchange

      F*EX (Frams' Fast File EXchange) je služba pro odesílání velkých souborů uživatelem A uživateli B.

      Odesilatel pomocí webového formuláře pro nahrání nahraje soubor na F*EX server a ten příjemci automaticky odešle e-mail s oznámením a s URL ke stažení.

      Říkáte si:

      Proč potřebuji další službu pro přenos souborů?!
      Mám e-mail, ftp, ssh a v neposlední řadě i sendfile!

      Já pravím:

      Stále potřebujete F*EX :-)

      Například chcete poslat svému známému video z vaší poslední dovolené (1 GB). Máte následující možnosti (a s tím související problémy):

      • poslat DVD poštou

        Nepřichází v úvahu - žijeme <> let od roku, kdy byl vynalezen Internet! Posílání paměťových médií je pro staříky.

      • použít e-mail

        Většina e-mailových serverů má limit pro přílohu 10 MB a velikost schránky kolem 100 MB a někdy i méně.

      • uucp

        Proč rovnou nezůstat u psaní klínovým písmem na kamenné destičky?

      • ssh

        Vy máte heslo svého známého, nebo se mu chystáte dát to své jen kvůli přenosu souboru?

      • ftp

        • Pomocí jakého ftp serveru?
        • Pomocí jakého účtu, jakého hesla?
        • Vám nevadí posílání nešifrovaného hesla a souborů přes nezabezpečený Internet?
        • Podporuje vaše proxy pasivní režim pro ftp?
        • V případě anonymního ftp:
          • Umožňuje nahrát 1 GB?
          • Umožňuje po nahrání soubor smazat?
          • Kdo další si váš soubor může stáhnout?
          • Kdo další může váš soubor smazat?
          • Svému známému musíte poslat URL, kde si soubor může stáhnout, on vás musí informovat, že si soubor stáhl, vy jej pak musíte smazat.
            Sečteno a podrženo: Otrava.

      • http

        • Žádné výchozí nahrávání a správa uživatelů - musí se naprogramovat
        • Žádné automatické oznamování
        • Žádné automatické mazání
        • Velice málo http serverů umí zpracovat soubory větší než 2 GB

      • sendfile

        • Používáte UNIX a máte nainstalovaný sendfile?
        • Používá příjemce UNIX a má nainstalovaný sendfile?
        • Nemáte vy ani příjemce firewall, který blokuje port 487?

      • komerční služby jako jsou DropLoad, ALLPeers, YouSendIt, etd.

        • Jaký mají limit (většinou méně než 2 GB)?
        • Co bezpečnost a ochrana osobních údajů: Budou vaše soubory skutečně uloženy a v bezpečí?
        • Jsou provozovány na open-source, nebo na uzavřeném proprietálním softwaru?
        • Jsou přístupné se všemi prohlížeči, nebo potřebujete Javu, Active-X, Flash či jiné hnusné zásuvné moduly?
        • Budou existovat více, jak pár měsíců?
          (DropLoad, ALLPeers a drop.io své služby již ukončili)

      Pokud jste byť na jedinou z výše uvedených otázek odpověděli "ne", potom potřebujete F*EX.

      Hlavní funkce F*EX

      • přenos souborů s prakticky neomezenou velikostí
      • příjemci a uživatelé potřebují pouze program pro elektronickou poštu a webový prohlížeč jakéhokoli typu, nemusí instalovat žádný další software
      • ZNOVU ODESLÁNÍ a ZNOVU STAŽENÍ pro pokračování přesně tam, kde došlo k selhání spojení
      • automatické oznamování pro příjemce
      • automatické mazání po stažení
      • automatické mazání po době platnosti (výchozí: 5 dnů)
      • plnohodnotní uživatelé si mohou vytvářet poduživatelé, kteří mohou odesílat pouze jim
      • plnohodnotní uživatelé mohou vytvářet skupiny, obdoba poštovních konferencí s tím rozdílem, že se jedná o soubory
      • bezúdržbovost: ze strany správce nejsou nutné žádné zásahy s vyjímkou vytváření nových F*EX účtů
      • odesílání více příjemcům spotřebuje na serveru pouze místo pro jednoho příjemce
      • F*EX je webová služba pro protokol HTTP a nepotřebuje žádné tunely ve firewallu
      • podporuje také vysílání
      • pro skalní UNIXové uživatele jsou k dispozici programy pro příkazovou řádku fexsend a fexget pro vyhnutí se použití otravných webových prohlížečů
      • protokol i zdrojový kód jsou volně dostupné (Perl Artistic)

      Promluvme si o SEXu

      F*EX má společníka: Stream EXchange (SEX).

      SEX si můžete představit jako bránu mezi UNIXovými síťovými rourami. Ta může být užitečná k odesílání dat uživatelem A uživateli B, kde A a B mezi sebou nemohou navázat přímé spojení, ale oba dva se mohou připojit pomocí HTTP k SEX serveru. Pro snadné začlenění do řady UNIXových nástrojů slouží nástroje pro příkazovou řádku sexsend a sexget.

      Ověřování je stejné jako u F*EX.

      Máte otázky?

      Přečtěte si FAQ

      kontaktujte: fexmaster
      fex-20130805/locale/czech/htdocs/FAQ.html0000644000174700017470000002347512031354114016023 0ustar fexfex This FAQ has 3 parts:

      
      
      Meta questions:
      ===============
      
      Q: Why name "F*EX" and not shortly "FEX"?
      
      A: At publication time there was already an (older) program named "FEX" on
         freshmeat.net. 
      
      
      Q: Why not use one of the commercial services like
         DropLoad, ALLPeers, YouSendIt, etc?
      
      A: They have a limit of 2 GB or even less.
         Their security and privacy status is unknown.
         They are not open source based.
         There are no UNIX (CLI) clients for them.
         They need java, active-X, flash or other evil plugins.
         It is unknown how long they will exist - DropLoad and ALLPeers already
         have terminated their business.
       
      
      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.rus.uni-stuttgart.de/Vortrag/tosa.html
      
      
      Q: Where can I get the F*EX sources?
      
      A: http://fex.rus.uni-stuttgart.de/fex.html
      
      
      Q: What do I need to install F*EX?
      
      A: A UNIX host with a DNS entry and smtp for outgoing e-mail.
         And you must be root on this host.
      
      
      Q: What is DNS and smtp?
      
      A: Do not install F*EX. It is beyond your horizon.
      
      
      Q: Who is the author?
      
      A: Ulli Horlacher <framstag@rus.uni-stuttgart.de>
      
      
      Q: Which licence does F*EX have?
      
      A: Perl Artistic free software, see http://fex.rus.uni-stuttgart.de/doc/Licence
      
      
      Q: Is there a F*EX mailing list?
      
      A: https://listserv.uni-stuttgart.de/mailman/listinfo/fex
      
      
      Q: Where can I get commercial support for F*EX?   
      
      A: Contact fex@nepustil.net http://www.nepustil.net/
      
      
      Q: I have more/other questions than in this document!
      
      A: Ask the author <framstag@rus.uni-stuttgart.de>
      
      
      
      User questions:
      ===============
      
      Q: What is the "auth-ID"?
      
      A: The auth-ID is an internal identification which authentificates the user.
         It will be first generated by the admin or the automatic registration
         process and can later be modified by you, the user. Think of some kind
         of a low security password.
      
      
      Q: Can I use a HTTP proxy?
      
      A: Yes.
      
      
      Q: I have uploaded a HUGE file but misspelled my recipient's address. Now I
         have got an error bounce e-mail. Must I re-upload the HUGE file?
      
      A: No, it is not necessary. You can redirect the file with 
         http://$HTTP_HOST$/rup
      
      
      Q: I have uploaded a HUGE file but forgot another recipient. 
         Must I re-upload the HUGE file?
      
      A: No, it is not necessary. You can forward-copy the file with 
         http://$HTTP_HOST$/foc
      
      
      Q: I cannot upload files > 2 GB with my web browser!?
      
      A: All web browsers I am aware of have bugs in their HTML-FORM
         implementation. The limit mostly is 2 GB, sometimes 4 GB. 
         
         You have to use a special F*EX client to upload files > 2 GB, see
         http://$HTTP_HOST$/tools.html
      
      
      Q: My download was aborted before it was finished. Can I resume the download?
      
      A: F*EX supports resuming at download, but your client also has to support
         this feature. Firefox eg is missing this HTTP feature, you need an other
         client like opera, wget or fexget.
      
      
      Q: My upload was aborted before it was finished. Can I resume the upload?
      
      A: F*EX supports resuming at upload, but your client also has to support it.
         No web browser has this feature, you need a special F*EX client like
         fexsend, schwuppdiwupp or F*IX. 
         See http://$HTTP_HOST$/tools.html
      
      
      Q: My webbrowser cannot start the java client F*IX, it says:
         "found no java runtime environment, cannot start F*IX upload applet"
      
      A: A java plugin for your webbrowser is missing. On Debian and Ubuntu you
         can install it with: "sudo aptitude install sun-java6-plugin"
      
      
      Q: When I hit [ESC] in firefox the upload is canceled. Why?
      
      A: This is a built-in feature of firefox: ESC terminates the current operation.
         Simple solution: do not hit ESC in Firefox. 
         Complex solution: ask the Firefox developers to add keyboard configuration.
      
      
      Q: Sending as a F*EX user is easy, but how to receive files from others,
         outside?
      
      A: Register them as your subusers or create a F*EX group 
         with http://$HTTP_HOST$/fuc
         
      
      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 requests the file
         several times at once. Otherwise they would report an error to the user.
      
      A: Your fexmaster has set AUTODELETE=DELAY as default, which means that
         the autodelete cleanup process is called once a day.
      
      A: Power users (use the source, Luke!) can set a "do not delete after
         download" flag.
      
      
      Q: The default keep time is too short for me, I need more. How can I set it?
      
      A: Use fexsend, ask your fexmaster or read the source code :-)
      
      
      Q: I cannot download files with Internet Explorer, it tells me "Cannot
         open Internet site". What shall I do?
         
      A: Use Firefox or any other Internet-compatible web browser, that Internet
         Explorer is not. This is one of the many bugs of Internet Explorer.
      
      
      
      
      Admin questions:
      ================
      
      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/
         http://freshmeat.net/projects/eventh/
         http://www.schaarwaechter.de/sp/projekte/dateiaustausch.html (German only!)
         which implement a file exchange as pure CGIs, but with a 2 GB file size limit.
      
      
      Q: F*EX is not working at all! I cannot connect to it with my web browser!
      
      A: Check your routing, ipfilters and firewall setup. 
         Also check whether your xinetd is linked with tcp-wrapper and configure
         it correctly (hosts.allow).
         F*EX needs port 80/tcp (HTTP) and optional port 443/tcp (HTTPS).
      
      
      Q: F*EX is too complicated! I need something more simplified.
      
      A: Try http://www.home.unix-ag.org/simon/woof.html
      
      
      Q: How can I integrate F*EX in the existing user management at my site?
      
      A: F*EX has several authentification modules: 
         local, RADIUS, LDAP, mailman and POP
         For the last 4 please contact the author framstag@rus.uni-stuttgart.de
         
      
      Q: I want that all of my local users can use F*EX automaticly. How?
      
      A: Let them register theirselves with http://yourfexserver/fur
         You have to edit lib/fex.ph and set (example):
         @local_hosts = qw(127.0.0.1 10.10.100.0-10.10.255.255);
         @local_domains = qw(flupp.org ulm.sub.net);
         (Of course you have to add your real local hosts/networks!)
      
      
      Q: I need more security! How can I enable HTTPS?
      
      A: Read doc/SSL and also look for "fop_auth" in doc/concept 
      
      
      Q: I need a corporate identity look. How can I configure F*EX in this way?
      
      A: See variable @H1_extra in fex.ph and you can add HTML code to 
         htdocs/header.html
      
      A: See htdocs/fup_template.html, modify it to your needs and use it as your
         start-page.
      
      
      Q: F*EX is too complicated for my tie users. I need a simplified upload form.
      
      A: See htdocs/fup_template.html
      
      
      Q: I want the Bcc mails to fex (admin user) to be sent to another address.
      
      A: Use procmail or write OTHERADDRESS to /home/fex/.forward
      
      
      Q: Can I get a localized version in my native languange?
      
      A: With your help, yes. Please contact the author framstag@rus.uni-stuttgart.de
      
      
      Misc questions:
      ===============
      
      Q: F*EX is great! Can I join the developing team? What needs to be done?
      
      A: Contact the author framstag@rus.uni-stuttgart.de
         Requested features are:
         
           - a F*EX plugin for thunderbird or outlook
           - more (other) languange support
      
      fex-20130805/locale/czech/lang.html0000644000174700017470000000002411605621330015035 0ustar fexfexčeština fex-20130805/install0000755000174700017470000002345612172324523012311 0ustar fexfex#!/usr/bin/perl -w use 5.006; use Getopt::Std; use Socket; use IO::Socket::INET; use Digest::MD5 qw(md5_hex); $ENV{PATH} .= ':/sbin:/usr/sbin'; $usage = "usage: $0 [-p port] [IP-address]\n"; $xinetd = '/etc/xinetd.d/fex'; umask 022; if ($<) { die "you must be root to install F*EX\n"; } goto INSTALL if $0 =~ /upgrade$/; $fex = 'fex.rus.uni-stuttgart.de'; if (system("host $fex >/dev/null") != 0) { die "host $fex is not resolvable - check /etc/resolv.conf\n"; } if (`uname` =~ /^SunOS/) { die "Solaris is currently not supported. " ."Please contact framstag\@rus.uni-stuttgart.de for details.\n"; } $opt_p = 80; if (open $xinetd,$xinetd) { while (<$xinetd>) { if (/^\s*port\s*=\s*(\d+)/) { $opt_p = $fexport = $1; } if (/^\s*bind\s*=\s*([\d.]+)/) { $fexip = $ip = $1; } } close $xinetd; } getopts('p:') or die $usage; $arg = shift; if ($arg and -f "locale/$arg/lib/fup.pl") { exec 'locale/translate',$arg; } else { $ip = $arg || $fexip || 0; } # if (not $ip and open P,"ifconfig 2>/dev/null |") { if (not $ip and open P,'host $(hostname)|') { $guessed_ip = 0; while (

      ) { if (/(\d+\.\d+\.\d+\.\d+)/) { $guessed_ip = $1; last; } } close P; print "Your IP [$guessed_ip] : "; chomp($ip = ); $ip = $guessed_ip unless $ip; } $ip =~ /^\d+\.\d+\.\d+\.\d+$/ or die $usage; ($hostname) = gethostbyaddr(gethostbyname($ip),AF_INET); die "cannot find hostname for IP $ip\n" unless $hostname; print "checking prerequisites\n"; if (`which xinetd` =~ m{^/}) { print "found xinetd\n"; } else { print "xinetd executable NOT found\n"; $premiss++; } if ( -x '/usr/lib/sendmail') { print "found /usr/lib/sendmail\n"; } elsif ( -x '/usr/sbin/sendmail') { print "found /usr/sbin/sendmail\n"; } else { print "sendmail NOT found\n"; $premiss++; } if ($premiss) { print "installation aborted, nothing has been touched yet\n"; print "what now? ==> see doc/installation\n"; exit 1; } unless ($fexport) { $SH = IO::Socket::INET->new( PeerAddr => $ip, PeerPort => $opt_p, Proto => 'tcp', ); if ($SH) { print "There is already a tcp-service running on $ip:$opt_p !\n"; print "Select another port for F*EX by running $0 -p OTHERPORT $ip\n"; print "or an alternative IP-address by running $0 OTHERADDRESS\n"; exit 5; } } print "prerequisites checked, ok\n"; unless (getpwnam('fex')) { print "creating user fex\n"; system 'useradd -s /bin/bash -c "File EXchange" -m fex'; } INSTALL: @FEX = getpwnam('fex') or die "no cannot create user fex\n"; $FEXHOME = $FEX[7]; die "no HOME directory for user fex\n" unless -d $FEXHOME; print "Installing:\n"; @save = ( "lib/fex.ph", "lib/fup.pl", "lib/reactivation.txt", "etc/mime.types", "htdocs/FAQ.html", "htdocs/index.html", "htdocs/robots.txt", ); foreach $s (@save) { $f = "$FEXHOME/$s"; if (-e $f) { $fs = $f.'_save'; rename $f,$fs and print "$f --> $fs\n"; } } cpav(qw(bin cgi-bin lib etc htdocs doc),$FEXHOME); unlink "$FEXHOME/doc/License"; unlink "$FEXHOME/htdocs/License"; $hl = "$FEXHOME/htdocs/locale"; unless (-d $hl) { mkdir $hl or die "$0: cannot mkdir $hl - $!\n" } if (-d "$FEXHOME/spool") { &convert_spool; } else { chmod 0700,$FEXHOME; mkdir "$FEXHOME/spool",0700 or die "cannot mkdir $FEXHOME/spool - $!\n"; mkdir "$FEXHOME/spool/.error",0700; } foreach $s (@save) { $f = "$FEXHOME/$s"; $fs = $f.'_save'; $fn = $f.'_new'; if (-e $fs) { system "rm -rf $fn"; rename $f,$fn and print "$f --> $fn\n"; rename $fs,$f and print "$fs --> $f\n"; } } system(qw(perl -p -i -e), 's:href="/?FAQ.html":href="/FAQ/FAQ.html":', "$FEXHOME/lib/fup.pl" ); $fph = "$FEXHOME/lib/fex.ph"; open $fph,$fph or die "cannot read $fph - $!\n"; while (<$fph>) { eval $_ if /^\s*\$admin_pw\s*=/; s/'HOSTNAME'/'$hostname'/; $conf .= $_; } close $fph; if (-x "$FEXHOME/cgi-bin/fac" and not $admin_pw) { while (not $admin_pw) { print "\nF*EX admin password (for web interface): "; $admin_pw = ; $admin_pw =~ s/\s//g; } $conf =~ s/\$admin_pw\s*=\s*''/\$admin_pw = '$admin_pw'/ or $conf =~ s/^/\$admin_pw = '$admin_pw';\n/; } open $fph,">$fph" or die "cannot write $fph - $!\n"; print {$fph} $conf; close $fph; require $fph or die "$0: error in $fph\n"; rename "locale/deutsch","locale/german" if -d "locale/deutsch"; rename "locale/espanol","locale/spanish" if -d "locale/espanol"; if (@locales = glob "locale/*/lib/fup.pl") { foreach (@locales) { m{locale/(.+?)/} and $locale = $1; if (-f "$FEXHOME/$_") { system 'locale/translate',$locale; $hl = "$FEXHOME/htdocs/locale/$locale"; symlink "$FEXHOME/locale/$locale/htdocs",$hl unless -l $hl; } else { push @nlocales,"./install $1\n"; } } if (@nlocales) { if (glob "$FEXHOME/locale/*/lib/fup.pl") { print "\nTo install another localized version, type:\n"; } else { print "\nTo install a localized version, type:\n"; } print @nlocales; } } unless (-f $xinetd) { my $xc = '/etc/xinetd.conf'; if (open $xc,$xc) { while (<$xc>) { if (/^\s*only_from/) { print "WARNING: found \"only_from\" in $xc : fexsrv is restricted!\n"; } } close $xc; } if (-d '/etc/xinetd.d') { unless (-f $xinetd) { open $xinetd,">$xinetd" or die "cannot write $xinetd - $!\n"; open F,'etc/xinetd_fex' or die "cannot read etc/xinetd_fex - $!\n"; while () { s/FEXHOME/$FEXHOME/; s/PORT/$opt_p/; s/ADDRESS/$ip/; print {$xinetd} $_; } close F; close $xinetd; system qw(/etc/init.d/xinetd restart); } } else { print "WARNING: No /etc/xinetd.d found.\n"; print "WARNING: You have to install etc/xinetd_fex manually.\n"; } $crontab = `crontab -u fex -l 2>/dev/null`; if ($crontab !~ /fex_cleanup/) { open $crontab,">fex.cron" or die "cannot create fex.cron - $!\n"; print {$crontab} $crontab,"\n"; print {$crontab} " 3 3 * * * exec $FEXHOME/bin/fex_cleanup\n"; close $crontab; system qw(crontab -u fex fex.cron); } system "chown -R fex:root $FEXHOME $FEXHOME/spool/"; system "chmod -R go-r $FEXHOME/lib $FEXHOME/cgi-bin $FEXHOME/spool/"; print "\nUse $FEXHOME/bin/fac to configure your F*EX server.\n"; } else { system "chmod -R go-r $FEXHOME/lib $FEXHOME/cgi-bin"; } $fph = "$FEXHOME/lib/fex.ph"; require $fph; if (@local_rdomains and not @local_rhosts) { print "WARNING:\n"; print "In $fph you have @local_rdomains but not @local_rhosts!\n"; print "Selfregistrating of external users will not work!\n"; print "See ${fph}_new/\n"; } exit; sub convert_spool { my ($f,$d,$to,$from,$link); our ($spooldir,$skeydir,$gkeydir); $ENV{FEXLIB} = "$FEXHOME/lib"; require "lib/fex.pp" or die "$0: cannot load lib/fex.pp - $!\n"; # User --> user@maildomain if ($mdomain) { foreach $f (glob "$spooldir/.dkeys/*") { if ($link = readlink $f) { (undef,$to,$from,$file) = split('/',$link); if ($file) { $to .= '@'.$mdomain if $to !~ /@/; $from .= '@'.$mdomain if $from !~ /@/; if ($link ne "../$to/$from/$file") { symlink "../$to/$from/$file",$f; } } } } } # fix spool layout: FROM and TO must have domains and must be lower case foreach $d ((glob "$spooldir/*/*"),(glob "$spooldir/*")) { if (not -l $d and -d $d and $d =~ m:(.+)/(.+):) { $p = $1; $b = $2; if ($b !~ /^@/ and $b !~ /^[A-Z_-]+$/) { if ($mdomain and $b !~ /@/) { rename $d,sprintf("%s/%s@%s",$p,lc($b),$mdomain); } elsif ($b ne lc($b)) { rename $d,sprintf("%s/%s",$p,lc($b)); } } } } # split auth-ID and subuser file: @ --> @ @SUBUSER foreach my $u (glob "$spooldir/*@*") { next if -f "$u/\@SUBUSER"; open my $idf,"$u/\@" or next; $id = <$idf>; if (defined ($su = <$idf>) and $su =~ /\w/ and open my $suf,">$u/\@SUBUSER") { print {$suf} $su; while (defined ($su = <$idf>)) { print {$suf} $su } close $suf; close $idf; if (open my $idf,">$u/\@") { print {$idf} $id; close $idf; } } } # create new SKEYs foreach my $sf (glob "$spooldir/*/\@SUBUSER") { $user = (split '/',$sf)[-2]; if (open $sf,$sf) { while (<$sf>) { s/#.*//; if (/(.+\@.+):(.+)/) { ($subuser,$id) = ($1,$2); next if $subuser =~ /\*/; $skey = md5_hex("$user:$subuser:$id"); if (open $skey,'>',"$skeydir/$skey") { print {$skey} "from=$subuser\n", "to=$user\n", "id=$id\n"; close $skey; } mkdirp("$spooldir/$subuser/\@MAINUSER"); symlink $skey,"$spooldir/$subuser/\@MAINUSER/$user"; } } } close $sf; } # create new GKEYs foreach my $gf (glob "$spooldir/*/\@GROUP/*") { next unless -f $gf; $group = (split '/',$gf)[-1]; $user = (split '/',$gf)[-3]; if (open $gf,$gf) { while (<$gf>) { s/#.*//; if (/(.+\@.+):(.+)/) { ($gm,$id) = ($1,$2); $gkey = md5_hex("$user:$group:$gm:$id"); if (open $gkey,'>',"$gkeydir/$gkey") { print {$gkey} "from=$gm\n", "to=\@$group\n", "user=$user\n", "id=$id\n"; close $gkey; } mkdirp("$spooldir/$gm/\@GROUP"); symlink "../../$user/\@GROUP/$group","$spooldir/$gm/\@GROUP/$group"; } } } close $gf; } } sub cpav { my $dd = pop @_; local *P; die "cpav: $dd is not a directory" unless -d $dd; open P,"tar cf - @_ | su -c 'cd $dd; tar xvf - 2>&1' fex |" or die "cpav: cannot tar - $!\n"; while (

      ) { chomp; print "$_ --> $dd/$_\n" unless /\/$/; } close P; }