Using cookies in Perl without CGI - perl

I am trying to create a standard forum style website using Perl but not using CGI, or any other framework for that matter. I've seen before use of a script simply titled "cookies.pl," but can't find any sort of documentation on it. Is there a way to set/read cookies with just core modules?

First, I am assuming that when you say you don't want to use "CGI", you mean the Perl module CGI.pm rather than the Common Gateway Interface (CGI) method of communicating with the web server, which is implemented by the CGI.pm module.
Second, this answer is for information and entertainment purposes only. Attempting to implement your own CGI handler for use in a production environment is not advisable. It's a Really, Really Bad Idea unless you know exactly what you're doing. And probably still a Bad Idea even if you do. And if you did know exactly what you're doing, you wouldn't have to ask questions about basic parts of the interface like how to implement cookie handling.
With all that out of the way, cookies are pretty simple to handle directly.
To set a cookie, send a Set-Cookie HTTP header to the client. In the most basic form, this looks like Set-Cookie: CookieName=CookieValue. There are many other options which can be added to this basic format, which are documented in various places around the web.
If you're now wondering "How do I send an HTTP header?", every line of text that you send to the client (i.e., print to STDOUT) prior to the first empty line is an HTTP header:
print "Content-Type: text/html\n"; # Content-Type header is mandatory!
print "Set-Cookie: CookieName=CookieValue\n"; # Header to set a cookie
print "\n"; # Blank line = end of headers
# continue on with sending the response body now that headers are done
To read a cookie, look at the environment variable HTTP_COOKIE, which is provided by the web server as a part of its CGI implementation and will contain a semicolon-delimited list of all cookies received with the client's HTTP request. This is accessed in Perl as $ENV{HTTP_COOKIE}.

Related

Use perl REST::Client and multi-part form to post image to Confluence

