123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Readonly;
  5. use CGI;
  6. ###
  7. ### CONSTANTS ###
  8. ###
  9. # settings
  10. Readonly my $DEFMIN => 1024;
  11. Readonly my $DEFMAX => 20480;
  12. Readonly my $FNAME_LENGTH => 16;
  13. Readonly my $FNAME_EXTENSION => '.txt';
  14. Readonly my $DEBUG => 0;
  15. # facts
  16. Readonly my $EICAR_BODY => 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*';
  17. Readonly my $HARDMIN => 1024;
  18. Readonly my $HARDMAX => 20480;
  19. my @RANDOM_CHARS = ( 'a' .. 'z', 'A' .. 'Z', '0' .. '9', '_' );
  20. ( $DEFMIN < $DEFMAX ) or die("Invalid lower and upper limits!");
  21. ( $HARDMIN < $HARDMAX ) or die("Invalid lower and upper limits!");
  22. my $q = CGI -> new();
  23. ###
  24. ### SUBBIES ###
  25. ###
  26. sub dprint { ## @message ## print all $message-s with dbg fancy
  27. my $mes;
  28. return if ( $DEBUG == 0 );
  29. while (1) {
  30. $mes = shift or return;
  31. print "randomfile: DEBUG: $mes\n";
  32. }
  33. return;
  34. }
  35. sub minmax_valid { ## low, high, min, max ## Validate boundaries
  36. my ($low, $hgh, $min, $max ) = @_;
  37. # dprint "## $low # $high ## $min # $max ##";
  38. # If array is wanted, try to crop
  39. if ( wantarray() ) {
  40. $low = $min if ( $low <= $min ); # crop low to min
  41. $low = $max if ( $low >= $max ); # crop low to max
  42. $hgh = $min if ( $hgh <= $min ); # crop hgh to min
  43. $hgh = $max if ( $hgh >= $max ); # crop hgh to max
  44. return ( $low, $hgh, $min, $max ); # return valid low high min max
  45. }
  46. # Else just answer if it's OK
  47. else {
  48. return 0 if ( $low < $min || $low > $max );
  49. return 0 if ( $hgh < $min || $hgh > $max );
  50. return 0 if ( $hgh < $low );
  51. return 0 if ( $max < $max );
  52. return 1;
  53. }
  54. }
  55. sub http_die { ## $status ## Http-die with $status
  56. my $status = shift || 400;
  57. print $q->header ( -type => 'text/plain' , -status => $status );
  58. exit 1;
  59. }
  60. sub generate_random_string { # -------
  61. my $length = shift;
  62. my $flush = shift;
  63. my $random_string;
  64. foreach ( 1 .. $length ) {
  65. $random_string .= $RANDOM_CHARS[ rand @RANDOM_CHARS ];
  66. }
  67. return $random_string;
  68. }
  69. sub print_random_string { # -------
  70. my $length = shift;
  71. foreach ( 1 .. $length ) {
  72. print $RANDOM_CHARS[ rand @RANDOM_CHARS ];
  73. }
  74. return 1;
  75. }
  76. ###
  77. ### PAREMETER RETRIEVAL & VALIDATION ###
  78. ###
  79. # Get parameters from CGI query
  80. $q->import_names;
  81. my $min = defined ($Q::min) ? $Q::min : $DEFMIN;
  82. my $max = defined ($Q::max) ? $Q::max : $DEFMAX;
  83. my $eicar_chance = defined ($Q::eicar) ? $Q::eicar : 0;
  84. # Validate min/max against hard min/max
  85. minmax_valid ( $min , $max, $HARDMIN, $HARDMAX ) or http_die( 400 );
  86. ###
  87. ### MAIN ###
  88. ###
  89. # Generate random output length
  90. my $length = int( $min + rand( $max - $min ) );
  91. # Generate the random filename
  92. my $random_fname = &generate_random_string($FNAME_LENGTH) . $FNAME_EXTENSION;
  93. # Random throw of EICAR ( 0 to 99 inclusive )
  94. my $eicar_throw = int ( rand ( 100 ) );
  95. #final printing
  96. if ($eicar_throw <= $eicar_chance ) {
  97. # serve EICAR
  98. print $q->header();
  99. print $EICAR_BODY;
  100. } else {
  101. # serve random content
  102. print $q->header();
  103. print_random_string($length);
  104. }
  105. dprint (
  106. "\$min = $min",
  107. "\$max = $max",
  108. "\$eicar_chance = $eicar_chance",
  109. "\$eicar_throw = $eicar_throw",
  110. );