how to get session id from cookie jar in perl? - perl

My question is very simple.. It is how to get session id from cookie jar ... I have tried below code :-
use warnings;
use HTTP::Cookies;
use HTTP::Request::Common;
use LWP::UserAgent;
$ua = new LWP::UserAgent;
if ( !$ua ) {
print "Can not get the page :UserAgent fialed \n";
return 0;
}
my $cookies = new HTTP::Cookies( file => './cookies.dat', autosave => 1 );
$ua->cookie_jar($cookies);
# push does all magic to exrtact cookies and add to header for further reqs. useragent should be newer
push #{ $ua->requests_redirectable }, 'POST';
$result = $ua->request(
POST "URL",
{ Username => 'admin',
Password => 'admin',
Submit => 'Submit',
}
);
my $session_id = $cookies->extract_cookies($result);
print $session_id->content;
print "\n\n";
$resp = $result->content;
#print "Result is \n\n\n $resp \n";
$anotherURI = URL;
$requestObject = HTTP::Request::Common::GET $anotherURI;
$result = $ua->request($requestObject);
$resp = $result->content;
#print $resp."\n";
I am not getting where the session id is stored and how to fetch it ?
Note:- URL contains the URL of the page.

I wrote HTTP::CookieMonster to make this kind of thing a bit easier. If you don't know which cookie you're looking for, you can do something like this:
use strict;
use warnings;
use HTTP::CookieMonster;
use WWW::Mechanize;
my $mech = WWW::Mechanize->new;
my $monster = HTTP::CookieMonster->new( $mech->cookie_jar );
my $url = 'http://www.nytimes.com';
$mech->get( $url );
my #all_cookies = $monster->all_cookies;
foreach my $cookie ( #all_cookies ) {
printf( "key: %s value: %s\n", $cookie->key, $cookie->val);
}
If you already know the cookie's key, you can something like:
my $cookie = $monster->get_cookie('RMID');
my $session_id = $cookie->val;

Have a look at HTTP::Cookies->scan.
Something like this should do the trick (should add a constraint on the domain at least):
my $session_id;
$cookie_jar->scan(
sub {
my ($key, $val, $path, $domain, $port,
$path_spec, $secure, $expires, $discard, $hash
) = #_;
if ( $key eq "session_id" ) {
$session_id = $val;
}
}
);

Related

Perl rest client declaration causes failure of user agent call with custom headers with another end point

I have 2 subroutines called in a single perl program .
First one (get_secrets) I am using the perl REST client directly with custom header and second one (app_restart) I am using LWP user agent and make and HTTP call .
my second subroutine fails when the $client header declaration is available in the first subroutine , as soon as i remove the that subroutine or comment the lines those lines app_restart subroutine works fine .
use REST::Client;
use Data::Dumper;
use JSON; #use strict;
use MIME::Base64 qw( decode_base64 );
use POSIX 'strftime';
use Date::Parse;
use DateTime;
use Date::Calc qw(:all);
use LWP::UserAgent;
#use IO::Socket::SSL 'debug4';
use Data::Dumper qw(Dumper);
use Getopt::Long;
sub toList {
my $data = shift;
my $key = shift;
if ( ref( $data->{$key} ) eq 'ARRAY' ) {
$data->{$key};
}
elsif ( ref( $data->{$key} ) eq 'HASH' ) {
[ $data->{$key} ];
}
else {
[];
}
}
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
$endpoint = $ENV{'ENDPOINT'};
$token = `cat /var/run/secrets/kubernetes.io/serviceaccount/token`;
$namespace = $ENV{'NAMESPACE'};
$apikey = $ENV{'APIKEY'};
$instance = $ENV{'INSTANCE'};
$appid = $ENV{'APPID'};
$storeid = "checker";
sub get_secrets {
my $client = REST::Client->new();
$client->setHost("https://${endpoint}");
#$client->addHeader('Authorization', "Bearer ${token}");
$client->addHeader( 'Accept', "application/json" );
$client->GET("/api/v1/namespaces/${namespace}/secrets?labelSelector=true");
}
get_secrets();
$ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS} = "Net::SSL";
my $ua = LWP::UserAgent->new( 'send_te' => '0' );
$ua->ssl_opts(
SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
SSL_hostname => '',
verify_hostname => 0
);
sub app_restart {
$ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS} = "Net::SSL";
$ua = LWP::UserAgent->new( 'send_te' => '0' );
$ua->ssl_opts(
SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
verify_hostname => 0
print "$instance\n";
print "$apikey\n";
print "$cstoreid\n";
print "$appid\n";
my $r = HTTP::Request->new(
'PUT' =>
"https://api.service.intranet.com/rest/application/$appid/instance/$instance/action?action=restart&config=$storeid&deploy=0",
[
'Accept' => '*/*',
'Authorization' => "Realm $apikey",
'Host' => 'api.service.intranet.com:443',
'User-Agent' => 'curl/7.55.1',
],
);
my $res = $ua->request( $r, );
#$response = $res->decoded_content;
$json = JSON->new->allow_nonref;
$response_decoded = $json->decode( $res->decoded_content );
$actionID = $response_decoded->{'action_id'};
print "$actionID\n";
}
app_restart();

