# TWiki Collaboration Platform, http://TWiki.org/
#
# Copyright (C) 1999-2004 Peter Thoeny, peter@thoeny.com
#
# 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
=begin twiki

---+ TWiki::UI::Manage

UI functions for web, topic and user management

=cut

package TWiki::UI::Manage;

use strict;
use File::Copy;
use TWiki;
use TWiki::UI;
use TWiki::User;

=pod

---+++ $config->{TWiki}->{UI}->{Manage}->removeUser ( $web, $topic, $userToRemove, $query )
Renames the user's topic (with renaming all links)
removes user entry from passwords. CGI parameters:
| =password= | |

=cut

sub new { 
	my $dummy = shift;
	my $config = shift;
	unshift @_,$dummy ;

   my ( $proto ) =@_ ;
   my $class = ref($proto) || $proto ;
   my $self;

	$self->{config}=$config;
   bless ( $self );

   return $self ;
}

sub removeUser { 

   my $self = shift;
	my $config = $self->{config} ;


  my( $webName, $topic, $wikiName, $query ) = @_;

  my $password = $query->param( 'password' );

  # check if user entry exists
  #TODO: need to handle the NoPasswdUser case (UserPasswordExists will retun false here)
  if(  ( $wikiName )  && (! $config->{TWiki}->{User}->UserPasswordExists ( $wikiName ) ) ) {
    $config->{TWiki}->{UI}->oops ( $webName, $topic, "notwikiuser", $wikiName );
    return;
  }

  #check to see it the user we are trying to remove is a memebr of a group.
  #initinally we refuse to delte the user
  #in a later implementation we will remove the from the group (if Access.pm implements it..)
  my @groups =  $config->{TWiki}->{Access}->getGroupsUserIsIn ( $wikiName );
  my $numberOfGroups =  $#groups;
  if ( $numberOfGroups > -1 ) { 
    $config->{TWiki}->{UI}->oops ( $webName, $topic, "genericerror");
    return;
  }

  my $pw = $config->{TWiki}->{User}->CheckUserPasswd ( $wikiName, $password );
  if( ! $pw ) {
    # NO - wrong old password
    $config->{TWiki}->{UI}->oops ( $webName, $topic, "wrongpassword");
    return;
  }

  #TODO: need to add GetUniqueTopicName
  #   # appends a unique number to the requested topicname
  #    my $newTopicName = TWiki::getUniqueTopicName("AnonymousContributor");
  #
  #   my $renameError = $config->{TWiki}->{Store}->renameTopic ( $config->{TWiki}->{mainWebname}, $wikiName, $config->{TWiki}->{mainWebname}, $newTopicName, "relink" );
  #
  #   if ( $renameError ) {
  #TODO: add better error message for rname failed
  #         $config->{TWiki}->{UI}->oops ( $webName, $topic, "renameerr");
  #         return;
  #     }
  #
  #    # Update references in referring pages - not applicable to attachments.
  #    my @refs = &TWiki::Store::findReferringPages( $oldWeb, $oldTopic );
  #    my $problems;
  #    ( $lockFailure, $problems ) = 
  #       $config->{TWiki}->{Store}->updateReferingPages ( $oldWeb, $oldTopic, $wikiUserName, $newWeb, $newTopic, @refs );

  $config->{TWiki}->{User}->RemoveUser ($wikiName);

  $config->{TWiki}->{UI}->oops ( $webName, $topic, "removeuserdone", $wikiName);
  return;
}

=pod

---+++ $config->{TWiki}->{UI}->{Manage}->changePassword ( $webName, $topic, $query )
Change the user's password. Details of the user and password
are passed in CGI parameters.
| =username= | |
| =password= | |
| =passwordA= | |
| =TopicName= | |

=cut

sub changePassword { 
   my $self = shift;
	my $config = $self->{config} ;


  my( $webName, $topic, $query ) = @_;

  my $wikiName = $query->param( 'username' );
  my $passwordA = $query->param( 'password' );
  my $passwordB = $query->param( 'passwordA' );
  my $topicName = $query->param( 'TopicName' );

  # check if required fields are filled in
  if( ! $wikiName || ! $passwordA ) {
    $config->{TWiki}->{UI}->oops ( $webName, $topic, "regrequ", );
    return;
  }

  # check if user entry exists
  #TODO: need to handle the NoPasswdUser case (UserPasswordExists will retun false here)
  if(  ( $wikiName )  && (! $config->{TWiki}->{User}->UserPasswordExists ( $wikiName ) ) ) {
    $config->{TWiki}->{UI}->oops ( $webName, $topic, "notwikiuser", $wikiName );
    return;
  }

  # check if passwords are identical
  if( $passwordA ne $passwordB ) {
    $config->{TWiki}->{UI}->oops ( $webName, $topic, "regpasswd" );
    return;
  }

  # c h a n g e
  my $oldpassword = $query->param( 'oldpassword' );

  # check if required fields are filled in
  if( ! $oldpassword ) {
    $config->{TWiki}->{UI}->oops ( $webName, $topic, "regrequ" );
    return;
  }

  my $pw = $config->{TWiki}->{User}->CheckUserPasswd ( $wikiName, $oldpassword );
  if( ! $pw ) {
    # NO - wrong old password
    $config->{TWiki}->{UI}->oops ( $webName, $topic, "wrongpassword");
    return;
  }

  # OK - password may be changed
  $config->{TWiki}->{User}->UpdateUserPassword ($wikiName,  $oldpassword, $passwordA );

  # OK - password changed
  $config->{TWiki}->{UI}->oops ( $webName, $topic, "changepasswd" );
}

# PRIVATE Prepare a template var for expansion in a message
sub _template { 
   my $self = shift;
	my $config = $self->{config} ;


  my $theTmplVar = shift;
  return "%TMPL:P{\"$theTmplVar\"}%";
}

=pod

---++ $config->{TWiki}->{UI}->{Manage}->createWeb ( $web, $topic, $user, $query )
Create a new web. Parameters defining the new web are passed
in a CGI query.

| =newweb= | Name of new web |
| =baseweb= | Name of web to copy to create newweb |
| =webbgcolor= | background color for new web |
| =sitemapwhat= | |
| =sitemapuseto= | |
| =nosearchall= | |

=cut

sub createWeb { 
   my $self = shift;
	my $config = $self->{config} ;


  my( $webName, $topicName, $userName, $query ) = @_;

  my $newWeb = $query->param( 'newweb' ) || "";
  my $newTopic = $query->param( 'newtopic' ) || "";
  my $baseWeb = $query->param( 'baseweb' ) || "";
  my $webBgColor = $query->param( 'webbgcolor' ) || "";
  my $siteMapWhat = $query->param( 'sitemapwhat' ) || "";
  my $siteMapUseTo = $query->param( 'sitemapuseto' ) || "";
  my $noSearchAll = $query->param( 'nosearchall' ) || "";
  my $theUrl = $query->url;
  my $oopsTmpl = "mngcreateweb";

  # check permission, user authorized to create webs?
  my $wikiUserName = $config->{TWiki}->userToWikiName ( $userName );
  return unless $config->{TWiki}->{UI}->isAccessPermitted ( $webName, $topicName,
                                              "manage", $wikiUserName );

  if( $newWeb =~ /^_[a-zA-Z0-9_]+$/ ) {
    # valid template web name, untaint
    $newWeb =~ /(.*)/;
    $newWeb = $1;
  } elsif( $config->{TWiki}->isWebName ( $newWeb ) ) {
    # valid web name, untaint
    $newWeb =~ /(.*)/;
    $newWeb = $1;
  } elsif( $newWeb ) {
    $config->{TWiki}->{UI}->oops ( "", "", $oopsTmpl, $config->{TWiki}->{UI}->{Manage}->_template ("msg_web_name") );
    return;
  } else {
    $config->{TWiki}->{UI}->oops ( "", "", $oopsTmpl, $config->{TWiki}->{UI}->{Manage}->_template ("msg_web_missing") );
    return;
  }

  if( $config->{TWiki}->{Store}->topicExists ( $newWeb, $config->{TWiki}->{mainTopicname} ) ) {
    $config->{TWiki}->{UI}->oops ( "", "", $oopsTmpl,
                     $config->{TWiki}->{UI}->{Manage}->_template ("msg_web_exist"), $newWeb );
    return;
  }

  $baseWeb =~ s/$config->{TWiki}->{securityFilter}//go;
  $baseWeb =~ /(.*)/;
  $baseWeb = $1;

  unless( $config->{TWiki}->{Store}->topicExists ( $baseWeb, $config->{TWiki}->{mainTopicname} ) ) {
    $config->{TWiki}->{UI}->oops ( "", "", $oopsTmpl, $config->{TWiki}->{UI}->{Manage}->_template ("msg_base_web"), $baseWeb );
    return;
  }

  unless( $webBgColor =~ /\#[0-9a-f]{6}/i ) {
    $config->{TWiki}->{UI}->oops ( "", "", $oopsTmpl, $config->{TWiki}->{UI}->{Manage}->_template ("msg_web_color") );
    return;
  }

  # create the empty web
  my $err = $config->{TWiki}->{UI}->{Manage}->_createEmptyWeb ( $newWeb );
  if( $err ) {
    $config->{TWiki}->{UI}->oops ( "", "", $oopsTmpl, $config->{TWiki}->{UI}->{Manage}->_template ("msg_web_create"), $err );
    return;
  }

  # copy needed topics from base web
  $err = $config->{TWiki}->{UI}->{Manage}->_copyWebTopics ( $baseWeb, $newWeb );
  if( $err ) {
    $config->{TWiki}->{UI}->oops ( $newWeb, "", $oopsTmpl, $config->{TWiki}->{UI}->{Manage}->_template ("msg_web_copy_topics"), $err );
    return;
  }

  # patch WebPreferences
  $err = $config->{TWiki}->{UI}->{Manage}->_patchWebPreferences ( $newWeb, $config->{TWiki}->{webPrefsTopicname}, $webBgColor,
                               $siteMapWhat, $siteMapUseTo, $noSearchAll );
  if( $err ) {
    $config->{TWiki}->{UI}->oops ( $newWeb, $config->{TWiki}->{webPrefsTopicname}, $oopsTmpl, $config->{TWiki}->{UI}->{Manage}->_template ("msg_patch_webpreferences"), $err );
    return;
  }

  # everything OK, redirect to last message
  $newTopic = $config->{TWiki}->{mainTopicname} unless( $newTopic );
  $config->{TWiki}->{UI}->oops ( $newWeb, $newTopic, $oopsTmpl, $config->{TWiki}->{UI}->{Manage}->_template ("msg_create_web_ok") );
  return;
}

# CODE_SMELL: Surely this should be done by Store?
sub _createEmptyWeb { 
   my $self = shift;
	my $config = $self->{config} ;


  my ( $theWeb ) = @_;

  my $dir = "$config->{TWiki}->{dataDir}/$theWeb";
  umask( 0 );
  unless( mkdir( $dir, 0775 ) ) {
    return( "Could not create $dir, error: $!" );
  }

  if ( $config->{TWiki}->{useRcsDir} ) {
    unless( mkdir( "$dir/RCS", 0775 ) ) {
      return( "Could not create $dir/RCS, error: $!" );
    }
  }

  unless( open( FILE, ">$dir/.changes" ) ) {
    return( "Could not create changes file $dir/.changes, error: $!" );
  }
  print FILE "";  # empty file
  close( FILE );

  unless( open( FILE, ">$dir/.mailnotify" ) ) {
    return( "Could not create mailnotify timestamp file $dir/.mailnotify, error: $!" );
  }
  print FILE "";  # empty file
  close( FILE );
  return "";
}

# CODE_SMELL: Surely this should be done by Store?
sub _copyWebTopics
{ 
   my $self = shift;
	my $config = $self->{config} ;


    my ( $theBaseWeb, $theNewWeb ) = @_;

    my $err = "";
    my @topicList = $config->{TWiki}->{Store}->getTopicNames ( $theBaseWeb );
    unless( $theBaseWeb =~ /^_/ ) {
        # not a template web, so filter for only Web* topics
        @topicList = grep { /^Web/ } @topicList;
    }
    foreach my $topic ( @topicList ) {
        $topic =~ s/$config->{TWiki}->{securityFilter}//go;
        $topic =~ /(.*)/;
        $topic = $1;
        $err = $config->{TWiki}->{UI}->{Manage}->_copyOneTopic ( $theBaseWeb, $topic, $theNewWeb );
        return( $err ) if( $err );
    }
    return "";
}

