line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
############################################################################### |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# This library is free software; you can redistribute it and/or |
4
|
|
|
|
|
|
|
# modify it under the terms of the GNU Library General Public |
5
|
|
|
|
|
|
|
# License as published by the Free Software Foundation; either |
6
|
|
|
|
|
|
|
# version 2 of the License, or (at your option) any later version. |
7
|
|
|
|
|
|
|
# |
8
|
|
|
|
|
|
|
# This library is distributed in the hope that it will be useful, |
9
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
10
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
11
|
|
|
|
|
|
|
# Library General Public License for more details. |
12
|
|
|
|
|
|
|
# |
13
|
|
|
|
|
|
|
# You should have received a copy of the GNU Library General Public |
14
|
|
|
|
|
|
|
# License along with this library; if not, write to the |
15
|
|
|
|
|
|
|
# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
16
|
|
|
|
|
|
|
# Boston, MA 02111-1307, USA. |
17
|
|
|
|
|
|
|
# |
18
|
|
|
|
|
|
|
# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/ |
19
|
|
|
|
|
|
|
# |
20
|
|
|
|
|
|
|
############################################################################### |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
package Net::XMPP3; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 NAME |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
Net::XMPP3 - XMPP Perl Library |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=head1 SYNOPSIS |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
Net::XMPP3 provides a Perl user with access to the Extensible |
31
|
|
|
|
|
|
|
Messaging and Presence Protocol (XMPP). |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
For more information about XMPP visit: |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
http://www.xmpp.org |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head1 DESCRIPTION |
38
|
|
|
|
|
|
|
This is a little modified version of Net::XMPP, with fixed one bug, for correctly |
39
|
|
|
|
|
|
|
works with ejabber servers. I do this, because author of Net::XMPP not available |
40
|
|
|
|
|
|
|
from 2007 year. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
Net::XMPP3 is a convenient tool to use for any perl script that would |
44
|
|
|
|
|
|
|
like to utilize the XMPP Instant Messaging protocol. While not a |
45
|
|
|
|
|
|
|
client in and of itself, it provides all of the necessary back-end |
46
|
|
|
|
|
|
|
functions to make a CGI client or command-line perl client feasible |
47
|
|
|
|
|
|
|
and easy to use. Net::XMPP3 is a wrapper around the rest of the |
48
|
|
|
|
|
|
|
official Net::XMPP3::xxxxxx packages. |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
There is are example scripts in the example directory that provide you |
51
|
|
|
|
|
|
|
with examples of very simple XMPP programs. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
NOTE: The parser that XML::Stream::Parser provides, as are most Perl |
55
|
|
|
|
|
|
|
parsers, is synchronous. If you are in the middle of parsing a packet |
56
|
|
|
|
|
|
|
and call a user defined callback, the Parser is blocked until your |
57
|
|
|
|
|
|
|
callback finishes. This means you cannot be operating on a packet, |
58
|
|
|
|
|
|
|
send out another packet and wait for a response to that packet. It |
59
|
|
|
|
|
|
|
will never get to you. Threading might solve this, but as of this |
60
|
|
|
|
|
|
|
writing threading in Perl is not quite up to par yet. This issue will |
61
|
|
|
|
|
|
|
be revisted in the future. |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=head1 EXAMPLES |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
use Net::XMPP3; |
67
|
|
|
|
|
|
|
my $client = new Net::XMPP3::Client(); |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=head1 METHODS |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
The Net::XMPP3 module does not define any methods that you will call |
72
|
|
|
|
|
|
|
directly in your code. Instead you will instantiate objects that call |
73
|
|
|
|
|
|
|
functions from this module to do work. The three main objects that |
74
|
|
|
|
|
|
|
you will work with are the Message, Presence, and IQ modules. Each one |
75
|
|
|
|
|
|
|
corresponds to the Jabber equivilant and allows you get and set all |
76
|
|
|
|
|
|
|
parts of those packets. |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
There are a few functions that are the same across all of the objects: |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=head2 Retrieval functions |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
GetXML() - returns the XML string that represents the data contained |
83
|
|
|
|
|
|
|
in the object. |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
$xml = $obj->GetXML(); |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
GetChild() - returns an array of Net::XMPP3::Stanza objects |
88
|
|
|
|
|
|
|
GetChild(namespace) that represent all of the stanzas in the object |
89
|
|
|
|
|
|
|
that are namespaced. If you specify a namespace |
90
|
|
|
|
|
|
|
then only stanza objects with that XMLNS are |
91
|
|
|
|
|
|
|
returned. |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
@xObj = $obj->GetChild(); |
94
|
|
|
|
|
|
|
@xObj = $obj->GetChild("my:namespace"); |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
GetTag() - return the root tag name of the packet. |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
GetTree() - return the XML::Stream::Node object that contains the data. |
99
|
|
|
|
|
|
|
See XML::Stream::Node for methods you can call on this |
100
|
|
|
|
|
|
|
object. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=head2 Creation functions |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
NewChild(namespace) - creates a new Net::XMPP3::Stanza object with |
105
|
|
|
|
|
|
|
NewChild(namespace,tag) the specified namespace and root tag of |
106
|
|
|
|
|
|
|
whatever the namespace says its root tag |
107
|
|
|
|
|
|
|
should be. Optionally you may specify |
108
|
|
|
|
|
|
|
another root tag if the default is not |
109
|
|
|
|
|
|
|
desired, or the namespace requres you to set |
110
|
|
|
|
|
|
|
one. |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
$xObj = $obj->NewChild("my:namespace"); |
113
|
|
|
|
|
|
|
$xObj = $obj->NewChild("my:namespace","foo"); |
114
|
|
|
|
|
|
|
ie. |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
InsertRawXML(string) - puts the specified string raw into the XML |
117
|
|
|
|
|
|
|
packet that you call this on. |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
$message->InsertRawXML("") |
120
|
|
|
|
|
|
|
... |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
$x = $message->NewChild(..); |
123
|
|
|
|
|
|
|
$x->InsertRawXML("test"); |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
$query = $iq->GetChild(..); |
126
|
|
|
|
|
|
|
$query->InsertRawXML("test"); |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
ClearRawXML() - removes the raw XML from the packet. |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=head2 Removal functions |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
RemoveChild() - removes all of the namespaces child elements |
133
|
|
|
|
|
|
|
RemoveChild(namespace) from the object. If a namespace is provided, |
134
|
|
|
|
|
|
|
then only the children with that namespace are |
135
|
|
|
|
|
|
|
removed. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=head2 Test functions |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
DefinedChild() - returns 1 if there are any known namespaced |
140
|
|
|
|
|
|
|
DefinedChild(namespace) stanzas in the packet, 0 otherwise. |
141
|
|
|
|
|
|
|
Optionally you can specify a namespace and |
142
|
|
|
|
|
|
|
determine if there are any stanzas with that |
143
|
|
|
|
|
|
|
namespace. |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
$test = $obj->DefinedChild(); |
146
|
|
|
|
|
|
|
$test = $obj->DefinedChild("my:namespace"); |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=head1 PACKAGES |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
For more information on each of these packages, please see the man page |
151
|
|
|
|
|
|
|
for each one. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=head2 Net::XMPP3::Client |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
This package contains the code needed to communicate with an XMPP |
156
|
|
|
|
|
|
|
server: login, wait for messages, send messages, and logout. It uses |
157
|
|
|
|
|
|
|
XML::Stream to read the stream from the server and based on what kind |
158
|
|
|
|
|
|
|
of tag it encounters it calls a function to handle the tag. |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=head2 Net::XMPP3::Protocol |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
A collection of high-level functions that Client uses to make their |
163
|
|
|
|
|
|
|
lives easier. These methods are inherited by the Client. |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head2 Net::XMPP3::JID |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
The XMPP IDs consist of three parts: user id, server, and resource. |
168
|
|
|
|
|
|
|
This module gives you access to those components without having to |
169
|
|
|
|
|
|
|
parse the string yourself. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=head2 Net::XMPP3::Message |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
Everything needed to create and read a received from the |
174
|
|
|
|
|
|
|
server. |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
=head2 Net::XMPP3::Presence |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
Everything needed to create and read a received from the |
179
|
|
|
|
|
|
|
server. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=head2 Net::XMPP3::IQ |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
IQ is a wrapper around a number of modules that provide support for |
184
|
|
|
|
|
|
|
the various Info/Query namespaces that XMPP recognizes. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=head2 Net::XMPP3::Stanza |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
This module represents a namespaced stanza that is used to extend a |
189
|
|
|
|
|
|
|
, , and . |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
The man page for Net::XMPP3::Stanza contains a listing of all supported |
192
|
|
|
|
|
|
|
namespaces, and the methods that are supported by the objects that |
193
|
|
|
|
|
|
|
represent those namespaces. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head2 Net::XMPP3::Namespaces |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
XMPP allows for any stanza to be extended by any bit of XML. This |
198
|
|
|
|
|
|
|
module contains all of the internals for defining the XMPP based |
199
|
|
|
|
|
|
|
extensions defined by the IETF. The documentation for this module |
200
|
|
|
|
|
|
|
explains more about how to add your own custom namespace and have it |
201
|
|
|
|
|
|
|
be supported. |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=head1 AUTHOR |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
Ryan Eatmon |
206
|
|
|
|
|
|
|
Currently maintained by Eric Hacker. |
207
|
|
|
|
|
|
|
Currently fixed by Guruperl. |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=head1 BUGS |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
Probably. There is at least one issue with XLM::Stream providing different node |
212
|
|
|
|
|
|
|
structures depending on how the node is created. Net::XMPP3 should now be able to |
213
|
|
|
|
|
|
|
handle this, but who knows what else lurks. |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=head1 COPYRIGHT |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
This module is free software, you can redistribute it and/or modify it |
218
|
|
|
|
|
|
|
under the LGPL. |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=cut |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
require 5.005; |
223
|
11
|
|
|
11
|
|
204075
|
use strict; |
|
11
|
|
|
|
|
28
|
|
|
11
|
|
|
|
|
476
|
|
224
|
11
|
|
|
11
|
|
21358
|
use XML::Stream 1.22 qw( Node ); |
|
11
|
|
|
|
|
1414342
|
|
|
11
|
|
|
|
|
101
|
|
225
|
11
|
|
|
11
|
|
15649
|
use Time::Local; |
|
11
|
|
|
|
|
21027
|
|
|
11
|
|
|
|
|
793
|
|
226
|
11
|
|
|
11
|
|
76
|
use Carp; |
|
11
|
|
|
|
|
19
|
|
|
11
|
|
|
|
|
540
|
|
227
|
11
|
|
|
11
|
|
8754
|
use Digest::SHA1; |
|
11
|
|
|
|
|
11970
|
|
|
11
|
|
|
|
|
529
|
|
228
|
11
|
|
|
11
|
|
76
|
use Authen::SASL; |
|
11
|
|
|
|
|
20
|
|
|
11
|
|
|
|
|
108
|
|
229
|
11
|
|
|
11
|
|
244
|
use MIME::Base64; |
|
11
|
|
|
|
|
19
|
|
|
11
|
|
|
|
|
560
|
|
230
|
11
|
|
|
11
|
|
57
|
use POSIX; |
|
11
|
|
|
|
|
15
|
|
|
11
|
|
|
|
|
101
|
|
231
|
11
|
|
|
11
|
|
38688
|
use vars qw( $AUTOLOAD $VERSION $PARSING ); |
|
11
|
|
|
|
|
23
|
|
|
11
|
|
|
|
|
816
|
|
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
$VERSION = "1.02"; |
234
|
|
|
|
|
|
|
|
235
|
11
|
|
|
11
|
|
8250
|
use Net::XMPP3::Debug; |
|
11
|
|
|
|
|
29
|
|
|
11
|
|
|
|
|
343
|
|
236
|
11
|
|
|
11
|
|
8501
|
use Net::XMPP3::JID; |
|
11
|
|
|
|
|
29
|
|
|
11
|
|
|
|
|
334
|
|
237
|
11
|
|
|
11
|
|
7922
|
use Net::XMPP3::Namespaces; |
|
11
|
|
|
|
|
30
|
|
|
11
|
|
|
|
|
555
|
|
238
|
11
|
|
|
11
|
|
9967
|
use Net::XMPP3::Stanza; |
|
11
|
|
|
|
|
37
|
|
|
11
|
|
|
|
|
356
|
|
239
|
11
|
|
|
11
|
|
8368
|
use Net::XMPP3::Message; |
|
11
|
|
|
|
|
35
|
|
|
11
|
|
|
|
|
297
|
|
240
|
11
|
|
|
11
|
|
8662
|
use Net::XMPP3::IQ; |
|
11
|
|
|
|
|
29
|
|
|
11
|
|
|
|
|
287
|
|
241
|
11
|
|
|
11
|
|
7444
|
use Net::XMPP3::Presence; |
|
11
|
|
|
|
|
31
|
|
|
11
|
|
|
|
|
384
|
|
242
|
11
|
|
|
11
|
|
14728
|
use Net::XMPP3::Protocol; |
|
11
|
|
|
|
|
52
|
|
|
11
|
|
|
|
|
472
|
|
243
|
11
|
|
|
11
|
|
8810
|
use Net::XMPP3::Client; |
|
11
|
|
|
|
|
45
|
|
|
11
|
|
|
|
|
10230
|
|
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
############################################################################## |
247
|
|
|
|
|
|
|
# |
248
|
|
|
|
|
|
|
# printData - debugging function to print out any data structure in an |
249
|
|
|
|
|
|
|
# organized manner. Very useful for debugging XML::Parser::Tree |
250
|
|
|
|
|
|
|
# objects. This is a private function that will only exist in |
251
|
|
|
|
|
|
|
# in the development version. |
252
|
|
|
|
|
|
|
# |
253
|
|
|
|
|
|
|
############################################################################## |
254
|
|
|
|
|
|
|
sub printData |
255
|
|
|
|
|
|
|
{ |
256
|
0
|
|
|
0
|
0
|
0
|
print &sprintData(@_); |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
############################################################################## |
261
|
|
|
|
|
|
|
# |
262
|
|
|
|
|
|
|
# sprintData - debugging function to build a string out of any data structure |
263
|
|
|
|
|
|
|
# in an organized manner. Very useful for debugging |
264
|
|
|
|
|
|
|
# XML::Parser::Tree objects and perl hashes of hashes. |
265
|
|
|
|
|
|
|
# |
266
|
|
|
|
|
|
|
# This is a private function. |
267
|
|
|
|
|
|
|
# |
268
|
|
|
|
|
|
|
############################################################################## |
269
|
|
|
|
|
|
|
sub sprintData |
270
|
|
|
|
|
|
|
{ |
271
|
0
|
|
|
0
|
0
|
0
|
return &XML::Stream::sprintData(@_); |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
############################################################################## |
276
|
|
|
|
|
|
|
# |
277
|
|
|
|
|
|
|
# GetTimeStamp - generic funcion for getting a timestamp. |
278
|
|
|
|
|
|
|
# |
279
|
|
|
|
|
|
|
############################################################################## |
280
|
|
|
|
|
|
|
sub GetTimeStamp |
281
|
|
|
|
|
|
|
{ |
282
|
4
|
|
|
4
|
0
|
10
|
my($type,$time,$length) = @_; |
283
|
|
|
|
|
|
|
|
284
|
4
|
0
|
33
|
|
|
21
|
return "" if (($type ne "local") && ($type ne "utc") && !($type =~ /^(local|utc)delay(local|utc|time)$/)); |
|
|
|
33
|
|
|
|
|
285
|
|
|
|
|
|
|
|
286
|
4
|
50
|
|
|
|
17
|
$length = "long" unless defined($length); |
287
|
|
|
|
|
|
|
|
288
|
4
|
|
|
|
|
11
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday); |
289
|
4
|
50
|
|
|
|
15
|
if ($type =~ /utcdelay/) |
290
|
|
|
|
|
|
|
{ |
291
|
0
|
|
|
|
|
0
|
($year,$mon,$mday,$hour,$min,$sec) = ($time =~ /^(\d\d\d\d)(\d\d)(\d\d)T(\d\d)\:(\d\d)\:(\d\d)$/); |
292
|
0
|
|
|
|
|
0
|
$mon--; |
293
|
0
|
|
|
|
|
0
|
($type) = ($type =~ /^utcdelay(.*)$/); |
294
|
0
|
|
|
|
|
0
|
$time = timegm($sec,$min,$hour,$mday,$mon,$year); |
295
|
|
|
|
|
|
|
} |
296
|
4
|
50
|
|
|
|
14
|
if ($type =~ /localdelay/) |
297
|
|
|
|
|
|
|
{ |
298
|
0
|
|
|
|
|
0
|
($year,$mon,$mday,$hour,$min,$sec) = ($time =~ /^(\d\d\d\d)(\d\d)(\d\d)T(\d\d)\:(\d\d)\:(\d\d)$/); |
299
|
0
|
|
|
|
|
0
|
$mon--; |
300
|
0
|
|
|
|
|
0
|
($type) = ($type =~ /^localdelay(.*)$/); |
301
|
0
|
|
|
|
|
0
|
$time = timelocal($sec,$min,$hour,$mday,$mon,$year); |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
|
304
|
4
|
50
|
|
|
|
20
|
return $time if ($type eq "time"); |
305
|
4
|
50
|
33
|
|
|
218
|
($sec,$min,$hour,$mday,$mon,$year,$wday) = |
|
|
50
|
|
|
|
|
|
306
|
|
|
|
|
|
|
localtime(((defined($time) && ($time ne "")) ? $time : time)) if ($type eq "local"); |
307
|
4
|
0
|
0
|
|
|
19
|
($sec,$min,$hour,$mday,$mon,$year,$wday) = |
|
|
50
|
|
|
|
|
|
308
|
|
|
|
|
|
|
gmtime(((defined($time) && ($time ne "")) ? $time : time)) if ($type eq "utc"); |
309
|
|
|
|
|
|
|
|
310
|
4
|
50
|
|
|
|
14
|
return sprintf("%d%02d%02dT%02d:%02d:%02d",($year + 1900),($mon+1),$mday,$hour,$min,$sec) if ($length eq "stamp"); |
311
|
|
|
|
|
|
|
|
312
|
4
|
|
|
|
|
14
|
$wday = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[$wday]; |
313
|
|
|
|
|
|
|
|
314
|
4
|
|
|
|
|
13
|
my $month = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')[$mon]; |
315
|
4
|
|
|
|
|
8
|
$mon++; |
316
|
|
|
|
|
|
|
|
317
|
4
|
50
|
|
|
|
63
|
return sprintf("%3s %3s %02d, %d %02d:%02d:%02d",$wday,$month,$mday,($year + 1900),$hour,$min,$sec) if ($length eq "long"); |
318
|
0
|
0
|
|
|
|
|
return sprintf("%3s %d/%02d/%02d %02d:%02d",$wday,($year + 1900),$mon,$mday,$hour,$min) if ($length eq "normal"); |
319
|
0
|
0
|
|
|
|
|
return sprintf("%02d:%02d:%02d",$hour,$min,$sec) if ($length eq "short"); |
320
|
0
|
0
|
|
|
|
|
return sprintf("%02d:%02d",$hour,$min) if ($length eq "shortest"); |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
############################################################################## |
325
|
|
|
|
|
|
|
# |
326
|
|
|
|
|
|
|
# GetHumanTime - convert seconds, into a human readable time string. |
327
|
|
|
|
|
|
|
# |
328
|
|
|
|
|
|
|
############################################################################## |
329
|
|
|
|
|
|
|
sub GetHumanTime |
330
|
|
|
|
|
|
|
{ |
331
|
0
|
|
|
0
|
0
|
|
my $seconds = shift; |
332
|
|
|
|
|
|
|
|
333
|
0
|
|
|
|
|
|
my $minutes = 0; |
334
|
0
|
|
|
|
|
|
my $hours = 0; |
335
|
0
|
|
|
|
|
|
my $days = 0; |
336
|
0
|
|
|
|
|
|
my $weeks = 0; |
337
|
|
|
|
|
|
|
|
338
|
0
|
|
|
|
|
|
while ($seconds >= 60) { |
339
|
0
|
|
|
|
|
|
$minutes++; |
340
|
0
|
0
|
|
|
|
|
if ($minutes == 60) { |
341
|
0
|
|
|
|
|
|
$hours++; |
342
|
0
|
0
|
|
|
|
|
if ($hours == 24) { |
343
|
0
|
|
|
|
|
|
$days++; |
344
|
0
|
0
|
|
|
|
|
if ($days == 7) { |
345
|
0
|
|
|
|
|
|
$weeks++; |
346
|
0
|
|
|
|
|
|
$days -= 7; |
347
|
|
|
|
|
|
|
} |
348
|
0
|
|
|
|
|
|
$hours -= 24; |
349
|
|
|
|
|
|
|
} |
350
|
0
|
|
|
|
|
|
$minutes -= 60; |
351
|
|
|
|
|
|
|
} |
352
|
0
|
|
|
|
|
|
$seconds -= 60; |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
|
355
|
0
|
|
|
|
|
|
my $humanTime; |
356
|
0
|
0
|
|
|
|
|
$humanTime .= "$weeks week " if ($weeks == 1); |
357
|
0
|
0
|
|
|
|
|
$humanTime .= "$weeks weeks " if ($weeks > 1); |
358
|
0
|
0
|
|
|
|
|
$humanTime .= "$days day " if ($days == 1); |
359
|
0
|
0
|
|
|
|
|
$humanTime .= "$days days " if ($days > 1); |
360
|
0
|
0
|
|
|
|
|
$humanTime .= "$hours hour " if ($hours == 1); |
361
|
0
|
0
|
|
|
|
|
$humanTime .= "$hours hours " if ($hours > 1); |
362
|
0
|
0
|
|
|
|
|
$humanTime .= "$minutes minute " if ($minutes == 1); |
363
|
0
|
0
|
|
|
|
|
$humanTime .= "$minutes minutes " if ($minutes > 1); |
364
|
0
|
0
|
|
|
|
|
$humanTime .= "$seconds second " if ($seconds == 1); |
365
|
0
|
0
|
|
|
|
|
$humanTime .= "$seconds seconds " if ($seconds > 1); |
366
|
|
|
|
|
|
|
|
367
|
0
|
0
|
|
|
|
|
$humanTime = "none" if ($humanTime eq ""); |
368
|
|
|
|
|
|
|
|
369
|
0
|
|
|
|
|
|
return $humanTime; |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
1; |