url encode and str_replace - php

I am trying to encode a sites current RFC 3986 standard and using this function:
function getUrl() {
$url = #( $_SERVER["HTTPS"] != 'on' ) ? 'http://'.$_SERVER["SERVER_NAME"] : 'https://'.$_SERVER["SERVER_NAME"];
$url .= ( $_SERVER["SERVER_PORT"] !== 80 ) ? ":".$_SERVER["SERVER_PORT"] : "";
$url .= $_SERVER["REQUEST_URI"];
$entities = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D', '%2B', '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D');
$replacements = array('!', '*', "'", "(", ")", ";", ":", "#", "&", "=", "+", "$", ",", "/", "?", "%", "#", "[", "]");
return str_replace($entities, $replacements, urlencode($url));
}
The URL added : http://localhost/test/test-countdown/?city=hayden&eventdate=20160301
Returns: http://localhost/test/test-countdown/?city=hayden&eventdate=20160301
Not encoded with the // and & replaced

While the canonical solution is to simply use rawurlencode() as fusion3k said, it's worth noting that, when rolling your own solution, you should:
Listen more closely to the spec and encode all characters that are not either alphanumeric or one of -_.~.
Be more lazy and refuse to type out all those entities. My rule of thumb is that I don't type of more than 10 array entries without a damn good reason. Automate!
Code:
function encode($str) {
return preg_replace_callback(
'/[^\w\-_.~]/',
function($a){ return sprintf("%%%02x", ord($a[0])); },
$str
);
}
var_dump(encode('http://localhost/test/test-countdown/?city=hayden&eventdate=20160301'));
Result:
string(88) "http%3a%2f%2flocalhost%2ftest%2ftest-countdown%2f%3fcity%3dhayden%26eventdate%3d20160301"

If you want encode an URL (not a site) in this format:
http%3A%2F%2Flocalhost%2Ftest%2Ftest-countdown%2F%3Fcity%3Dhayden%26eventdate%3D20160301
use the built-in php function rawurlencode( $url ).

Others have mentioned rawurlencode(), but the problem with your code is that you've got your arrays backwards.
Switch your arrays like this:
function getUrl() {
$url = #( $_SERVER["HTTPS"] != 'on' ) ? 'http://'.$_SERVER["SERVER_NAME"] : 'https://'.$_SERVER["SERVER_NAME"];
$url .= ( $_SERVER["SERVER_PORT"] !== 80 ) ? ":".$_SERVER["SERVER_PORT"] : "";
$url .= $_SERVER["REQUEST_URI"];
$entities = array('!', '*', "'", "(", ")", ";", ":", "#", "&", "=", "+", "$", ",", "/", "?", "%", "#", "[", "]");
$replacements = array('%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D', '%2B', '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D');
return str_replace($entities, $replacements, urlencode($url));
}

Related

PHP quick easy to replace characters?

I have a function that generates a hash and filters out characters:
$str = base64_encode(md5("mystring"));
$str = str_replace( "+", "_",
str_replace( "/", "-",
str_replace( "=", "x" $str
)));
What is the "right" way to do this in php?
i.e., is there a cleaner way?
// Let "tr()" be an imaginary function
$str = base64_encode(md5("mystring"));
$str = tr( "+/=", "_-x", $str );
There's a couple options here, first using str_replace properly:
$str = str_replace(array('+', '/', '='), array('_', '-', 'x'), $str);
And there's also the always-forgotten strtr:
$str = strtr($str, '+/=', '_-x');
You can use arrays in str_replace like this
$replace = Array('+', '/', '=');
$with = Array('_', '-', 'x');
$str = str_replace($replace, $with, $str);
Hope it helped
You can also use strtr with an array.
strtr('replace :this value', array(
':this' => 'that'
));

Making strings "URL safe" [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
URL Friendly Username in PHP?
Is there a way to make strings "URL safe" which means replacing whitespaces with hyphens, removing any punctuation and change all capital letters to lowercase?
For example:
"This is a STRING" -› "this-is-a-string"
or
"Hello World!" –› "hello-world"
You can use preg_replace to replace change those characters.
$safe = preg_replace('/^-+|-+$/', '', strtolower(preg_replace('/[^a-zA-Z0-9]+/', '-', $string)));
I Often use this function to generate my clean urls and seems to work fine,
You could alter it according to your needs but give it a try.
function sanitize($string, $force_lowercase = true, $anal = false) {
$strip = array("~", "`", "!", "#", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]",
"}", "\\", "|", ";", ":", "\"", "'", "‘", "’", "“", "”", "–", "—",
"—", "–", ",", "<", ".", ">", "/", "?");
$clean = trim(str_replace($strip, "", strip_tags($string)));
$clean = preg_replace('/\s+/', "-", $clean);
$clean = ($anal) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean ;
return ($force_lowercase) ?
(function_exists('mb_strtolower')) ?
mb_strtolower($clean, 'UTF-8') :
strtolower($clean) :
$clean;
}

