/*
* $Header: /home/cvspublic/jakarta-slide/src/webdav/client/src/org/apache/webdav/cmd/Slide.java,v 1.29 2001/06/09 00:17:59 remm Exp $
* $Revision: 1.29 $
* $Date: 2001/06/09 00:17:59 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.webdav.cmd;
import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileNotFoundException;
import java.util.Date;
import java.util.Stack;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.net.URL;
import java.net.MalformedURLException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.HttpException;
import org.apache.util.HttpURL;
import org.apache.webdav.lib.WebdavResource;
import org.apache.webdav.lib.methods.*;
import org.apache.webdav.lib.properties.AclProperty;
import org.apache.webdav.lib.Ace;
import org.apache.webdav.lib.Privilege;
/**
* The Slide client, the command line version for WebDAV client.
*
* @author <a href="mailto:jericho@thinkree.com">Park, Sung-Gu</a>
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
* @author <a href="mailto:daveb@miceda-data.com">Dave Bryson</a>
* @author Dirk Verbeeck
*/
public class Slide {
/**
* The version information for the Slide client.
*/
public final static String version = "Slide client v1.0 alpha";
/**
* The http URL on the client connection.
*/
private HttpURL httpURL;
/**
* The http URL string on the command line by the user given.
*/
private String stringUrl;
/**
* The path for the display information.
*/
private String path = "";
/**
* The current path on the local system.
*/
private File dir = new File(".");
/**
* The command prompt for the display information.
*/
private String commandPrompt = null;
/**
* The debug level.
*/
private int debugLevel = 0;
/**
* A space mark.
*/
public static final String SP = " ";
/**
* The main function to start a Slide client.
*/
public static void main(String args[]) {
final Slide slide = new Slide();
String argOptions = null;
// parse arguments
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("-")) {
if (argOptions != null)
argOptions += args[i].substring(1);
else
argOptions = args[i];
} else {
slide.stringUrl = args[i];
}
}
// print options
if (argOptions != null) {
char option;
for (int i = 0; i < argOptions.length(); i++) {
option = argOptions.charAt(i);
switch (option) {
case '-':
break;
case 'h':
printCmdLineUsage();
break;
case 'v':
System.out.println(version);
break;
case 'd':
slide.debugLevel = Integer.MAX_VALUE;
break;
default:
System.exit(-1);
}
}
}
Thread inner =
new Thread(
new Runnable() {
public void run() {
// Start command line client.
slide.processCommands();
}});
inner.start();
}
/**
* Parse the Slide client commands and execute the requests.
*/
public void processCommands() {
// The WebDAV resource.
WebdavResource webdavResource = null;
// Command input
String command = null;
BufferedReader in =
new BufferedReader(new InputStreamReader(System.in));
try {
if (stringUrl != null) {
// Set up for processing WebDAV resources from command line.
try {
httpURL = new HttpURL(stringUrl);
webdavResource = new WebdavResource(httpURL);
webdavResource.setDebug(debugLevel);
setPath(webdavResource.getPath());
} catch (HttpException we) {
// Check authorization and try it again.
if (we.getStatusCode() ==
HttpStatus.SC_UNAUTHORIZED) {
System.out.print("UserName: ");
String userName = in.readLine();
if (userName != null && userName.length() > 0) {
userName = userName.trim();
System.out.print("Password: ");
String password = in.readLine();
if (password != null)
password= password.trim();
try {
// It should be used like this way.
httpURL.setUserInfo(userName, password);
if (webdavResource != null) {
webdavResource.setHttpURL(httpURL);
} else {
webdavResource =
new WebdavResource(httpURL);
webdavResource.setDebug(debugLevel);
}
setPath(webdavResource.getPath());
} catch (HttpException e) {
System.err.println("Warning: "
+ e.getMessage());
httpURL = null;
} catch (IOException e) {
System.err.println("Error: Check! "
+ e.getMessage());
httpURL = null;
}
} else {
// Make the prompt display by default.
httpURL = null;
}
} else {
System.err.println("Warning: " + we.getMessage());
httpURL = null;
}
} catch (IOException e) {
System.err.println("Error: Check! " + e.getMessage());
httpURL = null;
}
}
updatePrompt(getPath());
do {
System.out.print(getPrompt());
command = in.readLine();
if (command == null) {
// Normally exit the program.
// Because the input by user is EOF.
System.exit(0);
} else {
command = command.trim();
}
if (command.length() <= 0)
continue;
StringTokenizer st = new StringTokenizer(command);
String todo = st.nextToken();
Stack params = new Stack();
while (st.hasMoreTokens()) {
params.push(st.nextToken());
}
if (todo.equalsIgnoreCase("open") ||
todo.equalsIgnoreCase("connect")) {
String inputUrl = null;
switch (params.size()) {
case 0:
System.out.print("Enter http URL: ");
inputUrl = in.readLine();
if (inputUrl == null) {
continue;
} else {
inputUrl = inputUrl.trim();
}
if (inputUrl.length() <= 0)
// Do not go further.
continue;
break;
case 1:
inputUrl = (String) params.pop();
break;
default:
System.err.println
("[Help] open " +
"http://hostname[:port][/path]");
continue;
}
try {
// Set up for processing WebDAV resources
httpURL = new HttpURL(inputUrl);
if (webdavResource == null) {
webdavResource = new WebdavResource(httpURL);
webdavResource.setDebug(debugLevel);
} else {
webdavResource.close();
webdavResource.setHttpURL(inputUrl);
}
setPath(webdavResource.getPath());
} catch (HttpException we) {
if (we.getStatusCode() ==
HttpStatus.SC_UNAUTHORIZED) {
System.out.print("UserName: ");
String userName = in.readLine();
if (userName != null && userName.length() > 0) {
userName = userName.trim();
System.out.print("Password: ");
String password = in.readLine();
if (password != null)
password= password.trim();
try {
try {
if (webdavResource != null)
webdavResource.close();
} catch (IOException e) {
} finally {
httpURL = null;
webdavResource = null;
}
httpURL = new HttpURL(inputUrl);
// It should be used like this way.
httpURL.setUserInfo(userName, password);
if (webdavResource != null) {
webdavResource.setHttpURL(inputUrl);
} else {
webdavResource =
new WebdavResource(httpURL);
webdavResource.setDebug(debugLevel);
}
setPath(webdavResource.getPath());
} catch (HttpException e) {
System.err.println("Warning: "
+ e.getMessage());
httpURL = null;
} catch (IOException e) {
System.err.println("Error: Check! "
+ e.getMessage());
httpURL = null;
}
} else {
// make the prompt display by default.
httpURL = null;
}
} else {
System.err.println("Error: " + we.getMessage());
httpURL = null;
}
} catch (IOException e) {
System.err.println("Error: Check! " + e.getMessage());
httpURL = null;
}
updatePrompt(getPath());
} else
if (todo.equalsIgnoreCase("exit") ||
todo.equalsIgnoreCase("quit") ||
todo.equalsIgnoreCase("q") ||
todo.equalsIgnoreCase("bye")) {
break;
} else
if (todo.equalsIgnoreCase("help") ||
todo.equalsIgnoreCase("h") ||
todo.equalsIgnoreCase("?")) {
printSlideClientUsage();
} else
if (todo.equalsIgnoreCase("lpwd")) {
System.out.println(dir.getCanonicalPath());
} else
if (todo.equalsIgnoreCase("lcd")) {
if (params.size() == 0) {
System.out.println(dir.getCanonicalPath());
} else
if (params.size() == 1) {
String path = (String) params.pop();
File anotherDir = (path.startsWith("/") ||
path.startsWith("\\")) ? new File(path) :
new File(dir.getCanonicalPath(), path);
if (anotherDir.isDirectory()) {
dir = anotherDir;
} else {
System.err.println("Warning: Not found the path");
}
}
} else
if (todo.equalsIgnoreCase("lls") ||
todo.equalsIgnoreCase("ldir")) {
String path = null;
// set default option.
char option = 'F';
while (!params.empty()) {
String token = (String) params.pop();
// parse the input token.
if (token != null) {
if (!token.startsWith("-")) {
path = token;
} else {
if (token.indexOf('l') > 0)
option = 'l';
}
}
}
File temp = (path != null) ? new File(dir, path) : dir;
if (!temp.exists()) {
System.err.println("Warning: Not found the path");
continue;
}
String[] list = temp.list();
// TODO: consider of options like '-a' for all and so on.
switch (option) {
case 'l':
for (int i = 0; i < list.length; i++) {
String s = list[i];
File file = new File(temp, s);
for (int j = 0; j < 4; j++) {
switch (j) {
case 0:
// Print the filename.
System.out.print(s);
for (int k = list[i].length();
k < 35; k++)
System.out.print(SP);
break;
case 1:
s = Long.toString(file.length());
for (int k = 10 - s.length();
k > 0 ; k--)
System.out.print(SP);
// don't cut the size.
System.out.print(s + SP);
break;
case 2:
// cut the description.
s = file.isDirectory() ?
"DIR" : "";
System.out.print(SP +
((s.length() > 5) ?
s.substring(0, 5) : s));
for (int k = s.length(); k < 5; k++)
System.out.print(SP);
break;
case 3:
s = new SimpleDateFormat().format(
new Date(file.lastModified()));
System.out.print(SP + s);
default:
}
}
// Start with a new line.
System.out.println();
}
break;
case 'F':
int i = 0;
for (; i < list.length; i++) {
System.out.print(list[i] + SP);
for (int j = list[i].length();
j < 25; j++) {
System.out.print(SP);
}
if (i % 3 == 2)
System.out.println();
}
if (list.length > 0 && i % 3 != 0) {
System.out.println();
}
break;
default:
} // end of switch
} else
if (todo.equalsIgnoreCase("options")) {
int count = params.size();
String param = null;
if (count > 0)
param = (String) params.pop();
try {
boolean succeeded = false;
if (param != null) {
if (!param.startsWith("/")) {
httpURL = new HttpURL(param);
Enumeration enum = null;
try {
// OPTIONS business logic
enum =
WebdavResource.optionsMethod(httpURL);
while (enum.hasMoreElements()) {
System.out.print(enum.nextElement());
if (enum.hasMoreElements()) {
System.out.print(", ");
} else {
System.out.println();
}
}
} catch (HttpException we) {
if (we.getStatusCode() ==
HttpStatus.SC_UNAUTHORIZED) {
System.out.print("UserName: ");
String userName = in.readLine();
if (userName != null &&
userName.length() > 0) {
userName = userName.trim();
System.out.print("Password: ");
String password = in.readLine();
if (password != null)
password= password.trim();
try {
// OPTIONS business logic
httpURL.setUserInfo(userName,
password);
enum = WebdavResource.
optionsMethod(httpURL);
while (
enum.hasMoreElements()) {
System.out.print
(enum.nextElement());
if (enum.
hasMoreElements()) {
System.out.print
(", ");
} else {
System.out.println();
}
}
} catch (Exception e) {
System.err.println("Error: "
+ e.getMessage());
}
}
} else {
System.err.println("Error: " +
we.getMessage());
}
} catch (IOException e) {
System.err.println(
"Error: Check! " + e.getMessage());
}
httpURL = null;
continue;
} else
if (webdavResource != null) {
succeeded =
webdavResource.optionsMethod(param);
} else {
System.out.println("Not connected yet.");
}
} else
if (webdavResource != null) {
succeeded = webdavResource.optionsMethod("*");
} else {
System.out.println("Not connected yet.");
}
if (succeeded) {
System.out.print
("Allowed methods by http OPTIONS: ");
Enumeration allowed =
webdavResource.getAllowedMethods();
while (allowed.hasMoreElements()) {
System.out.print(allowed.nextElement());
if (allowed.hasMoreElements())
System.out.print(", ");
}
Enumeration davCapabilities =
webdavResource.getDavCapabilities();
if (davCapabilities.hasMoreElements())
System.out.print("\nDAV: ");
while (davCapabilities.hasMoreElements()) {
System.out.print
(davCapabilities.nextElement());
if (davCapabilities.hasMoreElements())
System.out.print(", ");
}
System.out.println();
}
} catch (HttpException we) {
System.err.println("Warning: " + we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " + e.getMessage());
}
} else
// Check the status of connection
if (webdavResource == null) {
System.out.println("Not connected yet.");
continue;
} else
if (todo.equalsIgnoreCase("close")) {
try {
webdavResource.close();
} catch (IOException e) {
} finally {
// Make sure the connection closed.
httpURL = null;
webdavResource = null;
}
updatePrompt(getPath());
} else
if (todo.equalsIgnoreCase("url")) {
try {
System.out.println
(webdavResource.getHttpURLExceptForUserInfo());
} catch (MalformedURLException mue) {
System.err.println("Warning: " + mue.getMessage());
}
} else
if (todo.equalsIgnoreCase("status")) {
System.out.println(webdavResource.getStatusMessage());
} else
if (todo.equalsIgnoreCase("pwc") ||
todo.equalsIgnoreCase("pwd")) {
System.out.println(getPath());
} else
if (todo.equalsIgnoreCase("cc") ||
todo.equalsIgnoreCase("cd")) {
if (params.size() == 0) {
System.out.println(getPath());
} else
if (params.size() == 1) {
String cdPath = checkUri((String) params.pop() + "/");
try {
webdavResource.setPath(cdPath);
if (webdavResource.exists()) {
if (webdavResource.isCollection()) {
setPath(webdavResource.getPath());
} else {
System.err.println(
"Warning: Not a collection");
}
} else {
System.err.println
("Warning: Not found the path");
}
} catch (HttpException we) {
if (we.getStatusCode() ==
HttpStatus.SC_UNAUTHORIZED) {
System.out.print("UserName: ");
String userName = in.readLine();
if (userName != null &&
userName.length() > 0) {
userName = userName.trim();
System.out.print("Password: ");
String password = in.readLine();
if (password != null)
password= password.trim();
try {
// It should be used like this way.
httpURL.setUserInfo(userName,
password);
webdavResource.close();
webdavResource =
new WebdavResource(httpURL);
webdavResource.setDebug(debugLevel);
setPath(webdavResource.getPath());
} catch (HttpException e) {
System.err.println("Warning: "
+ e.getMessage());
httpURL = null;
} catch (IOException e) {
System.err.println("Error: Check! "
+ e.getMessage());
httpURL = null;
}
updatePrompt(getPath());
}
} else {
System.err.println
("Error: Couldn't change the collection"
+ we.getMessage());
}
} catch (IOException e) {
System.err.println(
"Error: Check! " + e.getMessage());
httpURL = null;
}
updatePrompt(getPath());
}
} else
if (todo.equalsIgnoreCase("ls") ||
todo.equalsIgnoreCase("dir")) {
String path = null;
// set default options.
char[] options = { '-', 'F' };
while (!params.empty()) {
// get the input token.
String token = (String) params.pop();
// parse the input token.
if (token != null) {
if (!token.startsWith("-")) {
// FIXME: in the case of the child-resource?
path = checkUri(token + "/");
} else {
options = token.toCharArray();
}
}
}
try {
// Check that the path is ok.
if (path != null) {
webdavResource.setPath(path);
} else {
path = checkUri("./");
webdavResource.setPath(path);
}
} catch (HttpException we) {
if (webdavResource.getStatusCode() ==
HttpStatus.SC_METHOD_NOT_ALLOWED) {
System.err.println
("Warning: Not WebDAV-enabled?");
} else {
System.err.println("failed. " +
webdavResource.getStatusMessage());
}
// Gotten error, do not go further!
continue;
}
// FIXME: do not loop for the repeated options.
for (int o = 1; o < options.length; o++) {
switch (options[o]) {
case 'l':
try {
Vector list = webdavResource.listBasic();
for (int i = 0; i < list.size(); i++) {
String[] longFormat =
(String []) list.elementAt(i);
for (int j = 0;
j < longFormat.length; j++) {
String s = longFormat[j];
int len = s.length();
switch (j) {
case 0:
System.out.print(s);
for (int k = len; k < 20; k++)
System.out.print(SP);
break;
case 1:
for (int k = 10 - len;
k > 0 ; k--)
System.out.print(SP);
// don't cut the size.
System.out.print(s + SP);
break;
case 2:
// cut the description.
System.out.print(SP +
((len > 20) ?
s.substring(0, 20) : s));
for (int k = len; k < 20; k++)
System.out.print(SP);
break;
case 3:
default:
System.out.print(SP + s);
}
}
// Start with a new line.
System.out.println();
}
} catch (HttpException we) {
System.err.println("Warning: "
+ we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " +
e.getMessage());
}
break;
case 'F':
String[] list = webdavResource.list();
int i = 0;
for (; i < list.length; i++) {
System.out.print(list[i] + SP);
for (int j = list[i].length();
j < 25; j++) {
System.out.print(SP);
}
if (i % 3 == 2)
System.out.println();
}
if (list.length > 0 && i % 3 != 0)
System.out.println();
break;
default:
} // end of switch
}
} else
if (todo.equalsIgnoreCase("grant")) {
int count = params.size();
String principal=null;
String to=null;
String path=null;
String on=null;
String permission=null;
String namespace=null;
if (count==3) { // grant <permission> to <principal>
principal=(String)params.pop();
to=(String)params.pop();
path=checkUri(webdavResource.getPath());
on="on";
permission=(String)params.pop();
namespace=null;
} else if (count==4) { // grant <namespace> <permission> to <principal>
principal=(String)params.pop();
to=(String)params.pop();
path=checkUri(webdavResource.getPath());
on="on";
permission=(String)params.pop();
namespace=(String)params.pop();
} else if (count==5) { // grant <permission> on <path> to <principal>
principal=(String)params.pop();
to=(String)params.pop();
path=checkUri((String)params.pop());
on=(String)params.pop();
permission=(String)params.pop();
namespace=null;
} else if (count==6) { // grant <namespace> <permission> on <path> to <principal>
principal=(String)params.pop();
to=(String)params.pop();
path=checkUri((String)params.pop());
on=(String)params.pop();
permission=(String)params.pop();
namespace=(String)params.pop();
}
if (!"to".equalsIgnoreCase(to) || !"on".equalsIgnoreCase(on)) {
System.out.println("Syntax: grant <namespace> <permission> on <path> to <principal>");
continue;
}
if (namespace==null) {
namespace=resolveNamespace(permission);
if (namespace==null) {
System.out.println("Could not resolve namespace for permission " + permission);
continue;
}
}
grant(webdavResource, namespace, permission, path, principal);
} else
if (todo.equalsIgnoreCase("acl")) {
String path=null;
AclProperty acl=null;
int count = params.size();
if (count>1) {
System.out.print("acl has a maximum of 1 argument");
continue;
}
if (count==1) {
path=checkUri((String)params.pop());
}
else {
path=webdavResource.getPath();
}
acl = webdavResource.aclfindMethod(path);
if (acl==null)
{
System.out.print("Error: PropFind didn't return an AclProperty!");
continue;
}
System.out.println();
showAces(path, acl.getAces());
} else
if (todo.equalsIgnoreCase("propget") ||
todo.equalsIgnoreCase("propfind")) {
// FIXME: some work is still needed.
int count = params.size();
if (count <= 1) {
System.out.print("Propget/propfind requires at least 2 arguments");
continue;
}
Vector properties = new Vector();
for (int i = 0; i < count-1; i++) {
String property = (String) params.pop();
properties.addElement(property);
}
String path = checkUri((String) params.pop());
try {
System.out.print("Getting properties '" +
path + "': ");
Enumeration propertyValues =
webdavResource.propfindMethod(path, properties);
if (propertyValues.hasMoreElements()){
while (propertyValues.hasMoreElements()){
System.out.println(
propertyValues.nextElement());
}
} else {
System.err.println("failed.");
System.err.println(
webdavResource.getStatusMessage());
}
} catch (HttpException we) {
System.err.println("Warning: " + we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " +
e.getMessage());
}
} else
if (todo.equalsIgnoreCase("propput") ||
todo.equalsIgnoreCase("proppatch")) {
if (params.size() == 3) {
String propertyValue = (String) params.pop();
String propertyName = (String) params.pop();
String path = checkUri((String) params.pop());
try {
System.out.print("Putting property(" +
propertyName + ", " + propertyValue +
") to '" + path + "': ");
if (webdavResource.proppatchMethod(
path, propertyName, propertyValue)) {
System.out.println("succeeded.");
} else {
System.err.println("failed.");
System.err.println(
webdavResource.getStatusMessage());
}
} catch (HttpException we) {
System.err.println("Warning: " + we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " +
e.getMessage());
}
} else {
System.out.print("Propput/proppatch requires 3 arguments");
}
} else
// TODO: more than 2, the mput command is easy to use.
if (todo.equalsIgnoreCase("put")) {
int count = params.size();
if (count == 1 || count == 2) {
String dest = (String) params.pop();
dest = dest.indexOf(":") > 1 ? dest : checkUri(dest);
String src = (count == 1) ?
HttpURL.getName(dest) : (String) params.pop();
try {
if ((count == 2 && src.indexOf(":") > 1) ||
count == 1 && dest.indexOf(":") > 1) {
URL url = new URL(count == 1 ? dest : src);
System.out.print("Uploading '" +
((count == 2) ? src : dest) +
"' to '" + ((count == 2) ?
dest : src) + "': ");
if (webdavResource.putMethod(dest, url)) {
System.out.println("succeeded.");
} else {
System.err.println("failed.");
}
continue;
}
File file = new File(dir.getCanonicalPath(), src);
if (file.exists()) {
System.out.print("Uploading '" + src +
"' to '" + dest + "': ");
if (webdavResource.putMethod(dest, file)) {
System.out.println("succeeded.");
} else {
System.err.println("failed.");
System.err.println(
webdavResource.getStatusMessage());
}
} else
System.err.println
("Warning: File not exists");
} catch (MalformedURLException mue) {
System.err.println("Warning: " + mue.getMessage());
} catch (HttpException we) {
System.err.println("Warning: " + we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " +
e.getMessage());
}
}
} else
// TODO: more than 2, the mget command is easy to use.
if (todo.equalsIgnoreCase("get")) {
int count = params.size();
if (count == 1 || count == 2) {
// The resource on the remote.
String src = null;
// The file on the local.
String dest = null;
if (count == 1) {
src = checkUri((String) params.pop());
dest = HttpURL.getName(src);
} else {
dest = (String) params.pop();
src = checkUri((String) params.pop());
}
try {
// For the overwrite operation;
String y = "y";
File file = new File(dest);
// Checking the local file.
if (file.exists()) {
System.out.print("Aleady exists. " +
"Do you want to overwrite it(Y/n)? ");
y = in.readLine();
}
if (y.trim().equalsIgnoreCase("y") ||
(y != null && y.length() == 0)) {
System.out.print("Downloading '" + src +
"' to '" + dest + "': ");
if (webdavResource.getMethod(src, file)) {
System.out.println("succeeded.");
} else {
System.err.println("failed.");
System.err.println(
webdavResource.getStatusMessage());
}
}
} catch (HttpException we) {
System.err.println("Warning: " + we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " +
e.getMessage());
}
}
} else
if (todo.equalsIgnoreCase("delete") ||
todo.equalsIgnoreCase("del") ||
todo.equalsIgnoreCase("rm")) {
int count = params.size();
for (int i = 0; i < count; i++) {
String path = checkUri((String) params.pop());
try {
System.out.print("Deleting '" + path + "': ");
if (webdavResource.deleteMethod(path)) {
System.out.println("succeeded.");
} else {
System.err.println("failed.");
System.err.println(
webdavResource.getStatusMessage());
}
} catch (HttpException we) {
System.err.println("Warning: " + we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " +
e.getMessage());
}
}
} else
if (todo.equalsIgnoreCase("mkcol") ||
todo.equalsIgnoreCase("mkdir")) {
int count = params.size();
for (int i = 0; i < count; i++) {
String path = checkUri((String) params.pop());
try {
System.out.print("Making '" + path +
"' collection: ");
if (webdavResource.mkcolMethod(path)) {
System.out.println("succeeded.");
} else {
System.err.println("failed.");
System.err.println(
webdavResource.getStatusMessage());
}
} catch (HttpException we) {
System.err.println("Warning: " + we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " +
e.getMessage());
}
}
} else
if (todo.equalsIgnoreCase("copy") ||
todo.equalsIgnoreCase("cp")) {
if (params.size() == 2) {
String dst = checkUri((String) params.pop());
String src = checkUri((String) params.pop());
try {
System.out.print("Copying '" + src +
"' to '" + dst + "': ");
if (webdavResource.copyMethod(src, dst)) {
System.out.println("succeeded.");
} else {
System.err.println("failed.");
System.err.println(
webdavResource.getStatusMessage());
}
} catch (HttpException we) {
System.err.println("Warning: " + we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " +
e.getMessage());
}
}
} else
if (todo.equalsIgnoreCase("move") ||
todo.equalsIgnoreCase("mv")) {
if (params.size() == 2) {
String dst = checkUri((String) params.pop());
String src = checkUri((String) params.pop());
try {
System.out.print("Moving '" + src +
"' to '" + dst + "': ");
if (webdavResource.moveMethod(src, dst)) {
System.out.println("succeeded.");
} else {
System.err.println("failed.");
System.err.println(
webdavResource.getStatusMessage());
}
} catch (HttpException we) {
System.err.println("Warning: " + we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " +
e.getMessage());
}
}
} else
if (todo.equalsIgnoreCase("lock")) {
if (params.size() == 1) {
String path = checkUri((String) params.pop());
try {
System.out.print("Locking '" + path + "': ");
if (webdavResource.lockMethod(path)) {
System.out.println("succeeded.");
} else {
System.err.println("failed.");
System.err.println(
webdavResource.getStatusMessage());
}
} catch (HttpException we) {
System.err.println("Warning: " + we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " +
e.getMessage());
}
}
} else
if (todo.equalsIgnoreCase("unlock")) {
if (params.size() == 1) {
String path = checkUri((String) params.pop());
try {
System.out.print("Unlocking '" + path + "': ");
if (webdavResource.unlockMethod(path)) {
System.out.println("succeeded.");
} else {
System.err.println("failed.");
System.err.println(
webdavResource.getStatusMessage());
}
} catch (HttpException we) {
System.err.println("Warning: " + we.getMessage());
} catch (IOException e) {
System.err.println("Error: Check! " +
e.getMessage());
}
}
} else
if (todo.equalsIgnoreCase("set")) {
if (params.size() == 2) {
String value = (String) params.pop();
String key = (String) params.pop();
if (key.equalsIgnoreCase("urlencode")) {
if (value.equalsIgnoreCase("on")) {
webdavResource.setEncodeURLs(true);
System.out.println
("URL encoding flag is on.");
} else {
webdavResource.setEncodeURLs(false);
System.out.println
("URL encoding flag is off.");
}
} else if (key.equalsIgnoreCase("debug")) {
if ((value.equalsIgnoreCase("on")) ||
(value.equalsIgnoreCase("all"))) {
debugLevel = Integer.MAX_VALUE;
webdavResource.setDebug(debugLevel);
System.out.println
("The debug flag is on (level=all).");
} else if (value.equalsIgnoreCase("off") ||
(value.equalsIgnoreCase("0"))) {
webdavResource.setDebug(debugLevel = 0);
System.out.println("The debug flag is off.");
} else {
try {
debugLevel = Integer.parseInt(value);
webdavResource.setDebug(debugLevel);
System.out.println
("The debug flag is on (level=" +
debugLevel + ").");
} catch (NumberFormatException nfe) {
System.err.println
("Invalid value, valid vlaues " +
"are 'on', 'off', <level>");
}
}
} else {
System.err.println("Invalid option.");
}
} else {
System.err.println("Error: 'set' needs at least 2 parameters");
}
} else {
System.err.println("Invalid Command.");
}
} while (true);
} catch (Exception e) {
System.err.println("Fatal Error: " + e.getMessage());
if (command != null)
System.err.println("Command input: " + command);
e.printStackTrace();
System.err.println
("Please, email to slide-user@jakarta.apache.org");
}
} // The end of processCommands().
/**
* Determine which URI to use at the prompt.
*
* @param uri the path to be set.
* @return the absolute path.
*/
private String checkUri(String uri) {
if (!uri.startsWith("/")) {
uri = getPath() + uri;
}
return normalize(uri);
}
/**
* Set the path.
*
* @param path the path string.
*/
private void setPath(String path) {
if (!path.endsWith("/")) {
path = path + "/";
}
this.path = normalize(path);
}
/**
* Get the path.
*
* @return the path string.
*/
private String getPath() {
return path;
}
/**
* Update the command prompt for the display.
*
* @param path the path string
*/
private void updatePrompt(String path) {
StringBuffer buff = new StringBuffer();
try {
buff.append("[" + httpURL.getHost().toUpperCase() + "] ");
buff.append(path);
} catch (Exception e) {
buff.append("[ Slide ]");
}
buff.append(" $ ");
commandPrompt = buff.toString();
}
/**
* Get the prompt.
*
* @return the prompt to be displayed.
*/
private String getPrompt() {
return commandPrompt;
}
/**
* Return a context-relative path, beginning with a "/", that represents
* the canonical version of the specified path after ".." and "." elements
* are resolved out. If the specified path attempts to go outside the
* boundaries of the current context (i.e. too many ".." path elements
* are present), return <code>null</code> instead.
*
* @param path the path to be normalized.
* @return the normalized path.
*/
private String normalize(String path) {
if (path == null)
return null;
String normalized = path;
// Normalize the slashes and add leading slash if necessary
if (normalized.indexOf('\\') >= 0)
normalized = normalized.replace('\\', '/');
if (!normalized.startsWith("/"))
normalized = "/" + normalized;
// Resolve occurrences of "/./" in the normalized path
while (true) {
int index = normalized.indexOf("/./");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 2);
}
// Resolve occurrences of "/../" in the normalized path
while (true) {
int index = normalized.indexOf("/../");
if (index < 0)
break;
if (index == 0)
return ("/"); // The only left path is the root.
int index2 = normalized.lastIndexOf('/', index - 1);
normalized = normalized.substring(0, index2) +
normalized.substring(index + 3);
}
// Resolve occurrences of "//" in the normalized path
while (true) {
int index = normalized.indexOf("//");
if (index < 0)
break;
normalized = normalized.substring(0, index) +
normalized.substring(index + 1);
}
// Return the normalized path that we have completed
return (normalized);
}
/**
* Print the commands options from startup
*/
private static void printCmdLineUsage() {
System.out.println("Usage: Slide [-vdh] " +
"http://hostname[:port][/path]");
System.out.println
(" Default protocol: http, port: 80, path: /");
System.out.println("Options:");
System.out.println(" -v: Print version information.");
System.out.println(" -d: Debug.");
System.out.println(" -h: Print this help message.");
System.out.println(
"Please, email bug reports to slide-user@jakarta.apache.org");
}
/**
* Print the Slide client commands for use
*/
private static void printSlideClientUsage() {
System.out.println(version + " commands:");
System.out.println(" options {http_URL|path} " +
"Print available http methods");
System.out.println(" open [http_URL] " +
"Connect to specified URL");
System.out.println(" close " +
"Close current connection");
System.out.println(" exit " +
"Exit Slide");
System.out.println(" help " +
"Print this help message");
System.out.println(" lpwd " +
"Print local working directory");
System.out.println(" lcd [path] " +
"Change local working directory");
System.out.println(" lls [-lF] [path] " +
"List contents of local directory");
System.out.println(" pwc " +
"Print working collection");
System.out.println(" cc [path] " +
"Change working collection");
System.out.println(" ls [-lF] [path] " +
"List contents of collection");
System.out.println(" url " +
"Print working URL");
System.out.println(" status " +
"Print latest http status message");
System.out.println(" get path [file] " +
"Get a resource to a file");
System.out.println(" put {URL|file} [path] " +
"Put a given file or URL to path");
System.out.println(" mkcol path ... " +
"Make new collections");
System.out.println(" delete path ... " +
"Delete resources");
System.out.println(" copy source destination " +
"Copy resource from source to destination path");
System.out.println(" move source destination " +
"Move resource from source to destination path");
System.out.println(" lock path " +
"Lock specified resource");
System.out.println(" unlock path " +
"Unlock specified resource");
System.out.println(" propget path property ... " +
"Print value of specified property");
System.out.println(" propput path property value " +
"Set property with given value");
System.out.println(" set URLencode {on|off} " +
"Set URL encoding flag, default: on");
System.out.println(" set debug {on|off|<level>} " +
"Set debug level, default: off");
System.out.println(" acl [path] " +
"Displays the ACL of path");
System.out.println(" grant [<namespace>] <permission> [on <path>] to <principal>");
System.out.println
("Aliases: help=?, open=connect, ls=dir, pwc=pwd, cc=cd, " +
"lls=ldir, copy=cp,\n move=mv, delete=del=rm, mkcol=mkdir, " +
"propget=propfind, propput=proppatch,\n exit=quit=bye");
System.out.println("Comment : Once executed, the debug mode will " +
"be active.\n\t\tBecause it's not triggered by " +
"methods yet.");
}
/**
* Sleep
*/
private static void pause(int secs) {
try {
Thread.sleep( secs * 1000 );
} catch( InterruptedException ex ) {
}
}
private String resolveNamespace(String permission)
{
String DEFAULT_NAMESPACE = "DAV:";
String SLIDE_NAMESPACE = "http://jakarta.apache.org/slide/";
String namespace=null;
if (permission==null)
return null;
if ((permission.equalsIgnoreCase("all")) ||
(permission.equalsIgnoreCase("read")) ||
(permission.equalsIgnoreCase("write")) ||
(permission.equalsIgnoreCase("read-acl")) ||
(permission.equalsIgnoreCase("write-acl")))
{
namespace=DEFAULT_NAMESPACE;
}
if ((permission.equalsIgnoreCase("read-object")) ||
(permission.equalsIgnoreCase("read-revision-metadata")) ||
(permission.equalsIgnoreCase("read-revision-content")) ||
(permission.equalsIgnoreCase("create-object")) ||
(permission.equalsIgnoreCase("remove-object")) ||
(permission.equalsIgnoreCase("lock-object")) ||
(permission.equalsIgnoreCase("read-locks")) ||
(permission.equalsIgnoreCase("create-revision-metadata")) ||
(permission.equalsIgnoreCase("modify-revision-metadata")) ||
(permission.equalsIgnoreCase("remove-revision-metadata")) ||
(permission.equalsIgnoreCase("create-revision-content")) ||
(permission.equalsIgnoreCase("modify-revision-content")) ||
(permission.equalsIgnoreCase("remove-revision-content")) ||
(permission.equalsIgnoreCase("grant-permission")) ||
(permission.equalsIgnoreCase("revoke-permission")))
{
namespace=SLIDE_NAMESPACE;
}
return namespace;
}
private boolean grant(WebdavResource webdavResource, String namespace, String permission, String path, String principal) throws HttpException, IOException
{
System.out.println("grant " + namespace + permission + " on " + path + " to " + principal);
AclProperty acl = webdavResource.aclfindMethod(path);
if (acl==null)
{
System.out.print("Error: PropFind didn't return an AclProperty!");
return false;
}
Ace[] aces=acl.getAces();
if (debugLevel>5) {
System.out.println();
System.out.println("ACL from server");
showAces(path, aces);
}
Ace ace=null;
for (int i=0; i<aces.length && (ace==null); i++)
{
if (!aces[i].isNegative() && !aces[i].isProtected()
&& !aces[i].isInherited() && aces[i].getPrincipal().equals(principal))
{
System.out.println("found ace");
ace=aces[i];
}
}
if (ace==null)
{
Ace[] oldAces=aces;
aces=new Ace[oldAces.length+1];
System.arraycopy(oldAces,0,aces,0,oldAces.length);
ace=new Ace(principal, false, false, false,null);
aces[oldAces.length]=ace;
}
Privilege privilege=new Privilege(namespace, permission, null);
ace.addPrivilege(privilege);
if (debugLevel>5) {
System.out.println();
System.out.println("ACL with updated privileges");
showAces(path, aces);
}
boolean success = webdavResource.aclMethod(path,aces);
if (!success)
System.err.println(webdavResource.getStatusMessage());
if (debugLevel>5) {
System.out.println();
System.out.println("ACL from server after update");
showAces(path, aces);
}
return success;
}
private void showAces(String path, Ace[] aces)
{
System.out.println("ACL for " + path + ":");
System.out.println("------------------------------------------------------------");
for (int i=0; i<aces.length ; i++)
{
Ace ace=aces[i];
System.out.println((!ace.isNegative()?"granted":"denied") +
" to " + ace.getPrincipal() + " " +
" (" + (ace.isProtected()?"protected":"not protected") + ")" +
" (" + (ace.isInherited()? ("inherited from '" + ace.getInheritedFrom() + "'"): "not inherited") +")");
Enumeration privileges=ace.enumeratePrivileges();
while (privileges.hasMoreElements())
{
Privilege priv=(Privilege)privileges.nextElement();
System.out.println(" " + priv.getNamespace() + priv.getName() + " " + (priv.getParameter()==null?"":("("+priv.getParameter()+")")));
}
}
System.out.println("------------------------------------------------------------");
}
}