special characters strange behavior - mysql

i have this string in my utf-8 mysql DB:
"Pruebá de eñes"
When i print it like plain text, everything works ok, but if i load that same field inside an input, textarea, etc, it becomes: "Pruebá de eñes"
How can i solve this problem? =(

First I recommend read this: http://www.joelonsoftware.com/articles/Unicode.html (The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) by Joel Spolsky) really useful.
Then if it's MySQL you can set the default character set in the connection by "SET NAMES 'utf8'". For example in Zend_Framework ($db->query("SET NAMES 'utf8'");)
Another option is add a filter to the data before print it in the screen. I made two handly functions ...
function utf8encode ($subject, $action = '//TRANSLIT')
{
if ( #iconv( 'UTF-8', "UTF-8{$action}", $subject) == $subject ) {
#-- the value it's utf8
} else {
$subject = utf8_encode ($subject);
}
return $subject;
}
function utf8decode ($subject, $action = '//TRANSLIT')
{
if ( #iconv( 'UTF-8', "UTF-8{$action}", $subject) == $subject ){
$subject = utf8_decode ($subject);
} else {
#-- the value is probably ISO-8859-1
}
return $subject;
}

Related

Drupal Views alter Filter to CAST() string as Float

i got a problem, altering my view so that it is filtering a string-field (where i know that there only can be numbers, but can't change this scenario) so that it is handled as number...
normaly i can achieve this by using "CAST" ... the problem is, that it gets altered in the hook so that my example looks like the following:
... AND (CASTfield_data_field_baserent.field_baserent_valueASDECIMAL <= '1000') ))
so all extra characters get stripped out... :-/
i tried a lot of hooks but none of them seem to do the job!
Does anyone have a idea, how i can do it?!
(the module computed field is not really an option..)
my current code is like the following:
function custom_helpers_views_query_alter(&$view, &$query){
if($view->name=="mietangebote"){
// Miete
if(!empty($view->exposed_raw_input['field_baserent_value'])){
foreach($query->where[1]['conditions'] as $key=>$condition){
if($condition['field']=="field_data_field_baserent.field_baserent_value"){
$view->query->where[1]['conditions'][$key]['operator']="<=";
$view->query->where[1]['conditions'][$key]['value']=(double)$view->query->where[1]['conditions'][$key]['value'];
$view->query->where[1]['conditions'][$key]['field']="CAST(".$view->query->where[1]['conditions'][$key]['field']." AS DECIMAL)";
//dpm($view->query->where[1]['conditions'][$key]);
}
}
}
}
}
where
$view->query->where[1]['conditions'][$key]['field']="CAST(".$view->query->where[1]['conditions'][$key]['field']." AS DECIMAL)";
is the important line
THANKS in advance :)
hook_views_query_alter function should do the job, here is what it should look like:
function custom_helpers_views_query_alter(&$view, &$query) {
if ( $view->name == 'mietangebote' ) {
// Miete
if(!empty($view->exposed_raw_input['field_baserent_value'])){
foreach($query->where[1]['conditions'] as $key => $condition) {
if ( $condition['field'] == 'field_data_field_baserent.field_baserent_value' ) {
$query->where[1]['conditions'][$key]['operator'] = 'formula';
$query->where[1]['conditions'][$key]['value'] = array(':val' => (double)$query->where[1]['conditions'][$key]['value']);
$query->where[1]['conditions'][$key]['field'] = 'CAST(' . $query->where[1]['conditions'][$key]['field'] . ' AS UNSIGNED) >= :val';
//dpm($view->query->where[1]['conditions'][$key]);
break;
}
}
// For sorting as well
foreach($query->orderby as $key => $condition) {
if ( $condition['field'] == 'field_data_field_count_field_count_value' ) {
$query->orderby[$key]['field'] = 'CAST(' . $query->orderby[$key]['field'] . ' AS UNSIGNED)';
break;
}
}
}
}
}
The important line is:
$query->where[1]['conditions'][$key]['operator'] = 'formula';
and will allow Views to treat the value of 'field' as an SQL snippet and not as a field's name. Check the source code of add_where_expression for the full details! [doc]
And good luck!
Disclaimer: This answer is a variation of a very similar one to this question from drupal.stackexchange.com. The code is modified to address the specific question (not just copy+paste).
See if there's any way to pass the condition yourself, something like this:
$view->query->where[1]['conditions'][$key]->condition("CAST(".$view->query->where[1]['conditions'][$key]['field']." AS DECIMAL) <= " . $view->query->where[1]['conditions'][$key]['value']);
Instead of CAST, simply build an expression with 0+ tacked onto the variable and/or constant:
0+'1000'
will be treated as the numeric value 1000, not the string '1000'.

