Replace CSS file if is specific subdomain, using preg_match - php

Regular Expressions are still a stone in my boot. Can you help me, guys?
I have this piece of code for a hook in a CMS. Actually it is the whole code enclosed in the function to be excecuted by the main code.
if (preg_match('#^/member/helpdesk/index.*#i', $_SERVER['REQUEST_URI'])) //do it only for specific url
{
$event->replace('#(<h1>Tickets.*</h1>)#i', '$1<div>Some content</div>');
}
But what I really want is to check if the pages belongs to subdomain member.site.com, find the <link rel="stylesheet" href="http://site.com/orange.css"/> and replace orange.css by blue.css
Thank you :)

I mean, at the core I think you're trying to do this:
$str = '<html><head><link rel="stylesheet" href="http://site.com/style.css"/></head></html>'
if (preg_match('#member\.site\.com#i'), $_SERVER['HTTP_HOST'])){
$str = preg_replace('#http://site\.com/style\.css#', 'http://site.com/style-member.css', $str);
}
But perhaps you should consider how whatever it is you're trying to replace is being generated in the first place? Perhaps this is a check that could be placed at that location? Additionally, if you're going to be modifying an html document, I highly suggest using a parser of some kind. If you're going to do the first, maybe something like this:
$head = '<head><link rel="stylesheet" href="http://site.com/style';
if (preg_match('#member\.site\.com#i'), $_SERVER['HTTP_HOST'])){
$head .= '-member';
}
$head .= '.css"></head>';
But if you insist on parsing an html document:
$str = '<html><head><link rel="stylesheet" href="http://site.com/style.css"/></head></html>'
$dom = new DOMDocument();
$dom->loadHTML($str);
if (preg_match('#member\.site\.com#i'), $_SERVER['HTTP_HOST'])){
$links = $dom->getElementsByTagName('link');
foreach ($links as $link){
$attr = $link->attributes;
if ($attr
&& $attr->getNamedItem('rel')->nodeValue == 'stylesheet'
&& $attr->getNamedItem('href')->nodeValue == 'http://site.com/style.css'){
$attr->getNamedItem('href')->nodeValue = 'http://site.com/style-member.css'
}
}
}
$str = $dom->saveHTML();

If you want to check full domain name use
if( strtolower($_SEVER['HTTP_HOST'])=='member.site.com' ){
// other stuff
}
if you need to check it with REQUEST_URI than
if( preg_match('#^/member#i',$_SERVER['REQUEST_URI']) ){
// other stuff
}
to check hostname from full url
if( preg_match('#^(?:http[s]*://)?([^/]+)#i',$url) ){
// other stuff
}
Note: Remember if there is really one line this will work with catching the beggining of line
preg_match('#^/member/#i','/member/blahstuftuff/member/member/member/me?user=amigo&dir=mber/member')
You can test regular expression here: RegExp online version
EDIT
If you want to change css when the user is in member site and if is logged in a session, than just set:
$_SESSION['member']=true; when logins,
and do this in the part of the page (header or wherever you plan to write the css file):
USING request uri that starts with '/member' :
echo '<link rel="stylesheet" href="http://site.com/'.(preg_match('#^/member#i',$_SERVER['REQUEST_URI'])==true&&$_SESSION['member']==true?'blue.css':'orange.css').'"/>';
USING member domain name 'member.site.com' :
echo '<link rel="stylesheet" href="http://site.com/'.(strtolower($_SEVER['HTTP_HOST'])=='member.site.com'&&$_SESSION['member']==true?'blue.css':'orange.css').'"/>';
If you want blue.css to be seen by even guest users that are not logged in than just remove the session variable comparison!

Related

PHP - display remote page's content in full

