#!/usr/bin/perl -wT
#
# TWiki Collaboration Platform, http://TWiki.org/
#
# Copyright (C) 1999-2003 Peter Thoeny, peter@thoeny.com
#
# Based on parts of Ward Cunninghams original Wiki and JosWiki.
# Copyright (C) 1998 Markus Peter - SPiN GmbH (warpi@spin.de)
# Some changes by Dave Harris (drh@bhresearch.co.uk) incorporated
#
# For licensing info read license.txt file in the TWiki root.
# 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

# A thought on design.  Information is passed to the preview script via various form variables.
# Much of the meta data could have been passed by an extra hidden field, instead individual items such
# as parent information is passed by individual form variables, hopefully giving a clear "API".

# Set library paths in @INC, at compile time
BEGIN { unshift @INC, '.'; require 'setlib.cfg'; }

use CGI;
use CGI::Carp qw(fatalsToBrowser);
use TWiki;

use strict;

&main();

# Uncomment the body of either routine to enable debugging
sub writeDebug
{
    my( $text ) = @_;
    #TWiki::writeDebug( $text );
}

sub writeDebugTimes
{
    my( $text ) = @_;
    #TWiki::writeDebugTimes( $text );
}

sub main
{
    my $query = new CGI;

    my $thePathInfo = $query->path_info(); 
    my $theRemoteUser = $query->remote_user();
    my $theTopic = $query->param( 'topic' ) || "";
    my $theUrl = $query->url;

    my( $topic, $webName, $dummy, $userName ) = 
	&TWiki::initialize( $thePathInfo, $theRemoteUser, $theTopic, $theUrl, $query );
    $dummy = "";  # to suppress warning

    my $saveCmd = $query->param( 'cmd' ) || "";
    my $breakLock = $query->param( 'breaklock' ) || "";
    my $onlyWikiName = $query->param( 'onlywikiname' ) || "";
    my $tmpl = "";
    my $text = "";
    my $meta = "";
    my $extra = "";
    my $wikiUserName = &TWiki::userToWikiName( $userName );

    if( ! &TWiki::Store::webExists( $webName ) ) {
        my $url = &TWiki::getOopsUrl( $webName, $topic, "oopsnoweb" );
        TWiki::redirect( $query, $url );
        return;
    }

    my( $mirrorSiteName, $mirrorViewURL ) = &TWiki::readOnlyMirrorWeb( $webName );
    if( $mirrorSiteName ) {
        my $url = &TWiki::getOopsUrl( $webName, $topic, "oopsmirror", $mirrorSiteName, $mirrorViewURL );
        print $query->redirect( $url );
        return;
    }

    # prevent non-Wiki names?
    if( ( $onlyWikiName )
      && ( ! &TWiki::Store::topicExists( $webName, $topic ) )
      && ( ! ( &TWiki::isWikiName( $topic ) || &TWiki::isAbbrev( $topic ) ) ) ) {
        # do not allow non-wikinames, redirect to view topic
        TWiki::redirect( $query, &TWiki::getViewUrl( $webName, $topic ) );
        return;
    }

    # Read topic 
    if( &TWiki::Store::topicExists( $webName, $topic ) ) {
        ( $meta, $text ) = &TWiki::Store::readTopic( $webName, $topic );
    }

    # Check access controls
    if( ! &TWiki::Access::checkAccessPermission( "change", $wikiUserName, $text, $topic, $webName ) ) {
        # user has not permission to change the topic
        my $url = &TWiki::getOopsUrl( $webName, $topic, "oopsaccesschange" );
        TWiki::redirect( $query, $url );
        return;
    }

    # Special save command
    if( ( $saveCmd ) &&
        ( ! &TWiki::Access::userIsInGroup( $wikiUserName, $TWiki::superAdminGroup ) ) ) {
        # user has no permission to execute undocumented cmd=... parameter
        my $url = &TWiki::getOopsUrl( $webName, $topic, "oopsaccessgroup", "$TWiki::mainWebname.$TWiki::superAdminGroup" );
        TWiki::redirect( $query, $url );
        return;
    }

    # Check for locks
    my( $lockUser, $lockTime ) = &TWiki::Store::topicIsLockedBy( $webName, $topic );
    if( ( ! $breakLock ) && ( $lockUser ) ) {
        # warn user that other person is editing this topic
        $lockUser = &TWiki::userToWikiName( $lockUser );
        use integer;
        $lockTime = ( $lockTime / 60 ) + 1; # convert to minutes
        my $editLock = $TWiki::editLockTime / 60;
        # PTh 20 Jun 2000: changed to getOopsUrl
        my $url = &TWiki::getOopsUrl( $webName, $topic, "oopslocked",
            $lockUser, $editLock, $lockTime );
        TWiki::redirect( $query, $url );
        return;
    }
    &TWiki::Store::lockTopic( $topic );

    my $formTemplate  = $query->param( "formtemplate" ) || "";
    my $templateTopic = $query->param( "templatetopic" ) || "";
    my $templateWeb = $webName;

    # Get edit template, standard or a different skin
    my $skin = $query->param( "skin" ) || &TWiki::Prefs::getPreferencesValue( "SKIN" );
    $tmpl = &TWiki::Store::readTemplate( "edit", $skin );
    if( ! &TWiki::Store::topicExists( $webName, $topic ) ) {
        if( $templateTopic ) {
            if( $templateTopic =~ /^(.+)\.(.+)$/ ) {
                # is "Webname.SomeTopic"
                $templateWeb   = $1;
                $templateTopic = $2;
            }
            ( $meta, $text ) = &TWiki::Store::readTopic( $templateWeb, $templateTopic );
        }
        if( ! $text ) {
            ( $meta, $text ) = &TWiki::Store::readTemplateTopic( "WebTopicEditTemplate" );
        }
        $extra = "(not exist)";

        # If present, instantiate form
        if( ! $formTemplate ) {
            my %args = $meta->findOne( "FORM" );
            $formTemplate = $args{"name"};
        }

        my $foo = &TWiki::getGmDate();
        $text =~ s/%DATE%/$foo/go;
        $text =~ s/%WIKIUSERNAME%/$wikiUserName/go;
        $text =~ s/%URLPARAM{(.*?)}%/TWiki::handleUrlParam($1)/geo;  # expand URL parameters
        $text =~ s/%NOP{.*?}%//gos;  # Remove filler: Use it to remove access control at time of
        $text =~ s/%NOP%//go;        # topic instantiation or to prevent search from hitting a template
    }
    
    # parent setting
    my $theParent = $query->param( 'topicparent' ) || "";
    if( $theParent ) {
        if( $theParent =~ /^([^.]+)\.([^.]+)$/ ) {
            my $parentWeb = $1;
            if( $1 eq $webName ) {
               $theParent = $2;
            }
        }
        $meta->put( "TOPICPARENT", ( "name" => $theParent ) );
    }
    $tmpl =~ s/%TOPICPARENT%/$theParent/;
    
    # Processing of formtemplate - comes directly from query parameter formtemplate , 
    # or indirectly from webtopictemplate parameter.
    my $oldargsr;
    if( $formTemplate ) {
       my @args = ( name => $formTemplate );
       $meta->remove( "FORM" );
       if( $formTemplate ne "none" ) {
          $meta->put( "FORM", @args );
       } else {
          $meta->remove( "FORM" );
       }
       $tmpl =~ s/%FORMTEMPLATE%/$formTemplate/go;
       my $ptext = $query->param( 'text' );
       if( defined $ptext ) {
           $text = $ptext;
           $text = &TWiki::decodeSpecialChars( $text );
       }
    }
    
    if( $saveCmd eq "repRev" ) {
       $text = TWiki::Store::readTopicRaw( $webName, $topic );
    }

    $text =~ s/&/&amp\;/go;
    $text =~ s/</&lt\;/go;
    $text =~ s/>/&gt\;/go;
    $text =~ s/\t/   /go;

    #AS added hook for plugins that want to do heavy stuff
    TWiki::Plugins::beforeEditHandler( $text, $topic, $webName ) unless( $saveCmd eq "repRev" );
    #/AS

    if( $TWiki::doLogTopicEdit ) {
        # write log entry
        &TWiki::Store::writeLog( "edit", "$webName.$topic", $extra );
    }

    if( $saveCmd ) {
        $tmpl =~ s/\(edit\)/\(edit cmd=$saveCmd\)/go;
    }
    $tmpl =~ s/%CMD%/$saveCmd/go;
    $tmpl = &TWiki::handleCommonTags( $tmpl, $topic );
    if( $saveCmd ne "repRev" ) {
        $tmpl = &TWiki::handleMetaTags( $webName, $topic, $tmpl, $meta );
    } else {
        $tmpl =~ s/%META{[^}]*}%//go;
    }
    $tmpl = &TWiki::getRenderedVersion( $tmpl );

    # Don't want to render form fields, so this after getRenderedVersion
    my %formMeta = $meta->findOne( "FORM" );
    my $form = "";
    $form = $formMeta{"name"} if( %formMeta );
    if( $form && $saveCmd ne "repRev" ) {
       my @fieldDefs = &TWiki::Form::getFormDef( $templateWeb, $form );
       
       if( ! @fieldDefs ) {
            my $url = &TWiki::getOopsUrl( $webName, $topic, "oopsnoformdef" );
            TWiki::redirect( $query, $url );
            return;
       }
       my $formText = &TWiki::Form::renderForEdit( $webName, $topic, $form, $meta, $query, @fieldDefs );
       $tmpl =~ s/%FORMFIELDS%/$formText/go;
    } elsif( $saveCmd ne "repRev" && TWiki::Prefs::getPreferencesValue( "WEBFORMS", $webName )) {
       $form = '<table width="100%"><tr><td align="right">'
             . &TWiki::Form::chooseFormButton( "Add form" )
             . '</dt></tr></table>';
       $tmpl =~ s/%FORMFIELDS%/$form/go;
    } else {
       $tmpl =~ s/%FORMFIELDS%//go;
    }
    
    $tmpl =~ s/%FORMTEMPLATE%//go; # Clear if not being used
    $tmpl =~ s/%TEXT%/$text/go;
    $tmpl =~ s|( ?) *</*nop/*>\n?|$1|gois;   # remove <nop> tags

    TWiki::writeHeaderFull ( $query, 'edit', 'text/html', length($tmpl) );

    print $tmpl;
}
