~ubuntu-branches/ubuntu/vivid/topal/vivid

« back to all changes in this revision

Viewing changes to keys.adb

  • Committer: Bazaar Package Importer
  • Author(s): Phil Brooke
  • Date: 2008-07-18 07:57:38 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 dapper)
  • Revision ID: james.westby@ubuntu.com-20080718075738-1jbtf92kurbkezdz
Tags: 62-1
* New upstream release.  This includes the necessary upstream work
  to make it work properly again.
* Move from contrib to main (Alpine is in main).
* Fix standards-version to 3.8.0.
* Update gnat dependency and add more architectures.
* Update debian/compat.
* Update description.
* Update copyright file.
* Update depends/recommends/suggests.
* Patches are installed in their own directory.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
--
2
 
--
3
 
--
4
 
--
 
1
-- Topal: GPG/GnuPG and Alpine/Pine integration
 
2
-- Copyright (C) 2001--2008  Phillip J. Brooke
 
3
--
 
4
-- This program is free software: you can redistribute it and/or modify
 
5
-- it under the terms of the GNU General Public License version 3 as
 
6
-- published by the Free Software Foundation.
 
7
--
 
8
-- This program is distributed in the hope that it will be useful,
 
9
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
-- GNU General Public License for more details.
 
12
--
 
13
-- You should have received a copy of the GNU General Public License
 
14
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
5
15
 
6
16
with Ada.IO_Exceptions;
7
17
with Ada.Strings.Fixed;
 
18
with Ada.Strings.Maps;
 
19
with Ada.Strings.Maps.Constants;
8
20
with Ada.Strings.Unbounded;
9
21
with Ada.Text_IO;
10
22
with Expanding_Array;
30
29
package body Keys is
31
30
 
32
31
   Key_List_Initial_Size : constant Positive := 200;
 
32
   Key_Head_Length       : constant Positive := 72;
 
33
 
 
34
   subtype Key_Head is String(1..Key_Head_Length);
 
35
   package Key_Head_Array_Package
 
36
   is new Expanding_Array (Item => Key_Head);
 
37
   package KHA renames Key_Head_Array_Package;
 
38
 
 
39
   subtype Key_Head_Array is Key_Head_Array_Package.Big_Array;
33
40
 
34
41
   type Menu_Array_Ptr is access all Keylist_Menus.MNA;
35
42
 
 
43
   function Match_PR (KP : Key_Properties;
 
44
                      KR : Key_Roles) return Boolean is
 
45
   begin
 
46
      case KR is
 
47
         when Any       => return True;
 
48
         when Encrypter => return KP(Encrypter);
 
49
         when Signer    => return KP(Signer);
 
50
         when Both      => return KP(Encrypter) and KP(Signer);
 
51
      end case;
 
52
   end Match_PR;
 
53
 
 
54
   -- Is the key usable?
 
55
   function Usable (KP : Key_Properties) return Boolean is
 
56
   begin
 
57
      return not (KP(Invalid) or KP(Disabled) or KP(Revoked) or KP(Expired));
 
58
   end Usable;
 
59
 
 
60
   -- Given a line from Listkey, return a processed version.
 
61
   procedure Process_Key (L  : in     String;
 
62
                          P  :    out UBS;
 
63
                          KP :    out Key_Properties) is
 
64
      LS : UBS_Array := Split_GPG_Colons(L);
 
65
      use Ada.Strings.Fixed;
 
66
   begin
 
67
      P := NullUBS;
 
68
      KP := Key_Properties'(others => False);
 
69
      if LS'Length >= 1
 
