Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

preg_match and arrays 1

Status
Not open for further replies.

jasc2k

Programmer
Nov 2, 2005
113
GB
Hi all,

Below is a function I have wrote for remembering previous URL vars that have been posted. i.e I have a mail section on my site where you can sort by different things like date or subject. they can also choose to sort asc or desc - my function will remember their previous choice and/or update it accordingly.

If anyone has any suggestions code samples to improve this please post them but in short my issue lies with my preg_match statement. Some vars sent via the URL are not wanted to be remembered i.e delete (for obvious reasons.)

I am attempting to preg_match multiple regex's but I believe its wrong (well it does not work :eek:)). I have used the /blah/ operators as this may only be a partial match on one side.

Code:
/**
    * remURL - this little function will
    * remember any url and update new vars
    */
 function remURL($var,$value){
  //$url = '';
  $i=0;
  $url = $_SERVER['REQUEST_URI'];
  $arr_var = explode(',', $var);
  $arr_value = explode(',', $value);
  
 //SOMETHING IS WRONG IN HERE - preg_match wrong???? post in a forum????
  /* Firstly cleanse the URL for any vars not wanted to be reposted */
 //if($url != ''){
  $urlpieces = explode('&', $url);
  foreach($urlpieces as $key => $val) {
   /* Dont remember certain vars in URL (separator |) */
   //if(preg_match("/=delete/", $val) || preg_match("/=markread/", $val) || preg_match("/=markunread/", $val) || preg_match("/pstid=/", $val) || preg_match("/msgid=/", $val)) {
   if(preg_match("(/=delete/|/=markread/|/=markunread/|/pstid=/|/msgid=/)", $val)){
    /* If the var is the one being posted remember it this time */
    $pos = strpos($val, $arr_var[$key]);
    if($pos === false){ unset($urlpieces[$key]); 
    echo "unset :".$urlpieces[$key]; }
   }
  }
  /* Create new array and put back into a string */
  $new_url = array_values($urlpieces);
  $url = implode("&",$new_url);
 //}
  
  
  

  while($i < count($arr_var)){ 
   if(isset($_GET[$var[$i]]) && $_GET[$var[$i]] != ""){
    /* Reply existing url with var modified */
    //$url = $_SERVER['REQUEST_URI'];
    if($arr_value[$i] != ''){
     $url = str_replace($arr_var[$i]."=".$_GET[$arr_var[$i]],$arr_var[$i]."=".$arr_value[$i],$url);
    } else {
     /* This will forget the var */
     $url = str_replace("&".$arr_var[$i]."=".$_GET[$arr_var[$i]],'',$url);
    }
   } else {
    /* Reply existing url with new var - remember to remove slash */
    if($arr_value[$i] != ''){ 
     $url .= "&".$arr_var[$i]."=".$arr_value[$i];
 //echo $url;  //substr_replace(BASE_URL,"",-1).$_SERVER['REQUEST_URI'].
     
    } else { // is this needed???????????
     $url = substr_replace(BASE_URL,"",-1).$_SERVER['REQUEST_URI'];
    }
   }
  $i++;
  } 
  return $url;
 }

 

 

usage:

<a class='deletesure' href='".$database->remURL('action,pstid',"delete,".$list['post_id'])."'>

Hope this makes sense to someone,
Thanks in advance
James
 
I had looked at it but I did not look much further into it because the address
echo "Query String: " . $myDomain["query"] . "<br>";
will return arg=value right?

my problem being I dont know what =value will be to match it?

Thanks
 
here is a function that will split a url more granularly and another that will assemble a url given certain input parameters

Code:
<?php
function assembleUrl($scheme, $host, $queryItems, $fragment=null){
	$queryItems = empty($queryItems) ? '' : '?' . http_build_query($queryItems);
	$fragment = empty($fragment) ? '' : '#' . $fragment;
	return $scheme . '://' . $host . $queryItems . $fragment;
}
function myparse_url($url){
  $bits = parse_url($url);
  parse_str($bits['query'], $queryItems);
  $bits['queryItems'] = $queryItems;
  return $bits;
}
?>

for example:
Code:
//url bits
$queryItems = array('var1'=>'val1', 'var2'=>'val2', 'var3'=>'£35');
$segment = 'segment';
$host = '[URL unfurl="true"]www.domain.com';[/URL]
$scheme = 'http';

//assemble the url
$url = assembleUrl($scheme, $host, $queryItems, $segments);

echo "Properly encoded url to test: " .$url ."\n";
echo "<pre>". print_r(myparse_url($url), true) . "</pre>";

you should get the response
Code:
Properly encoded url to test: [URL unfurl="true"]http://www.domain.com?var1=val1&var2=val2&var3=%A335[/URL]
Array
(
    [scheme] => http
    [host] => [URL unfurl="true"]www.domain.com[/URL]
    [query] => var1=val1&var2=val2&var3=%A335
    [queryItems] => Array
        (
            [var1] => val1
            [var2] => val2
            [var3] => £35
        )

)
//note if you are using utf charsets then the urlencoding of £ will not be the same (two characters)

