⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lite.pm

📁 lrc 歌词解析和实时显示源码, 是开发 mp3, 播放器的很好的模块
💻 PM
📖 第 1 页 / 共 2 页
字号:
## HTTP::Lite.pm## $Id: Lite.pm,v 1.1.1.1 2005/09/03 16:13:00 xiaosuo Exp $#package HTTP::Lite;use vars qw($VERSION);use strict qw(vars);$VERSION = "2.1.6";my $BLOCKSIZE = 65536;my $CRLF = "\r\n";my $URLENCODE_VALID = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.";# Required modules for Network I/Ouse Socket 1.3;use Fcntl;use Errno qw(EAGAIN);# Forward declarationssub prepare_post;sub http_write;sub http_readline;sub http_read;sub http_readbytes;# Prepare the urlencode validchars lookup hashmy @urlencode_valid;foreach my $char (split('', $URLENCODE_VALID)) {  $urlencode_valid[ord $char]=$char;}for (my $n=0;$n<255;$n++) {  if (!defined($urlencode_valid[$n])) {    $urlencode_valid[$n]=sprintf("%%%02X", $n);  }}sub new {  my $self = {};  bless $self;  $self->initialize();  return $self;}sub initialize{  my $self = shift;  $self->reset;  $self->{timeout} = 120;  $self->{HTTP11} = 0;  $self->{DEBUG} = 0;  $self->{header_at_once} = 0;   $self->{holdback} = 0;       # needed for http_write }sub header_at_once{  my $self=shift;  $self->{header_at_once} = 1;}sub local_addr{  my $self = shift;  my $val = shift;  my $oldval = $self->{'local_addr'};  if (defined($val)) {    $self->{'local_addr'} = $val;  }  return $oldval;}sub local_port{  my $self = shift;  my $val = shift;  my $oldval = $self->{'local_port'};  if (defined($val)) {    $self->{'local_port'} = $val;   }  return $oldval;}sub method{  my $self = shift;  my $method = shift;  $method = uc($method);  $self->{method} = $method;}sub DEBUG{  my $self = shift;  if ($self->{DEBUG}) {    print STDERR join(" ", @_),"\n";  }}sub reset{  my $self = shift;  foreach my $var ("body", "request", "content", "status", "proxy",    "proxyport", "resp-protocol", "error-message",      "resp-headers", "CBARGS", "callback_function", "callback_params")  {    $self->{$var} = undef;  }  $self->{HTTPReadBuffer} = "";  $self->{method} = "GET";  $self->{headers} = { 'user-agent' => "HTTP::Lite/$VERSION" };  $self->{headermap} = { 'user-agent'  => 'User-Agent' };}# URL-encode datasub escape {  my $toencode = shift;  return join('',     map { $urlencode_valid[ord $_] } split('', $toencode));}sub set_callback {  my ($self, $callback, @callbackparams) = @_;  $self->{'callback_function'} = $callback;  $self->{'callback_params'} = [ @callbackparams ];}sub request{  my ($self, $url, $data_callback, $cbargs) = @_;    my $method = $self->{method};  if (defined($cbargs)) {    $self->{CBARGS} = $cbargs;  }  my $callback_func = $self->{'callback_function'};  my $callback_params = $self->{'callback_params'};  # Parse URL   my ($protocol,$host,$junk,$port,$object) =     $url =~ m{^([^:/]+)://([^/:]*)(:(\d+))?(/.*)$};  # Only HTTP is supported here  if ($protocol ne "http")  {    warn "Only http is supported by HTTP::Lite";    return undef;  }    # Setup the connection  my $proto = getprotobyname('tcp');  local *FH;  socket(FH, PF_INET, SOCK_STREAM, $proto);  $port = 80 if !$port;  my $connecthost = $self->{'proxy'} || $host;  $connecthost = $connecthost ? $connecthost : $host;  my $connectport = $self->{'proxyport'} || $port;  $connectport = $connectport ? $connectport : $port;  my $addr = inet_aton($connecthost);  if (!$addr) {    close(FH);    return undef;  }  if ($connecthost ne $host)  {    # if proxy active, use full URL as object to request    $object = "$url";  }  # choose local port and address  my $local_addr = INADDR_ANY;   my $local_port = "0";  if (defined($self->{'local_addr'})) {    $local_addr = $self->{'local_addr'};    if ($local_addr eq "0.0.0.0" || $local_addr eq "0") {      $local_addr = INADDR_ANY;    } else {      $local_addr = inet_aton($local_addr);    }  }  if (defined($self->{'local_port'})) {    $local_port = $self->{'local_port'};  }  my $paddr = pack_sockaddr_in($local_port, $local_addr);   bind(FH, $paddr) || return undef;  # Failing to bind is fatal.  my $sin = sockaddr_in($connectport,$addr);  connect(FH, $sin) || return undef;  # Set nonblocking IO on the handle to allow timeouts  if ( $^O ne "MSWin32" ) {    fcntl(FH, F_SETFL, O_NONBLOCK);  }  if (defined($callback_func)) {    &$callback_func($self, "connect", undef, @$callback_params);  }    if ($self->{header_at_once}) {    $self->{holdback} = 1;    # http_write should buffer only, no sending yet  }  # Start the request (HTTP/1.1 mode)  if ($self->{HTTP11}) {    $self->http_write(*FH, "$method $object HTTP/1.1$CRLF");  } else {    $self->http_write(*FH, "$method $object HTTP/1.0$CRLF");  }  # Add some required headers  # we only support a single transaction per request in this version.  $self->add_req_header("Connection", "close");      if ($port != 80) {    $self->add_req_header("Host", "$host:$port");  } else {    $self->add_req_header("Host", $host);  }  if (!defined($self->get_req_header("Accept"))) {    $self->add_req_header("Accept", "*/*");  }  if ($method eq 'POST') {    $self->http_write(*FH, "Content-Type: application/x-www-form-urlencoded$CRLF");  }    # Purge a couple others  $self->delete_req_header("Content-Type");  $self->delete_req_header("Content-Length");    # Output headers  foreach my $header ($self->enum_req_headers())  {    my $value = $self->get_req_header($header);    $self->http_write(*FH, $self->{headermap}{$header}.": ".$value."$CRLF");  }    my $content_length;  if (defined($self->{content}))  {    $content_length = length($self->{content});  }  if (defined($callback_func)) {    my $ncontent_length = &$callback_func($self, "content-length", undef, @$callback_params);    if (defined($ncontent_length)) {      $content_length = $ncontent_length;    }  }    if ($content_length) {    $self->http_write(*FH, "Content-Length: $content_length$CRLF");  }    if (defined($callback_func)) {    &$callback_func($self, "done-headers", undef, @$callback_params);  }    # End of headers  $self->http_write(*FH, "$CRLF");    if ($self->{header_at_once}) {    $self->{holdback} = 0;     $self->http_write(*FH, ""); # pseudocall to get http_write going  }      my $content_out = 0;  if (defined($callback_func)) {    while (my $content = &$callback_func($self, "content", undef, @$callback_params)) {      $self->http_write(*FH, $content);      $content_out++;    }  }     # Output content, if any  if (!$content_out && defined($self->{content}))  {    $self->http_write(*FH, $self->{content});  }    if (defined($callback_func)) {    &$callback_func($self, "content-done", undef, @$callback_params);  }    # Read response from server  my $headmode=1;  my $chunkmode=0;  my $chunksize=0;  my $chunklength=0;  my $chunk;  my $line = 0;  my $data;  while ($data = $self->http_read(*FH,$headmode,$chunkmode,$chunksize))  {    $self->{DEBUG} && $self->DEBUG("reading: $chunkmode, $chunksize, $chunklength, $headmode, ".        length($self->{'body'}));    if ($self->{DEBUG}) {      foreach my $var ("body", "request", "content", "status", "proxy",        "proxyport", "resp-protocol", "error-message",         "resp-headers", "CBARGS", "HTTPReadBuffer")       {        $self->DEBUG("state $var ".length($self->{$var}));      }    }    $line++;    if ($line == 1)    {      my ($proto,$status,$message) = split(' ', $$data, 3);      $self->{DEBUG} && $self->DEBUG("header $$data");      $self->{status}=$status;      $self->{'resp-protocol'}=$proto;      $self->{'error-message'}=$message;      next;    }     if (($headmode || $chunkmode eq "entity-header") && $$data =~ /^[\r\n]*$/)    {      if ($chunkmode)      {        $chunkmode = 0;      }      $headmode = 0;            # Check for Transfer-Encoding      my $te = $self->get_header("Transfer-Encoding");      if (defined($te)) {        my $header = join(' ',@{$te});        if ($header =~ /chunked/i)        {          $chunkmode = "chunksize";        }      }      next;    }    if ($headmode || $chunkmode eq "entity-header")    {      my ($var,$datastr) = $$data =~ /^([^:]*):\s*(.*)$/;      if (defined($var))      {        $datastr =~s/[\r\n]$//g;        $var = lc($var);        $var =~ s/^(.)/&upper($1)/ge;        $var =~ s/(-.)/&upper($1)/ge;        my $hr = ${$self->{'resp-headers'}}{$var};        if (!ref($hr))        {          $hr = [ $datastr ];        }        else         {          push @{ $hr }, $datastr;        }        ${$self->{'resp-headers'}}{$var} = $hr;      }    } elsif ($chunkmode)    {      if ($chunkmode eq "chunksize")      {        $chunksize = $$data;        $chunksize =~ s/^\s*|;.*$//g;        $chunksize =~ s/\s*$//g;        my $cshx = $chunksize;        if (length($chunksize) > 0) {          # read another line          if ($chunksize !~ /^[a-f0-9]+$/i) {            $self->{DEBUG} && $self->DEBUG("chunksize not a hex string");          }          $chunksize = hex($chunksize);          $self->{DEBUG} && $self->DEBUG("chunksize was $chunksize (HEX was $cshx)");          if ($chunksize == 0)          {            $chunkmode = "entity-header";          } else {            $chunkmode = "chunk";            $chunklength = 0;          }        } else {          $self->{DEBUG} && $self->DEBUG("chunksize empty string, checking next line!");        }      } elsif ($chunkmode eq "chunk")      {        $chunk .= $$data;        $chunklength += length($$data);        if ($chunklength >= $chunksize)        {          $chunkmode = "chunksize";          if ($chunklength > $chunksize)          {            $chunk = substr($chunk,0,$chunksize);          }           elsif ($chunklength == $chunksize && $chunk !~ /$CRLF$/)           {            # chunk data is exactly chunksize -- need CRLF still            $chunkmode = "ignorecrlf";          }          $self->add_to_body(\$chunk, $data_callback);          $chunk="";          $chunklength = 0;          $chunksize = "";        }       } elsif ($chunkmode eq "ignorecrlf")      {        $chunkmode = "chunksize";      }    } else {      $self->add_to_body($data, $data_callback);    }  }  if (defined($callback_func)) {    &$callback_func($self, "done", undef, @$callback_params);  }  close(FH);  return $self->{status};}sub add_to_body{  my $self = shift;  my ($dataref, $data_callback) = @_;    my $callback_func = $self->{'callback_function'};  my $callback_params = $self->{'callback_params'};  if (!defined($data_callback) && !defined($callback_func)) {    $self->{DEBUG} && $self->DEBUG("no callback");    $self->{'body'}.=$$dataref;  } else {    my $newdata;    if (defined($callback_func)) {      $newdata = &$callback_func($self, "data", $dataref, @$callback_params);    } else {      $newdata = &$data_callback($self, $dataref, $self->{CBARGS});    }    if ($self->{DEBUG}) {      $self->DEBUG("callback got back a ".ref($newdata));      if (ref($newdata) eq "SCALAR") {        $self->DEBUG("callback got back ".length($$newdata)." bytes");      }    }    if (defined($newdata) && ref($newdata) eq "SCALAR") {      $self->{'body'} .= $$newdata;    }  }}sub add_req_header{  my $self = shift;  my ($header, $value) = @_;    my $lcheader = lc($header);  $self->{DEBUG} && $self->DEBUG("add_req_header $header $value");  ${$self->{headers}}{$lcheader} = $value;  ${$self->{headermap}}{$lcheader} = $header;}sub get_req_header{  my $self = shift;  my ($header) = @_;    return $self->{headers}{lc($header)};}sub delete_req_header{  my $self = shift;  my ($header) = @_;    my $exists;  if ($exists=defined(${$self->{headers}}{lc($header)}))  {    delete ${$self->{headers}}{lc($header)};    delete ${$self->{headermap}}{lc($header)};  }  return $exists;}sub enum_req_headers{  my $self = shift;  my ($header) = @_;    my $exists;  return keys %{$self->{headermap}};}sub body{  my $self = shift;  return $self->{'body'};}sub status{  my $self = shift;  return $self->{status};}sub protocol{  my $self = shift;  return $self->{'resp-protocol'};}sub status_message{  my $self = shift;  return $self->{'error-message'};}sub proxy{  my $self = shift;  my ($value) = @_;    # Parse URL   my ($protocol,$host,$junk,$port,$object) =     $value =~ m{^(\S+)://([^/:]*)(:(\d+))?(/.*)$};  if (!$host)  {    ($host,$port) = $value =~ /^([^:]+):(.*)$/;  }  $self->{'proxy'} = $host || $value;  $self->{'proxyport'} = $port || 80;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -