File Coverage

blib/lib/yesssSMS.pm
Criterion Covered Total %
statement 17 206 8.2
branch 0 92 0.0
condition 0 30 0.0
subroutine 6 23 26.0
pod 9 16 56.2
total 32 367 8.7


line stmt bran cond sub pod time code
1             package yesssSMS;
2              
3 1     1   69483 use 5.014002;
  1         4  
4 1     1   5 use strict;
  1         3  
  1         22  
5 1     1   5 use warnings;
  1         3  
  1         49  
6 1     1   607 use HTML::Parser;
  1         6109  
  1         41  
7 1     1   706 use LWP::UserAgent;
  1         47239  
  1         39  
8 1     1   568 use HTTP::Cookies;
  1         7095  
  1         2472  
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.20';
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             sub sendmessage
184             {
185 0     0 1   my $self = shift;
186 0           my ($telnr,$message)=@_;
187 0           my $tokenParser;
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             # get token for websms.php
216 0           $tokenParser=HTML::Parser->new(api_version=>3,
217             start_h => [\&websmsGetTokenStartTagParse, "self,tagname,attr"],
218             end_h => [\&websmsGetTokenEndTagParse, "self, tagname"]
219             );
220 0           $self->{'websmsToken'}='';
221 0           $tokenParser->{'inWebsmsSendForm'}=0;
222 0           $tokenParser->{'yesssSMSself'}=$self;
223 0           $tokenParser->parse($self->{CONTENT}->decoded_content);
224              
225             # try to send message
226             $self->{CONTENT}=$self->{UA}->post($self->{URL}."websms_send.php",
227             { 'to_netz' => 'a',
228             'to_nummer' => $telnr,
229             'nachricht' => $message,
230 0           'token' => $self->{'websmsToken'}
231             });
232              
233             # stop on error
234 0 0         if (!($self->{CONTENT}->is_success))
235             {
236             $self->{LASTERROR}='Error while sending message ('.
237 0           $self->{CONTENT}->status_line.')';
238 0           $self->{RETURNCODE}=5;
239 0           return 5;
240             }
241              
242 0           $self->{LASTERROR}='Message sent successfully';
243 0           $self->{RETURNCODE}=0;
244 0           return 0;
245             }
246              
247             sub getLoginstate
248             {
249 0     0 1   my $self = shift;
250            
251 0           return $self->{LOGINSTATE};
252             }
253              
254             sub logout
255             {
256 0     0 1   my $self = shift;
257              
258             # don't logout if not logged in...
259 0 0         if ($self->{LOGINSTATE} == 0)
260             {
261 0           $self->{LASTERROR}='Cannot logout when not logged in.';
262 0           $self->{RETURNCODE}=1;
263 0           return 1;
264             }
265              
266             # post the logout url
267 0           $self->{CONTENT}=$self->{UA}->post($self->{URL}."index.php?dologout=1");
268              
269             # if there was an error during logout, stop
270 0 0         if (!($self->{CONTENT}->is_success))
271             {
272 0           $self->{LASTERROR}='Error during logout.';
273 0           $self->{RETURNCODE}=2;
274 0           return 2;
275             }
276              
277             # reset LOGINSTATE
278 0           $self->{LOGINSTATE}=0;
279 0           $self->{LASTERROR}='Logout successful';
280 0           $self->{RETURNCODE}=0;
281 0           return 0;
282             }
283              
284             sub getLastResult
285             {
286 0     0 1   my $self = shift;
287              
288 0           return $self->{RETURNCODE};
289             }
290              
291             sub getLastError
292             {
293 0     0 1   my $self = shift;
294              
295 0           return $self->{LASTERROR};
296             }
297              
298             sub getContent
299             {
300 0     0 1   my $self = shift;
301              
302 0           return $self->{CONTENT};
303             }
304              
305             sub getSubscriptions
306             {
307 0     0 1   my $self = shift;
308              
309 0           return $self->{SUBSCRIPTIONS};
310             }
311              
312             sub DESTROY
313             {
314 0     0     my $self = shift;
315 0 0         if ($self->{LOGINSTATE}==1)
316             {
317 0           $self->logout();
318             }
319             }
320              
321              
322             ####### methods for parser
323             # login/switch phone number
324              
325             sub loginStartTagParse
326             {
327 0     0 0   my ($self, $tagname, $attr) = @_;
328              
329 0 0 0       if (($self->{'inSubscriber'} != 1) &&
    0          
    0          
330             ($self->{'inProgresslist'} < 1))
331             {
332 0 0 0       if (($tagname eq 'select') &&
    0 0        
      0        
333             ($attr->{'id'} eq 'subscriber'))
334             {
335 0           $self->{'inSubscriber'}=1;
336             }
337             elsif (($tagname eq 'div') &&
338             (defined ($attr->{'class'})) &&
339             ($attr->{'class'} eq 'progress-list'))
340             {
341 0           $self->{'inProgresslist'}++;
342             }
343             }
344             elsif ($self->{'inSubscriber'} == 1)
345             {
346 0 0         if ($tagname eq 'option')
347             {
348 0           $self->{'lastValue'}=$attr->{'value'};
349             }
350             }
351             elsif ($self->{'inProgresslist'} >= 1)
352             {
353 0 0         if ($tagname eq 'div')
354             {
355 0 0         if ($attr->{'class'} eq 'info-list-item')
    0          
356             {
357 0           $self->{'inProgresslist'}=0;
358 0           $self->{'amountItems'}=0;
359             }
360             elsif ($attr->{'class'} eq 'progress-item')
361             {
362 0           $self->{'amountItems'}++;
363 0           $self->{'inProgresslist'}++;
364             }
365             else
366             {
367 0           $self->{'inProgresslist'}++;
368             }
369             }
370 0 0         if ($tagname eq 'h3')
371             {
372 0 0 0       if ((defined($attr->{'id'})) &&
373             ($attr->{'id'} eq 'kostenkontrolle'))
374             {
375             # we ignore 'Kostenkontrolle'
376 0           $self->{'inProgresslist'}=0;
377 0           $self->{'amountItems'}=0;
378             }
379             else
380             {
381 0           $self->{'inProgressheading'}=1;
382             }
383             }
384             }
385             }
386              
387             sub loginTextParse
388             {
389 0     0 0   my ($self, $text) = @_;
390 0           my $phonenumber;
391             my $progressname;
392 0           my $value;
393              
394 0           &trim(\$text);
395 0 0 0       if (($self->{'inSubscriber'} == 1) &&
    0 0        
    0 0        
396             (length($text)>1))
397             {
398 0           ($phonenumber)=$text=~/^([0-9]+)[^0-9]/;
399 0           $self->{'yesssSMSself'}->{SUBSCRIBERS}->{$phonenumber}=$self->{'lastValue'};
400             }
401             elsif (($self->{'inProgressheading'} == 1) &&
402             (length($text)>1))
403             {
404 0           ($progressname)=$text=~/\s*(.*)\s*:$/;
405 0           $self->{'amountSubscriptions'}++;
406 0           $self->{'yesssSMSself'}->{SUBSCRIPTIONS}->[$self->{'amountSubscriptions'}-1]->{'name'}=$progressname;
407             }
408             elsif (($self->{'inProgresslist'} >= 1) &&
409             (length($text)>1))
410             {
411 0 0         if ($text=~/^[0-9]+\s/)
    0          
    0          
    0          
412             {
413 0           ($value)=$text=~/^[0-9]+\s(.+)$/;
414             $self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
415 0           [$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'unit'}=$value;
416             }
417             elsif ($text=~/^Verbraucht:/)
418             {
419 0           ($value)=$text=~/^Verbraucht: ([0-9]+)\s*$/;
420             $self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
421 0           [$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'used'}=$value;
422             }
423             elsif ($text=~/^Verbraucht Inland:/)
424             {
425 0           ($value)=$text=~/^Verbraucht Inland: ([0-9]+)\s*$/;
426             $self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
427 0           [$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'used'}+=$value;
428             }
429             elsif ($text=~/^Verbleibend/)
430             {
431 0           ($value)=$text=~/^Verbleibend: ([0-9]+)$/;
432             $self->{'yesssSMSself'}->{SUBSCRIPTIONS}->
433 0           [$self->{'amountSubscriptions'}-1]->{'items'}->[$self->{'amountItems'}-1]->{'remaining'}=$value;
434             }
435             }
436             }
437              
438             sub loginEndTagParse
439             {
440 0     0 0   my ($self, $tagname) = @_;
441              
442 0 0         if ($self->{'inSubscriber'} == 1)
    0          
443             {
444 0 0         if ($tagname eq 'select')
445             {
446 0           $self->{'inSubscriber'}=0;
447             }
448             }
449             elsif ($self->{'inProgresslist'} >= 1)
450             {
451 0 0         if ($tagname eq 'div')
452             {
453 0           $self->{'inProgresslist'}--;
454 0 0         if ($self->{'inProgresslist'} == 0)
455             {
456 0           $self->{'amountItems'}=0;
457             }
458             }
459 0 0         if ($self->{'inProgressheading'} == 1)
460             {
461 0 0         if ($tagname eq 'h3')
462             {
463 0           $self->{'inProgressheading'}=0;
464             }
465             }
466             }
467             }
468              
469             ## methods for parsing websms_send.php for the token
470             sub websmsGetTokenStartTagParse
471             {
472 0     0 0   my ($self, $tagname, $attr) = @_;
473              
474 0 0         if ($self->{'inWebsmsSendForm'} != 1)
475             {
476 0 0         if ($tagname eq 'form')
477             {
478 0 0         if ($attr->{'action'} eq 'websms_send.php')
479             {
480 0           $self->{'inWebsmsSendForm'} = 1,
481             }
482             }
483             }
484             else
485             {
486 0 0         if ($tagname eq 'input')
487             {
488 0 0 0       if (($attr->{'type'} eq 'hidden') &&
489             ($attr->{'name'} eq 'token'))
490             {
491 0           $self->{'yesssSMSself'}->{'websmsToken'}=$attr->{'value'};
492             }
493             }
494             }
495             }
496              
497             sub websmsGetTokenEndTagParse
498             {
499 0     0 0   my ($self, $tagname) = @_;
500              
501 0 0         if ($self->{'inWebsmsSendForm'} == 1)
502             {
503 0 0         if ($tagname eq 'form')
504             {
505 0           $self->{'inWebsmsSendForm'} = 0;
506             }
507             }
508             }
509              
510              
511             sub trim
512             {
513 0     0 0   my $string=$_[0];
514              
515 0           $$string =~ s/^\s+//;
516 0           $$string =~ s/\s+$//;
517             }
518              
519             1;
520             __END__