<%args> $type => undef $id => undef $msg => undef $activities => undef $details => undef $history => undef

<% i18nGettext ('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_SHOW_INSTANCE_TITLE', '__ID__' => $msg->{PARAMS}->{WORKFLOW}->{ID}, '__STATE__' => $msg->{PARAMS}->{WORKFLOW}->{STATE}) %>


<% i18nGettext ('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_SHOW_INSTANCE_ACTIVITIES') %>

% foreach my $action (sort keys %actions) % { % my $filename = lc($actions{$action}); % $filename =~ s/i18n_openxpki_wf_[^_]*_//; % # because of this hack, we need to specify all variants of this in % # the source, not the best solution here ... :-/ % my $buttonname = 'I18N_OPENXPKI_WF_ACTION_' . uc($filename);
<& /service/open_form.mhtml, 'action' => $context->{menu}->get_root()."/service/workflow/activity/$filename.html" &> % if ($filename eq 'approve_csr') { <& /lib/html/hidden.mhtml, 'name' => 'context_hash', 'value' => $context_hash &> % } <& /lib/html/hidden.mhtml, 'name' => 'type', 'value' => $type &> <& /lib/html/hidden.mhtml, 'name' => 'id', 'value' => $id &> <& /lib/html/input.mhtml, 'type' => 'submit', 'value' => i18nGettext($buttonname) &> <& /service/close_form.mhtml &>
% }

% ## I expect the following: % ## SERVICE_MSG => "COMMAND", % ## COMMAND => $cmd, % ## PARAMS => % ## { % ## WORKFLOW => % ## { % ## ID => $id, % ## STATE => $state, % ## CONTEXT => { ... a simple hash ... } % ## } % ## }

<% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_OVERVIEW') %>

% my $last_update = $msg->{PARAMS}->{WORKFLOW}->{LAST_UPDATE}; % $last_update =~ s/T/ /; % $last_update .= ' UTC'; % BASIC_DETAILS: % foreach my $context_key (@{ $basic_details{$msg->{PARAMS}->{WORKFLOW}->{TYPE}} }) { % # skip if context entry does not exist - this may for example be the % # case with entries that are added later in the process, such as % # csr_serial in CSR workflows % next BASIC_DETAILS if (! exists $msg->{PARAMS}->{WORKFLOW}->{CONTEXT}->{$context_key}); % }
<% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_TYPE') %> <% i18nGettext($msg->{PARAMS}->{WORKFLOW}->{TYPE}) %>
<% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_CREATOR') %> <% delete($msg->{PARAMS}->{WORKFLOW}->{CONTEXT}->{creator}) %>
<% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_LAST_UPDATE') %><% $last_update %>
% $m->comp('/lib/field_to_i18n.mhtml', % 'field' => $context_key); % my $value = delete($msg->{PARAMS}->{WORKFLOW}->{CONTEXT}->{$context_key}); % $value = encode('UTF-8', $value); % if ($untainted{$context_key}) { <% i18nGettext($value) | n %> % } % else { <% i18nGettext($value) %> % }
% if (! $details) { <% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_SHOW_INSTANCE_DETAILS') %> ...
% } % else {

<% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_OTHER_WORKFLOW_CONTEXT_KEYS') %> (<% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_HIDE') %>)

% foreach my $param (sort keys %{$msg->{PARAMS}->{WORKFLOW}->{CONTEXT}}) { %# next if ($param eq "approvals" and length $msg->{PARAMS}->{WORKFLOW}->{CONTEXT}->{$param} == 0); %# next if ($param eq "cert_profile_id"); % next if ($param =~ m{ \A _ }xms); # ignore "volatile" context parameters % }
% $m->comp('/lib/field_to_i18n.mhtml', % 'field' => $param); % my $value = $msg->{PARAMS}->{WORKFLOW}->{CONTEXT}->{$param}; % # someone is interpreting UTF8 data here, re-encode ... % # FIXME - find out why this is actually happening so that we % # can eliminate the source % $value = encode('UTF-8', $value); % if ($untainted{$param}) { <% i18nGettext($value) | n %> % } % else { <% i18nGettext($value) %> % }
% } % if (! $history) { <% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_SHOW_INSTANCE_HISTORY') %> ...
% } % else {

<% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_SHOW_INSTANCE_HISTORY_TITLE') %> (<% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_HIDE') %>)

