%# BEGIN BPS TAGGED BLOCK {{{
%#
%# COPYRIGHT:
%#
%# This software is Copyright (c) 1996-2025 Best Practical Solutions, LLC
%#                                          <sales@bestpractical.com>
%#
%# (Except where explicitly superseded by other copyright notices)
%#
%#
%# LICENSE:
%#
%# This work is made available to you under the terms of Version 2 of
%# the GNU General Public License. A copy of that license should have
%# been provided with this software, but in any event can be snarfed
%# from www.gnu.org.
%#
%# This work is distributed in the hope that it will be useful, but
%# WITHOUT ANY WARRANTY; without even the implied warranty of
%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
%# General Public License for more details.
%#
%# You should have received a copy of the GNU General Public License
%# along with this program; if not, write to the Free Software
%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
%# 02110-1301 or visit their web page on the internet at
%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
%#
%#
%# CONTRIBUTION SUBMISSION POLICY:
%#
%# (The following paragraph is not intended to limit the rights granted
%# to you to modify and distribute this software under the terms of
%# the GNU General Public License and is only of importance to you if
%# you choose to contribute your changes and enhancements to the
%# community by submitting them to Best Practical Solutions, LLC.)
%#
%# By intentionally submitting any modifications, corrections or
%# derivatives to this work, or any other work intended for use with
%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
%# you are the copyright holder for those contributions and you grant
%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
%# royalty-free, perpetual, license to use, copy, create derivative
%# works based on those contributions, and sublicense and distribute
%# those contributions and any derivatives thereof.
%#
%# END BPS TAGGED BLOCK }}}
<div class="form-row">
  <div class="col-auto">
% if ( RT->Config->Get('Crypt')->{'Outgoing'} eq 'GnuPG' ) {
    <div class="form-inline">
      <& '/Widgets/Form/Boolean:InputOnly',
        Name => 'Sign', CurrentValue => $self->{'Sign'},
        DefaultLabel => loc( 'Sign using' ),
      &>
      &nbsp;<& 'SelectKeyForSigning', User => $session{'CurrentUser'}->UserObj &>
    </div>
% } else {
    <& '/Widgets/Form/Boolean:InputOnly',
        Name => 'Sign', CurrentValue => $self->{'Sign'},
        DefaultLabel => loc( 'Sign' ),
    &>
% }
  </div>

  <div class="col-auto">
    <& /Widgets/Form/Boolean:InputOnly, Name => 'Encrypt', CurrentValue => $self->{'Encrypt'}, DefaultLabel => loc( 'Encrypt' ) &>
  </div>
</div>

<%ARGS>
$self => undef,
</%ARGS>
<%INIT>
return unless $self;
</%INIT>

<%METHOD new>
<%ARGS>
$Arguments => {}
</%ARGS>
<%INIT>
return undef unless RT->Config->Get('Crypt')->{'Enable'};
return { %$Arguments };
</%INIT>
</%METHOD>

<%METHOD ShowIssues>
<%ARGS>
$self => undef,
$Protocol => undef
$Queue => undef
</%ARGS>
<%INIT>
return unless $self;

return $m->comp( '/Elements/Crypt/KeyIssues',
    Protocol => $Protocol,
    Queue => $Queue,
    Issues => $self->{'GnuPGRecipientsKeyIssues'} || [],
    SignAddresses => $self->{'GnuPGCanNotSignAs'} || [],
);
</%INIT>
</%METHOD>


<%METHOD Process>
<%ARGS>
$self => undef
$QueueObj => undef
$TicketObj => undef
</%ARGS>
<%INIT>
return unless $self;

$QueueObj ||= $TicketObj->QueueObj if $TicketObj;

foreach ( qw(Sign Encrypt) ) {
    $self->{ $_ } = $m->comp( '/Widgets/Form/Boolean:Process',
        Name => $_,
        DefaultValue => $QueueObj->$_,
        Arguments => $self,
    );
}
</%INIT>
</%METHOD>

<%METHOD Check>
<%ARGS>
$self      => undef
$Operation => 'Update'
$TicketObj => undef
$QueueObj  => undef
</%ARGS>
<%INIT>
return 1 unless $self;

my $checks_failure = 0;

if ( $self->{'Sign'} ) {
    $QueueObj ||= $TicketObj->QueueObj
        if $TicketObj;

    my $private = $session{'CurrentUser'}->UserObj->PrivateKey || '';
    my $queue = ($self->{'UpdateType'} && $self->{'UpdateType'} eq "private")
        ? ( $QueueObj->CommentAddress || RT->Config->Get('CommentAddress') )
        : ( $QueueObj->CorrespondAddress || RT->Config->Get('CorrespondAddress') );

    my $address = $self->{'SignUsing'} || $queue;
    if ($address ne $private and $address ne $queue) {
        push @{ $self->{'GnuPGCanNotSignAs'} ||= [] }, $address;
        $checks_failure = 1;
    } elsif ( not RT::Crypt->DrySign( Queue => $QueueObj, Signer => $address ) ) {
        push @{ $self->{'GnuPGCanNotSignAs'} ||= [] }, $address;
        $checks_failure = 1;
    } else {
        RT::Crypt->UseKeyForSigning( $self->{'SignUsing'} )
            if $self->{'SignUsing'};
    }
}

if ( $self->{'Encrypt'} ) {

    my @recipients;

    if ( $Operation eq 'Update' ) {
        @recipients = map {$_->Recipients} $TicketObj->DryRun(
            sub { ProcessUpdateMessage( ARGSRef => {%$self}, TicketObj => $TicketObj ) } );
    }
    elsif ( $Operation eq 'Create' ) {
        $TicketObj = RT::Ticket->new( $session{'CurrentUser'} );
        @recipients = map {$_->Recipients} $TicketObj->DryRun(
            sub { CreateTicket( %$self, TicketObj => $TicketObj ); } );
    }
    elsif ( $Operation eq 'Forward' ) {
        push @recipients, RT::EmailParser->ParseEmailAddress( $self->{$_} || '' ) for qw(To Cc Bcc);
    }
    else {
        $RT::Logger->crit('Incorrect operation: '. $Operation );
    }

    my %seen;
    @recipients = grep !$seen{ lc $_ }++, @recipients;

    RT::Crypt->UseKeyForEncryption(
        map { (/^UseKey-(.*)$/)[0] => $self->{ $_ } }
        grep $self->{ $_ } && /^UseKey-/,
        keys %$self
    );

    $QueueObj ||= $TicketObj->QueueObj if $TicketObj;
    my ($status, @issues) = RT::Crypt->CheckRecipients( Queue => $QueueObj, Recipients => \@recipients );
    push @{ $self->{'GnuPGRecipientsKeyIssues'} ||= [] }, @issues;
    $checks_failure = 1 unless $status;
}

return $checks_failure ? 0 : 1;
</%INIT>
</%METHOD>
