--- /dev/null
+VJournal is a simple blog engine with extensive commenting feature.
+It's commenting style more or less mimics LiveJournal style blog sites,
+but it is designed to work on small sites with few blogs (or even just
+one)
+
+It doesn't use any relational database, only Perl builtin dbmopen
+function (for information which shouldn't be directly shown to the
+users).
+
+Blog (with discission) is kept in the static HTML files which are
+updated each time comment is posted. VJournal tries to limit number of
+files to be updated on each comment.
+
+It updates just
+
+1. Main file of the post where comment is stored.
+2. Calendar files for month and
+3. day when post was posted, to update comment count
+4. Main page of the blog, if post is recent enough to be displayed.
+
+VJournal doesn't keep user authentication information. It relies on
+OpenID to authenticate all users, including blog owner.
+
+However, VJournal includes its own OpenID provider to autenticate blog
+owner. Blog owner is assumed to be a user, whose OpenID url is same as
+top-level URL of the blog, unless other OpenID url is specified as
+-owner option in the config.
+
+
+File structure of the blog:
+
+Top level directory have index.html page which contain several recent
+posts, and set of directories with older posts by year and month:
+
+In the top level directory there is .vjournalrc file which is just
+serialized perl hash for configuration options.
+
+This hash should contain at least following options:
+
+-owner - openid URL for blog owner
+-statedir - directory outside of public tree serverd by webserver, which
+contains following files:
+ users.db - cached information about openid users
+ session.db - information about user sessions
+ owner.pwd - hash of owner password.
+Optionally, there also can be file openid.lst, which contain infomation
+about known openid sites. This information should be in the form
+site name:url_template.
+
+There probably should be format specifier %s in the url_template, which would be
+substituted by user name. But some sites don't need this. For instance,
+google uses same url for all users.
+
+Theoretically it is possible for several blogs to share same user cache
+and session cache (LiveJournal does so for millions of blogs), so
+owner.pwd can contain more than one record.
+
+This file can be created using apache htpasswd utility (or simular)
+using blog URI (without protocol prefix) as user names.
+
+It is recommended to deny HTTP access to .vjournalrc, using web server
+access control, although filesystem permissions should allow this file
+be read by CGI process.
+
+Inside publically accessable HTML tree should be subdirectories for the
+templates and user avatar pictures. By default these are subdirectories
+templats and avatars in the toplevel directory of blog.
+It can be redefined using options -templatedir and -avatardir in the
+config file.
+
+If several blogs share user cache, they should share avatar directory
+too.
+
+Initialization:
+
+1. Install perl scripts and modules (once per all users)
+2. Create top level directory for blog, and put .vjournalrc there.
+Make directory writable to web server.
+3. Create empty avatar directory and make it writable to the webserver
+4. Create template directory and populate with templates.
+5. Create state directory and make it writable to webserver.
+6. Go to the /cgi-bin/post/urltop/, where urltop is top-level directory
+of your blog (may be it is just / if your entire site dedicated for
+blog). It is important to type into this url such path_info so webserver
+would put path of the directory with you .vjournalrc into
+PATH_TRANSLATED. You would be able to set owner password and upload your
+avatar.
+
+Once you set up owner password, access to the post script would be
+resticted for blog owner.
+
croak("Invalid call to ".$pkg."->create");
}
my %params = @_;
- croack("User name is required by ".$pkg."->creae") unless $params{-user};
+ croack("User name is required by ".$pkg."->create") unless $params{-user};
$params{-cgi}=CGI->new() if(!$params{-cgi});
load_config($params{-cgi});
my $user=$params{-user};
sub isowner {
my $self=shift;
- return $self->{-name} eq $config{-owner};
+ return $self->{-name} eq $config->{-owner};
}
=head2 _update_user
=cut
sub load_config {
- my $path=$_[0]->path_translated();
- my @dirs = (File::Spec->splitdir($path));
+ my $cgi = $_[0];
+ my $path=$cgi->path_translated();
+ my @dirs = File::Spec->splitdir($path);
+ my @uri = File::Spec->splitdir($cgi->path_info);
my $found =0;
while (@dirs) {
my $d=File::Spec->catdir(@dirs,CONFIG_NAME);
my $config = <F>;
close F;
eval "%config = {$d}";
+ $config{-topdir}=File::Spec->catdir(@dirs);
+ $config{-topurl}=$cgi->url(-base=>1).File::Spec->catdir(@uri);
die $@ if ($@);
$found = 1;
}
pop @dirs;
+ pop @uri;
}
die ("Cannot find config file inside $path") unless $found;
- my @reqkeys=qw(-owner -statedir -templatedir);
+ my @reqkeys=qw(-statedir);
foreach my $key (@reqkeys) {
die "Required key $key missing from config"
unless exists $config{$key};
$config{-userbase}||=$config{-statedir}."/user.db";
$config{-sessiontime}||=86400*30;
$config{-gracetime}||=86400;
+ $config{-templatedir}||=$config{-topdir}."/templates"
+ $config{-avatardir}||=$config{-topdir}."/avatars";
+ if (!$config{-owner}) {
+ my $uri=substr($config{-topurl},index($config{-topurl},"://")+2;
+ $uri =~ s/:\d+(\/.*)?$//;
+ $config{-owner} = $uri;
+ }
}
=head2 AUTOLOAD