6

我有一个网站,其中个别页面可能需要将一些 javascript 或 CSS 文件挂在他们的脑海中。在管理此过程时,我试图将所有内容都保留在客户端,而不是访问 FTP 并将代码中的所有内容整理出来,因此我需要能够上传 css 和 js 文件。

我已经启动并运行 CCK 文件字段,它适用于 css 文件,但它拒绝上传 .js 文件。相反,它似乎将每个 .js 视为“.js.txt”,然后该文件在服务器上显示为 thisismyfile.js.txt

不理想...

有谁知道如何解决这个问题。是 Drupal 或服务器的 mime 类型问题,还是 Drupal 设置为避免脚本上传和 n00b 黑客攻击。

上传文件后,我打算在页面或节点上使用 PHP 模式来调用drupal_add_cssdrupal_add_js

4

6 回答 6

6

查看来自 filefield 模块的field_file_save_file()函数field_file.inc,您可以找到以下代码段

// Rename potentially executable files, to help prevent exploits.
if (preg_match('/\.(php|pl|py|cgi|asp|js)$/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
  $file->filemime = 'text/plain';
  $file->filepath .= '.txt';
  $file->filename .= '.txt';
}

所以,是的,正如 Jeremy 猜测的那样,这是一个“安全问题”。

可以修补该 RegEx 以立即“修复”,但这将完全删除该站点上使用的所有文件字段的此其他有用的安全检查。

因此,更具体的解决方法可能是更好的方法。由于您无论如何都想通过drupal_add_js()代码调用添加文件,您不妨在那里进行重命名,添加某种验证以确保您可以“信任”文件(例如,谁上传了它,等等)。


编辑:关于调用时重命名(和替代)的选项drupal_add_js()

  • 要重命名文件,请查看file_move()函数。这样做的一个问题是它不会更新文件表中的相应条目,因此如果移动操作成功,您也必须这样做。(文件字段只是将相应条目的“fid”存储在文件表中,因此您需要通过“fid”找到它并根据您的重命名更​​改“文件名”、“文件路径”和“文件mime”条目/移动)
  • 或者,您可以只加载 *.js.txt 文件的内容并使用 .js 的“内联”选项添加该字符串drupal_add_js()。这将不那么“优雅”,并且可能会影响性能,但是如果在您的特定情况下这些不是重要的标准,那么麻烦就会减少。
  • 另一种选择是将 *.js.txt 文件按原样传递给drupal_add_js(),而忽略“错误”扩展名。一个简短的本地测试表明这是有效的(至少在 Firefox 中)。这可能是“最省力”的解决方案,但需要一些额外的测试,涉及不同的浏览器行为,涉及“错误命名”的 js 文件的使用。
于 2009-09-04T10:07:19.967 回答
2

允许 Drupal 上传 javascript 文件会带来安全风险,这也是它不允许您这样做,而是附加 .txt 扩展名的原因。原因是 js 文件与 php、pl、py、cgi、asp 一起可执行。因此,如果 Drupal 可以将这些文件上传到服务器,那么作恶者就有可能上传一个文件并在您的服务器上运行它做各种令人讨厌的事情,基本上一切皆有可能。最好的办法是找到一种不同的方式来上传安全的文件。

于 2009-09-04T11:09:25.207 回答
2

我有类似的需求,并找到了一种绕过安全性的方法,首先通过在 hook_install 中运行这行代码来更改“allow_insecure_uploads”变量值:

 variable_set('allow_insecure_uploads', 1);

然后在一个模块中添加这个函数

/**
 * Implementation of FileField's hook_file_insert().
 */
function MODULE_NAME_file_insert(&$file) {
  //look for files with the extenstion .js.txt and rename them to just .js
  if(substr($file->filename, -7) == '.js.txt'){
  $file_path = $file->filepath;
  $new_file_path = substr($file_path, 0, strlen($file_path)-4);
  file_move($file_path, $new_file_path);

  $file->filepath = $file_path;
  $file->filename = substr($file->filename, 0, strlen($file->filename)-4);
  $file->filemime = file_get_mimetype($file->filename);
  $file->destination = $file->filepath;
  $file->status = FILE_STATUS_TEMPORARY;
  drupal_write_record('files', $file);
}

它的作用是在 hook_insert 调用中检查文件是否具有扩展名“.js.txt”。如果是,则将其复制到新位置并重命名。这是在安全检查之后,所以没关系。只要您不将它们放在 files/js 目录中,我认为您无需担心缓存清除删除您的 js 文件。为你的模块创建你自己的目录,你应该没问题。

于 2010-09-16T22:03:57.543 回答
2

当我想允许特定字段的 .js 文件按原样上传(没有 .txt 和 'application/javascript' mimetype)时,我遇到了这种情况。另外,我不想改变 Drupal 核心……当然。

所以我需要创建一个实现 hook_file_presave() 的模块。这也适用于 Multiupload File Widget,因为它的钩子是 on file_save()

请注意,您必须将MYMODULE_NAMEand替换MYFIELD_NAME为您自己的值。

function MYMODULE_NAME_file_presave($file) {

    // Bypass secure file extension for .js for field_additional_js field only
    if((isset($file->source) && strpos($file->source, "MYFIELD_NAME") !== FALSE) && substr($file->filename, strlen($file->filename) - 7) == ".js.txt") {

        // Define new uri and save previous
        $original_uri = $file->uri;
        $new_uri = substr($file->destination, null, -4);

        // Alter file object
        $file->filemime = 'application/javascript';
        $file->filename = substr($file->filename, null, -4);
        $file->destination = file_destination($new_uri, FILE_EXISTS_RENAME);
        $file->uri = $file->destination;

        // Move fil (to remove .txt)
        file_unmanaged_move($original_uri, $file->destination);

        // Display message that says that
        drupal_set_message(t('Security bypassed for .js for this specific field (%f).', array('%f' => $file->filename)));
    }
}
于 2014-07-31T20:26:11.237 回答
0

Drupal 也“munges” javascript 文件。为了防止 Drupal 自动将下划线添加到文件名,在文件名“munged”之前检查了一个隐藏变量。

将变量设置为 1 可以解决我的问题(以及更改包含/file.inc 中的 REGEX)。

我讨厌黑客核心,但这对我来说似乎是一个糟糕的设计。Javascript 文件不是像 php、py、pl、cgi 和 asp 这样的服务器端脚本。

您可以使用允许的文件扩展名设置来防止上传 php 和其他服务器端脚本。

例如:

variable_set('allow_insecure_uploads', 1);

见: http ://api.drupal.org/api/function/file_munge_filename/6

于 2010-03-22T02:33:49.393 回答
0

因此,将 .js 文件上传到 files 目录几乎是不可能的。

即使您设法干净地上传 .js 文件,这些文件也会在缓存被清除时被删除。

每当执行 drupal_clear_js_cache() 函数时,文件目录中的任何 js 文件都将被删除。

http://api.drupal.org/api/function/drupal_clear_js_cache/6

因此 Drupal 将文件上传目录中的 .js 文件视为临时文件。

现在我明白了他们为什么要附加“.txt”,这是为了防止在清除缓存时将它们删除。

因此,作为一种妥协,我想我将手动(通过 FTP)将 .js 文件上传到 /misc 文件夹。:(

于 2010-03-22T16:45:22.700 回答