PHP Livejournal Embedding


eng | rus 


1 Intro

Online diaries gain favor among the internet-users year by year. There is a great number of sites which allow to publish the revelations in the internet easily and naturally, without any knowledge of the programming and markup languages. One of such sites - Livejournal (www.livejournal.com), the internet service, where every user can create personal diary.

2 The problem

The task is to create software which will allow to embed a diary from Livejournal to the personal site, to foresee the possibility of posts and comments display with the use of the pre-set template.

3 Existing solutions

Not everyone likes to link to LiveJournal.com to show their LiveJournal; a lot of people prefer to embed it directly into their own home page. However, doing so isn't always easy. There are a lot of differences between servers, and outside of these basic instructions below, we don't have much time to help everybody configure their own servers correctly. Even if you don't have control over your server, there are still some HTML-only ways to do it, although less transparently and with other additional caveats. (http://www.livejournal.com/developer/embedding.bml?method=all):

  1. JavaScript. The simplest way to embed your journal into your website is to just insert this JavaScript wherever in your webpage HTML that you want your journal to show up. In browsers where JavaScript is unavailable, a link to your journal can be shown instead.
    This JavaScript fragment loads JavaScript from LiveJournal. The special thing to note here is the &enc=js at the end of the customview.cgi arguments that tells LiveJournal to encode the page as one big document.write("...."); JavaScript command.
    <script language="JavaScript"
    src="http://www.livejournal.com/customview.cgi?username=username&amp;styleid=101&amp;enc=js">
    <noscript><a href="http://username.livejournal.com/">View my LiveJournal</a></noscript>
    </script>
    
  2. HTML Frames. One way to hide www.livejournal.com from the URL and make your journal look like part of your site is using frames... put the HTML page with the on your own server, and then make one of the frames be your journal. This method will work with any frame-supporting browser, including Netscape and Internet Explorer.
    Additionally, HTML-4.0 compliant browsers are supposed to let you embed a frame inline with your page, so it doesn't have to be on the far side. This is called an <iframe>. Internet Explorer supports this, as do Netscape 6, Mozilla and all recent Opera versions. Inline frames aren't as compatible as normal frames, and won't work in Netscape 4. The following example shows an iframe:
    <center>
    <iframe name="livejournal"
    src="http://www.livejournal.com/users/username/"
    frameborder="0"
    scrolling="auto" height="400" width="460">
    <a href="http://username.livejournal.com/">View my LiveJournal</a>
    </iframe>
    </center>
    
  3. PHP. Using fsockopen(). This method is slightly different, and may work even if URL fopen wrappers aren't enabled on your server. This method uses fsockopen() to open a network socket to the journal site, and then uses the HTTP protocol to request the journal's content. Given that it doesn't fail, it will simply fetch each line of the server's response.
    <?php
    $fp = fsockopen("www.livejournal.com", 80, &$errno, &$errstr, 30);
    if($fp) {
        fputs($fp,"GET /customview.cgi?".
                  "username=username&styleid=101 HTTP/1.0\n\n");
        while(!feof($fp)) {
            echo fgets($fp,128);
        }
        fclose($fp);
    }
    ?>
    

Obvious advantage of all of existent solutions is simplicity of realization. Similar embedding will occupy no more than 10 minutes with the minimum increase of page's download time.
Disadvantages: all of the above-described embedding methods are a paid account feature, and so these instructions will not work for users with free accounts. In case of their modification for free journals on your page, advertising will appear which must be additionally removed. The problem of design and embedded journal disparity appears. Conclusion: none of this methods gives flexibility in display tuning and customizing.

4 The Solution

Essence of the offered method is journal's records and comments parsing subsequent output to browser with the use of the pre-set template.

5 Used technologies

PHP, MYSQL, RSS, Sockets

6 Cross-browser

Internet Explorer 5.0,6.0,7.0; Firefox 1.0,2.0; Opera 9.0; Safari 2.0;

7 Input and output parameters

