Preserve plus signs from CGI input in Perl - perl

I'm working on a web application with several forms on which the user is expected to input data often containing spaces and/or plus signs.
The data is generally sent either through GET requests; or through POST requests with a application/x-www-form-urlencoded Content-Type header.
I have tried using either Vars() and param from Perl's CGI module, but both of these methods insist on converting the + signs into spaces.
Does the CGI module provide any mechanism to preserve the + signs; or should I ditch CGI and manually parse the STDIN input?
Note:
With the large amount of forms (over the hundred), and having the CGI pre-processing happening in a centralized utility library, I'm quite biased towards a server-side solution rather than a client-side approach (in other words, I'd rather deal with the problem once on the pre-processing code once than adding JS noise on hundreds of places).
Thanks in advance for any help provided.
Example:
As requested in the comments, here is a (simplified) sample of some code that triggers the issue.
HTML
<form action="/cgi-bin/some-script.pl">
<input name="some_field" value="1 + 1 is 2">
<input name="submit" type="submit" value="Submit">
</form>
Perl
use CGI;
my $some_variable = CGI::param('some_field');
After submiting the form with the default value and running the server-side code, $some_variable's value is "1 1 is 2" (there are three spaces between the 1's, either the SO site or the browser may be collapsing them into a single space); the desired outcome would be to get the value "1 + 1 is 2" in that variable.

