line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl
|
2
|
|
|
|
|
|
|
package Ed2k_link;
|
3
|
|
|
|
|
|
|
our $VERSION = '20090428';
|
4
|
|
|
|
|
|
|
|
5
|
2
|
|
|
2
|
|
103941
|
use strict;
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
551
|
|
6
|
2
|
|
|
2
|
|
14
|
use warnings;
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
161
|
|
7
|
2
|
|
|
2
|
|
13
|
use base qw(Exporter);
|
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
1814
|
|
8
|
|
|
|
|
|
|
our @EXPORT = ();
|
9
|
|
|
|
|
|
|
our @EXPORT_OK = ();
|
10
|
|
|
|
|
|
|
|
11
|
2
|
|
|
2
|
|
18
|
use Carp qw(croak);
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
163
|
|
12
|
2
|
|
|
2
|
|
11
|
use File::Basename qw();
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
45
|
|
13
|
2
|
|
|
2
|
|
8808
|
use URI::Escape;
|
|
2
|
|
|
|
|
4240
|
|
|
2
|
|
|
|
|
164
|
|
14
|
2
|
|
|
2
|
|
2568
|
use Digest::MD4 qw(md4_hex);
|
|
2
|
|
|
|
|
6586
|
|
|
2
|
|
|
|
|
882
|
|
15
|
2
|
|
|
2
|
|
3642
|
use Digest::SHA1 qw(sha1);
|
|
2
|
|
|
|
|
7034
|
|
|
2
|
|
|
|
|
200
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
use constant {
|
18
|
2
|
|
|
|
|
6136
|
CHANK_SIZE => 9_728_000,
|
19
|
|
|
|
|
|
|
BLOCK_SIZE => 184_320,
|
20
|
2
|
|
|
2
|
|
21
|
};
|
|
2
|
|
|
|
|
6
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub encode_base32 {
|
23
|
0
|
|
|
0
|
0
|
0
|
my %bits_to_char = qw# 00000 A 00001 B 00010 C 00011 D 00100 E 00101 F 00110 G 00111 H
|
24
|
|
|
|
|
|
|
01000 I 01001 J 01010 K 01011 L 01100 M 01101 N 01110 O 01111 P
|
25
|
|
|
|
|
|
|
10000 Q 10001 R 10010 S 10011 T 10100 U 10101 V 10110 W 10111 X
|
26
|
|
|
|
|
|
|
11000 Y 11001 Z 11010 2 11011 3 11100 4 11101 5 11110 6 11111 7
|
27
|
|
|
|
|
|
|
#;
|
28
|
0
|
|
|
|
|
0
|
my ($source, $bits, $res) = shift;
|
29
|
0
|
|
|
|
|
0
|
$bits .= unpack('B*', substr($source, $_, 1)) for 0 .. length($source) - 1;
|
30
|
|
|
|
|
|
|
# generally $bits could be not 40 * k length and have to be padding. but not in our case
|
31
|
0
|
|
|
|
|
0
|
$res .= $bits_to_char{$&} while $bits =~ m/.{5}/g;
|
32
|
0
|
|
|
|
|
0
|
$res;
|
33
|
|
|
|
|
|
|
}
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub define_base_trees_orientation { # l/r, array_ref, start_idx, end_idx
|
36
|
0
|
0
|
|
0
|
0
|
0
|
if ($_[2] - $_[3] >= 0) {
|
|
|
0
|
|
|
|
|
|
37
|
0
|
|
|
|
|
0
|
$_[1][$_[2]] = $_[0];
|
38
|
|
|
|
|
|
|
} elsif ($_[2] + 1 == $_[3]) {
|
39
|
0
|
|
|
|
|
0
|
$_[1][$_[2]] = 'l';
|
40
|
0
|
|
|
|
|
0
|
$_[1][$_[3]] = 'r';
|
41
|
|
|
|
|
|
|
} else {
|
42
|
0
|
|
|
|
|
0
|
my $med = sprintf("%d", ($_[2] + $_[3]) / 2);
|
43
|
0
|
0
|
0
|
|
|
0
|
$med-- if $_[0] eq 'r' && $_[2] + $_[3] == $med * 2;
|
44
|
0
|
|
|
|
|
0
|
&define_base_trees_orientation('l', $_[1], $_[2], $med++);
|
45
|
0
|
|
|
|
|
0
|
&define_base_trees_orientation('r', $_[1], $med, $_[3]);
|
46
|
|
|
|
|
|
|
}
|
47
|
|
|
|
|
|
|
}
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub get_root_hash { # l/r, array_ref, start_idx, end_idx
|
50
|
0
|
|
|
0
|
0
|
0
|
my $med = $_[3];
|
51
|
0
|
0
|
|
|
|
0
|
if ($_[2] - $_[3] >= 0) {
|
|
|
0
|
|
|
|
|
|
52
|
0
|
|
|
|
|
0
|
return;
|
53
|
|
|
|
|
|
|
} elsif ($_[3] - $_[2] > 1) {
|
54
|
0
|
|
|
|
|
0
|
$med = sprintf("%d", ($_[2] + $_[3]) / 2);
|
55
|
0
|
0
|
0
|
|
|
0
|
$med-- if $_[0] eq 'r' && $_[2] + $_[3] == $med * 2;
|
56
|
0
|
|
|
|
|
0
|
&get_root_hash('l', $_[1], $_[2], $med++);
|
57
|
0
|
|
|
|
|
0
|
&get_root_hash('r', $_[1], $med, $_[3]);
|
58
|
|
|
|
|
|
|
}
|
59
|
0
|
|
|
|
|
0
|
$_[1] -> [$_[2]] = sha1($_[1] -> [$_[2]], $_[1] -> [$med]);
|
60
|
|
|
|
|
|
|
}
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub from_file {
|
63
|
0
|
|
|
0
|
1
|
0
|
my $either = shift;
|
64
|
0
|
0
|
|
|
|
0
|
%$either = () if ref $either;
|
65
|
0
|
|
|
|
|
0
|
my $file = shift;
|
66
|
0
|
0
|
|
|
|
0
|
return undef unless defined $file;
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# file must exist and be not empty!
|
69
|
0
|
0
|
0
|
|
|
0
|
return undef unless -f $file && -s $file;
|
70
|
|
|
|
|
|
|
|
71
|
0
|
|
|
|
|
0
|
my $self = { path_to_file => $file };
|
72
|
0
|
|
|
|
|
0
|
$self -> {filename} = File::Basename::fileparse($file);
|
73
|
|
|
|
|
|
|
# emule doesn't escape #[]@$&+,;=
|
74
|
0
|
|
|
|
|
0
|
$self -> {escaped_filename} = uri_escape_utf8($self -> {filename}, '^A-Za-z0-9\-_.!~*\'()#&+,;=');
|
75
|
|
|
|
|
|
|
# []@$
|
76
|
0
|
|
|
|
|
0
|
$self -> {escaped_filename} =~ s/%5B/[/g;
|
77
|
0
|
|
|
|
|
0
|
$self -> {escaped_filename} =~ s/%5D/]/g;
|
78
|
0
|
|
|
|
|
0
|
$self -> {escaped_filename} =~ s/%40/\@/g;
|
79
|
0
|
|
|
|
|
0
|
$self -> {escaped_filename} =~ s/%24/\$/g;
|
80
|
0
|
|
|
|
|
0
|
$self -> {size} = -s $file;
|
81
|
|
|
|
|
|
|
# hashes. step 1
|
82
|
0
|
|
|
|
|
0
|
my @aich_tree;
|
83
|
|
|
|
|
|
|
{
|
84
|
0
|
|
|
|
|
0
|
my $base_blocks = sprintf("%d", $self -> {size} / CHANK_SIZE);
|
|
0
|
|
|
|
|
0
|
|
85
|
0
|
0
|
|
|
|
0
|
$base_blocks-- if $self -> {size} == $base_blocks * CHANK_SIZE;
|
86
|
0
|
|
|
|
|
0
|
&define_base_trees_orientation('l', \@aich_tree, 0, $base_blocks);
|
87
|
|
|
|
|
|
|
}
|
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
{
|
90
|
0
|
0
|
|
|
|
0
|
open my $f, '<', $file or return undef;
|
|
0
|
|
|
|
|
0
|
|
91
|
0
|
|
|
|
|
0
|
binmode $f;
|
92
|
0
|
|
|
|
|
0
|
my ($t, $readed_bytes);
|
93
|
0
|
|
|
|
|
0
|
my $md4 = Digest::MD4 -> new;
|
94
|
0
|
|
|
|
|
0
|
while (defined($readed_bytes = read $f, $t, CHANK_SIZE)) {
|
95
|
0
|
|
|
|
|
0
|
$md4 -> add($t);
|
96
|
0
|
|
|
|
|
0
|
$self -> {hash} .= $md4 -> clone -> digest;
|
97
|
0
|
|
|
|
|
0
|
push @{$self -> {p}}, uc $md4 -> hexdigest;
|
|
0
|
|
|
|
|
0
|
|
98
|
0
|
0
|
|
|
|
0
|
if ($readed_bytes) {
|
99
|
0
|
|
|
|
|
0
|
my $pos = 0;
|
100
|
0
|
|
|
|
|
0
|
my @t_sha1;
|
101
|
0
|
|
|
|
|
0
|
while ($pos < $readed_bytes) {
|
102
|
0
|
|
|
|
|
0
|
push @t_sha1, sha1(substr($t, $pos, BLOCK_SIZE));
|
103
|
0
|
|
|
|
|
0
|
$pos += BLOCK_SIZE;
|
104
|
|
|
|
|
|
|
}
|
105
|
|
|
|
|
|
|
# sha1 for chank
|
106
|
0
|
|
|
|
|
0
|
&get_root_hash($aich_tree[$#{$self -> {p}}], \@t_sha1, 0, $#t_sha1);
|
|
0
|
|
|
|
|
0
|
|
107
|
0
|
|
|
|
|
0
|
$aich_tree[$#{$self -> {p}}] = $t_sha1[0];
|
|
0
|
|
|
|
|
0
|
|
108
|
|
|
|
|
|
|
}
|
109
|
0
|
0
|
|
|
|
0
|
last if $readed_bytes != CHANK_SIZE;
|
110
|
|
|
|
|
|
|
}
|
111
|
0
|
|
|
|
|
0
|
close $f;
|
112
|
0
|
|
|
|
|
0
|
return undef unless defined $readed_bytes
|
113
|
0
|
0
|
0
|
|
|
0
|
&& $self -> {size} == $#{$self -> {p}} * CHANK_SIZE + $readed_bytes;
|
114
|
|
|
|
|
|
|
}
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# hashes. step 2
|
117
|
0
|
0
|
|
|
|
0
|
if (@{$self -> {p}} == 1) {
|
|
0
|
|
|
|
|
0
|
|
118
|
0
|
|
|
|
|
0
|
$self -> {hash} = $self -> {p}[0];
|
119
|
|
|
|
|
|
|
} else {
|
120
|
0
|
|
|
|
|
0
|
$self -> {hash} = uc md4_hex($self -> {hash});
|
121
|
|
|
|
|
|
|
}
|
122
|
|
|
|
|
|
|
# aich hashset
|
123
|
0
|
|
|
|
|
0
|
&get_root_hash('l', \@aich_tree, 0, $#aich_tree);
|
124
|
0
|
|
|
|
|
0
|
$self -> {aich} = encode_base32($aich_tree[0]);
|
125
|
0
|
|
|
|
|
0
|
$self -> {reliable} = 1;
|
126
|
|
|
|
|
|
|
|
127
|
0
|
0
|
|
|
|
0
|
if (ref $either) {
|
128
|
0
|
|
|
|
|
0
|
%$either = %$self;
|
129
|
0
|
|
|
|
|
0
|
1;
|
130
|
|
|
|
|
|
|
} else {
|
131
|
0
|
|
|
|
|
0
|
bless $self, $either;
|
132
|
|
|
|
|
|
|
}
|
133
|
|
|
|
|
|
|
}
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub from_link {
|
136
|
1
|
|
|
1
|
1
|
12
|
my $either = shift;
|
137
|
1
|
50
|
|
|
|
5
|
%$either = () if ref $either;
|
138
|
1
|
|
|
|
|
3
|
my $link = shift;
|
139
|
1
|
50
|
|
|
|
4
|
return undef unless defined $link;
|
140
|
1
|
50
|
|
|
|
14
|
return undef unless $link =~ m#^ed2k://\|file\|([\d\D]+?)\|(\d+)\|([\da-f]{32})\|#i;
|
141
|
1
|
|
|
|
|
2
|
my $self;
|
142
|
1
|
|
|
|
|
5
|
$self -> {escaped_filename} = $1;
|
143
|
1
|
|
|
|
|
6
|
$self -> {filename} = uri_unescape($1);
|
144
|
1
|
|
|
|
|
14
|
$self -> {size} = $2;
|
145
|
1
|
|
|
|
|
5
|
$self -> {hash} = uc $3;
|
146
|
1
|
|
|
|
|
4
|
$self -> {reliable} = 1;
|
147
|
1
|
|
|
|
|
4
|
$link = "|$'";
|
148
|
1
|
50
|
|
|
|
4
|
return undef unless $self -> {size};
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
# complete hashset
|
151
|
1
|
50
|
|
|
|
4
|
if ($link =~ m/\|p=([\d\D]*?)\|/) {
|
152
|
0
|
|
|
|
|
0
|
my $t = uc $1;
|
153
|
0
|
|
|
|
|
0
|
$link = "|$`$'";
|
154
|
0
|
0
|
|
|
|
0
|
return undef unless $t =~ m/^([\dA-F]{32}(:[\dA-F]{32})*)$/;
|
155
|
|
|
|
|
|
|
|
156
|
0
|
|
|
|
|
0
|
my @t = split ':', $1;
|
157
|
0
|
|
|
|
|
0
|
$t = sprintf("%d", $self -> {size} / CHANK_SIZE);
|
158
|
0
|
0
|
|
|
|
0
|
$t++ if $self -> {size} >= $t * CHANK_SIZE;
|
159
|
0
|
0
|
|
|
|
0
|
return undef unless $t == @t;
|
160
|
|
|
|
|
|
|
|
161
|
0
|
0
|
|
|
|
0
|
if (@t == 1) {
|
162
|
0
|
0
|
|
|
|
0
|
return undef unless $self -> {hash} eq $t[0];
|
163
|
|
|
|
|
|
|
} else {
|
164
|
0
|
|
|
|
|
0
|
my $t = '';
|
165
|
0
|
|
|
|
|
0
|
foreach my $bh (@t) {
|
166
|
0
|
|
|
|
|
0
|
$t .= chr(hex($&)) while $bh =~ m/../g;
|
167
|
|
|
|
|
|
|
}
|
168
|
0
|
0
|
|
|
|
0
|
return undef unless $self -> {hash} eq uc md4_hex($t);
|
169
|
0
|
|
|
|
|
0
|
$self -> {reliable} = 0;
|
170
|
|
|
|
|
|
|
}
|
171
|
0
|
|
|
|
|
0
|
$self -> {p} = \@t;
|
172
|
|
|
|
|
|
|
}
|
173
|
1
|
50
|
33
|
|
|
19
|
$self -> {p}[0] = $self -> {hash} if $self -> {size} < CHANK_SIZE && not exists $self -> {p};
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# aich
|
176
|
1
|
50
|
|
|
|
4
|
if ($link =~ m/\|h=([\d\D]*?)\|/) {
|
177
|
0
|
|
|
|
|
0
|
$self -> {aich} = uc $1;
|
178
|
0
|
|
|
|
|
0
|
$link = "|$`$'";
|
179
|
0
|
0
|
|
|
|
0
|
return undef unless $self -> {aich} =~ m/^[A-Z2-7]{32}$/;
|
180
|
0
|
|
|
|
|
0
|
$self -> {reliable} = 0;
|
181
|
|
|
|
|
|
|
}
|
182
|
|
|
|
|
|
|
|
183
|
1
|
50
|
|
|
|
4
|
if (ref $either) {
|
184
|
0
|
|
|
|
|
0
|
%$either = %$self;
|
185
|
0
|
|
|
|
|
0
|
1;
|
186
|
|
|
|
|
|
|
} else {
|
187
|
1
|
|
|
|
|
6
|
bless $self, $either;
|
188
|
|
|
|
|
|
|
}
|
189
|
|
|
|
|
|
|
}
|
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub ok {
|
192
|
1
|
50
|
|
1
|
1
|
1268
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
193
|
1
|
|
33
|
|
|
21
|
return exists $instance -> {escaped_filename} && exists $instance -> {size} && exists $instance -> {hash};
|
194
|
|
|
|
|
|
|
}
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub filename {
|
197
|
1
|
50
|
|
1
|
1
|
5
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
198
|
1
|
|
|
|
|
6
|
$instance -> {filename};
|
199
|
|
|
|
|
|
|
}
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub escaped_filename {
|
202
|
1
|
50
|
|
1
|
1
|
7
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
203
|
1
|
|
|
|
|
6
|
$instance -> {escaped_filename};
|
204
|
|
|
|
|
|
|
}
|
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
sub filesize {
|
207
|
1
|
50
|
|
1
|
1
|
27
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
208
|
1
|
|
|
|
|
7
|
$instance -> {size};
|
209
|
|
|
|
|
|
|
}
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub hash {
|
212
|
0
|
0
|
|
0
|
1
|
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
213
|
0
|
|
|
|
|
|
$instance -> {hash};
|
214
|
|
|
|
|
|
|
}
|
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
sub has_complete_hashset {
|
217
|
0
|
0
|
|
0
|
1
|
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
218
|
0
|
0
|
|
|
|
|
exists $instance -> {p} && @{$instance -> {p}};
|
|
0
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
}
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub complete_hashset {
|
222
|
0
|
0
|
|
0
|
1
|
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
223
|
0
|
|
|
|
|
|
$instance -> has_complete_hashset ?
|
224
|
0
|
0
|
|
|
|
|
join ':', @{$instance -> {p}}
|
225
|
|
|
|
|
|
|
: undef;
|
226
|
|
|
|
|
|
|
}
|
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub has_aich {
|
229
|
0
|
0
|
|
0
|
1
|
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
230
|
0
|
|
|
|
|
|
exists $instance -> {aich};
|
231
|
|
|
|
|
|
|
}
|
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
sub aich {
|
234
|
0
|
0
|
|
0
|
1
|
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
235
|
0
|
|
|
|
|
|
$instance -> {aich};
|
236
|
|
|
|
|
|
|
}
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
sub link {
|
239
|
0
|
0
|
|
0
|
1
|
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
240
|
0
|
|
|
|
|
|
my $optional = shift;
|
241
|
0
|
0
|
|
|
|
|
return undef unless $instance -> ok;
|
242
|
0
|
|
|
|
|
|
my $res = 'ed2k://|file|'.$instance -> escaped_filename.'|'.$instance -> filesize.'|'.$instance -> hash.'|';
|
243
|
0
|
0
|
|
|
|
|
if (defined $optional) {
|
244
|
|
|
|
|
|
|
# complete hashset
|
245
|
0
|
0
|
0
|
|
|
|
$res .= "p=" . $instance -> complete_hashset . '|'
|
|
|
|
0
|
|
|
|
|
246
|
|
|
|
|
|
|
if $optional =~ /p/ && $instance -> filesize >= CHANK_SIZE && $instance -> has_complete_hashset;
|
247
|
|
|
|
|
|
|
# aich hashset
|
248
|
0
|
0
|
0
|
|
|
|
$res .= 'h=' . $instance -> aich . '|' if $optional =~ /h/ && $instance -> has_aich;
|
249
|
|
|
|
|
|
|
}
|
250
|
0
|
|
|
|
|
|
$res .= '/';
|
251
|
|
|
|
|
|
|
}
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
sub is_reliable {
|
254
|
0
|
0
|
|
0
|
1
|
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
255
|
0
|
|
|
|
|
|
$instance -> {reliable};
|
256
|
|
|
|
|
|
|
}
|
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub set_reliable {
|
259
|
0
|
0
|
|
0
|
1
|
|
ref(my $instance = shift) or croak "class usage! need to be instance usage";
|
260
|
0
|
|
|
|
|
|
$instance -> {reliable} = 1;
|
261
|
|
|
|
|
|
|
}
|
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
sub equal {
|
264
|
0
|
|
|
0
|
1
|
|
my $class = shift;
|
265
|
0
|
0
|
|
|
|
|
return undef unless @_ == 2;
|
266
|
0
|
|
|
|
|
|
my $one = shift;
|
267
|
0
|
|
|
|
|
|
my $two = shift;
|
268
|
0
|
|
0
|
|
|
|
my $res = $one -> ok && $two -> ok && $one -> filesize == $two -> filesize && $one -> hash eq $two -> hash;
|
269
|
0
|
0
|
|
|
|
|
return undef unless $res;
|
270
|
0
|
0
|
0
|
|
|
|
$res = $one -> complete_hashset eq $two -> complete_hashset
|
271
|
|
|
|
|
|
|
if $one -> has_complete_hashset && $two -> has_complete_hashset;
|
272
|
0
|
0
|
|
|
|
|
return undef unless $res;
|
273
|
0
|
0
|
0
|
|
|
|
$res = $one -> aich eq $two -> aich
|
274
|
|
|
|
|
|
|
if $one -> has_aich && $two -> has_aich;
|
275
|
0
|
0
|
|
|
|
|
return undef unless $res;
|
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# cases with copying complete hash or aich and setting reliable flag
|
278
|
0
|
0
|
0
|
|
|
|
if ($one -> is_reliable && $two -> is_reliable) {
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
279
|
0
|
0
|
0
|
|
|
|
if ($one -> has_complete_hashset && !$two -> has_complete_hashset) {
|
|
|
0
|
0
|
|
|
|
|
280
|
0
|
|
|
|
|
|
$two -> {p} = $one -> {p};
|
281
|
|
|
|
|
|
|
} elsif (!$one -> has_complete_hashset && $two -> has_complete_hashset) {
|
282
|
0
|
|
|
|
|
|
$one -> {p} = $two -> {p};
|
283
|
|
|
|
|
|
|
}
|
284
|
0
|
0
|
0
|
|
|
|
if ($one -> has_aich && !$two -> has_aich) {
|
|
|
0
|
0
|
|
|
|
|
285
|
0
|
|
|
|
|
|
$two -> {aich} = $one -> {aich};
|
286
|
|
|
|
|
|
|
} elsif (!$one -> has_aich && $two -> has_aich) {
|
287
|
0
|
|
|
|
|
|
$one -> {aich} = $two -> {aich};
|
288
|
|
|
|
|
|
|
}
|
289
|
|
|
|
|
|
|
} elsif ($one -> is_reliable) {
|
290
|
0
|
|
|
|
|
|
my $t = 0;
|
291
|
0
|
0
|
|
|
|
|
if ($one -> has_complete_hashset) {
|
292
|
0
|
|
|
|
|
|
$t++;
|
293
|
0
|
|
|
|
|
|
$two -> {p} = $one -> {p};
|
294
|
|
|
|
|
|
|
}
|
295
|
0
|
0
|
|
|
|
|
if ($one -> has_aich) {
|
296
|
0
|
|
|
|
|
|
$t++;
|
297
|
0
|
|
|
|
|
|
$two -> {aich} = $one -> {aich};
|
298
|
|
|
|
|
|
|
}
|
299
|
0
|
0
|
|
|
|
|
$t-- if $two -> has_complete_hashset;
|
300
|
0
|
0
|
|
|
|
|
$t-- if $two -> has_aich;
|
301
|
0
|
0
|
|
|
|
|
$two -> set_reliable if $t >= 0;
|
302
|
|
|
|
|
|
|
} elsif ($two -> is_reliable) {
|
303
|
0
|
|
|
|
|
|
my $t = 0;
|
304
|
0
|
0
|
|
|
|
|
if ($two -> has_complete_hashset) {
|
305
|
0
|
|
|
|
|
|
$t++;
|
306
|
0
|
|
|
|
|
|
$one -> {p} = $two -> {p};
|
307
|
|
|
|
|
|
|
}
|
308
|
0
|
0
|
|
|
|
|
if ($two -> has_aich) {
|
309
|
0
|
|
|
|
|
|
$t++;
|
310
|
0
|
|
|
|
|
|
$one -> {aich} = $two -> {aich};
|
311
|
|
|
|
|
|
|
}
|
312
|
0
|
0
|
|
|
|
|
$t-- if $one -> has_complete_hashset;
|
313
|
0
|
0
|
|
|
|
|
$t-- if $one -> has_aich;
|
314
|
0
|
0
|
|
|
|
|
$one -> set_reliable if $t >= 0;
|
315
|
|
|
|
|
|
|
}
|
316
|
|
|
|
|
|
|
|
317
|
0
|
|
|
|
|
|
$res;
|
318
|
|
|
|
|
|
|
}
|
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
1;
|
321
|
|
|
|
|
|
|
__END__
|