This file is indexed.

/usr/share/perl5/SMS/Send.pm is in libsms-send-perl 1.06-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
package SMS::Send;

=pod

=head1 NAME

SMS::Send - Driver-based API for sending SMS messages

=head1 SYNOPSIS

  # Create a sender
  my $sender = SMS::Send->new('SomeDriver',
      _login    => 'myname',
      _password => 'mypassword',
  );
  
  # Send a message
  my $sent = $sender->send_sms(
      text => 'This is a test message',
      to   => '+61 (4) 1234 5678',
  );
  
  # Did the send succeed.
  if ( $sent ) {
      print "Message sent ok\n";
  } else {
      print "Failed to send message\n";
  }

=head1 DESCRIPTION

C<SMS::Send> is intended to provide a driver-based single API for sending SMS
and MMS messages. The intent is to provide a single API against which to
write the code to send an SMS message.

At the same time, the intent is to remove the limits of some of the previous
attempts at this sort of API, like "must be free internet-based SMS services".

C<SMS::Send> drivers are installed separately, and might use the web, email or
physical SMS hardware. It could be a free or paid. The details shouldn't
matter.

You should not have to care how it is actually sent, only that it has been
sent (although some drivers may not be able to provide certainty).

=head1 METHODS

=cut

use 5.006;
use strict;
use Carp              ();
use SMS::Send::Driver ();
use Params::Util 0.14 ();

# We are a type of Adapter
use Class::Adapter::Builder 1.05
	AUTOLOAD => 'PUBLIC';

# We need plugin support to find the drivers
use Module::Pluggable 3.7
	require     => 0,
	inner       => 0,
	search_path => [ 'SMS::Send' ],
	except      => [ 'SMS::Send::Driver' ],
	sub_name    => '_installed_drivers';

use vars qw{$VERSION};
BEGIN {
	$VERSION = '1.06';
}

# Private driver cache
my @DRIVERS = ();

=pod

=head2 installed_drivers

The C<installed_drivers> the list of SMS::Send drivers that are installed
on the current system.

=cut

sub installed_drivers {
	my $class = shift;

	unless ( @DRIVERS ) {
		my @rawlist = $class->_installed_drivers;
		foreach my $d ( @rawlist ) {
			$d =~ s/^SMS::Send:://;
		}
		@DRIVERS = @rawlist;
	}

	return @DRIVERS;
}





#####################################################################
# Constructor and Accessors

=pod

=head2 new

  # The most basic sender
  $sender = SMS::Send->new('Test');
  
  # Indicate regional driver with ::
  $sender = SMS::Send->new('AU::Test');
  
  # Pass arbitrary params to the driver
  $sender = SMS::Send->new('MyDriver',
      _login    => 'adam',
      _password => 'adam',
  );

The C<new> constructor creates a new SMS sender.

It takes as its first parameter a driver name. These names map the class
names. For example driver "Test" matches the testing driver
L<SMS::Send::Test>.

Any additional params should be key/value pairs, split into two types.

Params without a leading underscore are "public" options and relate to
standardised features within the L<SMS::Send> API itself. At this
time, there are no usable public options.

Params B<with> a leading underscore are "private" driver-specific options
and will be passed through to the driver unchanged.

Returns a new L<SMS::Send> object, or dies on error.

=cut

sub new {
	my $class  = shift;
	my $driver = $class->_DRIVER(shift);
	my @params = Params::Util::_HASH0($_[0]) ? %{$_[0]} : @_;

	# Create the driver and verify
	my $object = $driver->new( $class->_PRIVATE(@params) );
	unless ( Params::Util::_INSTANCE($object, 'SMS::Send::Driver') ) {
		Carp::croak("Driver Error: $driver->new did not return a driver object");
	}

	# Hand off to create our object
	my $self = $class->SUPER::new( $object );
	unless ( Params::Util::_INSTANCE($self, $class) ) {
		die "Internal Error: Failed to create a $class object";
	}

	return $self;
}

=pod

=head2 send_sms

  # Send a message to a particular address
  my $result = $sender->send_sms(
      text => 'This is a test message',
      to   => '+61 4 1234 5678',
  );

The C<send_sms> method sends a standard text SMS message to a destination
phone number.

It takes a set of named parameters to describe the message and its
destination, again split into two types.

Params without a leading underscore are "public" options and relate to
standardised features within the L<SMS::Send> API itself.

=over

=item text

The C<text> param is compulsory and should be a plain text string of
non-zero length. The maximum length is currently determined by the
driver, and exceeding this length will result in an exception being
thrown if you breach it.

Better functionality for determining the maximum-supported length is
expected in the future. You input would be welcome.

=item to

The C<to> param is compulsory, and should be an international phone
number as indicated by a leading plus "+" character. Punctuation in
any form is allowed, and will be stripped out before it is provided
to the driver.

