I have a feeling I'm being very silly, but go easy on me as I'm very new to PHP.
So as part of an application, I'm building, I allow users to generate a URL that can be used to access some of their data from outside the platform. The URL is constructed by the PHP script based on URL parameters in the users browser (fear not, the parameters only allow the passing of integers to prevent abuse).
So to create the URL that will be shared, the script does this:
https://example.com/shared.php?function=form&account=<?php echo $userid; ?>&form=<?php echo $myform; ?><?php if (isset($_GET['ref'])) { echo '&ref='.$ref; } ?><?php if (isset($_GET['upload'])) { echo '&upload='.$upload; } ?>&key=<?php echo $key; ?><?php if (isset($_GET['saving'])) { echo '&saving='.$_GET['saving']; } ?><?php if (isset($_GET['expdate'])) { echo '&expdate='.$expdate; } ?><?php if (isset($_GET['enc'])) { echo '&enc='.$enc; } ?>
I know I don't need to keep opening and closing the PHP tag, but it was just easier visually when I was putting everything together.
Anyway, the above does a good job at spitting out the URL, but if I want to add the final URL to a variable, how can I do it?
Obviously, normally it would be trivial:
$whatever = 'https://example.com/shared.php?function=form&account='.$variable.'&something='.$variable2.'etc etc
But because I've got if statements that check for URL parameters, I'm not sure how to accomplish it.
You can concatenate strings with the . operator, you don't need to build the URL at once. However, in this case, it'd be easier to just use the builtin http_build_query() function. Populate an array as you validate parameters and feed it to the function when done.
P.S. Don't trust client-side validations. People may not care to enforce them when they type in the browser location bar.
Big thanks to everyone that made suggestions. In the end I went with the following:
$array = array(
'account' => $userid,
'form' => $myform,
'key' => $key,
);
if (isset($_GET['ref'])) {
$array['ref'] = $ref;
}
if (isset($_GET['upload'])) {
$array['upload'] = $upload;
}
if (isset($_GET['saving'])) {
$array['saving'] = $_GET['saving'];
}
if (isset($_GET['expdate'])) {
$array['expdate'] = $expdate;
}
if (isset($_GET['enc'])) {
$array['enc'] = $enc;
}
$finalURL = http_build_query($array);
Works perfectly.
You can always prepare parameters before putting into string. Or there is ternary operator ?:
$ref = $_GET['ref'] ? '&ref=' . $_GET['ref'] : '';
$upload = $_GET['upload'] ? '&upload=' . $_GET['upload'] : '';
$saving = $_GET['saving'] ? '&saving=' . $_GET['saving'] : '';
$expdate = $_GET['expdate'] ? '&expdate=' . $_GET['expdate'] : '';
$enc = $_GET['enc'] ? '&enc=' . $_GET['enc'] : '';
$whatever = "https://example.com/shared.php?function=form&account={$userid}&form={$myform}{$ref}{$upload}&key={key}{$saving}{$expdate}{$enc}";
Or make it dynamic using http_build_query():
$params = [
'function' => 'form',
'account' => $userid,
'form' => $myform,
'key' => $key,
'ref' => $_GET['ref'] ?? null,
'upload' => $_GET['upload'] ?? null,
...
];
$url = 'https://example.com/shared.php?';
// array_filter will remove any empty value
$url .= http_build_query(array_filter($params));
Related
Good Day,
Below I have provided 2 codes, which I did not write but grabbed from a forum. I really need to learn the solution to this new mystery. Both make use of the urlencode(). They are nearly the same code.
I notice that, only the 1st code's output is normal and not encoded while the 2nd one's output is encoded. Why ?
Since both are making use of the urlencode() then shouldn't both their outputs be in encoded format ? This has been greatly puzzling me for days now. I give-up. What's the mystery behind this ?
1st Code:
$url = 'http://nogdog.com/cat/subcat?var 1=value 1&var2=2&this other=thing&number is=12';
echo prepare_url($url) . "\n";
function prepare_url($url) {
$url_parts = parse_url($url);
if($url_parts === false or empty($url_parts['host'])) {
return false;
}
$url_out = preg_match('/^https?/i', $url_parts['scheme']) ? strtolower($url_parts['scheme']) : 'https';
$url_out .= "://{$url_parts['host']}{$url_parts['path']}";
if(!empty($url_parts['query'])) {
parse_str($url_parts['query'], $query_parts);
foreach($query_parts as $q_key => $q_value) {
$query_string_parts[] = urlencode($q_key).'='.urlencode($q_value);
}
$url_out .= '?'.implode('&', $query_string_parts);
}
return $url_out;
}
2nd Code:
function prepare_url2($url) {
$url_parts = parse_url($url);
if($url_parts === false or empty($url_parts['host'])) {
return false;
}
// re-assemble the start of url string
$url_start = preg_match('/^https?/i', $url_parts['scheme']) ? strtolower($url_parts['scheme']) : 'https';
$url_start .= "://{$url_parts['host']}{$url_parts['path']}";
// rawurlencode the start of url string
$url_out = rawurlencode($url_start);
if(!empty($url_parts['query'])) {
parse_str($url_parts['query'], $query_parts);
foreach($query_parts as $q_key => $q_value) {
// assemble and check if value is numeric
$query_string_parts[] = urlencode($q_key).'='.(is_numeric($q_value) ? intval($q_value) :urlencode($q_value));
}
$url_out .= '?'.implode('&', $query_string_parts);
}
return $url_out;
}
$url = 'http://zorg.com/cat/subcat?var 1=value 1&var2=2&this other=thing&number is=13';
echo prepare_url2($url);
NOTE
The difference between the two codes are that, the 1st one defines the $url and calls the prepare_url() function at the top. (Before the prepare_url() function's code).
$url = 'http://nogdog.com/cat/subcat?var 1=value 1&var2=2&this other=thing&number is=12';
echo prepare_url($url) . "\n";
While, the 2nd one defines the $url and calls the prepare_url() function at the bottom. (After the prepare_url() function's code).
$url = 'http://zorg.com/cat/subcat?var 1=value 1&var2=2&this other=thing&number is=13';
echo prepare_url($url);
Apart from that, both codes are the same.
So, if both the codes are the same (so to speak), then why does the 1st code output like this:
http://nogdog.com/cat/subcat?var_1=value+1&var2=2&this_other=thing&number_is=12
And, why does the 2nd code output like this:
http%3A%2F%2Fzorg.com%2Fcat%2Fsubcat?var_1=value+1&var2=2&this_other=thing&number_is=13
I am trying to detect status of invoice from a json file, then if the status is a confirmed payment, update the status and write the json to a new location, then unlink the existing json location.
<?php
// get posted variables or die;
if (isset($_POST['num'])) {
$invoice = strip_tags($_POST['num']);
$filename = $invoice.'.json';
} else {
die;
}
if (isset($_POST['status'])) {
$status = strip_tags($_POST['status']);
} else {
die;
}
// get existing invoice
$content = file_get_contents('data/'.$invoice.'.json');
$data = json_decode($content, true);
// read json into variables
$email = $data['email'];
$id = $data['id'];
$addr = $data['tac_address'];
$os = $data['os'];
$exp = $data['experience'];
$hosting = $data['type'];
if (isset($data['telegram']) && $data['telegram'] != '') { $telegram = $data['telegram']; } else { $telegram = ''; }
if (isset($data['linkedin']) && $data['linkedin'] != '') { $linkedin = $data['linkedin']; } else { $linkedin = ''; }
if (isset($data['pay_status']) && $data['pay_status'] != '' && $data['pay_status'] == $status) { $status = $data['pay_status']; }
$payment_addr = $data['bitcoin'];
$payment_value = $data['value'];
$payment = substr($payment_value, 0, -4);
// turn variables into json array
$arr = array(
'id' => $invoice,
'email' => $email,
'tac_address' => $addr,
'os' => $os,
'experience' => $exp,
'type' => $hosting,
'telegram' => $telegram,
'linkedin' => $linkedin,
'bitcoin' => $payment_addr,
'value' => $payment_value,
'pay_status' => $status
);
$json = json_encode($arr);
// check status if paid save output to new location and delete old file
if ($status == 'Confirmed Payment') {
file_put_contents('paid_data/'.$filename, $json);
unlink('data/'.$filename);
}
The problem I am facing is that file_put_contents('paid_data/'.$filename, $json); ends up a file with a bunch of NULL variables. If I remove the unlink the variables save just fine, when I add it back the variables are all NULL.
So how can I verify file_put_contents takes place before the unlinking happens?
Also.... WHY does this happen? Isn't php supposed to be linear and shouldn't file_put_contents finish before the next line is carried out? Everything I have read about file_put_contents suggests as much. So why does the unlink take place before writing the content to a new location?
I still hope for a better answer, but so far this is my working solution to the problem. I changed the final if statement to the following. This seems to solve the issue - but there really has to be a better way than this. This feels very "hacky".
if ($status == 'Confirmed Payment') {
file_put_contents('paid_data/'.$filename, $json);
$i = 0;
while ($i < 1000) {
$i++;
if (file_exists('paid_data/'.$filename)) {
unlink('data/'.$filename);
break;
}
}
}
After mimicking your file structure and seeding a few examples, I was able to execute your code as is with the expected results. However, file_put_contents willreturn false on failure, so you might try something like this:
if ($status == 'Confirmed Payment') {
if(!file_put_contents('paid_data/'.$filename, $json);){
print_r(error_get_last());
die;
}
unlink('data/'.$filename);
}
Your code as originally written should be fine, as far as I can see. Usually when I see the kind of behavior you're describing, the problem is that the script itself is being called twice (or more) and overlapping calls are manipulating the same file.
I would definitely put in some debugging statements to verify this; I don't know your environment, but a simple line written to a log will probably be enlightening.
bit of a strange one that I've not been able to resolve for months so I finally have given in and have come here for the answer. Hopefully.
I have the below shortcode that when ran returns the phone number depending on what variable has a value. This PHP code works as expected, the one thing that doesn't work as expected however, is the first ever page load.
When someone goes to the site for the first time (or in incognito mode) the shortcode doesn't output anything, however, refresh the page just once and it'll display the output of the correct value and I have no idea why.
<?php function gw_cookie($atts) {
extract(shortcode_atts(array(
"value" => ''
), $atts));
$getVariable = isset($_GET[$value]) ? $_GET[$value] : '';
$newGetVariable = str_replace('_', ' ', $getVariable);
$cookiePhone = isset($_COOKIE[$value]) ? $_COOKIE[$value] : '';
$acfField = get_field('page_cookie_'.$value.'');
$optionsACF = get_field('options_company_details', 'options');
$area = $optionsACF['options_area'];
$phone = $optionsACF['options_telephone'];
if(!empty($cookiePhone) && $cookiePhone !== 'undefined') { //If cookie is not empty do the following
echo '1';
} elseif(!empty($newGetVariable)) { //If cookie is empty and get variable is not
echo '2';
} elseif($acfField) { //If ACF field is not empty do the following
echo '3';
} elseif ($value == "phone") {
return '4';
}
} add_shortcode("gw-cookie", "gw_cookie");
This codes file is being imported into the functions.php file using the following line:
require_once( __DIR__ . '/shortcodes/gw-cookies.php' );
A cookie itself would be created on the first run and your criteria requires cookiePhone which is why you have to refresh to make it work.
As per the comments, change:
$cookiePhone = isset($_COOKIE[$value]) ? $_COOKIE[$value] : '';
to:
$cookiePhone = isset($_COOKIE[$value]) ? $_COOKIE[$value] : NULL;
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
}
I'm trying to use the break concept, but I am also am using some built in PHP functions to only allow certain values into the get function.
$allowedKeys = array(
'route'
);
$options = array(
'chapter_1' => 'chapter_1',
'chapter_2' => 'chapter_2',
'chapter_3' => 'chapter_3'
);
$_GET = array_intersect_key($_GET, array_flip($allowedKeys));
if($_GET[$allowedKeys[0]] && array_key_exists($_GET[$allowedKeys[0]], $options)) {
if($_GET[$allowedKeys[0]] == $options[0]) {
/* This is where I'm trying to see if route=chapter_1 then do something.
The logic I'm trying to write is if the route is chapter_1 then print
out the content from chapter 1 How can determine this? */
echo "Hello";
}
}
Why isn't this code echoing "hello"?
Why make it more complex than it needs to be?
//check you have a route
$route = isset( $_GET['route'] ) ? $_GET['route'] : '';
switch( $route ) {
case 'chapter_1':
//do chapter one stuff
echo 'Chapter 1';
break;
case 'chapter_2':
//do chapter two stuff
echo 'Chapter 2';
break;
default:
echo 'Intro';
}
I'll answer your question directly for you. 'Hello' isn't showing because it is inside an if statement that isn't being triggered because either "if($_GET[$allowedKeys[0]] && array_key_exists($_GET[$allowedKeys[0]], $options))" or "if($_GET[$allowedKeys[0]] == $options[0])" is returning false.