php preg_match_all finds empty matches - php

I'm having an error I don't understand after searching around the web for a couple hours.
I have an SQL request made through ajax query with POST method, and generated for the different pages of my website, even sometimes with a direct user input.
To avoid SQL injections, I want to check the content of the parameters.
I can't use PDO::quote() because some parameters can contain lists or SQL function : for example : the select parameter can contain c.id_client, c.nom, COUNT(c.id_client)...
To prevent SQL injection I'm blacklisting some SQL keywords and functions with preg_match_all();
$matches = array();
preg_match_all('"[\w% ]*(add|alter|create|delete|drop|exec|insert|set|table|truncate|update|view)[\w% ]*"[^:]', $inputs, $matches);
In the case I'm testing, $inputs is the json_encoded post array :
{"select":"c.id_client, c.prenom, c.nom, c.email, COUNT(t.actif) AS nombre_licences","from":"clients","as":"c","inner":{"1":{"cond":{"1":{"join_in":"cl.id_client","join_out":"c.id_client"}},"table":"clients_licences","as":"cl"},"2":{"cond":{"1":{"join_in":"t.id_client_licence","join_out":"cl.id_client_licence"},"2":{"join_in":"t.actif","join_out":"1"}},"table":"terminaux","as":"t"}},"where":{"1":{"index":"CONCAT_WS('', c.prenom, c.nom, c.email, c.siren)","operand":"LIKE","value":"%necas%"}},"group":{"1":{"index":"c.id_client"}},"order":{"1":{"index":"c.nom"},"2":{"index":"c.id_client"}},"offset":"0","limit":"3","resultFormat":"<tr class=\"result\"><td>$$id_client##<\/td><td>$$nom## $$prenom##<\/td><td>$$email##<\/td><td>$$nombre_licences##<\/td><td><button class=\"btn btn-xs btn-success\" onclick=\"location.href='\/admin\/view\/$$id_client##'\" ><i class=\"fa fa-search\" aria-hidden=\"true\"><\/i> Voir<\/button><\/td><\/tr>"}
And then I get :
$matches = [[], []]
I tested this a couple times on different regex testers like regex101 without getting any match...
Please note that I can't modify this code too much.
Thanks for the help, Jm56Z
_
EDIT:
It seems like preg_match_all() sets $matches to an array containing two times the matches array :
$matches = [[matches], [matches]]

Solution :
preg_match_all() puts all matches in a multidimentional array even if it doesn't find any.
By default :
[[matches of the full regex], [matches of group 1], [matches of group 2]...]
Next time I'll read documentation with more attention.
https://php.net/manual/fr/function.preg-match-all.php

It seems the regex itself is wrong. For the given JSON sample, please try:
"(add|alter|create|delete|drop|exec|insert|set|table|truncate|update|view)[\w% ]*":

Related

"encapsulate" a whole part in a html query?

It might sound odd, but I want to send "hierarchical" html-query's == queries that contain queries and sub-queries (to a PHP based system).
The idea is that the first parse_str() will just convert the "outer part" into an array leaving all the "inner party untouched (unlike it is done with %26 that is converted to "&" anywhere).
So, what I search for is kind of a "escape begin / escape end" type of char(s) that make the HTML parser to leave all inside the escape untouched.
Therefor, the "first" parse would deliver an array of queries (and values, if these are not "escaped").
Basically I my ideal query would look like this - where "{" and "}" are the escape begin/end chars:
"key1=abc&query[]={this_is_a_query}&query[]={and_yet_another}"
where {this_is_a_query} would be: "k1=abc&k2=100" and {and_yet_another} would be "k1=xyz&k2=200".
So, fully written:
"key1=abc&query[]={k1=abc&k2=100}&query[]={k1=xyz&k2=200}"
As a result, i would like to get an assoc array that holds "parsable" values that are queries themselfs:
key1=>abc
query[0] => "k1=abc&k2=100"
query[1] => "k1=xyz&k2=200"
I know that I can do that with "%26", but that only works in the "first hierarchy", but not for "queries/in-queries/in-queries" (and so forth)
What I want to achieve is kind of a "batch query" that allows for running multiple programs with one single call.
I hope my description above is understandable?
Sorry, it looks like I did not well express mself. To clearify, I wtry to mak another example, think about parse_str() would have "{}" as chars enclosing what it should not touch:
received string:
step[]={scene[]={dim=10&item=kitchenlamp}&scene[]={item=sprinkler&state=on}}&step[]=delay=20&step[]={scene[]={item=sprinkler&state=off}}
first parse_str would return:
step[0]=>scene[]={dim=10&item=kitchenlamp}&scene[]={item=sprinkler&state=on}
step[1]=>delay=20
step[2]=>scene[]={item=sprinkler&state=off}
My function would now iterate the steps 0..1..2 and hand over the values to the next function that also uses parse_str to aquire it's parameters and so forth.
The sub-function of step 1 would itself get an array and loop it ... apssing the parameters to the "scene" function that itself would dismantle the parameters of what to be done
step 2 would be a direct execution ... wait 10 seconds
step 3 would again get an array of scenes that it would hand over to the scene function.
I hope it's more clear now, what my direction goes to.
Especially that there are same "keys" for some different parts of the "action chain string".
Why I want it this way is the fact that 1.) the sending device has no similar function like http_build_query 2.) the parameters shall be entered by users (not programmers) in an INI-like file.
One way of doing it would be to urlencode the whole "part":
$part="key1=abc&query[]={k1=abc&k2=100}&query[]={k1=xyz&k2=200}";
$href="https://somepage.com?part=".urlencode($part);
// this will result in
// https://somepage.com?part=key1%3Dabc%26query%5B%5D%3D%7Bk1%3Dabc%26k2%3D100%7D%26query%5B%5D%3D%7Bk1%3Dxyz%26k2%3D200%7D
see a little demo here: https://rextester.com/NLBOA61240
Alternatively you could also json_encode() it:
$part=["key1"=>"abc","query"=>[["k1"=>"abc","k2"=>100],["k1"=>"xyz","k2"=>200]]];
$href="https://somepage.com?part=".urlencode(json_encode($part));
On the receiving end you can then easily json_decode() the string you get in $part.
see here: https://rextester.com/UZGV97528

Regex for URL with multuple parameters