Input parameters:

  1. $user - Livejournal username;
  2. $postCount - amount of records, represented on a page;

Output parameters:

  1. Data structure, containing records and comments from user's Livejournal page.
  2. HTML-code fragment, representing Livejournal records and comments with the use of the pre-set template.

8 Implementation

At first we must get user's posts. Fortunately Livejournal gives out on a RSS channel with all of necessary information about a diary and last 25 posts. The fragment of RSS feed is displayed below

<?xml version='1.0' encoding='utf-8' ?>
<rss version='2.0' xmlns:lj='http://www.livejournal.org/rss/lj/1.0/'>
<channel>
  <title>Every Thug Needs a Lady</title>
  <link>http://idgiebay.livejournal.com/</link>
  <description>Every Thug Needs a Lady - LiveJournal.com</description>
  <lastBuildDate>Fri, 25 May 2007 01:04:48 GMT</lastBuildDate>
  <generator>LiveJournal / LiveJournal.com</generator>
  <image>
    <url>http://userpic.livejournal.com/10996047/449659</url>
    <title>Every Thug Needs a Lady</title>
    <link>http://idgiebay.livejournal.com/</link>
    <width>100</width>
    <height>87</height>
  </image>

<item>
  <guid isPermaLink='true'>http://idgiebay.livejournal.com/335686.html</guid>
  <pubDate>Fri, 25 May 2007 01:04:48 GMT</pubDate>
  <title>GO GO TOTTLES</title>
  <link>http://idgiebay.livejournal.com/335686.html</link>
  <description>&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;&lt;a href=&quot;
  http://photobucket.com&quot; target=&quot;_blank&quot;&gt;&lt;img
  src=&quot;http://img.photobucket.com/albums/v177/idgiebay/raphsample1.jpg&quot; 
  border=&quot;0&quot; alt=&quot;Photo Sharing and Video Hosting at
  Photobucket&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Used a screen grab for reference. 
  I&apos;m glad I finally taught myself how to ink in
  Illustrator. I luvs yew, Adobe.</description>
  <comments>http://idgiebay.livejournal.com/335686.html</comments>
  <category>artwork</category>
  <category>tmnt</category>
  <lj:mood>creative</lj:mood>
  <lj:security>public</lj:security>
</item>
<item>
  <guid isPermaLink='true'>http://idgiebay.livejournal.com/335451.html</guid>
  <pubDate>Thu, 24 May 2007 21:42:50 GMT</pubDate>
  <title>*____*</title>
  <link>http://idgiebay.livejournal.com/335451.html</link>
  <description>Oh, Adobe Illustrator, how could I have hated you so?</description>
  <comments>http://idgiebay.livejournal.com/335451.html</comments>
  <category>artwork</category>
  <lj:mood>ecstatic</lj:mood>
  <lj:security>public</lj:security>
</item>
<item>
  <guid isPermaLink='true'>http://idgiebay.livejournal.com/334916.html</guid>
  <pubDate>Thu, 17 May 2007 19:47:38 GMT</pubDate>
  <title>there&apos;s nothing that a hundred men or more could ever do</title>
  <link>http://idgiebay.livejournal.com/334916.html</link>
  <description>Ever been a song that just made you all sorts of nostalgic and 
  melancholy and you had no idea why? This song does that to me. It&apos;s not 
  a sad song and it&apos;s not a song that brings back fond childhood memories, 
  so I have no idea what the deal is. I love it, though. &amp;lt;3&lt;br 
  /&gt;&lt;br /&gt;But the chorus makes me want to cry.&lt;br /&gt;&lt;br /
  &gt;Oh well. Anyway.&lt;br /&gt;&lt;br /&gt;I have an interview tomorrow! 
  I&apos;m not leaving VPI, but I am trying to transfer within the company. 
  I don&apos;t know if I&apos;ll get the position, but here&apos;s hoping. 
  I&apos;ve not even been there six months, but my supervisor seems to think 
  I stand a good chance of getting it. She said she was going to write me up 
  just so she had a reason to keep me on her team... jokingly, of course. I
  have mixed emotions. I really want the job because I know I&apos;d be really
  good at it and it would mean being off the phones, but at the same time, I
  love my current job and Sara is, like, the coolest supervisor ever. So I 
  dunno. We&apos;ll see what happens. It&apos;s a coveted position among 
  the customer care folk, apparently.&lt;br /&gt;&lt;br /&gt;Off to shower.</description>
  <comments>http://idgiebay.livejournal.com/334916.html</comments>
  <category>job</category>
  <lj:music>&quot;Africa&quot; - Toto</lj:music>
  <lj:mood>okay</lj:mood>
  <lj:security>public</lj:security>
</item>
<item>
  <guid isPermaLink='true'>http://idgiebay.livejournal.com/334501.html</guid>
  <pubDate>Sat, 05 May 2007 22:55:37 GMT</pubDate>
  <title>moo</title>
  <link>http://idgiebay.livejournal.com/334501.html</link>
  <description>Man, am I exhausted... I haven&apos;t forgotten about that meme 
  thingie, I&apos;ve just been non-stop busy since yesterday... I&apos;ll 
  probably get to it tomorrow, as I&apos;m gonna go see Spidey 3 with Tif, 
  Bryan, Manda, and a bunch of people from work and I may spend the night 
  at Bryan&apos;s place, but I&apos;m not sure about that yet.&lt;br /&gt;&lt;br 
  /&gt;My head is freaking killing me.&lt;br /&gt;&lt;br /&gt;[Edit] By the way, 
  is anyone else having problems with Photobucket? I can upload stuff just fine, 
  but the pictures never load.</description>
  <comments>http://idgiebay.livejournal.com/334501.html</comments>
  <lj:music>something on the radio</lj:music>
  <lj:mood>exhausted</lj:mood>
  <lj:security>public</lj:security>
</item>
</channel>
</rss>

PHP is one of the most popular script languages, so we will take advantage of this interpreter for Livejournal embedding.
There are two widespread methods to work with XML documents - Event-based APIs and Document Object Model (DOM) APIs. In PHP standard support of XML is organized by Event-based API (based on events).
Firstly we will create the Rssparser class, into which all of work will be executed on the analysis of XML. After class creation, we will get RSS data from Livejournal feed and initialize XML handler, which will use Rssparser for event treatment (Event-based API). The code of RSSParser is situated below:

//RSSParser class
class RSSParser
{
	var $postCurrentNumb = 0;
	var $postCount = 0;
	var $insideItem = false;
	var $tag = "";
	var $maxPostSize = 999999;

	var $imageURL = "";
	var $lastBuildDate = "";
	var $lbd = "";
	var $userPic = "";

	var $title = "";
	var $dt = "";
	var $text = "";
	var $category = "";
	var $comments = "";

	var $lj = array();

	function startElement($parser, $tagName, $attrs)
	{
		if($this->insideItem)
		{
			$this->tag = $tagName;
		}
		elseif($tagName == "ITEM")
		{
			$this->insideItem = true;
		}
		elseif($tagName == "IMAGE")
		{
			$this->insideItem = true;
		}
		elseif($tagName == "LASTBUILDDATE")
		{
			$this->tag = $tagName;
			$this->insideItem = false;
		}
	}

	function endElement($parser, $tagName)
	{
		if($tagName == "IMAGE")
		{
			$this->userPic=$this->imageURL;
			$this->title = "";
			$this->insideItem = false;
		}

		if($tagName == "ITEM")
		{
			if ($this->postCurrentNumb<$this->postCount)
			{
				$this->lj[$this->postCurrentNumb][title]=UtoW($this->title);
				$this->text=UtoW($this->text);
				if (strlen($this->text)>$this->maxPostSize)
					$this->text=substr($this->text,0,$this->maxPostSize);
				$this->lj[$this->postCurrentNumb][text]=$this->text;
				$this->lj[$this->postCurrentNumb][comments]=trim($this->comments);
				$this->lj[$this->postCurrentNumb][tag]=UtoW($this->category);
				$this->lj[$this->postCurrentNumb][dt]=dateConvert($this->dt);
			}

			$this->title = "";
			$this->text= "";
			$this->comments = "";
			$this->category = "";
			$this->dt = "";

			$this->postCurrentNumb++;

			$this->insideItem = false;
		}

		if($tagName == "LASTBUILDDATE")
		{
			$this->lbd=dateConvert($this->lastBuildDate);
			$this->insideItem = false;
		}
	}