Plus signs in CGI parameters mean spaces. That's in the CGI spec. Any HTTP client that sends you plus signs to mean anything else is broken. Any HTTP server that processes plus signs to mean anything else is broken.
So the problem is not in your CGI program (which is doing the right thing). The problem is in the HTTP client which is sending you plus signs intending them to be interpreted as plus signs. The correct way to sent a plus sign as a parameter in a CGI program is to encode it as %2B. That's the problem that you need to fix.
Update: I've run a simple test using Apache on Ubuntu.
My HTML file looked like this:
<html>
<head>
<title>Test</title>
</head>
<body>
<h1>Test</h1>
<form action="/cgi-bin/param">
<input name="some_field" value="1 + 1 is 2">
<input name="submit" type="submit" value="Submit">
</form>
</body>
</html>
My Perl program looked like this:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use CGI qw[header param];
print header(-type => 'text/plain');
for (param) {
say "$_ -> ", join ':', param($_);
}
When I visited the page and hit the 'submit' button, the browser went to the URL http://localhost/cgi-bin/param?some_field=1+%2B+1+is+2&submit=Submit and displayed the following:
some_field -> 1 + 1 is 2
submit -> Submit
This looks like the behaviour I expect to see. The browser correctly encodes the plus sign to %2B when sending it to the browser. Perl's CGI module decodes that value when I access it.
You need to track down why your browser (or whatever other client you're using to send these requests) isn't following the CGI spec.

Related

How to set up rotating images in email signature

My company has asked me to change our signatures so that the current image we use is replaced by a set of 4 that rotate, so only one shows at a time but they are often changing.
Now the problem is that we use Exclaimer Cloud to manage our signatures for our emails which run through Office 365. Exclaimer have an article on how to achieve it in their software, but for me it looks too time-consuming. I already have about 6 different signature designs for different departments, and their method involves splitting each signature into 3 parts and doing some fancy stuff on it but even they admit that this method requires admin input to reset dates every time the revolving images reach the last one. For me, splitting 6 signatures into 3 parts, setting them all up, managing them ongoing etc is not feasible.
So I've had some other ideas but don't know enough to develop them or know if they would work by myself:
I have admin access to a company (LAMP) server. Could I host the images on this and use a script to rename them every X minutes so that a different image matches the link after every time the code runs?
Is there any way the server could be set up to deliver a different image every time the link is called?
Exclaimer doesn't support any embedded html in the signature so anything like this has to be server side as far as I can see.
So far as a workaround I've done the following:
I've placed 4 alternate signature design banners in a server directory, then copied one of them and called it banner-main.png
Then I've placed the image in Exclaimer as a signature link to this copied file so [url]/banner-main.png
Then I've created index.php in the same directory with a radio form that allows any of the four images I've uploaded to be selected. When the form is submitted it copies the selected image and renames it as banner-main.png which overwrites the previous file with this name.
I've considered re-writing the code so that the page automatically refreshes every half hour or so, and chooses the next image in the sequence when it does so. It wouldn't be hard to do.
This method works for me and is relatively simple compared to the Exclaimer way of doing it but is still not ideal. I'd prefer it if the images could be re-written server side without having to open a page in my browser, or some way that doesn't require any human input / maintenance.
Anyway here is the code I'm currently using, maybe it will help someone else.
<!DOCTYPE html>
<html>
<body>
<?php
$formval = $_POST["banners"] ;
$newname = "banner-main.png" ;
$dir = "/home/armorgar/public_html/sites/productinfo/sig/" ;
$htmldir = "/sig/" ;
$oldimg = $dir . $formval . ".png" ;
$newimg = $dir . $newname ;
if (copy($oldimg, $newimg)) {
echo ($formval . " is the new email signature image.") ;
} else {
echo "Sorry, there was an error.";
} ;
echo "<br>" ;
echo 'Test link to banner' ;
echo "<br>" ;
?>
<h1>Which banner is next?</h1>
<br>
<form action="/sig/index.php" method="post">
<input type="radio" name="banners" value="banner-1">Banner 1
<br>
<input type="radio" name="banners" value="banner-2">Banner 2
<br>
<input type="radio" name="banners" value="banner-3">Banner 3
<br>
<input type="radio" name="banners" value="banner-4">Banner 4
<br>
<input type="submit" value="Submit">
</form>
</body>
</html>

How do I check if a CGI button is pressed and then redirect them

It's hard to explain but for example. If I have something like this:
print submit(value => Exit), "\n";
how do I make it so that when the person presses that exit button in the browser, it will redirect them to a page that says for example "cya later".
You're using the HTML generation functions from CGI.pm. These have been deprecated for some time (and they were never a good idea). I recommend that you look at using a templating engine instead.
Having said that, the changes the you require are pretty simple. You'll need to change your code in two places. Firstly, you need to change the code that generates the submit button so that it adds a name to the generated HTML.
# Don't do this. Use a template.
# NB: Note the '-' I've added to the option names.
print submit(-value => 'Exit', -name => 'Exit'), "\n";
Then you'll need to change the code which deals with your incoming parameters to deal with this new parameter.
if (param('Exit')) {
print redirect('http://somewhere_else.com/');
exit;
}
Note that a) the redirection header should be printed instead of any other headers that you program might be planning to return (so, don't include a content-type header) and b) your program should exit soon after printing the redirection header - you shouldn't print any other output.
Update: It's also worth pointing out that one of the reasons for avoiding the HTML generation functions is that they are (necessarily) over-complicated to use. A good example is your usage of them:
print submit(value => Exit)
This is actually wrong as it produces this output:
<input type="submit" name="value" value="Exit" />
What I suspect you meant was:
print CGI->new->submit(-value => 'Exit')
Which gives this:
<input type="submit" name=".submit" value="Exit" />
As you haven't given an explicit name, the function has synthesised one (.submit) for you. In my example above I have given the input an explicit name:
print submit(-value => 'Exit', -name => 'Exit')
Which produces this:
<input type="submit" name="Exit" value="Exit" />
Give the submit button a name. It will then appear in params if it is used to submit the form.

new-line causes POST to crap out, what to do?

So I'm getting an error:
501 Method Not Implemented
POST to /newbooks.php not supported.
The code works fine, except when I pass (via POST) new-line characters, in which case I get the above error. Here is the form
<form method="post" action="?action=addnewbooks&submit=validate">
<Textarea name="newbooklist" rows="30" cols="68"></textarea>
Password: <input type="password" name="password" size="8" maxlength="50"></input>
<button type="submit" name="Submit">Submit</button>
</form>
A sample of what I'm pasting in below.
Heartwishes : an Edilean novel / Jude Deveraux|Deveraux, Jude|2011|9781439108000 (hbk.)| Kill me if you can : a novel / by James Patterson and Marshall Karp|Patterson, James|2011|9780316097543| Murder by mocha / Cleo Coyle|Coyle, Cleo|2011|9780425241431 (hbk.)|
I can clean the data up once it's passed to the second page of the form, but I'm not sure what I can do since it's crapping out before it passes the data to the validation page. The data that is being pasted in the form is actually a huge report (full of duplicates to) that is auto-generated. Edited to add: I'm reasonably certain it's the James Patterson book that is causing the problem, but I can't see where the problem is.
EDIT: So James Patterson is a 1337 hacker. Since I know what the problem is, now it's just a matter of finding a solution. Since the list is all of the books added to the library's collection in the last week, we're sure to more titles that start with kill. Are there other words that are likely to make modsecurity think it's an SQL attack? What can I do to pre-clean the data to deal with this kind of thing?
So turns out this is triggering our server's firewall. It sees %0D%0AKill in the POST data and thinks it's a System Command Injection.

Why do forms timeout in ColdFusion?

We're on CF 8 and we have a CF application with a 1 hour session timeout specified.
<cfapplication sessionmanagement="yes" sessiontimeout="#CreateTimeSpan(0, 0, 60, 0)#" name="myAppName" clientmanagement="yes">
Within the CF administrator, we have a default session timeout of 1 hour, and a max session timeout of 1 day.
We're having some odd (intermittent) form timeout issues on submission of a regular form (not a flash form)...
Let's say the user hits the form page at 10:30am. (I know this because I'm appending the time to the "Action" property of the form tag). At 11:10am, the user submits the form, but none of the form struct is available to the action page, so the user gets an error.
I know that it's coming from the correct page since the CGI.referrer is defined properly.
In my custom error handler, I iterate over any form, session, or client structs -- and there is NO form struct defined at this point. All of the other Session and Client variables ARE still available.
Excerpts from Form Page:
<cfform name="chairsComment" id="chairsComment" action="library/save_chairsComment.cfm?Start=0224_153027" method="post" >
<input name="chairsCommentNumber" id="chairsCommentNumber" type="hidden" value="13" />
<textarea name="comment_13" rows="50" wrap="virtual" cols="100" id="comment_13" ></textarea>
<input name="save_answer" id="save_answer" type="submit" value="Save Response" />
</cfform>
And for the Action page, it throws an error on line 1:
<cfset whichCommentNumber = form.chairsCommentNumber>
It works during testing, but when some of our users use it, it throws the error that "Element CHAIRSCOMMENTNUMBER is undefined in FORM." We've just started looking at the specific browser that this individual is using (Safari 4.0.3) and asked him to upgrade to 5.x, but with SUCH a vanilla form, it seems an unlikely culprit.
Any Ideas?
In the midst of a discussion on Ray Camden's blog about file uploading, someone mentions a problem with Safari 4.0.5 throwing an error because the form field did not contain a file ... it's not the same problem, necessarily, but it could be related. Unfortunately, the commenter never returned with more information.
There's a post on another blog here where a commenter mentions an issue with Safari and a cfform inside a cfdiv tag. If your cfform is similarly nested, you might need to reverse the order (nest the cfdiv inside the form) to make this work.