# CODE_SMELL: Surely this should be done by Store?
sub _copyOneTopic
{ 
   my $self = shift;
	my $config = $self->{config} ;


    my ( $theFromWeb, $theTopic, $theToWeb ) = @_;

    # FIXME: This should go into TWiki::Store

    # copy topic file
    my $from = "$config->{TWiki}->{dataDir}/$theFromWeb/$theTopic.txt";
    my $to = "$config->{TWiki}->{dataDir}/$theToWeb/$theTopic.txt";
    unless( copy( $from, $to ) ) {
        return( "Copy file ( $from, $to ) failed, error: $!" );
    }
    umask( 002 );
    chmod( 0644, $to );

    # copy repository file
    # FIXME: Hack, no support for RCS subdirectory
    $from .= ",v";
    $to .= ",v";
    if( -e $from ) {
        unless( copy( $from, $to ) ) {
            return( "Copy file ( $from, $to ) failed, error: $!" );
        }
        umask( 002 );
        chmod( 0644, $to );
    }

    # FIXME: Copy also attachments if present

    return "";
}

# CODE_SMELL: Surely this should be done by Store?
sub _patchWebPreferences
{ 
   my $self = shift;
	my $config = $self->{config} ;


    my ( $theWeb, $theTopic, $theWebBgColor, $theSiteMapWhat, $theSiteMapUseTo, $doNoSearchAll ) = @_;

    my( $meta, $text ) = $config->{TWiki}->{Store}->readTopic ( $theWeb, $theTopic );

    my $siteMapList = "";
    $siteMapList = "on" if( $theSiteMapWhat );
    $text =~ s/(\s\* Set WEBBGCOLOR =)[^\n\r]*/$1 $theWebBgColor/os;
    $text =~ s/(\s\* Set SITEMAPLIST =)[^\n\r]*/$1 $siteMapList/os;
    $text =~ s/(\s\* Set SITEMAPWHAT =)[^\n\r]*/$1 $theSiteMapWhat/os;
    $text =~ s/(\s\* Set SITEMAPUSETO =)[^\n\r]*/$1 $theSiteMapUseTo/os;
    $text =~ s/(\s\* Set NOSEARCHALL =)[^\n\r]*/$1 $doNoSearchAll/os;

    my $err = $config->{TWiki}->{Store}->saveTopic ( $theWeb, $theTopic, $text, $meta );

    return $err;
}

=pod

---+++ $config->{TWiki}->{UI}->{Manage}->rename ( $web, $topic, $user, $query )
Rename the given topic. Details of the new topic name are passed in CGI
paremeters:
| =skin= | skin to use for derivative topics |
| =newweb= | new web name |
| =newtopic= | new topic name |
| =breaklock= | |
| =attachment= | |
| =confirm= | if defined, requires a second level of confirmation |
| =currentwebonly= | if defined, searches current web only for links to this topic |
| =nonwikiword= | if defined, a non-wikiword is acceptable for the new topic name |
| =changerefs= | |

=cut

