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

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.

Related

ValidForm Builder file type validation

Does anybody know how to validate the file type input.
I have modified (hard coded) the class.vf_file.php input.
$strOutput .= "<input accept=\".pdf,.doc,.docx\" etc----/>\n";
This helps with Google Chrome, but Safari, Firefox ignore the modifications
Preventing users to submit the form if any other type of file is detected would be the ideal solution.
Thank you
I would recommend using a third party file uploading library like Plupload. We always use ValidForm Builder together with Plupload; works like a charm.
However you can use the meta array to implement custom attributes in the <input> tag without having to hardcode anything:
$objForm->addField(
"upload-document",
"Upload Document",
ValidForm::VFORM_FILE,
array(), // Validation array
array(), // Error handling array
array( // Meta array
"fielddata-extensions" => "pdf,doc,docx"
)
);
By prefixing meta keys with the 'field' prefix, you add that specific meta to the <input> field itself instead of it's wrapping <div class='vf__optional'></div>
The above example will output:
<div class="vf__optional">
<label for="upload-image">Upload Image</label>
<input type="hidden" name="MAX_FILE_SIZE" value="2097152">
<input type="file" value="" name="upload-image[]" id="upload-image" class="vf__file" data-extensions="pdf,doc,docx">
</div>
So using a combination of meta and a third party file upload handler, you can actually to pretty cool stuff.
That being said -- I must admit that the file upload field didn't get as much attention as the other field types lately.

CGI Perl - changing action and mode variables

I am somewhat of a novice with CGI Perl and am working on a web app that uses 'mode' and 'action' variables to determine which pages load.
$mode = param('mode');
$action = param('action');
if ($mode eq 'page1') {
if ($action 'eq') {
&performAction;
}
displayPage1;
}
elsif ($mode eq 'page2') {
&displayPage2
}
During development I have been having trouble figuring out the best way to set these variables when trying to navigate to different modes/actions after a form submit.
In some cases, putting a hidden value in the form will work
hidden(-name=>'action',-value=>'save')
but sometimes it will not. In case of the latter, putting param('action',"save") before the form will make the action change when the form is submitted.
I am unable to figure out why this happens though, are there factors that affect these two variables that I am unaware of?
What I now need to do is have two buttons on the same form, one which will just set the action to save the form data, and another which will save the form data but navigate to another mode/page with that form data.
If anyone could at least point me in the right direction for what I should be researching I would be greatly appreciative.
By default the CGI module implements a state-preserving behavior called "sticky" fields. The way this works is that if you are regenerating a form, the methods that generate the form field values will interrogate param() to see if similarly-named parameters are present in the query string. If they find a like-named parameter, they will use it to set their default values.
You want
hidden(-name=>'action', -value=>$new_value, -override=>1)
or
hidden(-name=>'action', -value=>'default_value')
param('hidden_name', $new_value);
This is a try , not sure if it would work.
Try setting hidden variable before button and changing it before every button, so the new value should be taken.
For ex:
<input type='hidden' name='op' value='save'/>
<input type='submit' name='Save Form' value='SaveForm'/>
<input type='hidden' name='op' value='submit'/>
<input type='submit' name='Submit Form' value='SubmitForm'/>
<input type='hidden' name='op' value='cancel'/>
<input type='submit' name='Cancel Form' value='CancelForm'/>
You can check for hidden variable 'op' in perl script.

Getting user entries from a Form based on Genshi Template

