I am using PHP to remove/add static pages once a page has been deleted, I want to be able to remove it from the .htaccess, however I've tried this, but it throws an error:
Warning: preg_replace() [function.preg-replace]: Unknown modifier '' in ...
The code:
$page_name = $row['page_name']; // Example: help
preg_replace('/RewriteRule ' . preg_quote('^' . $page_name . '/?$ page.php?mode=') . '.*/i', '', $htaccess);
This is an example of what it should fully remove:
RewriteRule ^help/?$ page.php?mode=help
You have to escape the expression delimiter by passing it to preg_quote as the second argument.
preg_replace('/RewriteRule ' . preg_quote('^' . $page_name . '/?$ page.php?mode=', '/') . '.*/i', '', $htaccess);
Or else your / won't be escaped. As stated in the documentation "the special regular expression characters are: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : -"
USe like this
preg_replace ( "~~msi", "pattern to replace").
Also - good practive is analise by line's not - change in all text a time!!!
so
foreach ( file(.htaccess) as $line)
{
and replace in each line,
}
than output all, store copy of old .htaccess ...
,Arsen
Related
i need to convert decimals values into unicode and display the unicode character in PHP.
so for example, 602 will display as this character: ɚ
after referencing this SO question/answer, i was able to piece this together:
echo json_decode('"' . '\u0' . dechex(602) . '"' );
this seems pretty error-prone. is there a better way to do this?
i was unable to get utf8_encode to work since it seemed to want to start with a string, not a decimal.
EDIT: in order to do characters between 230 and 250, double prefixed zeros are required:
echo json_decode('"' . '\u00' . dechex(240) . '"' ); // ð
echo json_decode('"' . '\u00' . dechex(248) . '"' ); // ø
echo json_decode('"' . '\u00' . dechex(230) . '"' ); // æ
in some cases, no zero is required:
echo json_decode('"' . '\u' . dechex(8592) . '"' ); // ←
this seems strange.
While eval is generally to be avoided, it seems strictly-controlled enough to be fine here.
echo eval(sprintf('return "\u{%x}";',$val));
echo json_decode(sprintf('"\u%04x"',$val));
this ultimately worked for me, but i would not have found this without the answer from Niet the Dark Absol
normally, when i attempt to answer my own question, some SO wizard comes along and shows me a built-in function that i should have known about. but until that happens, this is all i can think of:
$leading_zeros = null;
if ( strlen(strval(dechex($val))) >= 4 ) {
$leading_zeros = '';
} else if ( ctype_alpha(dechex($val)[0]) ) {
$leading_zeros = '00';
} else if ( ctype_digit(dechex($val)[0]) ) {
$leading_zeros = '0';
}
echo json_decode('"' . '\u' . $leading_zeros . dechex($val) . '"' );
EDIT: when trying to something similar for javaScript, the documentation tells me the format is supposed to look like "\u####' four digits. i dont know if this is similar to PHP or not.
If you have IntlChar available I'd recommend using IntlChar::chr:
var_dump(IntlChar::chr(602));
Failing that, something like the following avoids any eval/json_decode trickery:
var_dump(iconv('UTF-32BE', 'UTF-8', pack('N', 602)));
The PHP Template Engine: Smarty 2.6.0 (/includes/Smarty) is using a deprecated modifier 'e' for preg_replace function call:
Block causing error: /include/Smarty/Smarty_Compiler.class.php # line 262
/* replace special blocks by "{php}" */
$source_content = preg_replace($search.'e', "'"
. $this->_quote_replace($this->left_delimiter) . 'php'
. "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'"
. $this->_quote_replace($this->right_delimiter)
. "'"
, $source_content);
if you try simply to upgrade Smarty to the current version 3.1.16, or the closest available version 2.6.28. it will not work.
Here comes solution:
So I applied substitute call recommanded by PHP reference.
Change: /include/Smarty/Smarty_Compiler.class.php # line 262
/* replace special blocks by "{php}" */
$source_content = preg_replace_callback($search,
function($m) {
return "{php ".str_repeat("\n", substr_count($m[0], "\n"))."}";
},
$source_content);
I hope this will help someone else and save him few hours.
The following code should allow for other Smarty delimiter tags to be used with your substitution:
$source_content = preg_replace_callback($search,
function($m) {
return $this->_quote_replace($this->left_delimiter)."php ".str_repeat("\n", substr_count($m[0], "\n")).$this->_quote_replace($this->right_delimiter);
},
$source_content);
Having following code to turn an URL in a message into HTML links:
$message = preg_replace("#(http|https|ftp|ftps)://([.]?[&;%=a-zA-Z0-9_/?-])*#",
"\\0", $message);
$message = preg_replace("#(^| |\n)(www([.]?[&;%=a-zA-Z0-9_/?-])*)#",
"\\1\\2", $message);
It works very good with almost all links, except in following cases:
1) http://example.com/mediathek#/video/1976914/zoom:-World-Wide
Problem here is the # and the : within the link, because not the complete link is transformed.
2) If someone just writes "www" in a message
Example: www
So the question is about if there is any way to fix these two cases in the code above?
Since you want to include the hash (#) to the regex, you need to change the delimiters to characters that are not included in your regex, e.g. !. So, your regex should look like this:
$message = preg_replace("!(http|https|ftp|ftps)://([.]?[&;%#:=a-zA-Z0-9_/?-])*!",
"\\0", $message);
Does this help?
Though, if you would like to be more along the specification (RCF 1738) you might want to exclude % which is not allowed in URLs. There are also some more allowed characters which you didn't include:
$
_
. (dot)
+
!
*
'
(
)
If you would include these chars, you should then delimiter your regex with %.
Couple minor tweaks. Add \# and : to the first regex, then change the * to + in the second regex:
$message = preg_replace("#(http|https|ftp|ftps)://([.]?[&;%=a-zA-Z0-9_/?\#:-])*#",
"\\0", $message);
$message = preg_replace("#(^| |\n)(www([.]?[&;%=a-zA-Z0-9_/?-])+)#",
"\\1\\2", $message);
In my opinion, it is vain to tackle this problem. A good alternative is to find what could be an URL via regex (begin with the protocol: http, ftp, mail... or by www) and then test it with FILTER_VALIDATE_URL. Keep in mind that this filter is not a waterproof way as the PHP manual says:
"Note that the function will only find ASCII URLs to be valid; internationalized domain names (containing non-ASCII characters) will fail."
Example of code (not tested):
$message = preg_replace_callback(
'~(?(DEFINE)
(?<prot> (?>ht|f) tps?+ :// ) # you can add protocols here
)
(?>
<a\b (?> [^<]++ | < (?!/a>) )++ </a> # avoid links inside "a" tags
|
<[^>]++> # and tags attributes.
) (*SKIP)(?!) # makes fail the subpattern.
| # OR
\b(?>(\g<prot>)|www\.)(\S++) # something that begins with
# "http://" or "www."
~xi',
function ($match) {
if (filter_var($match[2], FILTER_VALIDATE_URL)) {
$url = (empty($match[1])) ? 'http://' : '';
$url .= $match[0];
return '<a href="away?to=' . $url . '"target="_blank">'
. $url . '</a>';
} else { return $match[0] }
},
$message);
I want to match a subdomain that is in the PHP variable $_SERVER['SERVER_NAME'] and then do a internal redirect. Apache or nginx rewrites is not a option because this are external rewrites that are visible to the client/user.
My regular expression is (.*(?<!^.))subdomain\.example\.com as you can see I match a subdomain in a subdomain (multi-level subdomains). The first capture group would I like to use for later.
This is my PHP code:
if(preg_match('#(.*(?<!^.))subdomain\.example\.com#', $_SERVER['SERVER_NAME'], $match1)) {
echo $match1[1] . 'anothersubdomain.example.com';
}
But this will fail if the subdomain is for example csssubdomain.example.com because this is another subdomain that I don't want to match. With the following PHP script I test the matches:
$tests = array(
'subdomain.example.com' => 'anothersubdomain.example.com',
'css.subdomain.example.com' => 'css.anothersubdomain.example.com',
'csssubdomain.example.com' => 'csssubdomain.example.com',
'tsubdomain.example.com' => 'tsubdomain.example.com',
'multi.sub.subdomain.example.com' => 'multi.sub.anothersubdomain.example.com',
'.subdomain.example.com' => '.subdomain.example.com',
);
foreach( $tests as $test => $correct_answer) {
$result = preg_replace( '#(.*(?<!^.))subdomain\.example\.com#', '$1anothersubdomain.example.com', $test);
echo 'Input: ' . $test . "\n" .
'Expected: ' . $correct_answer . "\n" .
'Actual : ' .$result . "\n";
$passorfail = (strcmp( $result, $correct_answer) === 0 ? "PASS\n\n" : "FAIL\n\n");
echo $passorfail;
}
You'd get as output:
Input: subdomain.example.com
Expected: anothersubdomain.example.com
Actual : anothersubdomain.example.com
PASS
Input: css.subdomain.example.com
Expected: css.anothersubdomain.example.com
Actual : css.anothersubdomain.example.com
PASS
Input: csssubdomain.example.com
Expected: csssubdomain.example.com
Actual : cssanothersubdomain.example.com
FAIL
Input: tsubdomain.example.com
Expected: tsubdomain.example.com
Actual : tsubdomain.example.com
PASS
Input: multi.sub.subdomain.example.com
Expected: multi.sub.anothersubdomain.example.com
Actual : multi.sub.anothersubdomain.example.com
PASS
Input: .subdomain.example.com
Expected: .subdomain.example.com
Actual : .subdomain.example.com
PASS
The strange thing is that it does match csssubdomain.example.com but not tsubdomain.example.com.
Does someone know what regular expression you can use for this case? I've tried some things with lookahead and lookbehind zero-width assertions but it didn't really work.
You can try this pattern:
~^((?:\w+\.)*?)subdomain\.example\.com~
if you allow this .toto.subdomain.example.com, just add \.? at the beginning:
~^((?:\.?\w+\.)*?)subdomain\.example\.com~
if you want to allow a hyphen character just add it to the character class:
~^((?:\.?[\w-]+\.)*?)subdomain\.example\.com~
and if you don't allow substring to begin or ending with a hypen character:
~^((?:\.?\w+([\w-]*?\w)?\.)*?)subdomain\.example\.com~
Very(!) new to regex but...
I have the following text strings outputted from a $title variable:
A. This is a title
B. This is another title
etc...
I'm after the following:
<span>A.</span> This is a title
<span>B.</span> This is another title
etc...
Currently I have the following code:
$title = $element['#title'];
if (preg_match("([A-Z][\.])", $title)) {
return '<li' . drupal_attributes($element['#attributes']) . ">Blarg</li>\n";
} else {
return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
This replaces anything A. through to Z. with Blarg however I'm not sure how to progress this?
In the Text Wrangler app I could wrap regex in brackets and output each argument like so:
argument 1 = \1
argument 2 = \2
etc...
I know I need to add an additional regex to grab the remainder of the text string.
Perhaps a regex guru could help and novice out!
Thanks,
Steve
Try
$title = 'A. This is a title';
$title = preg_replace('/^[A-Z]\./', '<span>$0</span>', $title);
echo $title;
// <span>A.</span> This is a title
If the string contains newlines and other titles following them, add the m modifier after the ending delimiter.
If the regex doesn't match then no replacements will be made, so there is no need for the if statement.
Is it always just 2 char ("A.", "B.", "C.",...)
because then you could work with a substring instead of regex.
Just pick of the first 2 chars of the link and wrap the span around the substring
Try this (untested):
$title = $element['#title'];
if (preg_match("/([A-Z]\.)(.*)/", $title, $matches)) {
return '<li' . drupal_attributes($element['#attributes']) . "><span>{$matches[0]</span>{$matches[1]}</li>\n";
} else {
return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
The change here was to first add / to the start and end of the string (to denote it's a regex), then remove the [ and ] around the period . because that's just a literal character on its own, then to add another grouping which will match the rest of the string. I also Added a $matches to preg_match() to place these two matches in to to use later, which we do on the next life.
Note: You could also do this instead:
$title = preg_replace('/^([A-Z]\.)/', "<span>$1</span>", $title);
This will simply replace the A-Z followed by the period at the start of the string (denoted with the ^ character) with <span>, that character (grabbed with the brackets) and </span>.
Again, that's not tested, but should give you a headstart :)