If and only if your driver is a regional driver (as indicated by a
::-seperated name such as AU::Test) the C<to> number can also be in
a regional-specific dialing format, C<without> a leading plus "+"
character.

Providing a regional number to a non-regional driver will throw an
exception.

=back

Any parameters B<with> a leading underscore are considered private
driver-specific options and will be passed through without alteration.

Any other parameters B<without> a leading underscore will be silently
stripped out and not passed through to the driver.

After calling C<send_sms> the driver will do whatever is required to
send the message, including (potentially, but not always) waiting for
a confirmation from the network that the SMS has been sent.

Given that drivers may do the actual mechanics of sending a message by
quite a large variety of different methods the C<send_sms> method may
potentially block for some time. Timeout functionality is expected to
be added later.

The C<send_sms> returns true if the message was sent, or the driver
is fire-and-forget and unable to determine success, or false if the
message was not sent.

=cut

sub send_sms {
	my $self   = shift;
	my %params = @_;

	# Get the text content
	my $text = delete $params{text};
	unless ( _STRING($text) ) {
		Carp::croak("Did not provide a 'text' string param");
	}

	# Get the destination number
	my $to = delete $params{to};
	unless ( _STRING($to) ) {
		Carp::croak("Did not provide a 'to' message destination");
	}

	# Clean up the number
	$to =~ s/[\s\(\)\[\]\{\}\.-]//g;
	unless ( _STRING($to) ) {
		Carp::croak("Did not provide a 'to' message destination");
	}
	unless ( $to =~ /^\+?\d+$/ ) {
		Carp::croak("Invalid phone number format '$params{to}'");
	}

	# Extra validations of international or non-international issues
	if ( $to =~ /^\+0/ ) {
		Carp::croak("International phone numbers cannot have leading zeros");
	}
	if ( $to =~ /^\+/ and length($to) <= 7 ) {
		Carp::croak("International phone numbers must be at least 6 digits");
	}
	unless ( ref($self->_OBJECT_) =~ /^SMS::Send::\w+::/ ) {
		# International-only driver
		unless ( $to =~ /^\+/ ) {
			Carp::croak("Cannot use regional phone numbers with an international driver");
		}
	}

	# Merge params and hand off
	my $rv = $self->_OBJECT_->send_sms(
		text => $text,
		to   => $to,
		$self->_PRIVATE(@_),
	);

	# Verify we get some sort of result
	unless ( defined $rv ) {
		Carp::croak("Driver did not return a result");
	}

	return $rv;
}





#####################################################################
# Support Methods

sub _STRING {
	!! (defined $_[0] and ! ref $_[0] and length $_[0]);
}

sub _DRIVER {
	my $class  = shift;

	# The driver should be a string (other than 'Driver')
	my $name = $_[0];
	unless ( defined $name and ! ref $name and length $name ) {
		Carp::croak("Did not provide a SMS::Send driver name");
	}
	if ( $name =~ /^\d+$/ ) {
		# Although pure-digit Foo::123 class names are technically
		# allowed, we don't allow them as drivers, to reduce insanity.
		Carp::croak("Not a valid SMS::Send driver name");
	}

	# Clean up the driver name
	my $driver = "SMS::Send::$name";
	unless ( Params::Util::_CLASS($driver) ) {
		Carp::croak("Not a valid SMS::Send driver name");
	}

	# Load the driver
	eval "require $driver;";
	if ( $@ and $@ =~ /^Can't locate / ) {
		# Driver does not exist
		Carp::croak("SMS::Send driver $_[0] does not exist, or is not installed");
	} elsif ( $@ ) {
		# Fatal error within the driver itself
		# Pass on without change
		Carp::croak( $@ );
	}

	# Verify that the class is actually a driver
	unless ( $driver->isa('SMS::Send::Driver') and $driver ne 'SMS::Send::Driver' ) {
		Carp::croak("$driver is not a subclass of SMS::Send::Driver");
	}

	return $driver;
}

# Filter params for only the private params
sub _PRIVATE {
	my $class  = ref $_[0] ? ref shift : shift;
	my @input  = @_;
	my @output = ();
	while ( @input ) {
		my $key   = shift @input;
		my $value = shift @input;
		if ( _STRING($key) and $key =~ /^_/ ) {
			push @output, $key, $value;
		}
	}
	return @output;		
}

1;

=pod

=head1 SUPPORT

Bugs should be reported via the CPAN bug tracker at

L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=SMS-Send>

For other issues, contact the author.

=head1 AUTHOR

Adam Kennedy E<lt>adamk@cpan.orgE<gt>

=head1 COPYRIGHT

Copyright 2005 - 2011 Adam Kennedy.

This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

The full text of the license can be found in the
LICENSE file included with this module.

=cut