I'm trying to write a Plugin for Trac.
I've succeeded to export variables contents from my request (process_request)
to my template ...but I still having problems doing it in the other way : how to catch the information taped by the user ?
<form name="input" action="" method="POST">
Configuration : <input type="text" name="configuration" value ="$my_var" /> <br /><br />
<label for="file">URL:</label>
<input type="text" name="file" id="WillPosted" value="This text will be changed by the user"/>
<input type="submit" name="SubmiT" value="Browse" /><br /><br />
So how can I catch the content of the input form with the id="WillPosted" ?
Notice : actual problem is in IRequestHandler methods from Trac !
Any Idea ?
Thanks
You're asking about the common web-UI interaction
my_var --> template with input field 'file' and default value 'This will ..'
user input to field
submission by POST request
How to get (changed) new value of input, right? If so, you explained it rather complicated.
And I'm wondering, if you don't know about trac-hacks.org, probably the most authoritative source of Trac plugin code on the planet - much more working examples to look at than needed here.
Anyway, the key is reading the return value(s) from reg.args dict like so:
from pkg_resources import resource_filename
from trac.web.chrome import ITemplateProvider, add_stylesheet
implements(IRequestHandler, ITemplateProvider)
# IRequestHandler methods
def match_request(self, req):
# Any condition evaluating to True will fire the second method.
return req.path_info == '/<your_path>'
def process_request(self, req):
"Demo how to interact with your template."
# Check, if you'r really processing the right request by target matching,
# and only act on input of authorized users - as an added suggestion/option.
if req.path_info.startswith('/<your_path>') and req.authname != 'anonymous':
# Check for request type.
if req.method == 'POST':
# Ok, go pock for the new value now.
value = req.args.get('file', 'default_value')))
# Now go, process it, store it, even redirect away, if you're done.
# Fallback for Trac 0.11 compatibility included.
referer = req.args.get('referer') or req.get_header('Referer')
# Steer clear of requests going nowhere or loop to self
if referer is None or \
referer.startswith(str(req.abs_href()) + '/<your_path>'):
referer = req.abs_href()
req.redirect(referer)
# Still there, so that's the initial call or anonymous user, hey?
# So let's prepare information for displaying the template ...
data = dict(my_var='any_string_or_number')
# Take the env obj from self, if needed.
env = self.env
mod = MyOwnSecondaryModule(env)
if mod.can_do_something:
data['my_var'] = mod.do('better')
# Why not apply an own style?
add_stylesheet(req, 'your_plugin/most_famous_style.css')
return 'your_template.html', data
# ITemplateProvider methods
def get_htdocs_dirs(self):
"""Return the absolute path of a directory containing additional
static resources (such as images, style sheets, etc).
"""
return [('your_plugin', resource_filename('your_plugin_pkg_base_dir', 'htdocs'))]
def get_templates_dirs(self):
"""Return the absolute path of the directory containing the provided
Genshi templates.
"""
return [resource_filename('your_plugin_pkg_base_dir', 'templates')]
Questions on using various Trac extension point interfaces? See the authoritative wiki documentation on the subject as well!

Preserve plus signs from CGI input in 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.

get checkbox group values

This has driven me really bananas. It's so simple and easy and yet I can't figure out what's wrong with it.
I want to get my checkbox value populated in my controller (for testing purposes).
Here is my form.
<a href='#' name='submitForm'>submit the form</a>
//I have jquery attached to this tag and will submit the form when user clicks it
echo form_open('test/show');
echo form_checkbox('checkbox[]','value1');
echo form_checkbox('checkbox[]','value2');
echo form_checkbox('checkbox[]','value3');
echo form_checkbox('checkbox[]','value4');
echo "<input type='text' name='text1' value='ddd'>";
echo form_close();
//My controller test
public function show(){
$data1=$this->input->post('text1');
//I can get text1 value from input box
$data2=$this->input->post('checkbox');
//it keeps giving me undefined index 'checkbox'
$data3=$_POST['checkbox'];
//same error message
//WTH is going on here!!!!!
}
Please help. This thing drives me nuts! Thanks.
UPDATE:
Thanks for the help. To be more precisely, my submit button is a <a> tag and outside of form tag. It appear that I have to include <a> tag inside my form tag to make them works. Is that true?
A checkbox will not submit any data if it is unchecked as they're not considered successful (as per the w3c specification here)
If you actually tick the box and submit, it'll work - in fact it does, I've just tested it.
You need to wrap calls to $_POST in the isset() function.
if( isset( $_POST['checkbox'] ) ) {}
Calling $this->input->post('checkbox') shouldn't give you an undefined index error as the method deals with this eventuality. the Input::post() method returns false or the value of the checkbox.
Edit --
In response to your amendment to your question, you must use an element of type input with the type attribute set to submit in order to submit your form data without the use of Javascript etc. This button must be INSIDE the <form></form> which you are intending to submit.
<input type="submit" value="Submit">
The type="submit" causes the browser to send the data as submit event occurs. If you wish to use another element insider or outside of the form to do this you need to use Javascript. This however can be disabled on a per browser/user basis and isn't reliable as a result.
// Standard Javascript
<form name="myform"...
<a onclick="javascript:document.myform.submit();" href="javascript:void(0)">Submit</a>
// jQuery
$('#my-a-tag-submit-button').live( 'click', function() {
$('#my-form').submit();
}