sub rename { 
   my $self = shift;
	my $config = $self->{config} ;


  my ( $oldWeb, $oldTopic, $userName, $query ) = @_;

  my $newWeb = $query->param( 'newweb' ) || "";
  my $newTopic = $query->param( 'newtopic' ) || "";
  my $theUrl = $query->url;
  my $lockFailure = "";
  my $breakLock = $query->param( 'breaklock' );
  my $theAttachment = $query->param( 'attachment' );
  my $confirm = $query->param( 'confirm' );
  my $currentWebOnly = $query->param( 'currentwebonly' ) || "";
  my $doAllowNonWikiWord = $query->param( 'nonwikiword' ) || "";
  my $justChangeRefs = $query->param( 'changeRefs' ) || "";

  my $skin = $query->param( "skin" ) || $config->{TWiki}->{Prefs}->getPreferencesValue ( "SKIN" );

  $newTopic =~ s/\s//go;
  $newTopic =~ s/$config->{TWiki}->{securityFilter}//go;

  if( ! $theAttachment ) {
    $theAttachment = "";
  }

  my $wikiUserName = $config->{TWiki}->userToWikiName ( $userName );

  # justChangeRefs will be true when some topics that had links to $oldTopic
  # still need updating, previous update being prevented by a lock.

  my $fileName = $config->{TWiki}->{Store}->getFileName ( $oldWeb, $oldTopic );
  my $newName;
  $newName = $config->{TWiki}->{Store}->getFileName ( $newWeb, $newTopic ) if( $newWeb );

  if( ! $justChangeRefs ) {
    if( $config->{TWiki}->{UI}->{Manage}->_checkExist ( $oldWeb, $oldTopic, $newWeb, $newTopic, $theAttachment, $fileName, $newName ) ) {
      return;
    }

    if( ! $config->{TWiki}->{UI}->{Manage}->_checkPermissions ( $oldWeb, $oldTopic, $wikiUserName ) ) {
      return;
    }
  }

  # Has user selected new name yet?
  if( ! $newTopic || $confirm ) {
    $config->{TWiki}->{UI}->{Manage}->_newTopicScreen ( $oldWeb, $oldTopic, $newWeb, $newTopic, $theAttachment,
                     $confirm, $currentWebOnly, $doAllowNonWikiWord, $skin );
    return;
  }

  if( ! $justChangeRefs ) {
    if( ! $config->{TWiki}->{UI}->{Manage}->_getLocks ( $oldWeb, $oldTopic, $newWeb, $newTopic, $theAttachment, $breakLock, $skin ) ) {
      return;
    }
  }

  if( ! $justChangeRefs ) {
    if( $theAttachment ) {
      my $moveError = 
        $config->{TWiki}->{Store}->moveAttachment ( $oldWeb, $oldTopic, $newWeb, $newTopic, $theAttachment );
      if( $moveError ) {
        $config->{TWiki}->{UI}->oops ( $newWeb, $newTopic, "moveerr",
                         $theAttachment, $moveError );
        return;
      }
    } else {
      if( ! $doAllowNonWikiWord && ! $config->{TWiki}->isWikiName ( $newTopic ) ) {
        $config->{TWiki}->{UI}->oops ( $newWeb, $newTopic, "renamenotwikiword" );
        return;
      }

      my $renameError = $config->{TWiki}->{Store}->renameTopic ( $oldWeb, $oldTopic, $newWeb, $newTopic, "relink" );
      if( $renameError ) {
        $config->{TWiki}->{UI}->oops ( $oldWeb, $oldTopic, "renameerr",
                         $renameError, $newWeb, $newTopic );
        return;
      }
    }
  }

  # Update references in referring pages - not applicable to attachments.
  if( ! $theAttachment ) {
    my @refs = $config->{TWiki}->{UI}->{Manage}->_getReferingTopicsListFromURL ( $oldWeb, $oldTopic, $newWeb, $newTopic );

    my $problems;
    ( $lockFailure, $problems ) = 
      $config->{TWiki}->{Store}->updateReferingPages ( $oldWeb, $oldTopic, $wikiUserName, $newWeb, $newTopic, @refs );
  }

  my $new_url = "";
  if( $lockFailure ) {
    $config->{TWiki}->{UI}->{Manage}->_moreRefsToChange ( $oldWeb, $oldTopic, $newWeb, $newTopic, $skin );
    return;
  } elsif ( "$newWeb" eq "Trash" && "$oldWeb" ne "Trash" ) {
    if( $theAttachment ) {
      # go back to old topic after deleting an attachment
      $new_url = $config->{TWiki}->getViewUrl ( $oldWeb, $oldTopic );
    } else {
      #redirect to parent: ending in Trash is not the expected way (ColasNahaboo - 31 Mar 2003)
      my $meta = ""; my $text = "";
      ( $meta, $text ) = $config->{TWiki}->{Store}->readTopic ( $newWeb, $newTopic, 1 );
      my %parent = $meta->findOne( "TOPICPARENT" );
      if( %parent && $parent{"name"} && $parent{"name"} ne $oldTopic ) {
        if ( $parent{"name"} =~ /([^.]+)[.]([^.]+)/ ) {
          $new_url = $config->{TWiki}->getViewUrl ( $1, $2 );
        } else {
          $new_url = $config->{TWiki}->getViewUrl ( $oldWeb, $parent{"name"} );
        }
      } else {

        $new_url = $config->{TWiki}->getViewUrl ( $oldWeb, $config->{TWiki}->{UI}->{Manage}->{mainTopicname} );
      }
    }
  } else {
    #redirect to new topic
    $new_url = $config->{TWiki}->getViewUrl ( $newWeb, $newTopic );
  }

  $config->{TWiki}->{UI}->redirect ( $new_url );
  return;
}

#=========================

=pod

---++ _relockRcsFiles ( )
| Description:           | relocks all the rcs files using the configured apache user (called from testenv)) |

=cut

