| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
=pod |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Net::OSCAR::Utility -- internal utility functions for Net::OSCAR |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 VERSION |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
version 1.928 |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=cut |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
package Net::OSCAR::Utility; |
|
14
|
|
|
|
|
|
|
BEGIN { |
|
15
|
5
|
|
|
5
|
|
144
|
$Net::OSCAR::Utility::VERSION = '1.928'; |
|
16
|
|
|
|
|
|
|
} |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
$REVISION = '$Revision$'; |
|
19
|
|
|
|
|
|
|
|
|
20
|
5
|
|
|
5
|
|
28
|
use strict; |
|
|
5
|
|
|
|
|
7
|
|
|
|
5
|
|
|
|
|
173
|
|
|
21
|
5
|
|
|
5
|
|
25
|
use vars qw(@ISA @EXPORT); |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
362
|
|
|
22
|
5
|
|
|
5
|
|
29
|
use Digest::MD5 qw(md5); |
|
|
5
|
|
|
|
|
17
|
|
|
|
5
|
|
|
|
|
224
|
|
|
23
|
5
|
|
|
5
|
|
25
|
use Carp; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
291
|
|
|
24
|
|
|
|
|
|
|
|
|
25
|
5
|
|
|
5
|
|
25
|
use Net::OSCAR::TLV; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
230
|
|
|
26
|
5
|
|
|
5
|
|
33
|
use Net::OSCAR::Common qw(:loglevels); |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
3169
|
|
|
27
|
5
|
|
|
5
|
|
456
|
use Net::OSCAR::Constants; |
|
|
5
|
|
|
|
|
10
|
|
|
|
5
|
|
|
|
|
21326
|
|
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
require Exporter; |
|
30
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
|
31
|
|
|
|
|
|
|
@EXPORT = qw( |
|
32
|
|
|
|
|
|
|
randchars log_print log_printf log_print_cond log_printf_cond hexdump normalize tlv_decode tlv_encode send_error bltie |
|
33
|
|
|
|
|
|
|
signon_tlv encode_password send_versions hash_iter_reset millitime |
|
34
|
|
|
|
|
|
|
); |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
eval { |
|
37
|
|
|
|
|
|
|
require Time::HiRes; |
|
38
|
|
|
|
|
|
|
}; |
|
39
|
|
|
|
|
|
|
our $finetime = $@ ? 0 : 1; |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub millitime() { |
|
43
|
0
|
0
|
|
0
|
0
|
0
|
my $time = $finetime ? Time::HiRes::time() : time(); |
|
44
|
0
|
|
|
|
|
0
|
return int($time * 1000); |
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub randchars($) { |
|
48
|
0
|
|
|
0
|
0
|
0
|
my $count = shift; |
|
49
|
0
|
|
|
|
|
0
|
my $retval = ""; |
|
50
|
0
|
|
|
|
|
0
|
for(my $i = 0; $i < $count; $i++) { $retval .= chr(int(rand(256))); } |
|
|
0
|
|
|
|
|
0
|
|
|
51
|
0
|
|
|
|
|
0
|
return $retval; |
|
52
|
|
|
|
|
|
|
} |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub log_print($$@) { |
|
56
|
0
|
|
|
0
|
0
|
0
|
my($obj, $level) = (shift, shift); |
|
57
|
0
|
0
|
|
|
|
0
|
my $session = exists($obj->{session}) ? $obj->{session} : $obj; |
|
58
|
0
|
0
|
0
|
|
|
0
|
return unless defined($session->{LOGLEVEL}) and $session->{LOGLEVEL} >= $level; |
|
59
|
|
|
|
|
|
|
|
|
60
|
0
|
|
|
|
|
0
|
my $message = ""; |
|
61
|
0
|
0
|
|
|
|
0
|
$message .= $obj->{description}. ": " if $obj->{description}; |
|
62
|
0
|
|
|
|
|
0
|
$message .= join("", @_). "\n"; |
|
63
|
|
|
|
|
|
|
|
|
64
|
0
|
0
|
|
|
|
0
|
if($session->{callbacks}->{log}) { |
|
65
|
0
|
|
|
|
|
0
|
$session->callback_log($level, $message); |
|
66
|
|
|
|
|
|
|
} else { |
|
67
|
0
|
0
|
|
|
|
0
|
$message = "(".$session->{screenname}.") $message" if $session->{SNDEBUG}; |
|
68
|
0
|
|
|
|
|
0
|
print STDERR $message; |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub log_printf($$@) { |
|
73
|
0
|
|
|
0
|
0
|
0
|
my($obj, $level, $fmtstr) = (shift, shift, shift); |
|
74
|
|
|
|
|
|
|
|
|
75
|
0
|
|
|
|
|
0
|
$obj->log_print($level, sprintf($fmtstr, @_)); |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub log_printf_cond($$&) { |
|
79
|
0
|
|
|
0
|
0
|
0
|
my($obj, $level, $sub) = @_; |
|
80
|
0
|
0
|
|
|
|
0
|
my $session = exists($obj->{session}) ? $obj->{session} : $obj; |
|
81
|
0
|
0
|
0
|
|
|
0
|
return unless defined($session->{LOGLEVEL}) and $session->{LOGLEVEL} >= $level; |
|
82
|
|
|
|
|
|
|
|
|
83
|
0
|
|
|
|
|
0
|
log_printf($obj, $level, &$sub); |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub log_print_cond($$&) { |
|
87
|
0
|
|
|
0
|
0
|
0
|
my($obj, $level, $sub) = @_; |
|
88
|
0
|
0
|
|
|
|
0
|
my $session = exists($obj->{session}) ? $obj->{session} : $obj; |
|
89
|
0
|
0
|
0
|
|
|
0
|
return unless defined($session->{LOGLEVEL}) and $session->{LOGLEVEL} >= $level; |
|
90
|
|
|
|
|
|
|
|
|
91
|
0
|
|
|
|
|
0
|
log_print($obj, $level, &$sub); |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub hexdump($;$) { |
|
95
|
0
|
|
|
0
|
0
|
0
|
my $stuff = shift; |
|
96
|
0
|
|
0
|
|
|
0
|
my $forcehex = shift || 0; |
|
97
|
0
|
|
|
|
|
0
|
my $retbuff = ""; |
|
98
|
0
|
|
|
|
|
0
|
my @stuff; |
|
99
|
|
|
|
|
|
|
|
|
100
|
0
|
0
|
|
|
|
0
|
return "" unless defined($stuff); |
|
101
|
0
|
|
|
|
|
0
|
for(my $i = 0; $i < length($stuff); $i++) { |
|
102
|
0
|
|
|
|
|
0
|
push @stuff, substr($stuff, $i, 1); |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
0
|
0
|
0
|
|
|
0
|
return $stuff unless $forcehex or grep { $_ lt chr(0x20) or $_ gt chr(0x7E) } @stuff; |
|
|
0
|
0
|
|
|
|
0
|
|
|
106
|
0
|
|
|
|
|
0
|
while(@stuff) { |
|
107
|
0
|
|
|
|
|
0
|
my $i = 0; |
|
108
|
0
|
|
|
|
|
0
|
$retbuff .= "\n\t"; |
|
109
|
0
|
|
|
|
|
0
|
my @currstuff = splice(@stuff, 0, 16); |
|
110
|
|
|
|
|
|
|
|
|
111
|
0
|
|
|
|
|
0
|
foreach my $currstuff(@currstuff) { |
|
112
|
0
|
0
|
|
|
|
0
|
$retbuff .= " " unless $i % 4; |
|
113
|
0
|
0
|
|
|
|
0
|
$retbuff .= " " unless $i % 8; |
|
114
|
0
|
|
|
|
|
0
|
$retbuff .= sprintf "%02X ", ord($currstuff); |
|
115
|
0
|
|
|
|
|
0
|
$i++; |
|
116
|
|
|
|
|
|
|
} |
|
117
|
0
|
|
|
|
|
0
|
for(; $i < 16; $i++) { |
|
118
|
0
|
0
|
|
|
|
0
|
$retbuff .= " " unless $i % 4; |
|
119
|
0
|
0
|
|
|
|
0
|
$retbuff .= " " unless $i % 8; |
|
120
|
0
|
|
|
|
|
0
|
$retbuff .= " "; |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
|
|
123
|
0
|
|
|
|
|
0
|
$retbuff .= " "; |
|
124
|
0
|
|
|
|
|
0
|
$i = 0; |
|
125
|
0
|
|
|
|
|
0
|
foreach my $currstuff(@currstuff) { |
|
126
|
0
|
0
|
|
|
|
0
|
$retbuff .= " " unless $i % 4; |
|
127
|
0
|
0
|
|
|
|
0
|
$retbuff .= " " unless $i % 8; |
|
128
|
0
|
0
|
0
|
|
|
0
|
if($currstuff ge chr(0x20) and $currstuff le chr(0x7E)) { |
|
129
|
0
|
|
|
|
|
0
|
$retbuff .= $currstuff; |
|
130
|
|
|
|
|
|
|
} else { |
|
131
|
0
|
|
|
|
|
0
|
$retbuff .= "."; |
|
132
|
|
|
|
|
|
|
} |
|
133
|
0
|
|
|
|
|
0
|
$i++; |
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
} |
|
136
|
0
|
|
|
|
|
0
|
return $retbuff; |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub normalize($) { |
|
140
|
4
|
|
|
4
|
0
|
6
|
my $temp = shift; |
|
141
|
4
|
50
|
|
|
|
13
|
$temp =~ tr/ //d if $temp; |
|
142
|
4
|
50
|
|
|
|
21
|
return $temp ? lc($temp) : ""; |
|
143
|
|
|
|
|
|
|
} |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub tlv_decode($;$) { |
|
146
|
0
|
|
|
0
|
0
|
0
|
my($tlv, $tlvcnt) = @_; |
|
147
|
0
|
|
|
|
|
0
|
my($type, $len, $value, %retval); |
|
148
|
0
|
|
|
|
|
0
|
my $currtlv = 0; |
|
149
|
0
|
|
|
|
|
0
|
my $strpos = 0; |
|
150
|
|
|
|
|
|
|
|
|
151
|
0
|
|
|
|
|
0
|
my $retval = tlv; |
|
152
|
|
|
|
|
|
|
|
|
153
|
0
|
0
|
|
|
|
0
|
$tlvcnt = 0 unless $tlvcnt; |
|
154
|
0
|
|
0
|
|
|
0
|
while(length($tlv) >= 4 and (!$tlvcnt or $currtlv < $tlvcnt)) { |
|
|
|
|
0
|
|
|
|
|
|
155
|
0
|
|
|
|
|
0
|
($type, $len) = unpack("nn", $tlv); |
|
156
|
0
|
0
|
|
|
|
0
|
$len = 0x2 if $type == 0x13; |
|
157
|
0
|
|
|
|
|
0
|
$strpos += 4; |
|
158
|
0
|
|
|
|
|
0
|
substr($tlv, 0, 4) = ""; |
|
159
|
0
|
0
|
|
|
|
0
|
if($len) { |
|
160
|
0
|
|
|
|
|
0
|
($value) = substr($tlv, 0, $len, ""); |
|
161
|
|
|
|
|
|
|
} else { |
|
162
|
0
|
|
|
|
|
0
|
$value = ""; |
|
163
|
|
|
|
|
|
|
} |
|
164
|
0
|
|
|
|
|
0
|
$strpos += $len; |
|
165
|
0
|
0
|
|
|
|
0
|
$currtlv++ unless $type == 0; |
|
166
|
0
|
|
|
|
|
0
|
$retval->{$type} = $value; |
|
167
|
|
|
|
|
|
|
} |
|
168
|
|
|
|
|
|
|
|
|
169
|
0
|
0
|
|
|
|
0
|
return $tlvcnt ? ($retval, $strpos) : $retval; |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub tlv_encode($) { |
|
173
|
0
|
|
|
0
|
0
|
0
|
my $tlv = shift; |
|
174
|
0
|
|
|
|
|
0
|
my($buffer, $type, $value) = ("", 0, ""); |
|
175
|
|
|
|
|
|
|
|
|
176
|
0
|
0
|
0
|
|
|
0
|
confess "You must use a tied Net::OSCAR::TLV hash!" |
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
177
|
|
|
|
|
|
|
unless defined($tlv) and ref($tlv) eq "HASH" and defined(tied(%$tlv)) and tied(%$tlv)->isa("Net::OSCAR::TLV"); |
|
178
|
0
|
|
|
|
|
0
|
while (($type, $value) = each %$tlv) { |
|
179
|
0
|
|
0
|
|
|
0
|
$value ||= ""; |
|
180
|
0
|
|
|
|
|
0
|
$buffer .= pack("nna*", $type, length($value), $value); |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
} |
|
183
|
0
|
|
|
|
|
0
|
return $buffer; |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub send_error($$$$$;@) { |
|
187
|
0
|
|
|
0
|
0
|
0
|
my($oscar, $connection, $error, $desc, $fatal, @reqdata) = @_; |
|
188
|
0
|
|
|
|
|
0
|
$desc = sprintf $desc, @reqdata; |
|
189
|
0
|
|
|
|
|
0
|
$oscar->callback_error($connection, $error, $desc, $fatal); |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub bltie(;$) { |
|
193
|
2
|
|
|
2
|
0
|
4
|
my $retval = {}; |
|
194
|
2
|
|
|
|
|
12
|
tie %$retval, "Net::OSCAR::Buddylist", @_; |
|
195
|
2
|
|
|
|
|
4
|
return $retval; |
|
196
|
|
|
|
|
|
|
} |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
sub signon_tlv($;$$) { |
|
199
|
0
|
|
|
0
|
0
|
|
my($session, $password, $key) = @_; |
|
200
|
|
|
|
|
|
|
|
|
201
|
0
|
|
|
|
|
|
my %protodata = ( |
|
202
|
|
|
|
|
|
|
screenname => $session->{screenname}, |
|
203
|
|
|
|
|
|
|
clistr => $session->{svcdata}->{clistr}, |
|
204
|
|
|
|
|
|
|
supermajor => $session->{svcdata}->{supermajor}, |
|
205
|
|
|
|
|
|
|
major => $session->{svcdata}->{major}, |
|
206
|
|
|
|
|
|
|
minor => $session->{svcdata}->{minor}, |
|
207
|
|
|
|
|
|
|
subminor => $session->{svcdata}->{subminor}, |
|
208
|
|
|
|
|
|
|
build => $session->{svcdata}->{build}, |
|
209
|
|
|
|
|
|
|
subbuild => $session->{svcdata}->{subbuild}, |
|
210
|
|
|
|
|
|
|
); |
|
211
|
|
|
|
|
|
|
|
|
212
|
0
|
0
|
|
|
|
|
if($session->{svcdata}->{hashlogin}) { |
|
213
|
0
|
|
|
|
|
|
$protodata{password} = encode_password($session, $password); |
|
214
|
|
|
|
|
|
|
} else { |
|
215
|
0
|
0
|
|
|
|
|
if($session->{auth_response}) { |
|
216
|
0
|
|
|
|
|
|
$protodata{auth_response} = delete $session->{auth_response}; |
|
217
|
0
|
0
|
|
|
|
|
$protodata{pass_is_hashed} = "" if delete $session->{pass_is_hashed}; |
|
218
|
|
|
|
|
|
|
} else { |
|
219
|
|
|
|
|
|
|
# As of AIM 5.5, the password can be MD5'd before |
|
220
|
|
|
|
|
|
|
# going into the things-to-cat-together-and-MD5. |
|
221
|
|
|
|
|
|
|
# This lets applications that store AIM passwords |
|
222
|
|
|
|
|
|
|
# store the MD5'd password. We do it by default |
|
223
|
|
|
|
|
|
|
# because, well, AIM for Windows does. We support |
|
224
|
|
|
|
|
|
|
# the old way to preserve compatibility with |
|
225
|
|
|
|
|
|
|
# our auth_challenge/auth_response API. |
|
226
|
|
|
|
|
|
|
|
|
227
|
0
|
|
|
|
|
|
$protodata{pass_is_hashed} = ""; |
|
228
|
0
|
0
|
|
|
|
|
my $hashpass = $session->{pass_is_hashed} ? $password : md5($password); |
|
229
|
|
|
|
|
|
|
|
|
230
|
0
|
|
|
|
|
|
$protodata{auth_response} = encode_password($session, $hashpass, $key); |
|
231
|
|
|
|
|
|
|
} |
|
232
|
|
|
|
|
|
|
} |
|
233
|
|
|
|
|
|
|
|
|
234
|
0
|
|
|
|
|
|
return %protodata; |
|
235
|
|
|
|
|
|
|
} |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub encode_password($$;$) { |
|
238
|
0
|
|
|
0
|
0
|
|
my($session, $password, $key) = @_; |
|
239
|
|
|
|
|
|
|
|
|
240
|
0
|
0
|
|
|
|
|
if(!$session->{svcdata}->{hashlogin}) { # Use new SNAC-based method |
|
241
|
0
|
|
|
|
|
|
my $md5 = Digest::MD5->new; |
|
242
|
|
|
|
|
|
|
|
|
243
|
0
|
|
|
|
|
|
$md5->add($key); |
|
244
|
0
|
|
|
|
|
|
$md5->add($password); |
|
245
|
0
|
|
|
|
|
|
$md5->add("AOL Instant Messenger (SM)"); |
|
246
|
0
|
|
|
|
|
|
return $md5->digest(); |
|
247
|
|
|
|
|
|
|
} else { # Use old roasting method. Courtesy of SDiZ Cheng. |
|
248
|
0
|
|
|
|
|
|
my $ret = ""; |
|
249
|
0
|
|
|
|
|
|
my @pass = map {ord($_)} split(//, $password); |
|
|
0
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
|
|
251
|
0
|
|
|
|
|
|
my @encoding_table = map {hex($_)} qw( |
|
|
0
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
F3 26 81 C4 39 86 DB 92 71 A3 B9 E6 53 7A 95 7C |
|
253
|
|
|
|
|
|
|
); |
|
254
|
|
|
|
|
|
|
|
|
255
|
0
|
|
|
|
|
|
for(my $i = 0; $i < length($password); $i++) { |
|
256
|
0
|
|
|
|
|
|
$ret .= chr($pass[$i] ^ $encoding_table[$i]); |
|
257
|
|
|
|
|
|
|
} |
|
258
|
|
|
|
|
|
|
|
|
259
|
0
|
|
|
|
|
|
return $ret; |
|
260
|
|
|
|
|
|
|
} |
|
261
|
|
|
|
|
|
|
} |
|
262
|
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
sub send_versions($$;$) { |
|
264
|
0
|
|
|
0
|
0
|
|
my($connection, $send_tools, $server) = @_; |
|
265
|
0
|
|
|
|
|
|
my $conntype = $connection->{conntype}; |
|
266
|
0
|
|
|
|
|
|
my @services; |
|
267
|
|
|
|
|
|
|
|
|
268
|
0
|
0
|
0
|
|
|
|
if($conntype != CONNTYPE_BOS and !$server) { |
|
269
|
0
|
|
|
|
|
|
@services = (1, $conntype); |
|
270
|
|
|
|
|
|
|
} else { |
|
271
|
0
|
|
|
|
|
|
@services = sort {$b <=> $a} grep {not OSCAR_TOOLDATA()->{$_}->{nobos}} keys %{OSCAR_TOOLDATA()}; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
} |
|
273
|
|
|
|
|
|
|
|
|
274
|
0
|
|
|
|
|
|
my %protodata = (service => []); |
|
275
|
0
|
|
|
|
|
|
foreach my $service (@services) { |
|
276
|
0
|
|
|
|
|
|
my %service = ( |
|
277
|
|
|
|
|
|
|
service_id => $service, |
|
278
|
|
|
|
|
|
|
service_version => OSCAR_TOOLDATA->{$service}->{version} |
|
279
|
|
|
|
|
|
|
); |
|
280
|
0
|
0
|
|
|
|
|
if($send_tools) { |
|
281
|
0
|
|
|
|
|
|
$service{tool_id} = OSCAR_TOOLDATA->{$service}->{toolid}; |
|
282
|
0
|
|
|
|
|
|
$service{tool_version} = OSCAR_TOOLDATA->{$service}->{toolversion}; |
|
283
|
|
|
|
|
|
|
} |
|
284
|
|
|
|
|
|
|
|
|
285
|
0
|
|
|
|
|
|
push @{$protodata{service}}, \%service; |
|
|
0
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
} |
|
287
|
|
|
|
|
|
|
|
|
288
|
0
|
0
|
|
|
|
|
if($send_tools) { |
|
|
|
0
|
|
|
|
|
|
|
289
|
0
|
|
|
|
|
|
$connection->proto_send(protobit => "set_tool_versions", protodata => \%protodata, nopause => 1); |
|
290
|
|
|
|
|
|
|
} elsif($server) { |
|
291
|
0
|
|
|
|
|
|
$connection->proto_send(protobit => "host_versions", protodata => \%protodata, nopause => 1); |
|
292
|
|
|
|
|
|
|
} else { |
|
293
|
0
|
|
|
|
|
|
$connection->proto_send(protobit => "set_service_versions", protodata => \%protodata, nopause => 1); |
|
294
|
|
|
|
|
|
|
} |
|
295
|
|
|
|
|
|
|
} |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# keys(%foo) in void context, the standard way of reseting |
|
298
|
|
|
|
|
|
|
# a hash iterator, appears to leak memory. |
|
299
|
|
|
|
|
|
|
# |
|
300
|
|
|
|
|
|
|
sub hash_iter_reset($) { |
|
301
|
0
|
|
|
0
|
0
|
|
while((undef, undef) = each(%{$_[0]})) {} |
|
|
0
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
} |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
1; |