WinHttpRequest POST - php

I'm trying to read data from my online mySQL server using WinHttpRequest in VBA.
Dim objHTTP As New WinHttp.WinHttpRequest
With objHTTP
.Open "POST", "http://www.dname.com/ruski/php/getNewestPID.php", True
.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=""UTF-8"""
.Send "PID=" & lngPID
.WaitForResponse
Debug.Print .ResponseText
End With
<?php
$PID = $_POST['PID'];
require_once ('config.php');
if(!$PID>0){
die("##### Error: getNewestPID failed - PID='" . $PID . "' #####");
}
$phrases = mysql_query("SELECT * FROM phrases WHERE (PID > '$PID')");
if(!$phrases){
die("##### Error: getNewestPID SELECT failed - PID=" . $PID . " - " . mysql_error() . " #####");
}
mysql_close($db);
echo "data=";
while($row = mysql_fetch_array($phrases)) {
echo $row[0] . "|" . $row[1] . "|" . $row[2] . "|" . $row[3];
}
?>
All works well, but cyrillic text is returned like:
data=21361|105||Ð?алÑ?Ñ?ик игÑ?аеÑ? на ÑкÑ?ипке в Ñвоей комнаÑ?Ð
My db uses UTF-8 Unicode. I know cyrillic works in tables and forms, but views junk in the VB editor.
I tried this:
Set FileStream = CreateObject("ADODB.Stream")
FileStream.Open
FileStream.Type = 1 'Binary
FileStream.Write objHTTP.ResponseBody
FileStream.Position = 0
FileStream.Type = 2 'adTypeText
FileStream.Charset = "Windows-1251" ' https://msdn.microsoft.com/en-us/library/ms526296(v=exchg.10).aspx
strText = FileStream.ReadText
FileStream.Close
ending up with junk in the record:
Мальчик играет на скрипке в своей комнате.
The best result is with:
mb_convert_encoding($row[3], "Windows-1251", "UTF-8")
Ìàëü÷èê èãðàåò íà ñêðèïêå â ñâîåé êîìíàòå.

This is not very elegant but it worked for me when I had similar issues. It is simply a function that will manually go from 1251 into Unicode. This one works for Russian and Ukrainian but according to which language you are working with there may be different characters and you would need to add them to the if statement. Also consider adding an else if that throws a question mark in case the character you are looking for is not found.
Public Function AsciitoUni(base_cell As String) As String
AsciitoUni = ""
For i = 1 To Len(base_cell)
Dim s As String
Dim u As Integer
Dim a As Integer
s = Mid(base_cell, i, 1)
a = Asc(s)
If (a <= 127) Then
u = a
ElseIf (a >= 192) And (a <= 255) Then
u = a + 848
ElseIf (a = 184) Then
u = 1105
ElseIf (a = 186) Then
u = 1108
ElseIf (a = 179) Then
u = 1110
ElseIf (a = 191) Then
u = 1111
ElseIf (a = 168) Then
u = 1025
ElseIf (a = 170) Then
u = 1028
ElseIf (a = 178) Then
u = 1030
ElseIf (a = 175) Then
u = 1031
ElseIf (a = 185) Then
u = 8470
End If
AsciitoUni = AsciitoUni & ChrW(u)
Next
End Function

Related

How would I find the imaginary roots given a quadratic?

This code finds the two roots of a quadratic equation in the form ax^2+bx+c
Is my solution good time/space-complexity wise, and how I would go about allowing users to see the imaginary roots if the quadratic has any?
public function factor($a=0, $b=0, $c=0) {
$positive_solution = (-$b + sqrt($b**2-4*$a*$c))/2*$a;
$negative_solution = (-$b - sqrt($b**2-4*$a*$c))/2*$a;
if($b**2-4*$a*$c < 0) {
return "Solutions are imaginary";
}
$factor_one = $positive_solution * -1;
$factor_two = $negative_solution * -1;
$factor_one > 0 ? $factor_one = "+ " . $factor_one : $factor_one = "- " . $factor_one;
$factor_two > 0 ? $factor_two = "+ " . $factor_two : $factor_two = "- " . $factor_two;
return "Your roots are located at (0, " . $positive_solution . ")(0, " . $negative_solution . "),
Thus, the problem can be factored into (x " . $factor_one . ")(x " . $factor_two . ")";
}
the if($b**2-4*$a*$c < 0) is too late
You already used the sqrt so domain error might be thrown move the if to start
for imaginary part you just use negation or abs value
simply sqrt(-($b**2-4*$a*$c)) or sqrt(abs($b**2-4*$a*$c)) not sure if php uses abs or fabs for floats or if you even use floats... (havent code in php for ages)
I would combine this to something like this (just pseudo code as the var $ makes me dizzy :) ):
q = b*b-4*a*c
d = sqrt(abs(q))
if (q<0)
{
a0 = -b/(2*a);
b0 = +d/(2*a);
a1 = -b/(2*a);
b1 = -d/(2*a);
}
else
{
a0 = (-b + d)/(2*a);
b0 = 0
a1 = (-b - d)/(2*a);
b1 = 0
}
Where a0+i*b0 and a1+i*b1 are the 2 solutions where i=sqrt(-1)

Wrong calculations in PHP

I am trying to calculate in PHP. When I try to do that I can see that the result is mostly wrong.
The script I am using is the following:
$newrate = 1 / $rate["rate"];
echo '1 /'. $rate["rate"]. ' = '.$newrate;
The result I get is the following:
1 /1.0867 = 1
1 /117.01 = 0.0085470085470085
1 /1.9558 = 1
1 /27.534 = 0.037037037037037
1 /7.4589 = 0.14285714285714
1 /1.0867 should be 0.92021717125 and not 1.
I can reproduce this step by adding the following line to my script:
$rate["rate"] = 1.0867;
When I run the script the result is still 1. When I change my script like:
$newrate = 1 / 1.0867;
echo '1 / 1.0867 = '.$newrate;
I get a correct result. The output is then: 0.92021717125.
Does someone know what is wrong with this script? What is the reason that my script is making incorrect calculations?
Update 1:
Here is my full script:
<?php
$XML=simplexml_load_file("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml");
foreach($XML->Cube->Cube as $rat)
{
foreach($rat as $rate)
{
$newrate = '1' / $rate["rate"];
echo '1 /' . $rate["rate"] . ' = ' . $newrate;
echo '<br /><br />';
}
}
?>
I think there is something wrong with your example. I tested exactly what you described and works as expected.
<?php
$rate = [];
$rate["rate"] = "1.0867";
$newrate = 1 / $rate["rate"];
echo '1 / ' . $rate["rate"] . ' = ' . $newrate;
// 1 / 1.0867 = 0.92021717125242
You can see it running here
https://repl.it/#thiagodamata/NeighboringPeachpuffArchitect
Probably, you are using "," instead of "." when sending the number.
PHP cast the number only until it hits something unexpected. So "1,0867" is cast to 1. It is a classic problem when dealing with numbers in different formats, considering different languages.
<?php
// simulating the "," error
$rate["rate"] = "1,0867";
$newrate = 1 / $rate["rate"];
echo '1 / ' . $rate["rate"] . ' = ' . $newrate;
// 1 / 1,0867 = 1
Take a look in this thread about how to cast the number from different languages masks PHP: Locale aware number format and take a deeper look into the PHP function number-format https://www.php.net/manual/en/function.number_format.php
Update - After getting the full code example
Looking to your full code becomes more clear the problem. The var that you are getting in the loop it is a SimpleXmlElement, not a string. So, SimpleXmlElement is printed as the "1.0867" but it is not its real value.
To make the SimpleXmlElement cast to float properly, you need to use the cast function.
<?php
$XML=simplexml_load_file("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml");
foreach($XML->Cube->Cube as $rat)
{
foreach($rat as $rate)
{
print(var_dump($rate["rate"]));
/*
object(SimpleXMLElement)#7 (1) {
[0]=>
string(6) "1.0867"
}
*/
print("class = [" . get_class($rate["rate"]) . "]\n");
// class = [SimpleXMLElement]
print("as string = [" . $rate["rate"] . "]\n");
// as string = [1.0867]
print("without cast = [" . (1 * $rate["rate"]) . "]\n");
// without cast = [1]
$a = (float)($rate["rate"]);
print("with cast = [" . ($a) . "]\n");
// with cast = [1.0867]
print(serialize($a));
//d:1.0867;
$newrate = '1' / $a;
echo '1 / ' . $a . ' = ' . $newrate . "\n";
// 1 / 1.0867 = 0.92021717125242
echo '<br /><br />';
exit();
}
}
?>
You can see this running here:
https://repl.it/#thiagodamata/FuchsiaLightheartedPrintablecharacter
Just printing the value of a var does not always give you the real value of some object. There are other functions like var_export https://www.php.net/manual/en/function.var-export.php, var_dump https://www.php.net/manual/en/function.var-dump.php and serialize that may help you to see the real value of the vars.
Calculations are fine, and correct
You've not taken into account implicit type casting in PHP. Try this:
<?php
print "integer divided by float = " . (1 /1.0867) . "\n"; // returns 0.9202171712524
print "Integer divided by string = " . ((1/"1.0867") . "\n"; // returns 1
You are expecting PHP to know what your intention is when you throw a tring into an arithmetic operation - that's not how PHP works.
Just because it is dynamically typed doesn't mean you don't need to be careful with your data types.
print (1/(float)$rate['rate'];
try cast all values as a float
echo 1.0 / (float) $rate['rate'];

Replace value from database with space depending on its length if value is empty/null

Scenario:
Database Table
Column Type Length Sample Values
emp_code varchar 4 0011 0021 0012
emp_desc varchar 2 01 03 01
emp_stat varchar 1 1 0
Problem:
I am querying so that I can write the result into a text file.
$file = "data.txt";
$f = fopen($file, "a");
$qry = "SELECT * FROM tbl_emp";
$result = mysqli_query($conn, $qry );
if(!$result) {
echo "Cannot do query" . "<br/>";
exit;
}
$num_results =mysqli_num_rows($result);
for ($i=0; $i<=$num_results; $i++) {
$row = mysqli_fetch_assoc ($result);
$emp_code = (empty($row['emp_code']) ? " " : $row['emp_code']); //replace with 4 spaces
$emp_desc = (empty($row['emp_desc']) ? " " : $row['emp_desc ']); //replace with 2 spaces
$emp_stat = (empty($row['emp_code']) ? " " : $row['emp_code']); //replace with 1 space
$data = "$emp_code $emp_desc $emp_stat\r\n";
fwrite($f,$data);
}
Data.Txt should contain:
0011011
002103
0012010
But this is the result:
0011011
002103
001201
If the value of the row is 0, it replaces it with blank when it shouldn't. What needs to be changed to get the correct data? TIA.
Don't use empty. 0 is empty. Depending on what you are checking there it can be one of:
$emp_stat = (is_null($row[...]) ? " " : $row[...])
$emp_stat = (($row[...] === "") ? " " : $row[...])
$emp_stat = (is_numeric($row[...])? $row[...] : " ")
etc

PHP MD5 Not Matching VB.NET MD5

I am trying to get the same MD5 hash in PHP and VB.NET but no matter what text encoding I use I cannot get the hashes to match. What am I doing wrong? Below is my code in each language:
PHP Code:
echo '<b>$20.00 (UTF-32)</b> = ' . md5(mb_convert_encoding('1C9BRPS3TN85I2ULE5FP' + '20.00', 'UTF-32'));
echo '<b>$20.00 (UTF-32LE)</b> = ' . md5(mb_convert_encoding('1C9BRPS3TN85I2ULE5FP' + '20.00', 'UTF-32LE'));
echo '<b>$20.00 (UTF-32BE)</b> = ' . md5(mb_convert_encoding('1C9BRPS3TN85I2ULE5FP' + '20.00', 'UTF-32BE'));
echo '<b>$20.00 (UTF-8)</b> = ' . md5(mb_convert_encoding('1C9BRPS3TN85I2ULE5FP' + '20.00', 'UTF-8'));
echo '<b>$20.00 (UTF-7)</b> = ' . md5(mb_convert_encoding('1C9BRPS3TN85I2ULE5FP' + '20.00', 'UTF-7'));
echo '<b>$20.00 (UTF-16)</b> = ' . md5(mb_convert_encoding('1C9BRPS3TN85I2ULE5FP' + '20.00', 'UTF-16'));
echo '<b>$20.00 (UTF-16LE)</b> = ' . md5(mb_convert_encoding('1C9BRPS3TN85I2ULE5FP' + '20.00', 'UTF-16LE'));
echo '<b>$20.00 (UTF-16BE)</b> = ' . md5(mb_convert_encoding('1C9BRPS3TN85I2ULE5FP' + '20.00', 'UTF-16BE'));
echo '<b>$20.00 (ASCII)</b> = ' . md5(mb_convert_encoding('1C9BRPS3TN85I2ULE5FP' + '20.00', 'ASCII'));
VB.NET Code:
Try
' Create a new instance of the MD5 object.
Dim md5Hasher As MD5 = MD5.Create()
' Convert the input string to a byte array and compute the hash.
Dim strInput As String = "1C9BRPS3TN85I2ULE5FP" & "20.00"
Dim data As Byte() = md5Hasher.ComputeHash(Encoding.UTF32.GetBytes(strInput))
' Create a new Stringbuilder to collect the bytes
' and create a string.
Dim sBuilder As New StringBuilder()
' Loop through each byte of the hashed data
' and format each one as a hexadecimal string.
Dim i As Integer
For i = 0 To data.Length - 1
sBuilder.AppendFormat("{0:x2}", data(i))
'sBuilder.Append(data(i).ToString("x2"))
Next i
lblResponse.Text = "<b>$20.00 (UTF-32)</b> = " & sBuilder.ToString() & "<br>"
' Try a different encoding
data = md5Hasher.ComputeHash(Encoding.ASCII.GetBytes(strInput))
' Loop through each byte of the hashed data
' and format each one as a hexadecimal string.
sBuilder.Length = 0
For i = 0 To data.Length - 1
sBuilder.AppendFormat("{0:x2}", data(i))
Next i
lblResponse.Text &= "<b>$20.00 (ASCII)</b> = " & sBuilder.ToString() & "<br>"
' Try a different encoding
data = md5Hasher.ComputeHash(Encoding.Unicode.GetBytes(strInput))
' Loop through each byte of the hashed data
' and format each one as a hexadecimal string.
sBuilder.Length = 0
For i = 0 To data.Length - 1
sBuilder.AppendFormat("{0:x2}", data(i))
Next i
lblResponse.Text &= "<b>$20.00 (Unicode)</b> = " & sBuilder.ToString() & "<br>"
' Try a different encoding
data = md5Hasher.ComputeHash(Encoding.UTF7.GetBytes(strInput))
' Loop through each byte of the hashed data
' and format each one as a hexadecimal string.
sBuilder.Length = 0
For i = 0 To data.Length - 1
sBuilder.AppendFormat("{0:x2}", data(i))
Next i
lblResponse.Text &= "<b>$20.00 (UTF7)</b> = " & sBuilder.ToString() & "<br>"
' Try a different encoding
data = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(strInput))
' Loop through each byte of the hashed data
' and format each one as a hexadecimal string.
sBuilder.Length = 0
For i = 0 To data.Length - 1
sBuilder.AppendFormat("{0:x2}", data(i))
Next i
lblResponse.Text &= "<b>$20.00 (UTF8)</b> = " & sBuilder.ToString() & "<br>"
Catch ex As Exception
lblErrorMessage.Text = ex.ToString()
End Try
String concatenation is . in PHP not + as in VB.Net. Thus, '1C9BRPS3TN85I2ULE5FP' + '20.00' won't result in '1C9BRPS3TN85I2ULE5FP20.00'in PHP.
Edit: VB.net's Real string concatenation is & but since the term visual basic is used, + sign can do the same as long as mathematical interpretation is meaningless.
So to be on the safe side, use &.

comparing two strings for percentage match

I am trying to compare a user submitted string to a string of a database record and see how close they are in terms of %
i have found this rather interesting code which looks like a good solution
Function Compare(ByVal str1 As String, ByVal str2 As String) As Double
Dim count As Integer = If(str1.Length > str2.Length, str1.Length, str2.Length)
Dim hits As Integer = 0
Dim i, j As Integer : i = 0 : j = 0
For i = 0 To str1.Length - 1
If str1.Chars(i) = " " Then i += 1 : j = str2.IndexOf(" "c, j) + 1 : hits += 1
While j < str2.Length AndAlso str2.Chars(j) <> " "c
If str1.Chars(i) = str2.Chars(j) Then
hits += 1
j += 1
Exit While
Else
j += 1
End If
End While
If Not (j < str2.Length AndAlso str2.Chars(j) <> " "c) Then
j -= 1
End If
Next
Return Math.Round((hits / count), 2)
End Function
firstly can anyone tell me what the language is used above, and can anyone help me convert it to php please?
i've tried to convert it but ran in to a bit of trouble early on
function compare($str1,$str2) as $double
{
$count = if(strlen($str1) > strlen($str2), strlen($str1) > strlen($str2));
$hits = 0;
$i - 0;
$j = 0;
for($i = 0; $i < strlen($str1); $i++)
{
if($str1[$i] == " ")
{
$i .= "1";
}
}
}
any help with this would be hugely appreciated
As an option, then, try something like this:
$teststr = "This is a test.";
$dbstr = "This was a test.";
$percent = (1 - levenshtein($teststr, $dbstr)/max( strlen($teststr),strlen($dbstr) ) ) * 100;
print "Percent match".$percent."\n";
Percent match: 92.857142857143
Far more info at: http://us3.php.net//manual/en/function.levenshtein.php

Categories