#! /usr/bin/perl use strict ; use warnings ; use lib '.' ; use File::Path ; use Wotsap ; # printf "@INC\n" ; exit ; my $prog = substr $0, rindex ( $0, '/' ) + 1 ; my $help = Wotsap::Commands -> usage ; chomp $help ; my $Usage = < Make ( @ARGV ) ; @ARGV = @{ $cmds -> main } ; use Getopt::Long ; Getopt::Long::config ( 'no_ignore_case' ) ; my %opt = () ; Usage '' unless GetOptions ( \%opt, qw(v q d h version) ) ; Usage "Arg count [@ARGV]\n" unless $opt{h} or $opt{version} or @ARGV == 1 ; if ( $opt{version} ) { printf "%s\n", Wotsap -> Version ; exit ; } if ( $opt{h} ) { print $Usage ; exit ; } $opt{v} ||= $opt{d} ; OBB -> Verbosity ( 'Verbose' ) if $opt{v} ; OBB -> Verbosity ( 'Debug' ) if $opt{d} ; $| = 1 ; my $WDIR = shift ; unless ( -d $WDIR ) { if ( $cmds -> has_make ) { mkpath $WDIR, 0, 0755 ; } else { printf "Workdir '$WDIR' does not exist.\n" ; printf "Create workdir '$WDIR' with : $prog $WDIR make\n" ; exit 1 ; } } elsif ( ! Wotsap -> is_a_wd ( $WDIR ) and ! $cmds -> has_make ) { printf "Directory '$WDIR' is not a Wotsap workdir.\n" ; exit 1 ; } my $W = Wotsap -> Make ( path => $WDIR ) ; printf "Workdir : %s\n", $WDIR unless $opt{q} ; for my $cmd ( @{ $cmds -> cmds } ) { printf "Command : %s\n", $cmd -> name unless $opt{q} ; $cmd -> main ( $W ) ; } END { $W -> dbh -> disconnect if ref $W and $W -> can ( 'dbh' ) and $W -> dbh ; } __END__ =pod =head1 NAME wotsap - Wotsap archive manipulation =head1 SYNOPSIS Usage: wotsap [-v] [-q] [-d] [-h] work-dir COMMAND ... option v : be verbose option q : be quiet option d : show debug info option h : show help ; exit --------------------------- COMMANDS: Usage: make [-g path/to/gpg] [-k key_server] [-r root_key] Usage: open Usage: info [-v] [key_id] Usage: import wotsap-file Usage: check Usage: reset [-keysum where] [-keybad where] Usage: update [-cache days] max [kid] Usage: scc Usage: export [-v version] Usage: xpaths [-j] [-r] [-m max] from to =head1 DESCRIPTION Program B handles Wotsap archives. A Wotsap archive is a densely packed file containing historic information about the I. See L for a description of the Wotfile format. Central to B is the notion of a I (I for short). A workdir is just a directory containing files pertaining to one Wotsap archive. To decompress, unpack and decode an existing Wotsap archive I into workdir I use : wotsap my-workdir make import my-archive To create a fresh Wotsap archive C, use : wotsap prod make -k some-key-server update -reset 0 scc export ... and to refresh : wotsap prod update -reset 0 scc export B : =over =item * At this moment, a full update run retrieves some 100.000 keys from a keyserver ; unless you own the key-server, ask permission first! =back =head1 Options =over 4 =item -v be verbose =item -q be quiet =item -d show debug info =item -h show help ; exit =back =head1 Commands =head2 command I Usage: make [-g path/to/gpg] [-k key-server] [-r root-key] Command I creates or updates a workdir. The values of the options are stored in the workdir as meta-information. =over 4 =item B<-g> I The path to program B(1), default C. =item B<-k> I The domain name of a pgp keyserver ; no default. =item B<-r> I The start-key used by commands C and C ; default C<8b962943fc243f3c>. =back =head2 command I Usage: open Command I just execs sqlite3(1) on the workdir's sqlite database ; for your convenience. =head2 command I Usage: info [-v] [key-id] Command I shows the meta-data stored in the workdir's database. If a I] is provided, some info about the key is shown ; otherwise the number of keys and signatures is shown. =head2 command I Usage: import wotsap-file =over 4 =item * Command I copies the specified I into the workdir as C. =item * Then, it decompresses and unpacks I, creating files C, C, C, C, C and C. =item * Then, it decodes files C and C into files C and C. =item * Then, it creates a fresh sqlite database C with the proper layout and meta-info, and inserts the imported keys and signature information. =item * Then, it verifies that the keys+signatures form a graph that is I (contains exactly one I). =item * Files C, C and C have the same number of lines ; corresponding lines refer to the same key. =back =head2 command I Usage: check Command I verifies that the keys and signatures in the workdir's sqlite database form a I. =head2 command I Usage: reset [-keydata where] Command I resets the C process : the queue is emptied and all keys are set to I. Option I<-keydata> resets meta-data for keys specified with the I-clause. On subsequent C runs, the keys will be re-fetched from the key-server (or the cache), and re-evaluated. Example reset -keydata "bad = ''" reset -keydata "bad = 'expired'" reset -keydata "kid = 'some-key-id'" =head2 command I Usage: update [-cache days] max [kid] Command I fetches keys from a keyserver (or the cache), and updates the workdir's database. At most $max keys are updated ; C<$max = 0> means I. Starting with some I, command I does a search of the PGP graph, updating and marking visited keys. queue = [ some-root-key ] # if no keys are marked 'visited' while ( queue-is-not-empty ) { key = shift queue ; if ( key.visited == 0 ) { update key ; key.visited = 1 ; push queue key.signers ; } } Command I remembers the contents of the I and the state of the keys (visited, not-visited) from one run to the next ; it continues where the previous I-run stopped. If an optional key_id I is supplied, that key is deleted, and used as I ; I is set to I<1>. This is for debugging : % wotsap -d X update 1 kid With option I<-cache $days>, fetched keys are cached, and cached keys will be used (if not older that $days days), instead of fetched from the key-server. Keys that were not found on the keyserver in a previous update-run will always be retrieved from the keyserver, because only non-empty key-blocks are cached. With I<$days = 0>, the cache will be written but not used. Caching is cheap in cpu-cycles (involving only file link/unlinks), but a cache typically uses 1.2 GB per 100,000 keys. =head2 command I Usage: scc Command I computes the SCC of the keys and signatures in the workdir's database, marking keys with a I-bit : I or I the strong set. =head2 command I Usage: export [version] Command I creates an export file C. Optionally specify the export file's Wotsap version : C<0.2> or C<0.3> ; default is C<0.3>. =head2 command I Usage: xpaths [-j] [-r] [-m max] from to Command I finds paths from key I to key I. =over 4 =item -j Print a json identifying I, I and the (interior of the) paths found. =item -r Find reverse paths. =item -m I Return at most I paths ; default 8. =back Regarding arguments I and I : =over 4 =item * Key I and key I must be at least 8 hex digits long. =item * Key I and/or key I may be specified as C. =item * If key I or key I is longer than the workdir's key length (8 for wotsap version 0.1 and 0.2, 16 for version 0.3) a proper suffix of the key is used. =item * If key I or key I is shorter than the workdir's key length, some key with the given suffix is used. =back =head1 INSTALL Wotsap is available from L. Install with cpanm http://pgp.cs.uu.nl/wotsap/Wotsap.tar.gz or, test only with cpanm --test-only http://pgp.cs.uu.nl/wotsap/Wotsap.tar.gz =head1 SEE ALSO =for html Wotsap(3) =for man Wotsap(3) =head1 AUTHOR =for html Wotsap © 2015 Henk P. Penning - All rights reserved ; Wotsap-0.02.09 - Fri Aug 24 16:35:48 2018 =for man Wotsap by Henk P. Penning, . - Wotsap-0.02.09 - Fri Aug 24 16:35:48 2018 You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl 5.10.0 README file. =cut