-1

I've created a dynamic dropdown using JS/PHP/MySQL but it seems I'm having some problems with special characters. The script is going to be used to make a small application that helps my customers find a product that meets their criteria. We sell panel meters that can accept different ranges of input and many are denoted with a +/- or a value (example: a meter can expect to process a voltage +/- 10V around a specified voltage.) Everything is starting to work great in my script except when some characters are parsed through (+, / , ±, ½, etc.) My database originally used ± to denote plus or minus but I then switched to +/- (three characters) in hopes that it would fix the special character problem but it didn't... Also when using ± the character would should up as an unknown character (so somewhere I have my encoding set wrong as well.)

So now I still need to figure out why some things are not parsing right.

You can view a live version of the script at http://new.foxmeter.com/find.php

This is the important part of my frontend

    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script>        
        $(function(){
            $("#type").change(function() {
                var tval = document.getElementById('type').value;
                $("#range").load(encodeURI("findbackend.php?type=" + tval));
            });
            $("#range").change(function() {
                rval = document.getElementById('range').value;
                $("#power").load(encodeURI("findbackend.php?range=" + rval));
            });
            $("#power").change(function() {
                //var rval = document.getElementById('range').value;
                psval = document.getElementById('power').value;
                $("#setpoint").load(encodeURI("findbackend.php?range=" + rval + "&power=" + psval));
            });
            $("#setpoint").change(function() {
                //var rval = document.getElementById('range').value;
                //var psval = document.getElementById('power').value;
                stval = document.getElementById('setpoint').value;
                $("#output").load(encodeURI("findbackend.php?range=" + rval + "&power=" + psval + "&setpoint=" + stval));
            });
          });
    </script>

</head>
<body>
    <!-- Google Analytics Script -->
    <?php include_once("scripts/analyticstracking.php") ?>

    <div class="wrapper"> <!-- Sticky Footer Wrapper -->
        <div id="panorama"></div>
        <div id="header">
            <?php include("include/header/banner.php") ?>
            <?php include("include/header/nav.php") ?>
            <?php include("include/header/quicksearch.php") ?>
        </div>
        <div id="content">
            <div id="findoptions">
                <select id="type" class="finddrops">
                    <option selected value="base">Please Select</option>
                    <option value="DC Voltage">DC Voltage</option>
                    <option value="DC Current">DC Current</option>
                    <option value="AC Voltage">AC Voltage</option>
                    <option value="AC Current">AC Current</option>
                    <option value="Strainguage">Strainguage</option>
                </select>
                <br>
                <select id="range" class="finddrops">
                    <option>Please choose from above</option>
                </select>
                <br>
                <select id="power" class="finddrops">
                    <option>Please choose from above</option>
                </select>
                <br>
                <select id="setpoint" class="finddrops">
                    <option>Please choose from above</option>
                </select>
                <br>
                <select id="output" class="finddrops">
                    <option>Please choose from above</option>
                </select>
                <br>
                <select id="blarg" class="finddrops">
                    <option>Please choose from above</option>
                </select>                   
            </div>
            <div id="findresults" class="finddrops">
            </div>
        </div>
    </div>
    <div class="footer"> 
        <?php include("include/footer/footer.php") ?>
    </div>

And this is my PHP running on the backend:

<?php
    //\\ MODULAR DEPENDANT DROPDOWNS \\//

    //creates DB connection
    $dbHost = 'host';
    $dbUser = 'user'; 
    $dbPass = 'pass';
    $dbDatabase = 'database';
    $con = mysql_connect($dbHost, $dbUser, $dbPass) or trigger_error("Failed to connect to MySQL Server. Error: " . mysql_error());

    mysql_select_db($dbDatabase) or trigger_error("Failed to connect to database {$dbDatabase}. Error: " . mysql_error());

    //prevents injections
    //any order
    $type = mysql_real_escape_string(urldecode($_GET['type']));
    isset($_GET['range'])?$range = mysql_real_escape_string(urldecode($_GET['range'])):"";
    isset($_GET['power'])?$power = mysql_real_escape_string(urldecode($_GET['power'])):"";
    isset($_GET['setpoint'])?$setpoint = mysql_real_escape_string(urldecode($_GET['setpoint'])):"";

    //forms the query depending on what data is recieved through GET
    //first option on the bottom; last option on the top to avoid conflicts 
    if (isset($_GET['setpoint'])) {
        $query = "SELECT DISTINCT stp FROM meters WHERE sio='$range' AND pso='$power' AND stp='$setpoint' ORDER BY model";
    } elseif (isset($_GET['power'])) {
        $query = "SELECT DISTINCT stp FROM meters WHERE sio='$range' AND pso='$power' ORDER BY model";
    } elseif (isset($_GET['range'])) {
        $query = "SELECT DISTINCT pso FROM meters WHERE sio='$range' ORDER BY model";
    } else {
        $query = "SELECT DISTINCT sio FROM meters WHERE sit LIKE '%$type%' ORDER BY model";
    }

    //creates a result array from query results
    $result = mysql_query($query);

    //outputs dropdown options dependent on what GET variables are set
    //first option on the bottom; last option on the top to avoid conflicts
    if (isset($_GET['setpoint'])) {
        while ($row = mysql_fetch_array($result)) {
            echo "<option value='" . $row{'stp'} . "'>" . $row{'stp'} . "</option>";
        }
    } elseif (isset($_GET['power'])) {
        echo "<option>Choose Setpoint Options</option>";
        while ($row = mysql_fetch_array($result)) {
            $row{'stp'} = ucfirst($row{'stp'}); //capitalizes the first letter; necessary?
            echo "<option value='" . $row{'stp'} . "'>" . $row{'stp'} . "</option>";
        }
    } elseif (isset($_GET['range'])) {
        while ($row = mysql_fetch_array($result)) {
            echo "<option value='" . $row{'pso'} . "'>" . $row{'pso'} . "</option>";
        }
    } else {
        while ($row = mysql_fetch_array($result)) {
            echo "<option value='" . $row{'sio'} . "'>" . $row{'sio'} . "</option>";
        }
    }

    //Thanks to Chris Coyier for the wonderful examples on CSS-Tricks
    //A Web Application by Zach Klemp
?>

Again, you can view the script here.

Thanks for any and all help getting this to work! It doesn't seem like this should be too hard I'm just not sure at how I should be telling the script to keep everything in the right encoding.

ZZZZZZZZZZ
  • 57
  • 1
  • 9
  • 1
    This `mysql` extension is deprecated as of PHP 5.5.0, and will be removed in the future. Instead, the MySQLi or PDO_MySQL extension should be used. See http://www.php.net/manual/en/mysqlinfo.api.choosing.php – nullability Sep 19 '13 at 20:23
  • 1
    Have you tried adding to your ? – Leon Kramer Sep 19 '13 at 20:24
  • you are looking for `htmlentities` http://php.net/manual/en/function.htmlentities.php – cmorrissey Sep 19 '13 at 20:24
  • @nullability, I know I will deal with that later. Thanks, though! – ZZZZZZZZZZ Sep 19 '13 at 20:26
  • It's important that your webpages use UTF-8 and that your database uses UTF-8. By using UTF-8 everywhere, all the time, you avoid encoding issues with these characters. – TravisO Sep 19 '13 at 20:26
  • @Chris it seems like htmlentities may be what I need but I'm not sure where I'm going to be encoding and decoding as my JS are does one encode. – ZZZZZZZZZZ Sep 19 '13 at 20:39
  • @ZZZZZZZZZZ it goes in your `echo` lines ... like `echo "";` – cmorrissey Sep 19 '13 at 20:42
  • Placing in my echo breaks the script. `echo "";` – ZZZZZZZZZZ Sep 19 '13 at 20:46
  • Really? That is a reason to downvote my question? Because it's _possibly_ the same as another? – ZZZZZZZZZZ Sep 20 '13 at 16:46

2 Answers2

0

For this to work everything need to be set end-to-end to be utf8 So your content type needs to be explicitly set to utf8 (as above) JavaScript passes through utf8 encodings seamlessly. PHP is mostly ok with utf8 encoding but there are some functions that break it - have a look here http://blog.loftdigital.com/blog/php-utf-8-cheatsheet

Is your database encoding set to utf8 ? It's quite easy to accidentally set your database to latin1 (some web hosts have this as their default), you'll need to set the database AND each table to utf8.

Finally, when you copy and paste (or type) your non-latin characters into your database are you using a utf8 friendly editor? For instance I often use Navicat8 for MySQL but that doesn't play nicely with utf8. Also copying and pasting from Microsoft Word can do nasty things to character encodings!

Hope this is helpful

Craig

splig
  • 371
  • 1
  • 4
  • 11
  • Hi! I just sent a query to my DB to set it to UTF8 just in case it was not, although I'm sure I set it up that way. As well, I'm using Heidi to manage my remote DB which has had no problems with special characters so far. It has displayed everything fine. A commenter on my original post said that htmlentities is probably what I'll need to encode and decode my special characters through the script but I'm still trying to figure out where I should be using this function. – ZZZZZZZZZZ Sep 19 '13 at 20:36
0

maybe try something like this:

$("#power").load(encodeURI("findbackend.php?range=" + rval.replace("+","&#43;").replace("-","&#45;").replace("/","&#47;"));

basically just replace the special characters with html encoding...the plus and backslash are reserved characters in URL strings.

EDIT: You could also try encodeURIComponent:

rval = encodeURIComponent(document.getElementById('range').value);

EDIT 2 Ok, this seems to work for me so try it out:

Make sure to set the html encoding on your page with

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

And in your php with

header('Content-Type: text/html; charset=utf-8');

Make sure you use

rval = encodeURIComponent(document.getElementById('range').value);

to encode the values being passed through the url.

$_GET automatically decodes the parameters that are coming in so you should be able to just use the parameter string retrieved in your sql statement from there.

malificent
  • 1,441
  • 14
  • 18
  • This may be simplest (although hacky) way. Not every option in the input dropdown (second dropdown) will have have a +, -, or ± in its name, though. I'll try this out and see how I like it. – ZZZZZZZZZZ Sep 19 '13 at 20:39
  • If I try encodeURIComponent() I should be able to remove encodeURI before my string to send through GET, correct? – ZZZZZZZZZZ Sep 19 '13 at 20:51
  • Although I'm already using it so it may not work....the JS already encodes the URI and then my PHP decodes it when defining variables near the start. – ZZZZZZZZZZ Sep 19 '13 at 20:52
  • hmmm...I don't think that encodeURI will actually help you in this case...https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI states that encodeURI "Assumes that the URI is a complete URI, so does not encode reserved characters that have special meaning in the URI." which "+" is a reserved character. – malificent Sep 19 '13 at 20:59
  • can you log the result of encodeURIComponent(document.getElementById('range').value); to the console to see if it's properly encoding for you? – malificent Sep 19 '13 at 21:01
  • I'm sorry for getting back so late. After running it through console.log I get a response like `%2B%2F-%201.000%20V%20DC` which decodes properly to **+/- 1.000 V DC**. It doesn't seem to be the encoding that's the problem but the decoding and processing in the PHP. – ZZZZZZZZZZ Sep 20 '13 at 13:37
  • This is what the documentation for urldecode says: `Decodes any %## encoding in the given string. Plus symbols ('+') are decoded to a space character.` One of my problems now looks like it's translating my + into a space, as well. – ZZZZZZZZZZ Sep 20 '13 at 13:51
  • ah...hmmm...i wonder if it might be easier to do some kind of custom encoding? like url.replace("+/-", "plusminus") on the client side before it is sent then do the opposite on the php side? that plus symbol is really going to confuse things. – malificent Sep 20 '13 at 14:32
  • That seems like what I'll have to do because I just can't figure out what's causing it to parse the UTF8 encoded characters incorrectly. – ZZZZZZZZZZ Sep 20 '13 at 15:12