% foreach my $entry (@history) { % my ($next_state) = ($entry->{'WORKFLOW_DESCRIPTION'} =~ m{ NEW_STATE[^\s+]*:\ (.+) }xms); % next if ($entry->{'WORKFLOW_ACTION'} eq 'Create workflow'); % }
<% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_SHOW_INSTANCE_HISTORY_DATE') %> <% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_SHOW_INSTANCE_HISTORY_STATE') %> <% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_SHOW_INSTANCE_HISTORY_ACTION') %> <% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_SHOW_INSTANCE_HISTORY_NEW_STATE') %> <% i18nGettext('I18N_OPENXPKI_CLIENT_HTML_MASON_WORKFLOW_SHOW_INSTANCE_HISTORY_USER') %>
<% $entry->{'WORKFLOW_HISTORY_DATE'} %> <% $entry->{'WORKFLOW_STATE'} %> <& /lib/field_to_i18n.mhtml, field => $entry->{'WORKFLOW_ACTION'} &> % if ($entry->{'WORKFLOW_DESCRIPTION'} =~ /NEW_STATE_AUTORUN/) { <% $next_state %> % } % else { <% $next_state %> % } <% $entry->{'WORKFLOW_USER'} %>
<& /service/open_form.mhtml, 'action' => $context->{menu}->get_root()."/service/workflow/get_workflow_instance_info.html" &> <& /lib/html/hidden.mhtml, 'name' => 'id', 'value' => $id &> <& /lib/html/hidden.mhtml, 'name' => 'format', 'value' => 'png' &> <& /lib/html/input.mhtml, 'type' => 'submit', 'value' => i18nGettext ('I18N_OPENXPKI_HTML_GET_WORKFLOW_INSTANCE_INFO') &> <& /service/close_form.mhtml &>
% }

<%once> use Encode qw(encode decode); use HTML::Entities; use DateTime; use Data::Dumper; $Data::Dumper::Terse = 1; $Data::Dumper::Sortkeys = 1; <%init> if (not defined $msg or not ref $msg or not ref $msg eq "HASH") { if (! defined $type) { # type was not specified, get it from the server my $type_msg = $context->{client}->send_receive_command_msg( 'get_workflow_type_for_id', { 'ID' => $id, }, ); $type = $type_msg->{PARAMS}; } ## ok we have to get the info from the server $msg = $context->{client}->send_receive_command_msg ( "get_workflow_info", { "WORKFLOW" => $type, "ID" => $id } ); } else { ## sometimes we have only the message $id = $msg->{PARAMS}->{WORKFLOW}->{ID} if (! defined $id && exists $msg->{PARAMS} && exists $msg->{PARAMS}->{WORKFLOW} && exists $msg->{PARAMS}->{WORKFLOW}->{ID}); $type = $msg->{PARAMS}->{WORKFLOW}->{TYPE} if (! defined $type && exists $msg->{PARAMS} && exists $msg->{PARAMS}->{WORKFLOW} && exists $msg->{PARAMS}->{WORKFLOW}->{TYPE}); } if (ref $msg eq 'HASH' && exists $msg->{SERVICE_MSG} && $msg->{SERVICE_MSG} eq 'ERROR') { my @errors = $m->comp('/lib/get_deep_error.mhtml', 'msg' => $msg); $m->comp('/service/create_csr/print_errors.mhtml', 'errors' => \@errors); return; } my %untainted = (); my $context_hash = ''; if ($msg->{PARAMS}->{WORKFLOW}->{TYPE} eq 'I18N_OPENXPKI_WF_TYPE_CERTIFICATE_SIGNING_REQUEST') { $context_hash = $m->comp('/service/workflow/context_hash.mhtml', 'context' => $msg->{PARAMS}->{WORKFLOW}->{CONTEXT}, ); } foreach my $param (keys %{ $msg->{PARAMS}->{WORKFLOW}->{CONTEXT} }) { my $value = $msg->{PARAMS}->{WORKFLOW}->{CONTEXT}->{$param}; if ($param eq 'csr_serial' && $value =~ m{\A \d+ \z}xms) { # transform a scalar csr_serial into a one-element array $value = OpenXPKI::Serialization::Simple->new()->serialize([ $value ]); } if ($value =~ /^(ARRAY|HASH)/) { ## serialized stuff my $ser = OpenXPKI::Serialization::Simple->new(); my $ref = $ser->deserialize($value); if ($param eq "cert_info") { ## simple hash $value = ''; foreach my $key (sort keys %{$ref}) { my $key_i18n = $m->scomp('/lib/field_to_i18n.mhtml', 'field' => $key, ); $ref->{$key} =~ encode_entities($ref->{$key}); $ref->{$key} =~ s{\n}{
}xmsg; $value .= ''; } $value .= '
' . $key_i18n . '' . $ref->{$key} . '
'; $untainted{'cert_info'} = 1; } elsif ($param eq 'ticket') { $value = ''; $untainted{'ticket'} = 1; } elsif ($param eq "cert_subject_alt_name") { ## array of arrays $value = ''; foreach my $pair (@{$ref}) { next if (not $pair); ## empty array $value .= encode_entities($pair->[0]) . ': ' . encode_entities($pair->[1]) . '
'; } $untainted{'cert_subject_alt_name'} = 1; } elsif ($param eq "approvals") { $value = ''; if (ref $ref eq 'HASH') { # old style ## hash: user to role foreach my $user (sort keys %{$ref}) { next if (not defined $user); ## empty hash - !??? $value .= encode_entities($user) . '→' . encode_entities($ref->{$user}) . '
'; } } elsif (ref $ref eq 'ARRAY') { # new style for signatures foreach my $approval (@{$ref}) { if (defined $approval->{signature}) { $value .= i18nGettext('I18N_OPENXPKI_SIGNED_APPROVAL') . ':
'; $value .= encode_entities($approval->{signer_subject}) . '→' . encode_entities($approval->{signer_role}) . '
'; $value .= i18nGettext('I18N_OPENXPKI_SIGNER_CERTIFICATE_IDENTIFIER') . ': ' . encode_entities($approval->{signer_identifier}) . '
'; $value .= i18nGettext('I18N_OPENXPKI_SIGNED_TEXT') . ': ' . encode_entities($approval->{plaintext}) . '
'; $value .= i18nGettext('I18N_OPENXPKI_SIGNATURE') . ': ' . encode_entities($approval->{signature}) . '
'; } $value .= encode_entities($approval->{session_user}) . '→' . encode_entities($approval->{session_role}) . '

