#!/bin/bash
#  net/webdav - WebDAV support

set -e

lib_load 'net/tool/rsync'


######
# Settings

net_webdav_client_packages=( cadaver )


######
# Library Configuration

net_webdav_config_init() {
	lib_setting_vars webdav_host
	lib_setting_vars --null webdav_port
	lib_setting_vars --null webdav_root
	webdav_host=localhost

	# WebDAV property namespace
	lib_setting_vars --null webdav_namespace

	lib_setting_vars -ro webdav_netrc
	lib_setting_vars -ro webdav_stagedir

	lib_setting_vars -ro webdav_exportdir
	webdav_exportdir='.'

}

net_webdav_config_check() {
	webdav_netrc="${webdav_netrc:-${HOME}/.netrc}"

	webdav_stagedir="${webdav_stagedir:-$script_tempdir/stage}"
}


######
# Internal Functions

run_cadaver() {
	run_pushd "$webdav_stagedir"
	run cadaver "$@"
	run_popd
}

pipe_to_cadaver() {
	local tmp
	tmp=$(cmd_tempfile)
	"$@" >"$tmp"
	debug "running cadaver script:"$'\n'"$(<"$tmp")"
	run_cadaver <"$tmp"
}

webdav_filename() {
	echo "$1" \
		| ( iconv -f utf-8 -t ascii//translit \
			|| error "$1: unable to encode name" ) \
		| sed -e 's, - ,-,g' -e 's, ,-,g' -e 's,\?,-,g'
}


######
# WebDAV CLI

# webdav_dispatch() - Runs a webdav command
webdav_dispatch() { lib_cmd_dispatch webdav "$@"; }

webdav_usage() {
	cat <<USAGE
<cmd> ...
WebDAV Commands:
	host ...			Host credential commands
	stage ...			Staging directory commands
	remote ...			WebDAV remote/server commands
USAGE
}

######
# .netrc Management

webdav_host() { cmd_dispatch "$@"; }

webdav_host_usage() {
	cat <<USAGE
WebDAV Host Commands:
	init				Creates empty host credential file
	add <host> <user> <passwd>	Adds credentials for a host
	delete <host>			Removes credentials for a host
USAGE
}

webdav_host_init() {
	touch "$webdav_netrc"
	chmod 600 "$webdav_netrc"
}

webdav_host_add() {
	has_args "3" "$@"
	local name=$1
	local user=$2
	local pass=$3
	echo "machine $name login $user password $pass" >> "$webdav_netrc"
}

webdav_host_delete() {
	has_args "1" "$@"
	local name=$1
	local tmp
	tmp=$(cmd_tempfile)
	grep -v "^machine $name " "$webdav_netrc" >"$tmp"
	run mv "$tmp" "$webdav_netrc"
}


######
# Script generation

webdav_script_open() {
	echo "lcd '$webdav_stagedir'"

	local url="$webdav_host"
	[ -z "$webdav_port" ] || url="$url:$webdav_port"
	echo "open '$url'"

	[ -z "$webdav_namespace" ] || echo "set namespace '$webdav_namespace'"
}

webdav_script_close() {
	echo close
}

webdav_script_import_dir() {
	echo "echo '$1: creating collection...'"
	echo "mkcol '$1'"
}
webdav_script_import_file() {
	echo "echo '$2: importing...'"
	echo "put '$1' '$2'"
}
webdav_script_import_symlink() {
	debug "$2: skipping symlink ($3)"
}
webdav_script_import_default() {
	error "$2: unknown item type"
}

webdav_script_import_item() {
	local src=$1
	local dst="$webdav_root${src#$webdav_stagedir}"

	if [ -d "$src" ]; then
		webdav_script_import_dir "$dst"
	elif [ -f "$src" ]; then
		webdav_script_import_file "$src" "$dst"
	elif [ -L "$src" ]; then
		local tgt
		tgt=$(readlink "$src")
		webdav_script_import_symlink "$src" "$dst" "$tgt"
	else
		webdav_script_import_default "$src" "$dst"
	fi
}

