Drupal Filefield不会上传javascript文件?

时间:2009-09-04 09:46:58

标签: javascript drupal drupal-6 drupal-files

我有一个网站,个别网页可能需要一些javascript或CSS文件挂在他们的头上。在管理这个过程时,我试图保持客户端的一切,而不是在FTP上对代码中的所有内容进行排序,因此我需要能够上传css和js文件。

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

不理想......

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

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

6 个答案:

答案 0 :(得分: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';
}

所以,是的,正如杰瑞米所猜测的那样,这是一种“安全的事情”。

可以修补RegEx以立即'修复',但这将完全取消对网站上使用的所有文件字段的这个有用的安全检查。

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


修改:关于在调用drupal_add_js()时重命名(和替代方案)的选项:

  • 要重命名文件,请查看file_move()功能。这样做的一个问题是它不会更新文件表中的相应条目,因此如果移动操作成功,您也必须这样做。 (文件字段只存储文件表中相应条目的'fid',因此您需要通过'fid'找到它并根据您的重命名更​​改'filename','filepath'和'filemime'条目/移动)
  • 或者,您可以只加载* .js.txt文件的内容,并使用drupal_add_js()的'inline'选项添加该字符串。这将不那么“优雅”并且可能会受到性能影响,但如果这些不是您特定情况下的重要标准,那就不那么麻烦了。
  • 另一种选择是只是将* .js.txt文件传递给drupal_add_js() ,忽略“错误”扩展名。一个简短的本地测试表明这是有效的(至少在firefox中)。这可能是“努力程度最低”的解决方案,但需要对有关“错误名称”的js文件使用的不同浏览器行为进行一些额外的测试。

答案 1 :(得分:2)

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

答案 2 :(得分: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”。如果是,则将其复制到新位置并重命名。这是在安全检查之后所以确定。我不认为您需要担心缓存清除删除您的js文件,只要您不将它们放在files / js目录中。为你的模块创建自己的目录,你应该没问题。

答案 3 :(得分:2)

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

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

请注意,您必须使用自己的值替换MYMODULE_NAMEMYFIELD_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)));
    }
}

答案 4 :(得分:0)

Drupal还“摧毁”javascript文件。为了防止Drupal自动向文件名添加下划线,有一个隐藏变量在文件名“munged”之前被检查。

将变量设置为1可以解决我的问题(以及更改includes / 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

答案 5 :(得分: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文件夹。 :(