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
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();
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.
#!/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.
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!
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
}
}