mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-29 19:33:54 +01:00
move code for html or javascript content-type headers from webdav to html class and use it for attachments too
This commit is contained in:
parent
2fcfa9e0a8
commit
36bc17a442
@ -1870,7 +1870,7 @@ class mail_compose
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//error_log(__METHOD__.__LINE__.'->'.array2string($attachment));
|
//error_log(__METHOD__.__LINE__.'->'.array2string($attachment));
|
||||||
html::content_header($attachment['name'], $attachment['type'], 0, True, $_GET['mode'] == "save");
|
html::safe_content_header($attachment['attachment'], $attachment['name'], $attachment['type'], $size=0, true, $_GET['mode'] == "save");
|
||||||
echo $attachment['attachment'];
|
echo $attachment['attachment'];
|
||||||
|
|
||||||
common::egw_exit();
|
common::egw_exit();
|
||||||
|
@ -2506,7 +2506,7 @@ class mail_ui
|
|||||||
}
|
}
|
||||||
//error_log(__METHOD__.__LINE__.'->'.array2string($attachment));
|
//error_log(__METHOD__.__LINE__.'->'.array2string($attachment));
|
||||||
$filename = ($attachment['name']?$attachment['name']:($attachment['filename']?$attachment['filename']:$mailbox.'_uid'.$uid.'_part'.$part));
|
$filename = ($attachment['name']?$attachment['name']:($attachment['filename']?$attachment['filename']:$mailbox.'_uid'.$uid.'_part'.$part));
|
||||||
html::content_header($filename,$attachment['type'],0,True,($_GET['mode'] == "save"));
|
html::safe_content_header($attachment['attachment'], $filename, $attachment['type'], $size=0, True, $_GET['mode'] == "save");
|
||||||
echo $attachment['attachment'];
|
echo $attachment['attachment'];
|
||||||
|
|
||||||
$GLOBALS['egw']->common->egw_exit();
|
$GLOBALS['egw']->common->egw_exit();
|
||||||
@ -2550,19 +2550,16 @@ class mail_ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
$GLOBALS['egw']->session->commit_session();
|
$GLOBALS['egw']->session->commit_session();
|
||||||
if ($display==false)
|
if (!$display)
|
||||||
{
|
{
|
||||||
$subject = str_replace('$$','__',mail_bo::decode_header($headers['SUBJECT']));
|
$subject = str_replace('$$','__',mail_bo::decode_header($headers['SUBJECT']));
|
||||||
html::content_header($subject .".eml",'message/rfc822',0,True,($display==false));
|
html::safe_content_header($message, $subject.".eml", 'message/rfc822', $size=0, true, true);
|
||||||
echo $message;
|
echo $message;
|
||||||
|
|
||||||
$GLOBALS['egw']->common->egw_exit();
|
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
header('Content-type: text/html; charset=iso-8859-1');
|
html::safe_content_header($message, $subject.".eml", 'text/html', $size=0, true, false);
|
||||||
print '<pre>'. htmlspecialchars($message, ENT_NOQUOTES, 'iso-8859-1') .'</pre>';
|
print '<pre>'. htmlspecialchars($message, ENT_NOQUOTES, 'utf-8') .'</pre>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1488,7 +1488,91 @@ egw_LAB.wait(function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output content headers for file downloads
|
* Output content headers for user-content, mitigating risk of javascript or html
|
||||||
|
*
|
||||||
|
* Mitigate risk of serving javascript or css from our domain,
|
||||||
|
* which will get around same origin policy and CSP!
|
||||||
|
*
|
||||||
|
* Mitigate risk of html downloads by using CSP or force download for IE
|
||||||
|
*
|
||||||
|
* @param resource|string &$content content might be changed by this call
|
||||||
|
* @param string $path filename or path for content-disposition header
|
||||||
|
* @param string &$mime ='' mimetype or '' (default) to detect it from filename, using mime_magic::filename2mime()
|
||||||
|
* on return used, maybe changed, mime-type
|
||||||
|
* @param int $length =0 content length, default 0 = skip that header
|
||||||
|
* on return changed size
|
||||||
|
* @param boolean $nocache =true send headers to disallow browser/proxies to cache the download
|
||||||
|
* @param boolean $force_download =true send content-disposition attachment header
|
||||||
|
* @param boolean $no_content_type =false do not send actual content-type and content-length header, just content-disposition
|
||||||
|
*/
|
||||||
|
public static function safe_content_header(&$content, $path, &$mime='', &$length=0, $nocache=true, $force_download=true, $no_content_type=false)
|
||||||
|
{
|
||||||
|
// mitigate risk of serving javascript or css via webdav from our domain,
|
||||||
|
// which will get around same origin policy and CSP
|
||||||
|
list($type, $subtype) = explode('/', strtolower($mime));
|
||||||
|
if (!$force_download && in_array($type, array('application', 'text')) &&
|
||||||
|
in_array($subtype, array('javascript', 'x-javascript', 'ecmascript', 'jscript', 'vbscript', 'css')))
|
||||||
|
{
|
||||||
|
// unfortunatly only Chrome and IE >= 8 allow to switch content-sniffing off with X-Content-Type-Options: nosniff
|
||||||
|
if (html::$user_agent == 'chrome' || html::$user_agent == 'msie' && html::$ua_version >= 8)
|
||||||
|
{
|
||||||
|
$mime = 'text/plain';
|
||||||
|
header('X-Content-Type-Options: nosniff'); // stop IE & Chrome from content-type sniffing
|
||||||
|
}
|
||||||
|
// for the rest we change mime-type to text/html and let code below handle it safely
|
||||||
|
// this stops Safari and Firefox from using it as src attribute in a script tag
|
||||||
|
// but only for "real" browsers, we dont want to modify data for our WebDAV clients
|
||||||
|
elseif (isset($_SERVER['HTTP_REFERER']))
|
||||||
|
{
|
||||||
|
$mime = 'text/html';
|
||||||
|
if (is_resource($content))
|
||||||
|
{
|
||||||
|
$data = fread($content, $length);
|
||||||
|
fclose($content);
|
||||||
|
$content =& $data;
|
||||||
|
unset($data);
|
||||||
|
}
|
||||||
|
$content = '<pre>'.$content;
|
||||||
|
$length += 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// mitigate risk of html downloads by using CSP or force download for IE
|
||||||
|
if (!$force_download && in_array($mime, array('text/html', 'application/xhtml+xml')))
|
||||||
|
{
|
||||||
|
// use CSP only for current user-agents/versions I was able to positivly test
|
||||||
|
if (html::$user_agent == 'chrome' && html::$ua_version >= 24 ||
|
||||||
|
// mobile FF 24 on Android does NOT honor CSP!
|
||||||
|
html::$user_agent == 'firefox' && !html::$ua_mobile && html::$ua_version >= 24 ||
|
||||||
|
html::$user_agent == 'safari' && !html::$ua_mobile && html::$ua_version >= 536 || // OS X
|
||||||
|
html::$user_agent == 'safari' && html::$ua_mobile && html::$ua_version >= 9537) // iOS 7
|
||||||
|
{
|
||||||
|
$csp = "script-src 'none'"; // forbid to execute any javascript
|
||||||
|
header("Content-Security-Policy: $csp");
|
||||||
|
header("X-Webkit-CSP: $csp"); // Chrome: <= 24, Safari incl. iOS
|
||||||
|
//header("X-Content-Security-Policy: $csp"); // FF <= 22
|
||||||
|
//error_log(__METHOD__."('$options[path]') ".html::$user_agent.'/'.html::$ua_version.(html::$ua_mobile?'/mobile':'').": using Content-Security-Policy: $csp");
|
||||||
|
}
|
||||||
|
else // everything else get's a Content-dispostion: attachment, to be on save side
|
||||||
|
{
|
||||||
|
//error_log(__METHOD__."('$options[path]') ".html::$user_agent.'/'.html::$ua_version.(html::$ua_mobile?'/mobile':'').": using Content-disposition: attachment");
|
||||||
|
$force_download = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($no_content_type)
|
||||||
|
{
|
||||||
|
if ($force_download) self::content_disposition_header(egw_vfs::basename($path), $force_download);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self::content_header(egw_vfs::basename($path), $mime, $length, $nocache, $force_download);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output content-type headers for file downloads
|
||||||
|
*
|
||||||
|
* This function should only be used for non-user supplied content!
|
||||||
|
* For uploaded files, mail attachmentes, etc, you have to use safe_content_header!
|
||||||
*
|
*
|
||||||
* @author Miles Lott originally in browser class
|
* @author Miles Lott originally in browser class
|
||||||
* @param string $fn filename
|
* @param string $fn filename
|
||||||
@ -1533,21 +1617,16 @@ egw_LAB.wait(function() {
|
|||||||
*/
|
*/
|
||||||
public static function content_disposition_header($fn,$forceDownload=true)
|
public static function content_disposition_header($fn,$forceDownload=true)
|
||||||
{
|
{
|
||||||
if ($forceDownload===true)
|
if ($forceDownload===true)
|
||||||
{
|
{
|
||||||
$attachment = ' attachment;';
|
$attachment = ' attachment;';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$attachment = ' inline;';
|
$attachment = ' inline;';
|
||||||
}
|
}
|
||||||
// limit IE hack (no attachment in Content-disposition header) to IE < 9
|
|
||||||
if(self::$user_agent == 'msie' && self::$ua_version < 9)
|
|
||||||
{
|
|
||||||
$attachment = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Content-disposition:'.$attachment.' filename="'.translation::to_ascii($fn).'"; filename*=utf-8\'\''.rawurlencode($fn));
|
header('Content-disposition:'.$attachment.' filename="'.translation::to_ascii($fn).'"; filename*=utf-8\'\''.rawurlencode($fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -648,55 +648,14 @@ class vfs_webdav_server extends HTTP_WebDAV_Server_Filesystem
|
|||||||
}
|
}
|
||||||
if (($ok = parent::GET($options)))
|
if (($ok = parent::GET($options)))
|
||||||
{
|
{
|
||||||
// mitigate risk of serving javascript or css via webdav from our domain,
|
// mitigate risks of serving javascript or css from our domain
|
||||||
// which will get around same origin policy and CSP
|
html::safe_content_header($options['stream'], $options['path'], $options['mimetype'], $options['size'], false,
|
||||||
list($type, $subtype) = explode('/', strtolower($options['mimetype']));
|
$this->force_download, true); // true = do not send content-type and content-length header, but modify values
|
||||||
if (!$this->force_download && in_array($type, array('application', 'text')) &&
|
|
||||||
in_array($subtype, array('javascript', 'x-javascript', 'ecmascript', 'jscript', 'vbscript', 'css')))
|
if (!is_stream($options['stream']))
|
||||||
{
|
{
|
||||||
// unfortunatly only Chrome and IE >= 8 allow to switch content-sniffing off with X-Content-Type-Options: nosniff
|
$options['data'] =& $options['stream'];
|
||||||
if (html::$user_agent == 'chrome' || html::$user_agent == 'msie' && html::$ua_version >= 8)
|
unset($options['stream']);
|
||||||
{
|
|
||||||
$options['mimetype'] = 'text/plain';
|
|
||||||
header('X-Content-Type-Options: nosniff'); // stop IE & Chrome from content-type sniffing
|
|
||||||
}
|
|
||||||
// for the rest we change mime-type to text/html and let code below handle it safely
|
|
||||||
// this stops Safari and Firefox from using it as src attribute in a script tag
|
|
||||||
// but only for "real" browsers, we dont want to modify data for our WebDAV clients
|
|
||||||
elseif (isset($_SERVER['HTTP_REFERER']))
|
|
||||||
{
|
|
||||||
$options['mimetype'] = 'text/html';
|
|
||||||
$options['data'] = '<pre>'.fread($options['stream'], $options['size']);
|
|
||||||
$options['size'] += 5;
|
|
||||||
fclose($options['stream']);
|
|
||||||
unset($options['stream']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// mitigate risk of html downloads by using CSP or force download for IE
|
|
||||||
if (!$this->force_download && in_array($options['mimetype'], array('text/html', 'application/xhtml+xml')))
|
|
||||||
{
|
|
||||||
// use CSP only for current user-agents/versions I was able to positivly test
|
|
||||||
if (html::$user_agent == 'chrome' && html::$ua_version >= 24 ||
|
|
||||||
// mobile FF 24 on Android does NOT honor CSP!
|
|
||||||
html::$user_agent == 'firefox' && !html::$ua_mobile && html::$ua_version >= 24 ||
|
|
||||||
html::$user_agent == 'safari' && !html::$ua_mobile && html::$ua_version >= 536 || // OS X
|
|
||||||
html::$user_agent == 'safari' && html::$ua_mobile && html::$ua_version >= 9537) // iOS 7
|
|
||||||
{
|
|
||||||
$csp = "script-src 'none'"; // forbid to execute any javascript
|
|
||||||
header("Content-Security-Policy: $csp");
|
|
||||||
header("X-Webkit-CSP: $csp"); // Chrome: <= 24, Safari incl. iOS
|
|
||||||
//header("X-Content-Security-Policy: $csp"); // FF <= 22
|
|
||||||
//error_log(__METHOD__."('$options[path]') ".html::$user_agent.'/'.html::$ua_version.(html::$ua_mobile?'/mobile':'').": using Content-Security-Policy: $csp");
|
|
||||||
}
|
|
||||||
else // everything else get's a Content-dispostion: attachment, to be on save side
|
|
||||||
{
|
|
||||||
//error_log(__METHOD__."('$options[path]') ".html::$user_agent.'/'.html::$ua_version.(html::$ua_mobile?'/mobile':'').": using Content-disposition: attachment");
|
|
||||||
$this->force_download = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($this->force_download)
|
|
||||||
{
|
|
||||||
html::content_disposition_header(egw_vfs::basename($options['path']),true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $ok;
|
return $ok;
|
||||||
|
Loading…
Reference in New Issue
Block a user