# This source code file is part of the "mod_survey" package. # # Copyright (C) 2004 Joel Palmius # # 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; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program (probably in a file named "LICENSE.txt" or the like); # if not, write to: # # Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #!/usr/bin/perl package Survey::Argument; use strict; use Survey::Language; use CGI qw/:standard/; sub new { my ($crap, $session) = @_; my ($valid) = 0; my $self = {}; bless($self); if ($ENV{"CONTENT_TYPE"} =~ m/multipart/) { # Assume we are doing upload. Only allowed in admin for now, # thus fake action and so on. This is ugly. $self->{"ARG_action"} = "admin"; $self->{"ARG_admin"} = "flush"; $self->{"ARG_flush"} = "upload"; $self->{"ARG_file"} = "1"; $self->{"noillegalcheck"} = "1"; } else { if ($ENV{"REQUEST_METHOD"} eq "POST") { read(STDIN, $ENV{"QUERY_STRING"}, $ENV{'CONTENT_LENGTH'}); } } $self->{QUERY_STRING} = $ENV{"QUERY_STRING"} || "action=display"; $self->{ERROR} = 0; $self->{ERRORCODE} = 0; $self->{SESSION} = $session; #print $self->{QUERY_STRING}; @{ $self->{DEFINED} } = (""); $self->ParseMulti(); $self->ParseQuery(); if ($self->ArgByName("action") eq "display") { $valid = $self->PlaceDisplay(); } # added in CRU patch (MJ/20020820) if ($self->ArgByName("action") eq "soap") { $valid = $self->PlaceDisplay(); } # added in CRU patch (MJ/200208) if ($self->ArgByName("action") eq "retrieve") { $valid = $self->PlaceDisplay(); } if ($self->ArgByName("action") eq "submit") { if ($self->ArgByName("realaction") eq "persistance") { $valid = $self->PlaceDisplay(); } else { $valid = $self->PlaceSubmit(); } } # added in CRU patch (MJ/200208) if ($self->ArgByName("save") eq "save") { $valid = $self->PlaceSubmit(); } if ($self->ArgByName("action") eq "admin") { $valid = $self->PlaceAdmin(); } # Display actions for Presentation if ($self->ArgByName("action") eq "graph") { $valid = 1; } if ($self->ArgByName("action") eq "table") { $valid = 1; } if ($self->ArgByName("action") eq "data") { $valid = 1; } if ($self->ArgByName("action") eq "logout") { $valid = 1; } if (!$valid) { my ($acti) = $self->ArgByName("action"); if ($acti =~ /[\<\>]/) { $self->{ERROR} = lprint("Script injection attempt detected"); $self->{ERRORCODE} = 5; } else { $self->{ERROR} = lprint("Action ") . $self->ArgByName("action") . lprint(" is not valid."); $self->{ERRORCODE} = 1; } } return ($self); } sub ParseMulti { my ($self) = shift; my ($ses) = $self->{SESSION}; my ($ssofar) = $ses->getValue("submittedsofar"); if ($ssofar) { my (@sofar) = split(/\x03/, $ssofar); my ($name, $value); foreach $name (@sofar) { $value = $ses->getValue("SUBMITTED_$name"); $self->{ "ARG_" . $name } = $value; $self->{ "ARG_" . $name . "_FROMSESSION" } = 1; } } 1; } sub ParseQuery { my ($self) = shift; my (@args, $cell, $name, $value, $fullName); $self->{QUERY_STRING} =~ s/\+/\ /g; # MH 210502 This has to be done after splitting! # $self->{QUERY_STRING} =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; @args = split(/&/, $self->{QUERY_STRING}); map s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg, @args; # modified by P. Sweatman to handle MultiChoice statments Nov 01 # instead of just setting the value to the space defined by ARG_$name, we # first check to see if the space is null. If it is, just assign the value. # If it's not, we append the new value to the old value, seperating things with # a comma. # This block read: # foreach $cell (@args) # { # ($name,$value) = split(/=/,$cell,2); # $self->{"ARG_" . $name} = $value; # } #start change Nov 01 foreach $cell (@args) { ($name, $value) = split(/=/, $cell, 2); $fullName = "ARG_" . $name; push(@{ $self->{DEFINED} }, $name); # MH 210502 # Illegal value checking / replacement has to be done before values are rememberd # added '&' to illegal values - it confuses too many output formats. if (!$self->{"noillegalcheck"}) { if ($ENV{"_SURVEY_PROTESTILLEGAL"}) { if ($value =~ /[\x00-\x08\x0b\x0c\x0e-\x1f]/) { $self->{ERROR} = lprint("Submit contained illegal characters"); $self->{ERRORCODE} = 4; } } else { $value =~ s/[\x00-\x08\x0b\x0c\x0e-\x1f]/\|\|/g; } } if (($self->{$fullName} eq "") || (!defined($self->{"DEFINED_$fullName"}))) { $self->{ "ARG_" . $name } = $value; # So we know this was actually submitted now $self->{ "QUERY_" . $name } = $value; } else { if ($value ne "!") { $self->{$fullName} = $self->{$fullName} . ",$value"; # Separate for checking values submitted *for this page* $self->{ "QUERY_" . $name } = $self->{ "QUERY_" . $name } . ",$value"; } } $self->{"DEFINED_$fullName"} = 1; #end change Nov 01 } 1; } sub PlaceDisplay { my ($self) = shift; # -- Implement argument checking # (not that there is much to check) 1; } sub PlaceSubmit { my ($self) = shift; if (!$self->ArgByName("key")) { $self->{ERROR} = lprint("Key not defined in submit"); $self->{ERRORCODE} = 2; } 1; } sub PlaceAdmin { my ($self) = shift; my (%valid); $valid{"data"} = "..."; $valid{"source"} = "..."; $valid{"debug"} = "..."; $valid{"stats"} = "..."; $valid{"flush"} = "..."; if ((!$valid{ $self->ArgByName("admin") }) && ($self->ArgByName("admin"))) { $self->{ERROR} = "\"" . $self->ArgByName("admin") . "\" " . lprint("is not a valid administrative task."); $self->{ERRORCODE} = 3; } # -- Implement argument checking for admin tasks 1; } sub ArgByName { my ($self, $name) = @_; return $self->{ "ARG_" . $name }; } sub Error { my ($self) = shift; return $self->{ERROR}; } sub PrintErrorDescription { my $self = shift; my ($e) = $self->{ERRORCODE}; my ($found) = 0; my ($lb) = "\<\;"; my ($rb) = "\>\;"; print "

