f41b982009-05-07Martin Stjernholm // This is a roxen module. Copyright © 1997 - 2009, Roxen IS.
1430c02000-03-16Martin Nilsson 
8446081997-08-29Marcus Comstedt #include <module.h> inherit "modules/filesystems/filesystem";
0917d32013-03-04Anders Johansson constant cvs_version= "$Id$";
71b1a61999-10-06Henrik Grubbström (Grubba) 
f0d6942001-01-29Per Hedbor //<locale-token project="mod_incoming">_</locale-token> #define _(X,Y) _DEF_LOCALE("mod_incoming",X,Y) // end of the locale related stuff
71b1a61999-10-06Henrik Grubbström (Grubba) 
17013c2001-05-16Per Hedbor LocaleString module_name = _(1,"File systems: Incoming filesystem");
f0d6942001-01-29Per Hedbor LocaleString module_doc =
6150972001-01-29Per Hedbor _(2,"This file system is used only for uploads, the files that are uploaded\n"
f0d6942001-01-29Per Hedbor "can either not be downloaded, or they will be scrambled during the download.\n" "This is considered a nice way to treat people who try to " "use your FTP site for warez distribution.");
8446081997-08-29Marcus Comstedt 
fc40392008-08-15Martin Stjernholm protected class decaying_file {
8446081997-08-29Marcus Comstedt 
b282d61998-04-06Henrik Grubbström (Grubba)  inherit Stdio.File;
8446081997-08-29Marcus Comstedt 
fc40392008-08-15Martin Stjernholm  protected int rate, left; protected function other_read_callback; protected int crot;
8446081997-08-29Marcus Comstedt  constant rotten_bits = "muahaha!(%/?\"&?¡/&?(/?_,-.,_:;Ѭ¾´";
fc40392008-08-15Martin Stjernholm  protected string decay(string data)
8446081997-08-29Marcus Comstedt  { if(sizeof(data)<=left) { left -= sizeof(data); return data; } string newdata = ""; while(sizeof(data)>left) { newdata += data[..left-1]; newdata += rotten_bits[crot..crot]; data = data[left+1..]; left = rate; if(++crot >= sizeof(rotten_bits)) crot = 0; } left -= sizeof(data); return newdata + data; } string read(mixed ... args) { string r = ::read(@args); if(stringp(r)) r = decay(r); return r; }
fc40392008-08-15Martin Stjernholm  protected mixed my_read_callback(mixed id, string data)
8446081997-08-29Marcus Comstedt  { if(stringp(data)) data = decay(data); return other_read_callback(id, data); } void set_read_callback(function read_callback) { if(read_callback) { other_read_callback = read_callback; ::set_read_callback(my_read_callback); } else ::set_read_callback(read_callback); } void set_nonblocking(function ... args) { if(sizeof(args) && args[0]) { other_read_callback = args[0]; ::set_nonblocking(my_read_callback, @args[1..]); } else ::set_nonblocking(@args); } int query_fd() { return -1; } void create(object f, int s, int r) { assign(f); rate = r-1; if(rate<0) rate=0; left = s; crot = 0; } } void create() { ::create();
a800681998-12-14Peter Bortas  defvar("bitrot", 0,
6150972001-01-29Per Hedbor  _(3,"Scrambled downloads: Return files with bitrot"), TYPE_FLAG, _(4,"If this function is enabled, downloads <i>are</i> allowed, "
f0d6942001-01-29Per Hedbor  "but the files will be scrambled."));
8446081997-08-29Marcus Comstedt 
a800681998-12-14Peter Bortas  defvar("bitrot_header", 2376,
6150972001-01-29Per Hedbor  _(5,"Scrambled downloads: Unscrambled header length"),TYPE_INT, _(6,"Number of bytes to be sent without any bitrot at all."), 0,
ed540b2001-01-13Martin Nilsson  lambda(){ return !query("bitrot"); });
af81c62000-02-16Per Hedbor 
a800681998-12-14Peter Bortas  defvar("bitrot_percent", 3,
6150972001-01-29Per Hedbor  _(7,"Scrambled downloads: Percent of bits to rot"), TYPE_INT, _(8,"Selects the percentage of the file that will receive bitrot"), 0,
ed540b2001-01-13Martin Nilsson  lambda(){ return !query("bitrot"); });
8446081997-08-29Marcus Comstedt }
fc40392008-08-15Martin Stjernholm protected mixed not_allowed( object id )
8446081997-08-29Marcus Comstedt {
9d34032000-05-03Martin Stjernholm  id->misc->moreheads = (id->misc->moreheads||([]))|(["Allow":"PUT"]); return http_low_answer ( 405, "<h1>" + id->method + " method not allowed in incoming filesystem.</h1>\n");
8446081997-08-29Marcus Comstedt } #define FILE_SIZE(X) (stat_cache?_file_size((X),id):Stdio.file_size(X))
9b7d7a2016-03-22Henrik Grubbström (Grubba) protected mixed lose_file( string norm_f, object id )
8446081997-08-29Marcus Comstedt { object o;
9b7d7a2016-03-22Henrik Grubbström (Grubba)  int size = FILE_SIZE( norm_f );
8446081997-08-29Marcus Comstedt  if(size < 0) return (size==-2? -1:0);
9b7d7a2016-03-22Henrik Grubbström (Grubba)  o = open( norm_f, "r" );
8446081997-08-29Marcus Comstedt  if(!o) return 0;
9b7d7a2016-03-22Henrik Grubbström (Grubba)  id->realfile = norm_f;
8446081997-08-29Marcus Comstedt  accesses++;
ed540b2001-01-13Martin Nilsson  return decaying_file( o, query("bitrot_header"), 100/query("bitrot_percent") );
8446081997-08-29Marcus Comstedt } mixed find_file( string f, object id ) {
9b7d7a2016-03-22Henrik Grubbström (Grubba)  string norm_f = real_path(f, id); if (!norm_f) { return Roxen.http_status(403, "Access forbidden by user"); }
8446081997-08-29Marcus Comstedt  switch(id->method) { case "GET": case "HEAD": case "POST":
ed540b2001-01-13Martin Nilsson  if(query("bitrot") && query("bitrot_percent")>0)
9b7d7a2016-03-22Henrik Grubbström (Grubba)  return lose_file( norm_f, id );
8446081997-08-29Marcus Comstedt  else return not_allowed( id ); case "PUT":
9b7d7a2016-03-22Henrik Grubbström (Grubba)  if(FILE_SIZE( norm_f ) >= 0) {
8446081997-08-29Marcus Comstedt  id->misc->error_code = 409; return 0; } return ::find_file( f, id ); case "DELETE": default: return not_allowed( id ); } report_error("Not reached..\n"); return 0; }