#!/usr/bin/perl
################################################################################
# xmlrpc-voodoo
# O'Wiki interface using the VoodooPad XML-RPC API
#
# Copyright 2004 Will Norris.  All Rights Reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details, published at 
# http://www.gnu.org/copyleft/gpl.html
################################################################################

use strict;
use Data::Dumper qw(Dumper);

use lib ( '.' );
use lib ( '../lib' );
use TWiki;

our $twiki_web = 'Sandbox';

$SOAP::Constants::DO_NOT_USE_XML_PARSER = 1;

use XMLRPC::Transport::HTTP;
my $server = XMLRPC::Transport::HTTP::CGI->dispatch_to('vpwiki')->handle;
exit 0;

###########################################################################
### wiki methods
###########################################################################

package vpwiki;

# myboolean = vpwiki.authenticate(loginStruct) 
# This method just takes a login struct and authenticates the user. It returns true if the user authenticates, false otherwise.
sub authenticate
{
    my ($pkg,$login) = @_;

    return SOAP::Data->type(boolean => 1);
}


# myarray = vpwiki.getPageKeys(loginStruct) 
# This method returns all the keys that the server has on its end. If there are none, then it will return an empty array.
sub getPageKeys
{
    my ($pkg,$login) = @_;

    die "permissions" unless authenticate( $login );

    return [ TWiki::Func::getTopicList( $twiki_web ) ];
}


# mypageStruct = getPage(loginStruct, key) 
# This method returns a pageStruct for the given key.
sub getPage
{
    my ($pkg,$login,$key) = @_;

    die "permissions" unless authenticate( $login );

    my ($meta, $pagetext) = TWiki::Func::readTopic($twiki_web, $key);	# TWiki::Func::readTopic() is marked as deprecated, but i need the metadata

    my $h = {
	key => $key,
	page => SOAP::Data->type(base64 => $pagetext),
    };

    while ( my ($metakey,$metavalue) = each( %{$meta} ) )
    {
	my $prefix = (lc $metakey) . '.';
	# not sure what (if anything) array items other than the first one mean, or if it even happens?
	while ( my ($key,$value) = each( %{$metavalue->[0]} ) )
	{
	    $h->{$prefix . $key} = $value;
	}
    }

    $h->{version} = $h->{'topicinfo.version'};
    $h->{title} = $h->{'topicinfo.???'} || $h->{key};	# how is form's 'title' named/stored?

    my ($sec, $min, $hr, $dd, $mm, $yy, $wd, $yd, $isdst) = localtime( $h->{'topicinfo.date'} );
    ++$mm, $yy += 1900; 
    my @dow_name = qw(Sun Mon Tue Wed Thu Fri Sat);
    $h->{lastModified} = 
	SOAP::Data->type( dateTime => sprintf( '%s %s %02d %02d:%02d:%02d %04d', $dow_name[$wd],$mm,$dd,$hr,$min,$sec,$yy ) );

    # maybe 'data' is the rendered version?

    return $h;
}


# myboolean = setPage(loginStruct, pageStruct) 
# This method takes a pageStruct, and places it in the store. It returns a boolean on success, otherwise it'll throw an exception if something goes wrong. 
sub setPage
{
    my ($pkg,$login,$page) = @_;

    die "permissions" unless authenticate( $login );

    my $pagename = $page->{key} or die "where should i put this page?";
    my $text = $page->{page} or die "no page?"; 

    # !!! FIXME !!!
    $text =~ s/&#x(d);//eg;	# this isn't right (i *guess* the ^M's shouldn't be stripped from the topic files--why are they DOS format anyway?)
    # i wonder what else should be done here... ?
    $text =~ s/&#x([0-9a-fA-F]);/chr('0x$1')/eg;

    TWiki::initialize();
    TWiki::Func::setTopicEditLock( $twiki_web, $pagename, 1 );
    TWiki::Func::saveTopicText( $twiki_web, $pagename, $text, 1, 1 );
    TWiki::Func::setTopicEditLock( $twiki_web, $pagename, 0 );

    return SOAP::Data->type( boolean => 1 );
}

