# 
# $Header: rfeSaveFile.pl 06-feb-2006.12:38:10 sreddy Exp $
#
# rfeSaveFile.pl
# 
# Copyright (c) 2005, 2006, Oracle. All rights reserved.  
#
#    NAME
#      rfeSaveFile.pl - Perl script to save a file for Remote File Editor Page 
#                       in Edit Mode
#
#    DESCRIPTION
#      <short description of component this file declares/defines>
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    sreddy      01/24/06 - fix bug#4968435 
#    sreddy      12/23/05 - fix bug#4903488 
#    ajere       12/10/05 - XbranchMerge ajere_bug-4779290 from main 
#    ajere       06/27/05 - ajere_bug-4386234_1
#    ajere       06/27/05 - Creation
# 

require "emd_common.pl";
use strict;

#Subroutine declarations
sub saveFile($);
sub performPreFileSaveChk($$$$);
sub checkWritePermission($$);

#Global variables
my $windowsOsCmd      = "cmd";
my $unixOsCmd         = "/bin/sh";

#Save the file
saveFile(@ARGV);

#############################################
# saveFile()
# Subroutine to get file contents
#############################################
sub saveFile($)
{
  #Input params
  my $osCmd                  = $ARGV[0];
  my $fileName               = $ARGV[1];
  my $fileSizeLimitKB        = $ARGV[2];
  my $showConfPageBeforeSave = $ARGV[3];
 
  my $preSaveChkMsg     = "NULL";
  my $preSaveChkError   = "FALSE";

  #If the file name is null, return
  if (!$fileName) {
    EMD_PERL_ERROR("Input file name is empty!\n");
    exit 1;
  }
  
  #For Windows OS, execute exec_commonenv.bat if mount_shares.bat
  #and unmount_shares.bat files exist

  if (($osCmd eq $windowsOsCmd) && 
       !defined($ENV{EM_AGENT_COMMONENV_BAT_EXEC}) &&
       (-e "$ENV{EMDROOT}/bin/mount_shares.bat") &&
       (-e "$ENV{EMDROOT}/bin/unmount_shares.bat"))
  {
    #save STDERR into STDERZR_ORIG. Upon failure, skip exec_commonenv.bat step
    if (open (STDERR_ORIG, ">&STDERR"))
    {
      #send STDERR to null device. Upon failure, skip exec_commonenv.bat step
      if (open (STDERR, ">/dev/null"))
      {
        my $beginToken="BEGIN_REMOTE_OP_RESULT_SET_AFTER_COMMONENV_BAT";
        my $endToken="END_REMOTE_OP_RESULT_SET_AFTER_COMMONENV_BAT";
        my $beginTokenFound=0;
        my $line;

        #Batch file exec_commonenv.bat sets EM_AGENT_COMMONENV_BAT_EXEC and
        #call this script again after network shares from mount_shares.bat
        #are mounted. This block won't get executed then and the array 
        #scriptResult will contain actual output within start and end tokens.

        my @scriptResult=`$ENV{EMDROOT}\\bin\\exec_commonenv.bat rfeSaveFile.pl @ARGV`;

        #restore STDERR to STDERR_ORIG
        close(STDERR);
        open (STDERR, ">&STDERR_ORIG")
          or EMD_PERL_ERROR("Failed to restore STDERR"); 

        #Note: There is no good reason why the above open will fail. Upon
        #failure, there is no need to exit since result will be sent 
        #on STDOUT back to OMS
 
        #Extract actual output of this script
        chomp @scriptResult;
        foreach $line (@scriptResult)
        {
          if ($line =~ $endToken)
          {
            print "$`"; #prints the content on last line 
                        #if it does not end with <LF>
            exit 0;
          }
          print "$line\n" if ($beginTokenFound eq 1);
          $beginTokenFound=1 if ($line =~ $beginToken);
        }
        exit 0;
      }
      else
      {
        EMD_PERL_ERROR("Failed to redirect STDERR to null device");
      }
    }
    else
    {
      EMD_PERL_ERROR("Failed to save STDERR into STDERR_ORIG");
    }
  }

  my @fileContents           = <STDIN>;

  #Default fileSizeLimitKB is 100 KB
  if(!$fileSizeLimitKB || !($fileSizeLimitKB =~ /\d/)) 
  {
    $fileSizeLimitKB = 100;
  }
  #print "fileSizeLimitKB = $fileSizeLimitKB\n";
    
  #Perform pre-save file checks
  ($preSaveChkMsg, $preSaveChkError) = performPreFileSaveChk($osCmd, $fileName, $fileSizeLimitKB, $showConfPageBeforeSave);
  
  #Save the file contents, iff pre-save checks indicate file can be saved
  if(($preSaveChkError eq "FALSE")&&($preSaveChkMsg ne "SHOW_CONF_PAGE"))
  {
    #Open the file for writing and truncate it before we write to it
    if (!open(FH, "> $fileName")) { 
      EMD_PERL_ERROR("Unable to open the file $fileName for writing!\n");
      exit 1;
    } 
    
    #Workaround for the agent bug (strip extra newline at the start)
    if($fileContents[0] eq "\n")
    {
      @fileContents = @fileContents[1 .. $#fileContents];
    }

    chomp(@fileContents);
    
    #Save File Contents to file
    foreach my $line (@fileContents) 
    {
      print FH "$line\n";
    }
    
    #Close the file
    close FH;
  }

  print $preSaveChkMsg."|".$preSaveChkError."\n";
}

#############################################
# performPreFileSaveChk()
# Subroutine to Perform pre-save file checks
#############################################
sub performPreFileSaveChk($$$$) 
{
  my $osCmd                  = $_[0];
  my $fileName               = $_[1];
  my $fileSizeLimitKB        = $_[2];
  my $showConfPageBeforeSave = $_[3];
  my $directory       = $fileName;
  
  #Pre-save check logic
  #File is a directory file!
  return ("FILE_IS_DIRECTORY_SAVE", "TRUE")
    if(-d $fileName);

  #Get the parent directory
  if ($osCmd eq $windowsOsCmd) 
  {
    #Windows
    if($fileName =~ /(.*\\)/) 
    {
      $directory = $1;
    }
  }
  elsif ($osCmd eq $unixOsCmd) 
  {
    #UNIX
    if ($fileName =~ m!(.*\/)!) 
    {
      $directory = $1;
    }
  }
  #print ("directory = $directory\n");	
  
  #File doesn't exist
  if (!-e $fileName) 
  {
    #case: directory does not exist
    return ("FILE_DOESNT_EXIST_SAVE", "TRUE")
      if (! -d $directory);

    #case: directory not writeable
    return ("FILE_DOESNT_EXIST_SAVE", "TRUE")
      if (! -w $directory);

    #case: unable to open file with WRITE permission
    return ("FILE_DOESNT_EXIST_SAVE", "TRUE")
      if (!checkWritePermission($fileName, $osCmd));

    return ("NEW_FILE_CREATED", "FALSE");
  }
  else
  {
    #No write permissions!
    return ("NO_SAVE_PERMISSIONS", "TRUE")
      if (!checkWritePermission($fileName, $osCmd));

    close(TEST_FH);

    return ("SHOW_CONF_PAGE", "TRUE")
      if($showConfPageBeforeSave eq "TRUE");

  }

 #No message & no errors
 return ("NULL", "FALSE");
}

###########################################################
# checkWritePerssion()
# Subroutine to test if it is possible to write to the file
###########################################################

sub checkWritePermission($$)
{
  my $fname = shift @_;
  my $osCmd = shift @_;
  my $writePermission = 0;

  if ($osCmd eq $unixOsCmd)
  {
    $writePermission = 1 if ((! -e $fname) || (-w $fname));
  }
  elsif ($osCmd eq $windowsOsCmd)
  {

#
# On Windows, if (-w $fname) test sometimes returns true
# value even if the file is not writeable. This can happen
# on a directory where the user is not granted FULL 
# privileges. This subroutine verifies the write permission
# by opening the file in append mode. It cleans up the
# file if it did not exist before the file was opened
# in append mode.
#
# This is one of the issues fixed as part of  bug#4968435
#
    my $removeFile = 0;
    $removeFile = 1 if ( ! -e $fname );

    if (open(TEST_FH,">>$fname"))
    {
      $writePermission=1;
      close(TEST_FH);
      unlink($fname) if ($removeFile);
    }
  }
  
  return $writePermission;
}
