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