line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# WebService::UWO::Directory::Student
|
2
|
|
|
|
|
|
|
# Retrieve student information from the Western Student Directory
|
3
|
|
|
|
|
|
|
#
|
4
|
|
|
|
|
|
|
# $Id: Student.pm 10608 2009-12-23 16:06:17Z FREQUENCY@cpan.org $
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package WebService::UWO::Directory::Student;
|
7
|
|
|
|
|
|
|
|
8
|
4
|
|
|
4
|
|
95498
|
use strict;
|
|
4
|
|
|
|
|
12
|
|
|
4
|
|
|
|
|
146
|
|
9
|
4
|
|
|
4
|
|
25
|
use warnings;
|
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
103
|
|
10
|
4
|
|
|
4
|
|
23
|
use Carp ();
|
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
91
|
|
11
|
|
|
|
|
|
|
|
12
|
4
|
|
|
4
|
|
4449
|
use LWP::UserAgent;
|
|
4
|
|
|
|
|
268893
|
|
|
4
|
|
|
|
|
147
|
|
13
|
4
|
|
|
4
|
|
15163
|
use HTML::Entities ();
|
|
4
|
|
|
|
|
527212
|
|
|
4
|
|
|
|
|
5276
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 NAME
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
WebService::UWO::Directory::Student - Perl module for searching the UWO
|
18
|
|
|
|
|
|
|
student directory
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 VERSION
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
Version 1.004 ($Id: Student.pm 10608 2009-12-23 16:06:17Z FREQUENCY@cpan.org $)
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=cut
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
our $VERSION = '1.004';
|
27
|
|
|
|
|
|
|
$VERSION = eval $VERSION;
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
This module provides a Perl interface to the public directory search system
|
32
|
|
|
|
|
|
|
which lists current students at the University of Western Ontario. For more
|
33
|
|
|
|
|
|
|
information, see the web interface at L.
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
Example code:
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
use WebService::UWO::Directory::Student;
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# Create Perl interface to API
|
42
|
|
|
|
|
|
|
my $dir = WebService::UWO::Directory::Student->new;
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# Look up a student by name
|
45
|
|
|
|
|
|
|
my $results = $dir->lookup({
|
46
|
|
|
|
|
|
|
first => 'John',
|
47
|
|
|
|
|
|
|
last => 'S'
|
48
|
|
|
|
|
|
|
});
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Go through results
|
51
|
|
|
|
|
|
|
foreach my $stu (@{$results}) {
|
52
|
|
|
|
|
|
|
print 'email: ' . $stu->email . "\n";
|
53
|
|
|
|
|
|
|
}
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# Reverse a lookup (use e-mail to find record)
|
56
|
|
|
|
|
|
|
my $reverse = $dir->lookup({
|
57
|
|
|
|
|
|
|
email => 'jsmith@uwo.ca'
|
58
|
|
|
|
|
|
|
});
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
if (defined $reverse) {
|
61
|
|
|
|
|
|
|
print "Found: $reverse\n";
|
62
|
|
|
|
|
|
|
}
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=head1 COMPATIBILITY
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
This module was tested under Perl 5.10.0, using Debian Linux. However, because
|
67
|
|
|
|
|
|
|
it's Pure Perl and doesn't do anything too obscure, it should be compatible
|
68
|
|
|
|
|
|
|
with any version of Perl that supports its prerequisite modules.
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
If you encounter any problems on a different version or architecture, please
|
71
|
|
|
|
|
|
|
contact the maintainer.
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=head1 METHODS
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=head2 new
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
WebService::UWO::Directory::Student->new( \%params )
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
Creates a C search object, which uses a given web page
|
80
|
|
|
|
|
|
|
and server. Being that this module is developed to target UWO's in-house
|
81
|
|
|
|
|
|
|
system, the defaults should suffice.
|
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
The parameters available are:
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
my $dir = UWO::Directory::Student->new({
|
86
|
|
|
|
|
|
|
url => 'http://uwo.ca/cgi-bin/dsgw/whois2html2',
|
87
|
|
|
|
|
|
|
server => 'localhost',
|
88
|
|
|
|
|
|
|
});
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
Which instantiates a C instance using C as the
|
91
|
|
|
|
|
|
|
frontend and C as the "black-box" backend.
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=cut
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub new {
|
96
|
1
|
|
|
1
|
1
|
2858
|
my ($class, $params) = @_;
|
97
|
|
|
|
|
|
|
|
98
|
1
|
|
50
|
|
|
18
|
my $self = {
|
|
|
|
50
|
|
|
|
|
99
|
|
|
|
|
|
|
url => $params->{url} || 'http://uwo.ca/cgi-bin/dsgw/whois2html2',
|
100
|
|
|
|
|
|
|
server => $params->{server} || 'localhost',
|
101
|
|
|
|
|
|
|
};
|
102
|
|
|
|
|
|
|
|
103
|
1
|
|
|
|
|
6
|
return bless($self, $class);
|
104
|
|
|
|
|
|
|
}
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=head2 lookup
|
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
$dir->lookup( \%params )
|
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
Uses a C search object to locate a given
|
111
|
|
|
|
|
|
|
person based on either their name (C and/or C) or their e-mail
|
112
|
|
|
|
|
|
|
address (C).
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
The module uses the following procedure to locate users:
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=over
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=item 1
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
If an e-mail address is provided:
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=over
|
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=item 1
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
The address is deconstructed into a first initial and the portion of the last
|
127
|
|
|
|
|
|
|
name. (According to the regular expression C<^(\w)([^\d]+)([\d]*)$>)
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=item 2
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
The partial name is looked up in the directory.
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=item 3
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
The resulting records are tested against the e-mail address. If the e-mail
|
136
|
|
|
|
|
|
|
address matches a given record, an anonymous hash containing user information
|
137
|
|
|
|
|
|
|
is returned. The lookup returns a false value (0) upon failure.
|
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=back
|
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=item 2
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
If first and/or last names are provided:
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=over
|
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=item 1
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
The name is searched using the normal interface (using the query
|
150
|
|
|
|
|
|
|
C) and the results are returned as an array reference.
|
151
|
|
|
|
|
|
|
If there are no results, the method returns a false value (0).
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=back
|
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=back
|
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Example code:
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# Look up "John S" in the student directory
|
160
|
|
|
|
|
|
|
my $results = $dir->lookup({
|
161
|
|
|
|
|
|
|
first => 'John',
|
162
|
|
|
|
|
|
|
last => 'S'
|
163
|
|
|
|
|
|
|
});
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
# Look up jsmith@uwo.ca
|
166
|
|
|
|
|
|
|
my $reverse = $dir->lookup({
|
167
|
|
|
|
|
|
|
email => 'jsmith@uwo.ca'
|
168
|
|
|
|
|
|
|
});
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
This method is not guaranteed to return results. Keep in mind that if no
|
171
|
|
|
|
|
|
|
results are found, the return code will be 0, so make sure to check return
|
172
|
|
|
|
|
|
|
codes before attempting to dereference the expected array/hash.
|
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=head3 Record Format
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Each returned record will be a hash with the following fields:
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=over
|
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=item *
|
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
last_name,
|
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=item *
|
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
given_name (which may contain middle names)
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=item *
|
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
email (the registered @uwo.ca e-mail address)
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=item *
|
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
faculty
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=back
|
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
You may explore this using C.
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=cut
|
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub lookup {
|
203
|
0
|
|
|
0
|
1
|
0
|
my ($self, $params) = @_;
|
204
|
|
|
|
|
|
|
|
205
|
0
|
0
|
|
|
|
0
|
Carp::croak('You must call this method as an object')
|
206
|
|
|
|
|
|
|
unless ref $self;
|
207
|
|
|
|
|
|
|
|
208
|
0
|
0
|
|
|
|
0
|
Carp::croak('Parameter not a hash reference')
|
209
|
|
|
|
|
|
|
unless ref($params) eq 'HASH';
|
210
|
|
|
|
|
|
|
|
211
|
0
|
0
|
0
|
|
|
0
|
Carp::croak('No search parameters provided')
|
|
|
|
0
|
|
|
|
|
212
|
|
|
|
|
|
|
unless(
|
213
|
|
|
|
|
|
|
exists($params->{first}) ||
|
214
|
|
|
|
|
|
|
exists($params->{last}) ||
|
215
|
|
|
|
|
|
|
exists($params->{email})
|
216
|
|
|
|
|
|
|
);
|
217
|
|
|
|
|
|
|
|
218
|
0
|
0
|
|
|
|
0
|
$params->{first} = '' unless defined($params->{first});
|
219
|
0
|
0
|
|
|
|
0
|
$params->{last} = '' unless defined($params->{last});
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# Don't do anything in void context
|
222
|
0
|
0
|
|
|
|
0
|
unless (defined wantarray) {
|
223
|
0
|
|
|
|
|
0
|
Carp::carp('Output from function discarded');
|
224
|
0
|
|
|
|
|
0
|
return;
|
225
|
|
|
|
|
|
|
}
|
226
|
|
|
|
|
|
|
|
227
|
0
|
0
|
|
|
|
0
|
if (exists $params->{email}) {
|
228
|
0
|
|
|
|
|
0
|
my $query;
|
229
|
0
|
0
|
|
|
|
0
|
if ($params->{email} =~ /^(\w+)(\@uwo\.ca)?$/s) {
|
230
|
0
|
|
|
|
|
0
|
$query = $1;
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
# no domain provided, assume @uwo.ca for matching
|
233
|
0
|
0
|
|
|
|
0
|
if (!defined($2)) {
|
234
|
|
|
|
|
|
|
# This is intentionally not interpolated
|
235
|
|
|
|
|
|
|
## no critic(RequireInterpolationOfMetachars)
|
236
|
0
|
|
|
|
|
0
|
$params->{email} .= '@uwo.ca';
|
237
|
|
|
|
|
|
|
}
|
238
|
|
|
|
|
|
|
}
|
239
|
|
|
|
|
|
|
else {
|
240
|
0
|
|
|
|
|
0
|
Carp::croak('Only UWO usernames and addresses can be searched');
|
241
|
|
|
|
|
|
|
}
|
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
# Discover query by deconstructing the username
|
244
|
|
|
|
|
|
|
# jdoe32
|
245
|
|
|
|
|
|
|
# First name: j
|
246
|
|
|
|
|
|
|
# Last name: doe
|
247
|
|
|
|
|
|
|
# E-mail: jdoe32@uwo.ca
|
248
|
0
|
0
|
|
|
|
0
|
if ($query =~ /^(\w)([^\d]+)([\d]*)$/s) {
|
249
|
0
|
|
|
|
|
0
|
my $result = $self->lookup({
|
250
|
|
|
|
|
|
|
first => $1,
|
251
|
|
|
|
|
|
|
last => $2,
|
252
|
|
|
|
|
|
|
});
|
253
|
0
|
|
|
|
|
0
|
foreach my $stu (@{$result}) {
|
|
0
|
|
|
|
|
0
|
|
254
|
0
|
0
|
|
|
|
0
|
return $stu if ($stu->{email} eq $params->{email});
|
255
|
|
|
|
|
|
|
}
|
256
|
|
|
|
|
|
|
}
|
257
|
|
|
|
|
|
|
else {
|
258
|
0
|
|
|
|
|
0
|
Carp::croak('Given username does not match UWO username pattern');
|
259
|
|
|
|
|
|
|
}
|
260
|
|
|
|
|
|
|
}
|
261
|
|
|
|
|
|
|
else {
|
262
|
0
|
|
|
|
|
0
|
my $query;
|
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# If both first and last are given
|
265
|
0
|
0
|
0
|
|
|
0
|
if (length $params->{first} && length $params->{last}) {
|
|
|
0
|
|
|
|
|
|
266
|
0
|
|
|
|
|
0
|
$query = $params->{last} . ',' . $params->{first};
|
267
|
|
|
|
|
|
|
}
|
268
|
|
|
|
|
|
|
# First name only
|
269
|
|
|
|
|
|
|
elsif (length $params->{first}) {
|
270
|
0
|
|
|
|
|
0
|
$query = $params->{first} . '.';
|
271
|
|
|
|
|
|
|
}
|
272
|
|
|
|
|
|
|
# Last name only
|
273
|
|
|
|
|
|
|
else {
|
274
|
0
|
|
|
|
|
0
|
$query = $params->{last} . ',';
|
275
|
|
|
|
|
|
|
}
|
276
|
|
|
|
|
|
|
|
277
|
0
|
|
|
|
|
0
|
return _parse($self->_query($query));
|
278
|
|
|
|
|
|
|
}
|
279
|
0
|
|
|
|
|
0
|
return 0;
|
280
|
|
|
|
|
|
|
}
|
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=head1 UNSUPPORTED API
|
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
C provides access to some internal
|
285
|
|
|
|
|
|
|
methods used to retrieve and process raw data from the directory server. Its
|
286
|
|
|
|
|
|
|
behaviour is subject to change and may be finalized later as the need arises.
|
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=head2 _query
|
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
$dir->_query( $query, $ua )
|
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
This method performs an HTTP lookup using C and returns a
|
293
|
|
|
|
|
|
|
SCALAR reference to the returned page content. A C object may
|
294
|
|
|
|
|
|
|
optionally be passed, which is particularly useful if a proxy is required to
|
295
|
|
|
|
|
|
|
access the Internet.
|
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
Please note that if a C is passed, the User-Agent string will
|
298
|
|
|
|
|
|
|
not be modified. In normal operation, this module reports its user agent as
|
299
|
|
|
|
|
|
|
C<'WebService::UWO::Directory::Student/' . $VERSION>.
|
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
=cut
|
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
sub _query {
|
304
|
0
|
|
|
0
|
|
0
|
my ($self, $query, $ua) = @_;
|
305
|
|
|
|
|
|
|
|
306
|
0
|
0
|
|
|
|
0
|
Carp::croak('You must call this method as an object') unless ref($self);
|
307
|
|
|
|
|
|
|
|
308
|
0
|
0
|
|
|
|
0
|
if (!defined $ua) {
|
309
|
0
|
|
|
|
|
0
|
$ua = LWP::UserAgent->new;
|
310
|
0
|
|
|
|
|
0
|
$ua->agent(__PACKAGE__ . '/' . $VERSION);
|
311
|
|
|
|
|
|
|
}
|
312
|
|
|
|
|
|
|
|
313
|
0
|
|
|
|
|
0
|
my $r = $ua->post($self->{'url'},
|
314
|
|
|
|
|
|
|
{
|
315
|
|
|
|
|
|
|
server => $self->{'server'},
|
316
|
|
|
|
|
|
|
query => $query,
|
317
|
|
|
|
|
|
|
});
|
318
|
|
|
|
|
|
|
|
319
|
0
|
0
|
|
|
|
0
|
Carp::croak('Error reading response: ' . $r->status_line)
|
320
|
|
|
|
|
|
|
unless $r->is_success;
|
321
|
|
|
|
|
|
|
|
322
|
0
|
|
|
|
|
0
|
return \$r->content;
|
323
|
|
|
|
|
|
|
}
|
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=head2 _parse
|
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
WebService::UWO::Directory::Student::_parse( $response )
|
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
This method processes the HTML content retrieved by _query method and returns
|
330
|
|
|
|
|
|
|
an ARRAY reference containing HASH references to the result set. This is most
|
331
|
|
|
|
|
|
|
likely only useful for testing purposes.
|
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=cut
|
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub _parse {
|
336
|
1
|
|
|
1
|
|
33
|
my ($data) = @_;
|
337
|
|
|
|
|
|
|
|
338
|
1
|
50
|
|
|
|
5
|
Carp::croak('Expecting a scalar reference') unless ref($data) eq 'SCALAR';
|
339
|
|
|
|
|
|
|
|
340
|
1
|
|
|
|
|
3
|
HTML::Entities::decode_entities(${$data});
|
|
1
|
|
|
|
|
1222
|
|
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
# Record format from the directory server:
|
343
|
|
|
|
|
|
|
# Full Name: Last,First Middle
|
344
|
|
|
|
|
|
|
# E-mail: e-mail@uwo.ca
|
345
|
|
|
|
|
|
|
# Registered In: Faculty Name
|
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
# 4 fields captured
|
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
# We don't want the \n swallowed in .+
|
350
|
|
|
|
|
|
|
## no critic(RequireDotMatchAnything)
|
351
|
1
|
|
|
|
|
46
|
my @matches = (
|
352
|
1
|
|
|
|
|
14
|
${$data} =~ m{
|
353
|
|
|
|
|
|
|
[ ]{4}Full\ Name:\ ([^,]+),(.+)\n
|
354
|
|
|
|
|
|
|
[ ]{7}E-mail:.*\>(.+)\\n
|
355
|
|
|
|
|
|
|
Registered\ In:\ (.+)\n
|
356
|
|
|
|
|
|
|
}xg
|
357
|
|
|
|
|
|
|
);
|
358
|
|
|
|
|
|
|
|
359
|
1
|
|
|
|
|
4
|
my $res;
|
360
|
|
|
|
|
|
|
# Requires an irregular count - in steps of 4
|
361
|
|
|
|
|
|
|
## no critic (ProhibitCStyleForLoops)
|
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
# Copy the fields four at a time based on the above regular expression
|
364
|
1
|
|
|
|
|
13
|
for (my $i = 0; $i < scalar(@matches); $i += 4) {
|
365
|
2
|
|
|
|
|
18
|
my $stu = {
|
366
|
|
|
|
|
|
|
last_name => $matches[$i],
|
367
|
|
|
|
|
|
|
given_name => $matches[$i+1],
|
368
|
|
|
|
|
|
|
email => $matches[$i+2],
|
369
|
|
|
|
|
|
|
faculty => $matches[$i+3],
|
370
|
|
|
|
|
|
|
};
|
371
|
2
|
|
|
|
|
7
|
push(@{$res}, $stu);
|
|
2
|
|
|
|
|
14
|
|
372
|
|
|
|
|
|
|
}
|
373
|
|
|
|
|
|
|
|
374
|
1
|
|
|
|
|
9
|
return $res;
|
375
|
|
|
|
|
|
|
}
|
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
=head1 AUTHOR
|
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
Jonathan Yu Ejawnsy@cpan.orgE
|
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
=head1 SUPPORT
|
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command.
|
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
perldoc WebService::UWO::Directory::Student
|
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
You can also look for information at:
|
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
=over
|
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation
|
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
L
|
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=item * CPAN Ratings
|
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
L
|
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=item * Search CPAN
|
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
L
|
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
=item * CPAN Request Tracker
|
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
L
|
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
=item * CPAN Testing Service (Kwalitee Tests)
|
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
L
|
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
=item * CPAN Testers Platform Compatibility Matrix
|
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
L
|
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=back
|
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
=head1 REPOSITORY
|
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
You can access the most recent development version of this module at:
|
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
L
|
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
If you are a CPAN developer and would like to make modifications to the code
|
424
|
|
|
|
|
|
|
base, please contact Adam Kennedy Eadamk@cpan.orgE, the repository
|
425
|
|
|
|
|
|
|
administrator. I only ask that you contact me first to discuss the changes you
|
426
|
|
|
|
|
|
|
wish to make to the distribution.
|
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=head1 FEEDBACK
|
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
Please send relevant comments, rotten tomatoes and suggestions directly to the
|
431
|
|
|
|
|
|
|
maintainer noted above.
|
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
If you have a bug report or feature request, please file them on the CPAN
|
434
|
|
|
|
|
|
|
Request Tracker at L. If you are able to submit your bug
|
435
|
|
|
|
|
|
|
report in the form of failing unit tests, you are B encouraged to do
|
436
|
|
|
|
|
|
|
so.
|
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=head1 SEE ALSO
|
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
L, the site this module uses
|
441
|
|
|
|
|
|
|
to query the database
|
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
=head1 CAVEATS
|
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
=head2 KNOWN BUGS
|
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
There are no known bugs as of this release.
|
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
=head2 LIMITATIONS
|
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=over
|
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
=item *
|
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
This module is only able to access partial student records since students must
|
456
|
|
|
|
|
|
|
give consent for their contact information to be published on the web. For
|
457
|
|
|
|
|
|
|
more, see L.
|
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
=item *
|
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
Some students change their name (for example, a marriage), while retainining
|
462
|
|
|
|
|
|
|
the same email address. This means their email addresses cannot be effectively
|
463
|
|
|
|
|
|
|
reverse-searched.
|
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=item *
|
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
This module has not been very thoroughly tested for memory consumption. It
|
468
|
|
|
|
|
|
|
does a lot of copying that should be optimized, however, it is probably not
|
469
|
|
|
|
|
|
|
necessary for most uses.
|
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
=back
|
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
=head1 LICENSE
|
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
In a perfect world, I could just say that this package and all of the code
|
476
|
|
|
|
|
|
|
it contains is Public Domain. It's a bit more complicated than that; you'll
|
477
|
|
|
|
|
|
|
have to read the included F file to get the full details.
|
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
=head1 DISCLAIMER OF WARRANTY
|
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
The software is provided "AS IS", without warranty of any kind, express or
|
482
|
|
|
|
|
|
|
implied, including but not limited to the warranties of merchantability,
|
483
|
|
|
|
|
|
|
fitness for a particular purpose and noninfringement. In no event shall the
|
484
|
|
|
|
|
|
|
authors or copyright holders be liable for any claim, damages or other
|
485
|
|
|
|
|
|
|
liability, whether in an action of contract, tort or otherwise, arising from,
|
486
|
|
|
|
|
|
|
out of or in connection with the software or the use or other dealings in
|
487
|
|
|
|
|
|
|
the software.
|
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
=cut
|
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
1;
|