A post in my journal with Perl. |
[Oct. 17th, 2004|09:24 pm]
LiveJournal Client Discussions
|
Hi, I'm trying to write something simple in Perl, to post a private message in my journal. Is not working for me, though.
This is what I have done so far:
#!/usr/bin/perl -w use IO::Socket::INET; $MySocket=new IO::Socket::INET->new( PeerPort=>80, Proto=>'tcp', PeerAddr=>'livejournal.com');
$msg="POST /interface/flat HTTP/1.0 Host: www.livejournal.com Content-type: application/x-www-form-urlencoded mode=postevent&user=LJUSER&password=LJPASSWORD&event=yomama+is+phat&security=private"; $MySocket->send($msg); exit;
I tried just telnet www.livejournal.com and pasting $msg, and the connection gets' closed. Am I missing something? Also, how would you implement this, so that the password is not sent in clear text?.
I read http://www.livejournal.com/doc/server/ljp.csp.flat.postevent.html but says that password is Deprecated? I'm confused.
Perhaps one of you can give me an example on what to put on that line that starts with "mode"
Thanks -Dave- |
|
|
Comments: |
I believe you need a content-length header.
Before looking at details, I can tell you that it won't work unless you add an empty line between the HTTP headers and the body (mode=... line). (Deleted comment)
Damn, you beat me to the LWP::UserAgent suggestion, but that's because I was whipping up... #!/usr/bin/perl -w
use strict; use LWP;
my $ua = LWP::UserAgent->new; my $url = "http://www.livejournal.com/interface/flat";
my $msg = "yo+momma+is+phat"; my $sec = "private"; my $user = "LJUSER"; my $pass = "LJPASS";
my ($min, $hour, $day, $mon, $year) = (localtime)[1,2,3,4,5];
# year is $CALENDARYEAR - 1900 $year += 1900;
# month is 0-based $mon++;
my $content = "mode=postevent&user=$user&password=$pass&event=$msg&security=$sec&year=$year&mon=$mon&day=$day&hour=$hour&min=$min";
my $resp = $ua->post($url, content=>$content); :)
no problem :)
Obviously, this is quick-and-dirty and could use improvement, but it does work!
I must emphasize what others said, too: don't be tempted to do your own HTTP handling when there are good modules that do it for you :)
don't be tempted to do your own HTTP handling when there are good modules that do it for you :)
Thats one thing I love about Perl. 90% of any program I'm likely to write is already written for me, I just have to string a couple modules together and I'm done.
Ok, maybe its not quite that simple, but its pretty close.
how do I make this use md5 password?
Change "password" to "hpassword" and hash the thing. Check out the protocol docs for more info. MD5 passwords are no more secure than plain-text, though... you should use challenge/response :)
so after sending a getchallenge and printing use strict; use LWP; use Digest::MD5 qw(md5_hex);
my $ua = LWP::UserAgent->new; my $url = "http://www.livejournal.com/interface/flat";
my $content ="mode=getchallenge";
my $resp = $ua->post($url, content=>$content); if ($resp->is_success) { print $resp->content; } else { print "Bad luck this time\n"; }
I get the following auth_scheme c0 challenge c0:1098129600:2579:60:9HzLA0ZptbzIOfB66fIS:0cb96c3f8b712d5755af206d2e4c709e expire_time 1098132239 server_time 1098132179 success OK
I can't seem to find how to parse these reponse, in order to grab the challenge response to do my $response = md5_hex($result . md5_hex($pass)); How would you grab the response and put it in $result? I know this is more like a PERL question, but I just though you would know. thanks
oh I figured it out.
my @lo = split(/\n/,$resp->content);
thanks for the tips.
If you use a hash for it instead of an array, you can access it by name.
my %lo = split(/\n/, $resp->content); my $response = md5_hex($lo{challenge} . md5_hex($pass)); (Deleted comment)
It doesn't escape anything :) Hence why I said it's hacky and needs improvement :)
Actually, on that topic, I can't seem to find any url-encoding functions/modules anywhere, and neither can anyone here. We're probably just being dumb... do you know where I can find those? (Deleted comment)
Doesn't do URL encoding, just entitizing... at least as far as the CPAN page says.
URI::Escape includes the functions uri_escape and uri_unescape which will do that for you. Its part of the URI::URL module collection from CPAN includes this.
Page 21 of CGI Programming With Perl has the code for two functions that do the same thing, though it recommends using the ones from the module.
Rad, that's what I was looking for. I knew I had seen it before, but just couldn't track it down.
Kinda painful to bring in two modules for a 10-line hack, though ;)
You only need to bring in URI::Escape. Its just that that module is part of the collection called URI::URL. Granted, you have to install the whole collection unless you want to go through some hoops, but you only have to bring in the one to your actual script to do the escaping/unescaping.
Oh right, what I meant was URI::Escape and LWP :)
I've got a basically functional LJ client in Perl/Tk, development has stopped because I just couldn't deal with the broken Tk text widget.
It supports private/friends/friend group/public posting, using the XML-RPC interface. So if you are willing to use that interface, you can lift the code out you need. It isn't terribly well commented I'm afraid, and I'm sure you know how evil 200 or so lines of poorly commented perl can look.
It also supports moods, can't remember if I ever got around to user pictures or current music. | |