blowFIsh data store in mysql database

I am using a blowfish encryted function:
class Blowfish {
private $key;
private $iv;
public function __construct($key, $iv) {
$this->key = $key;
$this->iv = $iv;
}
public function encrypt($data) {
return mcrypt_encrypt(MCRYPT_BLOWFISH, $this->key, $data, MCRYPT_MODE_CBC, $this->iv);
}
public function decrypt($data) {
return mcrypt_decrypt(MCRYPT_BLOWFISH, $this->key, $data, MCRYPT_MODE_CBC, $this->iv);
}}
Now when I am encrypted something with this function like:
$blowfish = new blowfish('DfRgBWE4Y4T7UgTWEdFP1Y', '85440934');
echo $pass = $blowfish -> encrypt('12345');
which should displays --> ' ìI”‹YR” '
but I can't save it in database table. My table structure is like:
`Password` varchar(255) CHARACTER SET utf32 NOT NULL
But every time I try to insert it, the insertion is like " ?I??YR? "
what to do now?
I suggest to not store (potentially) binary, i.e. non-AlphaNumeric data, in an SQL database, especially not inside varchar(..) which will mess things up when you try to look at the the data.
Instead, either Base64 or HEX encode it, HEX is probably the better option, for HEX it is very easy and native for MySQL:
INSERT INTO table SET Password = HEX(?)
The ? is a placeholder for your Blowfish result
To pick up the binary data from the database do:
INSERT UNHEX(Password) FROM table

Undo mysql_real_escape_string

I have the following code at the top of every of my php pages:
<?php
function name_format($str)
{
return trim(mysql_real_escape_string(htmlspecialchars($str, ENT_QUOTES)));
}
?>
foreach ($_POST as $key => $value) {
if (!is_array($value))
{
$_POST[$key] = name_format($value);
}
}
This was pretty useful until now. I experienced that if I want to display a text from a <textarea> before writing it into a database, then it shows "\r\n" instead of normal line breaks.
Even if I try to do the following, it doesn't work:
$str = str_replace("\r\n", "<br>", $str);
The mistake you're making here is over-writing $_POST with a version of the string which you are hoping will be appropriate for all contexts (using mysqli_real_escape_string and htmlspecialchars at the same time).
You should leave the original value untouched, and escape it where it is used, using the appropriate function for that context. (This is one reason why the "magic quotes" feature of early versions of PHP are universally acknowledged to have been a bad idea.)
So in your database code, you would prepare a variable for use with SQL (specifically, MySQL):
$comment = mysqli_real_escape_string(trim($_POST['comment']));
And in your template, you would prepare a variable for use with HTML:
$comment = htmlspecialchars(trim($_POST['comment']));
Possibly adding a call to nl2br() in the HTML context, as desired.

How to amend sub strings?