using this you can compare the keys and values of queryItems to decide whether to keep them or not, then reassemble them for storage as you want.
 
hi there,

great reply that code works great and seems to be smoother
I do wonder if:
assembleUrl($scheme, $host, $queryItems, $segments);
should be $segment? or is that actually deliberate

I guess I just need to incoorporate this into my loops? will try that tonight and will post my results to let you know how I get on

Thanks,
 
you are absolutely right. really the variable should be, in both cases, $fragment.
 
ok so I have started to implement your code but I am unsure how to properly check the current URL for any vars that need changing as opposed to adding to the query?

for instance if the user sorts something by DESC it will add sort=desc to the URL but if the user then decides to change their sort I want to change the var value to ASC instead of adding another vr and value to the URL?

any ideas?
many thanks
 
surely you just re-parse the url? the sort variable will have changed and the fresh parsing will pick that up
 
sorry my mistake - am now at home fully testing, I did not realise it would do that too.

So what your saying is all that code I wrote is crap, lol
and your sample does everything I want

here is my sample usage:
Code:
echo "<a class='deletesure' href='".assembleUrl($scheme, $host, $queryItems, $segments)."'>url3 | </a>";

is there any particular reason why $scheme & $host are seperate vars?

thanks again - I swear I searched everywhere for something like that lol
 
sorry last question if you dont mind - what if the var in the URL has been set by another control/link how would I remeber that? using $_SERVER['REQUEST_URI']?
and then split that to check?

basically I have a page with comments on that the user can sort or delete. If I sort the list then resort its all great. If I want to sort then delete a post when I run the delete link I loose my sort?

I hope my explanation is ok my site is user name and pass: testing
If you wish to look. The code is in testing on the main status page.

Thanks again
 
sorry, have looked at your site and am not sure what you mean.

one comment though - i do not recommend using GET variables to trigger non-idempotent actions. it's a personal thing but based on sound logic. I also make sure that all non-idempotent actions are nonce'd to prevent loss of database integrity.
 
thats ok.

I would agree with the GET comment but I could not figure out any other way to start the relavant function without using jquery which I have even less knowledge on, lol

Not sure I know what nonce'd means but sounds like I need to do it?

Thanks
 
nonce is 'number used once'.
you don't have to use a nonce but you need to create a mechanism whereby a user cannot inadvertently action a non-idempotent transaction via a back button or similar.

to start a 'relevant function' use POST data just wrap the necessary information in <form> tags and set the method as post.
 
number used once - indeed I definatly have that issue with back button and refresh page, I will try and google some functions for that - thanks.

I sort of figured that nothing is secure so I just used the url to trigger actions but I guess form POST would at least stop the everyday user trigering these events. Not quite sure how to submit a form using a hyperlink will google this also.

Thanks you have been a great help - any more hints/ideas/snippets again would be appreciated.
 
going to try styling the buttons to 'llok' like hyperlinks:

as for the nonce'ing I have an xsrf script I am part way through implementing that I will try to build together:

Unfortunatly I cannot seem to figure out how to use this code more than once on a page as its only ever the last key generated that authenticates!

Thanks
 
here is some code for nonces. you can create whatever nonce you want (and multiple nonces) by adding a type parameter

Code:
<?php


function getNonce($type='basic'){
	if (empty($_SESSION['nonce'][$type])){
		setNonce($type);
	}
	return $_SESSION['nonce'][$type];
}

function setNonce($type='basic'){
	$uid = uniqid('nonce_' . $type, true);
	$_SESSION['nonce'][$type]=$uid;
}

function checkNonce($type = 'basic', $val = null){
	if (!isset($_SESSION['nonce'][$type])) return false;
	if (empty($val)) return false;
	if ($val != $_SESSION['nonce'][$type]) return false;
	unset($_SESSION['nonce'][$type]);
	return true;
}

?>

hopefully the usage is obvious but post back if you need.
 
ideal thanks for the snippet. Nice easy code am pretty sure I understand it. Usage should be easy.

Will try and implement tonight..

Again many thanks
 
actually it's probably better/easier to recast the checknonce function as shown

Code:
function checkNonce($type = 'basic'){
    $val = !empty($_POST['nonce']) ? trim($_POST['nonce']) : !empty($_GET['nonce'] ? trim($_GET['nonce']) : NULL;
    if (!isset($_SESSION['nonce'][$type])) return false;
    if (empty($val)) return false;
    if ($val != $_SESSION['nonce'][$type]) return false;
    unset($_SESSION['nonce'][$type]);
    return true;
}

also you might find this code useful

Code:
function getNonceFormField($type = 'basic'){
     $nonce = getNonce($type);
     return '<input type="hidden" name="nonce" value="'.$nonce.'" />';
}

you do need to make sure that there is only one nonce field per form that gets submitted. this would normally be the case.

postdata overrides any nonce in the query string too. this is logical.
 
sweet nice code for the auto form field generator that should simplify things.
what if I had two forms on one page is there anyway I can nonce them both - or could I perhaps use the same nonce multiple time on one page (though I include various pages so that might be tricky unless I generate a nonce on the main index page to be used on any form loaded at the time, what do you think?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top