1# Copyright (c) Olaf Gellert <og@pre-secure.de> and
2#               Stephan Martin <sm@sm-zone.net>
3#
4# $Id: X509_infobox.pm,v 1.7 2006/06/28 21:50:42 sm Exp $
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
19
20use strict;
21package GUI::X509_infobox;
22
23use HELPERS;
24use GUI::HELPERS;
25use GUI::WORDS;
26
27use POSIX;
28
29my $version = "0.1";
30my $true = 1;
31my $false = undef;
32
33sub new {
34   my $that = shift;
35   my $self = {};
36
37   my $class = ref($that) || $that;
38
39   $self->{'init'} = shift;
40
41   bless($self, $class);
42
43   $self;
44}
45
46
47sub display {
48  my ($self, $parent, $parsed, $mode, $title) = @_;
49
50  my ($bottombox, $textbox, $lefttable, $righttable, $leftbox, $rightbox,
51        @fields, $scrolled);
52
53  $self->{'root'} = $parent;
54
55  if (defined $self->{'child'}) {
56    $self->{'child'}->destroy();
57    }
58
59  # if title is given create a surrounding frame with the title
60  if (defined $title) {
61     $self->{'child'}= Gtk2::Frame->new($title);
62     $self->{'x509textbox'}= Gtk2::VBox->new(0,0);
63     $self->{'child'}->add($self->{'x509textbox'});
64  }
65  # otherwise we create the VBox directly inside the root widget
66  else {
67     $self->{'child'} = Gtk2::VBox->new(0,0);
68     $self->{'x509textbox'} = $self->{'child'};
69  }
70
71  # and pack it there
72  $self->{'root'}->pack_start($self->{'child'}, 1, 1, 0);
73
74   if (($mode eq 'cert') || ($mode eq 'cacert')) {
75      # fingerprint in the top of certtextbox
76      if(defined($self->{'certfingerprintmd5'})) {
77         $self->{'certfingerprintmd5'}->destroy();
78      }
79      $self->{'certfingerprintmd5'} = GUI::HELPERS::create_label(
80            _("Fingerprint (MD5)").": ".$parsed->{'FINGERPRINTMD5'},
81            'center', 0, 0);
82      $self->{'x509textbox'}->pack_start( $self->{'certfingerprintmd5'},
83            0, 0, 0);
84
85      if(defined($self->{'certfingerprintsha1'})) {
86         $self->{'certfingerprintsha1'}->destroy();
87      }
88      $self->{'certfingerprintsha1'} = GUI::HELPERS::create_label(
89            _("Fingerprint (SHA1)").": ".$parsed->{'FINGERPRINTSHA1'},
90            'center', 0, 0);
91      $self->{'x509textbox'}->pack_start($self->{'certfingerprintsha1'},
92            0, 0, 0);
93   }
94
95   if (($mode eq 'cert') || ($mode eq 'cacert')) {
96      $bottombox  = 'certbottombox';
97      $textbox    = 'x509textbox';
98      $lefttable  = 'certlefttable';
99      $leftbox    = 'certleftbox';
100      $righttable = 'certrighttable';
101      $rightbox   = 'certrightbox';
102   }else{
103      $bottombox  = 'reqbottombox';
104      $textbox    = 'x509textbox';
105      $lefttable  = 'reqlefttable';
106      $leftbox    = 'reqleftbox';
107      $righttable = 'reqrighttable';
108      $rightbox   = 'reqrightbox';
109   }
110
111   # hbox in the bottom
112   if(defined($self->{$bottombox})) {
113      $self->{$bottombox}->destroy();
114   }
115   $self->{$bottombox} = Gtk2::HBox->new(1, 0);
116   $self->{$textbox}->pack_start($self->{$bottombox}, 1, 1, 5);
117
118   # vbox in the bottom/left
119   if(defined($self->{$lefttable})) {
120      $self->{$lefttable}->destroy();
121   }
122   @fields = qw( CN EMAIL O OU L ST C);
123   $self->{$lefttable} = _create_detail_table(\@fields, $parsed);
124
125   # the only widget i know to set shadow type :-(
126   $scrolled = Gtk2::ScrolledWindow->new();
127   $scrolled->set_shadow_type('etched-in');
128   $scrolled->set_policy('never', 'never');
129
130   $self->{$leftbox} = Gtk2::VBox->new(0, 0);
131   $self->{$bottombox}->pack_start($self->{$leftbox}, 1, 1, 0);
132
133   $self->{$leftbox}->pack_start($scrolled, 1, 1, 0);
134   $scrolled->add($self->{$lefttable});
135
136   # vbox in the bottom/right
137   if(defined($self->{$righttable})) {
138      $self->{$righttable}->destroy();
139   }
140   if ($mode eq "cacert") {
141     @fields = qw(SERIAL NOTBEFORE NOTAFTER KEYSIZE PK_ALGORITHM SIG_ALGORITHM
142        TYPE);
143   } else {
144     @fields = qw(STATUS SERIAL NOTBEFORE NOTAFTER KEYSIZE PK_ALGORITHM
145        SIG_ALGORITHM TYPE);
146   }
147
148   $self->{$righttable} = _create_detail_table(\@fields, $parsed);
149
150   $scrolled = Gtk2::ScrolledWindow->new();
151   $scrolled->set_shadow_type('etched-in');
152   $scrolled->set_policy('never', 'never');
153
154   $self->{$rightbox} = Gtk2::VBox->new(0, 0);
155   $self->{$bottombox}->pack_start($self->{$rightbox}, 1, 1, 0);
156
157   $self->{$rightbox}->pack_start($scrolled, 1, 1, 0);
158   $scrolled->add($self->{$righttable});
159
160   $self->{$textbox}->show_all();
161
162   $parent->show_all();
163}
164
165sub hide {
166  my $self = shift;
167
168  if (defined $self->{'child'}) {
169    $self->{'child'}->destroy();
170    undef $self->{'child'};
171    }
172}
173
174#
175# create standard table with details (cert/req)
176#
177sub _create_detail_table {
178   my ($fields, $parsed) = @_;
179
180   my ($list, $store, $rows, $words, @l, $iter, $column, $renderer);
181
182   $words = GUI::WORDS->new();
183
184   $store = Gtk2::ListStore->new('Glib::String', 'Glib::String');
185   $list  = Gtk2::TreeView->new_with_model($store);
186   $list->set_headers_visible(0);
187   $list->get_selection->set_mode('none');
188
189   $renderer = Gtk2::CellRendererText->new();
190   $column = Gtk2::TreeViewColumn->new_with_attributes(
191         '', $renderer, 'text' => 0);
192   $list->append_column($column);
193
194   $renderer = Gtk2::CellRendererText->new();
195   $column = Gtk2::TreeViewColumn->new_with_attributes(
196         '', $renderer, 'text' => 1);
197   $list->append_column($column);
198
199
200   foreach my $f (@{$fields}) {
201      if(defined($parsed->{$f})){
202         if(ref($parsed->{$f})) {
203            foreach(@{$parsed->{$f}}) {
204               $iter = $store->append();
205               $store->set($iter, 0 => $words->{$f}, 1 => $_);
206               # print STDERR "DEBUG: add line: @l\n";
207
208            }
209         }else{
210            # print STDERR "DEBUG: add line: @l\n";
211            $iter = $store->append();
212            $store->set($iter, 0 => $words->{$f}, 1 => $parsed->{$f});
213         }
214      }
215   }
216
217   return($list);
218}
219
220
2211;
222
223
224__END__
225
226=head1 NAME
227
228GUI::X509_infobox - show X.509 certificates and requests in a Gtk2::VBox
229
230=head1 SYNOPSIS
231
232    use X509_infobox;
233
234    $infobox=X509_infobox->new();
235    $infobox->update($parent,$parsed,$mode,$title);
236    $infobox->update($parent,$parsed,$mode);
237    $infobox->hide();
238
239=head1 DESCRIPTION
240
241This displays the information of an X.509v3 certificate or
242certification request (CSR) inside a given Gtk2::VBox.
243
244Creation of an X509_infobox is done by calling B<new()>,
245no arguments are required.
246
247The infobox is shown when inserted into an already
248existing Gtk2::VBox using the method B<update()>. Arguments
249to update are:
250
251=over 1
252
253=item $parent:
254
255the existing Gtk2::VBox inside which the info will be
256displayed.
257
258=item $parsed:
259
260a structure returned by OpenSSL::parsecert() or OpenSSL::parsecrl()
261containing the required information.
262
263=item $mode:
264
265what type of information is to be displayed. Valid modes
266are 'req' (certification request), 'cert' (certificate), 'key' or 'cacert'
267(same as certificate but without displaying the validity information
268of the cert because this cannot be decided on from the view of the
269actual CA).
270
271=item $title:
272
273if specified, a surrounding frame with the given title
274is drawn.
275
276=back
277
278An existing infobox is destroyed by calling B<hide()>.
279
280=cut
281