Grails doesn't update data object when a file is included in GSP form? - forms

I'm a Grails newbie, but I thought I was doing ok until I started messing about with file uploads. I'm trying to upload a file to S3 and store the file location in my data object.
My problem is I can upload a file fine, and I can update my data object fine, but for some crazy reason I can't do both at the same time!
Here's the simplified test code:
GSP Form:
<form method="post" url="[resource:fileBundleInstance, action:'test']" enctype="multipart/form-data">
<input type="file" name="bundle">
<g:actionSubmit class="save" action="test" value="Test" />
</form>
Controller:
#Transactional
def test(FileBundle fileBundleInstance) {
def file = request.getFile('bundle')
println file ? "found " + file.originalFilename : "no file"
fileBundleInstance.state = "test" // only works if no file input in form
redirect (action:'edit', id: fileBundleInstance.id)
}
So this code gets the file just fine, but doesn't update the state of the FileBundleInstance. However, if I comment out the file upload form element:
<form method="post" url="[resource:fileBundleInstance, action:'test']" enctype="multipart/form-data">
<!--input type="file" name="bundle"-->
<g:actionSubmit class="save" action="test" value="Test" />
</form>
... suddenly the state gets updated fine (but of course I have no file)!
I suspect I'm fundamentally misunderstanding something here about how GSP forms work in grails - can anyone set me right?

Oops... embarrassingly this is my mistake :-/.
It turns out that the name I was using for my file, 'bundle', was also the name of a field in my data object. Grails was throwing a data exception, and I didn't have good error handling (newbie, remember :-) ).
When I add lines:
fileBundleInstance.save();
fileBundleInstance.errors.allErrors.each {error ->
println error.toString()}
I see my nice shiny error - and if I change the name from 'bundle' to 'myfile' everything works. Oops.

Related

MODX: I cannot send files using FormIt

I am trying to send a file from my form, but I receive only the name of the file. According to this article it seems that I have done the things properly, but in the end I get only the file's name.
<input type="file" name="files" value="[[!+fi.files]]"/> // form's field
[[+files]] // calling in &emailTpl
Perhaps, I have to do some transformation, but I have no idea...
There is a chunk including
[[!FormIt?
&hooks=`recaptchav2,spam,email`
&emailTo=`[[#1.mailto]]`
&emailFrom=`[[#1.mailfrom]]`
&emailSubject=`Заявка на расчет с сайта [[++site_url]]`
&emailTpl=`401-calculate-project-tpl`
&successMessage=`1`
&clearFieldsOnSuccess=`1`
&errTpl=`[[+error]]`
&validate=`email-3:required`
]]
There was a trouble in a version of FormIt. I should update it to 3.0.3, so I envolved this trouble. Congratulation.

testing for html/script injection and getting kicked from a server

In researching an idea I came across a good YouTube video on security (with nodejs) which covered a lot more than the usual SQL injection. One such was simple script and html injection through html encoding. javascript buffers etc.
In researching this for a project I'm working on I came across this script from the php.net documentation website:
<?php
if ($_POST) {
echo '<pre>';
echo htmlspecialchars(print_r($_POST, true));
echo '</pre>';
}
?>
<form action="" method="post">
Name: <input type="text" name="personal[name]" /><br />
Email: <input type="text" name="personal[email]" /><br />
Beer: <br />
<select multiple name="beer[]">
<option value="warthog">Warthog</option>
<option value="guinness">Guinness</option>
<option value="stuttgarter">Stuttgarter Schwabenbräu</option>
</select><br />
<input type="submit" value="submit me!" />
</form>
Looking at the code, I believed the html injection was safe and as I didn't have somewhere to test this script out, I just uploaded it to a hosting domain I have and played with it remotely. When I tried a basic alert injection:
<script>alert("test");</script>
I got an error from the server (a 403 Forbidden). I thought I malformed the html so I tried some minor variations and before I knew it I was banned from my server :D (I was able to reset it, that's not the concern).
Tonight I deployed a VM with apache and php and started playing with it, and when I used the same code, I actually saw what I'd originally expected to see. The array output is presented as expected because of the htmlspecialchars.
Array
(
[personal] => Array
(
[name] => <b>bold</bold>
[email] => <script>alert("test");</script>
)
[beer] => Array
(
[0] => stuttgarter
)
)
What I'd like to know is:
1. Does the browser do some manipulation that nullifies the script tags since there's nothing in the form that does that? My guess is that nothing is an issue until it's attempted to be parsed by the page on form submission. Correct?
2. When I ran it locally the output was as expected (ie, no alert box and correct parsing) which infers that the values are somewhat "safe" until php attempts to parse them via the print_r. If I remove the htmlspecialchars the page fails to load ERR_BLOCKED_BY_XSS_AUDITOR (so that's good). If the original page never parses the raw code, why would the remote server ban my IP if it's correctly escaped within the output code? Again, I'm guessing, but would it be the host is just preemptively trying to prevent attacks and processing all $_POST vars for XSS?

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.

Creating a Wordpress Plugin - Form Submission Fails when passed value of 00x00

I am writing a pretty simple plugin. I notice that when I submit a form with a text field with a value that is 2 or more digits followed by an x then followed by two or more digits that the form doesn't submit it redirects me to the index page. I get an apache error log message : [error] [client ::1] script '/Applications/MAMP/htdocs/index.php' not found or unable to stat but that is all of the info I can find.
To narrow down the problem, I made a super basic form that runs in the admin section with only one field. When it is submitted it calls a javascript alert to show the $_POST value. This works all day long UNTIL I enter 00x00 or any digits really with an x between them, 123x123, 999999999x999999999 etc...
In it's intended use this field would have a dimension like 120x120 but for what ever reason the x is causing something weird to happen. Any ideas?
Here is the stripped down basic example, added to an admin menu page
<?php
if(isset($_POST['update'])){
echo '<script type="text/javascript">', 'alert("' . $_POST['image_url'] . '");', '</script>';
}
?>
<form method="post" action="<?php echo htmlspecialchars($_SERVER['REQUEST_URI']);?>">
<input name="image_url" id="image_url" type="text" maxlength="200" value="00x00"/>
<input name="update" type="submit" id="update" value="Submit" />
</form>

How to change a form's action in Lift

I am building a Lift application, where one of the pages is based on the "File Upload" example from the Lift demo at: http://demo.liftweb.net/file_upload.
If you look at the source code for that page... you see that there is a Lift "snippet" tag, surrounding two "choose" tags:
<lift:snippet type="misc:upload" form="post" multipart="true">
<choose:post>
<p>
File name: <ul:file_name></ul:file_name><br >
MIME Type: <ul:mime_type></ul:mime_type><br >
File length: <ul:length></ul:length><br >
MD5 Hash: <ul:md5></ul:md5><br >
</p>
</choose:post>
<choose:get>
Select a file to upload: <ul:file_upload></ul:file_upload><br >
<input type="submit" value="Upload File">
</choose:get>
</lift:snippet>
The idea is that when a user hits the page for the first time (i.e. a GET request), then Lift will show the form for uploading a file. When the user submits the form (i.e. a POST request to the same page), then Lift instead displays the outcome of the file being processed.
With my application, the new wrinkle is that my "results" POST view needs to also contain a form. I want to provide a text input for the user to enter an email address, and a submit button that when pressed will email information about the processed file:
...
<choose:post>
<p>
File name: <ul:file_name></ul:file_name><br >
MIME Type: <ul:mime_type></ul:mime_type><br >
File length: <ul:length></ul:length><br >
MD5 Hash: <ul:md5></ul:md5><br >
</p>
<!-- BEGIN NEW STUFF -->
Output: <br/>
<textarea rows="30" cols="100"><ul:output></ul:output></textarea>
<br/><br/>
Email the above output to this email address:<br/>
<ul:email/><br/>
<input type="submit" value="Email"/>
<!-- END NEW STUFF -->
</choose:post>
...
However, both the GET and POST versions of this page are wrapped by the same Lift-generated form, which has its "action" set to the same snippet in both cases. How can I change this such that in the POST version, the form's action changes to a different snippet?
In a typical web framework, I would approach something like this with an "onclick" event and two basic lines of JavaScript. However, I haven't even begun to wrap my mind around Lift's... err, interesting notions about writing JavaScript in Scala. Maybe I need to go down that route, or maybe there's a better approach altogether.
First, I will suggest you use Lift's new designer friendly CSS binding instead of the custom XHTML tag.
And one thing you should remember when you're using Lift's snippet, is that it is recursive, you could put an lift snippet inside another snippet's HTML block.
For example, if you wish there is another form after POST, then just put it into the block.
<choose:post>
<p>
File name: <ul:file_name></ul:file_name><br >
MIME Type: <ul:mime_type></ul:mime_type><br >
File length: <ul:length></ul:length><br >
MD5 Hash: <ul:md5></ul:md5><br >
</p>
<!--
The following is same as <lift:snippet type="EMailForm" form="post" multipart="true">
-->
<form action="" method="post" data-lift="EMailForm">
<input type="text" name="email"/>
<input type="submit" />
</form>
</choose:post>
Then deal with the email form action at snippet class EMailForm.
Finally, you may pass the filename / minetype and other information by using hidden form element or SessionVar.
I agree with Brian, use Lift's new designer friendly CSS binding.
Use two separate forms, one for the file upload and one for the submitting the email. Use S.seeOther to redirect the user to the second form when the first has finished processing.
I also prefer the new 'data-lift' HTML attribute.
File upload HTML:
<div data-lift="uploadSnippet?form=post">
<input type="file" id="filename" />
<input type="submit" id="submit" />
</div
File upload snippet:
class uploadSnippet {
def processUpload = {
// do your processing
....
if (success)
S.seeOther("/getemail")
// if processing fails, just allow this method to exit to re-render your
// file upload form
}
def render = {
"#filename" #> SHtml.fileUpload(...) &
"#submit" #> SHtml.submit("Upload", processUpload _ )
}
}
GetEmail HTML:
<div data-lift="getEmailSnippet?form=post">
<input type="text" id="email" />
<input type="submit" id="submit" />
</div
Get Email Snippet:
class getEmailSnippet {
def processSubmit = {
....
}
def render = {
"#email" #> SHtml.text(...) &
"#submit" #> SHtml.submit("Upload", processSubmit _ )
}
There's a bit more on form processing in my blog post on using RequestVar's here:
http://tech.damianhelme.com/understanding-lifts-requestvars
Let me know if you want more detail.
Hope that's useful
Cheers
Damian
If somebody comes up with a more elegant (or "Lift-y") approach within the next few days, then I'll accept their answer. However, I came up with a workaround approach on my own.
I kept the current layout, where the view has a GET block and a POST block both submitting to the same snippet function. The snippet function still has an if-else block, handling each request differently depending on whether it's a GET or POST.
However, now I also have a secondary if-else block inside of the POST's block. This inner if-else looks at the name of the submit button that was clicked. If the submit button was the one for uploading a file, then the snippet handles the uploading and processing of the file. Otherwise, if it was the send email submit button shown after the first POST, then the snippet processes the sending of the email.
Not particularly glamorous, but it works just fine.