I need to fetch a remote page, modify some elements (using 'PHP Simple HTML DOM Parser' library for that) and output modified content.
There's a problem with remote pages that don't have full URLs in their source, so CSS elements and images are not loaded. Sure, it doesn't stop me from modifying elements, but the output looks bad.
For example, open https://www.raspberrypi.org/downloads/
However, if you use code
$html = file_get_html('http://www.raspberrypi.org/downloads');
echo $html;
it will look bad. I tried to apply a simple hack, but that helps just a little:
$html = file_get_html('http://www.raspberrypi.org/downloads');
$html=str_ireplace("</head>", "<base href='http://www.raspberrypi.org'></head>", $html);
echo $html;
Is there any way to "instruct" script to parse all links from $html variable from 'http://www.raspberrypi.org'? In other words, how to make raspberrypi.org to be the "main" source of all images/CSS elements fetched?
I daon't know how to explain it better, but I believe you got an idea.
I just have tried this on local, and I've noticed(in the source code) the link tags in the HTML are like this:
<link rel='stylesheet' href='/wp-content/themes/mind-control/js/qtip/jquery.qtip.min.css' />
It obviously requires a file that should be in my local directory (like localhost/wp-content/etc.../).
The href of the link tags must be something like
<link rel='stylesheet' href='https://www.raspberrypi.org/wp-content/themes/mind-control/js/qtip/jquery.qtip.min.css' />
So what you probably want to do is find all link tags and add in their href attribute "https://www.raspberrypi.org/" in front of the rest.
EDIT: Hey I've actually made the style work, try this code:
$html = file_get_html('http://www.raspberrypi.org/downloads');
$i = 0;
foreach($html->find('link') as $element)
{
$html->find('link', $i)->href = 'http://www.raspberrypi.org'.$element->href;
$i++;
}
echo $html;die;
Since only Nikolay Ganovski offered a solution, I wrote a code which converts partial pages into full by looking for incomplete css/img/form tags and making them full. In case someone needs it, find the code below:
//finalizes remote page by completing incomplete css/img/form URLs (path/file.css becomes http://somedomain.com/path/file.css, etc.)
function finalize_remote_page($content, $root_url)
{
$root_url_without_scheme=preg_replace('/(?:https?:\/\/)?(?:www\.)?(.*)\/?$/i', '$1', $root_url); //ignore schemes, in case URL provided by user was http://domain.com while URL in source is https://domain.com (or vice-versa)
$content_object=str_get_html($content);
if (is_object($content_object))
{
foreach ($content_object->find('link.[rel=stylesheet]') as $entry) //find css
{
if (substr($entry->href, 0, 2)!="//" && stristr($entry->href, $root_url_without_scheme)===FALSE) //ignore "invalid" URLs like //domain.com
{
$entry->href=$root_url.$entry->href;
}
}
foreach ($content_object->find('img') as $entry) //find img
{
if (substr($entry->src, 0, 2)!="//" && stristr($entry->src, $root_url_without_scheme)===FALSE) //ignore "invalid" URLs like //domain.com
{
$entry->src=$root_url.$entry->src;
}
}
foreach ($content_object->find('form') as $entry) //find form
{
if (substr($entry->action, 0, 2)!="//" && stristr($entry->action, $root_url_without_scheme)===FALSE) //ignore "invalid" URLs like //domain.com
{
$entry->action=$root_url.$entry->action;
}
}
}
return $content_object;
}

Regex running all matches together instead of returning separate

I am working on a php script for a custom cms that will replace a custom tag with information from a database.
There would be a tag like below
<!-- NAV id="123" suffix="somethinghere" prefix="somethingelse" -->
I need to pull out the id, suffix, and prefix attributes. The code below works great if there is only one instance of this tag on the page, but if I have more than one, or if "-->" is anywhere else on the page it does not work properly. It matches everything between the first
"<!--"
and the last
"-->"
instead of returning each match separately.
Here is my current code. If it were working properly it would replace the entire tag with the value of "id", eventually that will be data from the database.
<?php
global $lastNav, $html;
//the html content
$html = '<html><body><hr><br>Hi this is my content<br> <!-- NAV id="123" suffix="<br />" prefix="•" --> <br>Some more content here <!-- NAV id="125" suffix="<br />" prefix="•" --> </body></html>';
$regexNavPattern = '<!-- NAV.*?(?:(?:\s+(id)="([^"]+)")|(?:\s+(prefix)="([^"]+)")|(?:\s+(suffix)="([^"]+)")|(?:\s+[^\s]+))+.*-->';
preg_replace_callback($regexNavPattern, "parseNav", $html);
function parseNav($navData) {
global $lastNav, $html;
foreach($navData as $key=>$value) {
if($key == 0) { $lastNav['replace'] = '<'.$value.'>'; }
if($value == 'id') { $lastNav['id'] = $navData[$key+1]; }
if($value == 'prefix') { $lastNav['prefix'] = $navData[$key+1]; }
if($value == 'suffix') { $lastNav['suffix'] = $navData[$key+1]; }
}
$html = str_replace($lastNav['replace'], $lastNav['id'], $html);
}
echo $html;
?>
At this point I am not concerned about case sensitivity. There is a chance that the attributes may contain special characters including single or double quotes.
Hopefully I explained this well enough. Thanks in advance.
Jonathan Kuhn's solutions worked. For the time being I went with the first approach of just correcting the existing regex.
/<!-- NAV.*?(?:(?:\s+(id)="([^"]+)")|(?:\s+(prefix)="([^"]+)")|(?:\s+(suffix)="([^"]+)‌​")|(?:\s+[^\s]?+))+.*?-->/
Later I will modify it to break it down to work as a few functions. I appreciate the help.

php preg_macthing for tumblr avatar grabbing

