1package App::Acmeman::Domain;
2
3use strict;
4use warnings;
5use Carp;
6use Clone;
7
8require Exporter;
9our @ISA = qw(Exporter);
10our @EXPORT_OK = qw(CERT_FILE KEY_FILE CA_FILE);
11our %EXPORT_TAGS = ( files => [ qw(CERT_FILE KEY_FILE CA_FILE) ] );
12
13use constant {
14    CERT_FILE => 0,
15    KEY_FILE => 1,
16    CA_FILE => 2
17};
18
19sub uniq {
20    my %h;
21    map {
22	if (exists($h{$_})) {
23	    ()
24	} else {
25	    $h{$_} = 1;
26	    $_
27        }
28    } @_;
29}
30
31sub new {
32    my ($class, %args) = @_;
33
34    my $self = bless { }, $class;
35    my $v;
36
37    if ($v = delete $args{cn}) {
38	$self->{_cn} = lc $v;
39    }
40    if ($v = delete $args{alt}) {
41	if (ref($v) eq 'ARRAY') {
42	    $self->{_alt} =  [ uniq(map { lc } @$v) ];
43	} else {
44	    $self->{_alt} = [ lc $v ];
45	}
46    }
47    if ($v = delete $args{type}) {
48	$self->{_cert_type} = $v;
49    }
50    if (($v = delete $args{certificate_file})
51	|| ($v = delete $args{'certificate-file'})) {
52	$self->{_file}[CERT_FILE] = $v;
53    }
54    if (($v = delete $args{ca_file})
55	|| ($v = delete $args{'ca-file'})) {
56	$self->{_file}[CA_FILE] = $v;
57    }
58    if (($v = delete $args{key_file})
59	|| ($v = delete $args{'key-file'})) {
60	$self->{_file}[KEY_FILE] = $v;
61    }
62
63    $v = delete($args{argument}) || '$domain';
64    $v =~ s{\$}{\\\$};
65    $self->{_argument} = qr($v);
66
67    $self->{_postrenew} = delete $args{'postrenew'};
68
69    croak "unrecognized arguments" if keys %args;
70    return $self;
71}
72
73sub names {
74    my $self = shift;
75    if (wantarray) {
76	return ($self->cn, $self->alt);
77    } else {
78	return $self->alt() + 1;
79    }
80}
81
82sub contains {
83    my $self = shift;
84    my $val = lc shift;
85    return grep { $_ eq $val } $self->names;
86}
87
88sub _domain_cmp {
89    my ($a,$b) = @_;
90
91    carp "righthand-side argument should be a App::Acmeman::Domain"
92	unless $b->isa('App::Acmeman::Domain');
93    return $a->{_cn} cmp $b->{_cn};
94}
95
96sub _domain_plus {
97    my ($a, $b) = @_;
98
99    carp "righthand-side argument should be a App::Acmeman::Domain"
100	unless $b->isa('App::Acmeman::Domain');
101
102    $a = Clone::clone($a);
103    push @{$a->{_alt}}, $b->cn
104	unless $a->contains($b->cn);
105    @{$a->{_alt}} = uniq($a->alt, $b->alt);
106    return $a;
107}
108
109use overload
110    cmp => \&_domain_cmp,
111    '+' => \&_domain_plus,
112    '""' => sub { $_[0]->cn };
113
114sub cn {
115    my $self = shift;
116    return $self->{_cn};
117}
118
119sub alt {
120    my $self = shift;
121    if (wantarray) {
122	return exists($self->{_alt}) ? (@{$self->{_alt}}) : ();
123    } else {
124	return exists($self->{_alt}) ? (0+@{$self->{_alt}}) : 0;
125    }
126}
127
128sub file {
129    my ($self, $type) = @_;
130    return undef unless exists($self->{_file}[$type]);
131    my $res = $self->{_file}[$type];
132    $res =~ s{$self->{_argument}}{$self->cn}ge;
133    return $res;
134}
135
136sub certificate_file {
137    my $self = shift;
138    return $self->file(CERT_FILE);
139}
140
141sub postrenew {
142    my $self = shift;
143    return $self->{_postrenew}
144}
145
1461;
147
148