Im trying to compile a regular expression to match a URL in the following form:
http://www.example.com/param_1/param_2/.../param_n/?var_1=val_1&var2_=val_2&...val_n=var_n
In other words, the URL would have several subdirectories (param_1 - param_n) that need to be matched explicitly, and an unknown number of GET variables that need to be carried along with the URL without invalidating the match.
(Ive seen other topics for matching one, or two, or three GET variables but none for a general regex expression matching multiple variables who's total number is unknown)
I have the following Regex working for the following URL:
URL: http://www.example.com/users/john/
REGEX: "users\/john\/([a-z|A-Z|0-9|-]+)([\/]{0,1})\/([a-z|A-Z|0-9|-]+)([\/]{0,1})$/"
RESULT: MATCH!! :)
But the addition of "GET" variables (http://www.example.com/users/john/?car=blue) does not lead to a match (obviously).
I am not a regex guru and pretty sure what I have working probably isn't very elegant to begin with, but I have had no luck at all making it work with additional variables.
I am matching patterns in the following way:
$routes = array(~~ REGEX => controller script ~~);
foreach($routes as $pattern=>$ctrl){
if(preg_match($pattern, URI)) {
echo 'MATCH!!';
break;
}
}
First extract all params and all key-vals separately:
key-vals vvvv
^https?:\/\/[^\/]+((?:\/[^?]+)*)?(?:\?(.+))?$
^^^^^^^^^^^^^^^ params
For the example url, params = /param_1/param_2/.../param_n and key-vals = var_1=val_1&var2_=val_2&...val_n=var_n.
If params were extracted, get each individual param (use global to get every one):
\/([^\/]+)
^^^^^^^^ individual param
If key-vals were extracted, get each individual key and value (also use global):
vvvvvvv value
([^=]+)=([^&]+)
^^^^^^^ key
Sorry I can't help with the PHP, but this should point you in the right direction.
Thank you for your replies! The following regex ended up working for me:
/^\/param_1\/param_2\/...\/param_n\/?(\?.*)?$/

Adding characters to str_replace in PHP

I have a php file with thread ($tid) and post ($pid) ids defined and I'm looking to use str_replace to combine them and create my desired output (below) with &p= added:
Desired output:
$tid&p=$pid
The closest I've got is doing this:
$tid=$t1;
$pid=$p1;
$tid=str_replace("$tid","$tid"."$pid",$tid);
The result is:
$tid$pid
I may need to use a function (not sure which if so?) in the str_replace to support the &p= being added, as trying to add it in the quotes directly doesn't seem to work resulting only in database errors.
Edit #1: I tried doing the following based on the comments thus far:
$tid="";
$tid.="$t1";
$tid.="$p1";
$tid=$tid;
That results in the same as my previous example above:
$tid$pid
As soon as I add another with the &p= I get a database error:
$tid.="&p=";
So my question now is how to add the &p= to my Edit #1 example above correctly?
I'm attempting to understand the question a little bit. You have a couple options that are alluded to in the comments above. You could, for instance (where '1', '2', and '3' are replaced by the desired values):
<?php
$tid=1;
$pid=2;
$amp=3;
$tid=str_replace("$tid","$tid".'$amp;p='."$pid",$tid);
echo $tid;
?>
Here you can just explicitly state in the 'replace' argument of str_replace that the missing string should be part of the replacement string.
or you could also simply use the a concatenation operator to generate the string you desire which is probably simpler given what (little) I know of the surrounding code/use-case:
<?php
$tid=1;
$pid=2;
$amp=3;
echo "$tid".'$amp;p='."$pid";
?>
The reason I'd recommend the latter, is due to the fact that it's less resource intensive to actually produce the desired result which appears to just be a string. str_replace() searches the "haystack" or subject string using the search string and then must replace each of the found instances with the replace string.

What's the most efficient way to grab data from this particular file?

I'm trying to think of the most efficient way to parse a file that stores names, studentids and Facebook ids. I'm trying to get the fbid value, so for this particular line it would be: 1281766051. I thought about using regex for this, but I'm a bit lost as to where to start. I thought about adding all this data to an array and chopping away at it, but it just seems inefficient.
{"name":"John Smith","studentid":"10358595","fbid":"1284556651"}
I apologise if the post is too brief. I'll do my best to add anything that I might have missed out. Thanks.
Well, this seems to be JSON, so the right way would be
$json = json_decode($str);
$id = $json->fbid;
The regex solution would look like this:
preg_match('/"fbid":"(\d+)"/', $str, $matches);
$id = $matches[1];
But I cannot tell you off the top of my head which of these is more efficient. You would have to profile it.
UPDATE:
I performed a very basic check on execution times (nothing too reliable, I just measured 1,000,000 executions of both codes). For your particular input, the difference is rather negligible:
json_decode: 27s
preg_match: 24s
However, if your JSON records get larger (for example, if I add 3 fields to the beginning of the string (so that both solutions are affected)), the difference becomes quite noticeable:
json_decode: 46s
preg_match: 30s
Now, if I add the three fields to the end of the string, the difference becomes even larger (obviously, because preg_match does not care about anything after the match):
json_decode: 45s
preg_match: 24s
Even so, before you apply optimizations like this, perform proper profiling of your application and make sure that this is actually a crucial bottleneck. If it is not, it's not worth obscuring your JSON-parsing code with regex functions.
That's JSON, use:
$str = '{"name":"John Smith","studentid":"10358595","fbid":"1284556651"}';
$data = json_decode($str);
echo $data->fbid;
Cheers
Use json_decode
$txt='{"name":"John Smith","studentid":"10358595","fbid":"1284556651"}';
$student =json_decode($txt);
echo $student->fbid;

Getting array param out of query string with PHP

(NOTE: This is a follow up to a previous question, How to pass an array within a query string?, where I asked about standard methods for passing arrays within query strings.)
I now have some PHP code that needs to consume the said query string- What kind of query string array formats does PHP recognize, and do I have to do anything special to retrieve the array?
The following doesn't seem to work:
Query string:
?formparts=[a,b,c]
PHP:
$myarray = $_GET["formparts"];
echo gettype($myarray)
result:
string
Your query string should rather look like this:
?formparts[]=a&formparts[]=b&formparts[]=c
If you're dealing with a query string, you are looking at the $_GET variable. This will contain everything after the ? in your previous question.
So what you will have to do is pretty much the opposite of the other question.
$products = array();
// ... Add some checking of $_GET to make sure it is sane
....
// then assign..
$products = explode(',', $_GET['pname']);
and so on for each variable. I must give you a full warning here, you MUST check what comes through the $_GET variable to make sure it is sane. Otherwise you risk having your site compromised.

Categories