webdav_script_import() {
	info "searching for files to stage..."
	local -a files
	webdav_stage_find files "$@"

	echo 'echo "webdav import: connecting to server..."'
	webdav_script_open

	for_each webdav_script_import_item "${files[@]}"

	echo 'echo "webdav import: cleaning up..."'
	webdav_script_close

	echo 'echo "webdav import: ... done."'

	info "webdav import: ... found ${#files[@]} items!"
}

webdav_script_export() {
	webdav_script_open
	# TODO
	webdav_script_close
}


######
# WebDAV Server Interface

webdav_remote() { cmd_dispatch "$@"; }

webdav_remote_usage() {
	cat <<USAGE
...
WebDAV Remote Commands:
	import [<path>+]		Imports from staging to WebDAV server
	export [<path>+]		Exports from WebDAV server to staging
USAGE
}

webdav_remote_import() { pipe_to_cadaver webdav_script_import "$@"; }
webdav_remote_export() { pipe_to_cadaver webdav_script_export "$@"; }


######
# WebDAV Staging interface

webdav_stage_filename() { echo "$webdav_stagedir/$(webdav_filename "$1")"; }
webdav_stage_relname() { echo "${1#$webdav_stagedir}"; }


webdav_stage() { cmd_dispatch "$@"; }

webdav_stage_usage() {
	cat <<USAGE
<cmd> ...
WebDAV Staging Commands:
	list [<path>+]			Lists files in stanging directory
	import <path>+			Imports files to staging directory
	export [<path>+]		Exports files to \$webdav_exportdir'
					(default: $webdav_exportdir)
	shell [<path>]			Starts shell in "\$stagedir\$path"

WebDAV Staging Synchronization:
	push [<path>+]			Uploads files from staging to server
	fetch [<path>+]			Downloads files from server to staging
USAGE
}

webdav_stage_find() {
	min_args 1 "$@"
	local var=$1
	shift

	local -a wsf_files=( "$@" )
	[ "$*" ] || wsf_files=( "" )
	list_map webdav_stage_filename wsf_files

	file_find wsf_files "${wsf_files[@]}"
	eval "$var=( \"\${wsf_files[@]}\" )"
}
webdav_stage_findrel() {
	local var=$1
	webdav_stage_find "$@"
	list_map webdav_stage_relname $var
}

webdav_stage_shell() {
	local path=$1
	run_pushd "$(webdav_stage_filename "$path")"
	$SHELL
	run_popd
}

webdav_stage_list() {
	local -a file_find_opts=( -type f )

	local -a files
	webdav_stage_findrel files "$@"

	local IFS=$'\n'
	echo "${files[*]}"
}

webdav_stage_import() {
	min_args 1 "$@"
	local -a files
	file_find files "$@"

	run_mkdir "$webdav_stagedir"
	for_each webdav_stage_import_file "${files[@]}"
}

webdav_stage_import_file() {
	local src=$1
	local dst
	dst="$(webdav_stage_filename "$src")"
	run_mkdir "$(dirname "$dst")"
	rsync_run --archive "$src" "$dst"
}

webdav_stage_export() {
	: # TODO
}


webdav_stage_push() {
	local ssh_host="$webdav_host"
	run_ssh mkdir -p "$webdav_stagedir"

	if [ "$*" ]; then
		for_each webdav_stage_push_part "$@"
	else
		webdav_stage_push_part "/"
	fi
}

webdav_stage_push_part() {
	has_args 1 "$@"
	local part=$1
	[ "${part#/}" != "$part" ] || part="/$part"

	local src="$webdav_stagedir$part"
	local dst="$webdav_host:$webdav_stagedir$part"

	local -a opts=( --archive --checksum --progress --stats --links )
	rsync_run "${opts[@]}" "$src" "$dst"
}

webdav_stage_fetch() {
	: # TODO
}

View the Developer Guide Index

View the Reference Manual Index


Generated on Fri Jul 28 14:35:56 PDT 2017 by mcsh d14 v0.23.0.