submit via GET an email address avoiding url encoding?

I might have a freudian lips but i cant figure out how to send an email address to a specific url without the url encodes the AT symbol in %40...
basically i have a basic form
<form class="firstLoginform" id="firstLoginform" name="firstLoginform" method="get" action="https://myurl" >
<label for="email" >Email Address</label>
<input type="text" name="userEmail" id="userEmail" size="20" maxlength="150">
<center>
<input type="submit" value="submit" />
</center>
</form>
but i submit the form the url is gonna be like
https://myurl?userEmail=myemail%40mydomain.com
but I NEED, for soe reason of the previous settings a ul like this
https://myurl?userEmail=myemail#mydomain.com
i dont have access to the page that is receiving the variables...so i wonder if i can send the email address AS IS..
thanks!!!
No, you can't according to RFC1738, the URL Spec. The # symbol is reserved because it has a special meaning.
As Alan mentioned the URL specification (RFC1738) forbids the use of the # symbol in URLs because it's reserved for use within any type of URL. An example of this would be an FTP URL which provides the option to specify a username#host.domain syntax.
Section 3 of the RFC shows a number of cases that use the # symbol in a URL.
For this reason # along with a number of other characters can't be used as part of an HTTP URL.
No, you can't. Variables in query strings must be encoded, otherwise it isn't a valid URL.