sub relockRcsFiles { 
   my $self = shift;
	my $config = $self->{config} ;


print "Content-type: text/html\n\n";
print "<html><head></head><body>\n";
print "Preparing to change all RCS locks to match current webserver user.\n";
print "Please wait for this page to tell you it is finished.\n";
print "This could take awhile, depending on the number of topics to process\n";
print "(about 10 seconds for a standard twiki beta release - 615 topics -\n";
print "on a Win2k+cygwin+apache2 machine running @ 1100MHz with 512MB ram).";
  
$ENV{PATH} = '';
  
opendir(DATA, $config->{TWiki}->{dataDir}) or
  die "Open $config->{TWiki}->{dataDir} failed";
foreach my $web ( grep /^\w+$/, readdir DATA ) {
  $web =~ /(.*)/;     # untaint
  $web = $1;
  print "<h1>Unlocking $web</h1>\n";
  if ( -d "$config->{TWiki}->{dataDir}/$web" ) {
	opendir(WEB, "$config->{TWiki}->{dataDir}/$web") or
	  die "Open $config->{TWiki}->{dataDir}/$web failed";;
	foreach my $topic ( grep /.txt$/, readdir WEB ) {
      $topic =~ /(.*)/;     # untaint
      $topic = $1;
	  print "<code>$topic</code> ";
	  
#TODO replace with TWiki::Store::breakLockTopic( $web, $topic );	  
	  print `$config->{TWiki}->{rcsDir}/rcs -q -u -M $config->{TWiki}->{dataDir}/$web/$topic`;
#TODO replace with TWiki::Store::reLockTopic( $web, $topic );	  
	  print `$config->{TWiki}->{rcsDir}/rcs -q -l $config->{TWiki}->{dataDir}/$web/$topic`;
#TODO replace with TWiki::Store::checkIn (or something)
          print `$config->{TWiki}->{rcsDir}/ci -mtestenv -t-missing_v $config->{TWiki}->{dataDir}/$web/$topic`;
          print `$config->{TWiki}->{rcsDir}/co -q -l -M $config->{TWiki}->{dataDir}/$web/$topic`;
	  print "<br />\n";
	}
	closedir(WEB);
  }
}
closedir(DATA);
print "<h2>Re-locking finished</h2>\n";
print "It is now safe to reload <a href=\"$config->{TWiki}->{defaultUrlHost}$config->{TWiki}->{scriptUrlPath}/testenv\">testenv</a> \n";
print "</body></html>";
}

#=========================

=pod

---++ $config->{TWiki}->{UI}->{Manage}->_getReferingTopicsListFromURL ( $oldWeb, $oldTopic, $newWeb, $newTopic ) ==> @refs
| Description:           | returns the list of topics that have been found that refer to the renamed topic |
| Parameter: =$oldWeb=   |   |
| Parameter: =$oldTopic= |   |
| Parameter: =$newWeb=   |   |
| Parameter: =$newTopic= |   |
| Return: =@refs=        |   |
| TODO: | docco what the return list means |

=cut

sub _getReferingTopicsListFromURL { 
   my $self = shift;
	my $config = $self->{config} ;


  my $query = $config->{TWiki}->getCgiQuery ();
  my ( $oldWeb, $oldTopic, $newWeb, $newTopic ) = @_;

  my @result = ();

  # Go through parameters finding all topics for change
  my @types = qw\local global\;
  foreach my $type ( @types ) {
    my $count = 1;
    while( $query->param( "TOPIC$type$count" ) ) {
      my $checked = $query->param( "RENAME$type$count" );
      if ($checked) {
        push @result, $type;
		my $topic = $query->param( "TOPIC$type$count" );
		if ($topic =~ /^$oldWeb.$oldTopic$/ ) {
			$topic = "$newWeb.$newTopic";
		}
        push @result, $topic;
      }
      $count++;
    }
  }
  return @result;
}

#=============================
# return "" if problem, otherwise return text of oldTopic
sub _checkPermissions { 
   my $self = shift;
	my $config = $self->{config} ;


  my( $oldWeb, $oldTopic, $wikiUserName ) = @_;

  return "" unless $config->{TWiki}->{UI}->isAccessPermitted ( $oldWeb, $oldTopic, "change", $wikiUserName );
  return "" unless $config->{TWiki}->{UI}->isAccessPermitted ( $oldWeb, $oldTopic, "rename", $wikiUserName );

  my $ret = "";
  if( $config->{TWiki}->{Store}->topicExists ( $oldWeb, $oldTopic ) ) {
    $ret = $config->{TWiki}->{Store}->readWebTopic ( $oldWeb, $oldTopic );
  }
  return $ret;
}


