File Coverage

lib/Mailru/Cloud/Auth.pm
Criterion Covered Total %
statement 37 108 34.2
branch 0 48 0.0
condition 1 8 12.5
subroutine 11 16 68.7
pod 1 3 33.3
total 50 183 27.3


line stmt bran cond sub pod time code
1             package Mailru::Cloud::Auth;
2              
3 1     1   77301 use 5.008001;
  1         4  
4 1     1   5 use strict;
  1         2  
  1         37  
5 1     1   7 use warnings;
  1         2  
  1         38  
6 1     1   870 use utf8;
  1         15  
  1         5  
7 1     1   594 use open qw(:std :utf8);
  1         1279  
  1         5  
8 1     1   1027 use LWP::UserAgent;
  1         49859  
  1         35  
9 1     1   7 use HTTP::Request;
  1         2  
  1         28  
10 1     1   856 use JSON::XS;
  1         5652  
  1         56  
11 1     1   7 use URI::Escape;
  1         13  
  1         56  
12 1     1   11 use Carp qw/carp croak/;
  1         2  
  1         1639  
13              
14             our $VERSION = '0.10';
15              
16             sub new {
17 1     1 0 721 my ($class, %opt) = @_;
18 1   50     10 my $max_redirect = $opt{'-max_redirect'} // 30;
19 1         2 my $self = {};
20 1         4 $self->{debug} = $opt{-debug};
21 1         8 my $ua = LWP::UserAgent->new (
22             agent => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36',
23             cookie_jar => {},
24             );
25 1         11494 $self->{ua} = $ua;
26 1         4 $self->{ua}->max_redirect($max_redirect);
27 1         24 return bless $self, $class;
28             }
29              
30             sub login {
31 0     0 1   my ($self, %opt) = @_;
32 0   0       $self->{login} = $opt{-login} || $self->{login} || croak "You must specify -login opt for 'login' method";
33 0   0       $self->{password} = $opt{-password} || $self->{password} || croak "You must specify -password opt for 'login' method";
34 0           my $res;
35              
36             #Get login token
37 0           $res = $self->{ua}->get('https://mail.ru');
38 0 0         if ($res->code ne '200') {
39 0           croak "Can't get start mail.ru page. Code: " . $res->code;
40             }
41              
42 0           my $login_token;
43              
44             # В бровзере ловится вот этой регулярочкой
45 0 0         if ($res->decoded_content =~ /CSRF\s*=\s*\"([a-f|A-F|0-9]+)\"/) {
    0          
46 0           $login_token = $1;
47             # В этом скрипте - почему-то вот этой
48             } elsif ($res->decoded_content =~ /CSRF:\s+\"([a-f|A-F|0-9]+)\"/) {
49 0           $login_token = $1;
50             } else {
51 0           croak "Can't found login token";
52             }
53              
54             #Login
55             my $param = {
56             'login' => $self->{login},
57             'password' => $self->{password},
58 0           'saveauth' => 1,
59             'project' => 'e.mail.ru',
60             'token' => $login_token,
61             };
62              
63 0           my %headers = (
64             'Referer' => 'https://mail.ru/?from=logout',
65             'Origin' => 'https://mail.ru',
66             );
67              
68 0           $res = $self->{ua}->post('https://auth.mail.ru/jsapi/auth', $param, %headers);
69 0 0         if ($res->code ne '200') {
70 0           croak "Wrong response code from login form: " . $res->code;
71             }
72              
73 0           my $json = decode_json($res->decoded_content);
74 0 0         if ($json->{status} eq 'fail') {
75 0           croak "Fail login: $json->{code}";
76             }
77              
78 0 0         $self->__getToken() or return;
79 0           return $self->{authToken};
80             }
81              
82             sub __getToken {
83 0     0     my $self = shift;
84              
85 0           my $res = $self->{ua}->get('https://auth.mail.ru/sdc?from=' . uri_escape('https://cloud.mail.ru/?from=promo&from=authpopup') );
86              
87 0 0         if ($res->is_success) {
88 0           my $content = $res->decoded_content;
89 0 0         if ($content =~ /\"csrf\"\s*\:\s*\"([0-9|a-z|A-Z|_]+)\"/) {
90 0           $self->{authToken} = $1;
91 0 0         carp "Found authToken: $self->{authToken}" if $self->{debug};
92              
93 0 0         if ($content =~ /\"email\"\s*:\s*\"(.+?)\"/) {
94 0           $self->{email} = $1;
95 0 0         carp "Found email: $self->{email}" if $self->{debug};
96              
97             #Get BUILD
98 0           $self->{build} = 'hotfix_CLOUDWEB-7726_50-0-3.201710311503';
99 0 0         if ($content =~ /\"BUILD\"\s*:\s*\"(.+?)\"/) {
100 0           $self->{build} = $1;
101 0 0         carp "Found and use new build $self->{build}" if $self->{debug};
102             }
103              
104             #Get x-page-id
105 0           $self->{'x-page-id'} = 'f9jfLFeHA5';
106 0 0         if ($content =~ /\"x\-page\-id\"\s*:\s*\"(.+?)\"/) {
107 0           $self->{'x-page-id'} = $1;
108 0 0         carp "Found and use new x-page_id $self->{build}" if $self->{debug};
109             }
110              
111             #Parse free space info
112 0           $self->{info} = __parseInfo(\$content);
113 0           return 1;
114             }
115              
116             }
117             }
118 0           return;
119             }
120              
121             sub info {
122 0     0 0   my $self = shift;
123 0 0         if ($self->{info}) {
124 0           my %info = map {$_, $self->{info}->{$_}} keys %{$self->{info}};
  0            
  0            
125 0           return \%info;
126             }
127 0           return;
128             }
129              
130             sub __parseInfo {
131 0     0     my $content = shift;
132 0           my %info = (
133             'used_space' => '',
134             'total_space' => '',
135             'file_size_limit' => '',
136             );
137              
138 0 0         if (my ($size_block) = $$content =~ /"space":\s*{([^}]*)}/s) {
139 0           while ($size_block =~ /"([^"]+)":\s*(\w+?)\b/gm) {
140 0 0         if ($1 eq 'bytes_total') {
    0          
141 0           $info{total_space} = $2;
142             }
143             elsif ($1 eq 'bytes_used') {
144 0           $info{used_space} = $2;
145             }
146             }
147             }
148              
149 0 0         if ($$content =~ /"file_size_limit":\s*(.+?)[,\s]/) {
150 0           $info{file_size_limit} = $1;
151             }
152 0           return \%info;
153             }
154              
155             sub __isLogin {
156 0     0     my $self = shift;
157 0 0         if ($self->{authToken}) {
158 0           my $ua = $self->{ua};
159 0           my $res = $ua->get('https://auth.mail.ru/cgi-bin/auth?mac=1&Login=' . uri_escape($self->{login}));
160 0           my $code = $res->code;
161 0 0         if ($code ne '200') {
162 0           croak "Can't get status about login";
163             }
164 0           my $json_res = decode_json($res->content);
165 0 0         $json_res->{status} eq 'ok' and return 1;
166 0 0         $self->login() and return 1;
167             }
168              
169 0           croak "Not logined";
170             }
171              
172             1;
173              
174              
175             __END__