【问题标题】:Need to add newline between include()ed css files需要在 include()ed css 文件之间添加换行符
【发布时间】:2011-04-03 04:50:15
【问题描述】:

我在每个页面(页眉、全局、主页、页脚等)上加载了一堆 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-&gt;appContent['css']['link'] 是每个页面的动态样式表,其中会有很多。
  2. 如何在包含的文件之间添加换行符?
    • 我在foreach() 循环中添加了$output .= '\n\n';,但它不起作用。
    • 我仍然遇到如下输出:

#footer, #push {
height: 3em;
padding-top: 1em;
}#header{

列出的 CSS 有效,但我更希望将 #header 阻止两行,例如:

#footer, #push {
height: 3em;
padding-top: 1em;
}
<br>#header{

(我对奇怪的代码块表示歉意,Markdown 对这些哈希值造成了可怕的破坏,我不知道如何修复它)。

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

【问题讨论】:

  • include() 直接输出文件。您想改用file_get_contents()。然后添加换行符也可以。
  • 成功了!如果您将其作为答案并添加我的脚本开放的任何漏洞,我会给您答案:)
  • 你应该一起避免过滤。在 CSS.php 合并脚本中对样式表部分进行硬编码以避免任何问题。
  • 样式表会根据站点所在的页面而变化。我会更新问题。

标签: php css string concatenation string-concatenation


【解决方案1】:

您应该只将基本名称传递给 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";

}

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

【讨论】:

    【解决方案2】:

    关于安全漏洞:

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

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

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

    【讨论】:

    • 实际上,我唯一的原因是 Firebug 中的 YSlow 说我需要减少我的 HTTP 请求 :) 所以我 确实 有一堆链接标签,但我决定试试我的手,看看我能不能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 2011-10-23
    • 2014-10-16
    • 1970-01-01
    相关资源
    最近更新 更多