How can I attach an image to an existing Confluence page, using their latest REST API, from Perl via the REST::Client module?
This may be a perl question (I may be posting an image incorrectly), or a Confluence question (their API docs may be missing a required detail such as a required header that is being quietly added by curl), or both.
I have established a connection object, $client, using the REST::Client module. I have verified that $client is a valid connection by performing a $client->GET to a known Confluence page ID, which correctly returns the page's details.
I attempt to upload an image, using:
$headers = {Accept => 'application/json',
Authorization => 'Basic ' . encode_base64($user . ':' .
$password),
X_Atlassian_Token => 'no-check',
Content_Type => 'form-data',
Content =>
[ file => ["file1.jpg"], ]};
$client->POST('rest/api/content/44073843/child/attachment', $headers);
... and the image doesn't appear on the attachments list.
I've packet-sniffed the browser whilst uploading an image there, only to find that it uses the prototype API that is being deprecated. I'd hoped that I could just stand on Atlassian's shoulders in terms of seeing exactly what their post stream looks like, and replicating that... but I don't want to use the API that's being deprecated, since they recommend against it.
The curl example of calling the Confluence API to attach a file that they give at https://developer.atlassian.com/confdev/confluence-rest-api/confluence-rest-api-examples, when my host, filename, and page ID are substituted in, does post the attachment.
I formerly specified comment in my array of Content items, but removed that during debugging to simplify things since the documentation said it was optional.
One thing I'm unclear about is getting the contents of the file into the post stream. In the curl command, the # accomplishes that. In REST::Client, I'm not sure if I have to do something more than I did, to make that happen.
I can't packet-sniff the outgoing traffic because our server only allows https, and I don't know how (or if it's even possible) to set the REST::Client module or one of its underlying modules to record the SSL info to a log file so that Wireshark can pick it up and decode the resulting TLS traffic, the way one can with the environment variable for Chrome or Firefox. I also don't have access to server logs. So I don't know what the request I'm actually sending looks like (if I did, I could probably say, "OK, it looks wrong right HERE" or "But it looks right?!"). I am therefore unfortunately at a loss as to how to debug it so blindly.
A similar question about posting multipart forms using REST::Client was asked by someone else, more generically, back in April of last year, but received no responses. I'm hoping that since mine is more specific, someone can tell me what I might be doing wrong.
Any help would be appreciated.
You should be capturing your post response like so:
my $response = $client->POST('rest/api/content/44073843/child/attachment', $headers); print Dumper $response;
Also, the url you are using in the POST call is incomplete and won't work, you need the full url.

Yii2 Reading PUT request body after oauth2 server already did it

I am working on REST API with oauth2 authorization.
For Oauth2 server i use https://github.com/bshaffer/oauth2-server-php
Php doc says here http://php.net/manual/en/wrappers.php.php
Prior to PHP 5.6, a stream opened with php://input could only be read once; the stream did not support seek operations. However, depending on the SAPI implementation, it may be possible to open another php://input stream and restart reading. This is only possible if the request body data has been saved. Typically, this is the case for POST requests, but not other request methods, such as PUT or PROPFIND.
In short it means that it is possible to read POST body twice, but not PUT.
But Oauth2 server reads it first time here https://github.com/bshaffer/oauth2-server-php/blob/develop/src/OAuth2/Request.php#L114
So when i read raw body in Yii2 Request, it is empty. (only on PUT, on POST and PATCH it is ok and can be read twice).
https://github.com/yiisoft/yii2/blob/master/framework/web/Request.php#L345
I know that this is kind of expected, no bugs. But what would be the solution for this?
Before you create that auth server, run this (depending in where you do authentication, you can use beforeAction(), or even init():
$content = Yii::$app->request->rawBody;
$authentication = Request::createFromGlobals();
if ($content)
$authentication->content = $content;
Now, I don't know how/where you use the component, so it might not fully work, but in theory it should.

Best way to send content in PERL POST Request?

I am sending a PERL POST Request over HTTPS. During sending the request i need to send two things in content one is an authorization token and other is the command need to be executed on the server side.
What should be the approach to send these two things as the content?
Should it be:-
$request->content($token)
$request->content($command)
OR should it be
my #content =($token,$command)
$request->content(\#content)
The module which i am using is LWP::UserAgent and in that i will be creating a HTTP::Request type object my $request = HTTP::Request->new(POST => "<url>"); and in
this object i am sending content.
There is only a single content (request body) for a POST request. So any call of content just replaces the previously defined content. Please have a look at the documentation for LWP::UserAgent::post which clearly defines how to send POST data with multiple values. Also, it might be useful if you understand how forms in HTML work, both on the client (browser) and on the server side. Because only if you know what the server side expects in detail you can create the proper request.

How to reproduce a request via cURL

I want to capture how parameters are being sent. Usually what I do is to make a request and check on Firebug's params tab what are the parameters sent. However, when I try to do this on the following site (http://www.infraero.gov.br/voos/index_2.aspx), it doesn't work - I can't see what are the parameters in order to repeat this request using curl. How can I get it? I'm not sure but I think that cookies are being used.
EDIT
I was able to get the request content, but couldn't understand it. It seems it uses javascript to generate the proper request. How can I reproduce this request via cURL?
Did you see this previous question cURL post data to asp.net page ? That might answer the question right there (all I did was search "ASP.NET cURL"). And this one: Unable to load ASP.NET page using Python urllib2 talks about Python, but it approaches it in a way that should translate to cURL.
But for my $0.02, I wouldn't bother trying to untangle ASP.NET's and __VIEWSTATE and javascript. Is it an absolute requirement that you use cURL?
I think you would be better off using a client that works more like a real browser and understands javascript. That's a bit of work, but it isn't as bad as it sounds. I've done this before with http://watirwebdriver.com/ and a short Ruby script. Here's how to do it with Python and Mechanize (this is probably a bit more lightweight).
http://phantomjs.org/ is another option that you script using javascript. If you Google "Scraping ASP.NET" you will see that this is a common problem.
You didn't say how you want it done, but you can send the request with curl simply with curl -d name1=contents1&name2=contents2 [TARGETURL] etc.
Note that you probably first need to fetch the main page and extract the "__VIEWSTATE" form field and submit back that (VERY huge) contents to get your submission accepted.

Parsing Site with Perl LWP::UserAgent -- Cookies Required

On a certain project in Perl, I've written several "parsers", which allow me to visit websites with LWP::UserAgent. However, I'm having a problem with one website: it's behaving exactly as if I had visited the site with my browser, having turned off Cookies, so instead of giving me the page I want, it gives me a page with the message that I must turn on cookies. The entire code of my script is below. Any ideas? Thanks in advance.
(Note that I looked at the following url, which seems to be addressing my question, but unfortunately, I was unable to get a working script based on its suggestion: Cookies in perl lwp.)
use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Cookies;
my $useragent = LWP::UserAgent->new;
$useragent->cookie_jar(HTTP::Cookies->new);
my $request = HTTP::Request->new(GET => "http://www.the-site-im-trying-to-parse.com");
my $response = $useragent->request($request);
print "Content-type: text/html\n\n";
print $response->as_string;
Have you considered using WWW::Mechanize module? It does collect cookies automatically by default. And it's a bit easier to use since there are plenty of included methods which are very useful.
All you are doing is downloading the html data over HTTP, so there is no browser interaction until you decide to view the result in one. That being said, the HTTP server has no way of knowing if your request is from a client that has cookies enabled. So doing so won't actually do anything to change the result.
The WWW:Mechanize module is useful for easily traversing web sites, but it won't fix the problem you are facing. So it won't actually help you resolve the issue you are having.
More realistically what it is going on is there is some sort of client-side javascript code that isn't working correctly once you download the file and display it in your browser. This could be any number of things, such as breaking the cross-domain policy implemented in the javascript code. Without providing the URL you are accessing, it is impossible to say.
Try setting up cookie_jar to temporary storage (give it empty hashref):
$useragent->cookie_jar( {} );