# backup.tcl --
#
# Procedures for saving and restoring backups of current Apache installations.
# Currently only taking care of *.conf files

# ::apmanager::createBackUp
#   Takes a .conf file and returns xml backup file. It takes into account the 
# include directives so those files included are also saved

proc ::apmanager::createBackUp { backupdir pathToHttpdConf description} {
    set time [clock seconds]
    helper::writeFile $backupdir/backup-$time.xml \
	    [createBackUpText $pathToHttpdConf $description $time]
}

proc ::apmanager::createBackUpText { pathToHttpdConf description time} {
    update idletasks
    set docNode [dom::newDoc]
    set mainNode \
	    [dom::document createElement \
	    $docNode apacheInstallationBackUp]
    dom::setAttribute $mainNode time $time
    dom::setAttribute $mainNode description $description
    foreach pathToFile [getListOfConfigFilesToBackUp $pathToHttpdConf] {
	addConfigFileToBackUp $pathToFile $mainNode
    }
    set text [dom::DOMImplementation serialize $docNode]
    dom::deleteDoc $docNode
    return $text
}

proc ::apmanager::areThereBackUps { backupdir } {
    return [llength [glob -nocomplain [file join $backupdir *.xml]]]
}

proc ::apmanager::getBackUps { backupdir } {
    set backupList {}
    foreach file [glob -nocomplain [file join $backupdir *.xml]] {
	# filename description time
	lappend backupList [getBackupInfo $file]
    }
    return $backupList
}

proc ::apmanager::getBackupInfo {file} {
    set domNode [dom::getElements [dom::DOMImplementation parse \
	    [::helper::readFile $file]]]
    set description [dom::getAttribute $domNode description]
    set time [dom::getAttribute $domNode time]
    return [list $file $description $time]
}

proc ::apmanager::addConfigFileToBackUp { file domNode } {
    set confNode \
	    [dom::document createElement $domNode file]
    dom::setAttribute $confNode originalLocation $file
    set f [open $file]
    set text [read $f]
    dom::document createTextNode $confNode $text
    close $f
}

proc ::apmanager::processConfFileForInclude {file {includeRoot {}}} {
    update idletasks
    lappend fileList $file
    set f [open $file]
    set lines [split [read $f] \n]
    close $f
    foreach line $lines {
	switch [lindex [::apachePrettyDumper::getTypeOfLine $line] 0] {
	    directive {
		if [regexp -nocase -- ^serverroot [string trim $line]] {
		    set elements \
			    [ ::apacheparserutils::getElements $line]
		    set includeRoot [join [lindex $elements 1]]
		}
		if [regexp -nocase -- (^resourceconfig|^accessconfig) [string trim $line]] {
		    set elements \
			    [ ::apacheparserutils::getElements $line]
		    set includeFile [join [lindex $elements 1]]
		    switch [file pathtype $includeFile] {
			absolute - relative {
			    
			    # file join /5 /6 == /6
			    
			    set includeFile [::helper::fileNativename \
				    [file join $includeRoot $includeFile]]
			    if ![string match /dev/null $includeFile] {
	foreach myfile [processConfFileForInclude $includeFile $includeRoot] {
	lappend fileList $myfile
}
			    }
			}
		    }      		       
		}
	    } include  {
		set elements \
			[::apacheparserutils::getElements $line]
		set includeFile [join [lindex $elements 1] ]
		switch [file pathtype $includeFile] {
		    absolute - relative {
			set includeFile [::helper::fileNativename \
				[file join $includeRoot $includeFile]]
				foreach myfile [processConfFileForInclude $includeFile $includeRoot] {
	lappend fileList $myfile
}
		    }
		}
	    }
	}
    }
    return $fileList
}

# Returns list with
# {{name location} {name location ...}

proc ::apmanager::getListOfConfigFilesToBackUp { file } {
    return [processConfFileForInclude $file]
}

proc ::apmanager::getListOfLogFiles { file } {
    return [processConfFileForLogFiles $file]
}


proc ::apmanager::restoreBackUp {text} {
    set domNode [dom::getElements [dom::DOMImplementation parse $text]]
    foreach fileNode [dom::myGetElementsByTagName $domNode file] {
	set f [open [dom::getAttribute $fileNode originalLocation] w]
	set text [dom::getText $fileNode]
	regsub -all {\\\\\\\\} $text {\\} text
	update idletasks
	regsub -all {\\\\} $text {} text
	update idletasks
	regsub -all {\\\[} $text {[} text
	update idletasks
	regsub -all {\\\]} $text {]} text
	puts $f $text
	close $f
    }
    dom::deleteDoc $domNode
}


proc ::apmanager::processConfFileForLogFiles {file {includeRoot {}}} {
    set fileList {}
    set f [open $file]
    set lines [split [read $f] \n]
    close $f
    foreach line $lines {
	switch [lindex [::apachePrettyDumper::getTypeOfLine $line] 0] {
	    directive {
		if [regexp -nocase -- ^serverroot [string trim $line]] {
		    set elements \
			    [ ::apacheparserutils::getElements $line]
		    set includeRoot [join [lindex $elements 1]]
		}
		if [regexp -nocase -- (^resourceconfig|^accessconfig) [string trim $line]] {
		    set elements \
			    [ ::apacheparserutils::getElements $line]
		    set includeFile [join [lindex $elements 1]]
		    switch [file pathtype $includeFile] {
			absolute - relative {
			    
			    # file join /5 /6 == /6
			    
			    set includeFile [::helper::fileNativename \
				    [file join $includeRoot $includeFile]]
			    if ![string match /dev/null $includeFile] {
	foreach myfile [processConfFileForLogFiles $includeFile $includeRoot] {
	lappend fileList $myfile
}
			
			    }
			}
		    }      		       
		}
		if [regexp -nocase -- (^customlog|^errorlog) [string trim $line]] {
		    set elements \
			    [ ::apacheparserutils::getElements $line]
		    set logFile [lindex $elements 1]
		    switch [file pathtype $logFile] {
			absolute - relative {
			    lappend fileList [::helper::fileNativename \
				    [file join $includeRoot $logFile]]
				
			}
		    }      		       
		}
	    } include  {
		set elements \
			[::apacheparserutils::getElements $line]
		set includeFile [join [lindex $elements 1] ]
		switch [file pathtype $includeFile] {
		    absolute - relative {
			set includeFile [::helper::fileNativename \
				[file join $includeRoot $includeFile]]
	foreach myfile [processConfFileForLogFiles $includeFile $includeRoot] {
	lappend fileList $myfile
}
					    }
		}
	    }
	}
    }
    return $fileList
}