Sinatra execute code before uploading - forms

I'm having a simple HTML form on my page that looks like this:
<form action="/" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="input" name="pin" />
<input type="submit" value="Upload" />
</form>
Now what I am trying to accomplish (with Sinatra) is to check if the PIN entered into the form field is correct:
post "/" do
if params[:pin] == "1234"
start_upload()
else
print_error_message()
end
end
Of course, I want the PIN to be checked before the file starts uploading. But that's my problem. Immediately after clicking the "Upload" button, the file upload starts until it is finished. Then the script checks to see if the PIN is valid.
Is there a way to do stuff before the file upload starts? And if not, what other ways of doing this are there?

Unless you use some Ajax and split up your request this won't work. You could have two forms, one that holds the pin and that authorizes the user. Once you enter a correct pin you send an asyn request to the server which will then reply with a positive or a negative answer. Depending on the response some javascript will then enable your file upload button so you can start uploading the file. What you should also do is setting a session for the user so that only an authorized user (via the pin) is allowed to send a form. If you check the Sinatra Readme you can find some information on how to do that.
That would be my solution.

Related

How does Chrome detect Credit Card fields?

In some forms, Chrome autofill prompts with Credit card autofill.
EDIT:Adding screenshot. This is not the same as browser autocomplete. You need not have entered the value in the same form before.
How should I write my HTML form so the browser detects these as Credit card fields and triggers this behavior?
An example of it working with a Stripe form would be ideal.
This question is pretty old but I have an updated answer for 2019!
You can now tell your browser which fields are for credit card info just by naming the <input> correctly.
The following answer is from my original answer from here: https://stackoverflow.com/a/41965106/1696153
Here's a link to the official current WHATWG HTML Standard for enabling autocomplete.
Google wrote a pretty nice guide for developing web applications that are friendly for mobile devices. They have a section on how to name the inputs on forms to easily use auto-fill. Eventhough it's written for mobile, this applies for both desktop and mobile!
How to Enable AutoComplete on your HTML forms
Here are some key points on how to enable autocomplete:
Use a <label> for all your <input> fields
Add a autocomplete attribute to your <input> tags and fill it in using this guide.
Name your name and autocomplete attributes correctly for all <input> tags
Example:
<label for="frmNameA">Name</label>
<input type="text" name="name" id="frmNameA"
placeholder="Full name" required autocomplete="name">
<label for="frmEmailA">Email</label>
<input type="email" name="email" id="frmEmailA"
placeholder="name#example.com" required autocomplete="email">
<!-- note that "emailC" will not be autocompleted -->
<label for="frmEmailC">Confirm Email</label>
<input type="email" name="emailC" id="frmEmailC"
placeholder="name#example.com" required autocomplete="email">
<label for="frmPhoneNumA">Phone</label>
<input type="tel" name="phone" id="frmPhoneNumA"
placeholder="+1-555-555-1212" required autocomplete="tel">
How to name your <input> tags
In order to trigger autocomplete, make sure you correctly name the name and autocomplete attributes in your <input> tags. This will automatically allow for autocomplete on forms. Make sure also to have a <label>! This information can also be found here.
Here's how to name your inputs:
Name
Use any of these for name: name fname mname lname
Use any of these for autocomplete:
name (for full name)
given-name (for first name)
additional-name (for middle name)
family-name (for last name)
Example: <input type="text" name="fname" autocomplete="given-name">
Email
Use any of these for name: email
Use any of these for autocomplete: email
Example: <input type="text" name="email" autocomplete="email">
Address
Use any of these for name: address city region province state zip zip2 postal country
Use any of these for autocomplete:
For one address input:
street-address
For two address inputs:
address-line1
address-line2
address-level1 (state or province)
address-level2 (city)
postal-code (zip code)
country
Phone
Use any of these for name: phone mobile country-code area-code exchange suffix ext
Use any of these for autocomplete: tel
Credit Card
Use any of these for name: ccname cardnumber cvc ccmonth ccyear exp-date card-type
Use any of these for autocomplete:
cc-name
cc-number
cc-csc
cc-exp-month
cc-exp-year
cc-exp
cc-type
Usernames
Use any of these for name: username
Use any of these for autocomplete: username
Passwords
Use any of these for name: password
Use any of these for autocomplete:
current-password (for sign-in forms)
new-password (for sign-up and password-change forms)
Resources
Current WHATWG HTML Standard for autocomplete.
"Create Amazing Forms" from Google. Seems to be updated almost daily. Excellent read.
"Help Users Checkout Faster with Autofill" from Google in 2015.
From this answer https://stackoverflow.com/a/9795126/292060, it looks like Chrome is either matching a regex pattern on the field name, or the form is explicitly using the x-autocompletetype attribute, like this (This example uses "somename" to avoid mixing issues matching on the name):
<input type="text" name="somename" x-autocompletetype="cc-number" />
Practically, you could do both, picking a name that matches, and the x-autocompletetype:
<input type="text" name="ccnum" x-autocompletetype="cc-number" />
Do you have a view-source of the input box in your screenshot? That would show if it's matching on the name or on the x-autocompletetype attribute.
The answer I linked to has several links for more information; I didn't repeat them here.
Some other comments:
I know Chrome pops a question whether to save the credit card information (I don't), but I don't know if it is popping that question regardless of how it detected it. That is, I'm not sure if Chrome will autocomplete separate fields of credit cards along with other fields, or if it needs to save the whole thing as a credit card.
Your question was how to do it, not whether to. But from the comment in your question, I agree that you might not want to autocomplete the credit card fields. Personally I find it disconcerting when it happens, even knowing it's local in my browser (I especially feel this way about the CVV, and get a surprising amount of resistance when I report it). However, there are posts that find it frustrating when a customer wants to use it, has Chrome set up with credit cards, and a website blocks it.
Thanks #goodeye for directing me to the correct answer.
To trigger the Credit Card autofill,
SSL must be enabled on your form
Most variants of standard credit card field names should work if SSL is enabled.
Here is a link to the regexes Chrome uses to trigger detection
As of 04-12-2022 (from the link above)
/////////////////////////////////////////////////////////////////////////////
// credit_card_field.cc
/////////////////////////////////////////////////////////////////////////////
// ... snipped ...
const char kCardNumberRe[] =
"card.?number|card.?#|card.?no|cc.?num|acct.?num"
"|nummer" // de-DE
"|credito|numero|número" // es
"|numéro" // fr-FR
"|カード番号" // ja-JP
"|Номер.*карты" // ru
"|信用卡号|信用卡号码" // zh-CN
"|信用卡卡號" // zh-TW
"|카드"; // ko-KR
Chrome is using autocomplete attribute in inputs for autofill. This will probably be used by other browsers in future if not yet.
autocomplete's actual use is to say whether autocomplete is enabled or not by specifying autocomplete="off". But chrome uses the same for autofill.
Autofill and autocomplete are different, so don't get confused.
Autofill is what chrome uses to fill up forms from what is stored in your autofill settings in your chrome browser.
Autocomplete is what all browsers use to remember what you may have entered previously in the same form by suggesting values as you type. So when you use autocomplete="off" on an input, browser stops suggesting these values.
Coming back to the solution, for autofill to work use cc-number for card number, cc-name for card holder name, cc-csc for cvc and cc-exp for card expiry date in your autocomplete attribute.
Here is a sample that will be compatible with chrome autofill:
<div>
<label for="frmNameCC">Name on card</label>
<input name="ccname" id="frmNameCC" required placeholder="Full Name" autocomplete="cc-name">
</div>
<div>
<label for="frmCCNum">Card Number</label>
<input name="cardnumber" id="frmCCNum" required autocomplete="cc-number">
</div>
<div>
<label for="frmCCCVC">CVC</label>
<input name="cvc" id="frmCCCVC" required autocomplete="cc-csc">
</div>
<div>
<label for="frmCCExp">Expiry</label>
<input name="cc-exp" id="frmCCExp" required placeholder="MM-YYYY" autocomplete="cc-exp">
</div>
If you have credit cards saved in your chrome browser right now, try clicking Run code snippet button above and you can see chrome autofill in action.
Source: https://developers.google.com/web/updates/2015/06/checkout-faster-with-autofill
Chrome also scans thru placeholders.
Example: <input placeholder='dd-mm-yyyy'/> will trigger it to become a credit card field.

How to add a contact form to a static web site?

I have a mostly "static" web site with no server-side code and just a little JavaScript. Now I would like to add a contact form. I do not care how I get the contact form data (so just writing this data to a text file in the server will be ok).
What is the simplest solution for this problem? How do people usually handle this?
I believe I can add some server-side code (PHP or something) to handle the form (and write the form data to a file, for instance) but I would prefer a client-side solution.
Use an external tool, they are commonly referred to as "formmailer". You basically submit the form to their server, and they send the form contents via mail to you.
If you don't want that, you have to do something server-sided: Storing data on the server, without having a server side program that accepts the data from the client, is just not possible.
You could install CouchDB and interface that from Javascript :) Everyone could use that then, too :)
The most easy PHP script that stores POST data on your harddisk:
<?php file_put_contents('/path/to/file', serialize($_POST) . "\n", FILE_APPEND); ?>
You can use Google Drive and create form with required fields. and embed code (which will be iframe) in your static web page.
You will be able to get submitted data in spreadsheet.
You can use qontacto . it is a free contact form you can add to any website. it forwards you the messages.
I set up the fwdform service for this exact need.
Just two simple steps to get your form forwarded to your email.
1.Register
Make an HTTP POST request to register your email.
$ curl --data "email=<your_email>" https://fwdform.herokuapp.com/register
Token: 780a8c9b-dc2d-4258-83af-4deefe446dee
2. Set up your form
<form action="https://fwdform.herokuapp.com/user/<token>" method="post">
Email: <input type="text" name="name"><br>
Name: <input type="text" name="email"><br>
Message: <textarea name="message" cols="40" rows="5"></textarea>
<input type="submit" value="Send Message">
</form>
With a couple of extra seconds you can spin up your own instance on Heroku.

generate querystring

I have created one jsp form which contains the username textfield. On the click of submit button it pass on to servlet and read parameter and display on the screen.
I want to generate a querystring of username with the url.
Can anyone tell me how can i do that??
The following example will add the username field in the querystring of the request URL.
<form action="servletURL">
<input type="text" name="username" />
<input type="submit" />
</form>
Note that there's no method. It defaults to GET already, which means that all form data is passed by URL.
If you still don't see the querystring in the request URL, then it means that your servlet is performing a redirect after submit.
response.sendRedirect("result.jsp");
The enduser will then see the redirected URL in browser address bar instead. If you don't include the querystring in the redirect URL, then the enduser will indeed not see it at all.
You should either be doing a forward() instead,
request.getRequestDispatcher("/WEB-INF/result.jsp").forward(request, response);
or append the query string yourself:
response.sendRedirect("result.jsp?" + request.getQueryString());

grails form redirect gives 404, but url mapping works

I feel like I've entered the Twilight Zone. I have a Grails form that redirects to a URL, but gives a 404. If I go directly to that exact URL, everything works fine (that is, the URL mappings are correct).
This is an example generated form tag:
<form action="/alm/contactRefresh/itemRefreshProcess/7070" method="post">
On submit, it redirects to:
http://localhost:8080/alm/contactRefresh/itemRefreshProcess/7070
But gives this error:
HTTP ERROR 404
Problem accessing /alm/contactRefresh/itemRefreshProcess/7070. Reason:
NOT_FOUND
Powered by Jetty://
But then if I just go directly to that same URL (by focusing the browser Location bar and pressing enter), the page renders just fine, though the form params are lost because it's just a GET now. I've also tried changing the form method to GET, and that doesn't work either (throws a 404).
I've done similar forms a zillion times before with no problems. I'm sure this is some stupid user error, but I seriously can't figure out what's wrong.
Thanks for any ideas!
So, I finally started ripping parts out of the form and found out that for some reason you can’t name a Grails checkbox starting with the word "action". It must be something related to the default params["action"] entry. Though my checkbox names were a concatenation of "action_" + an id.
Anyway, there was some kind pre-processing of the checkbox form params that was blowing up before making it to the controller, and somehow that translated to a 404 instead of an actual Exception.
Originally I had this:
<g:checkBox name="action_${serviceRefreshAction.id}" value="${true}" />
Which renders this:
<input type="hidden" name="_action_7196" /><input type="checkbox" name="action_7196" checked="checked" id="action_7196" />
I changed "action" to "myAction", like this:
<g:checkBox name="myAction_${serviceRefreshAction.id}" value="${true}" />
Which renders this:
<input type="hidden" name="_myAction_7206" /><input type="checkbox" name="myAction_7206" checked="checked" id="myAction_7206" />
And now everything works fine.
Five hours of my life down the drain.
But I guess I have to forgive Grails, for the all time it saves me on a daily basis normally. :o)

