I need some help with strpos().
Need to build a way to match any URL that contains /apple-touch but also need to keep specifics matching, such as "/favicon.gif" etc
At the moment, the matches are listed out individually as part of an array:
<?php
$errorurl = $_SERVER['REQUEST_URI'];
$blacklist = array("/favicon.gif", "/favicon.png", "/apple-touch-icon-precomposed.png", "/apple-touch-icon.png", "/apple-touch-icon-72x72-precomposed.png", "/apple-touch-icon-72x72.png", "/apple-touch-icon-114x114-precomposed.png", "/apple-touch-icon-114x114.png", "/apple-touch-icon-57x57-precomposed.png", "/apple-touch-icon-57x57.png", "/crossdomain.xml");
if (in_array($errorurl, $blacklist)) { // do nothing }
else { // send an email about error }
?>
Any ideas?
Many thanks for help
Instead of a regex, you could also remove all occurrences of your blacklist items with str_replace and compare the new string to the old one:
if ( str_replace($blacklist, '', $errorurl) !== $errorurl )
{
// do nothing
}
else
{
// send an email about error
}
If you want to use regex for this, and you want a single regex string that will capture all the values in your existing blacklist plus match any apple-touch string, then something like this would do it.
if(preg_match('/^\/(favicon|crossdomain|apple-touch.*)\.(gif|png|xml)$/',$_SERVER['REQUEST_URI']) {
//matched the blacklist!
}
To be honest, though, that's far more complex than you need.
I'd say you'd be better off keeping the specific values like favicon.gif etc in the blacklist array you already have; it'd make it a lot easier when you come to adding more items to the list.
I'd only consider using regex for the apple-touch values, since you want to block any variant of them. But even with that, it would likely be simpler if you used strpos().
Related
I have one array which contains multiple strings. I have another array which contain also strings but they are shorter. My goal is to check is there any partial match in the bigger array for every item from the smaller array. However preg_match doesnt work at all with variables. If I put raw input everything seems fine but otherwise results is false. I have tried almost every possible regex combination but without success. Sample code:
//Lets say $needle is 3333 and bigPatern has 10 records with 10 digits each, for example third record is 5125433331. I want to perform the partial match and get true
$needle = $smlPattern[0]; //debugging with first item from smaller array
$needle2 = "/$needle/"; // I tried [$needle], ^..&, to concatenate and etc
foreach ($bigPatern as $val)
{
if (preg_match($needle2, $val))
{
echo "YES";
}
}
Any tips what Im doing wrong?
Please escape your regex input!
$needle2 = "/".preg_quote($needle,'/')."/"; //
Don't blindly add user input to your regex, much for the same reason you need to escape user input in SQL queries. In regex, the biggest issue is usually the ReDoS problem, where a malicious user can create a specially crafted regex that will use hours, or more, to execute, stealing all the CPU from your server.
Main wrong thing in your example is to use regexp for checking the presence of a string. There is a strpos function for that.
if ( strpos($bigOne, $smallOne) !== false ) {
echo "bigOne contains smallOne";
}
You can even use strpos function to achieve the same purpose. It finds the position of the first occurrence of a substring in a string, and returns false if no match is found.
$needle = $smlPattern[0];
$needle2 = "needle";
foreach ($bigPatern as $val){
if (strpos($val, $needle2) !== false){
echo "YES";
}
}
I am trying to learn PHP while I write a basic application. I want a process whereby old words get put into an array $oldWords = array(); so all $words, that have been used get inserted using array_push(oldWords, $words).
Every time the code is executed, I want a process that finds a new word from $wordList = array(...). However, I don't want to select any words that have already been used or are in $oldWords.
Right now I'm thinking about how I would go about this. I've been considering finding a new word via $wordChooser = rand (1, $totalWords); I've been thinking of using an if/else statement, but the problem is if array_search($word, $doneWords) finds a word, then I would need to renew the word and check it again.
This process seems extremely inefficient, and I'm considering a loop function but, which one, and what would be a good way to solve the issue?
Thanks
I'm a bit confused, PHP dies at the end of the execution of the script. However you are generating this array, could you also not at the same time generate what words haven't been used from word list? (The array_diff from all words to used words).
Or else, if there's another reason I'm missing, why can't you just use a loop and quickly find the first word in $wordList that's not in $oldWord in O(n)?
function generate_new_word() {
foreach ($wordList as $word) {
if (in_array($word, $oldWords)) {
return $word; //Word hasn't been used
}
}
return null; //All words have been used
}
Or, just do an array difference (less efficient though, since best case is it has to go through the entire array, while for the above it only has to go to the first word)
EDIT: For random
$newWordArray = array_diff($allWords, $oldWords); //List of all words in allWords that are not in oldWords
$randomNewWord = array_rand($newWordArray, 1);//Will get a new word, if there are any
Or unless you're interested in making your own datatype, the best case for this could possibly be in O(log(n))
I have a variable like this:
33,100,200
I need to detect if it contains a specific number, say
if(var contains '33'){
do stuff
}
But it has to not work if say they didn't have 333 in the variable the above statement shouldn't validate the if statement.
Edit: This is a string not an array.
Either explode & in_array route, or preg_match('/(?<![0-9])33(?![0-9])/',$string) route, I prefer the first.
I dont quite understand the second part of your question, but this may be the code you're looking for:
if(strpos($var, '33') !== false) {
// do stuff
}
Edit Oh, now I think i get what you're looking for
if(in_array('33', explode(',', $var)) {
// do stuff
}
I have a paragraph of text below that I want to use an input source. And I want the doSpin() function to take the stream of text and pick one value at random, from each [%group of replacement candidates%].
This [%should|ought|would|could%] make
it much [%more
convenient|faster|easier%] and help
reduce duplicate content.
So this sentence, when filtered, could potentially result in any of the following when input...
1) This should make it much more convenient and help reduce duplicate content.
2) This ought make it much faster and help reduce duplicate content.
3) This would make it much easier and help reduce duplicate content.
// So the code stub would be...
$content = file_get_contents('path to my input file');
function doSpin($content)
{
// REGEX MAGIC HERE
return $content;
}
$myNewContent = doSpin($content);
*I know zilch of Regex. But I know what I'm trying to do requires it.
Any ideas?
Use preg_replace_callback():
function doSpin($content) {
return preg_replace_callback('!\[%(.*?)%\]!', 'pick_one', $content);
}
function pick_one($matches) {
$choices = explode('|', $matches[1]);
return array_rand($choices);
}
The way this works is that it searches for [%...%] and captures what's in between. That's passed as $matches[1] to the callback (as it is the first captured group). That group is split on | using explode() and a random one is returned using array_rand(),
Ive been trying to match PHP comments using regex.
//([^<]+)\r\n
Thats what ive got but it doesn't really work.
Ive also tried
//([^<]+)\r
//([^<]+)\n
//([^<]+)
...to no avail
In what program are you coding this regex? Your final example is a good sanity check if you're worried that the newline chars aren't working. (I have no idea why you don't allow less-than in your comment; I'm assuming that's specific to your application.)
Try
//[^<]+
and see if that works. As Draemon says, you might have to escape the diagonals. You might also have to escape the parentheses. I can't tell if you know this, but parentheses are often used to enclose capturing groups. Finally, check whether there is indeed at least one character after the double slashes.
To match comments, you have to think there are two types of comments in PHP 5 :
comments which start by // and go to the end of the line
comments that start by /* and go to */
Considering you have these two lines first :
$filePath = '/home/squale/developpement/astralblog/website/library/HTMLPurifier.php';
$str = file_get_contents($filePath);
You could match the first ones with :
$matches_slashslash = array();
if (preg_match_all('#//(.*)$#m', $str, $matches_slashslash)) {
var_dump($matches_slashslash[1]);
}
And the second ones with :
$matches_slashstar = array();
if (preg_match_all('#/\*(.*?)\*/#sm', $str, $matches_slashstar)) {
var_dump($matches_slashstar[1]);
}
But you will probably get into troubles with '//' in the middle of string (what about heredoc syntax, btw, did you think about that one ? ), or "toggle comments" like this :
/*
echo 'a';
/*/
echo 'b';
//*/
(Just add a slash at the begining to "toggle" the two blocks, if you don't know the trick)
So... Quite hard to detect comments with only regex...
Another way would be to use the PHP Tokenizer, which, obviously, knows how to parse PHP code and comments.
For references, see :
token_get_all
List of Parser Tokens
With that, you would have to use the tokenizer on your string of PHP code, iterate on all the tokens you get as a result, and detect which ones are comments.
Something like this would probably do :
$tokens = token_get_all($str);
foreach ($tokens as $token) {
if ($token[0] == T_COMMENT
|| $token[0] == T_DOC_COMMENT) {
// This is a comment ;-)
var_dump($token);
}
}
And, as output, you'll get a list of stuff like this :
array
0 => int 366
1 => string '/** Version of HTML Purifier */' (length=31)
2 => int 57
or this :
array
0 => int 365
1 => string '// :TODO: make the config merge in, instead of replace
' (length=55)
2 => int 117
(You "just" might to strip the // and /* */, but that's up to you ; at least, you have extracted the comments ^^ )
If you really want to detect comments without any kind of strange error due to "strange" syntax, I suppose this would be the way to go ;-)
You probably need to escape the "//":
\/\/([^<]+)
This will match comments in PHP (both /* */ and // format)
/(\/\*).*?(\*\/)|(\/\/).*?(\n)/s
To get all matches, use preg_match_all to get array of matches.