init
This commit is contained in:
470
ljcom/htdocs/developer/embedding.bml
Normal file
470
ljcom/htdocs/developer/embedding.bml
Normal file
@@ -0,0 +1,470 @@
|
||||
<?_code
|
||||
|
||||
use strict;
|
||||
use vars qw(%FORM $body $title);
|
||||
|
||||
$title = "Embedding LiveJournal";
|
||||
$body = "";
|
||||
my $ret = "";
|
||||
|
||||
# until this is in a database somewhere, here is the basic data structure:
|
||||
# @methods =
|
||||
# {
|
||||
# 'group' => "short lowercase 'group of methods' name",
|
||||
# 'title' => "full title",
|
||||
# 'detail' => "optional extra description",
|
||||
# 'methods' =>
|
||||
# [
|
||||
# 'name' => "optional method name",
|
||||
# 'author' => "optional method author",
|
||||
# 'text' => "mandatory paragraph",
|
||||
# 'explanation' => "optional 'why this does such and such'",
|
||||
# 'note' => "optional 'warning' or 'caution'",
|
||||
# 'example' => "mandatory example",
|
||||
# ]
|
||||
# };
|
||||
|
||||
my $method_javascript =
|
||||
{
|
||||
'text' =>
|
||||
"<?p 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. p?>",
|
||||
'explanation' =>
|
||||
"<?p 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 <tt>document.write("....");</tt> JavaScript command. p?>',
|
||||
'example' => <<"EOT",
|
||||
<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>
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_frameslayers =
|
||||
{
|
||||
'text' =>
|
||||
"<?p One way to hide <tt>www.livejournal.com</tt> from the URL and make your journal ".
|
||||
"look like part of your site is using frames... put the HTML page with the ".
|
||||
"<tt><frameset></tt> 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. p?>".
|
||||
"<?p 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 <code><iframe></code>. 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 <tt>iframe</tt>: p?>",
|
||||
'note' =>
|
||||
"<?p For more information on <code><iframe></code>, see ".
|
||||
"<a href=\"http://www.w3.org/TR/REC-html40/present/frames.html\#h-16.5\">the HTML 4.0 spec</a>. p?>",
|
||||
'example' => <<"EOT",
|
||||
<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>
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_cgi_script =
|
||||
{
|
||||
'name' => "Basic CGI Script",
|
||||
'text' =>
|
||||
"<?p You can write a CGI script (a program that runs on your server) to download ".
|
||||
"your journal and then spit it back out to your clients. You could write a CGI ".
|
||||
"script like this in any language, but by far the easiest language would be Perl, mostly ".
|
||||
"because just about every hosting provider supports it. p?>",
|
||||
'explanation' =>
|
||||
"<?p The client will never see <tt>www.livejournal.com</tt>, because your server is ".
|
||||
"actually the one that's downloading it. p?>",
|
||||
'note' =>
|
||||
"<?p This example uses the <em>LibWWW</em> module for perl, which you may need to install on your server, ".
|
||||
"or have your admin do it. p?>",
|
||||
'example' =>
|
||||
<<"EOT",
|
||||
#!/usr/bin/perl
|
||||
|
||||
use LWP::Simple;
|
||||
print "Content-type: text/html\\n\\n";
|
||||
print get('http://www.livejournal.com/customview.cgi' .
|
||||
'?username=[[username]]&styleid=101');
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_cgi_ssi =
|
||||
{
|
||||
'name' => "Server Side Includes and CGI",
|
||||
'text' =>
|
||||
"<?p If you already have some existing content that you don't want to modify and you ".
|
||||
"just want your LiveJournal inserted into an existing HTML document on your server ".
|
||||
"everytime a client requests it, you can create the CGI script in the previous example ".
|
||||
"and then place the example below into a server-parsed HTML document. p?>",
|
||||
'note' =>
|
||||
"<?p To get an HTML file to be server parsed, you usually have to name it <tt>.shtml</tt>, ".
|
||||
"or set its execute bit; it depends on your webserver and how it's configured. ".
|
||||
"In order to figure that out you might need to talk to your sysadmin. p?>",
|
||||
'example' =>
|
||||
<<"EOT",
|
||||
<!--#exec cgi="/cgi-bin/livejournal.cgi" -->
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_bml =
|
||||
{
|
||||
'text' =>
|
||||
"<?p If you're using <a href=\"http://www.bradfitz.com/bml/\">BML</a> on your server, you need ".
|
||||
"to do two things in your document. First, you need to set the NOCACHE flag (example included), so that the visitor's ".
|
||||
"browser doesn't store old states of the page in cache. Then you simply need to add in the given ".
|
||||
"_CODE block somewhere on your page. p?>\n".
|
||||
"<?p Since BML evaluates markup blocks returned from code blocks, you can include BML markup in your ".
|
||||
"embedding style in order to make your embedded journal fit in with your BML scheme. p?>",
|
||||
'note' =>
|
||||
"<?p This uses the <em>LibWWW</em> module for Perl, which you may need to install on your server, ".
|
||||
"or have your admin do it. p?>",
|
||||
'example' =>
|
||||
"<?_info\nNOCACHE=>1\n_info?>\n\n".
|
||||
BML::ehtml("<?_code\n\n use LWP::Simple;\n".
|
||||
" return get('http://www.livejournal.com/customview.cgi' .\n".
|
||||
" '?username=[[username]]&styleid=101');\n\n".
|
||||
"_code?>"),
|
||||
};
|
||||
|
||||
my $method_python =
|
||||
{
|
||||
'author' => " Jeremy Tribby",
|
||||
'text'=>
|
||||
"<?p Embedding your LiveJournal is easy with Python; just use the urllib class. p?>",
|
||||
'example' => <<"EOT",
|
||||
<%
|
||||
import urllib
|
||||
u = urllib.open('http://www.livejournal.com/customview.cgi?username=[[username]]&styleid=101')
|
||||
print 'Content-type: text/html\\n\\n'
|
||||
print u.read()
|
||||
%>
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_flash =
|
||||
{
|
||||
'text' =>
|
||||
"One of our users informed us that it is possible to have Flash download a list of ".
|
||||
"variables to prefill into text elements in a Flash file. The formatting of these ".
|
||||
"variable=value pairs are the same as in URLs. To accomodate this need, we provide ".
|
||||
"a style which does this formatting for you. As an example, see the URL below.",
|
||||
'example' =>
|
||||
'http://www.livejournal.com/customview.cgi?username=[[username]]&styleid=103',
|
||||
};
|
||||
my $method_php_fpassthru =
|
||||
{
|
||||
'name' => "Using <code>fpassthru()</code>",
|
||||
'author' => "<a href=\"http://www.whump.com/moreLikeThis/\">Bill Humpries</a>",
|
||||
'text' => "<?p This method simply opens the journal URL, and then prints the content. p?>",
|
||||
'explanation' =>
|
||||
"<?p This method uses <tt>fopen()</tt> to open the journal URL, and then uses <tt>fpassthru()</tt> ".
|
||||
"to pass the journal content to stdout. p?>",
|
||||
'example' => <<"EOT",
|
||||
<?php
|
||||
\$journalURL = "http://www.livejournal.com/".
|
||||
"customview.cgi?username=[[username]]&styleid=101";
|
||||
|
||||
if (\$fh = fopen(\$journalURL,"r")) {
|
||||
fpassthru(\$fh);
|
||||
} else {
|
||||
echo "<p>Unable to load journal.</p>\\n";
|
||||
}
|
||||
?>
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_php_fsockopen =
|
||||
{
|
||||
'name' => "Using <code>fsockopen()</code>",
|
||||
'author' => "<a href=\"mailto:elliot\@rightnowtech.com\">Elliot Schlegelmilch</a>",
|
||||
'text' => "<?p This method is slightly different, and may work even if URL fopen wrappers aren't enabled on your server. p?>",
|
||||
'explanation' =>
|
||||
"<?p This method uses <code>fsockopen()</code> 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. p?>",
|
||||
'example' => <<"EOT",
|
||||
<?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);
|
||||
}
|
||||
?>
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_php_file =
|
||||
{
|
||||
'name' => "Using <code>file()</code>",
|
||||
'author' => "<a href=\"mailto:jay\@fudge.org\">Jay Cuthrell</a>",
|
||||
'text' => "This method is useful for those that want a line by line parse of their journal, with line number references.",
|
||||
'explanation' =>
|
||||
"<?p This method uses the <code>file()</code> function to read in the journal content as a large array, and then it prints ".
|
||||
"it back out line by line. p?>",
|
||||
'example' => <<"EOT",
|
||||
<?php
|
||||
\$page = "http://www.livejournal.com/customview.cgi".
|
||||
"?username=[[username]]&styleid=101";
|
||||
\$content = file(\$page);
|
||||
\$slurp = "";
|
||||
while (list(\$foo,\$bar) = each(\$content)) {
|
||||
\$slurp .= \$bar;
|
||||
}
|
||||
echo \$slurp;
|
||||
?>
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_php_include =
|
||||
{
|
||||
'name' => "Using <code>include()</code>",
|
||||
'author' => "<a href=\"mailto:jon\@csh.rit.edu\">Jon Parise</a>",
|
||||
'text' => "<?p This simply includes the journal page inside of the PHP page. p?>",
|
||||
'note' => "<?p This requires you have URL fopen wrappers enabled (they're on by default in PHP 4). p?>",
|
||||
'example' => <<"EOT",
|
||||
<?php
|
||||
include "http://www.livejournal.com/customview.cgi".
|
||||
"?username=[[username]]&styleid=101";
|
||||
?>
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_asp_xmlhttp =
|
||||
{
|
||||
'name' => "Using the <tt>Microsoft.XMLHTTP</tt> component",
|
||||
'author' => "<a href=\"mailto:Pavel.Titov\@mtu-net.ru\">Pavel Titov</a>",
|
||||
'text' => "<?p This is an easy way to embed your journal using the <tt>Microsoft.XMLHTTP</tt> component and IIS. p?>",
|
||||
'example' => <<"EOT",
|
||||
<%
|
||||
Response.Buffer = True
|
||||
Dim xml
|
||||
|
||||
' Create an xmlhttp object:
|
||||
Set xml = Server.CreateObject("Microsoft.XMLHTTP")
|
||||
' Or, for version 3.0 of XMLHTTP, use:
|
||||
' Set xml = Server.CreateObject("MSXML2.ServerXMLHTTP")
|
||||
|
||||
' Opens the connection to the remote server.
|
||||
xml.Open "GET",
|
||||
"http://www.livejournal.com/customview.cgi?username=[[username]]&styleid=101",
|
||||
False
|
||||
|
||||
' Actually Sends the request and returns the data:
|
||||
xml.Send
|
||||
|
||||
Response.Write xml.responseText
|
||||
|
||||
Set xml = Nothing
|
||||
%>
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_asp_perlscript =
|
||||
{
|
||||
'name' => "Using PerlScript",
|
||||
'author' => "<a href=\"mailto:ansley\@net-impact.net\">Ansley Ingram</a>",
|
||||
'text' => "<?p Here is how to embed your LiveJournal on your site using ASP and PerlScript. p?>",
|
||||
'note' =>
|
||||
"<?p Unfortuately, many WinNT hosting providers don't offer PerlScript. ".
|
||||
"PerlScript is included in the <a href=\"http://www.activestate.com/ActivePerl/\">ActivePerl</a> ".
|
||||
"installation for NT from ActiveState. p?>",
|
||||
'example' => <<"EOT",
|
||||
<%\@language=perlscript%>
|
||||
<%
|
||||
use LWP::Simple;
|
||||
\$Response->Write(get 'http://www.livejournal.com/customview.cgi?' .
|
||||
'username=[[username]]&styleid=101');
|
||||
%>
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_aolserver =
|
||||
{
|
||||
'author' => "<?ljuser jackal ljuser?>",
|
||||
'text' => "<?p You can embed your LiveJournal on your site using AOLServer's .adp pages. p?>",
|
||||
'note' =>
|
||||
"<?p This is <strong>not</strong> for people using AOL's Internet Access service; ".
|
||||
"it is for people using the AOLServer web server. p?>",
|
||||
'example' => <<"EOT",
|
||||
<%
|
||||
ns_puts "[ns_geturl http://www.livejournal.com/customview.cgi?username=[[username]]&styleid=101 ]"
|
||||
%>
|
||||
EOT
|
||||
};
|
||||
|
||||
my $method_coldfusion =
|
||||
{
|
||||
'author' => "<?ljuser mrh ljuser?>",
|
||||
'text' => "<?p Cold Fusion users can embed their journals as follows. p?>",
|
||||
'example' => <<"EOT",
|
||||
<CFHTTP
|
||||
URL="http://www.livejournal.com/customview.cgi?username=[[username]]&styleid=101"
|
||||
METHOD="GET">
|
||||
</CFHTTP>
|
||||
<CFOUTPUT>\#cfhttp.filecontent\#</CFOUTPUT>
|
||||
EOT
|
||||
};
|
||||
|
||||
my @methods =
|
||||
(
|
||||
{'group' => "js",
|
||||
'title' => "JavaScript",
|
||||
'detail' => "The easiest way to embed",
|
||||
'methods' => [$method_javascript],
|
||||
},
|
||||
{'group' => "frameslayers",
|
||||
'title' => "HTML Frames",
|
||||
'detail' => "The next easiest way",
|
||||
'methods' => [$method_frameslayers],
|
||||
},
|
||||
{'group' => "cgi",
|
||||
'title' => "CGI Scripts",
|
||||
'detail' => "Easy server side programming",
|
||||
'methods' => [$method_cgi_script, $method_cgi_ssi,],
|
||||
},
|
||||
{'group' => "bml",
|
||||
'title' => "Better Markup Language",
|
||||
'detail' => "Using the language of LiveJournal",
|
||||
'methods' => [$method_bml],
|
||||
},
|
||||
{'group' => "flash",
|
||||
'title' => "Macromedia Flash",
|
||||
'methods' => [$method_flash],
|
||||
},
|
||||
{'group' => "php",
|
||||
'title' => "PHP",
|
||||
'methods' => [$method_php_fpassthru, $method_php_fsockopen, $method_php_file, $method_php_include],
|
||||
},
|
||||
{'group' => "python",
|
||||
'title' => "Python",
|
||||
'methods' => [$method_python],
|
||||
},
|
||||
{'group' => "asp",
|
||||
'title' => "Active Server Pages",
|
||||
'methods' => [$method_asp_xmlhttp, $method_asp_perlscript],
|
||||
},
|
||||
{'group' => "coldfusion",
|
||||
'title' => "Cold Fusion",
|
||||
'methods' => [$method_coldfusion],
|
||||
},
|
||||
{'group' => "adp",
|
||||
'title' => "AOLServer .adp pages",
|
||||
'methods' => [$method_aolserver],
|
||||
},
|
||||
);
|
||||
|
||||
my $selected_method_group = $FORM{'method'};
|
||||
my $valid_selection = (defined $selected_method_group and
|
||||
($selected_method_group eq "all" or
|
||||
grep { $selected_method_group eq $_->{'group'} } @methods));
|
||||
|
||||
unless ($valid_selection)
|
||||
{
|
||||
$ret .= <<"EOT";
|
||||
<?h1 Introduction h1?>
|
||||
<?p 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. p?>
|
||||
<?p 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. p?>
|
||||
<?p Note that embedding is a <a href="/paidaccounts/">paid account</a> feature,
|
||||
and so these instructions will not work for users with free accounts. p?>
|
||||
|
||||
Listed below are some of the different ways that you can embed your journal.
|
||||
<ul>
|
||||
EOT
|
||||
foreach my $method (@methods) {
|
||||
my $group = LJ::eurl($method->{'group'});
|
||||
$ret .= "<li><a href=\"embedding.bml?method=$group\"><b>$method->{'title'}</b></a>";
|
||||
if (defined $method->{'detail'}) {
|
||||
$ret .= " - $method->{detail}\n";
|
||||
}
|
||||
}
|
||||
$ret .= <<"EOT";
|
||||
</ul>
|
||||
|
||||
<?p
|
||||
Optionally, you can <a href="embedding.bml?method=all">view all</a> of the methods on
|
||||
one page.
|
||||
p?>
|
||||
<?hr?>
|
||||
<a href="./"><< Back to the developer area</a>
|
||||
EOT
|
||||
$body = $ret;
|
||||
return;
|
||||
}
|
||||
|
||||
my $remote = LJ::get_remote_noauth();
|
||||
my $ru=$remote->{'user'} || "<var>username</var>";
|
||||
|
||||
my $display_method = sub
|
||||
{
|
||||
my $method = shift;
|
||||
my $heading = (shift() ? "H1" : "H2");
|
||||
|
||||
next if not defined $method->{'methods'};
|
||||
foreach $method (@{$method->{'methods'}}) {
|
||||
if (defined $method->{'name'}) {
|
||||
$ret .="<?$heading $method->{'name'} $heading?>\n";
|
||||
}
|
||||
if (defined $method->{'author'}) {
|
||||
$ret .="<?p <span style=\"font-weight: bold;\">Contributed by:</span> ";
|
||||
$ret .= $method->{'author'} . " p?>";
|
||||
}
|
||||
$ret .= "$method->{text}\n";
|
||||
if (defined $method->{'explanation'}) {
|
||||
$ret .= "<?h2 Explanation h2?>$method->{'explanation'}\n";
|
||||
}
|
||||
if (defined $method->{'note'}) {
|
||||
$ret .= "<?h2 Note h2?>$method->{'note'}\n";
|
||||
}
|
||||
my $example=$method->{'example'};
|
||||
$example=~s/\[\[username\]\]/$ru/gs;
|
||||
$ret .= '<pre style="color: #0000ff">';
|
||||
$ret .= $example;
|
||||
$ret .= '</pre>';
|
||||
}
|
||||
};
|
||||
|
||||
if ($selected_method_group eq "all") {
|
||||
$title .= " - All Methods";
|
||||
foreach my $method (@methods) {
|
||||
$ret .= "<?h1 $method->{'title'} h1?>\n";
|
||||
$display_method->($method);
|
||||
$ret .= "<?hr?>";
|
||||
}
|
||||
|
||||
} else {
|
||||
foreach my $method (@methods) {
|
||||
if ($method->{'group'} eq $selected_method_group) {
|
||||
$title .= " - $method->{'title'}";
|
||||
# $ret .= "<?h1 $method->{'title'} h1?>\n";
|
||||
$display_method->($method,1);
|
||||
$ret .= "<?hr?>";
|
||||
}
|
||||
}
|
||||
}
|
||||
$ret .= '<a href="./embedding.bml"><< Back to the embedding page</a>';
|
||||
$body = $ret;
|
||||
return;
|
||||
_code?>
|
||||
|
||||
<?page
|
||||
title=><?_code return $title _code?>
|
||||
body=><?_code return $body _code?>
|
||||
page?>
|
||||
155
ljcom/htdocs/developer/exporting.bml
Normal file
155
ljcom/htdocs/developer/exporting.bml
Normal file
@@ -0,0 +1,155 @@
|
||||
<?page
|
||||
title=>Exporting Comments
|
||||
body<=
|
||||
<?p LiveJournal provides an interface for exporting comments using an XML format that makes it easy
|
||||
for people to write utilities to use the information. A user is allowed to download comments for
|
||||
any journal they administrate. p?>
|
||||
|
||||
<?p Please read the <a href="/bots/">LiveJournal Bot Policy</a> page, which discusses more general
|
||||
rules on how to download information from our servers without getting yourself banned. Also please
|
||||
follow the directions contained in this guide. p?>
|
||||
|
||||
<?p In order to use the comment exporter, you will need to have a valid session cookie. This can
|
||||
be obtained with the <tt>sessiongenerate</tt> protocol mode or by posting login information to the
|
||||
login.bml page. p?>
|
||||
|
||||
<?h2 Comment Data Summary h2?>
|
||||
<table border="1">
|
||||
<tr><th>Element</th><th>Attribute</th><th>Mode</th><th>Mutable</th><th>Description</th></tr>
|
||||
|
||||
<?_code
|
||||
{
|
||||
my @elements = (
|
||||
[ 'maxid', '', 'meta', 'yes', 'This element gives you an integer value of the maximum comment id currently available in the user\'s journal. This is the endpoint, inclusive.' ],
|
||||
[ 'comment', 'id', 'meta, body', 'no', 'The id of this particular comment.' ],
|
||||
[ 'comment', 'posterid', 'meta, body', 'yes', 'The id of the poster of this comment. This can only change from 0 (anonymous) to some non-zero number. It will never go the other way, nor will it change from some non-zero number to another non-zero number. Anonymous (0) is the default if no posterid is supplied.' ],
|
||||
[ 'comment', 'state', 'meta, body', 'yes', 'S = screened comment, D = deleted comment, A = active (visible) comment. If the state is not explicitly defined, it is assumed to be A.' ],
|
||||
[ 'comment', 'jitemid', 'body', 'no', 'Journal itemid this comment was posted in.' ],
|
||||
[ 'comment', 'parentid', 'body', 'no', '0 if this comment is top-level, else, it is the id of the comment this one was posted in response to. Top-level (0) is the default if no parentid is supplied.' ],
|
||||
[ 'usermap', 'id', 'meta', 'no', 'Poster id part of pair.' ],
|
||||
[ 'usermap', 'user', 'meta', 'yes', 'Username part of poster id + user pair. This can change if a user renames.' ],
|
||||
[ 'body', '', 'body', 'no', 'The text of the comment.' ],
|
||||
[ 'subject', '', 'body', 'no', 'The subject of the comment. This may not be present with every comment.' ],
|
||||
[ 'date', '', 'body', 'no', 'The time this comment was posted at. This is in the <a href="http://www.w3.org/TR/NOTE-datetime">W3C Date and Time</a> format.' ],
|
||||
[ 'property', '', 'body', 'no', 'The property tag has one attribute, name, that indicates the name of this property. The content of the tag is the value of that property.' ],
|
||||
);
|
||||
|
||||
my $ret = '';
|
||||
foreach my $r (@elements) {
|
||||
$ret .= "<tr>\n";
|
||||
$ret .= "<td>$_</td>\n" foreach @$r;
|
||||
$ret .= "</tr>\n";
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
|
||||
</table>
|
||||
|
||||
<?h2 Fetching Metadata h2?>
|
||||
<?standout
|
||||
<span style="color: red;">NOTE:</span> Please cache metadata, but note that it does contain things that
|
||||
can change about a comment. You should follow these instructions to update your cache once in a while.
|
||||
standout?>
|
||||
|
||||
<?p Comment metadata includes only information that is subject to change on a comment. It
|
||||
is a lightweight call that returns a small XML file that provides basic information on each comment
|
||||
posted in a journal. Step 1 of any export should look like this: p?>
|
||||
|
||||
<?p <pre> GET /export_comments.bml?get=comment_meta&startid=0</pre> p?>
|
||||
|
||||
<?p After you have made the above request, you will get back a response that looks something like this: p?>
|
||||
|
||||
<?p <pre>
|
||||
<?xml version="1.0" encoding='utf-8'?>
|
||||
<livejournal>
|
||||
<maxid>100</maxid>
|
||||
<comments>
|
||||
<comment id='71' posterid='3' state='D' />
|
||||
<comment id='70' state='D' />
|
||||
<comment id='99' />
|
||||
<comment id='100' posterid='3' />
|
||||
<comment id='92' state='D' />
|
||||
<comment id='69' posterid='3' state='S' />
|
||||
<comment id='98' posterid='3' />
|
||||
<comment id='73' state='D' />
|
||||
<comment id='86' state='S' />
|
||||
</comments>
|
||||
<usermaps>
|
||||
<usermap id='6' user='test2' />
|
||||
<usermap id='3' user='test' />
|
||||
<usermap id='2' user='xb95' />
|
||||
</usermaps>
|
||||
</livejournal></pre>
|
||||
p?>
|
||||
|
||||
<?p The first part is the actual comment metadata. Each row will contain the mutable information
|
||||
about a single comment. After this data is the list of users and their ids. These mappings will never change,
|
||||
so feel free to completely cache these. p?>
|
||||
|
||||
<?p You should also notice the maxid line. This shows you the maximum comment id that is in this user's
|
||||
journal. You should use this number to determine if you are done downloading or not. So, in pseudocode,
|
||||
you should use something like this to get metadata: p?>
|
||||
|
||||
<?p <pre>
|
||||
sub gather_metadata
|
||||
get largest comment id known about from my cache
|
||||
GET /export_comments.bml?get=comment_meta&startid=<i>maxid+1</i>
|
||||
add results to metadata cache
|
||||
if maximum id returned is less than maxid returned, call gather_metadata again
|
||||
end sub
|
||||
</pre> p?>
|
||||
|
||||
<?h2 Downloading the Comments h2?>
|
||||
<?standout
|
||||
<span style="color: red;">WARNING:</span> Comment body data is to be <b>heavily cached</b>. None of
|
||||
this data can change. Once you have downloaded a comment, you do not need to do so again.
|
||||
standout?>
|
||||
|
||||
<?p Once you have the entire list of metadata, you can begin downloading comments. The steps you will
|
||||
use are much the same as for getting metadata. Again, here is some pseudocode: p?>
|
||||
|
||||
<?p <pre>
|
||||
sub download_comments
|
||||
get largest comment id we have fully downloaded
|
||||
GET /export_comments.bml?get=comment_body&startid=<i>maxid+1</i>
|
||||
add results to comment cache
|
||||
if maximum id returned is less than maxid in metadata cache, call download_comments again
|
||||
if nothing was returned, and startid+1000 < maxid from metadata, call download_comments again
|
||||
end sub
|
||||
</pre> p?>
|
||||
|
||||
<?p The resulting format each time you hit export_comments.bml will look like this: p?>
|
||||
|
||||
<?p <pre>
|
||||
<?xml version="1.0" encoding='utf-8'?>
|
||||
<livejournal>
|
||||
<comments>
|
||||
<comment id='68' posterid='3' state='S' jitemid='34'>
|
||||
<body>we should all comment all day</body>
|
||||
<date>2004-03-02T18:14:06Z</date>
|
||||
</comment>
|
||||
<comment id='69' posterid='3' state='S' jitemid='34'>
|
||||
<body>commenting is fun</body>
|
||||
<date>2004-03-02T18:16:08Z</date>
|
||||
</comment>
|
||||
<comment id='99' jitemid='43' parentid='98'>
|
||||
<body>anonynote!</body>
|
||||
<date>2004-03-16T19:06:31Z</date>
|
||||
<property name='poster_ip'>127.0.0.1</property>
|
||||
</comment>
|
||||
<comment id='100' posterid='3' jitemid='43' parentid='98'>
|
||||
<subject>subject!#@?</subject>
|
||||
<body>&lt;b&gt;BOLD!&lt;/b&gt;</body>
|
||||
<date>2004-03-16T19:19:16Z</date>
|
||||
</comment>
|
||||
</comments>
|
||||
</livejournal>
|
||||
</pre> p?>
|
||||
|
||||
<?p That concludes this brief tutorial on exporting comment data in an appropriate manner
|
||||
so as not to be overly hard on the LiveJournal servers. Thanks for your cooperation, and
|
||||
don't forget to read the <a href="/bots/">Bot Policy</a> page. p?>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
52
ljcom/htdocs/developer/index.bml
Normal file
52
ljcom/htdocs/developer/index.bml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
body<=
|
||||
<?h1 <?_ml .notice.header _ml?> h1?>
|
||||
<?p <?_ml .notice1 _ml?> p?>
|
||||
<?p <?_ml .notice2 _ml?> p?>
|
||||
|
||||
<?h1 <?_ml .code.header _ml?> h1?>
|
||||
<?p <?_ml .code _ml?> p?>
|
||||
|
||||
<?h1 <?_ml .dbschema.header _ml?> h1?>
|
||||
<?p <?_ml .dbschema _ml?> p?>
|
||||
|
||||
<?h1 <?_ml .styles.header _ml?> h1?>
|
||||
<?p <?_ml .styles _ml?> p?>
|
||||
<?h2 <?_ml .styles.s1.header _ml?> h2?>
|
||||
<dl>
|
||||
<dt><a href="styles.bml"><?_ml .styles.s1.system _ml?></a></dt>
|
||||
<dd><?_ml .styles.s1.system.about _ml?></dd>
|
||||
<dt><a href="views.bml"><?_ml .styles.s1.views _ml?></a></dt>
|
||||
<dd><?_ml .styles.s1.views.about _ml?></dd>
|
||||
<dt><a href="varlist.bml"><?_ml .styles.s1.varlist _ml?></a></dt>
|
||||
<dd><?_ml .styles.s1.varlist.about _ml?></dd>
|
||||
</dl>
|
||||
|
||||
<?h2 <?_ml .styles.s2.header _ml?> h2?>
|
||||
<dl>
|
||||
<dt><a href="/doc/s2/"><?_ml .styles.s2.manual _ml?></a></dt>
|
||||
<dd><?_ml .styles.s2.manual.about _ml?></dd>
|
||||
<dt><a href="/customize/advanced/layerbrowse.bml"><?_ml .styles.s2.layerbrowse _ml?></a></dt>
|
||||
<dd><?_ml .styles.s2.layerbrowse.about _ml?></dd>
|
||||
</dl>
|
||||
|
||||
<?h1 <?_ml .embedding.header _ml?> h1?>
|
||||
<?p <?_ml .embedding _ml?> p?>
|
||||
|
||||
<?h1 <?_ml .clients.header _ml?> h1?>
|
||||
<?p <?_ml .clients _ml?> p?>
|
||||
<?_ml .clients.links _ml?>
|
||||
|
||||
<?h1 Exporting Comments h1?>
|
||||
<?p Exporting comments made on a journal or in a community can be accomplished with the comment
|
||||
exporting tool. Please see our <a href="exporting.bml">comment exporting tutorial</a> for more
|
||||
information. p?>
|
||||
|
||||
<=body
|
||||
head<=
|
||||
<style type="text/css">
|
||||
dt { font-weight: bold; }
|
||||
</style>
|
||||
<=head
|
||||
page?>
|
||||
BIN
ljcom/htdocs/developer/lj-icons.zip
Normal file
BIN
ljcom/htdocs/developer/lj-icons.zip
Normal file
Binary file not shown.
BIN
ljcom/htdocs/developer/logo.gif
Normal file
BIN
ljcom/htdocs/developer/logo.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
67
ljcom/htdocs/developer/modeinfo.bml
Normal file
67
ljcom/htdocs/developer/modeinfo.bml
Normal file
@@ -0,0 +1,67 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?page
|
||||
title=><?_code $v = LJ::ehtml(BML::get_query_string()); return "Mode: $v"; _code?>
|
||||
body<=
|
||||
<?h1 Mode Details... h1?>
|
||||
<?p
|
||||
The following are details on the <?_code return $v; _code?> request mode.
|
||||
p?>
|
||||
|
||||
<?_code
|
||||
|
||||
my @vars;
|
||||
LJ::load_objects_from_file("protocol.dat", \@vars);
|
||||
my $ret = "";
|
||||
|
||||
foreach my $v (grep { $_->{'name'} eq $v } @vars)
|
||||
{
|
||||
my $mode = $v->{'name'};
|
||||
$ret .= "<p><table width='100%' bgcolor='#C0C0C0'><tr><td><font size='+1'><b>$mode</b></font></td></tr></table>\n\n";
|
||||
$ret .= "<table cellspacing='2'>\n";
|
||||
$ret .= "<tr valign='top'><td align='left' colspan='2' bgcolor='#e0e0e0'><i>Description</i></td></tr>\n";
|
||||
$ret .= "<tr><td colspan='2'>$v->{'props'}->{'des'}</td></tr>\n";
|
||||
|
||||
unshift (@{$v->{'props'}->{'request'}},
|
||||
{ 'name' => "mode", 'props' => { 'des' => "The protocol request mode: <b><tt>$mode</tt></b>", } },
|
||||
{ 'name' => "user", 'props' => { 'des' => "Username. Leading and trailing whitespace is ignored, as is case.", } },
|
||||
{ 'name' => "password", 'props' => { 'des' => "Password in plain-text. Either this needs to be sent, or <tt>hpassword</tt>.", } },
|
||||
{ 'name' => "hpassword", 'props' => { 'des' => "Alternative to plain-text <tt>password</tt>. Password as an MD5 hex digest. Not perfectly secure, but defeats the most simple of network sniffers.", } },
|
||||
{ 'name' => "ver", 'props' => { 'des' => "Protocol version supported by the client; assumed to be 0 if not specified. See <a href='versions.bml'>this document</a> for details on the protocol version.", 'optional' => 1, } },
|
||||
);
|
||||
unshift (@{$v->{'props'}->{'response'}},
|
||||
{ 'name' => "success", 'props' => { 'des' => "<b><tt>OK</tt></b> on success or <b><tt>FAIL</tt></b> when there's an error. When there's an error, see <tt>errmsg</tt> for the error text. The absence of this variable should also be considered an error.", } },
|
||||
{ 'name' => "errmsg", 'props' => { 'des' => "The error message if <tt>success</tt> was <tt>FAIL</tt>, not present if <tt>OK</tt>. If the success variable isn't present, this variable most likely won't be either (in the case of a server error), and clients should just report \"Server Error, try again later.\".", } },
|
||||
);
|
||||
|
||||
foreach my $rr (qw(request response))
|
||||
{
|
||||
$ret .= "<tr valign='top'><td align='left' colspan='2' bgcolor='#e0e0e0'><i>" . ucfirst($rr) . "</i></td></tr>\n";
|
||||
foreach (@{$v->{'props'}->{$rr}})
|
||||
{
|
||||
my $des = $_->{'props'}->{'des'};
|
||||
$des =~ s!\[special\[logprops\]\]!<a href="/doc/server/ljp.csp.proplist.html">logprops</a>!;
|
||||
$ret .= "<tr valign='top'><td align='left' nowrap='nowrap' bgcolor='#f0f0f0'><b>$_->{'name'}</b></td>";
|
||||
$ret .= "<td>";
|
||||
if ($_->{'props'}->{'optional'}) {
|
||||
$ret .= "<i>(Optional)</i> ";
|
||||
}
|
||||
$ret .= $des;
|
||||
$ret .= "</td>";
|
||||
$ret .= "</tr>\n";
|
||||
}
|
||||
}
|
||||
|
||||
$ret .= "</table>\n";
|
||||
}
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<?hr?>
|
||||
Back to <a href="modelist.bml">Protocol Modes</a>.<br/>
|
||||
Back to <a href="protocol.bml">Protocol Documentation</a>.<br/>
|
||||
Back to <a href="/developer/">Developer Area</a>.
|
||||
|
||||
<=body
|
||||
page?>
|
||||
37
ljcom/htdocs/developer/modelist.bml
Normal file
37
ljcom/htdocs/developer/modelist.bml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?page
|
||||
title=>Protocol Mode List
|
||||
body<=
|
||||
|
||||
<?h1 Introduction h1?>
|
||||
<?p
|
||||
The following information is a list of the different request modes you can make to the LiveJournal server using the <A HREF="protocol.bml">LiveJournal protocol</A>. Click one for more information, including request and response variables.
|
||||
p?>
|
||||
|
||||
<?h1 Variables h1?>
|
||||
<?p
|
||||
Click a variable name for more information about how and where to use it.
|
||||
<DL>
|
||||
<?_code
|
||||
|
||||
my @vars;
|
||||
LJ::load_objects_from_file("protocol.dat", \@vars);
|
||||
my $ret = "";
|
||||
|
||||
foreach my $v (sort { $a->{'name'} cmp $b->{'name'} } @vars)
|
||||
{
|
||||
$ret .= "<DT><A HREF=\"modeinfo.bml?$v->{'name'}\"><B>$v->{'name'}</B></A>";
|
||||
$ret .= "<DD>" . $v->{'props'}->{'des'} . "\n";
|
||||
}
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
</DL>
|
||||
p?>
|
||||
|
||||
<?hr?>
|
||||
Back to <A HREF="/developer/">Developer Area</A>.
|
||||
|
||||
<=body
|
||||
page?>
|
||||
105
ljcom/htdocs/developer/moods.txt
Executable file
105
ljcom/htdocs/developer/moods.txt
Executable file
@@ -0,0 +1,105 @@
|
||||
###
|
||||
### server-supported moods vs. custom moods
|
||||
###
|
||||
|
||||
users will be able to use either server-supported moods or their
|
||||
own custom moods.
|
||||
|
||||
to use a server-supported mood, clients will use metadata property:
|
||||
|
||||
current_moodid (numeric)
|
||||
|
||||
to use a custom mood, clients will use metadata property:
|
||||
|
||||
current_mood
|
||||
|
||||
Or, use them both. Why? The current_moodid will indicte the picture to use, the current_mood will have the text to display. Clients may decide how they'd like to do it (using neither, one, or both)
|
||||
|
||||
If only a current_moodid is given, the text will be from the server.
|
||||
|
||||
### a list of all server-supported moods
|
||||
### each mood has a parent (base) mood. at the top of the tree would be
|
||||
### "positive" or "negative", but since those are boring, maybe "happy" and "sad"
|
||||
|
||||
CREATE TABLE moods (
|
||||
moodid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
mood VARCHAR(40),
|
||||
parentmood INT UNSIGNED NOT NULL DEFAULT '0'
|
||||
);
|
||||
|
||||
### I think the moods should be displayed with a picture with ALIGN=ABSMIDDLE, a space,
|
||||
### and then the mood in text.
|
||||
|
||||
### people will of course want to customize the images for the moods, so there
|
||||
### will be mood themes
|
||||
|
||||
CREATE TABLE moodthemes (
|
||||
moodthemeid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
ownerid INT UNSIGNED NOT NULL
|
||||
name VARCHAR(50),
|
||||
des VARCHAR(100),
|
||||
is_public ENUM('Y', 'N') NOT NULL DEFAULT 'N'
|
||||
);
|
||||
|
||||
### users don't have to define pictures for every mood ... just certain base ones
|
||||
### LiveJournal will find the picture by working up the tree until it finds one
|
||||
### with a picture defined that's either gender neutral or matching gender
|
||||
|
||||
CREATE TABLE moodthemedata (
|
||||
moodthemeid INT UNSIGNED NOT NULL,
|
||||
KEY (moodthemeid),
|
||||
moodid INT UNSIGNED NOT NULL,
|
||||
gender ENUM('m', 'f', 'n') NOT NULL DEFAULT 'n',
|
||||
UNIQUE (moodthemeid, moodid, gender),
|
||||
picurl VARCHAR(100),
|
||||
width TINYINT UNSIGNED NOT NULL,
|
||||
height TINYINT UNSIGNED NOT NULL
|
||||
);
|
||||
|
||||
### how to get moods:
|
||||
###
|
||||
|
||||
extending the "login" protocol:
|
||||
|
||||
if you send the request key "getmoods" with a value of the highest moodid you have
|
||||
cached locally, the server will send you back the newer ones, if any:
|
||||
|
||||
mood_count
|
||||
mood_n_id -- mood ID number
|
||||
mood_n_name -- mood text
|
||||
|
||||
if you're lazy, you can send getmoods=0 to get all the moods everytime, or you can
|
||||
send no getmoods key at all, and not have them returned, so it doesn't slow old
|
||||
clients.
|
||||
|
||||
#### some moods (these need to be put into a tree, showing which moods
|
||||
#### are base moods of each other..... volunteers?)
|
||||
|
||||
aggravated
|
||||
angry
|
||||
annoyed
|
||||
anxious
|
||||
bored
|
||||
confused
|
||||
depressed
|
||||
exhausted
|
||||
happy
|
||||
lonely
|
||||
pissed
|
||||
sad
|
||||
stressed
|
||||
tired
|
||||
sore
|
||||
energetic
|
||||
enraged
|
||||
infuriated
|
||||
jubilant
|
||||
horny
|
||||
hungry
|
||||
discontent
|
||||
thirsty
|
||||
satisfied
|
||||
thoughtful
|
||||
.....
|
||||
|
||||
tons more needed. if you send me some, don't just rip off another site's list... use your head and think of them independently.
|
||||
154
ljcom/htdocs/developer/protocol.bml
Normal file
154
ljcom/htdocs/developer/protocol.bml
Normal file
@@ -0,0 +1,154 @@
|
||||
<?page
|
||||
title=>LiveJournal Protocol
|
||||
body<=
|
||||
|
||||
<?h1 Introduction h1?>
|
||||
<?p
|
||||
The following information is intended for developers interested in writing their own
|
||||
LiveJournal clients to talk to the LiveJournal server. End users <I>do not</I> need
|
||||
to know any of this, and are probably better off not knowing it. ;)
|
||||
p?>
|
||||
<?h1 Prerequisites h1?>
|
||||
<?p
|
||||
Before reading this document, it is assumed you know at least some basics about network programming,
|
||||
at least the whole idea of opening sockets and reading/writing to them. If not, this might
|
||||
be kinda confusing.
|
||||
p?>
|
||||
<?h1 It's really HTTP h1?>
|
||||
<?p
|
||||
If you already know the HTTP protocol, this is going to be really easy. For those of you
|
||||
who don't know, HTTP is the protocol that web browsers talk to web servers with. For simplicity
|
||||
of writing the LiveJournal server, we've decided to just use HTTP as our protocol transport.
|
||||
This way, we can also go through proxies at schools and corporations really easily and
|
||||
without drawing any attention.
|
||||
p?>
|
||||
<?h1 The Basics h1?>
|
||||
<?p
|
||||
Basically, sending a LiveJournal request is like this:
|
||||
p?>
|
||||
<OL>
|
||||
<LI>Open a socket to <B>www.livejournal.com</B> on port <B>80</B>
|
||||
<LI>Send an HTTP POST request, containing the request variables (mode, user, password, etc...)
|
||||
<LI>Read the socket to get the response. The response is really easy to parse.
|
||||
<LI>Close the socket. Do any approriate action based on the server's response.
|
||||
</OL>
|
||||
|
||||
<?h1 Encoding the request h1?>
|
||||
<?p
|
||||
As mentioned previously, the request is sent as an HTTP POST request. Open your socket, and send a request looking like:
|
||||
p?>
|
||||
<UL>
|
||||
<FONT COLOR=#0000FF><B>
|
||||
<XMP>
|
||||
POST /interface/flat HTTP/1.0
|
||||
Host: www.livejournal.com
|
||||
Content-type: application/x-www-form-urlencoded
|
||||
Content-length: 34
|
||||
|
||||
mode=login&user=test&password=test
|
||||
</XMP>
|
||||
</B></FONT>
|
||||
</UL>
|
||||
As you can pretty easily see, the variables TO the webserver are encoded in the form <B>var1=val1&var2=val2&....</B>. Note
|
||||
that you <B>must quote all values</B> or the values can interfere with the encoding form. For example, what if somebody's
|
||||
password was "blah&=2+&something=yeah". It's an ugly password, sure, but somebody may have it. And if they do, it'll mess
|
||||
up the pretty format of the encoding format. So, here are the rules on how to encode values:
|
||||
<UL>
|
||||
<LI>Leave all values from a-z, A-Z, and 0-9 alone. These are fine.
|
||||
<LI>Convert spaces to a <B>+</B> sign.
|
||||
<LI>Convert everything else to <B>%<I>hh</I></B> where <I>hh</I> is the hex representation of the character's ASCII value.
|
||||
</UL>
|
||||
So, for example, the phrase "I'm going to the mall" could encoded as "I%27m+going+to+the+mall". There should
|
||||
be CGI libraries for all major languages which do this encoding for you. If not, it isn't that hard to do it yourself.
|
||||
<?p
|
||||
After you construct the big long ugly string of variables/values, find the length of it and send it in the
|
||||
<I>Content-length</I> field, as in the example above. Then send a blank line, then the big long ugly string.
|
||||
p?>
|
||||
<?p
|
||||
<B>Note about line endings: </B> Please note that the end of lines should be a carriage return (ASCII 13, 0x0D) and then a newline (ASCII 10, 0x0A).
|
||||
In Perl, C/C++ or Java this is "\r\n". In Basic, this is Chr(13) & Chr(10). Sending just the newline may work too, but
|
||||
it's generally better to send both.
|
||||
p?>
|
||||
|
||||
<?p
|
||||
Here is a typical response from the web server after sending your request:
|
||||
|
||||
<UL>
|
||||
<FONT COLOR=#0000FF><B>
|
||||
<XMP>
|
||||
HTTP/1.1 200 OK
|
||||
Date: Sat, 23 Oct 1999 21:32:35 GMT
|
||||
Server: Apache/1.3.4 (Unix)
|
||||
Connection: close
|
||||
Content-Type: text/plain
|
||||
|
||||
name
|
||||
Mr. Test Account
|
||||
success
|
||||
OK
|
||||
message
|
||||
Hello Test Account!
|
||||
</XMP></B></FONT>
|
||||
</UL>
|
||||
|
||||
The top stuff is headers from the HTTP request. There may be a lot of other stuff in there too.
|
||||
First thing to do is make sure the first lines <B>ends with "200 OK"</B>. If the first line
|
||||
does not end with 200 OK, tell the user that an error occured on the server and that it's not their fault.
|
||||
If you see 200 OK at the end, proceed with parsing the output. The format is as follows:
|
||||
<UL>
|
||||
<XMP>
|
||||
variable
|
||||
value
|
||||
someothervariable
|
||||
someothervalue
|
||||
</XMP>
|
||||
</UL>
|
||||
The ordering of the variable/value pairs does not matter. As you read them in, read them into a hash
|
||||
structure. (associative array, dictionary, collection... whatever it's called in your language. Just
|
||||
a data structure that links one string variable key to another string variable value.)
|
||||
p?>
|
||||
<?p
|
||||
After your hash is loaded, proceed with the logic of reporting errors if needed, as governed by the
|
||||
variables and logic above.
|
||||
p?>
|
||||
|
||||
<?h1 Protocol modes h1?>
|
||||
<?p
|
||||
Of course, knowing all the above isn't useful unless you actually know what operations
|
||||
the server supports....
|
||||
p?>
|
||||
<P><CENTER>
|
||||
<A HREF="modelist.bml"><FONT SIZE=+1>Protocol Mode Documentation</FONT></A>
|
||||
</CENTER>
|
||||
|
||||
<?h1 Proxies h1?>
|
||||
<?p
|
||||
As a final feature, once you get that stuff working, is to implement support for HTTP proxies. This
|
||||
is <I>very</I> easy. Give the user a checkbox if they want to use a proxy or not, and if so, ask
|
||||
the proxy host and proxy port. Now, if they selected to use a proxy, do not connect to
|
||||
www.livejournal.com and port 80, but instead connect to their proxy host on whatever proxy
|
||||
port they specified. The rest is basically the same, except for one difference. Instead of doing:
|
||||
<UL>
|
||||
<XMP>
|
||||
POST /interface/flat HTTP/1.0
|
||||
</XMP>
|
||||
</UL>
|
||||
<p>You would do...
|
||||
<UL>
|
||||
<FONT COLOR=#0000FF><B><XMP>
|
||||
POST http://www.livejournal.com/interface/flat HTTP/1.0
|
||||
</XMP></B></FONT>
|
||||
</UL>
|
||||
<p>That's it! That line tells the proxy what host it needs to connect to in order to make the real request.
|
||||
The rest of the HTTP you should leave just as you did before.
|
||||
This should be all you need to know to make a LiveJournal client.
|
||||
p?>
|
||||
|
||||
|
||||
<?h1 Need more help? h1?>
|
||||
<?p
|
||||
If anything is unclear, join the <?ljuser lj_clients ljuser?> community, where all the client authors hang out.
|
||||
p?>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
49
ljcom/htdocs/developer/rawmode.bml
Normal file
49
ljcom/htdocs/developer/rawmode.bml
Normal file
@@ -0,0 +1,49 @@
|
||||
<?page
|
||||
title=>Raw Mode
|
||||
body<=
|
||||
|
||||
<?h1 Raw mode? h1?>
|
||||
<?p
|
||||
Before LiveJournal had the currently fancy style editor it has now, users had to edit the style files by hand. This is the old documentation on how that was done....
|
||||
p?>
|
||||
|
||||
<?hr?>
|
||||
|
||||
<?h1 Defining Variables h1?>
|
||||
<?p
|
||||
When creating a style or overriding other styles, you must define (or re-define) variables in a very specific format that the server can understand. You have two options, depending on whether the value of your variable is going to be very short (a single line) or multiple lines.
|
||||
p?>
|
||||
<?p For a single line element, like the number of items to be shown in your most-recent journal history, you specify the variable name (which is always in ALL-CAPS) and then the characters <B><tt>=></tt></B>, and the value. For example:
|
||||
<UL>
|
||||
<FONT COLOR=#0000FF><XMP>
|
||||
lastn_opt_items=>25
|
||||
</XMP></FONT>
|
||||
</UL>
|
||||
That will tell the server that for the "lastn" page (the recent journal history) that you want 25 items to be displayed.
|
||||
p?>
|
||||
<?p For multiple line elements, the format is similiar. First you specify the variable name, but instead of <tt>=></tt> you do a <B><tt><=</tt></B> and go to the next line. Then, type all the lines that you want in that variable and go to a new line and type <B><tt><=<I>VARIABLE</I></tt></B>. For example:
|
||||
<UL>
|
||||
<FONT COLOR=#0000FF><XMP>
|
||||
lastn_page<=
|
||||
<HTML>
|
||||
<BODY BGCOLOR=yellow>
|
||||
Here's what I've been doing lately... <P>
|
||||
%%events%%
|
||||
<HR>
|
||||
Back to my
|
||||
<A HREF="http://www.myserver.com/">
|
||||
my home page
|
||||
</A>.
|
||||
</HTML>
|
||||
<=lastn_page
|
||||
</XMP></FONT>
|
||||
</UL>
|
||||
The variable begins at the <HTML> line and ends with the </HTML> line.
|
||||
p?>
|
||||
<?p
|
||||
One thing interesting to note in the preceeding example is the <B>%%events%%</B> property. All things enclosed in double percent signs are properties that the server will fill in. All variables and properties are documented. See the <B><A HREF="varlist.bml">list of variables</A></B> for more information.
|
||||
page.
|
||||
p?>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
51
ljcom/htdocs/developer/styles.bml
Normal file
51
ljcom/htdocs/developer/styles.bml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?page
|
||||
title=>Style System
|
||||
body<=
|
||||
<?h1 Introduction h1?>
|
||||
<?p
|
||||
When LiveJournal was designed, we wanted it to be both easy to use, and still extremely flexible for the power users that like to tweak everything. We took some time and developed a system that we hope will accomodate everyone.
|
||||
p?>
|
||||
<?p
|
||||
In LiveJournal, there are different view modes. The most common one is named "lastn", a view that displays the last 'n' number of events in one's journal. Additionally, there is a calendar view, a day view, a search page, and a search results page, and possibly more modes we may add in the future. Knowing that we're going to want to extend this in the future, and knowing some users will never be happy if we hard-code the style of the pages (and knowing that we suck at making things really pretty), our system lets users pick a base style for each mode, and override individual elements of the style at will.
|
||||
p?>
|
||||
<?p To better explain how things work, let's walk through things step by step, from the perspective of different users, explaining what's going on behind the scenes... p?>
|
||||
|
||||
<?h1 The casual user... h1?>
|
||||
<?p
|
||||
The casual user is one that doesn't know much about programming, if any, and just wants to get their journal up and running as quick as possible, and they want it to look pretty. What we're going to offer the casual user is a way to pick from pre-made styles. The pre-made styles define a bunch of variables used internally by the LiveJournal server code that generates the pages. Users will see syles names like "Classic Layout", "Simple Layout", "Modern Look" and then they'll be able to specify their colors for that layout ("style"). But behind the scenes the server will load the user's record, see they've selected style ID# 1043, and preload all the variables necessary to make the page look a certain way. By default, we'll provide a few styles and in time we'll let users submit their self-created styles to be approved to be system-wide styles that anybody can use.
|
||||
p?>
|
||||
|
||||
<?h1 The advanced user... h1?>
|
||||
<?p
|
||||
The advanced user will more than likely start as being a casual user, but will soon grow annoyed at the way a certain thing about their journal pages are. The "overrides" section will let these advanced users research the variables that control the page layout and then redefine as much or as little as they want, without having to recreate their whole own style. In time, though, the user may get really good at the system and simply recreate everything.
|
||||
p?>
|
||||
|
||||
<?h1 Variables and Properties h1?>
|
||||
<?p
|
||||
It took us awhile to settle on some terminology that we were happy with, but what we finally decided on was variables and properties. A <B>variable</B> is something that a style defines (and that a user can override) and is either:
|
||||
<OL>
|
||||
<LI>A <B>page setup option</B>, like how many items to show, how to sort something, or the format of dates and times.
|
||||
<LI>Some <B>HTML</B> that the page contruction engine will use to make the page, with properties that it will fill in.
|
||||
</OL>
|
||||
A <B>property</B> is something that the server will generate (usually based on other variables) and prefill into your variables. Properties are mixed in variables like <NOBR><tt><B>%%property%%</B></tt></NOBR> and will be replaced by what they represent before being sent to the users' web-browsers.
|
||||
p?>
|
||||
|
||||
<?h1 So, what next? h1?>
|
||||
<?p To customize your journal beyond just changing colors, you'll need to make a new
|
||||
style. Here are some links:
|
||||
<UL>
|
||||
<LI><A HREF="/styles/create.bml">Create Style</A>
|
||||
<LI><A HREF="/styles/edit.bml">Edit Style</A> -- (for changing it later)
|
||||
</UL>
|
||||
p?>
|
||||
|
||||
<?h1 Questions? h1?>
|
||||
<?p
|
||||
If you have any questions or comments, ask the always-eager <a href="/support/submit.bml">support team</a>.
|
||||
p?>
|
||||
|
||||
<?hr?>
|
||||
Back to <A HREF="/developer/">Developer Area</A>.
|
||||
|
||||
<=body
|
||||
page?>
|
||||
173
ljcom/htdocs/developer/time-problem.txt
Normal file
173
ljcom/htdocs/developer/time-problem.txt
Normal file
@@ -0,0 +1,173 @@
|
||||
===============================
|
||||
LIVEJOURNAL'S TIME PROBLEM
|
||||
===============================
|
||||
|
||||
Brad Fitzpatrick
|
||||
brad@livejournal.com
|
||||
August 10, 2000
|
||||
|
||||
+------+
|
||||
| Goal |
|
||||
+------+
|
||||
|
||||
LiveJournal.com needs to handle time better, in particular to be aware of time
|
||||
zones. There are too many problems that arise by neglecting them. If I knew of
|
||||
an easy solution, I'd have implemented it already. This document is a plea for
|
||||
help. All suggestions (however seemingly stupid) are likely to help, if only to
|
||||
spark ideas for others.
|
||||
|
||||
Confession: I know very little about the details of time zones, daylight
|
||||
saving's time, etc... but I've read tons on the topic, enough to know there's
|
||||
a lot to know. In other words, the solution is likely complex as well.
|
||||
|
||||
+---------------+
|
||||
| Current Setup |
|
||||
+---------------+
|
||||
|
||||
LiveJournal's servers, and the primary developers are all on the west coast of
|
||||
the United States, in the PST/PDT (Pacific Standard/Daylight Time) timezone,
|
||||
which is -0800 GMT (and sometimes -0700 GMT, in daylight savings time, I
|
||||
believe). Here is how LiveJournal currently stores the dates/time for different
|
||||
events:
|
||||
|
||||
* journal creation date, update date --- PST/PDT local time.
|
||||
|
||||
* comment post dates --- PST/PDT local time.
|
||||
|
||||
* journal entries:
|
||||
|
||||
1) the "eventtime" is stored, whatever time you say it is wherever you're
|
||||
at. you specify the year, month, day, hour and minute. no time zone
|
||||
is recorded.
|
||||
|
||||
2) the "logtime" ... the time LiveJournal logs it to the database, in
|
||||
PST/PDT local time.
|
||||
|
||||
+-------------------------+
|
||||
| Description of problems |
|
||||
+-------------------------+
|
||||
|
||||
Outlined below are the problems that LiveJournal currently faces:
|
||||
|
||||
1. Friends view ordering
|
||||
2. Incorrect user clocks
|
||||
3. Offline journaling/queueing
|
||||
4. Comments post times
|
||||
|
||||
1. Friends view ordering
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The friends view is currently sorted according to the "logtime". In other
|
||||
words, regardless of what time you said the journal event happened, the server
|
||||
will sort them in the reverse order they were received. This has the advantages
|
||||
that if you have friends scattered all over different timezones the journal
|
||||
entries will still show in the order they actually happened.
|
||||
|
||||
The problem occurs though near midnight ... you can have friends in one
|
||||
timezone posting entries on one day interleaved with friends in another
|
||||
timezone posting commments on the previous day. The resultant friends view
|
||||
looks really messed up, going back and forth between days.
|
||||
|
||||
This leads me to topic 2 ...
|
||||
|
||||
2. Incorrect user clocks
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The friends view shows the time the user reported (the "eventtime"), even
|
||||
though it's sorted by the "logtime". So if a friend in your same timezone
|
||||
is posting comments near the same time as you, it's possible their post
|
||||
that happened after you has an earlier displayed time, because their computer
|
||||
clock is messed up.
|
||||
|
||||
The worst is when their computer clock is months/years behind/ahead (very very
|
||||
common because Windows users like to double-click their clock and use it as
|
||||
a calendar ... then hit "OK" instead of "Cancel"). Then, the users complain
|
||||
that "my journal entries are showing up on my friends page, but not on my
|
||||
recent events view". This is because the recent events view (and the day
|
||||
view, and the calendar) are all sorted by the "eventtime", the time the user
|
||||
said the event happened.
|
||||
|
||||
3. Offline journaling/queueing
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Many people have been asking for and patiently awaiting the "offline journaling"
|
||||
feature ... being able to enter journal entries on your no-Internet laptop or
|
||||
PDA and HotSync (or whatever) them later to LiveJournal's servers.
|
||||
|
||||
Now, how should the friends view be formatted? Say the user submits 10 journal
|
||||
entries ranging over a two week vacation. Should all 10 show up at once on
|
||||
all of that user's friends' friends views? Because under the current scheme,
|
||||
the "logtime" of all those entries would be seconds apart, and that's what the
|
||||
friends view uses to sort.
|
||||
|
||||
Should offline/queued entries not show up on friends lists? Should posts
|
||||
with eventtimes more than 'n' days in the past not show up on friends lists?
|
||||
|
||||
Both those solutions suck, because they're both ugly hacks that avoid fixing the
|
||||
real problem -- adding timezone support to livejournal.
|
||||
|
||||
4. Comment times
|
||||
~~~~~~~~~~~~~~~~
|
||||
Blah. You know the problem. Keep reading ... time for solutions:
|
||||
|
||||
+----------------+
|
||||
| Ideal Solution |
|
||||
+----------------+
|
||||
|
||||
Ideally what would happen is that LiveJournal would store all posts with a
|
||||
GMT time (that doesn't have daylight savings time) and the friends views
|
||||
would sort by the GMT time of the eventtime ... so the user that went on
|
||||
vacation and is dumping 10 entries into the system has them all intermixed
|
||||
with her friends' old entries. Then, the friends view should display both
|
||||
the remote browsing users's time and the time it was when the user posted the
|
||||
item.
|
||||
|
||||
So the problem turns into -- how do we convert the "eventtime" the user
|
||||
submits into a GMT time? But ... let's assume the user's computer clock
|
||||
is wrong, or we don't want to use it because it's not perfectly synchronized.
|
||||
So then we need to pass along to LiveJournal a timezone field.
|
||||
|
||||
So the problem is:
|
||||
|
||||
--- I need a list of all timezones. What format are these in?
|
||||
When does daylight savings time occur? Each country and states
|
||||
within those countries have different rules.
|
||||
|
||||
--- given a timezone code, how do I convert it to GMT? Are there
|
||||
good packages already in existence (preferrably in Perl) to
|
||||
do these conversions? I've looked around a lot, but haven't
|
||||
found anything perfect.
|
||||
|
||||
--- how do we deal with legacy clients? it'll be some time
|
||||
before all clients start sending timezone info.
|
||||
|
||||
Once the database is storing the eventtime in GMT and the timezone
|
||||
code as well, then the style system needs to be updated to allow style
|
||||
authors to show times in both the poster's time, and the journal owner
|
||||
or remote user's time.
|
||||
|
||||
But perhaps there's a better solution? I really don't know. I hate the
|
||||
dependency on users' system clocks, and I hate the misordering of friends
|
||||
items.
|
||||
|
||||
+----------------------+
|
||||
| Good example problem |
|
||||
+----------------------+
|
||||
|
||||
I have a journal I wrote from 1990 that I typed up, but I don't want
|
||||
to post it, because it'll show up on all my friends' friends views. I'd
|
||||
prefer it just went to my calendar, and I can make a single post to tell
|
||||
my friends to go read it (and link to the day it starts).
|
||||
|
||||
Sure, I could add a meta-data flag or something new on the protocol that
|
||||
says, "don't add this to my friends view" but then people will start using
|
||||
that for other purposes, and start asking for stupid stuff like, "can I have
|
||||
it not show up on certain people's friends view?", not understanding the
|
||||
point of it. It's just not clean. :/
|
||||
|
||||
|
||||
_____________________________________________________________________________
|
||||
Feedback requested:
|
||||
brad@livejournal.com
|
||||
|
||||
|
||||
79
ljcom/htdocs/developer/varinfo.bml
Normal file
79
ljcom/htdocs/developer/varinfo.bml
Normal file
@@ -0,0 +1,79 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?page
|
||||
title=><?_code $v = LJ::ehtml(BML::get_query_string()); return $v; _code?>
|
||||
body<=
|
||||
<?h1 Variable Details h1?>
|
||||
<?p
|
||||
The following are details on the <?_code return $v; _code?> variable. For more information on modifying this variable, see the information about the <A HREF="styles.bml">style system</A>.
|
||||
p?>
|
||||
|
||||
<?_code
|
||||
|
||||
my @vars;
|
||||
LJ::load_objects_from_file("vars.dat", \@vars);
|
||||
my $ret = "";
|
||||
|
||||
foreach my $v (grep { $_->{'name'} eq $v } @vars)
|
||||
{
|
||||
LJ::xlinkify(\$v->{'props'}->{'des'});
|
||||
|
||||
$ret .= "<P><TABLE WIDTH=100% BGCOLOR=#C0C0C0><TR><TD><FONT FACE=\"Arial,Helvetica\" SIZE=+1><B>$v->{'name'}</B></FONT></TD></TR></TABLE>\n\n";
|
||||
$ret .= "<TABLE CELLSPACING=2>\n";
|
||||
$ret .= "<TR VALIGN=TOP><TD ALIGN=RIGHT NOWRAP><I>view types:</I></TD><TD>";
|
||||
foreach (split (/\s*\,\s*/, $v->{'props'}->{'scope'}))
|
||||
{
|
||||
$ret .= "<A HREF=\"/developer/views.bml#$_\">$_</A>, ";
|
||||
}
|
||||
chop $ret; chop $ret;
|
||||
$ret .= "</TD></TR>\n";
|
||||
$ret .= "<TR VALIGN=TOP><TD ALIGN=RIGHT><I>description:</I></TD><TD>$v->{'props'}->{'des'}</TD></TR>\n";
|
||||
|
||||
# overrideable?
|
||||
$ret .= "<TR VALIGN=TOP><TD ALIGN=RIGHT NOWRAP><I>can override:</I></TD><TD>";
|
||||
if ($v->{'props'}->{'override'} eq "yes") {
|
||||
$ret .= "<B>Yes</B>; users of this style may override this";
|
||||
} elsif ($v->{'props'}->{'override'} eq "only") {
|
||||
$ret .= "<B>Only</B>; Only users of this style may override this, it cannot be defined in a style.";
|
||||
} else {
|
||||
$ret .= "<B>No</B>; users of the style cannot override this. It may only be defined in the style.";
|
||||
}
|
||||
$ret .= "</TD></TR>\n";
|
||||
|
||||
if (defined $v->{'props'}->{'type'})
|
||||
{
|
||||
$ret .= "<TR VALIGN=TOP><TD ALIGN=RIGHT NOWRAP><I>variable type:</I></TD><TD>$v->{'props'}->{'type'}</TD></TR>\n";
|
||||
}
|
||||
if (defined $v->{'props'}->{'default'})
|
||||
{
|
||||
$ret .= "<TR VALIGN=TOP><TD ALIGN=RIGHT NOWRAP><I>default value:</I></TD><TD>$v->{'props'}->{'default'}</TD></TR>\n";
|
||||
}
|
||||
if (defined $v->{'props'}->{'props'})
|
||||
{
|
||||
$ret .= "<TR VALIGN=TOP><TD ALIGN=RIGHT><I>properties:</I></TD><TD>\n";
|
||||
$ret .= "<TABLE CELLSPACING=1 BORDER=1 CELLPADDING=2>\n";
|
||||
foreach my $p (@{$v->{'props'}->{'props'}})
|
||||
{
|
||||
LJ::xlinkify(\$p->{'props'}->{'des'});
|
||||
$ret .= "<TR VALIGN=TOP><TD ALIGN=RIGHT><B>$p->{'name'}</B></TD>\n";
|
||||
$ret .= "<TD>$p->{'props'}->{'des'} ";
|
||||
if ($p->{'props'}->{'min'} > 0)
|
||||
{
|
||||
$ret .= "<FONT COLOR=#FF0000>[required]</FONT>";
|
||||
}
|
||||
$ret .= "</TD></TR>\n";
|
||||
}
|
||||
$ret .= "</TABLE></TD></TR>\n";
|
||||
}
|
||||
|
||||
$ret .= "</TABLE>\n";
|
||||
}
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<?hr?>
|
||||
Back to <A HREF="/developer/">Developer Area</A>.
|
||||
|
||||
<=body
|
||||
page?>
|
||||
34
ljcom/htdocs/developer/varlist.bml
Normal file
34
ljcom/htdocs/developer/varlist.bml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?page
|
||||
title=>Variable List
|
||||
body<=
|
||||
<?h1 Introduction h1?>
|
||||
<?p
|
||||
The following information is a list of the variables that users may define to control the look of their journal pages. Click a variable name to see more information about it, including its properties, if any. None of this will probably make sense unless you read the <a href="styles.bml">information about the style system</a>, which includes information on how to define variables and values.
|
||||
p?>
|
||||
|
||||
<?h1 Variables h1?>
|
||||
<?p
|
||||
Click a variable name for more information about how and where to use it.
|
||||
<UL>
|
||||
<?_code
|
||||
|
||||
my @vars;
|
||||
LJ::load_objects_from_file("vars.dat", \@vars);
|
||||
my $ret = "";
|
||||
|
||||
foreach my $v (sort { $a->{'name'} cmp $b->{'name'} } @vars) {
|
||||
$ret .= "<li><a href=\"varinfo.bml?$v->{'name'}\"><b>$v->{'name'}</b></a></li>\n";
|
||||
}
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
</UL>
|
||||
p?>
|
||||
|
||||
<?hr?>
|
||||
Back to <A HREF="/developer/">Developer Area</A>.
|
||||
|
||||
<=body
|
||||
page?>
|
||||
40
ljcom/htdocs/developer/versions.bml
Executable file
40
ljcom/htdocs/developer/versions.bml
Executable file
@@ -0,0 +1,40 @@
|
||||
<?page
|
||||
title=>LiveJournal Protocol Versions
|
||||
body<=
|
||||
<?h1 Protocol Versions h1?>
|
||||
<?p
|
||||
The LiveJournal protocol (so far) has been more or less static; while new
|
||||
modes have been added, the basic operation has not changed much. However, recent
|
||||
introduction of Unicode support in LiveJournal necessitated changes in the way
|
||||
text is encoded in protocol requests and responses. In order to allow new clients
|
||||
to take advantage of Unicode support and at the same time avoid breaking existing
|
||||
clients, a versioning scheme has been put into the protocol. The client sends
|
||||
the number of the highest protocol version it supports in every request, inside
|
||||
a <b><tt>ver</tt></b> attribute; version 0 is implicit if the client does not
|
||||
send the <b><tt>ver</tt></b> attribute. Currently there are two versions of the protocol,
|
||||
and the Unicode-enabled server code supports both of them.
|
||||
p?>
|
||||
|
||||
<ul>
|
||||
<li><b>Version 0</b><br/>
|
||||
If a client does not send a <b><tt>ver</tt></b> key on a request, it assumed to support
|
||||
protocol Version 0. In protocol Version 0, textual information transmitted from or to the
|
||||
server is always assumed to be a stream of 8-bit bytes, not necessarily ASCII, but without
|
||||
any guarantee that the non-ASCII bytes are presented in any particular encoding.
|
||||
<li><b>Version 1</b><br/>
|
||||
Version 1 differs from Version 0 only by imposing additional requirements on the text
|
||||
transmitted through requests and responses; there aren't any changes in protocol modes.
|
||||
The additional requirements are that in a Version 1 request, the client <b>must</b> transmit
|
||||
all textual information as a stream of Unicode data encoded in UTF-8; the server <b>must</b>
|
||||
respond to Version 1 requests with Version 1 responses; in such Version 1 responses, the server
|
||||
<b>must</b> also transmit all textual information encoded in UTF-8; and the client must expect
|
||||
that and handle such responses correctly.
|
||||
|
||||
In other words, all information transmitted via protocol when Version 1 is used is always encoded
|
||||
in UTF-8. UTF-8 is a representation of Unicode in a bytestream format compatible with ASCII. See
|
||||
<a href="http://www.unicode.org">the Unicode Consortium website</a> for more information on Unicode
|
||||
and UTF-8.</li>
|
||||
</ul>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
51
ljcom/htdocs/developer/views.bml
Normal file
51
ljcom/htdocs/developer/views.bml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?_info
|
||||
nocache=>1
|
||||
_info?><?page
|
||||
title=>View Types
|
||||
body<=
|
||||
<?h1 Introduction h1?>
|
||||
<?p
|
||||
A <B>view</B> is just our terminology for a page type, or a mode. There are a lot of different ways to look at one's journal --- the default way is the "lastn" view, where it shows the last 'n' most recent events, in reverse order. However, there's also a calendar view, a day view when you click a day on the calendar, and more coming soon (a search page, and a search results page). Each and every view type is customizable through the <A HREF="styles.bml">style system</A>, which you should read up on if you haven't already.
|
||||
p?>
|
||||
<?p
|
||||
Below is a list of all the view types, descriptions of them, and the <A HREF="varlist.bml">variables</A> that affect them.
|
||||
p?>
|
||||
|
||||
<?_code
|
||||
|
||||
my @views;
|
||||
my @vars;
|
||||
|
||||
LJ::load_objects_from_file("views.dat", \@views);
|
||||
LJ::load_objects_from_file("vars.dat", \@vars);
|
||||
|
||||
my $ret = "";
|
||||
|
||||
foreach my $vi (@views)
|
||||
{
|
||||
$ret .= "<P><A NAME=\"$vi->{'name'}\"><TABLE WIDTH=100% BGCOLOR=#C0C0C0><TR><TD><FONT FACE=\"Arial,Helvetica\" SIZE=+1><B>$vi->{'name'}: <I>$vi->{'props'}->{'name'}</B></I></FONT></TD></TR></TABLE>\n\n";
|
||||
LJ::xlinkify(\$vi->{'props'}->{'des'});
|
||||
$ret .= $vi->{'props'}->{'des'};
|
||||
|
||||
$ret .= " <A HREF=\"$vi->{'props'}->{'url'}\">Example page</A>.\n"
|
||||
if (defined $vi->{props}->{url});
|
||||
|
||||
$ret .= "<P><B>Variables affecting this view:</B><UL>\n";
|
||||
foreach my $v (sort { $a->{'name'} cmp $b->{'name'} } @vars)
|
||||
{
|
||||
next unless ($v->{'props'}->{'scope'} =~ /\b$vi->{'name'}\b/);
|
||||
$ret .= "<LI><A HREF=\"varinfo.bml?$v->{'name'}\"><B>$v->{'name'}</B></A>\n";
|
||||
}
|
||||
|
||||
$ret .= "</UL>\n";
|
||||
|
||||
}
|
||||
return $ret;
|
||||
|
||||
_code?>
|
||||
|
||||
<?hr?>
|
||||
Back to <A HREF="/developer/">Developer Area</A>.
|
||||
|
||||
<=body
|
||||
page?>
|
||||
42
ljcom/htdocs/developer/winamp.txt
Executable file
42
ljcom/htdocs/developer/winamp.txt
Executable file
@@ -0,0 +1,42 @@
|
||||
// gets playing music from WinAmp, and returns
|
||||
BOOL CPostOptionsDlg::GetPlayingMusic(CString &song)
|
||||
{
|
||||
// is WinAMP open?
|
||||
HWND hwndWinamp = ::FindWindow("Winamp v1.x",NULL);
|
||||
if (hwndWinamp == NULL) return FALSE;
|
||||
|
||||
// in WinAMP playing?
|
||||
int ret = ::SendMessage(hwndWinamp, WM_USER, 0, 104);
|
||||
if (ret != 1) return FALSE;
|
||||
|
||||
// it is, let's find out what the title bar is:
|
||||
char this_title[2048],*p;
|
||||
::GetWindowText(hwndWinamp,this_title,sizeof(this_title));
|
||||
p = this_title+strlen(this_title)-8;
|
||||
while (p >= this_title)
|
||||
{
|
||||
if (!strnicmp(p,"- Winamp",8)) break;
|
||||
p--;
|
||||
}
|
||||
if (p >= this_title) p--;
|
||||
while (p >= this_title && *p == ' ') p--;
|
||||
*++p=0;
|
||||
|
||||
char *iter, *start;
|
||||
start = this_title;
|
||||
iter = start;
|
||||
|
||||
// remove leading s/^\d+\. //;
|
||||
int numhead = 0;
|
||||
while (*iter) {
|
||||
if (isdigit(*iter)) { iter++; numhead++; }
|
||||
else break;
|
||||
}
|
||||
if (numhead && *iter=='.' && *(iter+1)==' ') {
|
||||
start = iter+2;
|
||||
}
|
||||
|
||||
song = start;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user