#==========================================
# Check that various webs and topics exist or don't exist as required
sub _checkExist { 
   my $self = shift;
	my $config = $self->{config} ;


  my( $oldWeb, $oldTopic, $newWeb, $newTopic, $theAttachment, $oldFileName, $newFileName ) = @_;

  my $ret = 0;
  my $query = $config->{TWiki}->getCgiQuery ();

  $ret = 1 unless $config->{TWiki}->{UI}->webExists ( $oldWeb, $oldTopic );
  $ret = 1 unless $config->{TWiki}->{UI}->webExists ( $newWeb, $newTopic );

  # Does old attachment exist?
  if( ! -e $oldFileName) {
    $config->{TWiki}->{UI}->oops ( $oldWeb, $oldTopic, "missing" );
    $ret = 1;
  }

  # Check new topic doesn't exist (opposite if we've moving an attachment)
  if( defined( $newFileName ) && -e $newFileName && ! $theAttachment ) {
    # Unless moving an attachment, new topic should not already exist
    $config->{TWiki}->{UI}->oops ( $newWeb, $newTopic, "topicexists" );
    $ret = 1;
  }

  if( defined( $newFileName ) && $theAttachment && ! -e $newFileName ) {
    $config->{TWiki}->{UI}->oops ( $newWeb, $newTopic, "missing" );
    $ret = 1;
  }

  return $ret;
}


#============================
#Return "" if can't get lock, otherwise "okay"
sub _getLocks { 
   my $self = shift;
	my $config = $self->{config} ;


  my( $oldWeb, $oldTopic, $newWeb, $newTopic, $theAttachment, $breakLock, $skin ) = @_;
  
  my( $oldLockUser, $oldLockTime, $newLockUser, $newLockTime );
  my $query = $config->{TWiki}->getCgiQuery ();

  if( ! $breakLock ) {
    # Check for lock - at present the lock can't be broken
    ( $oldLockUser, $oldLockTime ) = $config->{TWiki}->{Store}->topicIsLockedBy ( $oldWeb, $oldTopic );
    if( $oldLockUser ) {
      $oldLockUser = $config->{TWiki}->userToWikiName ( $oldLockUser );
      use integer;
      $oldLockTime = ( $oldLockTime / 60 ) + 1; # convert to minutes
    }

    if( $theAttachment ) {
      ( $newLockUser, $newLockTime ) = $config->{TWiki}->{Store}->topicIsLockedBy ( $newWeb, $newTopic );
      if( $newLockUser ) {
        $newLockUser = $config->{TWiki}->userToWikiName ( $newLockUser );
        use integer;
        $newLockTime = ( $newLockTime / 60 ) + 1; # convert to minutes
        my $editLock = $config->{TWiki}->{editLockTime} / 60;
      }
    }
  }

  if( $oldLockUser || $newLockUser ) {
    my $tmpl = $config->{TWiki}->{Store}->readTemplate ( "oopslockedrename", $skin );
    my $editLock = $config->{TWiki}->{editLockTime} / 60;
    if( $oldLockUser ) {
      $tmpl =~ s/%OLD_LOCK%/Source topic $oldWeb.$oldTopic is locked by $oldLockUser, lock expires in $oldLockTime minutes.<br \/>/go;
    } else {
      $tmpl =~ s/%OLD_LOCK%//go;
    }
    if( $newLockUser ) {
      $tmpl =~ s/%NEW_LOCK%/Destination topic $newWeb.$newTopic is locked by $newLockUser, lock expires in $newLockTime minutes.<br \/>/go;
    } else {
      $tmpl =~ s/%NEW_LOCK%//go;
    }
    $tmpl =~ s/%NEW_WEB%/$newWeb/go;
    $tmpl =~ s/%NEW_TOPIC%/$newTopic/go;
    $tmpl =~ s/%ATTACHMENT%/$theAttachment/go;
    $tmpl = $config->{TWiki}->handleCommonTags ( $tmpl, $oldTopic, $oldWeb );
    $tmpl = $config->{TWiki}->{Render}->getRenderedVersion ( $tmpl, $oldWeb );
    $tmpl =~ s/( ?) *<\/?(nop|noautolink)\/?>\n?/$1/gois;   # remove <nop> and <noautolink> tags
    $config->{TWiki}->writeHeader ( $query );
    print $tmpl;
    return "";
  } else {
    $config->{TWiki}->{Store}->lockTopicNew ( $oldWeb, $oldTopic );
    if( $theAttachment ) {
      $config->{TWiki}->{Store}->lockTopicNew ( $newWeb, $newTopic );
    }
  }

  return "okay";
}

