File Coverage

blib/lib/yesssSMS.pm
Criterion Covered Total %
statement 17 208 8.1
branch 0 92 0.0
condition 0 30 0.0
subroutine 6 23 26.0
pod 9 16 56.2
total 32 369 8.6


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