This file is indexed.

/usr/share/perl5/Config/Identity.pm is in libconfig-identity-perl 0.0019-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
use strict;
use warnings;

package Config::Identity;
# ABSTRACT: Load (and optionally decrypt via GnuPG) user/pass identity information 

our $VERSION = '0.0019';

use Carp;
use IPC::Run qw/ start finish /;
use File::HomeDir();
use File::Spec;

our $home = File::HomeDir->home;
{
    my $gpg;
    sub GPG() { $ENV{CI_GPG} || ( $gpg ||= do {
        require File::Which;
        $gpg = File::Which::which( $_ ) and last for qw/ gpg gpg2 /;
        $gpg;
    } ) }
}
sub GPG_ARGUMENTS() { $ENV{CI_GPG_ARGUMENTS} || '' }

# TODO Do not even need to do this, since the file is on disk already...
sub decrypt {
    my $self = shift;
    my $file = shift;

    my $gpg = GPG or croak "Missing gpg";
    my $gpg_arguments = GPG_ARGUMENTS;
    my $run;
    # Old versions, please ignore
    #$run = "$gpg $gpg_arguments -qd --no-tty --command-fd 0 --status-fd 1";
    #$run = "$gpg $gpg_arguments -qd --no-tty --command-fd 0";
    $run = "$gpg $gpg_arguments -qd --no-tty";
    my @run = split m/\s+/, $run;
    push @run, $file;
    my $process = start( \@run, '>pipe', \*OUT, '2>pipe', \*ERR );
    my $output = join '', <OUT>;
    my $_error = join '', <ERR>;
    finish $process;
    return ( $output, $_error );
}

sub best {
    my $self = shift;
    my $stub = shift;
    my $base = shift;
    $base = $home unless defined $base;

    croak "Missing stub" unless defined $stub && length $stub;

    for my $i0 ( ".$stub-identity", ".$stub" ) {
        for my $i1 ( "." ) {
            my $path = File::Spec->catfile( $base, $i1, $i0 );
            return $path if -f $path;
        }
    }

    return '';
}

sub read {
    my $self = shift;
    my $file = shift;

    croak "Missing file" unless -f $file;
    croak "Cannot read file ($file)" unless -r $file;

    my $binary = -B $file;

    open my $handle, $file or croak $!;
    binmode $handle if $binary;
    local $/ = undef;
    my $content = <$handle>;
    close $handle or warn $!;

    if ( $binary || $content =~ m/----BEGIN PGP MESSAGE----/ ) {
        my ( $_content, $error ) = $self->decrypt( $file );
        if ( $error ) {
            carp "Error during decryption of content" . $binary ? '' : "\n$content";
            croak "Error during decryption of $file:\n$error";
        }
        $content = $_content;
    }
    
    return $content;
}

sub parse {
    my $self = shift;
    my $content = shift;

    return unless $content;
    my %content;
    for ( split m/\n/, $content ) {
        next if /^\s*#/;
        next unless m/\S/;
        next unless my ($key, $value) = /^\s*(\w+)\s+(.+)$/;
        $content{$key} = $value;
    }
    return %content;
}

sub load_best {
    my $self = shift;
    my $stub = shift;

    croak "Unable to find .$stub-identity or .$stub" unless my $path = $self->best( $stub );
    return $self->load( $path );
}

sub try_best {
    my $self = shift;
    my $stub = shift;

    return unless my $path = $self->best( $stub );
    return $self->load( $path );
}

sub load {
    my $self = shift;
    my $file = shift;

    return $self->parse( $self->read( $file ) );
}

