<?php
/* LiveJournal export-file renderer; (c) 2002 Matt Robinson
 * 
 * Change the configuration below depending on how you plan 
 * to use this script. It's a bit boneheaded at the moment, 
 * so feel free to improve it, but email me at 
 * makali@lazycat.org and let me know, please. 
 * 
 * Current issues:
 *  - Bit messy, codewise
 *  - Export-files must be saved in XML format, and named in
 *    the following way: YYYY-MM.xml
 *  - Yes, that means the journals are rendered a month to a 
 *    page.  Don't write too much, I guess!
 *  - Output files are named YYYY-MM.html and are dumped
 *    wherever you run the script from.  
 */

/* Set this to your LJ username */
$user "makali";

/* Set this to the location of the data directory */
$data_dir "data";


/* Comment out the next line (remove the //) if you 
 * want to show friends-only and private posts as
 * well as the public ones. 
 */
define("HIDE_PRIVATE"TRUE);

/* ****************************************
 * You shouldn't need to change anything 
 * beyond this point.  Not that I mind or
 * anything!
 */

/* Journal Entry object */
class lj_entry {
    var 
$itemid;         // Entry ID; for building link to entry.
    
var $eventtime;      // Time & date of event, in English format (for now)
    
var $logtime;        // Er.. dunno?
    
var $subject;        // Entry subject line
    
var $event;          // Actual entry content
    
var $security;       // This is one of: public, friends, private, usemask
    
var $allowmask;      // This applies to "usemask" entries and is a list of friends to allow access to.
    
var $current_mood;   // Mood
    
var $current_music;  // Music.  With the right mood and the right music, anything can happen. Apparently.
    
    
function print_date() {
    return (empty(
$this->eventtime)) ? FALSE date("l jS F Y"strtotime($this->eventtime));
    }

    function 
print_event() {
    
/* Convert LJ-Cut to plain text */
    
$out preg_replace("/<lj\-cut.+text=\"(.+)\">/Ui""<span class=\"lj-cut\">$1</span>"$this->event);
    
$out str_replace("</lj-cut>"""$out);

    
/* Replace <lj user=""> with html equiv */
    
$out preg_replace("/<lj user=\"(.+)\">/Ui"
                
"<a href=\"http://www.livejournal.com/users/$1/\">$1</a>",
                
$out);

    
/* Return output */
    
return $out;
    }
    
    function 
set($field$value) {
    
/* Append the given data to the specified object property */
    
$this->$field .= $value;
    }
    
}


/* XML Parser object, loads and parses given file, and stores
 * it as an array of lj_entry objects. */

class journal {
    var 
$entries;
    var 
$current_entry;
    var 
$current_property;
    var 
$parser;

    
/* Constructor function; when a new object of this class is
     * created, set default values 
     */
    
function journal() {
    
$entries = array(); // Array of lj_entry objects
    
$current_entry 0// Array pointer to current object
    
$current_property NULL;
    }
    
    
    
/* XML Parser functions */
    
    
function startElement($parser$name$attrs) {
    switch (
$name) {
     case 
"LIVEJOURNAL":
        break;
     case 
"ENTRY":
        
$this->entries[$this->current_entry] = new lj_entry;
        break;
     default:
        
$this->current_property $name;
    }
    }
    
    function 
endElement($parser$name) {
    unset(
$this->current_property);
    if (
$name == "ENTRY") {
        
$this->current_entry++;
    }
    
    }
    
    function 
characterData($parser$data) {
    if (
trim($data) && !empty($this->current_property)) {
        
$this->entries$this->current_entry ]->set(strtolower($this->current_property), $data);
    }
    }
    

    function 
doconvert($matches) {
    return 
nl2br($matches);
    }
    
    
/* The main public function of this class */
    
function load_entries($filename) {
    
/* Load file into string, the create and run it through
     * a parser.
     */
    
$fp fopen($filename'rb') or die("Couldn't open file");
    
$file fread($fpfilesize ($filename));
    
fclose($fp);
    
    
$this->parser xml_parser_create();
    
xml_set_object($this->parser, &$this);
    
xml_parser_set_option($this->parserXML_OPTION_SKIP_WHITE1);

    
xml_set_element_handler($this->parser"startElement""endElement");
    
xml_set_character_data_handler($this->parser"characterData");

    if (!
xml_parse($this->parser$file)) {
        die(
sprintf("XML error: %s at line %d",
            
xml_error_string(xml_get_error_code($this->parser)),
            
xml_get_current_line_number($this->parser)));
    }
    
xml_parser_free($this->parser);
    }
}


/* Build the menu array */
$menu = array();
$out_menu "";
if (
$dp opendir($data_dir)) {
    while (
$filename readdir($dp)) {
    if (!
eregi("([0-9]{4}\-[0-9]{2}).xml"$filename$matches)) continue; // Skip non-conforming files.
    
$menu[] = $matches[1];
    
$out_menu .= "<li><a href=\"{$matches[1]}.html\">" date("F - Y"strtotime("{$matches[1]}-01")) . "</a></li>\n";
    }
    
sort($menu);
}


/* Loop through export files and rewrite output files */
foreach($menu as $month) {
    
$curr_month = new journal;
    if ( 
is_file("$data_dir/$month.xml") ) {
    
$curr_month->load_entries("$data_dir/$month.xml");
    
ob_start();

    foreach(
$curr_month->entries as $object) {
        if (
defined("HIDE_PRIVATE") && ( $object->security <> "public" ) )  continue;
?>
TITLE: <?=$object->subject?>

DATE: <?=date("m/d/Y H:i:s a"strtotime($object->eventtime))?>

AUTHOR:    <?=$user?>

-----
BODY:
<?=$object->print_event()?>

--------
<?
    
}
    
$output ob_get_contents();
    
ob_end_clean();
    if (!
$out_file fopen("$month.txt"'w')) {
        die(
"Couldn't open output file");
    } else {
        
fwrite($out_file$output);
        
fclose($out_file);
    }
    }
}
?>Done.