70
        and then ToStr(LS(LS'First)) = "pub" then
 
71
         if LS'Length >= 2 then
 
72
            declare
 
73
               S : constant String := ToStr(LS(LS'First+1));
 
74
            begin
 
75
               if Count(S, "i") = 1 then
 
76
                  KP(Invalid) := True;
 
77
               end if;
 
78
               if Count(S, "d") = 1 then
 
79
                  KP(Disabled) := True;
 
80
               end if;
 
81
               if Count(S, "r") = 1 then
 
82
                  KP(Revoked) := True;
 
83
               end if;
 
84
               if Count(S, "e") = 1 then
 
85
                  KP(Expired) := True;
 
86
               end if;
 
87
            end;
 
88
         end if;
 
89
         if LS'Length >= 12 then
 
90
            declare
 
91
               S : constant String := ToStr(LS(LS'First+11));
 
92
            begin
 
93
               if Count(S, "D") = 1 then
 
94
                  KP(Disabled) := True;
 
95
               end if;
 
96
               if Count(S, "E") = 1 then
 
97
                  KP(Encrypter) := True;
 
98
               end if;
 
99
               if Count(S, "S") = 1 then
 
100
                  KP(Signer) := True;
 
101
               end if;
 
102
            end;
 
103
         end if;
 
104
         declare
 
105
            use type UBS;
 
106
         begin
 
107
            if KP(Invalid) then
 
108
               P := P & ToUBS("[Invalid]");
 
109
            end if;
 
110
            if KP(Disabled) then
 
111
               P := P & ToUBS("[Disabled]");
 
112
            end if;
 
113
            if KP(Revoked) then
 
114
               P := P & ToUBS("[Revoked]");
 
115
            end if;
 
116
            if KP(Expired) then
 
117
               P := P & ToUBS("[Expired]");
 
118
            end if;
 
119
            if LS'Length >= 5 then
 
120
               -- Append the last eight characters of the key ID.
 
121
               declare
 
122
                  KS : constant String := ToStr(LS(LS'First+4));
 
123
                  F  : Integer;
 
124
               begin
 
125
                  F := KS'Last - 7;
 
126
                  if F < KS'First then
 
127
                     F := KS'First;
 
128
                  end if;
 
129
                  P := P & KS(F..KS'Last);
 
130
               end;
 
131
            end if;
 
132
            if LS'Length >= 6 then
 
133
               -- Append the start date.
 
134
               P := P & ToUBS(" ") & LS(LS'First+5);
 
135
            end if;
 
136
            if LS'Length >= 10 then
 
137
               -- Append the user name.
 
138
               P := P & ToUBS(" ") & LS(LS'First+9);
 
139
            end if;
 
140
         end;
 
141
      else
 
142
         P := ToUBS("??:" & L);
 
143
      end if;
 
144
   exception
 
145
      when others =>
 
146
         Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
 
147
                              "Exception raised in Keys.Process_Key");
 
148
         raise;
 
149
   end Process_Key;
 
150
 
36
151
   -- Add a key to the list....
37
152
   procedure Add_Key (Key  : in     UBS;
38
 
                      List : in out Key_List) is
39
 
      Match : Boolean := False;
 
153
                      List : in out Key_List;
 
154
                      Role : in     Key_Roles) is
 
155
      Match        : Boolean := False;
 
156
      Key_Filename : constant String := Temp_File_Name("addkey");
 
157
      P            : UBS;
 
158
      KP           : Key_Properties;
 
159
      File_Handle  : Ada.Text_IO.File_Type;
 
160
      First_Line   : UBS;
40
161
   begin
41
 
      Debug("+Add_Key");
42
 
      -- Is it a duplicate?
43
 
      Debug("Add_Key: Checking for duplicates");
 
162
      Debug("+Add_Key: `" & ToStr(Key) & "'");
 
163
      -- Puke if this is not a fingerprint....
44
164
      declare
45
 
         use type UBS;
 
165
         KS : constant String := ToStr(Key);
 
166
         use Ada.Strings.Maps;
46
167
      begin
47
 
         Debug("Add_Key: Approaching duplicates loop");
48
 
         for I in 1..List.Count loop
49
 
            Debug("Add_Key: In duplicates loop");
50
 
            Match := Match or Key = UAP.Value(List.KA, I);
 
168
         for I in KS'Range loop
 
169
            if not Is_In(KS(I),
 
170
                         Ada.Strings.Maps.Constants.Hexadecimal_Digit_Set) then
 
171
               Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
 
172
                                    "Expected fingerprint, but working on `"&
 
173
                                    KS &"'");
 
174
               raise Fingerprint_Expected;
 
175
            end if;
51
176
         end loop;
52
177
      end;
53
 
      if not Match then
54
 
         -- Add the key.
55
 
         Debug("Add_Key: Adding a key");
56
 
         List.Count := List.Count + 1;
57
 
         UAP.Set(List.KA, List.Count, Key);
58
 
         Debug("Add_Key: Done adding a key");
 
178
      -- Is this key usable?
 
179
      Externals.GPG.Listkey(Key => ToStr(Key), Target => Key_Filename);
 
180
      Ada.Text_IO.Open(File => File_Handle,
 
181
                       Mode => Ada.Text_IO.In_File,
 
182
                       Name => Key_Filename);
 
183
      First_Line := Unbounded_Get_Line(File_Handle);
 
184
      Ada.Text_IO.Close(File_Handle);
 
185
      Process_Key(ToStr(First_Line), P, KP);
 
186
      if not Usable(KP) then
 
187
         -- It's not usable!
 
188
         Ada.Text_IO.Put_Line("Key " & ToStr(Key) & " is not usable!");
 
189
      elsif not Match_PR(KP, Role) then
 
190
         -- Doesn't match role.
 
191
         Ada.Text_IO.Put_Line("Key " & ToStr(Key) & " has wrong role!");
 
192
      else
 
193
         -- Is it a duplicate?
 
194
         Debug("Add_Key: Checking for duplicates");
 
195
         declare
 
196
            use type UBS;
 
197
         begin
 
198
            Debug("Add_Key: Approaching duplicates loop");
 
199
            for I in 1..List.Count loop
 
200
               Debug("Add_Key: In duplicates loop");
 
201
               Match := Match or Key = UAP.Value(List.KA, I);
 
202
            end loop;
 
203
         end;
 
204
         if not Match then
 
205
            -- Add the key.
 
206
            Debug("Add_Key: Adding a key");
 
207
            List.Count := List.Count + 1;
 
208
            UAP.Set(List.KA, List.Count, Key);
 
209
            Debug("Add_Key: Done adding a key");
 
210
         end if;
59
211
      end if;
60
212
   exception
61
213
      when others =>
66
218
 
67
219
   -- Remove a key.  We then shuffle the array down.
68
220
   -- It will only remove the last key if there are multiple instances.
69
 
   procedure Remove_Key (Key  : in     UBS;
70
 
                         List : in out Key_List) is
71
 
      Key_Num : Integer;
72
 
      Key_Found : Boolean := False;
73
 
      use type UBS;
 
221
   -- The nastiness here is that we might be working with short
 
222
   --  fingerprints.  So choose the right hand end of the fingerprint.
 
223
   procedure Remove_Key (Key                  : in     UBS;
 
224
                         List                 : in out Key_List;
 
225
                         Exception_If_Missing : in     Boolean := False) is
 
226
      Key_Num    : Integer;
 
227
      Key_Found  : Boolean          := False;
 
228
      KS         : constant String  := ToStr(Key);
 
229
      Key_Length : constant Natural := KS'Length;
74
230
   begin
75
231
      for I in 1..List.Count loop
76
 
         if Key = UAP.Value(List.KA, I) then
77
 
            Key_Found := True;
78
 
            Key_Num := I;
79
 
         end if;
 
232
         declare
 
233
            -- Get this string...
 
234
            TK       : constant String := ToStr(UAP.Value(List.KA, I));
 
235
            TK_Start : Integer;
 
236
         begin
 
237
            -- Is TK longer?
 
238
            TK_Start := TK'First;
 
239
            if TK'Length > Key_Length then
 
240
               -- Advance TK_Start so that we've got matching lengths.
 
241
               TK_Start := TK'Last - Key_Length + 1;
 
242
            end if;
 
243
            if KS = TK(TK_Start..TK'Last) then
 
244
               Key_Found := True;
 
245
               Key_Num := I;
 
246
            end if;
 
247
         end;
80
248
      end loop;
81
249
      if Key_Found then
82
250
         -- Shuffle the array over it.
86
254
         -- Reduce the number of keys.
87
255
         List.Count := List.Count - 1;
88
256
      else
89
 
         raise Key_Not_Found;
 
257
         if Exception_If_Missing then
 
258
            raise Key_Not_Found;
 
259
         end if;
90
260
      end if;
91
261
   exception
92
262
      when others =>
114
284
   -- Get key fingerprint(s) for a key.  Add them.
115
285
   procedure Add_Keys_By_Fingerprint (Key_In : in     UBS;
116
286
                                      List   : in out Key_List;
 
287
                                      Role   : in     Key_Roles;
117
288
                                      Found  :    out Boolean) is
118
 
      K          : String := ToStr(Key_In);
119
 
      Tempfile   : String := Temp_File_Name("findkey-akbf");
 
289
      K          : constant String := ToStr(Key_In);
 
290
      Tempfile   : constant String := Temp_File_Name("findkey-akbf");
120
291
      TFH        : Ada.Text_IO.File_Type;
121
292
      L          : UBS;
122
293
      Match      : Boolean := False;
123
294
   begin
124
295
      Debug("Add_Keys_By_Fingerprint (A): starting...");
125
296
      -- First, try finding some keys for this Key_In.
126
 
      GPG.Findkey(Key    => K,
 
297
      Externals.GPG.Findkey(Key    => K,
127
298
                  Target => Tempfile);
128
 
      Debug("Add_Keys_By_Fingerprint (A): GPG.Findkey returned okay");
 
299
      Debug("Add_Keys_By_Fingerprint (A): Externals.GPG.Findkey returned okay");
129
300
      -- Now, open the file, and read in each line as a key for Add_Key.
130
301
      Ada.Text_IO.Open(File => TFH,
131
302
                       Mode => Ada.Text_IO.In_File,
136
307
         begin
137
308
            L := Unbounded_Get_Line(TFH);
138
309
            Debug("Add_Keys_By_Fingerprint: Adding " & ToStr(L));
139
 
            Add_Key(L, List);
 
310
            Add_Key(L, List, Role);
140
311
            Match := True;
141
312
         exception
142
313
            when Ada.IO_Exceptions.End_Error =>
153
324
   end Add_Keys_By_Fingerprint;
154
325
 
155
326
   procedure Add_Keys_By_Fingerprint (Key_In : in     UBS;
156
 
                                      List   : in out Key_List) is
 
327
                                      List   : in out Key_List;
 
328
                                      Role   : in     Key_Roles) is
157
329
      Found : Boolean;
158
330
   begin
159
 
      Add_Keys_By_Fingerprint(Key_In, List, Found);
 
331
      Add_Keys_By_Fingerprint(Key_In, List, Role, Found);
160
332
   exception
161
333
      when others =>
162
334
         Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
166
338
 
167
339
   -- Add the secret keys to this key list.
168
340
   procedure Add_Secret_Keys (Key_In : in     UBS;
169
 
                              List   : in out Key_List) is
170
 
      K          : String := ToStr(Key_In);
171
 
      Tempfile   : String := Temp_File_Name("findkey-ask");
 
341
                              List   : in out Key_List;
 
342
                              Role   : in     Key_Roles) is
 
343
      K          : constant String := ToStr(Key_In);
 
344
      Tempfile   : constant String := Temp_File_Name("findkey-ask");
172
345
      TFH        : Ada.Text_IO.File_Type;
173
346
      L          : UBS;
174
 
      Match      : Boolean := False;
175
347
   begin
176
348
      -- First, try finding some _secret_ keys for this Key_In.
177
 
      GPG.Findkey_Secret(Key    => K,
 
349
      Externals.GPG.Findkey_Secret(Key    => K,
178
350
                         Target => Tempfile);
179
351
      -- Now, open the file, and read in each line as a key for
180
352
      -- Add_Keys_By_Fingerprint (so we don't need to go hunting for the
187
359
         begin
188
360
            L := Unbounded_Get_Line(TFH);
189
361
            Debug("Add_Keys_By_Fingerprint: Adding " & ToStr(L));
190
 
            Add_Keys_By_Fingerprint(L, List);
191
 
            Match := True;
 
362
            Add_Keys_By_Fingerprint(L, List, Role);
192
363
         exception
193
364
            when Ada.IO_Exceptions.End_Error =>
194
365
               exit Fingerprint_Loop;
202
373
         raise;
203
374
   end Add_Secret_Keys;
204
375
 
 
376
   procedure Generate_Key_List (List      : in out Key_List;
 
377
                                Key_Heads : in out Key_Head_Array;
 
378
                                Key_Menu  : in out Menu_Array_Ptr) is
 
379
      C : Natural := 0;
 
380
   begin
 
381
      Debug("+Generate_Key_List");
 
382
      -- First, we generate a current list of info files for the keys.
 
383
      for I in 1..List.Count loop
 
384
         declare
 
385
            Key_File_Name : constant String
 
386
              := Temp_File_Name("key"
 
387
                                & Trim_Leading_Spaces(Integer'Image(I)));
 
388
         begin
 
389
            Externals.GPG.Listkey(Key    => ToStr(UAP.Value(List.KA, I)),
 
390
                        Target => Key_File_Name);
 
391
            -- Now, dump into our `head' array the first line of each.
 
392
            declare
 
393
               File_Handle    : Ada.Text_IO.File_Type;
 
394
               First_Line, P  : UBS;
 
395
               KP             : Key_Properties;
 
396
            begin
 
397
               Ada.Text_IO.Open(File => File_Handle,
 
398
                                Mode => Ada.Text_IO.In_File,
 
399
                                Name => Key_File_Name);
 
400
               First_Line := Unbounded_Get_Line(File_Handle);
 
401
               Ada.Text_IO.Close(File_Handle);
 
402
               Process_Key(ToStr(First_Line), P, KP);
 
403
--               if Usable(KP) then
 
404
                  C := C + 1;
 
405
                  declare
 
406
                     FL  : constant String := ToStr(P);
 
407
                     use Ada.Strings.Fixed;
 
408
                  begin
 
409
                     if FL'Length >= Key_Head_Length then
 
410
                        KHA.Set(Key_Heads, I, FL(FL'First..
 
411
                                                 FL'First+Key_Head_Length-1));
 
412
                     else
 
413
                        KHA.Set(Key_Heads, I, FL
 
414
                                & (Key_Head_Length - FL'Length) * ' ');
 
415
                     end if;
 
416
                  end;
 
417
--               end if;
 
418
            end;
 
419
         end;
 
420
      end loop;
 
421
      -- Now, create a menu with those key_heads.
 
422
      Key_Menu := new Keylist_Menus.MNA(1..C);
 
423
      for I in 1..C loop
 
424
         Key_Menu(I) := ToUBS(KHA.Value(Key_Heads, I));
 
425
      end loop;
 
426
      Debug("-Generate_Key_List");
 
427
   exception
 
428
      when others =>
 
429
         Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
 
430
                              "Exception raised in Keys.Generate_Key_List");
 
431
         raise;
 
432
   end Generate_Key_List;
 
433
 
205
434
   -- List the keys and edit them as appropriate (include removing a key
206
435
   -- from that list, and adding one from the keyring.
207
436
   procedure List_Keys (List : in out Key_List) is
208
 
      Key_Head_Length : constant Positive := 65;
209
 
      subtype Key_Head is String(1..Key_Head_Length);
210
 
      package Key_Head_Array_Package
211
 
      is new Expanding_Array (Item => Key_Head);
212
 
      package KHA renames Key_Head_Array_Package;
213
 
 
214
 
      subtype Key_Head_Array is Key_Head_Array_Package.Big_Array;
215
 
 
216
 
      Key_Heads : Key_Head_Array;
217
 
 
218
 
      Key_Menu : Menu_Array_Ptr;
219
 
 
220
 
      procedure Generate_Key_List is
221
 
      begin
222
 
         Debug("+Generate_Key_List");
223
 
         -- First, we generate a current list of info files for the keys.
224
 
         for I in 1..List.Count loop
225
 
            declare
226
 
               Key_File_Name : String
227
 
                 := Temp_File_Name("key"
228
 
                                   & Trim_Leading_Spaces(Integer'Image(I)));
229
 
            begin
230
 
               GPG.Listkey(Key    => ToStr(UAP.Value(List.KA, I)),
231
 
                           Target => Key_File_Name);
232
 
               -- Now, dump into our `head' array the first line of each.
233
 
               declare
234
 
                  File_Handle : Ada.Text_IO.File_Type;
235
 
                  First_Line  : UBS;
236
 
               begin
237
 
                  Ada.Text_IO.Open(File => File_Handle,
238
 
                                   Mode => Ada.Text_IO.In_File,
239
 
                                   Name => Key_File_Name);
240
 
                  First_Line := Unbounded_Get_Line(File_Handle);
241
 
                  Ada.Text_IO.Close(File_Handle);
242
 
                  declare
243
 
                     FL  : String := ToStr(First_Line);
244
 
                     use Ada.Strings.Fixed;
245
 
                  begin
246
 
                     if FL'Length >= Key_Head_Length then
247
 
                        KHA.Set(Key_Heads, I, FL(FL'First..
248
 
                                             FL'First+Key_Head_Length-1));
249
 
                     else
250
 
                        KHA.Set(Key_Heads, I, FL
251
 
                            & (Key_Head_Length - FL'Length) * ' ');
252
 
                     end if;
253
 
                  end;
254
 
               end;
255
 
            end;
256
 
         end loop;
257
 
         -- Now, create a menu with those key_heads.
258
 
         Key_Menu := new Keylist_Menus.MNA(1..List.Count);
259
 
         for I in 1..List.Count loop
260
 
            Key_Menu(I) := ToUBS("Details: " & KHA.Value(Key_Heads, I));
261
 
         end loop;
262
 
         Debug("-Generate_Key_List");
263
 
      exception
264
 
         when others =>
265
 
            Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
266
 
                                 "Exception raised in Keys.List_Keys.Generate_Key_List");
267
 
            raise;
268
 
      end Generate_Key_List;
269
 
 
 
437
      Key_Heads    : Key_Head_Array;
 
438
      Key_Menu     : Menu_Array_Ptr;
270
439
      Selection    : Keylist_Menus.CLM_Return;
271
440
      Selected     : Integer;
272
441
      SK_Selection : Specific_Key_Index;
273
442
   begin
274
443
      Debug("+List_Keys");
275
444
      KHA.Create(Key_Heads, Key_List_Initial_Size);
276
 
      Generate_Key_List;
 
445
      Generate_Key_List(List, Key_Heads, Key_Menu);
277
446
  List_Keys_Loop:
278
447
      loop
 
448
         Ada.Text_IO.New_Line(5);
 
449
         Ada.Text_IO.Put_Line("** Key list menu:");
 
450
         Ada.Text_IO.Put_Line(Integer'Image(Keys.Count(List))
 
451
                         & " key(s) in key list      ");
279
452
         Selection := Keylist_Menu(Key_Menu.all);
280
453
         if not Selection.Is_Num then
281
454
            case Selection.I is
290
463
                     Put_Line("Main key ring access:");
291
464
                     New_Key
292
465
                       := ToUBS(Readline.Get_String("Type GPG search pattern: "));
293
 
                     Add_Keys_By_Fingerprint(New_Key, List);
294
 
                     Generate_Key_List;
 
466
                     Add_Keys_By_Fingerprint(New_Key, List, Encrypter);
 
467
                     Generate_Key_List(List, Key_Heads, Key_Menu);
295
468
                  end;
296
469
               when AddSearch => -- Do a search, then select a key.
297
470
                  declare
302
475
                  begin
303
476
                     Empty_Keylist(Search_List);
304
477
                     Pattern := ToUBS(Readline.Get_String("Type GPG search pattern: "));
305
 
                     Add_Keys_By_Fingerprint(Pattern, Search_List);
 
478
                     Add_Keys_By_Fingerprint(Pattern, Search_List, Encrypter);
306
479
                     Select_Key_From_List(Search_List, The_Key, Aborted);
307
480
                     if not Aborted then
308
 
                        Add_Key(The_Key, List);
309
 
                        Generate_Key_List;
 
481
                        Add_Key(The_Key, List, Encrypter);
 
482
                        Generate_Key_List(List, Key_Heads, Key_Menu);
310
483
                     end if;
311
484
                  end;
312
485
            end case;
315
488
            Selected := Selection.N;
316
489
        Specific_Key_Loop:
317
490
            loop
 
491
               Ada.Text_IO.New_Line(5);
 
492
               Ada.Text_IO.Put_Line("** Examining key currently in key list:");
318
493
               SK_Selection := Specific_Key_Menu1("Key: "
319
494
                                                  & ToStr(Key_Menu(Selected))
320
495
                                                  & NL
326
501
                  when Done =>
327
502
                     exit Specific_Key_Loop;
328
503
                  when Display =>
329
 
                     GPG.Viewkey(ToStr(UAP.Value(List.KA, Selected)));
 
504
                     Externals.GPG.Viewkey(ToStr(UAP.Value(List.KA, Selected)));
330
505
                  when DisplayVerbose =>
331
 
                     GPG.Viewkey(ToStr(UAP.Value(List.KA, Selected)),
 
506
                     Externals.GPG.Viewkey(ToStr(UAP.Value(List.KA, Selected)),
332
507
                                 Verbose => True);
333
508
                  when Remove =>
334
509
                     Remove_Key(UAP.Value(List.KA, Selected),
335
510
                                List);
336
 
                     Generate_Key_List;
 
511
                     Generate_Key_List(List, Key_Heads, Key_Menu);
337
512
                     exit Specific_Key_Loop;
338
513
                  when SSelect =>
339
514
                     Error("Menu should not have allowed SSelect here");
354
529
   procedure Select_Key_From_List (List            : in out Key_List;
355
530
                                   The_Fingerprint :    out UBS;
356
531
                                   Aborted         :    out Boolean) is
357
 
      Key_Head_Length : constant Positive := 65;
358
 
      subtype Key_Head is String(1..Key_Head_Length);
359
 
      package Key_Head_Array_Package
360
 
      is new Expanding_Array (Item => Key_Head);
361
 
      package KHA renames Key_Head_Array_Package;
362
 
 
363
 
      subtype Key_Head_Array is Key_Head_Array_Package.Big_Array;
364
 
 
365
 
      Key_Heads : Key_Head_Array;
366
 
 
367
 
      Key_Menu : Menu_Array_Ptr;
368
 
 
369
 
      procedure Generate_Key_List is
370
 
      begin
371
 
         Debug("+Generate_Key_List");
372
 
         -- First, we generate a current list of info files for the keys.
373
 
         for I in 1..List.Count loop
374
 
            declare
375
 
               Key_File_Name : String
376
 
                 := Temp_File_Name("key"
377
 
                                   & Trim_Leading_Spaces(Integer'Image(I)));
378
 
            begin
379
 
               GPG.Listkey(Key    => ToStr(UAP.Value(List.KA, I)),
380
 
                           Target => Key_File_Name);
381
 
               -- Now, dump into our `head' array the first line of each.
382
 
               declare
383
 
                  File_Handle : Ada.Text_IO.File_Type;
384
 
                  First_Line  : UBS;
385
 
               begin
386
 
                  Ada.Text_IO.Open(File => File_Handle,
387
 
                                   Mode => Ada.Text_IO.In_File,
388
 
                                   Name => Key_File_Name);
389
 
                  First_Line := Unbounded_Get_Line(File_Handle);
390
 
                  Ada.Text_IO.Close(File_Handle);
391
 
                  declare
392
 
                     FL  : String := ToStr(First_Line);
393
 
                     use Ada.Strings.Fixed;
394
 
                  begin
395
 
                     if FL'Length >= Key_Head_Length then
396
 
                        KHA.Set(Key_Heads, I, FL(FL'First..
397
 
                                             FL'First+Key_Head_Length-1));
398
 
                     else
399
 
                        KHA.Set(Key_Heads, I, FL
400
 
                            & (Key_Head_Length - FL'Length) * ' ');
401
 
                     end if;
402
 
                  end;
403
 
               end;
404
 
            end;
405
 
         end loop;
406
 
         -- Now, create a menu with those key_heads.
407
 
         Key_Menu := new Keylist_Menus.MNA(1..List.Count);
408
 
         for I in 1..List.Count loop
409
 
            Key_Menu(I) := ToUBS("Details: " & KHA.Value(Key_Heads, I));
410
 
         end loop;
411
 
         Debug("-Generate_Key_List");
412
 
      exception
413
 
         when others =>
414
 
            Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
415
 
                                 "Exception raised in Keys.Select_Key_From_List.Generate_Key_List");
416
 
            raise;
417
 
      end Generate_Key_List;
418
 
 
 
532
      Key_Heads        : Key_Head_Array;
 
533
      Key_Menu         : Menu_Array_Ptr;
419
534
      Selection        : Keylist_Menus.CLM_Return;
420
535
      Selected         : Integer;
421
536
      SK_Selection     : Specific_Key_Index;
424
539
   begin
425
540
      Debug("+List_Keys");
426
541
      KHA.Create(Key_Heads, Key_List_Initial_Size);
427
 
      Generate_Key_List;
 
542
      Generate_Key_List(List, Key_Heads, Key_Menu);
428
543
  List_Keys_Loop:
429
544
      loop
430
545
         Selection := Keylist_Menu2(Key_Menu.all);
431
 
         if (not Selection.Is_Num) then
 
546
         if not Selection.Is_Num then
432
547
            case Selection.I is
433
548
               when Done =>
434
549
                  Abort_Real := True;
443
558
            Selected := Selection.N;
444
559
        Specific_Key_Loop:
445
560
            loop
 
561
               Ada.Text_IO.New_Line(5);
 
562
               Ada.Text_IO.Put_Line("** Examining key found in search results:");
446
563
               SK_Selection := Specific_Key_Menu2("Key: "
447
564
                                                  & ToStr(Key_Menu(Selected))
448
565
                                                  & NL
454
571
                  when Done =>
455
572
                     exit Specific_Key_Loop;
456
573
                  when Display =>
457
 
                     GPG.Viewkey(ToStr(UAP.Value(List.KA, Selected)));
 
574
                     Externals.GPG.Viewkey(ToStr(UAP.Value(List.KA, Selected)));
458
575
                  when DisplayVerbose =>
459
 
                     GPG.Viewkey(ToStr(UAP.Value(List.KA, Selected)),
 
576
                     Externals.GPG.Viewkey(ToStr(UAP.Value(List.KA, Selected)),
460
577
                                 Verbose => True);
461
578
                  when SSelect =>
462
579
                    Fingerprint_Real := UAP.Value(List.KA, Selected);
473
590
   exception
474
591
      when others =>
475
592
         Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
476
 
                              "Exception raised in Keys.List_Keys");
 
593
                              "Exception raised in Keys.Select_Key_From_List");
477
594
         raise;
478
595
   end Select_Key_From_List;
479
596
 
480
 
   -- Use keylist.
 
597
   procedure First_Key_From_List (List            : in out Key_List;
 
598
                                  The_Fingerprint :    out UBS) is
 
599
   begin
 
600
      The_Fingerprint := UAP.Value(List.KA, 1);
 
601
   exception
 
602
      when others =>
 
603
         Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error,
 
604
                              "Exception raised in Keys.First_Key_From_List");
 
605
         raise;
 
606
   end First_Key_From_List;
 
607
 
 
608
 
 
609
 
 
610
    -- Use keylist.
481
611
   procedure Use_Keylist (Recipients : in     UBS_Array;
482
612
                          List       : in out Key_List) is
483
613
      use Ada.Text_IO;
498
628
               if UAP.Value(Config.AKE_Email, J) = Recipients(I) then
499
629
                  Add_Keys_By_Fingerprint(UAP.Value(Config.AKE_Key, J),
500
630
                                          List,
 
631
                                          Encrypter,
501
632
                                          Found);
502
633
                  Found_Key(I) := Found_Key(I) or Found;
503
634
               end if;
515
646
               use type UBS;
516
647
            begin
517
648
               Empty_Keylist(Search_List);
518
 
               Add_Keys_By_Fingerprint(Recipients(I), Search_List);
 
649
               Add_Keys_By_Fingerprint(Recipients(I), Search_List, Encrypter);
519
650
               -- Remove any on the XK list.  Dead easy: simply run
520
651
               -- through the entire XK list saying `Remove Key'.
521
652
               for J in 1 .. Config.XK_Count loop
526
657
                           & ToStr(Recipients(I)) & "'");
527
658
                  -- Add the keys in Search_List to List.
528
659
                  for J in 1 .. Search_List.Count loop
529
 
                     Add_Key(UAP.Value(Search_List.KA, J), List);
 
660
                     Add_Key(UAP.Value(Search_List.KA, J), List, Encrypter);
530
661
                  end loop;
531
662
               else
532
663
                  Put_Line("Warning: Cannot find key for recipient: `"