diff --git a/Bugzilla/Attachment.pm b/Bugzilla/Attachment.pm index 7ba91fef8..a3793979e 100644 --- a/Bugzilla/Attachment.pm +++ b/Bugzilla/Attachment.pm @@ -60,6 +60,7 @@ use Bugzilla::Field; use Bugzilla::Hook; use LWP::MediaTypes; +use MIME::Base64; use base qw(Bugzilla::Object); @@ -558,6 +559,9 @@ sub _check_data { $params->{ispatch} = 0; $params->{store_in_file} = 0; } + elsif ($params->{base64_content}) { + $data = decode_base64($params->{base64_content}); + } else { if ($params->{store_in_file} || !ref $params->{data}) { # If it's a filehandle, just store it, not the content of the file @@ -608,11 +612,15 @@ sub _check_description { } sub _check_filename { - my ($invocant, $filename, $is_url) = @_; + my ($invocant, $filename, $params) = @_; - $is_url = $invocant->isurl if ref $invocant; # No file is attached, so it has no name. - return '' if $is_url; + return '' if ref $invocant && $invocant->isurl || $params && $params->{isurl}; + + if ($params && $params->{base64_content}) + { + $filename = $params->{description}; + } $filename = trim($filename); $filename || ThrowUserError('file_not_specified'); @@ -914,11 +922,12 @@ sub run_create_validators { $params->{data} = $class->_check_data($params); $params = $class->SUPER::run_create_validators($params); - $params->{filename} = $class->_check_filename($params->{filename}, $params->{isurl}); + $params->{filename} = $class->_check_filename($params->{filename}, $params); $params->{creation_ts} ||= Bugzilla->dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)'); $params->{modification_time} = $params->{creation_ts}; $params->{submitter_id} = Bugzilla->user->id || ThrowCodeError('invalid_user'); + delete $params->{base64_content}; return $params; } diff --git a/Bugzilla/Config/Attachment.pm b/Bugzilla/Config/Attachment.pm index b861b1b16..d1ecebca0 100644 --- a/Bugzilla/Config/Attachment.pm +++ b/Bugzilla/Config/Attachment.pm @@ -65,6 +65,12 @@ sub get_param_list { default => 0 }, + { + name => 'use_supa_applet', + type => 'b', + default => 0, + }, + # The maximum size (in bytes) for patches and non-patch attachments. # The default limit is 1000KB, which is 24KB less than mysql's default # maximum packet size (which determines how much data can be sent in a diff --git a/attachment.cgi b/attachment.cgi index a8eec4943..d811f2e2e 100755 --- a/attachment.cgi +++ b/attachment.cgi @@ -521,6 +521,7 @@ sub insert { isurl => scalar $cgi->param('attachurl'), mimetype => $content_type, store_in_file => scalar $cgi->param('bigfile'), + base64_content => scalar $cgi->param('base64_content'), }); foreach my $obsolete_attachment (@obsolete_attachments) { diff --git a/extensions/custis/custis.pl b/extensions/custis/custis.pl index 41264eda0..5b2754724 100644 --- a/extensions/custis/custis.pl +++ b/extensions/custis/custis.pl @@ -29,6 +29,11 @@ my $OPTIONAL_MODULES = module => 'Net::IP::Match::XS', feature => 'FOF-Sudo system-to-system authorization', }, + { + package => 'LWP-MediaTypes', + module => 'LWP::MediaTypes', + feature => 'Guessing attachment types', + }, ]; required_modules('custis', $REQUIRED_MODULES); diff --git a/js/Supa.jar b/js/Supa.jar new file mode 100644 index 000000000..1ffb7028e Binary files /dev/null and b/js/Supa.jar differ diff --git a/js/attachment.js b/js/attachment.js index 8fc78c091..5ad2bab1b 100644 --- a/js/attachment.js +++ b/js/attachment.js @@ -21,15 +21,103 @@ * Marc Schumann */ -function switch_aft(n) +var SUPA_JAVA_DISABLED_ERROR = 'You cannot paste images from clipboard because Java support'+ + ' is not enabled in your browser. Please download Java plugin'+ + ' from http://java.com/'; + +function htmlspecialchars_decode(str) { - var f = document.getElementById('form_type_file'+n); - var u = document.getElementById('form_type_url'+n); - var t = document.getElementById('form_type_text'+n); - document.getElementById('tr_file'+n).style.display = f && f.checked ? '' : 'none'; - document.getElementById('tr_text'+n).style.display = t && t.checked ? '' : 'none'; - if (u) - document.getElementById('tr_url'+n).style.display = u.checked ? '' : 'none'; + str = str.replace(/>/g, '>'); + str = str.replace(/</g, '<'); + str = str.replace(/"/g, '"'); + str = str.replace(/'/g, '\''); + str = str.replace(/&/g, '&'); + return str; +} + +function switchAttype(chk) +{ + var t = chk.value=='text'; + var s = chk.value=='supa'; + var u = chk.value=='url'; + var ur = document.getElementById('attype_url_row'); + var sr = document.getElementById('attype_supa_row'); + u = u && ur; + s = s && sr; + document.getElementById('attype_text_row').style.display = t ? '' : 'none'; + document.getElementById('attype_file_row').style.display = t || s || u ? 'none' : ''; + if (ur) ur.style.display = u ? '' : 'none'; + if (sr) sr.style.display = s ? '' : 'none'; + document.getElementById('content_type_row').style.display = s ? 'none' : ''; + var d = document.getElementById('description'); + if (s) + { + if (d.value == '') + d.value = 'Screenshot.png'; + document.getElementById('manual').checked = true; + document.getElementById('contenttypeentry').value = 'image/png'; + document.getElementById('ispatch').checked = false; + setContentTypeDisabledState(chk.form); + var sc = document.getElementById('supa_container'); + if (sc.innerHTML.toLowerCase().indexOf('param('version') && length $cgi->param('version')) # Add an attachment if requested. if (defined($cgi->upload('data')) || $cgi->param('attachurl') || - $cgi->param('text_attachment')) { + $cgi->param('text_attachment') || $cgi->param('base64_content')) +{ $cgi->param('isprivate', $cgi->param('commentprivacy')); # Must be called before create() as it may alter $cgi->param('ispatch'). @@ -240,6 +241,7 @@ if (defined($cgi->upload('data')) || $cgi->param('attachurl') || isurl => scalar $cgi->param('attachurl'), mimetype => $content_type, store_in_file => scalar $cgi->param('bigfile'), + base64_content => scalar $cgi->param('base64_content'), }); }; Bugzilla->error_mode($error_mode_cache); @@ -305,9 +307,10 @@ if (Bugzilla->usage_mode != USAGE_MODE_EMAIL) sent => \@all_mail_results, title => $title, header => $header, + message => $vars->{message}, }; # CustIS Bug 38616 - CC list restriction - if ($bug->{restricted_cc}) + if (!$ses->{message} && $bug->{restricted_cc}) { $ses->{message_vars} = { restricted_cc => [ map { $_->login } @{ $bug->{restricted_cc} } ], diff --git a/show_bug.cgi b/show_bug.cgi index b8112516c..da1c37e2c 100755 --- a/show_bug.cgi +++ b/show_bug.cgi @@ -128,7 +128,7 @@ if (my @f = $cgi->param("includefield")) { %displayfields = map { $_ => 1 } grep { $displayfields{$_} } @f; } -$vars->{'displayfields'} = \%displayfields; +$vars->{displayfields} = \%displayfields; my $sd; if (Bugzilla->session && ($sd = Bugzilla->session_data) && $sd->{sent}) @@ -139,6 +139,8 @@ if (Bugzilla->session && ($sd = Bugzilla->session_data) && $sd->{sent}) header => undef, sent_attrs => undef, failed_checkers => undef, + message => undef, + message_vars => undef, }); $vars->{last_title} = $sd->{title}; $vars->{last_header} = $sd->{header}; @@ -152,7 +154,8 @@ if (Bugzilla->session && ($sd = Bugzilla->session_data) && $sd->{sent}) $vars->{$_} = $sd->{sent_attrs}->{$_} for keys %{$sd->{sent_attrs} || {}}; } -$cgi->send_header($format->{'ctype'}); +$cgi->send_header($format->{ctype}); -$template->process("$format->{'template'}", $vars) - || ThrowTemplateError($template->error()); +$template->process($format->{template}, $vars) + || ThrowTemplateError($template->error()); +exit; diff --git a/template/en/default/admin/params/attachment.html.tmpl b/template/en/default/admin/params/attachment.html.tmpl index 7deeaef92..ae4dde22e 100644 --- a/template/en/default/admin/params/attachment.html.tmpl +++ b/template/en/default/admin/params/attachment.html.tmpl @@ -66,6 +66,11 @@ "specify a URL when creating an attachment and " _ "treat the URL itself as if it were an attachment.", + use_supa_applet => + "If this option is on, the SUPA java applet " _ + "(Screenshot UPload Applet) will be enabled to allow uploading of images from the clipboard. " _ + "Note this requires Java support in user's browser.", + maxattachmentsize => "The maximum size (in kilobytes) of attachments stored in the database. " _ "$terms.Bugzilla will not accept attachments greater than this number " _ diff --git a/template/en/default/attachment/createformcontents.html.tmpl b/template/en/default/attachment/createformcontents.html.tmpl index 5e7450dc0..aa85dbf83 100644 --- a/template/en/default/attachment/createformcontents.html.tmpl +++ b/template/en/default/attachment/createformcontents.html.tmpl @@ -21,46 +21,66 @@ # Marc Schumann #%] - - Attachment text: or - - - : + [%# Don't remove this hidden text, its purpose is to align columns correctly! %] + Attachment text: - Enter the path to the file on your computer.
- + + + [% IF Param("allow_attach_url") %] + + + [% END %] + + + [% IF Param("use_supa_applet") %] + + + [% END %] - + + : + + Enter the path to the file on your computer.
+ + + + - Enter attachment text here instead of selecting file.
+ Enter or paste attachment text here:
+[% IF Param("use_supa_applet") %] + + + Paste again + + + + [% FILTER html %] + + + + + + + + Please enable Java Applet support in your browser. + + [% END %] + + +[% END %] [% IF Param("maxlocalattachment") && !Param("force_attach_bigfile") %] BigFile: - + @@ -68,10 +88,10 @@ function switch_afot(fot) [% END %] [% IF Param("allow_attach_url") %] - + : - URL to be attached instead.
+ URL to be attached instead.
@@ -82,16 +102,16 @@ function switch_afot(fot) : - Describe the attachment briefly.
+ Describe the attachment briefly.
- + Content Type: - If the attachment is a patch, check the box below.
+ If the attachment is a patch, check the box below.
+ onchange="setContentTypeDisabledState(this.form);" />

[%# Reset this whenever the page loads so that the JS state is up to date %] - Otherwise, choose a method for determining the content type.
+ Otherwise, choose a method for determining the content type.
-
+
:
+
: @@ -123,7 +143,7 @@ function switch_afot(fot) [% IF flag_types && flag_types.size > 0 %] - [% PROCESS "flag/list.html.tmpl" bug_id=bugid attach_id=attachid %]
+ [% PROCESS "flag/list.html.tmpl" bug_id=bugid attach_id=attachid %]
[% END %] diff --git a/template/en/default/bug/create/create.html.tmpl b/template/en/default/bug/create/create.html.tmpl index 120cdc859..ea715f437 100644 --- a/template/en/default/bug/create/create.html.tmpl +++ b/template/en/default/bug/create/create.html.tmpl @@ -272,7 +272,8 @@ TUI_hide_default('expert_fields'); [% END %]
+ enctype="multipart/form-data" onkeypress="return ctrlEnter(event||window.event,this)" + onsubmit="return encodeSupaContent()"> diff --git a/template/en/default/list/edit-multiple.html.tmpl b/template/en/default/list/edit-multiple.html.tmpl index 11fa43e3d..efaf17097 100644 --- a/template/en/default/list/edit-multiple.html.tmpl +++ b/template/en/default/list/edit-multiple.html.tmpl @@ -393,7 +393,7 @@ document.write(' [% IF !bug_status.is_open %] - [% filtered_status = bug_status.name FILTER js %] + [% filtered_status = bug_status.name FILTER js %] [% closed_status_array.push( filtered_status ) %] [% END %] [% END %] diff --git a/template/en/default/list/table.html.tmpl b/template/en/default/list/table.html.tmpl index a86e8debc..e8b80d5ea 100644 --- a/template/en/default/list/table.html.tmpl +++ b/template/en/default/list/table.html.tmpl @@ -153,7 +153,7 @@ [% IF dotweak %] - + [% END %]