Using collation xxx_german2_ci which treats ü and ue as identical, is it possible to have all occurences of München be highlighted as follows?
Example input: "München can also be written as Muenchen."
Example output: "<b>München</b> can also be written as <b>Muenchen</b>."
Note: It is OK to use some non-SQL programming in addition. The only requirement is that the knowledge about which character sequences are identical is taken from the MySQL collation.
I have found this tables: http://developer.mimer.com/collations/charts/index.tml. They are, of course, landuage dependant. Collation is just comapring algorithm. For general utf8 I am not sure, how it treats special characters.
You can use them to found desired symbols and replace them in output to get same result as in example. But for those, you will need some programming language (PHP or anything else).
Another resources:
http://collation-charts.org/
http://mysql.rjweb.org/doc.php/charcoll (down on the page)
Basicly, try to google "collation algorithm mysql utf8_general_ci" or something like this
In the end I decided to do it all in PHP, therefore my question about
which characters are equal with utf8_general_ci.
Below is what I came up with, by example: A label is constructed from a text
$description, with sub strings $term highlighted, and special characters
converted. Substitution is not complete, but probably sufficient for the actual
use case.
mb_internal_encoding("UTF-8");
function withoutAccents($s) {
return strtr(utf8_decode($s),
utf8_decode('àáâãäçèéêëìíîïñòóôõöùúûüýÿß'),
'aaaaaceeeeiiiinooooouuuuyys');
}
function simplified($s) {
return withoutAccents(strtolower($s));
}
function encodedSubstr($s, $start, $length) {
return htmlspecialchars(mb_substr($s, $start, $length));
}
function labelFromDescription($description, $term) {
$simpleTerm = simplified($term);
$simpleDescription = simplified($description);
$lastEndPos = $pos = 0;
$termLen = strlen($simpleTerm);
$label = ''; // HTML
while (($pos = strpos($simpleDescription,
$simpleTerm, $lastEndPos)) !== false) {
$label .=
encodedSubstr($description, $lastEndPos, $pos - $lastEndPos).
'<strong>'.
encodedSubstr($description, $pos, $termLen).
'</strong>';
$lastEndPos = $pos + $termLen;
}
$label .= encodedSubstr($description, $lastEndPos,
strlen($description) - $lastEndPos);
return $label;
}
echo labelFromDescription('São Paulo <SAO>', 'SAO')."\n";
echo labelFromDescription('München <MUC>', 'ünc');
Output:
<strong>São</strong> Paulo <<strong>SAO</strong>>
M<strong>ünc</strong>hen <MUC>

Sanitizing Form Data for MySQL table

Will this do the trick if I am sanitizing code that is going from a form into a mysql table? the data that should/will be entered will be school subjects and professor's first/last names...any other suggestions on how to do this?
/*
Sanitize() function removes any potential threat from the
data submitted. Prevents email injections or any other hacker attempts.
if $remove_nl is true, newline chracters are removed from the input.
*/
function Sanitize($str,$remove_nl=true)
{
$str = $this->StripSlashes($str);
if($remove_nl)
{
$injections = array('/(\n+)/i',
'/(\r+)/i',
'/(\t+)/i',
'/(%0A+)/i',
'/(%0D+)/i',
'/(%08+)/i',
'/(%09+)/i'
);
$str = preg_replace($injections,'',$str);
}
return $str;
}
function StripSlashes($str)
{
if(get_magic_quotes_gpc())
{
$str = stripslashes($str);
}
return $str;
}
I recommend PHP's PDO class. You would do something like:
try
{
$sql ='INSERT INTO whatever(a,b,c) VALUES(:a,:b:c);
//or if you prefer...
$sql ='INSERT INTO whatever(a,b,c) VALUES(?,?,?);
$stmt = db::db()->prepare($sql);
$stmt->execute(array(123,234,345));
}
catch(PDOException $e){library::sql_error($e,$sql);}
Thanks to everyone for taking the time to help. I went with the preg_replace function which limits characters to only what i want people to use: preg_replace("~" . "[^a-zA-Z0-9\-\_\.\ ]" . "~iU", "", $string). I also used mysql_real_escape_string so I'm doing two levels of filtering before sending on to the database.
Why don't you use mysql_real_escape_string() which escapes all potential characters that can cause issues? Besides being built in, it cals MySQL's own mysql_real_escape_string so you know you'll always be up to date on what needs to be escaped for your installed database.
The best option is to use PDO's bindValue method:
http://www.php.net/manual/en/pdostatement.bindvalue.php
This sorts out all your escaping.
For forms, you can also look at this:
http://semlabs.co.uk/docs/xfl/xfl-elements/sanitise
It's a set of PHP classes to handle forms with less hassle, though it will take a while to get your head round.
Try this :
function sanatize($value) {
$value = preg_replace("~" . "[^a-zA-Z0-9\-\_\.]" . "~iU", "", $value);
return $value;
}