preg_match to remove forbidden chars?

I'm trying to remove forbidden chars from a string.
$forbidden = array( "<", ">", "{", "}", "[", "]", "(", ")", "select", "update", "delete", "insert", "drop", "concat", "script");
foreach ($forbidden as $forbidChar) {
if (preg_match("/$forbidChar/i", $string)) {
return TRUE;
}
return FALSE;
}
But it's not working as expected, where did I go wrong?
You can do this with a single regex like this:
$forbidden = array(
"<", ">", "{", "}", "[", "]", "(", ")",
"select", "update", "delete", "insert", "drop", "concat", "script");
$forbidden = array_map( 'preg_quote', $forbidden, array_fill( 0, count( $forbidden), '/'));
return (bool) preg_match( '/' . implode( '|', $forbidden) . '/', $string);
This properly escapes all of the characters with preg_quote(), and forms a single regex to test for all of the cases.
Note: I haven't tested it, but it should work.
You need to use preg_replace() if you want characters to be replaced. Not preg_match().
You may also want to ensure that your forbidden characters are properly escaped using preg_quote().
You need to escape the character "[", "]", "(", ")" with "\[", "\]", "\)", "\)"
Here is the working code,
<?php
$string = "dfds fdsf dsfs fkldsk select dsasd asdasd";
$forbidden = array(
"<", ">", "{", "}", "\[", "\]", "\(", "\)",
"select", "update", "delete", "insert", "drop", "concat", "script");
foreach ($forbidden as $forbidChar) {
if (preg_match("/$forbidChar/i", $string)) {
exit('Forbidden char dtected');
return TRUE;
}
return FALSE;
}
?>
You can use the performanter string_replace function to do this
<?php
$forbidden = array(
"<", ">", "{", "}", "[", "]", "(", ")",
"select", "update", "delete", "insert", "drop", "concat", "script");
$cleanString = str_ireplace($forbidden, "", $string);
?>

PHP - a function to "sanitize" a string

is there any PHP function available that replaces spaces and underscores from a string with dashes?
Like:
Some Word
Some_Word
Some___Word
Some Word
Some ) # $ ^ Word
=> some-word
basically, the sanitized string should only contain a-z characters, numbers (0-9), and dashes (-).
This should produce the desired result:
$someword = strtolower(preg_replace("/[^a-z]+/i", "-", $theword));
<?php
function sanitize($s) {
// This RegEx removes any group of non-alphanumeric or dash
// character and replaces it/them with a dash
return strtolower(preg_replace('/[^a-z0-9-]+/i', '-', $s));
}
echo sanitize('Some Word') . "\n";
echo sanitize('Some_Word') . "\n";
echo sanitize('Some___Word') . "\n";
echo sanitize('Some Word') . "\n";
echo sanitize('Some ) # $ ^ Word') . "\n";
Output:
Some-Word
Some-Word
Some-Word
Some-Word
Some-Word
You might like to try preg_replace:
http://php.net/manual/en/function.preg-replace.php
Example from this page:
<?php
$string = 'April 15, 2003';
$pattern = '/(\w+) (\d+), (\d+)/i';
$replacement = '${1}1,$3';
echo preg_replace($pattern, $replacement, $string);
//April1,2003
?>
You might like to try a search for "search friendly URLs with PHP" as there is quite a bit of documentation, example:
function friendlyURL($string){
$string = preg_replace("`\[.*\]`U","",$string);
$string = preg_replace('`&(amp;)?#?[a-z0-9]+;`i','-',$string);
$string = htmlentities($string, ENT_COMPAT, 'utf-8');
$string = preg_replace( "`&([a-z])(acute|uml|circ|grave|ring|cedil|slash|tilde|caron|lig|quot|rsquo);`i","\\1", $string );
$string = preg_replace( array("`[^a-z0-9]`i","`[-]+`") , "-", $string);
return strtolower(trim($string, '-'));
}
and usage:
$myFriendlyURL = friendlyURL("Barca rejects FIFA statement on Olympics row");
echo $myFriendlyURL; // will echo barca-rejects-fifa-statement-on-olympics-row
Source: http://htmlblog.net/seo-friendly-url-in-php/
I found a few interesting solutions throughout the web.. note none of this is my code. Simply copied here in hopes of helping you build a custom function for your own app.
This has been copied from Chyrp. Should work well for your needs!
/**
* Function: sanitize
* Returns a sanitized string, typically for URLs.
*
* Parameters:
* $string - The string to sanitize.
* $force_lowercase - Force the string to lowercase?
* $anal - If set to *true*, will remove all non-alphanumeric characters.
*/
function sanitize($string, $force_lowercase = true, $anal = false) {
$strip = array("~", "`", "!", "#", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]",
"}", "\\", "|", ";", ":", "\"", "'", "‘", "’", "“", "”", "–", "—",
"—", "–", ",", "<", ".", ">", "/", "?");
$clean = trim(str_replace($strip, "", strip_tags($string)));
$clean = preg_replace('/\s+/', "-", $clean);
$clean = ($anal) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean ;
return ($force_lowercase) ?
(function_exists('mb_strtolower')) ?
mb_strtolower($clean, 'UTF-8') :
strtolower($clean) :
$clean;
}
EDIT:
Even easier function I found! Just a few lines of code, fairly self-explanitory.
function slug($z){
$z = strtolower($z);
$z = preg_replace('/[^a-z0-9 -]+/', '', $z);
$z = str_replace(' ', '-', $z);
return trim($z, '-');
}
Not sure why #Dagon chose to leave a comment instead of an answer, but here's an expansion of his answer.
php's preg_replace function allows you to replace anything with anything else.
Here's an example for your case:
$input = "a word 435 (*^(*& HaHa";
$dashesOnly = preg_replace("#[^-a-zA-Z0-9]+#", "-", $input);
print $dashesOnly; // prints a-word-435-HaHa;
You can think of writing this piece of code with the help of regular expressions.
But I dont see any available functions which help you directly replace the " " with "-"

How do I linkify urls in a string with php?

I have the following string:
"Look on http://www.google.com".
I need to convert it to:
"Look on http://www.google.com"
The original string can have more than 1 URL string.
How do I do this in php?
Thanks
You can use the following:
$string = "Look on http://www.google.com";
$string = preg_replace(
"~[[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/]~",
"\\0",
$string);
PHP versions < 5.3 (ereg_replace) otherwise (preg_replace)
lib_autolink does a pretty good job, avoiding pitfalls like extra punctuation after the link and links inside HTML tags:
https://github.com/iamcal/lib_autolink
Have a look at regular expressions. You would then do something like:
$text = preg_replace('#(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)#', '$1', $text);
Small update from nowadays. Just a regex won't be enough. Urls could contain unicode characters, brackets, punctuation etc.
There is a Url highlight library that cover lots of edge cases.
Example:
<?php
use VStelmakh\UrlHighlight\UrlHighlight;
$urlHighlight = new UrlHighlight();
$urlHighlight->highlightUrls('Look on http://www.google.com or even google.com.');
// return: 'Look on http://www.google.com or even google.com.'
You will need to use regular expressions...
Something like this will help.
$result = preg_replace('/\b(https?|ftp|file):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[A-Z0-9+&##\/%=~_|]/i', '\0', $text);
I found an example which allows for links that include ftp, https and others which seems to work fine for multiple URLs
how-to-detect-urls-in-text-and-convert-to-html-links-php-using-regular-expressions
<?php
// The Regular Expression filter
$pattern = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
//example text
$text="Example user text with a URL http://www.zero7web.com , second link http://www.didsburydesign.co.uk";
// convert URLs into Links
$text= preg_replace($pattern, "\\0", $text);
echo $text;
?>
Proabably a good idea to add nofollow to the link too is it's a user submitted value.
Try this...
<?
function link_it($text)
{
$text= preg_replace("/(^|[\n ])([\w]*?)([\w]*?:\/\/[\w]+[^ \,\"\n\r\t<]*)/is", "$1$2<a href=\"$3\" >$3</a>", $text);
$text= preg_replace("/(^|[\n ])([\w]*?)((www)\.[^ \,\"\t\n\r<]*)/is", "$1$2<a href=\"http://$3\" >$3</a>", $text);
$text= preg_replace("/(^|[\n ])([\w]*?)((ftp)\.[^ \,\"\t\n\r<]*)/is", "$1$2<a href=\"ftp://$3\" >$3</a>", $text);
$text= preg_replace("/(^|[\n ])([a-z0-9&\-_\.]+?)#([\w\-]+\.([\w\-\.]+)+)/i", "$1$2#$3", $text);
return($text);
}
$text = "ini link gue: http://sapua.com <br>
https://sapua.com <br>
anything1://www.sss.com <br>
dua www.google.com <br>
tiga http://www.google.com <br>
ftp.sapua.com <br>
someone#sapua.com
";
print link_it($text);
?>
I found this code at http://code.seebz.net/p/autolink-php/ and tweaked it a bit to recognize www.* as links. I am not very conversant with regular expressions but I think the two str_replace lines can be modified to one regexp
<?php
$text = 'First link is: www.example.com. Second link is http://example.com. Third link is https://example.com. Fourth link is http://www.example.com. Fifth link is www.example.com';
function autolink($str, $attributes=array()) {
$str = str_replace("http://www","www",$str);
$str = str_replace("https://www","www",$str);
$attrs = '';
foreach ($attributes as $attribute => $value) {
$attrs .= " {$attribute}=\"{$value}\"";
}
$str = ' ' . $str;
$str = preg_replace(
'`([^"=\'>])((http|https|ftp)://[^\s<]+[^\s<\.)])`i',
'$1<a href="$2"'.$attrs.'>$2</a>',
$str
);
$str = preg_replace(
'`([^"=\'>])((www).[^\s<]+[^\s<\.)])`i',
'$1<a href="http://$2"'.$attrs.'>$2</a>',
$str
);
$str = substr($str, 1);
return $str;
}
echo autolink($text);
?>
Correctly linkifying a URL is non-trivial. (See: http://www.codinghorror.com/blog/2008/10/the-problem-with-urls.html for more on why this is so.) I spent quite a bit of time on this and have come up with a pretty good solution to the problem (for both PHP and/or Javascript). See:
http://jmrware.com/articles/2010/linkifyurl/linkify.html
Checkout my linkify function, which uses preg_replace_callback (PHP 5.3 only). It supports http, email and twitter:
http://www.jasny.net/articles/linkify-turning-urls-into-clickable-links-in-php/
/**
* Turn all URLs in clickable links.
*
* #param string $value
* #param array $protocols http/https, ftp, mail, twitter
* #param array $attributes
* #param string $mode normal or all
* #return string
*/
function linkify($value, $protocols = array('http', 'mail'), array $attributes = array(), $mode = 'normal')
{
// Link attributes
$attr = '';
foreach ($attributes as $key => $val) {
$attr = ' ' . $key . '="' . htmlentities($val) . '"';
}
$links = array();
// Extract existing links and tags
$value = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) { return '<' . array_push($links, $match[1]) . '>'; }, $value);
// Extract text links for each protocol
foreach ((array)$protocols as $protocol) {
switch ($protocol) {
case 'http':
case 'https': $value = preg_replace_callback($mode != 'all' ? '~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i' : '~([^\s<]+\.[^\s<]+)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { if ($match[1]) $protocol = $match[1]; $link = $match[2] ?: $match[3]; return '<' . array_push($links, '<a' . $attr . ' href="' . $protocol . '://' . $link . '">' . $link . '</a>') . '>'; }, $value); break;
case 'mail': $value = preg_replace_callback('~([^\s<]+?#[^\s<]+?\.[^\s<]+)(?<![\.,:])~', function ($match) use (&$links, $attr) { return '<' . array_push($links, '<a' . $attr . ' href="mailto:' . $match[1] . '">' . $match[1] . '</a>') . '>'; }, $value); break;
case 'twitter': $value = preg_replace_callback('~(?<!\w)[##](\w++)~', function ($match) use (&$links, $attr) { return '<' . array_push($links, '<a' . $attr . ' href="https://twitter.com/' . ($match[0][0] == '#' ? '' : 'search/%23') . $match[1] . '">' . $match[0] . '</a>') . '>'; }, $value); break;
default: $value = preg_replace_callback($mode != 'all' ? '~' . preg_quote($protocol, '~') . '://([^\s<]+?)(?<![\.,:])~i' : '~([^\s<]+)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { return '<' . array_push($links, '<a' . $attr . ' href="' . $protocol . '://' . $match[1] . '">' . $match[1] . '</a>') . '>'; }, $value); break;
}
}
// Insert all link
return preg_replace_callback('/<(\d+)>/', function ($match) use (&$links) { return $links[$match[1] - 1]; }, $value);
}
Simple like that:
$text = "Atenção, isto é um link de teste";
$text = str_replace(
[' ', ',', '&', '&', 'á', 'ã', 'à', 'é', 'ê', 'í', 'ç', 'õ', 'ô', 'ó', 'ú', "'", ")", "(", "]", "["],
['-', '', '', '', 'a', 'a', 'a', 'e', 'e', 'i', 'c', 'o', 'o', 'o', 'u', '', "", "", "", ""],
$text
);
echo strtolower($text);
If you need more chars, add them in the str_replace.

Categories