================================================================
'; } } $untainted{'approvals'} = 1; } elsif ($param eq 'wf_children_instances') { $value = ''; foreach my $instance (@{ $ref }) { $value .= '' . encode_entities(i18nGettext($instance->{TYPE})) . ' #' . encode_entities($instance->{ID}) . '
'; } $untainted{'wf_children_instances'} = 1; } elsif ($param eq 'csr_serial') { $value = ''; foreach my $serial (@{ $ref }) { $value .= $serial . ' (' . i18nGettext('I18N_OPENXPKI_WORKFLOWS') . ''; if ($msg->{PARAMS}->{WORKFLOW}->{STATE} eq 'SUCCESS') { # there should be a certificate for this ID, too $value .= ', ' . i18nGettext('I18N_OPENXPKI_CERTIFICATE') . ''; } $value .= ')
'; } $untainted{'csr_serial'} = 1; } else { my $dump = Dumper($ref); Encode::_utf8_on($dump); $value = $dump; } } elsif ($param eq 'spkac') { for (my $i = int(length ($value) / 64); $i > 0; $i--) { $value = substr ($value, 0, $i*64)."
".substr($value,$i*64); } $value = '
' . $value . '
'; $untainted{'spkac'} = 1; } elsif ($param eq 'notafter' || $param eq 'notbefore') { $value = substr($value, 0, 4) . '-' . substr($value, 4, 2) . '-' . substr($value, 6, 2) . ' ' . substr($value, 8, 2) . ':' . substr($value, 10, 2) . ':' . substr($value, 12, 2) . ' UTC'; } elsif ($param eq 'cert_subject') { # make certificate subject more breakable $value =~ s{,}{, }xmsg; } elsif ($param eq 'cert_identifier' || $param eq 'current_identifier') { $value = '' . encode_entities($value) . ''; $untainted{$param} = 1; } elsif ($param eq 'workflow_parent_id') { $value = '#' . encode_entities($value) . ''; $untainted{$param} = 1; } elsif ($param eq 'invalidity_time') { $value = DateTime->from_epoch( epoch => $value )->strftime('%Y-%m-%d %H:%M UTC'); } elsif ($value =~ m{ \A -----BEGIN }xms || $param eq 'pkcs7_content') { # PKCS 10/7 or key $value = encode_entities($value); $value =~ s{\n}{
}xmsg; $value = '
' . $value . '
'; $untainted{$param} = 1; } $msg->{PARAMS}->{WORKFLOW}->{CONTEXT}->{$param} = $value; } if (not defined $activities) { ## ok we have to get the info from the server ## FIXME: this fails if type and id are undefined, id can ## be extracted from $msg, but what about type? my $hmsg = $context->{client}->send_receive_command_msg ( "get_workflow_activities", { "WORKFLOW" => $type, "ID" => $id } ); $activities = $hmsg->{PARAMS}; } my @history = (); if ($history) { my $msg = $context->{client}->send_receive_command_msg( 'get_workflow_history', { 'ID' => $id, }, ); eval { @history = @{ $msg->{PARAMS} }; }; } my %actions = (); foreach my $key (@{$activities}) { ## I hope that nobody will translate two actions with the same string ## Here are some translation tags for CRR activities (for pot-file) ## I18N_OPENXPKI_WF_ACTION_ADD_MISSING_NODE ## I18N_OPENXPKI_WF_ACTION_APPROVE_CRR ## I18N_OPENXPKI_WF_ACTION_APPROVE_CSR ## I18N_OPENXPKI_WF_ACTION_CANCEL_CRR_APPROVAL ## I18N_OPENXPKI_WF_ACTION_CANCEL_CSR_APPROVAL ## I18N_OPENXPKI_WF_ACTION_CHANGE_CRR_INVALIDITY_TIME ## I18N_OPENXPKI_WF_ACTION_CHANGE_CRR_REASON ## I18N_OPENXPKI_WF_ACTION_CHANGE_CSR_PROFILE ## I18N_OPENXPKI_WF_ACTION_CHANGE_CSR_ROLE ## I18N_OPENXPKI_WF_ACTION_CHANGE_CSR_SUBJECT ## I18N_OPENXPKI_WF_ACTION_CHANGE_CSR_SUBJECT_ALT_NAME ## I18N_OPENXPKI_WF_ACTION_CHANGE_CSR_SUBJECT_STYLE ## I18N_OPENXPKI_WF_ACTION_CHILD_FINISHED_FAILURE ## I18N_OPENXPKI_WF_ACTION_CHILD_FINISHED_SUCCESSFULLY ## I18N_OPENXPKI_WF_ACTION_CONTINUE ## I18N_OPENXPKI_WF_ACTION_CONTINUE_ISSUANCE ## I18N_OPENXPKI_WF_ACTION_CREATE_CRR ## I18N_OPENXPKI_WF_ACTION_CREATE_CSR ## I18N_OPENXPKI_WF_ACTION_CREATE_SERVER_CSR ## I18N_OPENXPKI_WF_ACTION_DETERMINE_ISSUING_CA ## I18N_OPENXPKI_WF_ACTION_DETERMINE_NEXT_CA ## I18N_OPENXPKI_WF_ACTION_DO_NOTHING ## I18N_OPENXPKI_WF_ACTION_DO_NOTHING2 ## I18N_OPENXPKI_WF_ACTION_EXPORT_CRR ## I18N_OPENXPKI_WF_ACTION_EXTRACT_CSR ## I18N_OPENXPKI_WF_ACTION_FAIL_WORKFLOW ## I18N_OPENXPKI_WF_ACTION_FORK_CERT_ISSUANCE_INSTANCE ## I18N_OPENXPKI_WF_ACTION_FORK_CERT_ISSUANCE_INSTANCES ## I18N_OPENXPKI_WF_ACTION_GENERATE_KEY ## I18N_OPENXPKI_WF_ACTION_GENERATE_PKCS10 ## I18N_OPENXPKI_WF_ACTION_GET_CERT_PROFILE ## I18N_OPENXPKI_WF_ACTION_GET_CRL_PROFILE ## I18N_OPENXPKI_WF_ACTION_GET_LDAP_DATA ## I18N_OPENXPKI_WF_ACTION_IMPORT ## I18N_OPENXPKI_WF_ACTION_IMPORT_PUBLIC_DATA ## I18N_OPENXPKI_WF_ACTION_ISSUE_CERTIFICATE ## I18N_OPENXPKI_WF_ACTION_ISSUE_CRL ## I18N_OPENXPKI_WF_ACTION_NOTIFY_PARENT_FAILURE ## I18N_OPENXPKI_WF_ACTION_NOTIFY_PARENT_SUCCESS ## I18N_OPENXPKI_WF_ACTION_NOTIFY_USER_OF_CREATION ## I18N_OPENXPKI_WF_ACTION_NOTIFY_USER_OF_ISSUANCE ## I18N_OPENXPKI_WF_ACTION_NULL ## I18N_OPENXPKI_WF_ACTION_NULL2 ## I18N_OPENXPKI_WF_ACTION_NULL3 ## I18N_OPENXPKI_WF_ACTION_PERSIST_CERTIFICATE ## I18N_OPENXPKI_WF_ACTION_PERSIST_CRR ## I18N_OPENXPKI_WF_ACTION_PERSIST_CSR ## I18N_OPENXPKI_WF_ACTION_PERSIST_CSRS ## I18N_OPENXPKI_WF_ACTION_PUBLIC_CERT_LDAP ## I18N_OPENXPKI_WF_ACTION_PUBLISH_CERTIFICATES ## I18N_OPENXPKI_WF_ACTION_PUBLISH_CRL ## I18N_OPENXPKI_WF_ACTION_REJECT_CRR ## I18N_OPENXPKI_WF_ACTION_REJECT_CSR ## I18N_OPENXPKI_WF_ACTION_REVOKE_CERTIFICATE ## I18N_OPENXPKI_WF_ACTION_SET_CONTEXT_FROM_CSR ## I18N_OPENXPKI_WF_ACTION_SET_CONTEXT_FROM_ORIGINAL_CERT ## I18N_OPENXPKI_WF_ACTION_SET_ERROR_CERT_TEST_FAILED ## I18N_OPENXPKI_WF_ACTION_SET_ERROR_CODE_1 ## I18N_OPENXPKI_WF_ACTION_SET_ERROR_CODE_2 ## I18N_OPENXPKI_WF_ACTION_SET_ERROR_CODE_4 ## I18N_OPENXPKI_WF_ACTION_SET_ERROR_ISSUANCE_FAILED ## I18N_OPENXPKI_WF_ACTION_SET_ERROR_LDAP ## I18N_OPENXPKI_WF_ACTION_SLEEP_FOR_CHILD ## I18N_OPENXPKI_WF_ACTION_SLEEP_FOR_CHILDREN ## I18N_OPENXPKI_WF_ACTION_UNLOCK_CA_KEY ## I18N_OPENXPKI_WF_ACTION_WRITE_CERTIFICATE_TEST_RESULT ## I18N_OPENXPKI_WF_ACTION_WRITE_CERTIFICATE_TO_INSTALL $actions{i18nGettext($key)} = $key; } my %basic_details = ( 'I18N_OPENXPKI_WF_TYPE_CERTIFICATE_SIGNING_REQUEST' => [ qw( cert_subject cert_profile cert_role cert_subject_alt_name cert_info csr_serial wf_children_instances notafter notbefore) ], 'I18N_OPENXPKI_WF_TYPE_CERTIFICATE_ISSUANCE' => [ qw( cert_subject cert_profile cert_role cert_subject_alt_name csr_serial workflow_parent_id ) ], 'I18N_OPENXPKI_WF_TYPE_SMARTCARD_PERSONALIZATION' => [ qw( csr_serial wf_children_instances ) ], 'I18N_OPENXPKI_WF_TYPE_CERTIFICATE_REVOCATION_REQUEST' => [ qw( cert_identifier reason_code invalidity_time comment ) ], 'I18N_OPENXPKI_WF_TYPE_SCEP_REQUEST' => [ qw( cert_subject cert_profile cert_role cert_subject_alt_name current_identifier current_valid_certificates csr_serial wf_children_instances) ], 'I18N_OPENXPKI_WF_TYPE_CERTIFICATE_LDAP_PUBLISHING' => [ qw( workflow_parent_id ) ], );