Check if part of a string is a number - php

Im building an API which can read messages from a SQL database. I check the URL with the following if statement: if ($uri[0] == "/rooms/1/messages"). The 1 is the room number requested, but there are more rooms than "1".
What I want is an if statement like this: if ($uri[0] == "/rooms/" . $thisHasToBeANumber . "/messages")
I have thought about exploding the URL on the "/" but I dont know from the beginning how much slashes there are in the URL.
My whole function:
function checkUrl()
{
// Variables about URL, first explode with "api" then with "?"
$uri = explode('api', $_SERVER['REQUEST_URI']);
$uri = explode('?', $uri[1]);
// Check the url path for "/rooms/1/messages/" and check request method
if ($uri[0] == "/rooms/ " . $thisHasToBeANumber . "/messages") {
if ($_SERVER["REQUEST_METHOD"] === "GET") {
$roomId = explode('/', $uri[0])[2];
getMessages($roomId);
} else {
header("HTTP/1.0 400");
die("Wrong request method");
}
}
// Check the url path for "/messages/" and check request method
elseif ($uri[0] == "/messages") {
if ($_SERVER["REQUEST_METHOD"] === "POST") {
// Get POST parameters
$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE);
if (!empty($input['content']) && !empty($input['roomId'])) {
$messageContent = $input['content'];
$roomId = $input['roomId'];
$userId = getUserId($_GET['token']);
sendMessage($userId, $messageContent, $roomId);
} else {
header("HTTP/1.0 400");
die("Missing arguments");
}
} else {
header("HTTP/1.0 400");
die("Wrong request method");
}
}
// Check the url path for "/rooms/" and check request method
elseif ($uri[0] == "/rooms") {
if ($_SERVER["REQUEST_METHOD"] === "GET") {
getRoomNames();
} else {
header("HTTP/1.0 400");
die("Wrong request method");
}
}
// Path is not found
else {
header("HTTP/1.0 404");
die("Path not found");
}
}```

I think you are looking for regular expressions.
And preg_match ( documentation ) is the thing you are looking for.
If we do something like this:
if ( ( preg_match( "rooms/([\d]+)/messages", $uri[0], $match ) === 1 ) {
if ($_SERVER["REQUEST_METHOD"] === "GET") {
//$roomId = match[1];
getMessages($match[1]);
} else {
header("HTTP/1.0 400");
die("Wrong request method");
}
}
!Note
The reason why we use preg_match( ... ) === 1 is because of the return value.

I don't know exactly what kind of data you will receive, but it looks like you can use a regular expression. For example, assume that $uri is the string and you want a number in the format: "/room/NUMBER/messages". You can use:
preg_match("~/room/([0-9]+)/messages~", $uri, $matches);
If the pattern fits, $matches[1] will contain the room number.
You can put this into an if-else with:
if(isset($matches[1])) {
$roomnumber = $matches[1];
// do what you want
} else {
// There is no room number
}

I would expect the URL to always come in the same format, so using explode should be safe. You would need to work out what the format was and then extract the number from the right position.
Alternatively, you could use RegEx. That will allow you to be more flexible in extracting the room number. Some example code you could use would be:
$uri = '/room/123/abc'; // test code
if (preg_match('/(^|\/)room\/(\d+)($|\/)/', $test, $matches)===1) {
$roomId = $matches[2];
} else {
// no match
}
To explain, preg_match will take a RegEx pattern and apply it to the URL and return an array of matches. The RegEx in the example will look for the sequence "room/" following a slash or at the beginning of your URL and then followed by one or more numerical digits (which are returned in the array) and finally by either another slash or the end of the string. The numerical digits are returned as the third match.

Related

how to secure $_GET

I'm trying to secure my $_GET inputs everything are working the problem is $_GET['action'] can't pass preg_match() and always resulta in:
"action is not valid"
I don't know why it's happening, the action can have only two values like or hate which both are in lowercase but still can't pass it.
if(isset($_GET['username']) && isset($_GET['action']))
{
$username = $_GET['username'];
$action = $_GET['action'];
$user_filter_a = mysqli_real_escape_string($username);
$user_filter_b = mysqli_real_escape_string($user_filter_a);
$user_filter_c = strip_tags($user_filter_b);
$action_filter_a = mysqli_real_escape_string($action);
$action_filter_b = mysqli_real_escape_string($action_filter_a);
$action_filter_c = strip_tags($action_filter_b);
$action_filter_c_lower = strip_tags($action_filter_b);
if(preg_match('%^[a-z0-9\.]{4,69}$%',$user_filter_c))
{
if(preg_match('%^[a-z]$%',$action_filter_c_lower))
{
if($action_filter_c_lower=='like')
{
echo 'you have liked this post';
}elseif(action_filter_c_lower=='hate')
{
echo 'you have hated this post';
}
}else
{
echo 'action is not valid';
}
}else
{
echo 'username is not valid';
}
When you need to validate that a string is completely comprised of letters, you can use ctype_alpha().
Code: (Demo)
$string = 'asdgadsfg';
if (ctype_alpha($string)) {
echo "all alphabetical";
} else {
echo "not entirely alphabetical";
}
Output:
all alphabetical
If you need to check if a submitted value is like, hate, or [something else]; create a "whitelist" array to look up the value.
Code: (Demo)
$string = 'like';
$whitelist = ['like', 'hate'];
if (in_array($string, $whitelist)) {
echo "valid: $string";
} else {
echo "invalid: $string";
}
Output:
valid: like
Additional tips:
if(isset($_GET['username']) && isset($_GET['action']))
can be written more simply as:
if (isset($_GET['username'], $_GET['action'])) {
You shouldn't be performing escaping until just before applying the data to the query, this way you don't accidentally mangle your data or confuse yourself. Honest, I always use prepared statements to build a query with user-submitted data, so I'll recommend that you research that topic.
In your regular expression, you don't need to escape a dot inside of a character class so the character class can look like this: [a-z0-9.] If you also wish to allow capital letters, you can add i after the end pattern delimiter (%) so that it looks like %^[a-z0-9.]{4,69}$%i or %^[a-z\d.]{4,69}$%i.
_lower is a strange thing to append to your variable name, because you aren't calling any functions that force the string to lowercase.
The total number of actions is limited. It is more secure to not use the user input at all. Instead, use a switch statement with a default action:
$userAction = strtolower($_GET['action']);
switch($userAction) {
case "like":
$action = "like";
break;
case "hate":
$action = "hate";
break;
default:
$action = "default-action";
}
Or, you can have the list of valid actions in an array:
$validAction = ["like","hate","other"];
$action = "";
if (in_array($_GET["action"],$validAction)){
$action = $_GET["action"];
}
Here you have the guarantee that the action is valid.

Detect if URL equals to value and preforme action

I want to make action if the current url only equals to this: https://www.example.co.il/index.php?id=1000&2222
$url = 'https://www.example.co.il/index.php?id=1000';
if(strpos($url,'&2222'))
{
// Do something
echo "2222";
}
else
{
// Do Nothing
}
To exactly do what you are asked, try this
//actual link (http or https)
$actualUrl = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$url = 'https://www.example.co.il/index.php?id=1000';
if($actualUrl === $url) {
//do something
}
But if you just want to retrieve the id :
$id = $_GET('id');
//return 1000 in your case
You're able to read the parameters in the URL using the $_GET object. It lists the keys and values in the querystring, i.e. in your example,
https://www.example.co.il/index.php?id=1000
if you use:
print $_GET['id'];
you'll see 100.
so you could simply check for the existence of the key 2222:
if (isset($_GET['2222'])) { /** do something **/ }
bear in mind, this is only the case if you're actually reading a URL the script is running on.
your method of searching for a string within the URL is appropriate if you simply want to match a value in a string, whether its a URL or not.
USE THIS
// Assign your parameters here for restricted access
$valid_url = new stdClass();
$valid_url->scheme = 'https';
$valid_url->host = 'www.example.co.il';
$valid_url->ids = array(1000,2222);
$url = 'https://www.example.co.il/index.php?id=1000&2222';
$urlinfo = parse_url($url); // pass url here
$ids = [];
parse_str(str_replace('&', '&id1=', $urlinfo['query']), $ids);
if($urlinfo['scheme'] == $valid_url->scheme && $urlinfo['host'] == $valid_url->host && count(array_intersect($valid_url->ids, $ids)) == count($valid_url->ids)){
echo 'valid';
// Do something
}else{
echo 'in valid';
// error page
}

if / and statement for URL with strpos

I have the following three possible urls..
www.mydomain.com/445/loggedin/?status=empty
www.mydomain.com/445/loggedin/?status=complete
www.mydomain.com/445/loggedin/
The www.mydomain.com/445 part is dynamically generated and is different each time so I can't do an exact match, how can i detect the following...
If $url contains loggedin but DOES NOT CONTAIN either /?status=empty OR /?status=complete
Everything I try fails as no matter what it will always detect the logged in part..
if(strpos($referrer, '?status=empty')) {
echo 'The status is empty';
}
elseif(strpos($referrer, '?status=complete')) {
echo 'The status is complete';
}
elseif(strpos($referrer, '/loggedin/')) {
echo 'The status is loggedin';
}
Slice up the URL into segments
$path = explode('/',$referrer);
$path = array_slice($path,1);
Then just use your logic on that array, the first URL you included would return this:
Array ( [0] => 445 [1] => loggedin [2] => ?status=empty )
You could do something like this:
$referrer = 'www.mydomain.com/445/loggedin/?status=empty';
// turn the referrer into an array, delimited by the /
$url = explode('/', $referrer);
// the statuses we check against as an array
$statuses = array('?status=complete', '?status=empty');
// If "loggedin" is found in the url, and count the array_intersect matches, if the matches = 0, none of the statuses you specified where found
if( in_array('loggedin', $url) && count(array_intersect($url, $statuses)) == 0 )
{
echo 'The user is logged in';
}
// if the complete status exists in the url
else if( in_array('?status=complete', $url) )
{
echo 'The status is complete';
}
// if the empty status exists in the url
else if( in_array('?status=empty', $url) )
{
echo 'The status is empty';
}
I would recommend looking at array_intersect, it is quite useful.
Hope it helps, not sure if this is the best way of doing it, but might spark your imagination.
Strpos is probably not what you want to use for this. You could do it with stristr:
if($test_str = stristr($referrer, '/loggedin/'))
{
if(stristr($test_str, '?status=empty'))
{
echo 'empty';
}
elseif (stristr($test_str, '?status=complete'))
{
echo 'complete';
} else {
echo 'logged in';
}
}
But it's probably easier/better to do it with regular expressions:
if(preg_match('/\/loggedin\/(\?status=(.+))?$/', $referrer, $match))
{
if(count($match)==2) echo "The status is ".$match[2];
else echo "The status is logged in";
}

PHP GET String with explode and if statements

I am writing what I thought would be a simple script but I am stuck.
The scenario is that I want to create 2 strings from the GET request.
eg: domain.com/script.php?Client=A12345
In script.php it needs to grab the "Client" and create 2 variables. One is $brand and needs to grab the A or B from the URL. The Other is $id which needs to grab the 12345 from the URL.
Now, after it has these 2 variables $brand and $id it needs to have an if statement to redirect based on the brand like below
if ($brand=="A") {
header('Location: http://a.com');
}
if ($brand=="B") {
header('Location: http://b.com');
At the end of each URL I want to apend the $id though and I am unsure on how to do this.
So for example I would access the script at domain.com/script?Client=A1234 and it needs to redirect me to a.com/12345
Thanks in advance!
$fullCode = $_REQUEST['Client'];
if(strpos($fullCode, 'A') !== false) {
$exp = explode('A',$fullcode);
header('Location: http://a.com/' . $exp[1]);
}
else if(strpos($fullCode, 'B') !== false) {
$exp = explode('B',$fullcode);
header('Location: http://b.com/' . $exp[1]);
}
else {
die('No letter occurence');
}
You can easily do,
$value = $_GET['Client'];
$brand = substr($value, 0, 1);
$rest = substr($value, 1, strlen($brand)-1);
now you have the first character in $brand string and you can do the if statement and redirect the way you want...
You mean like this?
Notice: this will only work if brand is just 1 character long. If that's not the case, please give better examples.
<?php
$client = $_GET['Client'];
$brand = strtolower(substr($client, 0, 1));
$id = substr($client, 1);
if ($brand == 'a')
{
header("Location: http://a.com/$id");
}
elseif ($brand == 'b')
{
header("Location: http://b.com/$id");
}
?>
Try using:
preg_match("/([A-Z])(\d*)/",$_GET['Client'],$matches);
$matches[1] will contain the letter and $matches[2] will contain your id.
Then you can use:
if ($matches[1]=="A")
{
header('Location: http://a.com/{$matches[2]}');
}
if ($matches[1]=="B")
{
header('Location: http://b.com/{$matches[2]}');
}
suggest you could also try
$requested = $_GET["Client"];
$domain = trim(preg_replace('/[^a-zA-Z]/',' ', $requested)); // replace non-alphabets with space
$brand = trim(preg_replace('/[a-zA-Z]/',' ', $requested)); // replace non-numerics with space
$redirect_url = 'http://' . $domain . '/' . $brand;
header('Location:' . $redirect_url);
but it'd be better if you could get the domain name and brand as two individual parameters and sanitize them individually before redirecting them to prevent the overhead of extracting them from a single parameter.
Note: this expression might be useless when the domain name itself has numerics and because the Client is obtained through get a good deal of validation and sanitation would be required in reality.
$brand = strtolower($_GET['Client'][0]);
$id = substr($_GET['Client'], 1);
header("Location: http://{$brand}.com/{$id}");
If for some purpose you want to use explode, then you need to have a separator.
Let's take '_' as the separator, so your example would be something like this: domain.com/script.php?Client=A_12345
$yourstring = explode("_",$_GET["Client"]);
echo $yourstring[0];
//will output A
echo $yourstring[1];
//will output 12345
//your simple controller could be something like this
switch($yourstring[0]){
case: 'A':
header('Location: http://a.com?id='.$yourstring[1]);
exit();
break;
case: 'B':
header('Location: http://b.com?id='.$yourstring[1]);
exit();
break;
default:
//etc
}

How to parse a youtube url to obtain the video or playlist ids?

I'm looking for a way to extract both (partials) youtube urls and single ids from a user input string.
This article How do I find all YouTube video ids in a string using a regex? got me going quite well but still i'm struggling a bit.
Is there a way to find both playlist and/or video ids from a strings from:
E4uySuFiCis
PLBE0103048563C552
Through:
?v=4OfUVmfNk4E&list=PLBE0103048563C552&index=5
http://www.youtube.com/watch?v=4OfUVmfNk4E&list=PLBE0103048563C552&index=5
use:
$urlInfo = parse_url($url); // to get url components (scheme:host:query)
$urlVars = array();
parse_str($queryString, $urlVars); // to get the query vars
check out the youtube api for more details on the format
I wrote a script to do this once where the YouTube URL is posted via "POST" under the key "l" (lowercase "L").
Unfortunately I never got round to incorporating it into my project so it's not been extensively tested to see how it does. If it fails it calls invalidURL with the URL as a parameter, if it succeeds it calls validURL with the ID from the URL.
This script may not be exactly what you're after because it ONLY retrieves the ID of the video currently playing - but you should be able to modify it easily.
if (isset($_POST['l'])) {
$ytIDLen = 11;
$link = $_POST['l'];
if (preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $link)) {
$urlParts = parse_url($link);
//$scheme
//$host
//$path
//$query["v"]
if (isset($urlParts["scheme"])) {
if ( ($urlParts["scheme"] == "http" ) || ($urlParts["scheme"] == "https") ) {
//$scheme = "http";
} else invalidURL($link);
} //else $scheme = "http";
if (isset($urlParts["host"])) {
if ( ($urlParts["host"] == "www.youtube.com") || ($urlParts["host"] == "www.youtube.co.uk") || ($urlParts["host"] == "youtube.com") || ($urlParts["host"] == "youtube.co.uk")) {
//$host = "www.youtube.com";
if (isset($urlParts["path"])) {
if ($urlParts["path"] == "/watch") {
//$path = "/watch";
if (isset($urlParts["query"])) {
$query = array();
parse_str($urlParts["query"],$query);
if (isset($query["v"])) {
$query["v"] = preg_replace("/[^a-zA-Z0-9\s]/", "", $query["v"]);
if (strlen($query["v"]) == $ytIDLen) {
validUrl($query["v"]);
} else invalidURL($link);
} else invalidURL($link);
} else invalidURL($link);
} else invalidURL($link);
} else invalidURL($link);
} else invalidURL($link);
} else invalidURL($link);
} else invalidURL($link);
}

Categories