	function characterData($parser, $data)
	{
		if($this->insideItem)
		{
				switch($this->tag)
				{
					case "TITLE": $this->title .= $data; break;
					case "DESCRIPTION": $this->text .= $data; break;
					case "COMMENTS": $this->comments .= $data; break;
					case "CATEGORY": $this->category .= $data; break;
					case "PUBDATE": $this->dt .= $data; break;
					case "URL": $this->imageURL .= $data; break;
				}
		}
		else
		{
				switch($this->tag)
				{
					case "LASTBUILDDATE": $this->lastBuildDate .= $data; break;
				}

		}
	}

}

For strings decoding from Utf-8 to Windows-1251 we use UtoW() function:

//convert Unicode to Windows-1251
function UtoW($str)
{
	return (mb_convert_encoding($str,"windows-1251","UTF-8"));
}

For date format converting we use dateConvert() function:

//convert date
function dateConvert($str)
{
	return (date("Y-m-d H:i:s", strtotime($str)));
}

Now we'll create a function which initialize RSS handler.

	//generate posts
	function generatePostData($postCount)
	{
		$this->postsCount=$postCount;
		$xml_parser=xml_parser_create("UTF-8");
		$rss_parser=new RSSParser();
		$rss_parser->postCount=$this->postsCount;
		$rss_parser->maxPostSize=$this->maxPostSize;
		xml_set_object($xml_parser, &$rss_parser);
		xml_set_element_handler($xml_parser, "startElement", "endElement");
		xml_set_character_data_handler($xml_parser, "characterData");

		$fp = fopen("http://".$this->user.".livejournal.com/data/rss", "r")
			or die("Error reading RSS data from http://".$this->user.".livejournal.com/data/rss !");

		while(($data = fread($fp, 4096)) && ($rss_parser->postCurrentNumb<$rss_parser->postCount))
		{
			xml_parse($xml_parser, $data, feof($fp))
				  or die("Error parsing RSS data from http://".$this->user.".
			livejournal.com/data/rss !");
		}
		fclose($fp);

		xml_parser_free($xml_parser);

		$this->posts=$rss_parser->lj;
		$this->userPic=$rss_parser->userPic;
		$this->lastBuildDate=$rss_parser->lbd;

		if ($this->delcuts)
			$this->clearLivejournalCuts();
	}

This function is one of methods of Livejournal class. Parameter $this->postsCount determines the amount of records which will be proceed, $this->maxPostSize it is a maximal byte size of post. As a result of function generatepostdata() implementation we'll get an array $this->posts, in which journal's posts are stored by elements: Heading, Date, Text, Comment link.
A next step is a comments processing for each record. Unfortunately, Livejournal doesn't give out the RSS-feed for comments. Such feature isn't available even for paid accounts. Comments must be parsed with the help of Html-parser.
In Livejournal there are two stylesystems for journal displaying (http://www.livejournal.com/customize/) - S1 (for users with knowledge in CSS and HTML) and S2 (for other). In addition, there are a few styles for journal viewing (http://www.livejournal.com/manage/settings/): Horizon, Xcalibur, Dystopia, Lynx. We'll use Lynx style for comments page parsing. Also it will allow us to create universal parser for all display styles.
Getsocketdata() method reads HTML data from comments page. To use Lynx style for journal displaying we must append address string with parameter "?format=light".

	//get socket data
	function getSocketData($host,$request)
	{
		if ($fp = fsockopen($host, 80, $errno, $errstr, 5))
		{
			fputs($fp,$request);
			$data="";
			while(!feof($fp))
				$data.=fgets($fp,2048);
			fclose($fp);
		}
		return ($data);
	}

	//get livejournal comments
	function getLJCommentsSock($ljUser, $commentsId)
	{
		$commentsPath=$commentsId.".html?format=light";
		$host="livejournal.com";
		$commonRequest=	"Accept: */*"."\r\n".
	"Accept-Language: ru"."\r\n".
	"User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT)"."\r\n".
	"Connection: Keep-Alive"."\r\n";

	//  Get request

		$request=	"GET /".$commentsPath." HTTP/1.0"."\r\n".
					$commonRequest.
					"Cookie: ".$cookie."\r\n".
					"Host: ".$ljUser.".livejournal.com\r\n"."\r\n".
					"Pragma: no-cache"."\r\n";

		$data=$this->getSocketData($host, $request);

		$temp1=strpos($data,"/><a name='")+2;
		$temp2=strpos($data,"<hr />",$temp1);

		if ($temp1 && $temp2)
			$data = substr($data, $temp1, $temp2-$temp1);
		else
			$data="";

		$this->commentsData=UtoW($data);

	}

Next step - parsing comments with parseComments() method.

	//parse livejournal comments
	function parseComments()
	{
		$j=0;
		$prevName="";
		$parser = new HtmlParser($this->commentsData);

		while ($parser->parse())
		{
			if ($parser->iNodeName=="span" && $parser->iNodeType == NODE_TYPE_ELEMENT)
			{
				$attrValues = $parser->iNodeAttributes;
				$attrNames = array_keys($attrValues);
				$size = count($attrNames);
				for ($i = 0; $i < $size; $i++)
				{
					$name = $attrNames[$i];
					if ($attrNames[$i]=="lj:user")
						$this->comments[$j][user]=UtoW($attrValues[$name]);
				}
			};

			if ($parser->iNodeName=="Text" && ($parser->iNodeType == 
				NODE_TYPE_TEXT || $parser->iNodeType == NODE_TYPE_COMMENT))
			{
				if (strpos($parser->iNodeValue,"UTC"))
					$this->comments[$j][dt]=dateConvert($parser->iNodeValue);

				if ($prevName=="td" && trim($parser->iNodeValue))
					$this->comments[$j][text].=$parser->iNodeValue;

				if ($prevName=="br")
					$this->comments[$j][text].="<BR>".$parser->iNodeValue;

				if ($prevName=="b" && !$this->comments[$j][user] && $parser->iNodeValue!="(")
					$this->comments[$j][subj]=$parser->iNodeValue;

			};

			if ($parser->iNodeName=="img" && $parser->iNodeType == NODE_TYPE_ELEMENT)
			{
				$attrValues = $parser->iNodeAttributes;
				$attrNames = array_keys($attrValues);
				$size = count($attrNames);
				for ($i = 0; $i < $size; $i++)
				{
					$name = $attrNames[$i];
					if ($name=="src" && strpos($attrValues[$name],"userpic"))
						$this->comments[$j][pic]=$attrValues[$name];
				}
			}

			if ($parser->iNodeName=="a" && $parser->iNodeType == NODE_TYPE_ELEMENT)
			{
				$attrValues = $parser->iNodeAttributes;
				$attrNames = array_keys($attrValues);
				$size = count($attrNames);
				for ($i = 0; $i < $size; $i++)
				{
					$name = $attrNames[$i];
					if ($name=="href" && strpos($attrValues[$name],"replyto"))
					{
						$this->comments[$j][reply]=$attrValues[$name];
						$j++;
						$this->comments[$j][text]="";
					}
				}
			}

			$prevName=$parser->iNodeName;

		};

			$this->commentsCount=$j;
	}

As a result of parsecomments()function execution we'll get an array $this->comments with comments: Username, Userpic address, Heading, Date, Text, Answer link.
Some additional parameters are available: maximal size of record (var $maxPostSize = 999999) and cut deletion (var $delcuts = true);

9 Example

As an example of script work demonstration an arbitrary template was created.

<?php

require_once('inc/function.inc.php');
require_once('class/rssparser.class.php');
require_once('class/htmlparser.class.php');
require_once('class/lj.class.php');

connect_to_db($host,$login,$pass,$db_name);

$user="idgiebay";
$postCount=10;

$lj=new Livejournal($user);

if ($_GET[comment])
	{
		$lj->generateCommentsData($lj->user, $_GET[comment]);

		$query="SELECT value FROM info WHERE name='userpic' OR name='lastbuilddate' ORDER BY name ASC";
		$result=mysql_query($query);
		$row=mysql_fetch_array($result);
		$lbd=$row[value];
		$row=mysql_fetch_array($result);
		$userpic=$row[value];

		$postOut='<table width="600px" align="center" cellpadding="10">';

		$query="SELECT text, textfull FROM posts WHERE commentid='$_GET[comment]'";
		$result=mysql_query($query);
		$row=mysql_fetch_array($result);

		if ($row[textfull])
			$row[text]=$row[textfull];

		$postOut.='<tr><td><table width="100%" style="border: 1px dashed #000000; 
		background: url('/img/back2.jpg');"><tr>';
		$postOut.='<td style="padding: 20px" valign="top"><img src="'.$userpic.'"></td>';
		$postOut.='<td width="100%" style="padding: 20px 20px 20px 0px"><p class="text">'.
			str_replace("&rsquo;","'",$row[text]).'</p></td>';
		$postOut.='</tr><tr><td colspan="2" align="right" style="padding-right: 10px"><A href="http://'.
		$lj->user.'.livejournal.com/'.$_GET[comment].'.html?mode=reply" 
		target="_blank">reply...</A></td></tr></table></td></tr>';



		for ($i=0; $i<$lj->commentsCount; $i++)
		{
			$imgOut = ($lj->comments[$i][pic]) ? '<img src="'.$lj->comments[$i][pic].'"><BR>
				<img src="/img/lj.gif" hspace="2">
				<A href="http://'.$lj->comments[$i][user].'.livejournal.com" 
				target="_blank" style="line-height: 0"><b>'.$lj->comments[$i][user].'</b>
				</A>' : '<b>anonymous</b>';

			$postOut.='<tr><td><table width="100%" style="border: 1px dashed #000000; 
			background: url('/img/back.gif'); height: 100%">';

			$postOut.='<tr><td style="padding: 20px" align="center">'.$imgOut.'</td><td 
				width="100%" valign="top" style="height: 100%"
			><table width="100%" style="height: 100%">';

			$dateOut=substr($lj->comments[$i][dt],8,2)."-".
				substr($lj->comments[$i][dt],5,2)."-".substr($lj->comments[$i][dt],0,4)." |
			".substr($lj->comments[$i][dt],11,5);

			$postOut.='<tr><td align="right" style="padding: 4px">
				<span class="dt">['.$dateOut.']</span></td></tr>';

			$postOut.='<tr><td colspan="2" align="left"><span class="title">'.
				$lj->comments[$i][subj].'</span></td></tr>';
			$postOut.='<tr><td colspan="2" style="padding: 10px 10px 10px 0px; 
			height: 100%" valign="top"><p class="text">'.$lj->comments[$i][text].'</p></td></tr>';
			$postOut.='<tr><td colspan="2" align="right" style="padding-right: 
			10px"><A href="'.$lj->comments[$i][reply].'">reply...</A></td></tr>';

			$postOut.='</table></td></table></td></tr>';


		}

		$postOut.='<tr><td><table width="100%" style="border: 1px dashed #000000; 
		background: url('/img/back2.jpg');"><tr>';
		$postOut.='<td style="padding: 10px" align="center"><A href="/'.$lj->path.'
		/">&lt;&lt;&lt;&nbsp;back</A></td></tr></table></td></tr>';

		$postOut.='</table>';

	}
else
	{
		$lj->generatePostData($postCount);

		$query="UPDATE info SET value='".$lj->userPic."' WHERE name='userpic'";
		$result=mysql_query($query);

		$query="UPDATE info SET value='".$lj->lastBuildDate."' WHERE name='lastbuilddate'";
		$result=mysql_query($query);

		$postOut='<table width="600px" align="center" cellpadding="10">';

		$postOut.='<tr><td><table width="100%" style="border: 1px dashed #000000; 
		background: url('/img/back2.jpg');"><tr>';
		$postOut.='<td style="padding: 20px"><img src="'.$lj->userPic.'"></td>';
		$postOut.='<td width="100%" style="padding: 20px"><b>'.$user.''s livejournal</b></td>';
		$postOut.='</tr></table></td></tr>';

		for ($i=0; $i<$lj->postsCount; $i++)
		{
			$commentId=$lj->getCommentId($lj->posts[$i][comments]);
			
			$query="SELECT id FROM posts WHERE commentid='$commentId'";
			$result=mysql_query($query);
			$row_count=mysql_num_rows($result);

			if ($row_count==0)
				$query="INSERT INTO posts (commentid, text, textfull) VALUES 
				('$commentId', '".str_replace("'",'&rsquo;',$lj->posts[$i][text])."' ,
					'".str_replace("'",'&rsquo;',$lj->posts[$i][textfull])."')";
			else
				$query="UPDATE posts SET text='".str_replace("'",'&rsquo;',
				$lj->posts[$i][text])."', textfull='".str_replace("'",'&rsquo;',
				$lj->posts[$i][textfull])."' WHERE commentid='$commentId'";

			$result=mysql_query($query);

			$postOut.='<tr><td><table width="100%" style="border: 1px dashed 
			#000000; background: url('/img/back.gif');">';

			$dateOut=substr($lj->posts[$i][dt],8,2)."-".substr($lj->posts[$i][dt],5,2).
				"-".substr($lj->posts[$i][dt],0,4)." | ".substr($lj->posts[$i][dt],11,5);

			$postOut.='<tr><td align="right" style="padding: 4px">
				<span class="dt">['.$dateOut.']</span></td></tr>';

			$postOut.='<tr><td colspan="2" align="center"><span class="title">'.
				$lj->posts[$i][title].'</span></td></tr>';
			$postOut.='<tr><td colspan="2" style="padding: 10px"><p class="text">'.
				$lj->posts[$i][text].'</p></td></tr>';
			$postOut.='<tr><td colspan="2" align="right" style="padding-right: 10px">
				<A href="/'.$lj->path.'/'.$commentId.'/">comments...</A></td></tr>';

			$postOut.='</table></td></tr>';

		}

		$postOut.='</table>';

	}


?>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

<head>
	<title>Livejournal Integrator Sample</title>
	<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
	<style type="text/css">
		html, body
		{
			margin: 0;
			padding: 0;
			height: 100%;
			background: url('/img/back.jpg');
		}
		.dt
		{
			font: 13px Arial;
		}
		.text
		{
			font: 14px Tahoma;
			color: #FFF;
		}
		.title
		{
			font: 14px Tahoma;
		}
		a
		{
			color: #1C1FA7;
		}
		a:hover
		{
			color: #1C1FA7;
			text-decoration: none;
		}
	</style>
</head>

<body>

<?=$postOut?>

</body>
</html>




To watch online demonstration click here - PHP Livejournal Embedding

10 References

  1. Livejournal RSS processing - http://bikman.ru/texts/techarticle/ljrssphp/
  2. HTML Parser - http://php-html.sourceforge.net/
  3. Livejournal FAQ - http://www.livejournal.com/support/faq.bml

11 Downloads

PHP Livejournal Embedding classes, sql, template: ljembed.zip
Description: ljembed.pdf

© Andrew Zhupanenko
research@zhupanenko.com
http://research.zhupanenko.com/livejournal/

May, 2007


Comments

Name:
E-mail:
Text: