I'm using smarty for my website and special link modifier that turns into clickable links text from users comments. It works perfect except it is turning such pieces of text as p.s. someword.asag and so on? Is there any way to improve it and prevent such things to happen, keeping it work only on real web links?
function smarty_modifier_autolink($string)
{
$string = preg_replace_callback('#(?:https?://\S+)|(?:www.\S+)|(?:\S+\.\S+)#', function($arr)
{
$email = filter_var($arr[0], FILTER_VALIDATE_EMAIL) === $arr[0] ? true : false;
$origArr0 = $arr[0];
if(strpos($arr[0], 'http://') !== 0 && strpos($arr[0], 'https://') !== 0)
{
$arr[0] = 'http://' . $arr[0];
}
$url = parse_url($arr[0]);
// images
if(isset($url['path'])){
if(preg_match('#\.(png|jpg|gif)$#', $url['path']))
{
return '<img class="img-responsive" src="'. $arr[0] . '" />';
}
}
// youtube
if(in_array($url['host'], array('www.youtube.com', 'youtube.com'))
&& $url['path'] == '/watch'
&& isset($url['query']))
{
parse_str($url['query'], $query);
return sprintf('<div class="embed-responsive embed-responsive-16by9"><iframe class="embed-responsive-item" src="http://www.youtube.com/embed/%s" allowfullscreen></iframe></div>', $query['v']);
}
//links
if($email){
return sprintf('%1$s', $origArr0);
}else{
return sprintf('%2$s', $arr[0], str_replace($url['scheme'].'://', '', $arr[0]));
}
}, $string);
return $string;
}
Related
This question already has answers here:
Multiple returns from a function
(32 answers)
Closed 2 years ago.
I have the script below and I need to return both of the conditional return values -- each result on a line. Is there any way to format it as an array in order to work ?
The script is:
if ($pdf_url != '') {
if ($title != '') {
$title_from_url = $this->make_title_from_url($pdf_url);
if ($title == $title_from_url || $this->make_title_from_url('/'.$title) == $title_from_url) {
// This would be the default title anyway based on URL
// OR if you take .pdf off title it would match, so that's close enough - don't load up shortcode with title param
$title = '';
} else {
$title = ' title="' . esc_attr( $title ) . '"';
}
}
return apply_filters('pdfemb_override_send_to_editor', '[pdf-embedder url="' . $pdf_url . '"'.$title.']', $html, $id, $attachment);
} else {
return $html;
}
If you want each result on a line, it sounds like you could use a temporary variable, and concatenate to it based on the logic.
<?php
$output = '';
if ($pdf_url != '') {
if ($title != '') {
$title_from_url = $this->make_title_from_url($pdf_url);
if ($title == $title_from_url || $this->make_title_from_url('/'.$title) == $title_from_url) {
// This would be the default title anyway based on URL
// OR if you take .pdf off title it would match, so that's close enough - don't load up shortcode with title param
$title = '';
} else {
$title = ' title="' . esc_attr( $title ) . '"';
}
}
// You may need print_r() around apply_filters() if it returns an array
$output .= apply_filters('pdfemb_override_send_to_editor', '[pdf-embedder url="' . $pdf_url . '"'.$title.']', $html, $id, $attachment) . "\n";
} else {
$output .= $html . "\n";
}
return $output;
Or if you want it in array:
<?php
$output = [];
if ($pdf_url != '') {
if ($title != '') {
$title_from_url = $this->make_title_from_url($pdf_url);
if ($title == $title_from_url || $this->make_title_from_url('/'.$title) == $title_from_url) {
// This would be the default title anyway based on URL
// OR if you take .pdf off title it would match, so that's close enough - don't load up shortcode with title param
$title = '';
} else {
$title = ' title="' . esc_attr( $title ) . '"';
}
}
// You may need print_r() around apply_filters() if it returns an array
$output[] = apply_filters('pdfemb_override_send_to_editor', '[pdf-embedder url="' . $pdf_url . '"'.$title.']', $html, $id, $attachment);
} else {
$output[] = $html;
}
return $output;
I'm trying to get the title of a website that is entered by the user.
Text input: website link, entered by user is sent to the server via AJAX.
The user can input anything: an actual existing link, or just single word, or something weird like 'po392#*#8'
Here is a part of my PHP script:
// Make sure the url is on another host
if(substr($url, 0, 7) !== "http://" AND substr($url, 0, 8) !== "https://") {
$url = "http://".$url;
}
// Extra confirmation for security
if (filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)) {
$urlIsValid = "1";
} else {
$urlIsValid = "0";
}
// Make sure there is a dot in the url
if (strpos($url, '.') !== false) {
$urlIsValid = "1";
} else {
$urlIsValid = "0";
}
// Retrieve title if no title is entered
if($title == "" AND $urlIsValid == "1") {
function get_http_response_code($theURL) {
$headers = get_headers($theURL);
if($headers) {
return substr($headers[0], 9, 3);
} else {
return 'error';
}
}
if(get_http_response_code($url) != "200") {
$urlIsValid = "0";
} else {
$file = file_get_contents($url);
$res = preg_match("/<title>(.*)<\/title>/siU", $file, $title_matches);
if($res === 1) {
$title = preg_replace('/\s+/', ' ', $title_matches[1]);
$title = trim($title);
$title = addslashes($title);
}
// If title is still empty, make title the url
if($title == "") {
$title = $url;
}
}
}
However, there are still errors occuring in this script.
It works perfectly if an existing url as 'https://www.youtube.com/watch?v=eB1HfI-nIRg' is entered and when a non-existing page is entered as 'https://www.youtube.com/watch?v=NON-EXISTING', but it doesn't work when the users enters something like 'twitter.com' (without http) or something like 'yikes'.
I tried literally everthing: cUrl, DomDocument...
The problem is that when an invalid link is entered, the ajax call never completes (it keeps loading), while it should $urlIsValid = "0" whenever an error occurs.
I hope someone can help you - it's appreciated.
Nathan
You have a relatively simple problem but your solution is too complex and also buggy.
These are the problems that I've identified with your code:
// Make sure the url is on another host
if(substr($url, 0, 7) !== "http://" AND substr($url, 0, 8) !== "https://") {
$url = "http://".$url;
}
You won't make sure that that possible url is on another host that way (it could be localhost). You should remove this code.
// Make sure there is a dot in the url
if (strpos($url, '.') !== false) {
$urlIsValid = "1";
} else {
$urlIsValid = "0";
}
This code overwrites the code above it, where you validate that the string is indeed a valid URL, so remove it.
The definition of the additional function get_http_response_code is pointless. You could use only file_get_contents to get the HTML of the remote page and check it against false to detect the error.
Also, from your code I conclude that, if the (external to context) variable $title is empty then you won't execute any external fetch so why not check it first?
To sum it up, your code should look something like this:
if('' === $title && filter_var($url, FILTER_VALIDATE_URL))
{
//# means we suppress warnings as we won't need them
//this could be done with error_reporting(0) or similar side-effect method
$html = getContentsFromUrl($url);
if(false !== $html && preg_match("/<title>(.*)<\/title>/siU", $file, $title_matches))
{
$title = preg_replace('/\s+/', ' ', $title_matches[1]);
$title = trim($title);
$title = addslashes($title);
}
// If title is still empty, make title the url
if($title == "") {
$title = $url;
}
}
function getContentsFromUrl($url)
{
//if not full/complete url
if(!preg_match('#^https?://#ims', $url))
{
$completeUrl = 'http://' . $url;
$result = #file_get_contents($completeUrl);
if(false !== $result)
{
return $result;
}
//we try with https://
$url = 'https://' . $url;
}
return #file_get_contents($url);
}
What I am trying to do is create a syntax highlighter.What I need help with is creating reg expression to find and highlight punction marks but I want the match to exclude strings between certain characters "",'' and also exclude strings that have been commented or defined//,/**/,#. I am currently useing this pattern
'/(!|%|\^|\*|\(|\)|\+|\=|\-|>|<|\?|,|\.|\:|\;|\'|&|\[|\]|\}|\{|~)(?=[^>]*(<|$))/'
This part seems to work to exclude stuff between tags but honestly it looks incorrect and I am clueless on how to structure the pattern correctly.
(?=[^>]*(<|$))
Here is my Highlight class
class SyntaxHighlight
{
public static function process($s,$lang,$raw = false)
{
$orig_s = $s;
$regexp = array(
//Keywords working
'/(?<!\w|\$|\%|\#|>)(and|or|xor|for|do|while|foreach|as|return|die|exit|if|then|else|
elseif|new|delete|try|throw|catch|finally|class|function|string|
array|object|resource|var|bool|boolean|int|integer|float|double|
real|string|array|global|const|static|public|private|protected|
published|extends|switch|true|false|null|void|this|self|struct|
char|signed|unsigned|short|long|break|goto|static_cast|const_cast|
LIMIT|ASC|DESC|ORDER|BY|SELECT|FROM|WHERE)(?!\w|=")/iux'
=> '<span class="K">$1</span>',
//$var, %var, #var
'/(?<!\w)(
(\$|\%|\#)(\->|\w)+
)(?!\w)/ix'
=> '<span class="V">$1</span>',
// Numbers (also look for Hex)
'/(?<!\w)(
0x[\da-f]+|
\d+
)(?!\w)(?=[^"]*(<|"))/ix'
=> '<span class="N">$1</span>',
//comments
'/(\/\*.*?\*\/|
\/\/.*?\n|
\#.[^a-zA-Z0-9]+?\|
\<\!\-\-[\s\S]+\-\-\>|
(?<!\\\)\'(.*?)(?<!\\\)\'
)/isx'
=> '<span class="C">$1</span>',
//char strings
'/\'(.+?)\'(?=[^>]*(<|$))/'
=> "<span class='CS'>'$1'</span>",
//back quote strings
'/\`(.+?)\`(?=[^>]*(<|$))/'
=> "<span class='BS'>`$1`</span>",
//strings
'/"(.+?)"(?=[^>]*(<|$))/'
=> '<span class="S">"$1"</span>',
//Punc
'/(!|%|\^|\*|\(|\)|\+|\=|\-|>|<|\?|,|\.|\:|\;|\'|&|\[|\]|\}|\{|~)(?=[^>]*(<|$))/'
=> '<span class="P">$1</span>',
);
$s = preg_replace( array_keys($regexp), array_values($regexp), $s);
if($lang == "Text" || $lang == "Other")
$s = $orig_s;
if($raw == "false")
$s = self::DisplayLineCount($s);
return '<pre style = "background-color:white;margin:0auto;text-align:left;overflow:auto;">'.$s.'</pre>';
}
private static function DisplayLineCount($s)
{
$i=1;
$count = substr_count($s, "\n");
$s = "<span style = 'color:#dfecf2;'>".$i."\t</span>".$s;
while($i <= $count)
{
++$i;
$s = preg_replace("/[\n]/","<span style = 'color:#dfecf2;'>".$i."\t</span>",$s,1);
}
return $s;
}
}
I am getting the syntax to highligh from a database and calling the function like this.
if(isset($row['syntax']) && $row['syntax'] == $cat_ && isset($row['title']) && $row['title'] == $top_ && isset($row['id']) && $row['id'] == $id_)
{
$id_ = isset($row['id']) ? $row['id'] : '';
$top_ = isset($row['title']) ? $row['title'] : '';
$top_ = htmlspecialchars($top_);
$auth_ = isset($row['author']) ? $row['author'] : '';
$date_ = isset($row['date']) ? $row['date'] : '';
$post_ = isset($row['paste']) ? $row['paste'] : '';
$newtext = htmlspecialchars($post_);
echo SyntaxHighlight::process($newtext,$cat_,$raw);
}
I am very new to useing reg expression patterns so please forgive me and thank you in advance.
I need a form to autolink links that users input in text fields. I found an example on stack which works perfectly, except for one thing. if the user inputs a link without including http:// or https:// and instead starts the link only using www. the link does not work properly.
ie a user input would be
check out our twitter!
www.twitter.com/#!/profile
and our facebook!
https://www.facebook.com/profile
the output would be
check out our twitter!
www.twitter.com/#!/profile
and our facebook!
http://www.facebook.com/profile
so the facebook link works perfectly, but the twitter one would not, as its being linked to the current location the user is on plus the new link, ie if they are currently on www.example.com the link would become www.example.com/www.twitter.com/#!/profile
for the life of me, i cant figure out how to fix this by simply adding http:// to the beginning of the link, this is the function:
function auto_link_text($text) {
$pattern = '#\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))#';
return preg_replace_callback($pattern, 'auto_link_text_callback', $text);
}
function auto_link_text_callback($matches) {
$max_url_length = 50;
$max_depth_if_over_length = 2;
$ellipsis = '…';
$url_full = $matches[0];
$url_short = '';
if (strlen($url_full) > $max_url_length) {
$parts = parse_url($url_full);
$url_short = $parts['scheme'] . '://' . preg_replace('/^www\./', '', $parts['host']) . '/';
$path_components = explode('/', trim($parts['path'], '/'));
foreach ($path_components as $dir) {
$url_string_components[] = $dir . '/';
}
if (!empty($parts['query'])) {
$url_string_components[] = '?' . $parts['query'];
}
if (!empty($parts['fragment'])) {
$url_string_components[] = '#' . $parts['fragment'];
}
for ($k = 0; $k < count($url_string_components); $k++) {
$curr_component = $url_string_components[$k];
if ($k >= $max_depth_if_over_length || strlen($url_short) + strlen($curr_component) > $max_url_length) {
if ($k == 0 && strlen($url_short) < $max_url_length) {
// Always show a portion of first directory
$url_short .= substr($curr_component, 0, $max_url_length - strlen($url_short));
}
$url_short .= $ellipsis;
break;
}
$url_short .= $curr_component;
}
} else {
$url_short = $url_full;
}
return "<a rel=\"nofollow\" href=\"$url_full\">$url_short</a>";
}
Use strpos function.
if the input contains "http://" forward directly. Otherwise add it direct it.
I'm using the jquery address plugin to build an ajax driven site, and i've got it working! Yay! For the purposes of this question we can use the test site:
http://www.asual.com/jquery/address/samples/crawling
http://www.asual.com/download/jquery/address
(I had to remove two calls to urlencode() to make the crawling example work.)
I'm encountering a problem with the $crawling->nav() call. It basically uses js and php to load parts of an xml file into the dom. I (mostly) understand how it works, and I would like to modify the example code to include sub pages.
For example, I would like to show 'subnav-project.html' at '/!#/project' and '/!#/project/blue', but not at '/!#/contact'. To do this, I figure php should 'know' what page the user is on, that way I can base my logic off of that.
Is this crazy? Can php ever know the current state of the site if I'm building it this way? If not, how does one selectively load html snippets, or modify what links are shown in navigation menus?
I've never gotten too crazy with ajax before, so any feedback at all would be helpful.
EDIT
This is the crawling class.
class Crawling {
const fragment = '_escaped_fragment_';
function Crawling(){
// Initializes the fragment value
$fragment = (!isset($_REQUEST[self::fragment]) || $_REQUEST[self::fragment] == '') ? '/' : $_REQUEST[self::fragment];
// Parses parameters if any
$this->parameters = array();
$arr = explode('?', $fragment);
if (count($arr) > 1) {
parse_str($arr[1], $this->parameters);
}
// Adds support for both /name and /?page=name
if (isset($this->parameters['page'])) {
$this->page = '/?page=' . $this->parameters['page'];
} else {
$this->page = $arr[0];
}
// Loads the data file
$this->doc = new DOMDocument();
$this->doc->load('data.xml');
$this->xp = new DOMXPath($this->doc);
$this->nodes = $this->xp->query('/data/page');
$this->node = $this->xp->query('/data/page[#href="' . $this->page . '"]')->item(0);
if (!isset($this->node)) {
header("HTTP/1.0 404 Not Found");
}
}
function base() {
$arr = explode('?', $_SERVER['REQUEST_URI']);
return $arr[0] != '/' ? preg_replace('/\/$/', '', $arr[0]) : $arr[0];
}
function title() {
if (isset($this->node)) {
$title = $this->node->getAttribute('title');
} else {
$title = 'Page not found';
}
echo($title);
}
function nav() {
$str = '';
// Prepares the navigation links
foreach ($this->nodes as $node) {
$href = $node->getAttribute('href');
$title = $node->getAttribute('title');
$str .= '<li><a href="' . $this->base() . ($href == '/' ? '' : '?' . self::fragment . '=' .html_entity_decode($href)) . '"'
. ($this->page == $href ? ' class="selected"' : '') . '>'
. $title . '</a></li>';
}
echo($str);
}
function content() {
$str = '';
// Prepares the content with support for a simple "More..." link
if (isset($this->node)) {
foreach ($this->node->childNodes as $node) {
if (!isset($this->parameters['more']) && $node->nodeType == XML_COMMENT_NODE && $node->nodeValue == ' page break ') {
$str .= '<p><a href="' . $this->page .
(count($this->parameters) == 0 ? '?' : '&') . 'more=true' . '">More...</a></p>';
break;
} else {
$str .= $this->doc->saveXML($node);
}
}
} else {
$str .= '<p>Page not found.</p>';
}
echo(preg_replace_callback('/href="(\/[^"]+|\/)"/', array(get_class($this), 'callback'), $str));
}
private function callback($m) {
return 'href="' . ($m[1] == '/' ? $this->base() : ($this->base() . '?' . self::fragment . '=' .$m[1])) . '"';
}
}
$crawling = new Crawling();
You won't be able to make server-side decisions using the fragment-identifier (i.e., everything to the right of the # character). This is because browsers don't send fragment-identifiers to the server. If you're going to want to make server-side decisions, you'll need to use some JavaScript assistance (including AJAX) to communicate what the current fragment-identifier is.