#============================
# Display screen so user can decide on new web and topic.
sub _newTopicScreen { 
   my $self = shift;
	my $config = $self->{config} ;


  my( $oldWeb, $oldTopic, $newWeb, $newTopic, $theAttachment,
      $confirm, $currentWebOnly, $doAllowNonWikiWord, $skin ) = @_;

  my $query = $config->{TWiki}->getCgiQuery ();
  my $tmpl = "";

  $newTopic = $oldTopic unless ( $newTopic );
  $newWeb = $oldWeb unless ( $newWeb );
  my $nonWikiWordFlag = "";
  $nonWikiWordFlag = 'checked="checked"' if( $doAllowNonWikiWord );

  $config->{TWiki}->writeHeader ( $query );
  if( $theAttachment ) {
    $tmpl = $config->{TWiki}->{Store}->readTemplate ( "moveattachment", $skin );
    $tmpl =~ s/%FILENAME%/$theAttachment/go;
  } elsif( $confirm ) {
    $tmpl = $config->{TWiki}->{Store}->readTemplate ( "renameconfirm", $skin );
  } elsif( $newWeb eq "Trash" ) {
    $tmpl = $config->{TWiki}->{Store}->readTemplate ( "renamedelete", $skin );
  } else {
    $tmpl = $config->{TWiki}->{Store}->readTemplate ( "rename", $skin );
  }

  $tmpl = $config->{TWiki}->{UI}->{Manage}->_setVars ( $tmpl, $oldTopic, $newWeb, $newTopic, $nonWikiWordFlag );
  $tmpl = $config->{TWiki}->handleCommonTags ( $tmpl, $oldTopic, $oldWeb );
  $tmpl = $config->{TWiki}->{Render}->getRenderedVersion ( $tmpl );
  if( $currentWebOnly ) {
    $tmpl =~ s/%RESEARCH\{.*?web=\"all\".*\}%/(skipped)/o; # Remove search all web search
  }
  $tmpl =~ s/%RESEARCH/%SEARCH/go; # Pre search result from being rendered
  $tmpl = $config->{TWiki}->handleCommonTags ( $tmpl, $oldTopic, $oldWeb );   
  $tmpl =~ s/( ?) *<\/?(nop|noautolink)\/?>\n?/$1/gois;   # remove <nop> and <noautolink> tags
  print $tmpl;
}

#=========================
sub _setVars { 
   my $self = shift;
	my $config = $self->{config} ;


  my( $tmpl, $oldTopic, $newWeb, $newTopic, $nonWikiWordFlag ) = @_;
  $tmpl =~ s/%NEW_WEB%/$newWeb/go;
  $tmpl =~ s/%NEW_TOPIC%/$newTopic/go;
  $tmpl =~ s/%NONWIKIWORDFLAG%/$nonWikiWordFlag/go;
  return $tmpl;
}

#=========================
sub _moreRefsToChange { 
   my $self = shift;
	my $config = $self->{config} ;


  my( $oldWeb, $oldTopic, $newWeb, $newTopic, $skin ) = @_;
  my $query = $config->{TWiki}->getCgiQuery ();

  $config->{TWiki}->writeHeader ( $query );
  my $tmpl = $config->{TWiki}->{Store}->readTemplate ( "renamerefs", $skin );
  $tmpl = $config->{TWiki}->{UI}->{Manage}->_setVars ( $tmpl, $oldTopic, $newWeb, $newTopic );
  $tmpl = $config->{TWiki}->{Render}->getRenderedVersion ( $tmpl );
  $tmpl =~ s/%RESEARCH/%SEARCH/go; # Pre search result from being rendered
  $tmpl = $config->{TWiki}->handleCommonTags ( $tmpl, $oldTopic, $oldWeb );
  $tmpl =~ s/( ?) *<\/?(nop|noautolink)\/?>\n?/$1/gois;   # remove <nop> and <noautolink> tags
  print $tmpl;
}

1;

1;