perl retrieving page details after mechanize::POST

I am trying to gather data from a website. Some anti-patterns make looking finding the right form objects difficult but I have this solved. I am using a post method to get around some javascript acting as a wrapper to submit the form. My problem seems to be in getting the results from the mechanize->post method.
Here's a shortened version of my code.
use strict;
use warnings;
use HTML::Tree;
use LWP::Simple;
use WWW::Mechanize;
use HTTP::Request::Common;
use Data::Dumper;
$| = 1;
my $site_url = "http://someURL";
my $mech = WWW::Mechanize->new( autocheck => 1 );
foreach my $number (#numbers)
{
my $content = get($site_url);
$mech->get ($site_url);
my $tree = HTML::Tree->new();
$tree->parse($content);
my ($title) = $tree->look_down( '_tag' , 'a' );
my $atag = "";
my $atag1 = "";
foreach $atag ( $tree->look_down( _tag => q{a}, 'class' => 'button', 'title' => 'SEARCH' ) )
{
print "Tag is ", $atag->attr('id'), "\n";
$atag1 = Dumper $atag->attr('id');
}
# Enter permit number in "Number" search field
my #forms = $mech->forms;
my #fields = ();
foreach my $form (#forms)
{
#fields = $form->param;
}
my ($name, $fnumber) = $fields[2];
print "field name and number is $name\n";
$mech->field( $name, $number, $fnumber );
print "field $name populated with search data $number\n" if $mech->success();
$mech->post($site_url ,
[
'$atag1' => $number,
'internal.wdk.wdkCommand' => $atag1,
]) ;
print $mech->content; # I think this is where the problem is.
}
The data I get from my final print statement is the data from teh original URL not the page the POST command should take me to. What have I done wrong?
Many Thanks
Update
I don't have Firefox installed so I'm avoiding WWW::Mechanize::Firefox intentionally.
Turns out I was excluding some required hidden fields from my POST command.

How to print the profile details individual lines

#!/usr/bin/perl -w
use WWW::LinkedIn;
use CGI; # load CGI routines
use CGI::Session;
$q = CGI->new; # create new CGI object
print $q->header, # create the HTTP header
$q->start_html('hello world'), # start the HTML
$q->h1('hello world'), # level 1 header
$q->end_html; # end the HTML
my $consumer_key = 'xxxxxxx';
my $consumer_secret = 'xxxxxxxxx';
my $li = WWW::LinkedIn->new(
consumer_key => $consumer_key,
consumer_secret => $consumer_secret,
);
if ( length( $ENV{'QUERY_STRING'} ) > 0 ) {
$buffer = $ENV{'QUERY_STRING'};
#pairs = split( /&/, $buffer );
foreach $pair (#pairs) {
( $name, $value ) = split( /=/, $pair );
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$in{$name} = $value;
}
$sid = $q->cookie('CGISESSID') || $q->param('CGISESSID') || undef;
$session = new CGI::Session( undef, $sid, { Directory => '/tmp' } );
my $access_token = $li->get_access_token(
verifier => $in{'oauth_verifier'},
request_token => $session->param("request_token"),
request_token_secret => $session->param("request_token_secret"),
);
undef($session);
my $profile_xml = $li->request(
request_url =>
'http://api.linkedin.com/v1/people/~:(id,first-name,last-name,positions,industry,distance)',
access_token => $access_token->{token},
access_token_secret => $access_token->{secret},
);
print $profile_xml;
}
The output is printing in single line. I want to print that is separate line.
OUTPUT
aAVGFD34 jj DD 456456 2003 6 true ara systems Technology and Services Technology and Services 0
How can i get the each column value from the profile_xml variable?
id avsdff
first name jj
lastname dd
Simply use Data::Dumper and XML::Simple.
use Data::Dumper;
use XML::Simple; #you may want to install a specific package from your distribution
{...}
my $hash_ref = SimpeXML::XMLin($profile_xml);
print Dumper($hash_ref);
I do not know if you would like more beautifully output.
try just to make simple print out from your hash reference
foreach $key (keys %{$profile_xml}) {
print "$key $profile_xml->{$key}\n";
}
Here i am going the show the way to parse the data and print in the individual lines.
my $parser = XML::Parser->new( Style => 'Tree' );
my $tree = $parser->parse( $profile_xml );
#print Dumper( $tree ); you can use this see the data displayed in the tree formatted
my $UID = $tree->[1]->[4]->[2],"\n";
print "User ID:$UID";
print"</br>";
my $FirstName = $tree->[1]->[8]->[2],"\n";
print "First Name:$FirstName";
print"</br>";
For sample i have showed for UID and FirstName. And this is working fine.

Twitter OAuth 1.0 authentication with signature in perl

I'm getting this problem with my app in perl for oauth authentication:
401 Unauthorized Failed to validate oauth signature and token
Here is my code:
sub Twitter {
my $IN = new CGI;
my $qs = build_query({
oauth_callback => $callback_url,
oauth_consumer_key => $consumer_key,
oauth_nonce => time,
oauth_signature_method => "HMAC-SHA1",
oauth_timestamp => time,
oauth_version => "1.0"
});
# Create Signature
my $signing_key = $IN->escape($consumer_secret)."&";
my $base_signature = "POST&".$IN->escape($request_token_url)."&".$qs;
use Digest::HMAC_SHA1;
my $hmac = Digest::HMAC_SHA1->new($signing_key);
$hmac->add($base_signature);
$qs .= "&oauth_signature=".$IN->escape($hmac->b64digest);
# Fetch the page
use LWP;
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(POST => $request_token_url);
$req->content_type('application/x-www-form-urlencoded');
$req->content($qs);
my $res = $ua->request($req);
# Check the outcome of the response
unless ($res->is_success) {
print $IN->header.$res->status_line, "\n";
print $res->content;
exit;
}
print $IN->header.$res->content;
}
sub build_query {
my $input = shift;
use URI;
my $uri = URI->new;
$uri->query_form($input);
return $uri->query;
}
I have obviously deleted my callback url and key information.
I figured it out. I was encoding the signature wrong, I had to sort my query strings, and the call back URL is not needed in this instance. Here is my working code:
sub Twitter {
my $IN = new CGI;
my $params = {
oauth_consumer_key => $consumer_key,
oauth_nonce => time,
oauth_signature_method => "HMAC-SHA1",
oauth_timestamp => time,
oauth_version => "1.0"
};
my $qs = build_sorted_query($params);
my $signing_key = $IN->escape($consumer_secret)."&";
my $signature_base = "POST&".$IN->escape($request_token_url)."&".$IN->escape($qs);
use Digest::HMAC_SHA1;
use MIME::Base64;
my $hmac = Digest::HMAC_SHA1->new($signing_key);
$hmac->add($signature_base);
$params->{oauth_signature} = $IN->escape(encode_base64($hmac->digest));
$qs = build_sorted_query($params);
use LWP;
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(POST => $request_token_url);
$req->content_type('application/x-www-form-urlencoded');
$req->content($qs);
my $res = $ua->request($req);
# Check the outcome of the response
unless ($res->is_success) {
print $IN->header.$res->status_line, "\n";
print $res->content;
exit;
}
print $IN->header.$res->content;
return;
}
sub build_sorted_query {
my $input = shift;
my $qs;
foreach (sort keys %$input) {
$qs .= $_."=".$input->{$_}."&";
}
return substr ($qs, 0, -1);
}
Thanks for looking!

How to use Net::Twitter::Stream to read stream from API?

I'm trying to use the Net::Twitter::Stream Perl module from CPAN to read the stream from sample.json. I believe this is the corect module though they way they crafted it allows one to process the filter stream. I've modified it as such but I must be missing something as I don't get any data in return. I establish a connection but nothing comes back. I'm guessing this should be an easy fix but I'm a touch new to this part of Perl.....
package Net::Twitter::Stream;
use strict;
use warnings;
use IO::Socket;
use MIME::Base64;
use JSON;
use IO::Socket::SSL;
use LibNewsStand qw(%cf);
use utf8;
our $VERSION = '0.27';
1;
=head1 NAME
Using Twitter streaming api.
=head1 SYNOPSIS
use Net::Twitter::Stream;
Net::Twitter::Stream->new ( user => $username, pass => $password,
callback => \&got_tweet,
track => 'perl,tinychat,emacs',
follow => '27712481,14252288,972651' );
sub got_tweet {
my ( $tweet, $json ) = #_; # a hash containing the tweet
# and the original json
print "By: $tweet->{user}{screen_name}\n";
print "Message: $tweet->{text}\n";
}
=head1 DESCRIPTION
The Streaming verson of the Twitter API allows near-realtime access to
various subsets of Twitter public statuses.
The /1/status/filter.json api call can be use to track up to 200 keywords
and to follow 200 users.
HTTP Basic authentication is supported (no OAuth yet) so you will need
a twitter account to connect.
JSON format is only supported. Twitter may depreciate XML.
More details at: http://dev.twitter.com/pages/streaming_api
Options
user, pass: required, twitter account user/password
callback: required, a subroutine called on each received tweet
perl#redmond5.com
#martinredmond
=head1 UPDATES
https fix: iwan standley <iwan#slebog.net>
=cut
sub new {
my $class = shift;
my %args = #_;
die "Usage: Net::Twitter::Stream->new ( user => 'user', pass => 'pass', callback => \&got_tweet_cb )" unless
$args{user} && $args{pass} && $args{callback};
my $self = bless {};
$self->{user} = $args{user};
$self->{pass} = $args{pass};
$self->{got_tweet} = $args{callback};
$self->{connection_closed} = $args{connection_closed_cb} if
$args{connection_closed_cb};
my $content = "follow=$args{follow}" if $args{follow};
$content = "track=$args{track}" if $args{track};
$content = "follow=$args{follow}&track=$args{track}\r\n" if $args{track} && $args{follow};
my $auth = encode_base64 ( "$args{user}:$args{pass}" );
chomp $auth;
my $cl = length $content;
my $req = <<EOF;
GET /1/statuses/sample.json HTTP/1.1\r
Authorization: Basic $auth\r
Host: stream.twitter.com\r
User-Agent: net-twitter-stream/0.1\r
Content-Type: application/x-www-form-urlencoded\r
Content-Length: $cl\r
\r
EOF
my $sock = IO::Socket::INET->new ( PeerAddr => 'stream.twitter.com:https' );
#$sock->print ( "$req$content" );
while ( my $l = $sock->getline ) {
last if $l =~ /^\s*$/;
}
while ( my $l = $sock->getline ) {
next if $l =~ /^\s*$/; # skip empty lines
$l =~ s/[^a-fA-F0-9]//g; # stop hex from compaining about \r
my $jsonlen = hex ( $l );
last if $jsonlen == 0;
eval {
my $json;
my $len = $sock->read ( $json, $jsonlen );
my $o = from_json ( $json );
$self->{got_tweet} ( $o, $json );
};
}
$self->{connection_closed} ( $sock ) if $self->{connection_closed};
}
You don't need to post the source, we can pretty much figure it out. You should try one of the examples, but my advice is to use AnyEvent::Twitter::Stream which comes with a good example that you only have to modify a bit to get it running
sub parse_from_twitter_stream {
my $user = 'XXX';
my $password = 'YYYY';
my $stream = Net::Twitter::Stream->new ( user => $user, pass => $password,
callback => \&got_tweet,
connection_closed_cb => \&connection_closed,
track => SEARCH_TERM);
sub connection_closed {
sleep 1;
warn "Connection to Twitter closed";
parse_from_twitter_stream();#This isn't working for me -- can't get connection to reopen after disconnect
}
sub got_tweet {
my ( $tweet, $json ) = #_; # a hash containing the tweet
#Do stuff here
}
}