Selectize.js doesn't read HTML entities correctly - php

I'm working with Selectize.js currently and am stuck on a problem relating to HTML entities not displaying correctly in Selectize fields, and therefore failing checks after submission. We use PHP on the backend and run every Selectize option through htmlspecialchars($option);. We then export the PHP array to a JSON array in preparation for adding it to the Selectize script/field.
//Array of options
$options = getOptions();
$optionsArray = array();
foreach($options as $item) {
$optionsArray[] = array('text' => htmlspecialchars($item), 'value' => htmlspecialchars($item));
}
//Create html script to run selectize initialization
$htmlcode = "<script>";
...
$htmlcode .= "var optionList = " . json_encode($"optionsArray") . ";";
$htmlcode .= "$('#selector').selectize({ options: optionList });";
...
$htmlcode .= "</script>";
The point here is to protect against malicious entries by encoding. This typically wouldn't be a problem, as browsers will detect the entities and convert them automatically (ie. will detect & and display as &. However, that is NOT happening inside the selectize. As you can see in the image below, outputting an option with an ampersand displays correctly on the page, but it doesn't display accurately in the Selectize field.
Example:
The problem then becomes larger, as we are comparing the selected item against the database after submission, to ensure that the selected entry actually exists. If the entry testOption&stuff actually exists, the form submission will check testOption&stuff against it, and will obviously fail the check.
//For simplicity, checking against static option
var $selectedOption = $_POST["options"];
if ($selectedOption == "testOption&stuff") {
//Do success
} else {
//Do failure
}
How can I resolve this and make it so that the Selectize field will store and display the correct entry (ie. &)?
Thanks!

Related

Data is UTF-8, Ajax is returning some characters incorrectly

I have spent a lot of time searching the web and seeing a lot of similar answers, but cannot find anything that works for my situation.
I spent some time converting my MySQL database to UTF-8 from latin1 (the default). I emptied the tables (truncate), and re-imported the data from a text file. I have set the headers for my pages to use the meta tag to UTF-8:
<meta http-equiv="Content-Type" content="text/html" charset="UTF-8" />
And that's being used everywhere. When I read data via PHP and output it into forms, and such, the data appears correctly, text like: Königstadt appear as one might hope. Saving them (update set ...) they seem to be okay, because when I re-read them from the data the display in the form is correct. (The display in PHP Admin shows "Königstadt", which is weird, but when I read the data it seems to be correct ... -- I am hoping this is some oddity of PHPAdmin)
Where everything seems to be falling down on me is my Ajax code, when I retrieve data via PHP using Ajax. The following is a relatively simple routine that calls a PHP program to generate the option tags for an SELECT:
function get_branches()
{
// numeric values that need to be passed to the
// routine (so we show the correct item selected)
var region = document.getElementById("search_region").value;
// the code in load_branches needs this, but ...
var branch = document.getElementById("search_branch").value;
$.ajax
({
type: "POST",
url: "<?php echo $Roster_html_RootPath; ?>lookups/load_branches.php",
data: {
'region' : region,
'local_branch' : branch
},
//cache: false,
success: function(data)
{
// load contents of DIV tag with id of branchoptions:
$("#branch_options").html(data);
} // end success
}); // end ajax call
}; // end function get_branches()
}); // end document.ready ...
Most of the records returned are fine. However the one shown above (Königstadt) looks like: Königstadt in the HTML Select that is returned.
I have been trying to find a solution, such as setting contentType for Ajax, here are things I have tried:
contentType: "application/x-www-form-urlencoded;charset=utf-8",
This one doesn't seem to make any difference at all. Nothing changes.
contentType: "application/text; charset=utf-8",
(or application/json)
This kills the values being passed to the PHP file -- the data array doesn't seem to get there, because I get errors from PHP:
Notice: Undefined index: region in C:\xampp\htdocs\Heralds\Roster\lookups\load_branches.php on line 32
Notice: Undefined index: local_branch in C:\xampp\htdocs\Heralds\Roster\lookups\load_branches.php on line 33
I am at a complete loss how to return the values correctly. I need versions for both text or html (where I return an html table or the option tags as here), but I also need to use the json array for some of my code to return the values correctly. None of them seem to work properly with UTF-8 encoded data. I have been working on this for some time now, and am very frustrated. The explanations I am seeing are not working or in some cases not making sense ...
PHP lookups/load_branches.php
<?php
// if session has not started:
session_start();
// load some basic configuration, including relative paths
// and variables needed ...
include_once( "../includes/configuration.php" );
// data connection
include_once( $Roster_RootPath . "includes/connect.php");
// values from Ajax code:
$region = $_POST["region"];
$local_branch = $_POST["local_branch"];
// open the roster_branches table and get list
if( $region > 0 ) // check only needed for find_by_branch.php
{
$branch_statement = "select * from roster_branches where region=" . $region . " order by local";
}
else
{
$branch_statement = "select * from roster_branches order by local";
}
// first, get the data from the table:
$branch_result = mysqli_query( $connect, $branch_statement );
if( !$branch_result )
{
$out = "";
$out .= "<div class='alert alert-danger'>";
$out .= "<p><b>Error in SQL statement ...</b><br />";
$errornum = mysqli_errno( $connect );
$out .= "MySQL Error Number: " . $errornum . "<br />";
$out .= "MySQL Error: " . mysqli_error( $connect ) . "<br />";
$out .= "SQL Statement: " . $branch_statement . "</p>";
$out .= "</div>";
echo $out;
die;
}
else
{
$out = "";
// create select:
$out = "<select class='form-control' id='local_branch' name='local_branch'>\n";
// need the blank option:
$out .= " <option value=0 selected></option>\n";
while( $branch_row = mysqli_fetch_array( $branch_result ) )
{
$id = $branch_row["rb_id"];
$local = $branch_row["local"];
$selected = "";
if( $local_branch == $id )
{
$selected = " selected";
}
$out .= "<option value=" . $id . $selected . ">" . $local . "</option> \n";
}
$out .= "</select>\n";
echo $out;
} // we have something
?>
my MySQL database to UTF-8 from latin1 (the default).
1) I used "utf8_unicode_ci". 2) I have no idea what "multibyte safe functions" you're talking about. I use mysqli_real_escape_string() when reading data from $_POST, and the usual mysqli_query() and so on functions
This is the cause of your issue.
There are 3 main places to work to correct this:
1)
You need to enable true UTF-8 (4-byte) in MySQL so that data stored in your SQL is stored as the correct UTF-8 characters. by universally using collations and character sets with the utf8mb4_ prefix.
2)
To ensure data from your application/PHP is saved correctly you then need to ensure that the data is passed to MySQL as UTF-8 4-byte characters by setting the connection character set to full (4-byte) UTF-8 in your PHP:
$mysqliObject->set_charset('utf8mb4'); // object oriented style
mysqli_set_charset($connect, 'utf8mb4'); // procedural code style
3)
Finally; you need to ensure that any processing PHP does with the resulting data is multi-byte aware; by using the mbstring set of functions.
Most notably:
mb_http_output() — Detect and convert HTTP output character encoding
mb_internal_encoding() — Set PHP's internal character encoding
So your top of each PHP page should look like this before any browser output)
mb_internal_encoding('UTF-8');
mb_http_output('UTF-8');
Then if you do anything with str_<whatever> functions (and some others) you know it won't break you strings before they're output to the browser (ajx in this case).
If you can't use mbstring functions for any reason then check out here [how to install them](http://www.knowledgebase-script.com/kb/article/how-to-enable-mbstring-in-php-46.html
).
Please also review this excellent Q&A has helped you at all?
Further reading about solving the MySQL side of things can be found here.
ö is "Mojibake" for ö. See "Mojibake" in Trouble with UTF-8 characters; what I see is not what I stored .
But the real problem probably happen when you converted from latin1.
The tables needed to be converted via ALTER TABLE .. CONVERT TO CHARACTER SET utf8mb4. Any other technique is likely to make a mess.
Any connection to MySQL needs to be specify utf8mb4.

simple html dom extracting table by its id

I'm using simple html dom in php to extract a table depending on its id. I have done this without any issues when the id doesn't involve any characters like hyphens(-). I suspect it is due to a hyphen because I used the same code with an id with no hyphens and no trouble receiving the data. The data I want to extract is also in a tab that is hidden, does this effect the process?
Here is my code
<?php
include('simple_html_dom.php');
//Insert the url you want to extract data from
$html = file_get_html('http://espnfc.com/team/_/id/359/arsenal?cc=5739');
$i = 0;
$dataInTable = true;
while($dataInTable){
if($html->find('div[id=ui-tabs-1] table tbody', 0)->children(0)->children($i)){
for($j=0;$j<3;$j++){
if($html->find('div[id=ui-tabs-1] table tbody', 0)->children(0)->children($i)->children($j)){
$gk[] = $html->find('div[id=ui-tabs-1] table tbody', 0)->children(0)->children($i)->children($j)->plaintext;
}else{
$dataInTable = false;
}
}
//else if nothing is in the next cell return false.
}else{
$dataInTable = false;
}
$i+=2;
}
var_dump($gk);
?>
Here is the HTML content
When you take a look at the source(not via dev-tools, use browser->viewsource) of http://espnfc.com/team/_/id/359/arsenal?cc=5739 you'll not see anything with the ID ui-tabs-1
This element has been created via javascript(I guess jQueryUI-tabs)
simple_html_dom parses HTML but did not evaluate javascript, so the answer is:
You can't select this element

Mail Dynamic Table with Forms via PHP

I have an order form (table) that I need to be sent to an email address.
I understand the basics of how to send an email in PHP, but not the specifics
of this situation (taking the information of the cookie array + form elements and put them in body of the PHP mailer)
I am using this link's answer to store the order form as an array in a cookie
Then I use this javascript to create the table in HTML, inside the #catalog div. The important part is the for loop that makes the table. Using list.items(); one can list the "cookie array" as an array
function loopArrayMail() {
if ($.cookie('productWishlist') == null) {
html = ""; $('#catalog').html(html);
} else {
var cookie = $.cookie("productWishlist"); var items = cookie ? cookie.split(/,/) : new Array();
var html = "<table><tr><th>Product</th><th># to order</th></tr>";
for(var i=0;i<items.length;i++){ html += "<tr><td width='450'>"+items[i]+"</td><td><input type='text' name='numberOfItems' /></td></tr>"; }
html += "</table>"; $('#catalog').html(html);
}}
There is a text input next to each item in the order form for the user to input the # of items they want.
How would I send the contents of the table and each form input as an email in PHP?
My guess is that I'd have to take the cookie array, and with each iteration have an array of all the text inputs and use foreach so that they are together in the email (unsure of how to do this exactly). It is also important that there can be any number of text inputs as the number of items on the order form will increase/decrease.
Here is an example of using foreach to get multiple input boxes, but how might I combine the array from my cookie with the text inputs?
Better you send only plain HTML in the email without any javascript because you won't have any javascript in the email program nor you have any cookies.
No idea who told you you could use that, but Email programs are not Browsers.
However if you send a link via email, any user can then open it in a full-featured internet browser so this might be what you're looking for.
Netscape Communicator 4 had support for javascript in emails, no idea about the cookies.
First you must give the form elements a name followed by [] indicating that it is an array, when you create the form elements in the loopArrayMail() function.
for(var i=0;i<items.length;i++){
html += "<tr><td width='450'>"+items[i]+"</td><td><input type='text' name='ordernum[]' size='8' /></td></tr>";
}
Since the cookie is a string you must first explode the string based on the delimiter which is a comma. Place the two arrays into variables. Then use a for loop to go through all of the array.
function explode_trim($str, $delimiter = ',') {
if ( is_string($delimiter) ) {
$str = trim(preg_replace('|\\s*(?:' . preg_quote($delimiter) . ')\\s*|', $delimiter, $str));
return explode($delimiter, $str);
}
return $str; }
$orderCookie = explode_trim($_COOKIE['productWishlist']);
$orderNum = $_POST['ordernum'];
for ( $i = 0; $i < count($orderCookie); $i++) {
echo $orderCookie[$i] . ' = ' . $orderNum[$i] . '<br />';
}

php processing a dynamically generated form

I'm using php to generate an html page that displays blog/thread items, and I am using javascript to show/hide some of the details. The problem is that I am generating unique IDs for each set of hidden content, which contains a form to process the input. In processing the form, I need to know which blog item was edited - I want to use $_POST. I'm pretty new to javascript, and I'm thinking that there is probably a solution I can use there.
I want the post to save the text to the mysql database (so call one of my php functions that I have working) and tell me what the text was and what the threadId is.
Here is the php code snipet, where $threadDetailItem is an array that has my thread data in it.
foreach ($threadData as $threadDetailItem)
{
// display main line (a bunch of code here ...)
// append button to edit or delete the post for admin
if ( isset ($_SESSION['isAdmin']) && $_SESSION['isAdmin'] == 'Y'){
// edit link opens content, and delete pops up a confirmation box
$el = sprintf ("editThreadLink_%d", $threadDetailItem['blogThreadId']);
$ec = sprintf ("editThreadContent_%d", $threadDetailItem['blogThreadId']);
$link1 = sprintf ("<a id=\"%s\" href=\"javascript:toggle('%s', '%s');\">+</a>", $el, $ec, $el);
$msg .= sprintf ("<li id=\"field6\">%s</li>\n", $link1);
}
$msg .= "</ul>\n";
echo $msg;
// now that the row is printed, lets add the hidden content if admin so they can edit
if ( isset ($_SESSION['isAdmin']) && $_SESSION['isAdmin'] == 'Y'){
// hidden content to enable editing of the posting
$msg = sprintf ("<div id=\"%s\" style=\"display: none\">\n", $ec);
echo $msg;
echo "<form name=\"form\" method=\"post\" action=\"\">\n";
$msg = sprintf ("<textarea id=\"%s\" name=\"%s\">%s</textarea>\n",
$ec, $ec, $threadDetailItem['threadTitle']);
echo $msg;
$msg = sprintf ("<button type=\"submit\"> %s</button>\n", $lang->get('BLOG POST'));
echo $msg;
echo "</form>\n";
echo "</div>";
}
}
Suggestions on good ways to handle this event are much appreciated. Thanks in advance.
The fields in the data are: blogThreadId, threadTitle, username, createdOn, lastUpdated, displayed (not used) and threadDetails (array containing the posting information).
I was able to use $_POST along w/ the ID in a hidden field to enable my php scripts to know which thread was being edited. It is working

How do I create a server-side form submission script that has client-side characteristics?

I'm working in PHP to build a form. I know how to display the form and then take submitted values from the $_POST variable, and I know how to validate those variables and display a "Thank You" or an "Error" page depending on the input.
What I don't know how to do, though, is create a client-side-like system wherein despite having my users hit a "back" button a separate screen I can then take the information I gathered from the first submission and display dynamic error messages like "Please provide a valid email address" or "First name is a required field" next to the fields that were entered incorrectly. I'd also like to retrieve any previously submitted data that was valid and have it populate in the form so users don't get frustrated by losing everything they entered.
What is the right approach to accomplishing something like this in PHP? I originally thought if I could pass back an array of error messages with an input type="hidden" tag I could then pull my values and display messages dynamically with PHP, but I keep getting stuck in that approach.
You could add the errors a php session, but this creates issues for users who have multiple browser tabs open.
My preferred method is to have the form submit to the same page and put the errors directly on that page so the user does not have to click the back button. That way you can highlight the fields directly in the form (make the background or outline red or something similar.)
<input type="text"
<?php (empty($_POST['field']?'style="backgroung-color: red;"':''))?>
name="field" value="<?php echo $_POST['field']?>" />
You can put <input type="text" name="field" value="<?php echo $_POST['field']?>" /> to get the old value.
Because the web is, by definition, stateless, there is no really good way to track what the user does when they hit the back button. There are hacks that work using a hidden iframe, but that is way more trouble that what you are looking for.
Don't mix client logic with server logic. The exact same script can output the form and take it's input. In case input successfully validates, it goes on. If not, it will display the form again, this time with error messages and the already-entered data.
Next time the user submits the form, validation starts again until it passes successfully.
So you extend the form with input values and error messages in the first place, but you only display them if flagged/set.
This can be done just with additional variables next to $_POST - or if you like it - by using a complete form abstraction from a framework, like zend framework (which might be overhead for what you like to do) or just with a library/component like the popular HTML_QuickForm2.
Edit:
This is some very bare code to demonstrate the overall methodology, if you use a library it is much nicer (and you don't have to code it instead you can concentrate on the actual form like the definition on top). This code is more for reading and understanding the flow than for using, I quickly typed it so it (most certainly has) syntax errors and it's not feature complete for a full blown form. This one has only one email field and is even missing the submit button:
/* setup the request */
$request->isSubmit = isset($_POST['submit']);
/* define the form */
$form->fields = array
(
'email' => array
(
'validate' => function($value) {return filter_var($value, FILTER_VALIDATE_EMAIL);},
'output' => function($value, $name) {return sprintf('<input type="text" value="%s" id="%s">', htmlspecialchars($value), htmlspecialchars($name)},
'default' => 'info#example.com',
),
);
/**
* Import form data from post request
*
* #return array data with keys as field names and values as the input strings
* or default form values.
*/
function get_form_post_data($form, $request)
{
$data = array();
foreach($form->fields as $name => $field)
{
$data[$name] = $field->default;
if ($request->isSubmit && isset($_POST[$name]))
{
$data[$name] = $_POST[$name];
}
}
return $data;
}
/**
* Validate form data
*/
function validate_form_data($form, $data)
{
foreach($form->fields as $name => $field)
{
$value = $data[$name];
$valid = $field['validate']($value);
if (!$valid)
{
$form->errors[$name] = true;
}
}
}
function display_form($form, $data)
{
foreach($form->fields as $name => $field)
{
$value = isset($data[$name]) ? $data[$name] : '';
$hasError = isset($form->errors[$name]);
$input = $field['output']($name, $value);
$mask = '%s';
if ($hasError)
{
$mask = '<div class="error"><div class="message">Please Check:</div>%s</div>';
}
printf($mask, $input);
}
}
// give it a run:
# populate form with default values -or- with submitted values:
$form->data = get_form_post_data($form, $request);
# validate form if there is actually a submit:
if ($request->isSubmit)
{
validate_form_data($form, $form->data);
}
# finally display the form (that can be within your HTML/template part), works like echo:
display_form($form, $form->data)
Use the form to submit to the same page, and if the form validates, use a header to redirect the user into the thank you page.
header("Location: thank-you.php");
If the form fails validation, you could easily display all the errors on the same page.

Categories