File Coverage

blib/lib/yesssSMS.pm
Criterion Covered Total %
statement 17 188 9.0
branch 0 78 0.0
condition 0 27 0.0
subroutine 6 21 28.5
pod 9 14 64.2
total 32 328 9.7


line stmt bran cond sub pod time code
1             package yesssSMS;
2              
3 1     1   69468 use 5.014002;
  1         4  
4 1     1   5 use strict;
  1         2  
  1         32  
5 1     1   6 use warnings;
  1         2  
  1         37  
6 1     1   599 use HTML::Parser;
  1         5807  
  1         36  
7 1     1   731 use LWP::UserAgent;
  1         50258  
  1         39  
8 1     1   580 use HTTP::Cookies;
  1         7020  
  1         2317  
9              
10              
11             require Exporter;
12              
13             our @ISA = qw(Exporter);
14              
15             # Items to export into callers namespace by default. Note: do not export
16             # names by default without a very good reason. Use EXPORT_OK instead.
17             # Do not simply export all your public functions/methods/constants.
18              
19             # This allows declaration use yesssSMS ':all';
20             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
21             # will save memory.
22             our %EXPORT_TAGS = ( 'all' => [ qw(
23            
24             ) ] );
25              
26             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
27              
28             our @EXPORT = qw(
29            
30             );
31              
32             our $VERSION = '2.15';
33              
34             sub new
35             {
36 0     0 1   my $self = {};
37 0           $self->{LOGINSTATE} = 0;
38 0           $self->{URL}="https://www.yesss.at/kontomanager.at/";
39              
40 0           bless ($self);
41 0           return $self;
42             }
43              
44             sub login
45             {
46 0     0 1   my $self = shift;
47 0           my $phoneParser;
48              
49             ($self->{TELNR},
50 0           $self->{PASS})=@_;
51              
52             # don't login if logged in...
53 0 0         if ($self->{LOGINSTATE} == 1)
54             {
55 0           $self->{LASTERROR}='Cannot login when already logged in';
56 0           $self->{RETURNCODE}=1;
57 0           return 1;
58             }
59              
60             # Cookies are needed
61 0           $self->{UA} = LWP::UserAgent->new;
62 0           $self->{UA}->cookie_jar(HTTP::Cookies->new);
63              
64             # go to start page
65 0           $self->{CONTENT}=$self->{UA}->get($self->{URL});
66              
67             # if there was an error on the start page, stop
68 0 0         if (!($self->{CONTENT}->is_success))
69             {
70 0           $self->{LASTERROR}='Error loading startpage of YESSS!';
71 0           $self->{RETURNCODE}=2;
72 0           return 2;
73             }
74              
75             # do the login post
76 0           $self->{CONTENT}=$self->{UA}->post($self->{URL}."index.php",{'login_rufnummer' => $self->{TELNR},'login_passwort' => $self->{PASS}});
77              
78             # successful login results in redirect
79 0 0         if (!($self->{CONTENT}->is_redirect))
80             {
81 0           $self->{LASTERROR}='Error sending credentials!';
82 0           $self->{RETURNCODE}=3;
83 0           return 3;
84             }
85              
86             # usually, a redirect is replied
87 0           while ($self->{CONTENT}->is_redirect)
88             {
89             # follow redirect
90 0           $self->{CONTENT}=$self->{UA}->post($self->{CONTENT}->header("Location"),{'login_rufnummer' => $self->{TELNR},'login_passwort' => $self->{PASS}});
91              
92             # if there was an error during redirect, stop
93 0 0         if (!($self->{CONTENT}->is_success))
94             {
95 0           $self->{LASTERROR}='Error during post-login redirect';
96 0           $self->{RETURNCODE}=4;
97 0           print $self->{CONTENT}->status_line;
98 0           return 4;
99             }
100             }
101              
102             # parse interesting values
103 0           $phoneParser=HTML::Parser->new(api_version=>3,
104             start_h => [\&loginStartTagParse, "self,tagname,attr"],
105             text_h => [\&loginTextParse, "self, text"],
106             end_h => [\&loginEndTagParse, "self, tagname"]
107             );
108             # bring my "self" into the handlers without global vars
109             # delete possible existing subscriptions
110             # initialize some variables needed for the parser
111 0           undef($self->{SUBSCRIPTIONS});
112 0           $phoneParser->{'yesssSMSself'}=$self;
113 0           $phoneParser->{'inSubscriber'}=0;
114 0           $phoneParser->{'inProgresslist'}=0;
115 0           $phoneParser->{'inProgressheading'}=0;
116 0           $phoneParser->{'amountSubscriptions'}=0;
117 0           $phoneParser->{'amountItems'}=0;
118 0           $phoneParser->parse($self->{CONTENT}->decoded_content);
119              
120             # print found phone numbers and their values
121              
122 0           $self->{LOGINSTATE}=1;
123 0           $self->{LASTERROR}='Login successful';
124 0           $self->{RETURNCODE}=0;
125 0           return 0;
126             }
127              
128             sub selectPhonenumber
129             {
130 0     0 0   my $self = shift;
131 0           my ($telnr)=@_;
132 0           my $phoneParser;
133              
134             # switching is only possible after login
135 0 0         if ($self->{LOGINSTATE} == 0)
136             {
137 0           $self->{LASTERROR}='Not logged in while trying to select phonenumber';
138 0           $self->{RETURNCODE}=1;
139 0           return 1;
140             }
141              
142             # check, if the requested phonenumber is valid
143 0 0         if (! defined($self->{SUBSCRIBERS}->{$telnr}))
144             {
145 0           $self->{LASTERROR}='Requested phonenumber not available in account';
146 0           $self->{RETURNCODE}=6;
147 0           return 6;
148             }
149              
150             $self->{CONTENT}=$self->{UA}->post($self->{URL}."kundendaten.php",
151             {
152 0           'subscriber' => $self->{SUBSCRIBERS}->{$telnr},
153             'groupaction' => 'change_subscriber'
154             }
155             );
156              
157             # stop on error
158 0 0         if (!($self->{CONTENT}->is_success))
159             {
160 0           $self->{LASTERROR}='Error while selecting phonenumber';
161 0           $self->{RETURNCODE}=7;
162 0           return 7;
163             }
164              
165             # parse interesting values
166 0           $phoneParser=HTML::Parser->new(api_version=>3,
167             start_h => [\&loginStartTagParse, "self,tagname,attr"],
168             text_h => [\&loginTextParse, "self, text"],
169             end_h => [\&loginEndTagParse, "self, tagname"]
170             );
171             # bring my "self" into the handlers without global vars
172 0           undef($self->{SUBSCRIPTIONS});
173 0           $phoneParser->{'yesssSMSself'}=$self;
174 0           $phoneParser->{'inSubscriber'}=0;
175 0           $phoneParser->{'inProgresslist'}=0;
176 0           $phoneParser->{'inProgressheading'}=0;
177 0           $phoneParser->{'amountSubscriptions'}=0;
178 0           $phoneParser->{'amountItems'}=0;
179 0           $phoneParser->parse($self->{CONTENT}->decoded_content);
180              
181            
182             }
183              
184             sub sendmessage
185             {
186 0     0 1   my $self = shift;
187 0           my ($telnr,$message)=@_;
188              
189             # only send message when login was successful
190 0 0         if ($self->{LOGINSTATE} == 0)
191             {
192 0           $self->{LASTERROR}='Not logged in while trying to send a message';
193 0           $self->{RETURNCODE}=1;
194 0           return 1;
195             }
196              
197 0 0 0       if (!($telnr=~/^00/) || (length($telnr)<14))
198             {
199 0           $self->{LASTERROR}='Invalid destination (not starting with 00 or too short)';
200 0           $self->{RETURNCODE}=3;
201 0           return 3;
202             }
203              
204             # go to correct menu item
205 0           $self->{CONTENT}=$self->{UA}->post($self->{URL}."websms.php");
206              
207             # stop on error
208 0 0         if (!($self->{CONTENT}->is_success))
209             {
210 0           $self->{LASTERROR}='Error while selecting SMS menu';
211 0           $self->{RETURNCODE}=4;
212 0           return 4;
213             }
214              
215             # try to send message
216 0           $self->{CONTENT}=$self->{UA}->post($self->{URL}."websms_send.php",{'to_netz' => 'a','to_nummer' => $telnr,'nachricht' => $message});
217              
218             # stop on error
219 0 0         if (!($self->{CONTENT}->is_success))
220             {
221 0           $self->{LASTERROR}='Error while sending message';
222 0           $self->{RETURNCODE}=5;
223 0           return 5;
224             }
225              
226 0           $self->{LASTERROR}='Message sent successfully';
227 0           $self->{RETURNCODE}=0;
228 0           return 0;
229             }
230              
231             sub getLoginstate
232             {
233 0     0 1   my $self = shift;
234            
235 0           return $self->{LOGINSTATE};
236             }
237              
238             sub logout
239             {
240 0     0 1   my $self = shift;
241              
242             # don't logout if not logged in...
243 0 0         if ($self->{LOGINSTATE} == 0)
244             {
245 0           $self->{LASTERROR}='Cannot logout when not logged in.';
246 0           $self->{RETURNCODE}=1;
247 0           return 1;
248             }
249              
250             # post the logout url
251 0           $self->{CONTENT}=$self->{UA}->post($self->{URL}."index.php?dologout=1");
252              
253             # if there was an error during logout, stop
254 0 0         if (!($self->{CONTENT}->is_success))
255             {
256 0           $self->{LASTERROR}='Error during logout.';
257 0           $self->{RETURNCODE}=2;
258 0           return 2;
259             }
260              
261             # reset LOGINSTATE
262 0           $self->{LOGINSTATE}=0;
263 0           $self->{LASTERROR}='Logout successful';
264 0           $self->{RETURNCODE}=0;
265 0           return 0;
266             }
267              
268             sub getLastResult
269             {
270 0     0 1   my $self = shift;
271              
272 0           return $self->{RETURNCODE};
273             }
274              
275             sub getLastError
276             {
277 0     0 1   my $self = shift;
278              
279 0           return $self->{LASTERROR};
280             }
281              
282             sub getContent
283             {
284 0     0 1   my $self = shift;
285              
286 0           return $self->{CONTENT};
287             }
288              
289             sub getSubscriptions
290             {
291 0     0 1   my $self = shift;
292              
293 0           return $self->{SUBSCRIPTIONS};
294             }
295              
296             sub DESTROY
297             {
298 0     0     my $self = shift;
299 0 0         if ($self->{LOGINSTATE}==1)
300             {
301 0           $self->logout();
302             }
303             }
304              
305              
306             ####### methods for parser
307             # login/switch phone number
308             sub loginStartTagParse
309             {
310 0     0 0   my ($self, $tagname, $attr) = @_;
311              
312 0 0 0       if (($self->{'inSubscriber'} != 1) &&
    0          
    0          
313             ($self->{'inProgresslist'} < 1))
314             {
315 0 0 0       if (($tagname eq 'select') &&
    0 0        
      0        
316             ($attr->{'id'} eq 'subscriber'))
317             {
318 0           $self->{'inSubscriber'}=1;
319             }
320             elsif (($tagname eq 'div') &&
321             (defined ($attr->{'class'})) &&
322             ($attr->{'class'} eq 'progress-list'))
323             {
324 0           $self->{'inProgresslist'}++;
325             }
326             }
327             elsif ($self->{'inSubscriber'} == 1)
328             {
329 0 0         if ($tagname eq 'option')
330             {
331 0           $self->{'lastValue'}=$attr->{'value'};
332             }
333             }
334             elsif ($self->{'inProgresslist'} >= 1)
335             {
336 0 0         if ($tagname eq 'div')
337             {
338 0 0         if ($attr->{'class'} eq 'info-list-item')
    0          
339             {
340 0           $self->{'inProgresslist'}=0;
341 0           $self->{'amountItems'}=0;
342             }
343             elsif ($attr->{'class'} eq 'progress-item')
344             {
345 0           $self->{'amountItems'}++;
346 0           $self->{'inProgresslist'}++;
347             }
348             else
349             {
350 0           $self->{'inProgresslist'}++;
351             }
352             }
353 0 0         if ($tagname eq 'h3')
354             {
355 0 0 0       if ((defined($attr->{'id'})) &&
356             ($attr->{'id'} eq 'kostenkontrolle'))
357             {
358             # we ignore 'Kostenkontrolle'
359 0           $self->{'inProgresslist'}=0;
360 0           $self->{'amountItems'}=0;
361             }
362             else
363             {
364 0           $self->{'inProgressheading'}=1;
365             }
366             }
367             }
368             }
369              
370             sub loginTextParse
371             {
372 0     0 0   my ($self, $text) = @_;
373 0           my $phonenumber;
374             my $progressname;
375 0           my $value;
376              
377 0           &trim(\$text);
378 0 0 0       if (($self->{'inSubscriber'} == 1) &&
    0 0        
    0 0        
379             (length($text)>1))
380             {
381 0           ($phonenumber)=$text=~/^([0-9]+)[^0-9]/;
382 0           $self->{'yesssSMSself'}->{SUBSCRIBERS}->{$phonenumber}=$self->{'lastValue'};
383             }
384             elsif (($self->{'inProgressheading'} == 1) &&
385             (length($text)>1))
386             {
387 0           ($progressname)=$text=~/\s*(.*)\s*:$/;
388 0           $self->{'amountSubscriptions'}++;
389 0           $self->{'yesssSMSself'}->{SUBSCRIPTIONS}->[$self->{'amountSubscriptions'}-1]->{'name'}=$progressname;
390             }
391             elsif (($self->{'inProgresslist'} >= 1) &&
392             (length($text)>1))
393             {
394 0 0         if ($text=~/^[0-9]+\s/)
    0          
    0          
    0          
395             {
396 0           ($value)=$text=~/^[0-9]+\s(.+)$/;
397             $self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
398 0           [$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'unit'}=$value;
399             }
400             elsif ($text=~/^Verbraucht:/)
401             {
402 0           ($value)=$text=~/^Verbraucht: ([0-9]+)\s*$/;
403             $self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
404 0           [$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'used'}=$value;
405             }
406             elsif ($text=~/^Verbraucht Inland:/)
407             {
408 0           ($value)=$text=~/^Verbraucht Inland: ([0-9]+)\s*$/;
409             $self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
410 0           [$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'used'}+=$value;
411             }
412             elsif ($text=~/^Verbleibend/)
413             {
414 0           ($value)=$text=~/^Verbleibend: ([0-9]+)$/;
415             $self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
416 0           [$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'remaining'}=$value;
417             }
418             }
419             }
420              
421             sub loginEndTagParse
422             {
423 0     0 0   my ($self, $tagname) = @_;
424              
425 0 0         if ($self->{'inSubscriber'} == 1)
    0          
426             {
427 0 0         if ($tagname eq 'select')
428             {
429 0           $self->{'inSubscriber'}=0;
430             }
431             }
432             elsif ($self->{'inProgresslist'} >= 1)
433             {
434 0 0         if ($tagname eq 'div')
435             {
436 0           $self->{'inProgresslist'}--;
437 0 0         if ($self->{'inProgresslist'} == 0)
438             {
439 0           $self->{'amountItems'}=0;
440             }
441             }
442 0 0         if ($self->{'inProgressheading'} == 1)
443             {
444 0 0         if ($tagname eq 'h3')
445             {
446 0           $self->{'inProgressheading'}=0;
447             }
448             }
449             }
450             }
451              
452             sub trim
453             {
454 0     0 0   my $string=$_[0];
455              
456 0           $$string =~ s/^\s+//;
457 0           $$string =~ s/\s+$//;
458             }
459              
460             1;
461             __END__