Python3 How would I log in Facebook using requests

<input type="text" class="inputtext" name="email" id="email" value="" tabindex="1"> is the email box
<input type="password" class="inputtext" name="pass" id="pass" tabindex="2"> is the password box
<input value="Connexion" tabindex="4" type="submit" id="u_0_v">
is the submit button
Now... I have this script running but I still can't manage to login ( I get to the same login page: facebook.com)
import requests
from bs4 import BeautifulSoup
body = {'email':'xxxx#hotmail.com','pass':'xxxxx',}
con = requests.post('https://www.facebook.com', data=body)
s = BeautifulSoup(con.content)
print (s)
Do I have to pass in the 'submit button' in the body{}. I thought I should include it but there is no name for the submit button so I don't know how to include it in the body{}. Thanks for the help
You always need to pay attention to any additional (hidden) fields, that are sent along credentials, and might be needed for any server processing.
That is the case for your example with runescape.com. When you use your browser to intercept data, that is normally being sent along with the form, you can modify the script in this manner:
import requests
from bs4 import BeautifulSoup
body = {'username':'xxxx#hotmail.com','password':'xxxxx','submit':'Login','mod':'www','dest':'community'}
con = requests.post('https://secure.runescape.com/m=weblogin/login.ws', data=body)
s = BeautifulSoup(con.content)
print(s)
You can see mod and dest parameters were needed to make the server processing function. As for the submit button, it is rarely checked for, but it is always safer to include it as well (as I did in this example).
The result is not 404 anymore, but the login will nevertheless fail, as there is Captcha in place to prevent automatic login.
As for Facebook, there are a lot of complicated supplementary fields, that would require a lot of reverse engineering to be done. I would strongly suggest to consider using the official Facebook Graph API (https://developers.facebook.com/docs/graph-api) if possible to accomplish what you need.