\n "; if ($e) { if ($e eq 1) { print "[" . lprint("ARGUMENT ERROR 1, ACTION IS NOT VALID") . "] "; print lprint('The supplied value for the argument "action" is not valid. '); print lprint("Valid actions are ") . "display, submit, retrieve " . lprint("and") . "admin."; $found = 1; } if ($e eq 2) { print "[" . lprint("ARGUMENT ERROR 2, KEY IS NOT DEFINED") . "] "; print lprint( "As a security measure, a valid key has to be given when submitting data. No such key was found in the query string. "); $found = 1; } if ($e eq 3) { print "[" . lprint("ARGUMENT ERROR 3, IS NOT A VALID ADMINISRATIVE TASK") . "] "; print lprint('The supplid value for the argument "admin" is not valid. '); print lprint("Valid administrative tasks are") . " data, stats, debug, source " . lprint("and") . " flush."; $found = 1; } if ($e eq 4) { print "[" . lprint("ARGUMENT ERROR 4, SUBMIT CONTAINED ILLEGAL CHARACTERS") . "] "; print lprint("Submitted data cannot contain some specific characters, most notably"); print " \\x00 " . lprint("to") . " \\x1F. "; print lprint('Please press "back" in your browser and remove these characters from your answers.'); $found = 1; } if ($e eq 5) { print "[" . lprint("ARGUMENT ERROR 5, SCRIPT INJECTION ATTEMPT DETECTED") . "] "; print lprint( "One system parameter contained illegal characters normally associated with script injection attempts.") . " "; print lprint( "If you did not do this, then please report a possible security breach to the system administrator."); $found = 1; } if (!$found) { print lprint("This error is not in the knowledge base, so I guess the programmer has made a mistake."); } } else { print "[" . lprint("ARGUMENT ERROR 0, NO ERROR") . "] "; print lprint( "No error has occured, but the programmer has for some reason called PrintErrorDescription() anyway. "); print lprint("I guess the programmer has again made a mistake, something that is a very common event indeed."); } print "\n

\n"; 1; } 1;