/*
* $Header: /home/cvs/jakarta-slide/webdavclient/commandline/src/java/org/apache/webdav/cmd/Client.java,v 1.2.2.8 2004/04/28 08:59:36 ozeigermann Exp $
* $Revision: 1.2.2.8 $
* $Date: 2004/04/28 08:59:36 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.webdav.cmd;
import antlr.RecognitionException;
import antlr.TokenStreamException;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.HttpURL;
import org.apache.commons.httpclient.HttpsURL;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.util.QName;
import org.apache.webdav.lib.Ace;
import org.apache.webdav.lib.Lock;
import org.apache.webdav.lib.Privilege;
import org.apache.webdav.lib.Property;
import org.apache.webdav.lib.PropertyName;
import org.apache.webdav.lib.ResponseEntity;
import org.apache.webdav.lib.WebdavResource;
import org.apache.webdav.lib.methods.DepthSupport;
import org.apache.webdav.lib.properties.AclProperty;
import org.apache.webdav.lib.properties.LockDiscoveryProperty;
import org.apache.webdav.lib.properties.PrincipalCollectionSetProperty;
/**
* 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
*/
final class Client {
private Spool spool;
private InputStream in;
private PrintStream out;
private boolean displayPrompt = true;
/** The path for the display information. */
private String path = "";
/** The command prompt for the display information. */
private String commandPrompt = null;
/** The http URL on the client connection. */
private HttpURL httpURL;
/** The debug level. */
private int debugLevel = 0;
/** The WebDAV resource. */
private WebdavResource webdavResource = null;
/** The current path on the local system. */
private File dir = new File(".");
/////////////////////////////////////////////////////////////////
Client(InputStream in, PrintStream out)
{
this.spool = new Spool(in,out);
this.in = in;
this.out = new PrintStream(spool.getOutputStream());
updatePrompt(getPath());
}
void run()
{
while(true) {
try {
InputStream in=spool.getInputStream();
ClientLexer lexer = new ClientLexer(new DataInputStream(in));
ClientParser parser = new ClientParser(lexer);
parser.setClient(this);
parser.commands();
}
catch(TokenStreamException ex) {
handleException(ex);
}
catch(RecognitionException ex) {
handleException(ex);
}
}
// TODO test EOF ???
}
///////////////////////////////////////////////////////////////////
// Helper funtions for the parser and error handlers
///////////////////////////////////////////////////////////////////
void printInvalidCommand(String command)
{
out.println("Error: invalid command: " + command);
}
void printUsage(String command)
{
out.println("Syntax error. \"help\" for more info");
// out.println("Usage: " + command + " ...");
// out.println
// ("[Help] open " +
// "http://hostname[:port][/path]");
// out.println("Syntax: grant <namespace> <permission> on <path> to <principal>");
// out.println("Syntax: revoke <namespace> <permission> on <path> from <principal>");
// out.println("Syntax: deny <namespace> <permission> on <path> to <principal>");
// out.println("Syntax: lock <path>");
// out.println("Syntax: unlock <path>");
// out.println("Syntax: vc/VersionControl <path>");
// else out.println("Syntax: eReport path");
// else out.println("Syntax: lReport <property> \n History URLs are needed");
}
void prompt()
{
if (displayPrompt)
out.print(getPrompt());
}
void print(String line) {
out.println(line);
}
private void handleException(Exception ex)
{
if (ex instanceof HttpException) {
if (((HttpException) ex).getReasonCode() == HttpStatus.SC_METHOD_NOT_ALLOWED) {
out.println("Warning: Not WebDAV-enabled?");
}
else if (((HttpException) ex).getReasonCode() == HttpStatus.SC_UNAUTHORIZED) {
out.println("Warning: Unauthorized");
}
else {
out.println("Warning: " + ex.getMessage());
}
}
else if (ex instanceof IOException) {
out.println("Error: " + ex.getMessage());
}
else {
out.println("Fatal Error: " + ex.getMessage());
ex.printStackTrace(out);
out.println("Please, email to slide-user@jakarta.apache.org");
System.exit(-1);
}
}
/////////////////////////////////////////////////////////////////
// Commands available on the command line
/////////////////////////////////////////////////////////////////
void setEchoEnabled(boolean isEnabled)
{
spool.setEcho(isEnabled);
setDisplayPrompt(isEnabled);
// if this is an interactive client keep the prompt
if (this.in==System.in)
setDisplayPrompt(true);
}
void executeScript(String scriptname)
{
try {
FileInputStream script = new FileInputStream(scriptname);
Client scriptClient = new Client(script,out);
scriptClient.setDisplayPrompt(false);
out.println("Executing script: " + scriptname);
scriptClient.run();
out.println("Script " + scriptname + " complete.");
script.close();
}
catch (FileNotFoundException ex) {
out.println("Error: Script " + scriptname + " not found.");
}
catch (IOException ex) {
out.println("Error: " + ex.toString() + " during execution of " + scriptname);
}
}
void enableSpoolToFile(String filename)
{
out.println("Spool to file: " + filename);
try {
spool.enable(filename);
}
catch (FileNotFoundException ex) {
out.println("Error: Could not spool to file: " + filename);
disableSpoolToFile();
}
}
void disableSpoolToFile()
{
spool.disable();
out.println("Spooling disabled");
}
/** Debug level for all debug messages */
final static int DEBUG_ON = Integer.MAX_VALUE;
/** Debug level for no debug messages */
final static int DEBUG_OFF = 0;
/**
* Set the debug level
*/
void setDebug(int level)
{
this.debugLevel=level;
if (webdavResource != null) webdavResource.setDebug(debugLevel);
switch (level) {
case DEBUG_ON: out.println("The debug flag is on."); break;
case DEBUG_OFF: out.println("The debug flag is off."); break;
default: out.println("The debug level is " + level); break;
}
}
void connect(String uri)
{
out.println("connect " + uri);
try {
// Set up for processing WebDAV resources
httpURL = uriToHttpURL(uri);
if (webdavResource == null) {
webdavResource = new WebdavResource(httpURL);
webdavResource.setDebug(debugLevel);
} else {
webdavResource.close();
webdavResource.setHttpURL(httpURL);
}
setPath(webdavResource.getPath());
}
catch (HttpException we) {
if (we.getReasonCode() == HttpStatus.SC_UNAUTHORIZED) {
try {
out.print("UserName: ");
BufferedReader in =
new BufferedReader(new InputStreamReader(System.in));
String userName = in.readLine();
if ((userName==null) || (userName.length()==0)) {
disconnect();
return;
}
userName = userName.trim();
System.out.print("Password: ");
String password = in.readLine();
if (password != null)
password= password.trim();
try {
if (webdavResource != null)
webdavResource.close();
} catch (IOException e) {
} finally {
httpURL = null;
webdavResource = null;
}
httpURL = uriToHttpURL(uri);
// It should be used like this way.
httpURL.setUserinfo(userName, password);
webdavResource = new WebdavResource(httpURL);
webdavResource.setDebug(debugLevel);
setPath(webdavResource.getPath());
}
catch (Exception ex) {
handleException(ex);
httpURL = null;
webdavResource = null;
}
}
else {
handleException(we);
httpURL = null;
webdavResource = null;
}
}
catch (Exception ex) {
handleException(ex);
webdavResource = null;
httpURL = null;
}
updatePrompt(getPath());
}
void disconnect()
{
out.println("disconnect");
try {
webdavResource.close();
} catch (IOException e) {
} finally {
// Make sure the connection closed.
httpURL = null;
webdavResource = null;
}
updatePrompt(getPath());
}
void options(String path)
{
out.println("options " + path);
String param = path;
try {
boolean succeeded = false;
if (param != null) {
if (!param.startsWith("/")) {
httpURL = uriToHttpURL(param);
Enumeration enum = null;
try {
// OPTIONS business logic
enum =
webdavResource.optionsMethod(httpURL);
while (enum.hasMoreElements()) {
out.print(enum.nextElement());
if (enum.hasMoreElements()) {
out.print(", ");
} else {
out.println();
}
}
} catch (HttpException we) {
if (we.getReasonCode() ==
HttpStatus.SC_UNAUTHORIZED) {
BufferedReader in =
new BufferedReader(new InputStreamReader(System.in));
out.print("UserName: ");
String userName = in.readLine();
if (userName != null &&
userName.length() > 0) {
userName = userName.trim();
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()) {
out.print
(enum.nextElement());
if (enum.
hasMoreElements()) {
out.print
(", ");
} else {
out.println();
}
}
} catch (Exception e) {
out.println("Error: "
+ e.getMessage());
}
}
} else {
out.println("Error: " +
we.getMessage());
}
} catch (IOException e) {
out.println(
"Error: Check! " + e.getMessage());
}
httpURL = null;
return;
} else
if (webdavResource != null) {
succeeded =
webdavResource.optionsMethod(param);
} else {
out.println("Not connected yet.");
}
} else
if (webdavResource != null) {
succeeded = webdavResource.optionsMethod("*");
} else {
out.println("Not connected yet.");
}
if (succeeded) {
out.print
("Allowed methods by http OPTIONS: ");
Enumeration allowed =
webdavResource.getAllowedMethods();
while (allowed.hasMoreElements()) {
out.print(allowed.nextElement());
if (allowed.hasMoreElements())
out.print(", ");
}
Enumeration davCapabilities =
webdavResource.getDavCapabilities();
if (davCapabilities.hasMoreElements())
out.print("\nDAV: ");
while (davCapabilities.hasMoreElements()) {
out.print
(davCapabilities.nextElement());
if (davCapabilities.hasMoreElements())
out.print(", ");
}
out.println();
}
}
catch (Exception ex) {
handleException(ex);
}
}
void help(String topic)
{
if (topic==null) {
printSlideClientUsage();
}
else {
out.println("No help available on " + topic);
}
}
void lpwd()
{
try {
out.println(dir.getCanonicalPath());
}
catch (IOException ex) {
out.println("Warning: Not found the path");
}
}
void lcd(String path)
{
try
{
out.println("lcd " + path);
File anotherDir = (path.startsWith("/") ||
path.startsWith("\\")) ? new File(path) :
new File(dir.getCanonicalPath(), path);
if (anotherDir.isDirectory()) {
dir = anotherDir;
} else {
out.println("Warning: Not found the path");
}
}
catch (IOException ex)
{
out.println("Warning: Not found the path");
}
}
void lls(String options, String path)
{
// set default option.
char option = 'F';
if ((options!=null) && (options.indexOf('l') > 0))
option = 'l';
File temp = (path != null) ? new File(dir, path) : dir;
if (!temp.exists()) {
out.println("Warning: Not found the path");
return;
}
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.
out.print(s);
for (int k = list[i].length();
k < 35; k++)
out.print(" ");
break;
case 1:
s = Long.toString(file.length());
for (int k = 10 - s.length();
k > 0 ; k--)
out.print(" ");
// don't cut the size.
out.print(s + " ");
break;
case 2:
// cut the description.
s = file.isDirectory() ?
"DIR" : "";
out.print(" " +
((s.length() > 5) ?
s.substring(0, 5) : s));
for (int k = s.length(); k < 5; k++)
out.print(" ");
break;
case 3:
s = new SimpleDateFormat().format(
new Date(file.lastModified()));
out.print(" " + s);
default:
}
}
// Start with a new line.
out.println();
}
break;
case 'F':
int i = 0;
for (; i < list.length; i++) {
out.print(list[i] + " ");
for (int j = list[i].length();
j < 25; j++) {
out.print(" ");
}
if (i % 3 == 2)
out.println();
}
if (list.length > 0 && i % 3 != 0) {
out.println();
}
break;
default:
} // end of switch
}
void pwc()
{
out.println(getPath());
}
void cd(String path)
{
try {
String cdPath = checkUri(path + "/");
webdavResource.setPath(cdPath);
if (webdavResource.exists()) {
if (webdavResource.isCollection()) {
setPath(webdavResource.getPath());
} else {
out.println("Warning: Not a collection");
}
} else {
out.println("Warning: Not found the path");
}
}
catch (Exception ex) {
handleException(ex);
}
updatePrompt(getPath());
}
void ls(String options, String path)
{
// set default option.
char option = 'F';
if ((options!=null) && (options.indexOf('l') > 0))
option = 'l';
try {
// Check that the path is ok.
if (path != null) {
path = checkUri(path + "/");
webdavResource.setPath(path);
} else {
path = checkUri("./");
webdavResource.setPath(path);
}
switch (option) {
case 'l':
Vector basiclist = webdavResource.listBasic();
for (int i = 0; i < basiclist.size(); i++) {
String[] longFormat =
(String []) basiclist.elementAt(i);
for (int j = 0;
j < longFormat.length; j++) {
String s = longFormat[j];
int len = s.length();
switch (j) {
case 0:
out.print(s);
for (int k = len; k < 20; k++)
out.print(" ");
break;
case 1:
for (int k = 10 - len;
k > 0 ; k--)
out.print(" ");
// don't cut the size.
out.print(s + " ");
break;
case 2:
// cut the description.
out.print(" " +
((len > 20) ?
s.substring(0, 20) : s));
for (int k = len; k < 20; k++)
out.print(" ");
break;
case 3:
default:
out.print(" " + s);
}
}
// Start with a new line.
out.println();
}
break;
case 'F':
String[] list = webdavResource.list();
int i = 0;
for (; i < list.length; i++) {
out.print(list[i] + " ");
for (int j = list[i].length(); j < 25; j++) {
out.print(" ");
}
if (i % 3 == 2)
out.println();
}
if (list.length > 0 && i % 3 != 0)
out.println();
break;
default:
} // end of switch
}
catch (Exception ex) {
handleException(ex);
}
}
void propfind(String path, Vector properties)
{
try {
path = checkUri(path);
out.print("Getting properties '" + path + "': ");
Enumeration propertyValues =
webdavResource.propfindMethod(path, properties);
if (propertyValues.hasMoreElements()){
while (propertyValues.hasMoreElements()){
out.println(propertyValues.nextElement());
}
}
else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void status()
{
out.println(webdavResource.getStatusMessage());
}
void propfindall(String path)
{
try {
path=checkUri(path);
out.print("Getting properties '" + path + "': ");
Enumeration responses = webdavResource.propfindMethod(path, DepthSupport.DEPTH_0);
if (!responses.hasMoreElements()) {
out.println("failed (no response received).");
out.println(webdavResource.getStatusMessage());
return;
}
else {
out.println();
}
ResponseEntity response = (ResponseEntity) responses.nextElement();
Enumeration properties = response.getProperties();
while (properties.hasMoreElements()){
Property property = (Property)properties.nextElement();
out.println(" " + property.getName() + " : " + property.getPropertyAsString());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void proppatch(String path, String prop, String value)
{
String name=prop;
try {
out.print("Putting property(" + name + ", " + value +
") to '" + path + "': ");
if (webdavResource.proppatchMethod(
path, new PropertyName("DAV:",name), value, true)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void get(String path, String filename)
{
try {
// The resource on the remote.
String src = checkUri(path);
// The file on the local.
String dest = (filename!=null)
? filename
: URIUtil.getName(src.endsWith("/")
? src.substring(0, src.length() - 1)
: src);
out.println("get " + src + " " + dest);
// For the overwrite operation;
String y = "y";
File file = new File(dest);
// Checking the local file.
if (file.exists()) {
// FIXME: interactive ?
out.print("Aleady exists. " +
"Do you want to overwrite it(Y/n)? ");
BufferedReader in =
new BufferedReader(new InputStreamReader(System.in));
y = in.readLine();
}
if (y.trim().equalsIgnoreCase("y") ||
(y != null && y.length() == 0)) {
out.print("Downloading '" + src +
"' to '" + dest + "': ");
if (webdavResource.getMethod(src, file)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
}
catch (Exception ex) {
handleException(ex);
}
}
void put(String filename, String path)
{
out.println("put " + filename + " " + path);
// FIXME upload URLs !!!!
// if ((count == 2 && src.indexOf(":") > 1) ||
// count == 1 && dest.indexOf(":") > 1) {
// URL url = new URL(count == 1 ? dest : src);
// out.print("Uploading '" +
// ((count == 2) ? src : dest) +
// "' to '" + ((count == 2) ?
// dest : src) + "': ");
// if (webdavResource.putMethod(dest, url)) {
// out.println("succeeded.");
// } else {
// out.println("failed.");
// }
// continue;
// }
try {
String src = filename;
String dest = checkUri(path);
File file = new File(dir.getCanonicalPath(), src);
if (file.exists()) {
out.print("Uploading '" + src + "' to '" + dest + "': ");
if (webdavResource.putMethod(dest, file)) {
out.println("succeeded.");
}
else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
else {
out.println("Warning: File not exists");
}
}
catch (Exception ex) {
handleException(ex);
}
}
// TODO multi
void delete(String path)
{
try {
path = checkUri(path);
out.print("Deleting '" + path + "': ");
if (webdavResource.deleteMethod(path)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
// TODO multi
void mkcol(String path)
{
try {
path = checkUri(path);
out.print("Making '" + path + "' collection: ");
if (webdavResource.mkcolMethod(path)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void copy(String src, String dst)
{
try {
src = checkUri(src);
dst = checkUri(dst);
out.print("Copying '" + src + "' to '" + dst + "': ");
if (webdavResource.copyMethod(src, dst)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void move(String src, String dst)
{
try {
src = checkUri(src);
dst = checkUri(dst);
out.print("Moving '" + src + "' to '" + dst + "': ");
if (webdavResource.moveMethod(src, dst)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void locks(String path)
{
try {
path=checkUri(path);
LockDiscoveryProperty lockDiscoveryProperty=webdavResource.lockDiscoveryPropertyFindMethod(path);
if (lockDiscoveryProperty==null) {
out.println("Server did not return a LockDiscoveryProperty.");
out.println(webdavResource.getStatusMessage());
return;
}
Lock[] locks=lockDiscoveryProperty.getActiveLocks();
showLocks(path,locks);
}
catch (Exception ex) {
handleException(ex);
}
}
void lock(String path)
{
try {
path = checkUri(path);
out.print("Locking '" + path + "': ");
if (webdavResource.lockMethod(path)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void unlock(String path)
{
try {
path = checkUri(path);
out.print("Unlocking '" + path + "': ");
if (webdavResource.unlockMethod(path)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void grant(String permission,String path, String principal)
{
grant(new QName("DAV:",permission),path,principal);
// FIME lookup permission ?
// if (namespace==null) {
// namespace=resolveNamespace(permission);
// if (namespace==null) {
// out.println("Could not resolve namespace for permission " + permission);
// continue;
// }
// }
}
void grant(QName permission,String path, String principal)
{
try {
principal=checkPrincipal(principal,webdavResource,path);
grant(webdavResource, permission, path, principal);
}
catch (Exception ex) {
handleException(ex);
}
}
void deny(String permission,String path, String principal)
{
deny(new QName("DAV:",permission),path,principal);
}
void deny(QName permission,String path, String principal)
{
try {
principal=checkPrincipal(principal,webdavResource,path);
deny(webdavResource, permission, path, principal);
}
catch (Exception ex) {
handleException(ex);
}
}
void revoke(String permission,String path, String principal)
{
revoke(new QName("DAV:",permission),path,principal);
}
void revoke(QName permission,String path, String principal)
{
try {
principal=checkPrincipal(principal,webdavResource,path);
revoke(webdavResource, permission, path, principal);
}
catch (Exception ex) {
handleException(ex);
}
}
void acl(String path)
{
try
{
AclProperty acl=null;
if (path!=null) {
path=checkUri(path);
}
else {
path=webdavResource.getPath();
}
acl = webdavResource.aclfindMethod(path);
if (acl==null)
{
out.println("Error: PropFind didn't return an AclProperty!");
return;
}
out.println();
showAces(path, acl.getAces());
}
catch (Exception ex)
{
handleException(ex);
}
}
void principalcollectionset(String path)
{
try
{
PrincipalCollectionSetProperty set=null;
if (path!=null) {
path=checkUri(path);
}
else {
path=webdavResource.getPath();
}
set = webdavResource.principalCollectionSetFindMethod(path);
if (set==null)
{
out.println("Error: PropFind didn't return an PrincipalCollectionSetProperty!");
return;
}
String[] hrefs=set.getHrefs();
if (hrefs==null) {
out.println("No PrincipalCollectionSet for " + path);
}
out.println();
out.println("PrincipalCollectionSet for " + path + ":");
for (int i=0 ; i<hrefs.length ; i++)
out.println(" " + hrefs[i]);
out.println();
}
catch (Exception ex)
{
}
}
///////////////////////////////////////////////////////////////////
void checkin(String path)
{
try {
path = checkUri(path);
out.print("checking in '" + path + "': ");
if (webdavResource.checkinMethod(path)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void checkout(String path)
{
try {
path = checkUri(path);
out.print("checking out '" + path + "': ");
if (webdavResource.checkoutMethod(path)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void uncheckout(String path)
{
try {
path = checkUri(path);
out.print("unchecking out '" + path + "': ");
if (webdavResource.uncheckoutMethod(path)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void versioncontrol(String path)
{
try {
path = checkUri(path);
out.print("setting up VersionControl '" + path + "': ");
if (webdavResource.versionControlMethod(path)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void versioncontrol(String target, String path)
{
try {
path = checkUri(path);
out.print("creating versioncontroled Resource '" + target + "' based on '" + path + "' : ");
if (webdavResource.versionControlMethod(path, target)) {
out.println("succeeded.");
} else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void report(String path, Vector properties)
{
Enumeration propertyValues;
try {
path = checkUri(path);
out.println("Getting version-tree Report of '" + path + "':");
if ((properties!=null) && (properties.size()>0)) {
propertyValues =
webdavResource.reportMethod(uriToHttpURL(path), properties, 1);
}
else {
propertyValues =
webdavResource.reportMethod(uriToHttpURL(path), 1);
}
if (propertyValues.hasMoreElements()){
while (propertyValues.hasMoreElements()){
out.println(propertyValues.nextElement().toString());
}
}
else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void ereport(String path, String srcFilename)
{
try {
String sQuery ="";
if (srcFilename==null) {
sQuery = "<D:expand-property xmlns:D='DAV:'><D:property name='version-history'><D:property name='version-set'><D:property name='successor-set'><D:property name='comment'/></D:property></D:property></D:property></D:expand-property>";
}
else {
File file = new File(dir.getCanonicalPath(), srcFilename);
if (!file.exists()) {
out.println("report src file not found");
return;
}
InputStream isQuery = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(isQuery));
while (reader.ready()) {
sQuery += reader.readLine();
}
reader.close();
sQuery.replace('\t',' ');
out.println (sQuery);
}
path = checkUri(path);
out.println("expand-property Report of '" + path + "':");
Enumeration propertyValues =
webdavResource.reportMethod(uriToHttpURL(path), sQuery, 1);
if (propertyValues.hasMoreElements()){
while (propertyValues.hasMoreElements()){
out.println(displayXML(propertyValues.nextElement().toString(), 0));
}
}
else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
/**
* lreport path properties on historyUris
*/
void lreport(String path, Vector properties, Vector historyUris)
{
try {
path = checkUri(path);
out.println("Getting version-tree Report of '" + path + "':");
Enumeration propertyValues =
webdavResource.reportMethod(uriToHttpURL(path), properties, historyUris, 1);
if (propertyValues.hasMoreElements()) {
while (propertyValues.hasMoreElements()) {
out.println(propertyValues.nextElement().toString());
}
}
else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
void mkws(String path)
{
try {
path = checkUri(path);
out.print("Making '" + path + "' workspace: ");
if (webdavResource.mkWorkspaceMethod(path)) {
out.println("succeeded.");
}
else {
out.println("failed.");
out.println(webdavResource.getStatusMessage());
}
}
catch (Exception ex) {
handleException(ex);
}
}
/**
* Update
*
* @param path
* @param version
*/
void update(String path, String version){
try {
path = checkUri(path);
out.print("Updateing resource " + path + ": ");
if (webdavResource.updateMethod(path, version)) {
out.println("succeeded.");
} else {
out.println("failed!");
out.println(webdavResource.getStatusMessage());
}
} catch (Exception ex) {
handleException(ex);
}
}
///////////////////////////////////////////////////////////////////
// Support methods
///////////////////////////////////////////////////////////////////
private void setDisplayPrompt(boolean displayPrompt)
{
this.displayPrompt = displayPrompt;
}
/**
* Determine which URI to use at the prompt.
*
* @param uri the path to be set.
* @return the absolute path.
*/
private String checkUri(String uri) throws IOException
{
if (webdavResource == null) {
throw new IOException("Not connected yet.");
}
if (uri==null) {
uri=webdavResource.getPath();
}
if (!uri.startsWith("/")) {
uri = getPath() + uri;
}
return normalize(uri);
}
private String checkPrincipal(String principal, WebdavResource webdavResource, String path) throws HttpException,IOException
{
// Do not complete reserved words
String[] types={"all","authenticated","unauthenticated","property","self"};
for (int i=0; i<types.length ; i++)
{
if (types[i].equals(principal))
return principal;
}
// FIXME: when search support is complete enhance this
// to really search for the principal
if (!principal.startsWith("/") && !principal.startsWith("http")) {
PrincipalCollectionSetProperty set = webdavResource.principalCollectionSetFindMethod(path);
if ((set!=null) && (set.getHrefs()!=null) && (set.getHrefs().length==1))
principal = set.getHrefs()[0] + "/" + principal;
}
return normalize(principal);
}
/**
* 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 Slide client commands for use
*/
private void printSlideClientUsage()
{
out.println("Commands:");
out.println(" options {http_URL|path} " +
"Print available http methods");
out.println(" open [http_URL] " +
"Connect to specified URL");
out.println(" close " +
"Close current connection");
out.println(" exit " +
"Exit Slide");
out.println(" help " +
"Print this help message");
out.println(" debug {ON|OFF} " +
"set debugmode");
out.println(" lpwd " +
"Print local working directory");
out.println(" lcd [path] " +
"Change local working directory");
out.println(" lls [-lF] [path] " +
"List contents of local directory");
out.println(" pwc " +
"Print working collection");
out.println(" cc [path] " +
"Change working collection");
out.println(" ls [-lF] [path] " +
"List contents of collection");
out.println(" url " +
"Print working URL");
out.println(" status " +
"Print latest http status message");
out.println(" get path [file] " +
"Get a resource to a file");
out.println(" put {URL|file} [path] " +
"Put a given file or URL to path");
out.println(" mkcol path ... " +
"Make new collections");
out.println(" delete path ... " +
"Delete resources");
out.println(" copy source destination " +
"Copy resource from source to destination path");
out.println(" move source destination " +
"Move resource from source to destination path");
out.println(" lock path " +
"Lock specified resource");
out.println(" unlock path " +
"Unlock specified resource");
out.println(" locks [<path>] " +
"Displays locks on specified resource");
out.println(" propget path property ... " +
"Print value of specified property");
out.println(" propgetall [<path>] " +
"Print value of all properties");
out.println(" propput path property value " +
"Set property with given value");
out.println(" set URLencode {on|off} " +
"Set URL encoding flag, default: on");
out.println(" set debug {on|off} " +
"Set debug level, default: off");
out.println(" acl [<path>] " +
"Displays the ACL of path");
out.println(" principalcol [<path>] " +
"Displays the principal collection set of path");
out.println(" grant [<namespace>] <permission> [on <path>] to <principal>");
out.println(" deny [<namespace>] <permission> [on <path>] to <principal>");
out.println(" revoke [<namespace>] <permission> [on <path>] from <principal>");
out.println(" versioncontrol path "+
"set a versionable resource under versioncontrol");
out.println(" versioncontrol URL path "+
"create a new versioncontrolled resource at path based on history URL");
out.println(" checkout path "+
"checkout of a checkedin resource");
out.println(" checkin path "+
"checkin of a checkedout resource");
out.println(" uncheckout path "+
"undoing changes on Resource since checkedout (including checkout)");
out.println(" report path [<property>] "+
"getting report (version-tree) for any resource");
out.println(" eReport path "+
"getting report (expand-property) for any resource");
out.println(" LReport path [<property>] ON [<historyuri>] "+
"getting report (locate-by-history)");
out.println(" mkws path ... " +
"Make new workspace");
out.println(" update path target " +
"Update a resource identified by path to version identified by target");
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");
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, QName permission, String path, String principal) throws HttpException, IOException
{
out.println("grant " + permission + " on " + path + " to " + principal);
return addPermission(webdavResource, permission, path, principal, false);
}
private boolean deny(WebdavResource webdavResource, QName permission, String path, String principal) throws HttpException, IOException
{
out.println("deny " + permission + " on " + path + " to " + principal);
return addPermission(webdavResource, permission, path, principal, true);
}
private boolean revoke(WebdavResource webdavResource, QName permission, String path, String principal) throws HttpException, IOException
{
out.println("revoke " + permission + " on " + path + " from " + principal);
return removePermission(webdavResource, permission, path, principal);
}
private boolean addPermission(WebdavResource webdavResource, QName permission, String path, String principal, boolean negative) throws HttpException, IOException
{
AclProperty acl = webdavResource.aclfindMethod(path);
if (acl==null)
{
out.println("Error: PropFind didn't return an AclProperty!");
return false;
}
Ace[] aces=acl.getAces();
if (aces==null)
aces=new Ace[0];
if (debugLevel>5) {
out.println();
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()==negative) && !aces[i].isProtected()
&& !aces[i].isInherited() && aces[i].getPrincipal().equals(principal))
{
if (debugLevel>5)
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, negative, false, false,null);
aces[oldAces.length]=ace;
}
Privilege privilege=new Privilege(permission.getNamespaceURI(), permission.getLocalName(), null);
ace.addPrivilege(privilege);
if (debugLevel>5) {
out.println();
out.println("ACL with updated privileges");
showAces(path, aces);
}
boolean success = webdavResource.aclMethod(path,aces);
if (!success)
out.println(webdavResource.getStatusMessage());
if (debugLevel>5) {
acl = webdavResource.aclfindMethod(path);
if (acl==null)
out.println("Error: PropFind didn't return an AclProperty!");
else
{
aces=acl.getAces();
out.println();
out.println("ACL from server after update");
showAces(path, aces);
}
}
return success;
}
private boolean removePermission(WebdavResource webdavResource, QName permission, String path, String principal) throws HttpException, IOException
{
AclProperty acl = webdavResource.aclfindMethod(path);
if (acl==null)
{
out.println("Error: PropFind didn't return an AclProperty!");
return false;
}
Ace[] aces=acl.getAces();
if (aces==null)
{
out.println("Privilege not found");
return false;
}
if (debugLevel>5) {
out.println();
out.println("ACL from server");
showAces(path, aces);
}
boolean found=false;
Privilege privilege=new Privilege(permission.getNamespaceURI(), permission.getLocalName(), null);
for (int i=0; i<aces.length; i++)
{
if (!aces[i].isProtected() && !aces[i].isInherited() && aces[i].getPrincipal().equals(principal))
{
if (debugLevel>5)
out.println("found ace");
boolean removed = aces[i].removePrivilege(privilege);
found = found || removed;
if (removed)
out.println("Privilege removed");
}
}
if (!found)
{
out.println("Privilege not found");
return false;
}
if (debugLevel>5) {
out.println();
out.println("ACL with updated privileges");
showAces(path, aces);
}
boolean success = webdavResource.aclMethod(path,aces);
if (!success)
out.println(webdavResource.getStatusMessage());
if (debugLevel>5) {
acl = webdavResource.aclfindMethod(path);
if (acl==null)
out.println("Error: PropFind didn't return an AclProperty!");
else
{
aces=acl.getAces();
out.println();
out.println("ACL from server after update");
showAces(path, aces);
}
}
return success;
}
private void showAces(String path, Ace[] aces)
{
if ((aces==null) || (aces.length==0)) {
out.println("ACL for " + path + " is empty.");
return;
}
out.println("ACL for " + path + ":");
out.println("------------------------------------------------------------");
for (int i=0; i<aces.length ; i++)
{
Ace ace=aces[i];
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();
out.println(" " + priv.getNamespace() + priv.getName() + " " + (priv.getParameter()==null?"":("("+priv.getParameter()+")")));
}
}
out.println("------------------------------------------------------------");
}
private void showLocks(String path, Lock[] locks)
{
if ((locks==null) || (locks.length==0)) {
out.println("No locks on " + path);
return;
}
out.println("Locks for " + path + ":");
out.println("------------------------------------------------------------");
for (int i=0; i<locks.length ; i++)
{
int lockScope = locks[i].getLockScope();
if (lockScope==Lock.SCOPE_EXCLUSIVE) {
out.print("Exclusive ");
}
else if (lockScope==Lock.SCOPE_SHARED) {
out.print("Shared ");
}
else if (lockScope==-1) {
out.print("Unknown scope ");
}
else {
out.println("!!! Internal error !!!");
return;
}
int lockType = locks[i].getLockType();
if (lockType==Lock.TYPE_WRITE) {
out.println("write lock");
}
else if (lockType==-1) {
out.println("unknown type");
}
else {
out.println("!!! Internal error !!!");
return;
}
int depth=locks[i].getDepth();
if (depth==DepthSupport.DEPTH_INFINITY) {
out.println(" depth: infinity");
}
else if (depth==-1) {
// unknown
}
else {
out.println(" depth: " + depth);
}
String owner=locks[i].getOwner();
if (owner!=null)
out.println(" owner: " + owner);
int timeout=locks[i].getTimeout();
if (timeout!=-1)
out.println(" timeout: " + timeout);
String token=locks[i].getLockToken();
if (token!=null)
out.println(" token: " + token);
}
}
private String displayXML(String xmlString, int count)
{
String sResult ="";
if(xmlString.startsWith("</")) {
count --;
//out.println("cl: " + count);
for (int cc = count; cc > 0; cc--) {
sResult += "\t";
}
try {
sResult += xmlString.substring(0, xmlString.indexOf(">") + 1)+"\n";
xmlString = xmlString.substring(xmlString.indexOf(">") + 1);
//count --;
sResult += displayXML(xmlString, count);
}
catch (Exception any) {
//sResult += "endtag" + any;
}
}
else if (xmlString.startsWith("<")) {
//out.println("op: " + count);
for (int cc = count; cc > 0; cc--) {
sResult += "\t";
}
try {
sResult += xmlString.substring(0, xmlString.indexOf(">") + 1)+"\n";
xmlString = xmlString.substring(xmlString.indexOf(">") + 1);
count ++;
sResult += displayXML(xmlString, count);
}
catch (Exception any) {
//sResult += "starttag" + any;
}
}
else {
//out.println("em: " + count);
for (int cc = count; cc > 0; cc--) {
sResult += "\t";
}
try {
sResult += xmlString.substring(0, xmlString.indexOf("<"))+ "\n";
xmlString = xmlString.substring(xmlString.indexOf("<"));
sResult += displayXML(xmlString, count);
}
catch (Exception any) {
//sResult += any;
}
}
return sResult;
}
private static HttpURL uriToHttpURL(String uri) throws URIException {
return uri.startsWith("https") ? new HttpsURL(uri.toCharArray())
: new HttpURL(uri.toCharArray());
}
}