Need to add newline between include()ed css files
I have a bunch of CSS files that get loaded on every page (header, global, main page, footer, etc.).
I have written a simple PHP script that compiles them into a single string and then outputs that string.
<?php
set_include_path('../');
header('Content-Type: text/css');
$q = $_GET['q'];
$patterns = array(
'/.*[\.]{2,}.*/',
'/,\//',
'/^\//'
);
$replacements = array(
'',
',',
''
);
$q = preg_replace($patterns, $replacements, $q);
$css = explode(",", $q);
$output = '';
foreach( $css as $link )
{
$output .= include($link);
}
print $output;
?>
it can be called (and the way I am calling it) like this:
<?php
$cssLinks = array(
"/global/global.css",
"/styles/local.css",
$tmpl->headerContent['css']['link'],
$tmpl->appContent['css']['link'],
"/styles/css3buttons.css"
);
$css = implode(",", $cssLinks);
?>
<link rel="stylesheet" href="/components/CSS.php?q=<?= $css; ?>" type="text/css" />
Which results in a string like this:
<link rel="stylesheet" href="/components/CSS.php?q=/global/global.css,/styles/local.css,/styles/header.css,/styles/index.css,/styles/css3buttons.css" type="text/css" />
This is fine, and - more importantly - it works.
What is my question, then, you ask?
It's a two-parter:
- What security vulnerabilities am I overlooking in the script?
- I've removed any directory traversal possibilities, but what else?
- I do need to be able to change what the links are, so I can't hard-code them into this script. For example,
$tmpl->appContent['css']['link']
is a dynamic stylesheet for each page, of which there will be many.
- How can I add line breaks between the included files?
- I've added
$output .= '\n\n';
in theforeach()
loop, but it doesn't work. - I'm still stuck with output like:
- I've added
#footer, #push {
height: 3em;
padding-top: 1em;
}#header{
The CSS listed works but I would prefer to have the #header
block two lines down, like:
#footer, #push {
height: 3em;
padding-top: 1em;
}
开发者_StackOverflow中文版#header{
(I apologize about the strange code block, Markdown broke horrendously on those hashes, and I couldn't figure out how to fix it).
Note, this lack of line breaks only happens at the junction between two different files. The code inside each CSS file is formated just as it should be.
You should prefer to pass only basenames to the CSS.php merge script:
<link rel="stylesheet" href="CSS.php?q=global,local,header,index,css3buttons" type="text/css" >
Then it becomes safer to implement in CSS.php with just:
preg_match_all('#\w+#', $_GET["q"], $files);
foreach ($files[0] as $fn) {
foreach (array("global/$fn.css", "local/$fn.css") as $fn)
if (file_exists($fn))
$content .= file_get_contents($fn);
$content .= "\n\n";
}
The only difference is that this script now has a little intelligence and knows where to look for the stylesheets. So you don't lose the flexibility of having variable stylesheet parts glued together.
In regards to secutiry vulnerabilities:
- Any include is somewhat dangerous. It will be executing whatever files are specified as a PHP script. If it contains purely non-PHP code such as CSS, it's much safer to simply use readfile().
- It's very difficult to guarantee no directory traversal. You still have the potential to show any file on the system that the web server has read access to.
- What about Windows servers that use a \ in the include path?
In regards to the second question, post the exact code that doesn't work. You're saying that you tried .= '\n\n', which should have introduced literal \n\n characters (as opposed to "\n\n"). If you did use double quotes, then that should have worked. Unless you viewed the file in an editor that wants \r\n. Either way, hard to tell without seeing the specific broken code.
Personally, you're better off just generating a lot of link tags rather than trying to jam these scripts together. I suppose you have your reason though.
精彩评论