package Net::YahooMessenger::HTTPS;
use strict;
use warnings;
use WWW::Mechanize;
use MD5;

use constant YMSG_LOGIN_URL => 'https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=&login=%s&passwd=%s&chal=%s';
use constant YMSG_TOKEN_URL => 'https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=&token=';

sub new {
    my ($class,$id,$password,$seed) = @_;
    my $self = bless {_SEED_ => $seed},$class;
    $self->_https_login($id,$password,$seed);   
    return $self;
}

sub _https_login {
    my ($self,$username,$password,$seed) = @_;
    my $mech = WWW::Mechanize->new(agent => 'Mozilla/5.0');

    my $url = sprintf(YMSG_LOGIN_URL,$username,$password,$seed);

    $mech->get($url);
    my @lines = split("\r\n",$mech->content());
    chomp(@lines);

    my (undef,$token) = split('=',$lines[1]);
    chomp($token);

    $url = YMSG_TOKEN_URL . $token;

    $mech->get($url);

    @lines = split("\r\n",$mech->content());
    chomp(@lines);

    $self->{_CRUMB_} = $lines[1];
    $self->{_Y_} = $lines[2];
    $self->{_T_} = $lines[3];
    $self->{_CRUMB_} =~ s/crumb=//g;
    $self->{_Y_} =~ s/Y=//g;
    $self->{_T_} =~ s/T=//g;

    return $self;
}

sub y_string {
    return shift->{_Y_};
}

sub t_string {
    return shift->{_T_};
}

sub crumb {
    return shift->{_CRUMB_};
}

sub md5_string {
    my $self = shift;
    return $self->ym_hash(MD5->hash("$self->{_CRUMB_}$self->{_SEED_}"));
}

sub ym_hash {
    my ($self, $in) = @_;
    my @base64digits = split('',"ABCDEFGHIJKLMNOPQRSTUVWXYZ" . "abcdefghijklmnopqrstuvwxyz" . "0123456789._");
    my @in = split('',$in);
    my $out = '';
    my $length = 16;
    for (;$length >= 3;$length -= 3) {
            $out .= $base64digits[ord($in[0]) >> 2];
            $out .= $base64digits[((ord($in[0])<<4) & 0x30) | (ord($in[1])>>4)];
            $out .= $base64digits[((ord($in[1])<<2) & 0x3c) | (ord($in[2])>>6)];
            $out .= $base64digits[ord($in[2]) & 0x3f];
            shift(@in);shift(@in);shift(@in);
    }
    if($length > 0 ){
        $out .= $base64digits[ord($in[0]) >> 2];
        my $fragment = (ord($in[0]) << 4) & 0x30;
        if ($length > 1) {
                $fragment |= ord($in[1]) >> 4;
        }
        $out .= $base64digits[$fragment];
        $out .= ($length < 2) ? '-'
                  : $base64digits[(ord($in[1]) << 2) & 0x3c];
        $out .= '-';


    }
    return $out;
}

1;
