summaryrefslogtreecommitdiffstats
path: root/kioslave/fish/fish.pl
diff options
context:
space:
mode:
Diffstat (limited to 'kioslave/fish/fish.pl')
-rwxr-xr-xkioslave/fish/fish.pl369
1 files changed, 369 insertions, 0 deletions
diff --git a/kioslave/fish/fish.pl b/kioslave/fish/fish.pl
new file mode 100755
index 000000000..1ba539f9f
--- /dev/null
+++ b/kioslave/fish/fish.pl
@@ -0,0 +1,369 @@
+#!/usr/bin/perl
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 2 of the License
+=pod
+This file was transferred by kio_fish, a network client part of the
+KDE project. You may safely delete it, it will be transferred again
+when needed. It's only purpose is to make kio_fish access faster and
+more reliable.
+=cut
+
+use Fcntl;
+
+$|++;
+#open(DEBUG,">/tmp/kio_fish.debug.$$.log");
+# save code in initial directory if just transferred
+if (defined $code) {
+ unlink('.fishsrv.pl');
+ sysopen(FH,'.fishsrv.pl',O_WRONLY|O_CREAT|O_EXCL);
+ print FH $code;
+ close(FH);
+ chmod(0444,'.fishsrv.pl');
+# request new code if it changed (checksum mismatch)
+# for automatic upgrades
+} elsif ($ARGV[0] ne "{CHECKSUM}") {
+ $|=1;
+ print "### 100 transfer fish server\n";
+ while(<STDIN>) {
+ last if /^__END__/;
+ $code.=$_;
+ }
+ exit(eval($code));
+}
+
+# we are up and running.
+print "### 200\n";
+use strict;
+use POSIX qw(getcwd dup2 strftime);
+$SIG{'CHLD'} = 'IGNORE';
+$| = 1;
+MAIN: while (<STDIN>) {
+ chomp;
+ chomp;
+ next if !length($_) || substr($_,0,1) ne '#';
+#print DEBUG "$_\n";
+ s/^#//;
+ /^VER / && do {
+ # We do not advertise "append" capability anymore, as "write" is
+ # as fast in perl mode and more reliable (overlapping writes)
+ print "VER 0.0.3 copy lscount lslinks lsmime exec stat\n### 200\n";
+ next;
+ };
+ /^PWD$/ && do {
+ print getcwd(),"\n### 200\n";
+ next;
+ };
+ /^SYMLINK\s+((?:\\.|[^\\])*?)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $ofn = unquote($1);
+ my $fn = unquote($2);
+ print (symlink($ofn,$fn)?"### 200\n":"### 500 $!\n");
+ next;
+ };
+ /^COPY\s+((?:\\.|[^\\])*?)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $ofn = unquote($1);
+ my $fn = unquote($2);
+ my ($size) = (stat($ofn))[7];
+ my $read = 1;
+ if (-l $ofn) {
+ my $dest = readlink($ofn);
+ unlink($fn);
+ symlink($dest,$fn) || ($read = 0);
+ } else {
+ sysopen(FH,$ofn,O_RDONLY) || do { print "### 500 $!\n"; next; };
+ sysopen(OFH,$fn,O_WRONLY|O_CREAT|O_TRUNC) || do { close(FH); print "### 500 $!\n"; next; };
+ local $/ = undef;
+ my $buffer = '';
+ while ($size > 32768 && ($read = sysread(FH,$buffer,32768)) > 0) {
+ $size -= $read;
+ if (syswrite(OFH,$buffer,$read) != $read) {
+ close(FH); close(OFH);
+ print "### 500 $!\n";
+ next MAIN;
+ }
+
+ }
+ while ($size > 0 && ($read = sysread(FH,$buffer,$size)) > 0) {
+ $size -= $read;
+ if (syswrite(OFH,$buffer,$read) != $read) {
+ close(FH); close(OFH);
+ print "### 500 $!\n";
+ next MAIN;
+ }
+ }
+ close(FH);
+ close(OFH);
+ }
+ if ($read > 0) {
+ print "### 200\n";
+ } else {
+ print "### 500 $!\n";
+ }
+ next;
+ };
+ /^LINK\s+((?:\\.|[^\\])*?)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $ofn = unquote($1);
+ my $fn = unquote($2);
+ print (link($ofn,$fn)?"### 200\n":"### 500 $!\n");
+ next;
+ };
+ /^RENAME\s+((?:\\.|[^\\])*?)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $ofn = unquote($1);
+ my $fn = unquote($2);
+ print (rename($ofn,$fn)?"### 200\n":"### 500 $!\n");
+ next;
+ };
+ /^CHGRP\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $fn = unquote($2);
+ print (chown(-1,int($1),$fn)?"### 200\n":"### 500 $!\n");
+ next;
+ };
+ /^CHOWN\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $fn = unquote($2);
+ print (chown(int($1),-1,$fn)?"### 200\n":"### 500 $!\n");
+ next;
+ };
+ /^CHMOD\s+([0-7]+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $fn = unquote($2);
+ print (chmod(oct($1),$fn)?"### 200\n":"### 500 $!\n");
+ next;
+ };
+ /^DELE\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $fn = unquote($1);
+ print (unlink($fn)?"### 200\n":"### 500 $!\n");
+ next;
+ };
+ /^RMD\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $dn = unquote($1);
+ print (rmdir($dn)?"### 200\n":"### 500 $!\n");
+ next;
+ };
+ /^MKD\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $dn = unquote($1);
+ if (mkdir($dn,0777)) {
+ print "### 200\n";
+ } else {
+ my $err = $!;
+ print (chdir($dn)?"### 501 $err\n":"### 500 $err\n");
+ }
+ next;
+ };
+ /^CWD\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $dn = unquote($1);
+ print (chdir($dn)?"### 200\n":"### 500 $!\n");
+ next;
+ };
+ /^LIST\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ list($1, 1);
+ next;
+ };
+ /^STAT\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ list($1, 0);
+ next;
+ };
+ /^WRITE\s+(\d+)\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ write_loop($2,$3,O_WRONLY|O_CREAT,$1);
+ next;
+ };
+ /^APPEND\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ write_loop($1,$2,O_WRONLY|O_APPEND);
+ next;
+ };
+ /^STOR\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ write_loop($1,$2,O_WRONLY|O_CREAT|O_TRUNC);
+ next;
+ };
+ /^RETR\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ read_loop($1);
+ next;
+ };
+ /^READ\s+(\d+)\s+(\d+)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ read_loop($3,$2,$1);
+ next;
+ };
+ /^EXEC\s+((?:\\.|[^\\])*?)\s+((?:\\.|[^\\])*?)\s*$/ && do {
+ my $tempfile = unquote($2);
+ my $command = unquote($1);
+ $command = $command . ";echo \"###RESULT: \$?\"";
+ print("### 500 $!\n"), next
+ if (!sysopen(FH,$tempfile,O_CREAT|O_EXCL|O_WRONLY,0600));
+ my $pid = fork();
+ print("### 500 $!\n"), next
+ if (!defined $pid);
+ if ($pid == 0) {
+ open(STDOUT,'>>&FH');
+ open(STDERR,'>>&FH');
+ open(STDIN,'</dev/null'); # not sure here, ms windows anyone?
+ exec('/bin/sh','-c',$command);
+ print STDERR "Couldn't exec /bin/sh: $!\n";
+ exit(255);
+ }
+ waitpid($pid,0);
+ close(FH);
+ print "### 200\n";
+ next;
+ };
+}
+exit(0);
+
+sub list {
+ my $dn = unquote($_[0]);
+ my @entries;
+ if (!-e $dn) {
+ print "### 404 File does not exist\n";
+ return;
+ } elsif ($_[1] && -d _) {
+ opendir(DIR,$dn) || do { print "### 500 $!\n"; return; };
+ @entries = readdir(DIR);
+ closedir(DIR);
+ } else {
+ ($dn, @entries) = $dn =~ m{(.*)/(.*)};
+ $dn = '/' if (!length($dn));
+ }
+ print scalar(@entries),"\n### 100\n";
+ my $cwd = getcwd();
+ chdir($dn) || do { print "### 500 $!\n"; return; };
+ foreach (@entries) {
+ my $link = readlink;
+ my ($mode,$uid,$gid,$size,$mtime) = (lstat)[2,4,5,7,9];
+ print filetype($mode,$link,$uid,$gid);
+ print "S$size\n";
+ print strftime("D%Y %m %d %H %M %S\n",localtime($mtime));
+ print ":$_\n";
+ print "L$link\n" if defined $link;
+ print mimetype($_);
+ print "\n";
+ }
+ chdir($cwd);
+ print "### 200\n";
+}
+
+sub read_loop {
+ my $fn = unquote($_[0]);
+ my ($size) = ($_[1]?int($_[1]):(stat($fn))[7]);
+ my $error = '';
+ print "### 501 Is directory\n" and return if -d $fn;
+ sysopen(FH,$fn,O_RDONLY) || ($error = $!);
+ if ($_[2]) {
+ sysseek(FH,int($_[2]),0) || do { close(FH); $error ||= $!; };
+ }
+ print "### 500 $error\n" and return if $error;
+ if (@_ < 2) {
+ print "$size\n";
+ }
+ print "### 100\n";
+ my $buffer = '';
+ my $read = 1;
+ while ($size > 32768 && ($read = sysread(FH,$buffer,32768)) > 0) {
+#print DEBUG "$size left, $read read\n";
+ $size -= $read;
+ print $buffer;
+ }
+ while ($size > 0 && ($read = sysread(FH,$buffer,$size)) > 0) {
+#print DEBUG "$size left, $read read\n";
+ $size -= $read;
+ print $buffer;
+ }
+ while ($size > 0) {
+ print ' ';
+ $size--;
+ }
+ $error ||= $! if $read <= 0;
+ close(FH);
+ if (!$error) {
+ print "### 200\n";
+ } else {
+ print "### 500 $error\n";
+ }
+}
+
+sub write_loop {
+ my $size = int($_[0]);
+ my $fn = unquote($_[1]);
+#print DEBUG "write_loop called $size size, $fn fn, $_[2]\n";
+ my $error = '';
+ sysopen(FH,$fn,$_[2]) || do { print "### 400 $!\n"; return; };
+ eval { flock(FH,2); };
+ if ($_[3]) {
+ sysseek(FH,int($_[3]),0) || do { close(FH);print "### 400 $!\n"; return; };
+ }
+ <STDIN>;
+ print "### 100\n";
+ my $buffer = '';
+ my $read = 1;
+ while ($size > 32768 && ($read = read(STDIN,$buffer,32768)) > 0) {
+#print DEBUG "$size left, $read read\n";
+ $size -= $read;
+ $error ||= $! if (syswrite(FH,$buffer,$read) != $read);
+ }
+ while ($size > 0 && ($read = read(STDIN,$buffer,$size)) > 0) {
+#print DEBUG "$size left, $read read\n";
+ $size -= $read;
+ $error ||= $! if (syswrite(FH,$buffer,$read) != $read);
+ }
+ close(FH);
+ if (!$error) {
+ print "### 200\n";
+ } else {
+ print "### 500 $error\n";
+ }
+}
+
+sub unquote { $_ = shift; s/\\(.)/$1/g; return $_; }
+
+sub filetype {
+ my ($mode,$link,$uid,$gid) = @_;
+ my $result = 'P';
+ while (1) {
+ -f _ && do { $result .= '-'; last; };
+ -d _ && do { $result .= 'd'; last; };
+ defined($link) && do { $result .= 'l'; last; };
+ -c _ && do { $result .= 'c'; last; };
+ -b _ && do { $result .= 'b'; last; };
+ -S _ && do { $result .= 's'; last; };
+ -p _ && do { $result .= 'p'; last; };
+ $result .= '?'; last;
+ }
+ $result .= ($mode & 0400?'r':'-');
+ $result .= ($mode & 0200?'w':'-');
+ $result .= ($mode & 0100?($mode&04000?'s':'x'):($mode&04000?'S':'-'));
+ $result .= ($mode & 0040?'r':'-');
+ $result .= ($mode & 0020?'w':'-');
+ $result .= ($mode & 0010?($mode&02000?'s':'x'):($mode&02000?'S':'-'));
+ $result .= ($mode & 0004?'r':'-');
+ $result .= ($mode & 0002?'w':'-');
+ $result .= ($mode & 0001?($mode&01000?'t':'x'):($mode&01000?'T':'-'));
+
+ $result .= ' ';
+ $result .= (getpwuid($uid)||$uid);
+ $result .= '.';
+ $result .= (getgrgid($gid)||$gid);
+ $result .= "\n";
+ return $result;
+}
+
+sub mimetype {
+ my $fn = shift;
+ return "Minode/directory\n" if -d $fn;
+ pipe(IN,OUT);
+ my $pid = fork();
+ return '' if (!defined $pid);
+ if ($pid) {
+ close(OUT);
+ my $type = <IN>;
+ close(IN);
+ chomp $type;
+ chomp $type;
+ $type =~ s/[,; ].*//;
+ return '' if ($type !~ m/\//);
+ return "M$type\n"
+ }
+ close(IN);
+ sysopen(NULL,'/dev/null',O_RDWR);
+ dup2(fileno(NULL),fileno(STDIN));
+ dup2(fileno(OUT),fileno(STDOUT));
+ dup2(fileno(NULL),fileno(STDERR));
+ exec('/usr/bin/file','-i','-b','-L',$fn);
+ exit(0);
+}
+__END__