sub load_check {
    my $self = shift;
    my $stub = shift;
    my $required = shift || [];

    my %identity = $self->load_best($stub);
    my @missing;
    if ( ref $required eq 'ARRAY' ) {
        @missing = grep { ! defined $identity{$_} } @$required;
    }
    elsif ( ref $required eq 'CODE' ) {
        local $_ = \%identity;
        @missing = $required->(\%identity);
    }
    else {
        croak "Argument to check keys must be an arrayref or coderef";
    }

    if ( @missing ) {
        my $inflect = @missing > 1 ? "fields" : "field";
        croak "Missing required ${inflect}: @missing"
    }

    return %identity;
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Config::Identity - Load (and optionally decrypt via GnuPG) user/pass identity information 

=head1 VERSION

version 0.0019

=head1 SYNOPSIS

PAUSE:

    use Config::Identity::PAUSE;

    # 1. Find either $HOME/.pause-identity or $HOME/.pause
    # 2. Decrypt the found file (if necessary), read, and parse it
    # 3. Throw an exception unless  %identity has 'user' and 'password' defined

    my %identity = Config::Identity::PAUSE->load_check;
    print "user: $identity{user} password: $identity{password}\n";

GitHub API:

    use Config::Identity::GitHub;

    # 1. Find either $HOME/.github-identity or $HOME/.github
    # 2. Decrypt the found file (if necessary) read, and parse it
    # 3. Throw an exception unless %identity has 'login' and 'token' defined

    my %identity = Config::Identity::PAUSE->load_check;
    print "login: $identity{login} token: $identity{token}\n";

=head1 DESCRIPTION

Config::Identity is a tool for loading (and optionally decrypting via GnuPG) user/pass identity information

For GitHub API access, an identity is a C<login>/C<token> pair

For PAUSE access, an identity is a C<user>/C<password> pair

=head1 USAGE

=head2 %identity = Config::Identity->load_best( <stub> )

First attempt to load an identity from $HOME/.<stub>-identity

If that file does not exist, then attempt to load an identity from $HOME/.<stub>

The file may be optionally GnuPG encrypted

%identity will be populated like so:

    <key> <value>

For example:

    username alice
    password hunter2

If an identity file can't be found or read, the method croaks.

=head2 %identity = Config::Identity->load_check( <stub>, <checker> )

Works like C<load_best> but also checks for required keys.  The C<checker>
argument must be an array reference of B<required> keys or a code reference
that takes a hashref of key/value pairs from the identity file and returns
a list of B<missing> keys.  For convenience, the hashref will also be
placed in C<$_>.

If any keys are found missing, the method croaks.

=head1 Using a custom C<gpg> or passing custom arguments

You can specify a custom C<gpg> executable by setting the CI_GPG environment variable

    export CI_GPG="$HOME/bin/gpg"

You can pass custom arguments by setting the CI_GPG_ARGUMENTS environment variable

    export CI_GPG_ARGUMENTS="--no-secmem-warning"

=head1 Encrypting your identity information with GnuPG

If you've never used GnuPG before, first initialize it:

    # Follow the prompts to create a new key for yourself
    gpg --gen-key 

To encrypt your GitHub identity with GnuPG using the above key:

    # Follow the prompts, using the above key as the "recipient"
    # Use ^D once you've finished typing out your authentication information
    gpg -ea > $HOME/.github

=head1 Caching your GnuPG secret key via gpg-agent

Put the following in your .*rc

    if which gpg-agent 1>/dev/null
    then
        if test -f $HOME/.gpg-agent-info && \
            kill -0 `cut -d: -f 2 $HOME/.gpg-agent-info` 2>/dev/null
        then
            . "${HOME}/.gpg-agent-info"
            export GPG_AGENT_INFO
        else
            eval `gpg-agent --daemon --write-env-file "${HOME}/.gpg-agent-info"`
        fi
    else
    fi

=head1 PAUSE identity format

    user <user>
    password <password>

C<username> can also be used as alias for C<user>

=head1 GitHub identity format

    login <login>
    token <token>

=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Bugs / Feature Requests

Please report any bugs or feature requests through the issue tracker
at L<http://rt.cpan.org/Public/Dist/Display.html?Name=Config-Identity>.
You will be notified automatically of any progress on your issue.

=head2 Source Code

This is open source software.  The code repository is available for
public review and contribution under the terms of the license.

L<https://github.com/dagolden/Config-Identity>

  git clone https://github.com/dagolden/Config-Identity.git

=head1 AUTHOR

Robert Krimen <robertkrimen@gmail.com>

=head1 CONTRIBUTOR

=for stopwords David Golden

David Golden <dagolden@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2010 by Robert Krimen.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut