需要在 include()ed css 文件之间添加换行符

发布于 2024-10-29 19:32:01 字数 2330 浏览 2 评论 0原文

我有一堆在每个页面(页眉、全局、主页、页脚等)上加载的 CSS 文件。

我编写了一个简单的 PHP 脚本,将它们编译成单个字符串,然后输出该字符串。

<?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;
?>

它可以这样调用(以及我调用它的方式):

<?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" />

这会产生这样的字符串:

<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" />

这很好,而且 - 更重要的是 - 它有效

那你问我的问题是什么?

这是一个由两部分组成的问题:

  1. 我在脚本中忽略了哪些安全漏洞?
    • 我已经删除了所有目录遍历的可能性,但是还有什么?
    • 我确实需要能够更改链接的内容,因此我无法将它们硬编码到此脚本中。例如,$tmpl->appContent['css']['link']是每个页面的动态样式表,其中会有很多。
  2. 如何在包含的文件之间添加换行符?
    • 我已在 foreach() 循环中添加了 $output .= '\n\n';,但它不起作用。
    • 我仍然坚持这样的输出:

#footer, #push {
高度:3em;
顶部填充:1em;
}#header{

CSS 列出有效,但我更希望将 #header 块向下两行,例如:

#footer ,#push{
高度:3em;
顶部填充:1em;
<代码>}
<代码>
#header{

(我对奇怪的代码块表示歉意,Markdown 在这些哈希值上严重崩溃,我不知道如何修复它)。

请注意,这种缺少换行符的情况仅发生在两个不同文件之间的连接处。每个 CSS 文件内的代码都按照应有的格式进行格式化。

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:

  1. 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.
  2. How can I add line breaks between the included files?
    • I've added $output .= '\n\n'; in the foreach() loop, but it doesn't work.
    • I'm still stuck with output like:

#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;
}

#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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

樱桃奶球 2024-11-05 19:32:01

您应该更愿意仅将基本名称传递给 CSS.php 合并脚本:

<link rel="stylesheet" href="CSS.php?q=global,local,header,index,css3buttons" type="text/css" >

然后在 CSS.php 中实现变得更安全,只需:

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";

}

唯一的区别是该脚本现在具有一点智能,并且知道在哪里查找样式表。因此,您不会失去将可变样式表部分粘合在一起的灵活性。

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.

毁梦 2024-11-05 19:32:01

关于安全漏洞:

  • 任何包含都有些危险。它将执行指定为 PHP 脚本的任何文件。如果它包含纯粹的非 PHP 代码(例如 CSS),那么简单地使用 readfile() 会更安全。
  • 保证不进行目录遍历是非常困难的。您仍然可以显示系统上 Web 服务器具有读取访问权限的任何文件。
  • 在包含路径中使用 \ 的 Windows 服务器怎么样?

关于第二个问题,请发布不起作用的确切代码。您是说您尝试了 .= '\n\n',它应该引入文字 \n\n 字符(而不是“\n\n”)。如果您确实使用了双引号,那么应该有效。除非您在需要 \r\n 的编辑器中查看该文件。无论哪种方式,如果没有看到具体的损坏代码,都很难判断。

就个人而言,您最好生成大量链接标签,而不是尝试将这些脚本塞在一起。我想你也有你的理由。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文