there is a website called https://www.guidgenerator.com/online-guid-generator.aspx which generates a global unique identifier. I'm trying to use perl's Mechanize to post to the site to pull that guid. I realize that this is based on javascript but was wondering if I could issue the proper post to pull the number. I trace it from my browser and I've got the headers all in the request but the returned html doesn't contain the guid.
This is from a successful run:
<textarea name="txtResults" rows="2" cols="20" id="txtResults" style="font-family:Courier New,Courier,monospace;font-size:Larger;font-weight:bold;height:152px;width:421px;">qk5DF22bhkm4C2AwZ5OcZw==</textarea>
and this is from my script:
<textarea name="txtResults" rows="2" cols="20" id="txtResults" style="font-family:Courier New,Courier,monospace;font-size:Larger;font-weight:bold;height:152px;width:421px;"></textarea>
This is the form within the page:
In my script I dump out the form and the input fields required with the following:
my #forms = $mech->forms;
foreach my $form (#forms) {
my #inputfields = $form->param;
print Dumper \#inputfields;
}
resulting in
$VAR1 = [
'__EVENTTARGET',
'__EVENTARGUMENT',
'__LASTFOCUS',
'__VIEWSTATE',
'__VIEWSTATEGENERATOR',
'__EVENTVALIDATION',
'txtCount',
'chkUppercase',
'chkBrackets',
'chkHypens',
'chkBase64',
'chkRFC7515',
'chkURL',
'LocalTimestampValue',
'btnGenerate',
'txtResults'
];
and this is the post
my $mainpage = "https://www.guidgenerator.com/online-guid-generator.aspx";
$mech->post( "$mainpage",
fields => {
'txtCount' => "1",
'chkBase64' => "on",
'LocalTimestampValue' => "Date%28%29.getTime%28%29",
'btnGenerate' => "Generate+some+GUIDs%21",
'txtResults' => "",
'__EVENTTARGET' => 'on',
'__EVENTARGUMENT', => 'on',
'__LASTFOCUS', => 'on',
'__VIEWSTATEGENERATOR' => "247C709F",
'__VIEWSTATE' => 'on',
'__EVENTVALIDATION' => 'on',
'chkUppercase' => 'off',
'chkBrackets' => 'off',
'chkHypens' => 'off',
'chkRFC7515' => 'off',
'chkURL' => 'off',
},
);
When I do the trace on the website I get the headers but there is another tab called Payload. That contains most of the fields listed above. I try to input these fields into the POST but not sure if I should be doing this differently or it doesn't matter because its javascript?
I know this is a lot of information. I'm not even sure that perl's mechanize can pull this information. Any help would be appreciated. Please let me know any other data you want me to post here.
You can use Mech's built-in stuff to do this. There is no need to submit any extra fields or headers.
use strict;
use warnings;
use feature 'say';
use WWW::Mechanize;
my $mech = WWW::Mechanize->new;
$mech->get('https://www.guidgenerator.com/online-guid-generator.aspx');
$mech->field( txtCount => 10 );
$mech->click;
say $mech->value('txtResults');
This will output something like:
$ perl mech.pl
211b3cad1665483ca303360bdbda0c61
ecc3348d83cb4bb5bdcb11c6148c5ae1
0a3f2fe5748946a1888a4a5bde8ef2e6
acb26deb9fda4411aa64638cdd1ec5f1
2afe609c355b4a10b6a0ae8c74d3aef1
30fd89ab170147cfb24f131346a203e3
2301d258e1d045aa8f0682f2ea14464c
f064507ca3e14a4eb860b0a30ba096ed
9a42b15d5c79420c921dcc07c306459b
5bea2e345f75453caaf795681963866a
The crux here was that you cannot use $mech->submit as that wouldn't submit the value of the submit button. That's a bit annoying. So instead, you have to use $mech->click, which pretends the default form's default submit button was clicked, hence submitting that value as well. That's just how buttons work on forms, and in this case the backend checks the value to see which one was clicked.
You can then use $mech->value to get the field value out. You'd probably want to split it to process it further.
The JavaScript in this page is actually completely irrelevant to the functionality. All it does is save and restore the settings you've chosen in a cookie, so that when you come back the same checkboxes will be ticked. That's nice, but nowadays probably better done with local storage on the frontend side. However you don't have to deal with the JS at all to crawl this page. The main functionality is backend side.
You might also be interested in $mech->dump_forms, which is a nice debugging aid that prints out all the forms with fields and values. Another good debugging aid when working with Mech (or any LWP based class) is LWP::ConsoleLogger::Everywhere. That's what I used to compare my program's request with my browser's one to find the missing button form field.
Disclaimer: I am a maintainer of WWW::Mechanize and I wrote LWP::ConsoleLogger::Everywhere.
Related
I have html and css code for a basic quiz template. I want to give the user the ability to make their own custom quiz.
Example: I have created my own math quizzes, science quizzes, etc, that the user can take. I am looking for the ability that Users can make their own personal quiz.
You don't append users input to your code. You should have your quiz as a data and let the user update the data by adding their quiz.
The structure of a form looks like this:
<form method = 'post' action='./handleSubmission/'>
<label>Question 1: </label>
<input type='text' class='question' name='question1'>
<label>Answer 1: </label>
<input type='text' class='answer' name='answer2'>
<label>Question 2: </label>
<input type='text' class='question' name='question2'>
<label>Answer 2: </label>
<input type='text' class='answer' name='answer2'>
<button>Submit</button>
</form>
(You can find all the different input types here. You might want another type for multiple choice questions.
When the user clicks on submit, the default behaviour is that the content of the form will be sent as an http request to the action url. if you set post as method, the method will be POST. If you set get as method, the method will be GET.
Now, in order to do something useful with it, there needs to be a server-side script at './handleSubmission/' or whatever url you put in here, that can read the sent data and upload it to some place where you store the data for your quizzes. This can be either a database or a repository containing some files.
I'd go for json files. Because json files can very easily be decoded and used in any web scripting language.
In PHP for example you'd get the content of the form through a special array called $_GET (or $_POST depending on the method).
You'd then have access to 'question1' with $_GET['question1'].
You'd then have to find a way to put that data into a json file.
To use the content of the json files, you can either use a backend script or a frontend script like javascript.
Are you already using a scripting language for the backend such as PHP or Python? Or do you focus on frontend?
If you want to focus on javascript and frontend, this is the alternative:
<form>
//...
<button id='btn-submit'>Submit</button>
</form>
As you can see, i ommited action and method because in this alternative we don't want to send the form to the server. What we'll do is, when the button is clicked, we'll capture the content of the form without refreshing the page, and then send it a Backend-as-a-service like Google Firebase.
const submitButton = document.querySelector('#btn-submit');
submitButton.addEventListener('click', (e) => {
/* important! prevents the default behaviour which is to submit the form */
e.preventDefault();
const data = [];
/* do stuff here to retrieve the data from form like: */
const questionInputs = document.querySelector('.question');
const answerInputs = document.querySelector('.answer');
for(let key in questionInputs){
data[key] = {
question: questionInputs[key].value;
answer: answerInputs[key].value;
}
}
sendToFirebase(data);
});
You'd then have to write the sendToFirebase function.
Firebase requires making an account, starting a project by giving a name etc. Then it gives you the code to put in your app and you can read the documentation about how to upload data to the Realtime Database.
I strongly prefer the first option however. Because i think in this case the Firebase Realtime Database would be a bit cumbersome to use compared to just setting up a small backend script that generates json files.
I have a simple web application so far that is written in php using the laravel framework.
My question is in the title: if I have a web form that has multiple SELECT elements, could somebody use javascript to append new options to that `SELECT' element and submit the form (therefore saving items that weren't suppose to options in my database?)?
As the comments have suggested, it is certainly possible to append options, or even change the values of what is being submitted.
To prevent this, you can use server side validation to check what is being passed in. Laravel provides validation out of the box that makes doing this a breeze.
The validation rule you want to use is in:
The field under validation must be included in the given list of values.
Inside your controller function that receives the request, just add this at the top to validate the request before you pass it in to your database:
$validator = Validator::make($request->all(), [
'select_input' => 'in:foo,bar',
], [
'select_input.in' => 'The option selected was not valid!',
]);
if ($validator->fails()) {
return Redirect::back()
->withErrors($validator)
->withInput();
}
You would need to add these to the top of your controller:
use Validator;
use Input;
use Redirect;
There's plenty more validation that you can utilise, just read the docs.
I'm trying to have a search option for users to fill in and search multiple tables for orders, commissions, etc without having to reload the page. Never used AJAX before so if anyone could point out where I'm going wrong or help me get this working it would be very much appreciated! Right now when I click on the submit button nothing happens except for getting an 500 (Internal Server Error) message.
Here is my View (home):
<div class="large-6 columns">
{{Form::open( array('route' => 'search', 'method' => 'post', 'id' => 'search_form'))}}
{{ Form::select('search_table',
array(
'select' => 'Search...',
'commissions' => 'Search commissions',
'estimates' => 'Search estimates',
'orders' => 'Search orders',
'warranties' => 'Search warranties',
), null, array('id' => 'search_table')) }}
<div class="search_box" id="search_column_div">
<!-- Search_column select goes here -->
</div>
<div id="search_input_div">
<!-- Search_input text field goes here -->
</div>
{{ Form::submit('Search', array('id' => 'search_button','class' => 'button expand radius search_button no_display'))}}
{{ Form::close() }}
</div>
<div id="search_results_div">
</div>
</div>
Because the search has a lot of variables but I didn't want to make it take up a lot of space I have JS insert the next part of the query based on their previous selection. So they will start with the ability to pick a table to search, then a column, then they will have an input field to write what exactly they are searching for.
JS (where my problem probably is):
$(document).ready(function($){
$('#search_form').on('submit', function(){
$.post(
$(this).prop('action'),{
"search_table": $('#search_table').val(),
"search_column": $('#search_column').val(),
"search_input": $('#search_input').val(),
},
function(data){
$('#search_results_div').html(data);
},
'json'
);
return false;
});
});
Controller:
public function searchPost(){
$search_table = Input::get('search_table');
$search_column = Input::get('search_column');
$search_input = Input::get('search_input');
$search = DB::table($search_table)->where($search_column, 'LIKE', "%{$search_input}%")->get();
return $search;
}
And the Route:
/*Search Page for Ajax*/
Route::post('/search', array(
'as' => 'search',
'uses' => 'HomeController#searchPost'
));
Thanks again for your time and help! Please feel free to make suggestions for best practices!
Well, for a start, you're didn't say what the problem was, but just looking at that code, you're setting HomeController#searchPost as the action for your post method, but your search method is actually HomeController#search.
You're also using the wrong variables. You're passing in search_table, search_column and search_input as the keys in your Javascript, but you're trying to read table_searched, column_searched and input_searched - so all those variables will always be nulls in your server-side code.
Your $search query will also always fail. '%LIKE%' is not valid SQL - the % need to go around the search term. What you really want is:
$search = DB::table($search_table)->where($search_column, 'LIKE', "%{$search_input}%")->get();
Try fixing all of those and see if it deals with your problem :)
It looks like there are several issues. I see that you've already made some changes but there are some more problems you need to fix. Your AJAX request is using a POST request but your route is listening for a GET request. Even once that's fixed, you'll need to included some sort of error handling or validation for the controller and database query before returning the result. After that you need to look at how you're handling what is being returned by the AJAX request.
The 500 error you're getting means that there's a problem with your server-side code. More than likely something isn't "wired-up" correctly. If you're having troubles getting a detailed error report, use "console.log()" to output what's returned via AJAX to the dev console. From there you can debug the problem.
1.is there a way to do form_set_error in client side so if there is error in javascript validate it will set error and wont let user process the other steps? js can be disabled so i want to take extra caution...
where is a complete list of drupal javascript function reference like Drupal.t and stuff?
how can i change the error messages of form set error (the default errors like { fieldname... field is required } ?
how can i do errors that will show below/above/inline the field ?
JavaScript in Drupal, Covers the Drupal JavaScript API, AHAH forms, and the kind of stuff your looking for. The Quick start Guide is pretty good.
As for validation, you're right, Javascript can be turned off. JavaScript validation is mostly done for usability, since the user doesn't have to wait to POST his form in order to receive an error message. JavaScript lets him know in real time if for example, his password is too weak, or email invalid, before submitting the form.
JavaScript validation however is not good for security. That's where you will need to do server-side validation. form_set_error will take care of the server-side validation.
So if you have a form that looks like:
function form_foo($form_state) {
$form['foo'] = array(
'#type' => 'textfield',
'#title' => t('bar'),
'#default_value' => $object['foo'],
'#size' => 60,
'#maxlength' => 64,
'#description' => t('baz'),
);
return $form;
}
The server-side validation would look like:
function form_foo_validate($form, &$form_state) {
if (empty($form_state['values']['foo'])) {
form_set_error('foo', t('Foo cannot be empty.'));
}
}
If the bar textfield in the form is indeed empty, when the user submits the form bar will be highlighted, the 'Foo cannot be empty' error message will appear, and the form _submit hook won't be called.
For JavaScript functionality, the Overview of Drupal JavaScript API document has most of the information you will need.
I want to know how can I validate using Javascript that if user has entered any username at the time of creating an account is already present in database and ask user to type any other username?
Attach listener for blur event for <input /> element.
Using AJAX send request to the server (with field value as parameter)
On the server side check whether given username is already in use or not
Based on server's response display (or not) This username is already in use message
jQuery (I'm too lazy for pure JS) + PHP sample code:
<form ...>
...
<input type="text" name="username" id="input-username" />
<p class="error"></p>
...
$("#input-username").blur(function() {
$.post("/check-username.php", { username: $(this).val() }, function(data) {
if ("0" == data) { /* username in use */
$(this).next("p").text("This username is already in use.</p>");
} else { /* username is fine */
$(this).next("p").empty();
}
});
});
<?php
$username = $_POST['username'];
// check whether given username exists in database
$usernameExists = ...;
echo $usernameExists ? '0' : '1'; // 0 if exists, 1 if not.
The answer is AJAX. If you must validate against a database, you need to make a call to the server. The only way to do that (EDIT: properly) without reloading the page is AJAX. How you implement it will depend upon what javascript libraries you are using, if any, and what your server is like. I suggest you do a little searching and reading on it - this is a pretty common use case.
Personally, I would use a JQuery validation plugin just to make things simple.
http://bassistance.de/jquery-plugins/jquery-plugin-validation/
But in general it would consist of a small AJAX request to a server (ie. JSON object) with the username and do a 'search' in your database and return either true/false after the user hits enter or tab in the textfield (attach an event listener). Then within your callback response alter the DOM elements of your choice to indicate to your users whether the account name is already present in the database or not.
Ajax might not be the only solution, since usernames are generally public. A simple way is to just have an RDF/XML document at some point (which just updates with every new user added) which has a list of all the users on your site that you can easily just traverse with Javascript DOM to see if that user is already in use. You also make them pay computational power, not you, depending on how nice you are it's an advantage or a dis-advantage.