amm please kindly check this code? cos it won't work..
<?php
$page = file_get_contents("http://natadec0c0.tumblr.com/");
$avatar = preg_match('/<a rel="shortcut icon" href="(http+)"/', $page, $matches) ? $matches[1]: 'http://27.media.tumblr.com/avatar_749f6bc22627_128.png';
echo $avatar;
?>
To Grab copy this tag view-source:http://natadec0c0.tumblr.com/
<link rel="shortcut icon" href="http://25.media.tumblr.com/avatar_fa85d9b5e571_16.png" />
whew almost half of hour im stuck in this problem.. hope someone can help me...
You're searching for an <a rel..., instead of a <link rel....
Also, you'll likely want something like (http.+?) instead of (http+).
A better better way for finding that link though would be something like:
if (preg_match('/<link.+?>/si', $page, $link_matches)
&& strpos($link_matches[0], 'shortcut icon') !== false
&& preg_match('/href\s*=\s*"(http:.+?)"/si', $link_matches[0], $matches))
{
$avatar = $matches[1];
}
else
{
$avatar = 'http://27.media.tumblr.com/avatar_749f6bc22627_128.png';
}
In the above example, you'd first be looking for <link/> tags, then look for the href attribute in the found link tags. Just in case they look a little differently from what you expect them to look like.

How do I programmatically add rel="external" to external links in a string of HTML?

How can I check if links from a string variable are external? This string is the site content (like comments, articles etc).
And if they are, how do I append a external value to their rel attribute? And if they don't have this attribute, append rel="external" ?
A HTML parser is appropriate for input filtering, but for modifying output you'll need the performance of a simpleminded regex solution. In this case a callback regex would do:
$html = preg_replace_callback("#<a\s[^>]*href="(http://[^"]+)"[^>]*>#",
"cb_ext_url", $html);
function cb_ext_url($match) {
list ($orig, $url) = $match;
if (strstr($url, "http://localhost/")) {
return $orig;
}
elseif (strstr($orig, "rel=")) {
return $orig;
}
else {
return rtrim($orig, ">") . ' rel="external">';
}
}
You'll probably need more fine-grained checks. But that's the general approach.
Use an XML parser, like SimpleXML. Regex isn't made to do XML/HTML parsing, and here's a perfect explanation of what happens when you do: RegEx match open tags except XHTML self-contained tags.
Parse the input as XML, use the parser to select the required elements, edit their properties using the parser, and spit them back out.
It'll save you a headache, as regex makes me cry...
Here's my way of doing this (didn't test it):
<?php
$xmlString = "This is where the HTML of your site should go. Make sure it's valid!";
$xml = new SimpleXMLElement($xmlString);
foreach($xml->getElementsByTagName('a') as $a)
{
$attributes = $a->attributes();
if (isThisExternal($attributes['href']))
{
$a['rel'] = 'external';
}
}
echo $xml->asXml();
?>
It might be easier to do something like this on the client side, using jQuery:
<script type="text/javascript">
$(document).ready(function()
{
$.each($('a'), function(idx, tag)
{
// you might make this smarter and throw out URLS like
// http://www.otherdomain.com/yourdomain.com
if ($(tag).attr('href').indexOf('yourdomain.com') < 0)
{
$(tag).attr('rel', 'external');
}
});
});
</script>
As Craig White points out though, this doesn't do anything SEO-wise and won't help users who have JavaScript disabled.

Custom User CSS in PHP?

I would like to add a feature onto my site that would allow a user to choose between multiple styles. I have seen this feature on other sites. How would I go about doing this or could somebody refer me to a tutorial or guide on how this can be done?
To start you off, you could simply make the stylesheet link(s) dynamic:
<link rel="stylesheet" href="<?=$style?>" type="text/css"/>
And provide links that change them:
Racecar
On the server, assign $style according to the query string, it would also be a good idea to default to something in case the user decides to modify the URL:
<?php
$stylesArr = array('racecar', 'magenta', 'cartman');
if(isset($_GET['theme']) && in_array($_GET['theme'], $stylesArr)) {
$style = $_GET['theme'] . '.css';
setcookie("theme", $style, time()+(3600*24*30));//expires in one month
} else {
if(isset($_COOKIE['theme']) && in_array($_COOKIE['theme'], $stylesArr)) {
$style = $_COOKIE['theme'] . '.css';
} else {
$style = 'default.css';
}
}
?>
<link rel="stylesheet" href="<?=$style?>" type="text/css"/>
You can propogate the user's style via the query string, cookies or sessions.
You can store information about style in cookies, or in database if users are regitered. And then depending on value add required css file on page with php.
Depending on how your pages are rendered it might be best to store the theme in a cookie once a theme has been selected otherwise you need to append ?theme=racecar to every link on your page.
if(isset($_GET['theme']))
{
setcookie('theme', $_GET['theme']);
$style = $_GET['theme'];
}
else if(isset($_COOKIE['theme']))
{
$style = $_COOKIE['theme'];
}
else
{
$style = 'default';
}
<link href="/styles/<?php echo $style; ?>.css" rel="stylesheet">
I've also seen it done with javascript.
Same basic idea as a few other answers: you write the chosen style to a cookie, and then read that when the page loads to determine which stylesheet to load.
With javascript, you have the added benefit of being able to switch styles without reloading the page, and if you set up your css nicely, you can switch something like the body's id or class and have a new style without having to download a new stylesheet, so the style-switch happens almost instantly.
Very sweet effect, good luck with the implementation.

Categories