File Coverage

blib/lib/Mail/Webmail/Gmail.pm
Criterion Covered Total %
statement 6 880 0.6
branch 0 374 0.0
condition 0 61 0.0
subroutine 2 31 6.4
pod 0 29 0.0
total 8 1375 0.5


line stmt bran cond sub pod time code
1             package Mail::Webmail::Gmail;
2            
3 1     1   11381 use lib qw(lib);
  1         1084  
  1         7  
4 1     1   274 use strict;
  1         2  
  1         12695  
5            
6             require LWP::UserAgent;
7             require HTTP::Headers;
8             require HTTP::Cookies;
9             require HTTP::Request::Common;
10             require Crypt::SSLeay;
11             require Exporter;
12            
13             our $VERSION = "1.09";
14            
15             our @ISA = qw(Exporter);
16             our @EXPORT_OK = ();
17             our @EXPORT = ();
18            
19             our $USER_AGENT = "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.8) Gecko/20050511 Firefox/1.0.4";
20             our $MAIL_URL = "http://mail.google.com/mail";
21             our $SSL_MAIL_URL = "https://mail.google.com/mail";
22             our $LOGIN_URL = "https://www.google.com/accounts/ServiceLoginBoxAuth";
23            
24             our %FOLDERS = (
25             'INBOX' => '^I',
26             'STARRED' => '^T',
27             'SPAM' => '^S',
28             'TRASH' => '^K',
29             );
30            
31             sub new {
32 0     0 0   my $class = shift;
33 0           my %args = @_;
34            
35 0           my $ua = new LWP::UserAgent( agent => $USER_AGENT, keep_alive => 1 );
36 0 0         $ua->timeout( $args{timeout} ) if defined $args{timeout};
37            
38 0           push( @LWP::Protocol::http::EXTRA_SOCK_OPTS, SendTE => 0 );
39            
40 0 0 0       my $self = bless {
      0        
      0        
      0        
      0        
      0        
      0        
41             _username => $args{username} || die( 'No username defined' ),
42             _password => $args{password} || die( 'No password defined' ),
43             _login_url => $args{login_server} || $LOGIN_URL,
44             _mail_url => $args{mail_server} || $args{encrypt_session} ? $SSL_MAIL_URL : $MAIL_URL,
45             _proxy_user => $args{proxy_username} || '',
46             _proxy_pass => $args{proxy_password} || '',
47             _proxy_name => $args{proxy_name} || '',
48             _proxy_enable => 0,
49             _logged_in => 0,
50             _err_str => '',
51             _cookies => { },
52             _ua => $ua,
53             _debug_level => 0,
54             _error => 0,
55             }, $class;
56            
57 0 0         if ( defined( $args{proxy_name} ) ) {
58 0           $self->{_proxy_enable}++;
59 0 0 0       if ( defined( $args{proxy_username} ) && defined( $args{proxy_password} ) ) {
60 0           $self->{_proxy_enable}++;
61             }
62             }
63            
64 0           return $self;
65             }
66            
67             sub error {
68 0     0 0   my ( $self ) = @_;
69 0           return( $self->{_error} );
70             }
71            
72             sub error_msg {
73 0     0 0   my ( $self ) = @_;
74 0           my $error_msg = $self->{_err_str};
75            
76 0           $self->{_error} = 0;
77 0           $self->{_err_str} = '';
78 0           return( $error_msg );
79             }
80            
81             sub login {
82 0     0 0   my ( $self ) = @_;
83            
84 0 0         return 0 if $self->{_logged_in};
85            
86 0 0 0       if ( $self->{_proxy_enable} && $self->{_proxy_enable} >= 1 ) {
87 0           $ENV{HTTPS_PROXY} = $self->{_proxy_name};
88 0 0 0       if ( $self->{_proxy_enable} && $self->{_proxy_enable} >= 2 ) {
89 0           $ENV{HTTPS_PROXY_USERNAME} = $self->{_proxy_user};
90 0           $ENV{HTTPS_PROXY_PASSWORD} = $self->{_proxy_pass};
91             }
92             }
93            
94 0           my $req = HTTP::Request->new( POST => $self->{_login_url} );
95 0           $req->header( 'Cookie' => $self->{_cookie} );
96 0           my ( $cookie );
97            
98 0           $req->content_type( "application/x-www-form-urlencoded" );
99 0           $req->content( 'Email=' . $self->{_username} . '&Passwd=' . $self->{_password} . '&null=Sign+in' );
100            
101 0           my $res = $self->{_ua}->request( $req );
102            
103 0 0         if ( !$res->is_success() ) {
104 0           $self->{_error} = 1;
105 0           $self->{_err_str} .= "Error: Could not login with those credentials - the request was not a success\n";
106 0           $self->{_err_str} .= " Additionally, HTTP error: " . $res->status_line . "\n";
107 0           return;
108             }
109            
110 0           update_tokens( $self, $res );
111 0 0         if ( $res->content() !~ /var url = (["'])(.*?)\1/ ) {
112 0           $self->{_error} = 1;
113 0           $self->{_err_str} .= "Error: Could not login with those credentials - could not find final URL\n";
114 0           $self->{_err_str} .= " Additionally, HTTP error: " . $res->status_line . "\n";
115 0           return;
116             }
117            
118 0           my $final_url;
119 0           ( $final_url = $2 ) =~ s/\\u003d/=/;
120            
121 0           $req = HTTP::Request->new( GET => $final_url );
122 0           $req->header( 'Cookie' => $self->{_cookie} );
123 0           $res = $self->{_ua}->request( $req );
124             # if ( ( $res->content() !~ / (?:.*?) <\/a>/ ) &&
125             # ( $res->content() !~ /(?:.*?)<\/a>/ ) ) {
126             # $self->{_error} = 1;
127             # $self->{_err_str} .= "Error: Could not login with those credentials - could not find Gmail account.\n";
128             # $self->{_err_str} .= " Additionally, HTTP error: " . $res->status_line . "\n";
129             # return;
130             # }
131 0           update_tokens( $self, $res );
132            
133 0           $req = HTTP::Request->new( GET => 'http://mail.google.com/mail?view=pr&fs=1' );
134 0           $req->header( 'Cookie' => $self->{_cookie} );
135 0           $res = $self->{_ua}->request( $req );
136 0 0         if ( $res->content() !~ /top.location="(.*?)"/ ) {
137 0           $self->{_error} = 1;
138 0           $self->{_err_str} .= "Error: Could not login with those credentials - could not find 'top.location'\n";
139 0           $self->{_err_str} .= " Additionally, HTTP error: " . $res->status_line . "\n";
140 0           return;
141             }
142 0           update_tokens( $self, $res );
143            
144 0           $final_url = ( URI::Escape::uri_unescape( $1 ) );
145 0 0         if ( $self->{_proxy_enable} ) {
146 0 0         if ( $self->{_proxy_enable} >= 1 ) {
147 0           $self->{_ua}->proxy( 'http', $self->{_proxy_name} );
148 0           delete ( $ENV{HTTPS_PROXY} );
149             }
150 0 0         if ( $self->{_proxy_enable} >= 2 ) {
151 0           delete ( $ENV{HTTPS_PROXY_USERNAME} );
152 0           delete ( $ENV{HTTPS_PROXY_PASSWORD} );
153             }
154             }
155            
156 0           $self->{_logged_in} = 1;
157 0           $res = get_page( $self, search => '', start => '', view => '', req_url => $final_url );
158 0           $res = get_page( $self, search => 'inbox' );
159            
160 0           return ( 1 );
161             }
162            
163             sub check_login {
164 0     0 0   my ( $self ) = @_;
165            
166 0 0         if ( !$self->{_logged_in} ) {
167 0 0         unless ( $self->login() ) {
168 0           $self->{_error} = 1;
169 0           $self->{_err_str} .= "Error: Could not Login.\n";
170 0           return;
171             }
172             }
173 0           return ( $self->{_logged_in} );
174             }
175            
176             sub update_tokens {
177 0     0 0   my ( $self, $res ) = @_;
178            
179 0           my $previous = $res->previous();
180 0 0         if ( $previous ) {
181 0           update_tokens( $self, $previous );
182             }
183 0           my $header = $res->header( 'Set-Cookie' );
184 0 0         if ( defined( $header ) ) {
185 0           my ( @cookies ) = split( ',', $header );
186 0           foreach( @cookies ) {
187 0           $_ =~ s/^\s*//;
188 0 0         if ( $_ =~ /(.*?)=(.*?);/ ) {
189 0 0         if ( $2 eq '' ) {
190 0           delete( $self->{_cookies}->{$1} );
191             } else {
192 0 0         unless ( $1 =~ /\s/ ) {
193 0 0         if ( $1 ne '' ) {
194 0           $self->{_cookies}->{$1} = $2;
195             } else {
196 0           $self->{_cookies}->{'Session'} = $2;
197             }
198             }
199             }
200             }
201             }
202 0           $self->{_cookie} = join( '; ', map{ "$_=$self->{_cookies}->{$_}"; }( sort keys %{ $self->{_cookies} } ) );
  0            
  0            
203             }
204             }
205            
206             sub get_page {
207 0     0 0   my ( $self ) = shift;
208 0           my ( %args ) = (
209             search => 'all',
210             view => 'tl',
211             start => 0,
212             method => '',
213             req_url => $self->{_mail_url},
214             @_, );
215 0           my ( $res, $req, $req_url, @tees );
216            
217 0 0         unless ( check_login( $self ) ) { return };
  0            
218            
219 0 0         if ( defined( $args{ 'label' } ) ) {
220 0           $args{ 'label' } = validate_label( $self, $args{ 'label' } );
221 0 0         if ( $self->error ) {
222 0           return;
223             } else {
224 0           $args{ 'cat' } = $args{ 'label' };
225 0           delete( $args{ 'label' } );
226 0           $args{ 'search' } = 'cat';
227             }
228             }
229            
230 0 0         if ( defined( $args{ 't' } ) ) {
231 0 0         if ( ref( $args{ 't' } ) eq 'ARRAY' ) {
232 0           foreach ( @{ $args{ 't' } } ) {
  0            
233 0           push( @tees, 't' );
234 0           push( @tees, $_ );
235             }
236 0           delete( $args{ 't' } );
237             }
238             }
239            
240 0           $req_url = $args{ 'req_url' };
241 0           delete( $args{ 'req_url' } );
242            
243 0           my ( $url, $method, $view ) = '' x 3;
244            
245 0           $method = $args{ 'method' };
246 0           delete( $args{ 'method' } );
247            
248 0 0         if ( $method eq 'post' ) {
249 0           $view = $args{ 'view' };
250 0           delete( $args{ 'view' } );
251             }
252            
253 0           foreach ( keys %args ) {
254 0 0         if ( defined( $args{ $_ } ) ) {
255 0 0         if ( $args{ $_ } eq '' ) {
256 0           delete( $args{ $_ } );
257             }
258             } else {
259 0           delete( $args{ $_ } );
260             }
261             }
262            
263 0 0         if ( $method eq 'post' ) {
264 0           $req = HTTP::Request::Common::POST( $req_url,
265             Content_Type => 'multipart/form-data',
266             Connection => 'Keep-Alive',
267             'Keep-Alive' => 300,
268             Cookie => $self->{_cookie},
269             Content => [ view => $view, %args, @tees ] );
270 0 0 0       if ( $self->{_proxy_enable} && $self->{_proxy_enable} >= 2 ) {
271 0           $req->proxy_authorization_basic( $self->{_proxy_user}, $self->{_proxy_pass} );
272             }
273 0           $res = $self->{_ua}->request( $req );
274             } else {
275 0           $url = join( '&', map{ "$_=$args{ $_ }"; }( keys %args ) );
  0            
276 0 0         if ( $url ne '' ) {
277 0           $url = '?' . $url;
278             }
279 0           $req = HTTP::Request->new( GET => $req_url . "$url" );
280 0           $req->header( 'Cookie' => $self->{_cookie} );
281 0 0 0       if ( $self->{_proxy_enable} && $self->{_proxy_enable} >= 2 ) {
282 0           $req->proxy_authorization_basic( $self->{_proxy_user}, $self->{_proxy_pass} );
283             }
284 0           $res = $self->{_ua}->request( $req );
285             }
286            
287 0 0         if ( $res ) {
288 0 0         if ( $res->is_success() ) {
    0          
289 0           update_tokens( $self, $res );
290             } elsif ( $res->previous() ) {
291 0           update_tokens( $self, $res->previous() );
292             }
293             }
294            
295 0           return ( $res );
296             }
297            
298             sub size_usage {
299 0     0 0   my ( $self, $res ) = @_;
300            
301 0 0         unless ( check_login( $self ) ) { return };
  0            
302            
303 0 0         unless ( $res ) {
304 0           $res = get_page( $self );
305             }
306            
307 0           my %functions = %{ parse_page( $self, $res ) };
  0            
308            
309 0 0         if ( $self->{_error} ) {
310 0           return;
311             }
312            
313 0 0         if ( $res->is_success() ) {
314 0 0         if ( defined( $functions{ 'qu' } ) ) {
315 0 0         if ( wantarray ) {
316 0           pop( @{ $functions{ 'qu' } } );
  0            
317 0           foreach ( @{ $functions{ 'qu' } } ) {
  0            
318 0           s/"//g;
319             }
320 0           return( @{ $functions{ 'qu' } } );
  0            
321             } else {
322 0           $functions{ 'qu' }[0] =~ /"(.*)\s/;
323 0           my $used = $1;
324 0           $functions{ 'qu' }[1] =~ /"(.*)\s/;
325 0           my $size = $1;
326 0           return( $size - $used );
327             }
328             } else {
329 0           $self->{_error} = 1;
330 0           $self->{_err_str} .= "Error: Could not find free space info.\n";
331 0           return;
332             }
333             } else {
334 0           $self->{_error} = 1;
335 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
336 0           return;
337             }
338             }
339            
340             sub edit_labels {
341 0     0 0   my ( $self ) = shift;
342 0           my ( %args ) = (
343             start => '',
344             search => '',
345             action => '',
346             label => '',
347             new_name => '',
348             view => 'up',
349             method => 'post',
350             @_,
351             );
352            
353 0 0         unless ( check_login( $self ) ) { return };
  0            
354            
355 0           my $action;
356            
357 0 0         if ( uc( $args{ 'action' } ) eq 'CREATE' ) {
    0          
    0          
    0          
    0          
358 0           $action = 'cc_';
359 0           $args{ 'new_name' } = '';
360             } elsif ( uc( $args{ 'action' } ) eq 'DELETE' ) {
361 0           $action = 'dc_';
362 0           $args{ 'new_name' } = '';
363             } elsif ( uc( $args{ 'action' } ) eq 'REMOVE' ) {
364 0           $action = 'rc_';
365 0           $args{ 'new_name' } = '';
366             } elsif ( uc( $args{ 'action' } ) eq 'ADD' ) {
367 0           $action = 'ac_';
368 0           $args{ 'new_name' } = '';
369 0 0         unless ( defined( $args{ 'msgid' } ) ) {
370 0           $self->{_error} = 1;
371 0           $self->{_err_str} .= "To add a label to a message, you must supply a msgid.\n";
372 0           return;
373             } else {
374 0           $args{ 't' } = $args{ 'msgid' };
375 0           delete( $args{ 'msgid' } );
376 0           $args{ 'search' } = 'all';
377             }
378             } elsif ( uc( $args{ 'action' } ) eq 'RENAME' ) {
379 0           $args{ 'new_name' } = '^' . validate_label( $self, $args{ 'new_name' } );
380 0 0         if ( $self->{_error} ) {
381 0           return;
382             }
383 0           $action = 'nc_';
384             } else {
385 0           $self->{_error} = 1;
386 0           $self->{_err_str} .= "Error: No action defined.\n";
387 0           return;
388             }
389            
390 0           $args{ 'act' } = $action . validate_label( $self, $args{ 'label' } ) . $args{ 'new_name' };
391 0 0         if ( $self->{_error} ) {
392 0           return;
393             } else {
394 0           delete( $args{ 'label' } );
395 0           delete( $args{ 'action' } );
396 0           $args{ 'at' } = $self->{_cookies}->{GMAIL_AT};
397             }
398            
399 0           my $res = get_page( $self, %args );
400            
401 0 0         if ( $res->is_success() ) {
402 0           my %functions = %{ parse_page( $self, $res ) };
  0            
403 0 0         if ( defined( $functions{ 'ar' } ) ) {
404 0 0         unless ( $functions{ 'ar' }->[0] ) {
405 0           $self->{_error} = 1;
406 0           $self->{_err_str} .= "Error: " . $functions{ 'ar' }->[1] . "\n";
407 0           return;
408             } else {
409 0           return( 1 );
410             }
411             } else {
412 0           $self->{_error} = 1;
413 0           $self->{_err_str} .= "Error: Could not find label success message.\n";
414 0           return;
415             }
416             } else {
417 0           $self->{_error} = 1;
418 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
419 0           return;
420             }
421             }
422            
423             sub get_labels {
424 0     0 0   my ( $self, $res ) = @_;
425            
426 0 0         unless ( check_login( $self ) ) { return };
  0            
427            
428 0 0         unless ( $res ) {
429 0           $res = get_page( $self, search => 'inbox' );
430             }
431            
432 0 0         if ( $res->is_success() ) {
433 0           my %functions = %{ parse_page( $self, $res ) };
  0            
434            
435 0 0         if ( $self->{_error} ) {
436 0           return;
437             }
438            
439 0 0         unless ( defined( $functions{ 'ct' } ) ) {
440 0           return;
441             }
442            
443 0           my @fields = @{ extract_fields( $functions{ 'ct' }->[0] ) };
  0            
444 0           foreach ( @fields ) {
445 0           $_ = ${ extract_fields( $_ ) }[0];
  0            
446 0           $_ = remove_quotes( $_ );
447             }
448 0 0         if ( @fields ) {
449 0           return( @fields );
450             } else {
451 0           $self->{_error} = 1;
452 0           $self->{_err_str} .= "Error: No Labels found.\n";
453 0           return;
454             }
455             } else {
456 0           $self->{_error} = 1;
457 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
458 0           return;
459             }
460             }
461            
462             sub validate_label {
463 0     0 0   my ( $self, $label ) = @_;
464            
465 0 0         if ( defined( $label ) ) {
466 0           $label =~ s/^\s//;
467 0           $label =~ s/\s$//;
468 0 0         if ( $label =~ /\^/ ) {
469 0           my $is_folder = 0;
470 0           foreach ( keys %FOLDERS ) {
471 0 0         if ( $FOLDERS{ $_ } eq uc( $label ) ) {
472 0           $is_folder = 1;
473             }
474             }
475 0 0         unless ( $is_folder ) {
476 0           $self->{_error} = 1;
477 0           $self->{_err_str} .= "Error: Labels cannot contain the character '^'.\n";
478 0           return;
479             }
480             }
481 0 0         if ( length( $label ) > 40 ) {
482 0           $self->{_error} = 1;
483 0           $self->{_err_str} .= "Error: Labels cannot contain more than 40 characters.\n";
484 0           return;
485             }
486 0 0         if ( length( $label ) == 0 ) {
487 0           $self->{_error} = 1;
488 0           $self->{_err_str} .= "Error: No labels specified.\n";
489 0           return;
490             }
491 0           return( $label );
492             } else {
493 0           $self->{_error} = 1;
494 0           $self->{_err_str} .= "Error: No labels specified.\n";
495 0           return;
496             }
497             }
498            
499             sub edit_star {
500 0     0 0   my ( $self ) = shift;
501 0           my ( %args ) = (
502             start => '',
503             action => '',
504             view => 'up',
505             @_,
506             );
507            
508 0 0         unless ( check_login( $self ) ) { return };
  0            
509            
510 0           my $action;
511            
512 0 0         if ( $args{ 'action' } eq 'add' ) {
    0          
513 0           $args{ 'act' } = 'st';
514             } elsif ( $args{ 'action' } eq 'remove' ) {
515 0           $args{ 'act' } = 'xst';
516             } else {
517 0           $self->{_error} = 1;
518 0           $self->{_err_str} .= "Error: No action defined.\n";
519 0           return;
520             }
521 0           delete( $args{ 'action' } );
522            
523 0 0         if ( defined( $args{ 'msgid' } ) ) {
524 0           $args{ 'm' } = $args{ 'msgid' };
525 0           delete( $args{ 'msgid' } );
526             } else {
527 0           $self->{_error} = 1;
528 0           $self->{_err_str} .= "Error: No msgid sent.\n";
529 0           return;
530             }
531            
532 0           $args{ 'at' } = $self->{_cookies}->{GMAIL_AT};
533            
534 0           my $res = get_page( $self, %args );
535            
536 0 0         if ( $res->is_success() ) {
537 0           my %functions = %{ parse_page( $self, $res ) };
  0            
538 0 0         if ( defined( $functions{ 'ar' } ) ) {
539 0 0         unless ( $functions{ 'ar' }->[0] ) {
540 0           $self->{_error} = 1;
541 0           $self->{_err_str} .= "Error: " . $functions{ 'ar' }->[1] . "\n";
542 0           return;
543             } else {
544 0           return( 1 );
545             }
546             } else {
547 0           $self->{_error} = 1;
548 0           $self->{_err_str} .= "Error: Could not find label success message.\n";
549 0           return;
550             }
551             } else {
552 0           $self->{_error} = 1;
553 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
554 0           return;
555             }
556             }
557            
558             sub edit_archive {
559 0     0 0   my ( $self ) = shift;
560 0           my ( %args ) = (
561             action => '',
562             msgid => '',
563             method => 'post',
564             @_,
565             );
566            
567 0 0         unless ( check_login( $self ) ) { return };
  0            
568            
569 0 0         if ( $args{ 'action' } eq 'archive' ) {
    0          
570 0           $args{ 'act' } = 'rc_' . lc( $FOLDERS{ 'INBOX' } );
571             } elsif ( $args{ 'action' } eq 'unarchive' ) {
572 0           $args{ 'act' } = 'ib';
573             } else {
574 0           $self->{_error} = 1;
575 0           $self->{_err_str} .= "Error: No action defined.\n";
576 0           return;
577             }
578 0           delete( $args{ 'action' } );
579            
580 0 0         if ( defined( $args{ 'msgid' } ) ) {
581 0           $args{ 't' } = $args{ 'msgid' };
582 0           delete( $args{ 'msgid' } );
583             } else {
584 0           $self->{_error} = 1;
585 0           $self->{_err_str} .= "Error: No msgid sent.\n";
586 0           return;
587             }
588            
589 0           $args{ 'at' } = $self->{_cookies}->{GMAIL_AT};
590            
591 0           my $res = get_page( $self, %args );
592            
593 0 0         if ( $res->is_success() ) {
594 0           my %functions = %{ parse_page( $self, $res ) };
  0            
595 0 0         if ( defined( $functions{ 'ar' } ) ) {
596 0 0         unless ( $functions{ 'ar' }->[0] ) {
597 0           $self->{_error} = 1;
598 0           $self->{_err_str} .= "Error: " . $functions{ 'ar' }->[1] . "\n";
599 0           return;
600             } else {
601 0           return( 1 );
602             }
603             } else {
604 0           $self->{_error} = 1;
605 0           $self->{_err_str} .= "Error: Could not find archive success message.\n";
606 0           return;
607             }
608             } else {
609 0           $self->{_error} = 1;
610 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
611 0           return;
612             }
613             }
614            
615             sub multi_email_addr {
616 0     0 0   my $array_ref = shift;
617            
618 0           my $email_list;
619 0           foreach( @{ $array_ref } ) {
  0            
620 0           $email_list .= "<$_>, ";
621             }
622 0           return( $email_list );
623             }
624            
625             sub send_message {
626 0     0 0   my ( $self ) = shift;
627 0           my ( %args ) = (
628             start => '',
629             search => '',
630             action => '',
631             view => 'sm',
632             cmid => '1' || $_{cmid},
633             to => '' || $_{to},
634             cc => '' || $_{cc},
635             bcc => '' || $_{bcc},
636             subject => '' || $_{subject},
637             msgbody => '' || $_{msgbody},
638             method => 'post',
639             @_,
640             );
641            
642 0 0         unless ( check_login( $self ) ) { return };
  0            
643            
644 0           $args{ 'at' } = $self->{_cookies}->{GMAIL_AT};
645            
646 0 0 0       if ( ( $args{to} ne '' ) || ( $args{cc} ne '' ) || ( $args{bcc} ne '' ) ) {
      0        
647 0           foreach( 'to', 'cc', 'bcc' ) {
648 0 0         if ( ref( $args{$_} ) eq 'ARRAY' ) {
649 0           $args{$_} = multi_email_addr( $args{$_} );
650             }
651             }
652            
653 0           foreach( keys %args ) {
654 0 0         if ( defined( $args{ $_ } ) ) {
655 0           $args{ $_ } =~ s/&/%26/g;
656             }
657             }
658            
659 0           my $res = get_page( $self, %args );
660 0 0         if ( $res->is_success() ) {
661 0           my %functions = %{ parse_page( $self, $res ) };
  0            
662            
663 0 0         if ( $self->{_error} ) {
664 0           return;
665             }
666 0 0         unless ( defined( $functions{ 'sr' } ) ) {
667 0           return;
668             }
669 0 0         if ( $functions{ 'sr' }->[1] ) {
670 0 0         if ( $functions{ 'sr' }->[3] eq '"0"' ) {
671 0           $self->{_error} = 1;
672 0           $self->{_err_str} .= "This message has already been sent.\n";
673 0           return;
674             } else {
675 0           $functions{ 'sr' }->[3] =~ s/"//g;
676 0           return( $functions{ 'sr' }->[3] );
677             }
678             } else {
679 0           $self->{_error} = 1;
680 0           $self->{_err_str} .= "Message could not be sent.\n";
681 0           return;
682             }
683             }
684             } else {
685 0           $self->{_error} = 1;
686 0           $self->{_err_str} .= "One of the following must be filled out: to, cc, bcc.\n";
687 0           return;
688             }
689             }
690            
691             sub get_messages {
692 0     0 0   my ( $self ) = shift;
693 0           my ( %args ) = (
694             init => 1,
695             start => 0,
696             @_, );
697 0           my ( $res, $req );
698            
699 0 0         if ( defined( $args{ 'label' } ) ) {
700 0           $args{ 'label' } = validate_label( $self, $args{ 'label' } );
701 0 0         if ( $self->error ) {
702 0           return;
703             } else {
704 0           $args{ 'cat' } = $args{ 'label' };
705 0           delete( $args{ 'label' } );
706 0           $args{ 'search' } = 'cat';
707             }
708             }
709            
710 0 0         unless ( check_login( $self ) ) { return };
  0            
711            
712 0           $res = get_page( $self, %args );
713            
714 0 0         if ( $res->is_success() ) {
715 0           my %functions = %{ parse_page( $self, $res ) };
  0            
716            
717 0 0         if ( $self->{_error} ) {
718 0           return;
719             }
720 0           my ( @emails, @letters );
721            
722 0 0         unless ( defined( $functions{ 't' } ) ) {
723 0           return;
724             }
725            
726 0           foreach ( @{ $functions{ 't' } } ) {
  0            
727 0           my @email_line = @{ extract_fields( $_ ) };
  0            
728 0           my %indv_email;
729 0           $indv_email{ 'id' } = remove_quotes( $email_line[0] );
730 0           $indv_email{ 'new' } = remove_quotes( $email_line[1] );
731 0           $indv_email{ 'starred' } = remove_quotes( $email_line[2] );
732 0           $indv_email{ 'date_received' } = remove_quotes( $email_line[3] );
733 0           $indv_email{ 'sender_email' } = remove_quotes( $email_line[4] );
734 0           $indv_email{ 'sender_email' } =~ /\\"(.*?)\\">/;
735 0           $1 =~ /_(?:.*?)_(.*?)$/;
736 0           $indv_email{ 'sender_email' } = $1;
737 0           $indv_email{ 'sender_name' } = remove_quotes( $email_line[4] );
738 0           $indv_email{ 'sender_name' } =~ />(?:)?(.*?)<\//;
739 0           $indv_email{ 'sender_name' } = $1;
740 0           $indv_email{ 'subject' } = remove_quotes( $email_line[6] );
741 0           $indv_email{ 'blurb' } = remove_quotes( $email_line[7] );
742 0           $indv_email{ 'labels' } = [ map{ remove_quotes( $_ ) }@{ extract_fields( $email_line[8] ) } ];
  0            
  0            
743 0           $email_line[9] = remove_quotes( $email_line[9] );
744 0 0         $indv_email{ 'attachments' } = extract_fields( $email_line[9] ) if ( $email_line[9] ne '' );
745 0           push ( @emails, \%indv_email );
746             }
747 0 0 0       if ( ( @emails == @{ $functions{ 'ts' } }[1] ) && ( @{ $functions{ 'ts' } }[0] != @{ $functions{ 'ts' } }[2] ) ) {
  0            
  0            
  0            
748 0           my $start = $args{ 'start' };
749 0           delete( $args{ 'start' } );
750 0 0         if ( $args{ 'cat' } ) {
751 0           $args{ 'label' } = $args{ 'cat' };
752 0           delete ( $args{ 'cat' } );
753 0           delete ( $args{ 'search' } );
754             }
755 0           my $next_page_emails = get_messages( $self, start => ( $start + @emails ), %args );
756 0 0         if ( $next_page_emails ) {
757 0           @emails = ( @emails, @{ $next_page_emails } );
  0            
758             }
759             }
760 0           return ( \@emails );
761             } else {
762 0           $self->{_error} = 1;
763 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
764 0           return;
765             }
766             }
767            
768             sub delete_message {
769 0     0 0   my ( $self ) = shift;
770 0           my ( %args ) = (
771             act => 'tr',
772             method => 'post',
773             at => '',
774             del_message => 1,
775             @_, );
776            
777 0 0         if ( defined( $args{ 'msgid' } ) ) {
778 0           $args{ 't' } = $args{ 'msgid' };
779 0           delete( $args{ 'msgid' } );
780             } else {
781 0           $self->{_error} = 1;
782 0           $self->{_err_str} .= "Error: No msgid provided.\n";
783 0           return;
784             }
785            
786 0           my $del_message = $args{ 'del_message' };
787 0           delete( $args{ 'del_message' } );
788            
789 0 0         unless ( check_login( $self ) ) { return };
  0            
790            
791 0           $args{ 'at' } = $self->{_cookies}->{GMAIL_AT};
792            
793 0           my $res = get_page( $self, %args );
794            
795 0 0         if ( $res->is_success() ) {
796 0           my %functions = %{ parse_page( $self, $res ) };
  0            
797            
798 0 0         if ( $self->{_error} ) {
799 0           return;
800             }
801 0 0         unless ( defined( $functions{ 'ar' } ) ) {
802 0           return;
803             }
804 0 0         if ( $functions{ 'ar' }->[0] ) {
805 0 0         if ( $del_message ) {
806 0           $args{ 'act' } = 'dl';
807 0           $args{ 'search' } = 'trash';
808 0           $res = get_page( $self, %args );
809 0 0         if ( $res->is_success() ) {
810 0           my %functions = %{ parse_page( $self, $res ) };
  0            
811            
812 0 0         if ( $self->{_error} ) {
813 0           return;
814             }
815 0 0         unless ( defined( $functions{ 'ar' } ) ) {
816 0           return;
817             }
818 0 0         if ( $functions{ 'ar' }->[0] ) {
819 0           return( 1 );
820             } else {
821 0           $self->{_error} = 1;
822 0           $self->{_err_str} .= remove_quotes( $functions{ 'ar'}->[1] ) . "\n";
823 0           return;
824             }
825             } else {
826 0           $self->{_error} = 1;
827 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
828 0           return;
829             }
830             } else {
831 0           return( 1 );
832             }
833             } else {
834 0           $self->{_error} = 1;
835 0           $self->{_err_str} .= remove_quotes( $functions{ 'ar'}->[1] ) . "\n";
836 0           return;
837             }
838             } else {
839 0           $self->{_error} = 1;
840 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
841 0           return;
842             }
843             }
844            
845             sub get_indv_email {
846 0     0 0   my ( $self ) = shift;
847 0           my ( %args ) = (
848             view => 'cv',
849             @_, );
850            
851 0 0 0       if ( defined( $args{ 'id' } ) && defined( $args{ 'label' } ) ) {
    0          
852 0           $args{ 'label' } = validate_label( $self, $args{ 'label' } );
853 0 0         if ( $self->error() ) {
854 0           return;
855             } else {
856 0           $args{ 'cat' } = $args{ 'label' };
857 0           delete( $args{ 'label' } );
858 0           $args{ 'search' } = 'cat';
859             }
860 0           $args{ 'th' } = $args{ 'id' };
861 0           delete( $args{ 'id' } );
862             } elsif ( defined( $args{ 'msg' } ) ) {
863 0 0         if ( defined( $args{ 'msg' }->{ 'id' } ) ) {
864 0           $args{ 'th' } = $args{ 'msg' }->{ 'id' };
865             } else {
866 0           $self->{_error} = 1;
867 0           $self->{_err_str} .= "Error: Not a valid msg reference.\n";
868 0           return;
869             }
870            
871 0 0         if ( defined( @{ $args{ 'msg' }->{ 'labels' } } ) ) {
  0            
872 0 0         if ( $args{ 'msg' }->{ 'labels' }->[0] ne '' ) {
873 0           $args{ 'label' } = validate_label( $self, $args{ 'msg' }->{ 'labels' }->[0] );
874 0           delete( $args{ 'msg' }->{ 'label' } );
875 0 0         if ( $self->error ) {
876 0           return;
877             } else {
878 0 0         if ( $args{ 'label' } =~ /^\^.$/ ) {
879 0           $args{ 'label' } = cat_to_search( $args{ 'label' } );
880 0           $args{ 'search' } = $args{ 'label' };
881             } else {
882 0           $args{ 'cat' } = $args{ 'label' };
883 0           $args{ 'search' } = 'cat';
884             }
885 0           delete( $args{ 'label' } );
886             }
887             }
888             }
889 0           delete( $args{ 'msg' } );
890             } else {
891 0           $self->{_error} = 1;
892 0           $self->{_err_str} .= "Error: Must specify either id and label or send a reference to a valid message with msg.\n";
893 0           return;
894             }
895            
896 0 0         unless ( check_login( $self ) ) { return };
  0            
897            
898 0           my $res = get_page( $self, %args );
899            
900 0 0         if ( $res->is_success() ) {
901 0           my %functions = %{ parse_page( $self, $res ) };
  0            
902            
903 0 0         if ( defined( $functions{ 'mi' } ) ) {
904 0           my %messages;
905             my @thread;
906 0           foreach ( @{ $functions{ 'mi' } } ) {
  0            
907 0           my %message;
908 0           my @email = @{ extract_fields( $_ ) };
  0            
909 0           $email[2] = remove_quotes( $email[2] );
910 0 0         if ( $email[16] ne '' ) {
911 0           my @attachments = @{ extract_fields( $email[17] ) };
  0            
912 0           my @files;
913 0           foreach ( @attachments ) {
914 0           my @attachment = @{ extract_fields( $_ ) };
  0            
915 0           my %indv_attachment;
916 0           $indv_attachment{ 'id' } = remove_quotes( $attachment[0] );
917 0           $indv_attachment{ 'name' } = remove_quotes( $attachment[1] );
918 0           $indv_attachment{ 'encoding' } = remove_quotes( $attachment[2] );
919 0           $indv_attachment{ 'th' } = $email[2];
920 0           push( @files, \%indv_attachment );
921             }
922 0           $message{ 'attachments' } = \@files;
923             }
924 0           $message{ 'id' } = $email[2];
925 0           $message{ 'sender' } = remove_quotes( $email[7] );
926 0           $message{ 'sent' } = remove_quotes( $email[9] );
927 0           $message{ 'to' } = remove_quotes( $email[10] );
928 0           $message{ 'read' } = remove_quotes( $email[14] );
929 0           $message{ 'subject' } = remove_quotes( $email[15] );
930 0 0         if ( $args{ 'th' } eq $email[2] ) {
931 0           foreach ( @{ $functions{ 'mb' } } ) {
  0            
932 0           my $body = extract_fields( $_ );
933 0           $message{ 'body' } .= $body->[0];
934             }
935 0 0         if ( defined( $functions{ 'cs' } ) ) {
936 0 0         if ( $functions{ 'cs' }[8] ne '' ) {
937 0           $message{ 'ads' } = get_ads( $self, adkey => remove_quotes( $functions{ 'cs' }[8] ) );
938             }
939             }
940             }
941 0           $messages{ $email[2] } = \%message;
942             }
943 0           return ( \%messages );
944             }
945            
946             } else {
947 0           $self->{_error} = 1;
948 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
949 0           return;
950             }
951             }
952            
953             sub get_mime_email {
954 0     0 0   my ( $self ) = shift;
955 0           my ( %args ) = (
956             view => 'om',
957             @_, );
958            
959 0 0 0       if ( defined( $args{ 'id' } ) && defined( $args{ 'label' } ) ) {
    0          
960 0           $args{ 'label' } = validate_label( $self, $args{ 'label' } );
961 0 0         if ( $self->error() ) {
962 0           return;
963             } else {
964 0           $args{ 'cat' } = $args{ 'label' };
965 0           delete( $args{ 'label' } );
966 0           $args{ 'search' } = 'cat';
967             }
968 0           $args{ 'th' } = $args{ 'id' };
969 0           delete( $args{ 'id' } );
970             } elsif ( defined( $args{ 'msg' } ) ) {
971 0 0         if ( defined( $args{ 'msg' }->{ 'id' } ) ) {
972 0           $args{ 'th' } = $args{ 'msg' }->{ 'id' };
973             } else {
974 0           $self->{_error} = 1;
975 0           $self->{_err_str} .= "Error: Not a valid msg reference.\n";
976 0           return;
977             }
978            
979 0 0         if ( defined( @{ $args{ 'msg' }->{ 'labels' } } ) ) {
  0            
980 0 0         if ( $args{ 'msg' }->{ 'labels' }->[0] ne '' ) {
981 0           $args{ 'label' } = validate_label( $self, $args{ 'msg' }->{ 'labels' }->[0] );
982 0           delete( $args{ 'msg' }->{ 'label' } );
983 0 0         if ( $self->error ) {
984 0           return;
985             } else {
986 0 0         if ( $args{ 'label' } =~ /^\^.$/ ) {
987 0           $args{ 'label' } = cat_to_search( $args{ 'label' } );
988 0           $args{ 'search' } = $args{ 'label' };
989             } else {
990 0           $args{ 'cat' } = $args{ 'label' };
991 0           $args{ 'search' } = 'cat';
992             }
993 0           delete( $args{ 'label' } );
994             }
995             }
996             }
997 0           delete( $args{ 'msg' } );
998             } else {
999 0           $self->{_error} = 1;
1000 0           $self->{_err_str} .= "Error: Must specify either id and label or send a reference to a valid message with msg.\n";
1001 0           return;
1002             }
1003            
1004 0 0         unless ( check_login( $self ) ) { return };
  0            
1005            
1006 0           my $res = get_page( $self, %args );
1007            
1008 0 0         if ( $res->is_success() ) {
1009 0           my $content = $res->content;
1010 0           $content =~ s/\r\n/\n/g;
1011 0           $content =~ s/^(\s*\n)+//;
1012 0           return $content;
1013             } else {
1014 0           $self->{_error} = 1;
1015 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
1016 0           return;
1017             }
1018             }
1019            
1020             sub get_contacts {
1021 0     0 0   my ( $self ) = shift;
1022 0           my ( %args ) = (
1023             @_, );
1024 0           my ( $res, $req );
1025            
1026 0           $args{ 'view' } = 'cl';
1027 0           $args{ 'search' } = 'contacts';
1028 0           $args{ 'start' } = undef;
1029 0           $args{ 'method' } = 'get';
1030 0 0         $args{ 'pnl' } = $args{ 'frequent' } ? 'p' : 'a';
1031 0           delete $args{ 'frequent' };
1032            
1033 0 0         unless ( check_login( $self ) ) { return };
  0            
1034            
1035 0           $res = get_page( $self, %args );
1036            
1037 0 0         if ( $res->is_success() ) {
1038 0           my %functions = %{ parse_page( $self, $res ) };
  0            
1039            
1040 0 0         if ( $self->{_error} ) {
1041 0           return;
1042             }
1043 0           my ( @contacts );
1044            
1045 0 0         unless ( defined( $functions{ 'cl' } ) ) {
1046 0           return;
1047             }
1048            
1049 0           foreach ( @{ $functions{ 'cl' } } ) {
  0            
1050 0           my @contact_line = @{ extract_fields( $_ ) };
  0            
1051 0           my %indv_contact;
1052 0           $indv_contact{ 'id' } = remove_quotes( $contact_line[1] );
1053 0           $indv_contact{ 'name1' } = remove_quotes( $contact_line[2] );
1054 0           $indv_contact{ 'name2' } = remove_quotes( $contact_line[3] );
1055 0           $indv_contact{ 'email' } = remove_quotes( $contact_line[4] );
1056 0           $indv_contact{ 'note' } = remove_quotes( $contact_line[5] );
1057 0           push ( @contacts, \%indv_contact );
1058             }
1059 0           return ( \@contacts );
1060             } else {
1061 0           $self->{_error} = 1;
1062 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
1063 0           return;
1064             }
1065             }
1066            
1067             sub get_ads {
1068 0     0 0   my ( $self ) = shift;
1069 0           my ( %args ) = (
1070             adkey => '',
1071             view => 'ad',
1072             search => '',
1073             start => '',
1074             @_, );
1075            
1076 0 0         unless ( check_login( $self ) ) { return };
  0            
1077            
1078 0 0         if ( defined( $args{ 'adkey' } ) ) {
1079 0           $args{ 'bb' } = $args{ 'adkey' };
1080 0           delete( $args{ 'adkey' } );
1081             } else {
1082 0           $self->{_error} = 1;
1083 0           $self->{_err_str} .= "Error: No addkey provided.\n";
1084 0           return;
1085             }
1086            
1087 0           my $res = get_page( $self, %args );
1088 0 0         if ( $res->is_success() ) {
1089 0           my $ad_text = $res->content();
1090 0           $ad_text =~ s/\n//g;
1091 0           $ad_text =~ /\[(\[.*?\])\]/;
1092 0           $ad_text = $1;
1093 0           my @indv_ads = @{ extract_fields( $ad_text ) };
  0            
1094 0           my @ads;
1095 0           foreach ( @indv_ads ) {
1096 0           my @split_ad = @{ extract_fields( $_ ) };
  0            
1097 0 0         if ( uc( remove_quotes( $split_ad[0] ) ) eq 'A' ) {
    0          
    0          
1098 0           $split_ad[5] =~ s/.*//i;
1099 0           my %ad_hash = (
1100             title => remove_quotes( $split_ad[2] ),
1101             body => remove_quotes( $split_ad[3] ),
1102             vendor_link => remove_quotes( $split_ad[5] ),
1103             link => remove_quotes( $split_ad[4] ), );
1104 0           push( @ads, \%ad_hash );
1105             } elsif ( uc( remove_quotes( $split_ad[0] ) ) eq 'RN' ) {
1106 0 0         if ( $split_ad[3] =~ /redir_url=(.*?)\"/ ) {
1107 0           my $vendor_link = $1;
1108 0           my %ad_hash = (
1109             title => remove_quotes( $split_ad[1] ),
1110             body => remove_quotes( $split_ad[2] ),
1111             vendor_link => url_unencode( $self, url => $vendor_link ),
1112             link => remove_quotes( $split_ad[3] ), );
1113 0           push( @ads, \%ad_hash );
1114             }
1115             } elsif ( uc( remove_quotes( $split_ad[0] ) ) eq 'RP' ) {
1116 0           my %ad_hash = (
1117             title => remove_quotes( $split_ad[1] ),
1118             body => remove_quotes( $split_ad[2] ),
1119             vendor_link => remove_quotes( $split_ad[4] ),
1120             link => remove_quotes( $split_ad[3] ), );
1121 0           push( @ads, \%ad_hash );
1122             }
1123             }
1124            
1125 0           return( \@ads );
1126             } else {
1127 0           $self->{_error} = 1;
1128 0           $self->{_err_str} .= "Error: " . $res->status_line();
1129             }
1130            
1131 0           return;
1132             }
1133            
1134             sub url_unencode {
1135 0     0 0   my $self = shift;
1136 0           my ( %args ) = (
1137             url => '',
1138             @_,
1139             );
1140            
1141 0 0         if ( $args{ 'url' } ) {
1142 0           $args{ 'url' } =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack( "C", hex( $1 ) )/eg;
  0            
1143 0           return( $args{ 'url' } );
1144             } else {
1145 0           $self->{_error} = 1;
1146 0           $self->{_err_str} .= "Error: Must supply URL to unencode.";
1147 0           return;
1148             }
1149             }
1150            
1151             sub get_attachment {
1152 0     0 0   my ( $self ) = shift;
1153 0           my ( %args ) = (
1154             view => 'att',
1155             disp => 'attd',
1156             search => '',
1157             @_, );
1158            
1159 0 0 0       if ( defined( $args{ 'attid' } ) && defined( $args{ 'msgid' } ) ) {
    0          
1160 0           $args{ 'th' } = $args{ 'msgid' };
1161 0           delete( $args{ 'msgid' } );
1162             } elsif ( defined( $args{ 'attachment' } ) ) {
1163 0 0         if ( defined( $args{ 'attachment' }->{ 'id' } ) ) {
1164 0           $args{ 'attid' } = $args{ 'attachment' }->{ 'id' };
1165             } else {
1166 0           $self->{_error} = 1;
1167 0           $self->{_err_str} .= "Error: Not a valid attachment.1\n";
1168 0           return;
1169             }
1170 0 0         if ( defined( $args{ 'attachment' }->{ 'th' } ) ) {
1171 0           $args{ 'th' } = $args{ 'attachment' }->{ 'th' };
1172             } else {
1173 0           $self->{_error} = 1;
1174 0           $self->{_err_str} .= "Error: Not a valid attachment.2\n";
1175 0           return;
1176             }
1177 0           delete( $args{ 'attachment' } );
1178             } else {
1179 0           $self->{_error} = 1;
1180 0           $self->{_err_str} .= "Error: Must supply attid and msgid or a reference to an attachment through 'attachment'.\n";
1181 0           return;
1182             }
1183            
1184 0 0         unless ( check_login( $self ) ) { return };
  0            
1185            
1186 0           my $res = get_page( $self, %args );
1187            
1188 0 0         if ( $res->is_success() ) {
1189 0           my $attachment = $res->content();
1190 0           return( \$attachment );
1191             } else {
1192 0           $self->{_error} = 1;
1193 0           $self->{_err_str} .= "Error: While requesting attachment: '$res->{_request}->{_uri}'.\n";
1194 0           return;
1195             }
1196             }
1197            
1198             sub update_prefs {
1199 0     0 0   my ( $self ) = shift;
1200 0           my ( %args ) = (
1201             view => 'tl',
1202             act => 'prefs',
1203             search => 'inbox',
1204             @_, );
1205            
1206 0 0         unless ( check_login( $self ) ) { return };
  0            
1207            
1208 0           $args{ 'at' } = $self->{_cookies}->{GMAIL_AT};
1209            
1210 0           my ( %pref_mappings ) = (
1211             bx_hs => 'keyboard_shortcuts',
1212             ix_nt => 'max_page_size',
1213             bx_sc => 'indicators',
1214             sx_dn => 'display_name',
1215             bx_ns => 'snippets',
1216             sx_rt => 'reply_to',
1217             sx_sg => 'signature', );
1218            
1219 0           my ( %pref_args ) = (
1220             view => 'pr',
1221             pnl => 'g',
1222             search => '',
1223             start => '',
1224             method => '',
1225             );
1226            
1227 0           my $pref_res = get_page( $self, %pref_args );
1228            
1229 0 0         if ( $pref_res->is_success() ) {
1230 0           my %functions = %{ parse_page( $self, $pref_res ) };
  0            
1231            
1232 0 0         if ( $self->{_error} ) {
1233 0           return;
1234             }
1235            
1236 0 0         unless ( defined( $functions{ 'p' } ) ) {
1237 0           return;
1238             }
1239            
1240             ### Delete if equal to the string '' ###
1241 0           foreach ( 'signature', 'reply_to', 'display_name' ) {
1242 0 0         if ( defined( $args{ $_ } ) ) {
1243 0 0         if ( $args{ $_ } eq '' ) {
1244 0           $args{ $_ } = '%0A%0D';
1245             }
1246             }
1247             }
1248            
1249             ### Load Prefs if not redefined ###
1250 0           foreach ( @{ $functions{ 'p' } } ) {
  0            
1251 0           my ( @setting ) = @{ extract_fields( $_ ) };
  0            
1252 0           foreach ( @setting ) {
1253 0           $_ = remove_quotes( $_ );
1254             }
1255 0 0         unless ( defined( $args{ $pref_mappings{ $setting[0] } } ) ) {
1256 0           $args{ 'p_' . $setting[0] } = $setting[1];
1257             } else {
1258 0           $args{ 'p_' . $setting[0] } = $args{ $pref_mappings{ $setting[0] } };
1259             }
1260 0           delete( $args{ $pref_mappings{ $setting[0] } } );
1261             }
1262            
1263             ### Add preferences to be added ###
1264 0           my %rev_pref_mappings;
1265 0           foreach ( keys %pref_mappings ) {
1266 0           $rev_pref_mappings{ $pref_mappings{ $_ } } = $_;
1267             }
1268 0           foreach ( keys %args ) {
1269 0 0         if ( $rev_pref_mappings{ $_ } ) {
1270 0           $args{ 'p_' . $rev_pref_mappings{ $_ } } = $args{ $_ };
1271 0           delete( $args{ $_ } );
1272             }
1273             }
1274            
1275 0           my $res = get_page( $self, %args );
1276 0 0         if ( $res->is_success() ) {
1277 0           my %functions = %{ parse_page( $self, $res ) };
  0            
1278 0 0         if ( @{ $functions{ 'ar' } }[0] == 1 ) {
  0            
1279 0           return( 1 );
1280             } else {
1281 0           $self->{_error} = 1;
1282 0           $self->{_err_str} .= "Error: While updating user preferences: '" . remove_quotes( @{ $functions{ 'ar' } }[1] ) . "'.\n";
  0            
1283 0           return;
1284             }
1285             } else {
1286 0           $self->{_error} = 1;
1287 0           $self->{_err_str} .= "Error: While updating user preferences: '$res->{_request}->{_uri}'.\n";
1288 0           return;
1289             }
1290             } else {
1291 0           $self->{_error} = 1;
1292 0           $self->{_err_str} .= "Error: While requesting user preferences: '$pref_res->{_request}->{_uri}'.\n";
1293 0           return;
1294             }
1295             }
1296            
1297             sub recurse_slash {
1298 0     0 0   my ( $field ) = @_;
1299 0           my $count_slashes = 0;
1300 0           my $end_slash = 0;
1301 0           my $cnt = length( $field );
1302            
1303 0   0       while ( ( $cnt > 0 ) && ( !$end_slash ) ){
1304 0           $cnt--;
1305 0           my $char = substr( $field, $cnt, 1 );
1306 0 0         if ( $char eq '\\' ) {
1307 0 0         if ( $count_slashes ) {
1308 0           $count_slashes = 0;
1309             } else {
1310 0           $count_slashes = 1;
1311             }
1312             } else {
1313 0           $end_slash = 1;
1314             }
1315             }
1316            
1317 0           return( $count_slashes );
1318             }
1319            
1320             sub extract_fields {
1321 0     0 0   my ( $line ) = @_;
1322 0           my @fields;
1323 0           my $in_quotes = 0;
1324 0           my $in_brackets = 0;
1325 0           my $in_brackets_quotes = 0;
1326 0           my $delim_count = 0;
1327 0           my $end_field = 0;
1328 0           my $field = '';
1329 0           my $char;
1330            
1331             my $cnt;
1332 0           for ( $cnt=0; $cnt < length( $line ); $cnt++ ) {
1333 0           $char = substr( $line, $cnt, 1 );
1334 0 0         if ( $in_quotes ) {
    0          
    0          
    0          
    0          
    0          
1335 0 0 0       if ( ( $char eq '"' ) && ( !recurse_slash( $field ) ) ) {
1336 0           $in_quotes = 0;
1337 0           $end_field = 1;
1338             }
1339 0           $field .= $char;
1340             } elsif ( $in_brackets ) {
1341 0 0         if ( $in_brackets_quotes ) {
    0          
1342 0 0 0       if ( ( $char eq '"' ) && ( !recurse_slash( $field ) ) ) {
1343 0           $in_brackets_quotes = 0;
1344             }
1345 0           $field .= $char;
1346             } elsif ( $char eq '"' ) {
1347 0           $in_brackets_quotes = 1;
1348 0           $field .= $char;
1349             } else {
1350 0 0         if ( $char eq '[' ) {
    0          
1351 0           $delim_count++;
1352 0           $field .= $char;
1353             } elsif ( $char eq ']' ) {
1354 0           $delim_count--;
1355 0 0         if ( $delim_count == 0 ) {
1356 0           $in_brackets = 0;
1357 0           $end_field = 1;
1358 0 0         if ( $field eq '' ) {
1359 0           push( @fields, '' );
1360             }
1361             } else {
1362 0           $field .= $char;
1363             }
1364             } else {
1365 0           $field .= $char;
1366             }
1367             }
1368             } elsif ( $char eq '"' ) {
1369 0           $in_quotes = 1;
1370 0           $field .= $char;
1371             } elsif ( $char eq '[' ) {
1372 0           $in_brackets = 1;
1373 0           $delim_count = 1;
1374             } elsif ( $char ne ',' ) {
1375 0           $field .= $char;
1376             } elsif ( $char eq ',' ) {
1377 0           $end_field = 1;
1378             }
1379            
1380 0 0         if ( $end_field ) {
1381 0 0         if ( $field ne '' ) {
1382 0           push ( @fields, $field );
1383             }
1384 0           $field = '';
1385 0           $end_field = 0;
1386             }
1387             }
1388            
1389 0 0         if ( $field ne '' ) {
1390 0           push ( @fields, $field );
1391             }
1392 0           return( \@fields );
1393             }
1394            
1395             sub remove_quotes {
1396 0     0 0   my ( $field ) = @_;
1397            
1398 0 0         if ( defined( $field ) ) {
1399 0           $field =~ s/^"(.*)"$/$1/;
1400             }
1401            
1402 0           return ( $field );
1403             }
1404            
1405             sub cat_to_search {
1406 0     0 0   my ( $cat ) = @_;
1407            
1408 0           my %REVERSE_CAT = map{ $FOLDERS{ $_ } => $_ }(keys %FOLDERS);
  0            
1409            
1410 0 0         if ( defined( $REVERSE_CAT{ uc( $cat ) } ) ) {
1411 0           return( lc( $REVERSE_CAT{ uc( $cat ) } ) );
1412             } else {
1413 0           return( $cat );
1414             }
1415             }
1416            
1417             sub parse_page {
1418 0     0 0   my ( $self, $res ) = @_;
1419            
1420 0 0         if ( $res->is_success() ) {
1421 0           my $page;
1422 0           $res->content() =~ //s;
1423 0           $page = $1;
1424 0           my ( %functions );
1425 0           while ( $page =~ /D\((.*?)\);\n/mgs ) {
1426 0           my $line = $1;
1427 0           $line =~ s/\n//g;
1428 0           $line =~ s/^\["(.*?)",?//;
1429 0           my $function = $1;
1430 0           $line =~ s/\]$//;
1431 0 0 0       if ( ( uc( $function ) eq 'MI' ) || ( uc( $function ) eq 'MB' ) ) {
1432 0           $functions{ $function } .= "[$line],";
1433             } else {
1434 0           $functions{ $function } .= "$line,";
1435             }
1436             }
1437 0           foreach ( keys %functions ) {
1438 0           chop( $functions{ $_ } );
1439 0           my $fields = extract_fields( $functions{ $_ } );
1440 0           $functions{ $_ } = $fields;
1441             }
1442 0           return ( \%functions );
1443             } else {
1444 0           $self->{_error} = 1;
1445 0           $self->{_err_str} .= "Error: While requesting: '$res->{_request}->{_uri}'.\n";
1446 0           return;
1447             }
1448             }
1449            
1450             1;
1451            
1452             __END__