Here's an outline of the technique: I wrote a quick-and-dirty XML-RPC class designed to make fetching and editing friends, groups, and entries easier. Then, I threw a hidden image into a post whose src attribute referred it back to this PHP script. There, the PHP script instantiated the XML-RPC class, logged into my LJ account, and updated my entry with the relevant data. Cool, eh?
<?php class LJXMLRPC { var $if = null; var $user = null, $password = null; var $userid = null; var $fullname = null; var $friendgroups = null; var $fastserver = null; var $usejournals = null; function LJXMLRPC($user = null, $password = null) { require_once("XML/RPC.php"); $this->if = new XML_RPC_Client('/interface/xmlrpc', 'www.livejournal.com', 80); $this->user = $user; $this->password = $password; $msg = new XML_RPC_Message('LJ.XMLRPC.login', array(XML_RPC_encode(array('username' => $user, 'hpassword' => md5($password), 'ver' => 1)))); $resp = $this->if->send($msg); if (!$resp) { echo 'Transmission error: ' . $this->if->errstr; } else { if (!$resp->faultCode()) { $val = $resp->value(); $data = XML_RPC_decode($val); $this->userid = $data['userid']; $this->fullname = $data['fullname']; $this->friendgroups = $data['friendgroups']; $this->fastserver = $data['fastserver']; $this->usejournals = $data['usejournals']; } else { echo 'Fault Code: ' . $resp->faultCode() . "\n"; echo 'Fault Reason: ' . $resp->faultString() . "\n"; } } } function getFriends($limit = 0) { $msg = new XML_RPC_Message('LJ.XMLRPC.getfriends', array(XML_RPC_encode(array('username' => $this->user, 'hpassword' => md5($this->password), 'ver' => 1, 'limit' => $limit)))); $resp = $this->if->send($msg); if (!$resp) { echo 'Transmission error: ' . $this->if->errstr; } else { if (!$resp->faultCode()) { $val = $resp->value(); $data = XML_RPC_decode($val); return $data['friends']; } else { echo 'Fault Code: ' . $resp->faultCode() . "\n"; echo 'Fault Reason: ' . $resp->faultString() . "\n"; } } } function getFriendOfs($limit = 0) { $msg = new XML_RPC_Message('LJ.XMLRPC.friendof', array(XML_RPC_encode(array('username' => $this->user, 'hpassword' => md5($this->password), 'ver' => 1, 'friendoflimit' => $limit)))); $resp = $this->if->send($msg); if (!$resp) { echo 'Transmission error: ' . $this->if->errstr; } else { if (!$resp->faultCode()) { $val = $resp->value(); $data = XML_RPC_decode($val); return $data['friendofs']; } else { echo 'Fault Code: ' . $resp->faultCode() . "\n"; echo 'Fault Reason: ' . $resp->faultString() . "\n"; } } } function getFriendGroups() { return $this->friendgroups; } function getJournals() { return $this->usejournals; } function addFriend($user = null) { $msg = new XML_RPC_Message('LJ.XMLRPC.editfriends', array(XML_RPC_encode(array('username' => $this->user, 'hpassword' => md5($this->password), 'ver' => 1, 'add' => array(array('username' => $user)))))); $resp = $this->if->send($msg); if (!$resp) { echo 'Transmission error: ' . $this->if->errstr; } else { if (!$resp->faultCode()) { $val = $resp->value(); $data = XML_RPC_decode($val); } else { echo 'Fault Code: ' . $resp->faultCode() . "\n"; echo 'Fault Reason: ' . $resp->faultString() . "\n"; } } } function deleteFriend($user = null) { $msg = new XML_RPC_Message('LJ.XMLRPC.editfriends', array(XML_RPC_encode(array('username' => $this->user, 'hpassword' => md5($this->password), 'ver' => 1, 'delete' => array($user))))); $resp = $this->if->send($msg); if (!$resp) { echo 'Transmission error: ' . $this->if->errstr; } else { if (!$resp->faultCode()) { $val = $resp->value(); $data = XML_RPC_decode($val); } else { echo 'Fault Code: ' . $resp->faultCode() . "\n"; echo 'Fault Reason: ' . $resp->faultString() . "\n"; } } } function postEntry($subject = null, $text = null) { $msg = new XML_RPC_Message('LJ.XMLRPC.postevent', array(XML_RPC_encode(array('username' => $this->user, 'hpassword' => md5($this->password), 'ver' => 1, 'subject' => $subject, 'event' => $text, 'lineendings' => "\n", 'year' => date("Y"), 'mon' => date("m"), 'day' => date("d"), 'hour' => date("H"), 'min' => date("i"))))); $resp = $this->if->send($msg); if (!$resp) { echo 'Transmission error: ' . $this->if->errstr; } else { if (!$resp->faultCode()) { $val = $resp->value(); $data = XML_RPC_decode($val); } else { echo 'Fault Code: ' . $resp->faultCode() . "\n"; echo 'Fault Reason: ' . $resp->faultString() . "\n"; } } } function editEntry($itemid = null, $subject = null, $text = null) { $msg = new XML_RPC_Message('LJ.XMLRPC.editevent', array(XML_RPC_encode(array('username' => $this->user, 'hpassword' => md5($this->password), 'ver' => 1, 'itemid' => $itemid, 'subject' => $subject, 'event' => $text, 'lineendings' => "\n", 'year' => date("Y"), 'mon' => date("m"), 'day' => date("d"), 'hour' => date("H"), 'min' => date("i"))))); $resp = $this->if->send($msg); if (!$resp) { echo 'Transmission error: ' . $this->if->errstr; } else { if (!$resp->faultCode()) { $val = $resp->value(); $data = XML_RPC_decode($val); } else { echo 'Fault Code: ' . $resp->faultCode() . "\n"; echo 'Fault Reason: ' . $resp->faultString() . "\n"; } } } function getEntry($itemid = null) { $msg = new XML_RPC_Message('LJ.XMLRPC.getevents', array(XML_RPC_encode(array('username' => $this->user, 'hpassword' => md5($this->password), 'ver' => 1, 'selecttype' => 'one', 'itemid' => $itemid, 'lineendings' => "\n")))); $resp = $this->if->send($msg); if (!$resp) { echo 'Transmission error: ' . $this->if->errstr; } else { if (!$resp->faultCode()) { $val = $resp->value(); $data = XML_RPC_decode($val); return $data['events'][0]; } else { echo 'Fault Code: ' . $resp->faultCode() . "\n"; echo 'Fault Reason: ' . $resp->faultString() . "\n"; } } } } $l = new LJXMLRPC("g0thm0g", "OMGMYPASSWORDINPLAINTEXT"); $e = $l->getEntry(489); $l->editEntry(489, $e['subject'], $e['event'] . "\n<li>Viewed from " . $_SERVER['HTTP_REFERER'] . ' by ' . gethostbyaddr($_SERVER['REMOTE_ADDR']) . ' at ' . date("H:i:s m-d-Y")); ?>
I would try demo-ing it here, but as you can see from my journal, entries can get pretty long pretty quickly. Anyway, as usual, use the source as you wish and have fun!