[jcifs] Abstract File(File,
SmbFile) and enhanced Servlet application
Rolf Breuning
Rolf.Breuning at t-online.de
Sun May 30 14:18:51 GMT 2004
Skipped content of type multipart/alternative-------------- next part --------------
/*
* ExplorerServlet.java
*
* Created on 30. Mai 2004, 14:02
*/
package jcifs.http;
import java.io.*;
import java.net.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.ecs.*;
import org.apache.ecs.html.*;
import com.oreilly.servlet.multipart.MultipartParser;
import com.oreilly.servlet.multipart.Part;
import com.oreilly.servlet.multipart.FilePart;
import com.oreilly.servlet.multipart.ParamPart;
import jcifs.smb.*;
import jcifs.util.MimeMap;
import jcifs.util.AbstractFile;
/**
*
* @author Rolf Breuning (Rolf.Breuning at t-online.de)
*/
public class ExplorerServlet extends javax.servlet.http.HttpServlet {
String servletPath;
static final String Cmd = "cmd";
static final String CmdStart = "Cmd";
static final String CmdRootAddDialog = "CmdRootAddDialog";
static final String CmdRootAdd = "CmdRootAdd";
static final String CmdRootSelect = "CmdRootSelect";
static final String CmdDirectoryList = "CmdDirectoryList";
static final String CmdDirectoryCreate = "CmdDirectoryCreate";
static final String CmdFileSend = "CmdFileSend";
static final String CmdFileRemoveDialog = "CmdFileRemoveDialog";
static final String CmdFileRemove = "CmdFileRemove";
static final String CmdFileRenameDialog = "CmdFileRenameDialog";
static final String CmdFileRename = "CmdFileRename";
static final String CmdFileUpload = "CmdFileUpload";
static final String FldRootFiles = "FldRootFiles";
static final String FldLocalFile = "FldLocalFile";
static final String FldDomain = "FldDomain";
static final String FldServer = "FldServer";
static final String FldShare = "FldShare";
static final String FldUser = "FldUser";
static final String FldPass = "FldPass";
static final String FldPort = "FldPort";
static final String FldChkBox = "FldChk";
static final String FldPathInput = "FldPathInput";
static final String FldUploadFile = "FldUploadFile";
static final String FldUploadUnzip = "FldUploadUnzip";
static final String FldNewDir = "FldNewDir";
static final String Sort = "Srt";
static final String StyTitle = "StyTitle";
static final String StyTrMark = "StyTrMark";
static final String StyTdHead = "StyTdHead";
static final String AtrRootFiles = "RootFiles";
static final String AtrRootIndex = "RootIndex";
static final String AtrFileHandler = "FileHandler";
static final String Encoding = "utf-8";
static final DateFormat FileDateFormat = new SimpleDateFormat( "yy-MM-dd HH:mm:ss" );
static final Comparator CmpType = new Comparator() { public int compare( Object a, Object b ) {
try {
boolean aDir = ( (AbstractFile) a).getAbsoluteURL().endsWith( "/" );
boolean bDir = ( (AbstractFile) b).getAbsoluteURL().endsWith( "/" );
if ( aDir == bDir ) return CmpPath.compare( a, b );
return ( aDir ? -1 : 1 );
} catch (Exception exc) { return 0;}
} };
static final Comparator CmpPath = new Comparator() { public int compare( Object a, Object b ) {
return ( (AbstractFile) a).getName().compareToIgnoreCase( ( (AbstractFile) b).getName() );
} };
static final Comparator CmpSize = new Comparator() { public int compare( Object a, Object b ) {
long result = 0;
try { result += ( (AbstractFile) a).length(); } catch (Exception exc) {};
try { result -= ( (AbstractFile) b).length(); } catch (Exception exc) {};
if ( result == 0 ) return 0; else return ( result > 0 ) ? 1 : -1;
} };
static final Comparator CmpLastModified = new Comparator() { public int compare( Object a, Object b ) {
long result = 0;
try { result += ( (AbstractFile) a).lastModified(); } catch (Exception exc) {};
try { result -= ( (AbstractFile) b).lastModified(); } catch (Exception exc) {};
if ( result == 0 ) return 0; else return ( result > 0 ) ? 1 : -1;
} };
/**
* Return the first string in the enumeration 'e' starting with 'start'.
*
* Creation date: (01.10.00 17.15.36)
* @return java.lang.String
* @param e java.util.Enumeration
* @param start java.lang.String
*/
static public String getStringStartingWith(java.util.Enumeration e, String start ) {
String current;
for ( ; e.hasMoreElements(); ) {
current = (String) e.nextElement();
if ( current.startsWith( start ) ) return current;
};
return null;
}
/** Return the HTML <head> elements including the title
* @param title
* @return
*/
protected String getHeadElements( String title ) {
return "<head>\n <title>" + title + "</title>\n" +
" <style type=\"text/css\">\n" +
" body { font-family:sans-serif; text-align:justify; }\n" +
" td { font-family:sans-serif; }\n" +
" input { font-family:sans-serif; }\n" +
" a:link { color:blue; text-decoration:underline; }\n" +
" a:visited { color:blue; text-decoration:underline; }\n" +
" a:active { color:red; text-decoration:none; }\n" +
" #StyTitle { font-family:sans-serif; font-size:18px; font-weight:bold; }\n" +
" #StyTrMark { background-color:#c0c0c0; }\n" +
" #StyTdHead { background-color:#c0c0c0; font-weight:bold; }\n" +
" </style>\n" +
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + Encoding + "\" >\n" +
"</head>";
}
/** Create directory. Called from cmdDirectoryList(). 'filename' is the file "download.zip" in the directory where the new directory is created
* @param base
* @param directory
* @param req an {@link HttpServletRequest} object that contains the request the client has made of the servlet
* @param resp an {@link HttpServletResponse} object that contains the response the servlet sends to the object
* @throws Exception
*/
protected void cmdDirectoryCreate(HttpServletRequest req, HttpServletResponse resp, AbstractFile base, String filename ) throws Exception {
AbstractFile dir = base.getChild( filename ).getParent();
String newName = req.getParameter( FldNewDir );
newName = newName.replace( '\\', '/' );
if ( newName.startsWith( "/" ) ) newName = newName.substring(1);
if ( ! newName.endsWith( "/" ) ) newName += "/";
dir.getChild( newName ).mkdirs();
resp.sendRedirect( "." );
}
/**
*
* @param req an {@link HttpServletRequest} object that contains the request the client has made of the servlet
* @param resp an {@link HttpServletResponse} object that contains the response the servlet sends to the object
* @exception IOException if an input or output error is detected when the servlet handles the GET request
* @exception ServletException if the request for the GET could not be handled
*/
protected void cmdDirectoryList(HttpServletRequest req, HttpServletResponse resp, AbstractFile base, String directory ) throws Exception {
AbstractFile dir = base.getChild( directory );
AbstractFile files[] = new AbstractFile[0];
files = dir.listFiles();
String sort = req.getParameter( Sort );
Comparator cmp = CmpType;
if ( "P".equals( sort ) ) cmp = CmpPath;
if ( "S".equals( sort ) ) cmp = CmpSize;
if ( "L".equals( sort ) ) cmp = CmpLastModified;
Arrays.sort( files, cmp );
Table table = new Table().setBorder(0).setCellPadding( 0 ).setCellSpacing( 0 ).setWidth( "100%");
table.addElement( new TR()
.addElement( new TD( new A().setHref( "?" + Sort + "=T" ).addElement( "Type" ) ).setID( StyTdHead) )
.addElement( new TD().setWidth( 5 ) )
.addElement( new TD( new A().setHref( "?" + Sort + "=P" ).addElement( "Path" ) ).setID( StyTdHead) )
.addElement( new TD().setWidth( 5 ) )
.addElement( new TD( new A().setHref( "?" + Sort + "=S" ).addElement( "Size" ) ).setID( StyTdHead) )
.addElement( new TD().setWidth( 5 ) )
.addElement( new TD( new A().setHref( "?" + Sort + "=L" ).addElement( "Last modified" ) ).setID( StyTdHead) )
);
sort = ( sort == null ) ? "" : "?" + Sort + "=" + sort;
int pos = directory.lastIndexOf( "/" );
if ( pos > 0 ) {
table.addElement( new TR()
.addElement( new TD("D") )
.addElement( new TD() )
.addElement( new TD( new A().setHref( "../" + sort ).addElement( ".." ) ) )
);
};
String basePath = base.getAbsoluteURL();
for ( int i=0; i<files.length; i++ ) {
AbstractFile file = files[i];
String path = file.getAbsoluteURL().substring( basePath.length() );
String name = file.getName();
long length = 0;
String fileSign = "-";
String link = URLEncoder.encode( name );
if ( file.isDirectory() ) { name += "/"; link += "/"; fileSign = "D"; }
if ( file.isFile() ) fileSign = "F";
try { length = file.length(); } catch (Exception exc) {};
table.addElement( new TR()
.addElement( new TD()
.addElement( fileSign )
.addElement( new Input( Input.CHECKBOX, FldChkBox, name ) ) )
.addElement( new TD() )
.addElement( new TD( new A().setHref( link + sort).addElement( name ) ) )
.addElement( new TD() )
.addElement( new TD( "" + length ).setAlign( "right" ) )
.addElement( new TD() )
.addElement( new TD( FileDateFormat.format( new Date( file.lastModified() ) ) ) )
);
};
new Html()
.addElement( new ClearElement( getHeadElements( "FB: " + directory ) ) )
.addElement( new Body()
.addElement( new ClearElement( showTopLine( req, base ) ) )
.addElement( "Directory: " )
.addElement( new A().setHref( "./" + sort ).addElement( dir.toString() ) )
.addElement( new Form()
.setMethod( Form.POST )
.setAction( "download.zip" )
.addElement( table )
.addElement( "Selected:" )
.addElement( new Input( Input.SUBMIT, CmdFileSend, "Download" ) )
.addElement( new Input( Input.SUBMIT, CmdFileRemoveDialog, "Remove..." ) )
.addElement( new Input( Input.SUBMIT, CmdFileRenameDialog, "Rename to:" ) )
.addElement( new Input( Input.text, FldPathInput, "" ) )
.addElement( new BR() )
.addElement( new BR() )
.addElement( new Table().setCellPadding(3).setCellSpacing(0).setBorder(0)
.addElement( new TR()
.addElement( new TD( "Create directory:" ) )
.addElement( new TD( new Input( Input.text, FldNewDir, "" ).setSize( 30 ) ) )
.addElement( new TD( new Input( Input.submit, CmdDirectoryCreate, "Create" ) ) )
.setID( StyTrMark )
) ) )
.addElement( new Form()
.setMethod( Form.POST )
.setEncType( Form.ENC_UPLOAD )
.setAction( "" )
.addElement( new Table().setCellPadding(3).setCellSpacing(0).setBorder(0)
.addElement( new TR()
.addElement( new TD( "Upload file:" ) )
.addElement( new TD()
.addElement( new Input( Input.file, FldUploadFile, "" ).setSize( 30 ) )
.addElement( new BR() )
.addElement( new Input( Input.CHECKBOX, FldUploadUnzip, FldUploadUnzip ) )
.addElement( "Unzip after upload" )
)
.addElement( new TD( new Input( Input.SUBMIT, CmdFileUpload, "Upload" ) ) )
.setID( StyTrMark )
)
)
)
)
.output( resp.getWriter() );
}
/**
* Remove file dialog, called from cmdDirectoryList. 'filename' is the file "download.zip" in the directory where the files
* identified by the names by parameters are to be removed
* @param base
* @param fileName
* @param req an {@link HttpServletRequest} object that contains the request the client has made of the servlet
* @param resp an {@link HttpServletResponse} object that contains the response the servlet sends to the object
* @throws Exception
*/
protected void cmdFileRemoveDialog( HttpServletRequest req, HttpServletResponse resp, AbstractFile base, String fileName ) throws Exception {
String selected[] = req.getParameterValues( FldChkBox );
AbstractFile dir = base.getChild( fileName ).getParent();
if ( selected == null ) selected = new String[0];
Table table = new Table().setCellPadding(0).setCellSpacing(0).setBorder(0)
.addElement( new TR()
.addElement( new TD( "File" ).setID( StyTdHead ) ) );
for ( int i=0; i<selected.length; i++) {
table.addElement( new TR()
.addElement( new TD()
.addElement( new Input( Input.HIDDEN, FldChkBox, selected[i] ) )
.addElement( selected[i] ) ) );
};
new Html()
.addElement( new ClearElement( getHeadElements( "FB: " + dir ) ) )
.addElement( new Body()
.addElement( new ClearElement( showTopLine( req, base ) ) )
.addElement( new Form()
.setMethod( Form.POST )
.setAction( "." ) // Point to the directory from the URL, not the download file
.addElement( "Remove in directory: " + dir )
.addElement( table )
.addElement( new Input( Input.SUBMIT, CmdFileRemove, "Remove" ) )
.addElement( new Input( Input.SUBMIT, CmdDirectoryList, "Cancel" ) )
)
)
.output( resp.getWriter() );
}
/**
* Remove file dialog, called from cmdFileRemoveDialog.
* @param base
* @param directory
* @param req an {@link HttpServletRequest} object that contains the request the client has made of the servlet
* @param resp an {@link HttpServletResponse} object that contains the response the servlet sends to the object
* @throws Exception
*/
protected void cmdFileRemove( HttpServletRequest req, HttpServletResponse resp, AbstractFile base, String directory ) throws Exception {
String selected[] = req.getParameterValues( FldChkBox );
AbstractFile dir = base.getChild( directory );
if ( selected == null ) selected = new String[0];
Table table = new Table().setCellPadding(0).setCellSpacing(0).setBorder(0)
.addElement( new TR()
.addElement( new TD( "File" ).setID( StyTdHead ) )
.addElement( new TD().setWidth( 5 ) )
.addElement( new TD( "Status" ).setID( StyTdHead ) ) );
for ( int i=0; i<selected.length; i++) {
Exception exception = null;
try { dir.getChild( selected[i] ).delete(); }
catch ( Exception exc ) { exception = exc; };
table.addElement( new TR()
.addElement( new TD( selected[i] ) )
.addElement( new TD() )
.addElement( new TD( exception == null ? "removed" : "fail" ) ) );
};
new Html()
.addElement( new ClearElement( getHeadElements( "FB: " + dir ) ) )
.addElement( new Body()
.addElement( new ClearElement( showTopLine( req, base ) ) )
.addElement( "Removed in directory: " + dir )
.addElement( table )
.addElement( new Form()
.addElement( new Input( Input.SUBMIT, CmdDirectoryList, "Go on" ) ) )
)
.output( resp.getWriter() );
}
/**
* Rename file. 'filename' is the file "download.zip" in the directory where the files
* identified by the names by parameters are to be renamed
* 'dialog' == true: called from cmdDirectoryList, display dialog only.
* 'dialog' == false: called from dialog, actual rename
* @param base
* @param fileName
* @param req an {@link HttpServletRequest} object that contains the request the client has made of the servlet
* @param resp an {@link HttpServletResponse} object that contains the response the servlet sends to the object
* @throws Exception
*/
protected void cmdFileRename( HttpServletRequest req, HttpServletResponse resp, AbstractFile base, String fileName, boolean dialog ) throws Exception {
String selected[] = req.getParameterValues( FldChkBox );
AbstractFile dir = base.getChild( fileName );
if ( dialog ) dir = dir.getParent();
String renamePath = req.getParameter( FldPathInput );
if ( selected == null ) selected = new String[0];
Table table = new Table().setCellPadding(0).setCellSpacing(0).setBorder(0)
.addElement( new TR()
.addElement( new TD( "File" ).setID( StyTdHead ) )
.addElement( new TD().setWidth( 3 ) )
.addElement( new TD( "->" ).setID( StyTdHead ) )
.addElement( new TD().setWidth( 3 ) )
.addElement( new TD( "New name" ).setID( StyTdHead ) )
);
for ( int i=0; i<selected.length; i++) {
String newName = renamePath.replaceFirst( "\\*", selected[i] ); // * -> last part of old file name
AbstractFile newFile = dir.createFromURL( dir.getChild( newName ).getAbsoluteURL() );
TR row = new TR();
String success = "";
if ( ! newFile.getAbsoluteURL().startsWith( base.getAbsoluteURL() ) ) {
success = "Not allowed"; row.setBgColor( "#FF0000" );
} else if ( ! dialog ) { // rename
success = "ok";
try { dir.getChild( selected[i] ).renameTo( newFile ); }
catch ( Exception exc ) { success = "fail"; row.setBgColor( "#FF0000" ); };
}
table.addElement( row
.addElement( new TD()
.addElement( new Input( Input.HIDDEN, FldChkBox, selected[i] ) )
.addElement( selected[i] ) )
.addElement( new TD() )
.addElement( new TD( success ) )
.addElement( new TD() )
.addElement( new TD( newFile.toString() ) ) );
};
new Html()
.addElement( new ClearElement( getHeadElements( "FB: " + dir ) ) )
.addElement( new Body()
.addElement( new ClearElement( showTopLine( req, base ) ) )
.addElement( new Form()
.setMethod( Form.POST )
.setAction( "." ) // Point to the directory from the URL, not the download file
.addElement( "Rename in directory: " + dir )
.addElement( new Input( Input.HIDDEN, FldPathInput, renamePath ) )
.addElement( table )
.addElement( dialog ? new Input( Input.SUBMIT, CmdFileRename, "Rename" ) : null )
.addElement( dialog ? new Input( Input.SUBMIT, CmdDirectoryList, "Cancel" ) : null )
.addElement( ! dialog ? new Input( Input.SUBMIT, CmdDirectoryList, "Go on" ) : null )
)
)
.output( resp.getWriter() );
}
/**
* @param base
* @param fileName
* @param req
* @param resp
* @throws Exception
*/
protected void cmdFileSend(HttpServletRequest req, HttpServletResponse resp, AbstractFile base, String fileName ) throws Exception {
String selected[] = req.getParameterValues( FldChkBox );
AbstractFile file = base.getChild( fileName );
if ( selected != null && selected.length > 0 ) { // Download zipped selected files
base = file.getParent();
AbstractFile files[] = new AbstractFile[selected.length];
for ( int i=0; i<files.length; i++) files[i] = base.getChild( selected[i] );
resp.setContentType( "file/download" );
ZipOutputStream zip = new ZipOutputStream( resp.getOutputStream() );
AbstractFile.zip( zip, base.getAbsoluteURL(), "", files );
zip.close();
} else { // Download single file without zipping
InputStream in = file.getInputStream();
long length = file.length();
ServletOutputStream out = resp.getOutputStream();
String url = file.getAbsoluteURL();
int n = url.lastIndexOf( '.' );
String type = null;
if ( n > 0 && (type = url.substring(n+1)).length() > 1 && type.length() < 6 ) {
type = new MimeMap().getMimeType( type );
};
resp.setContentType( type == null ? "file/download" : type );
resp.setHeader( "Content-Length", length + "" );
resp.setHeader( "Accept-Ranges", "Bytes" );
AbstractFile.copy( in, out, new byte[16000] );
out.close();
};
}
/**
* @param base
* @param directory
* @param req
* @param resp
* @throws Exception
*/
protected void cmdFileUpload(HttpServletRequest req, HttpServletResponse resp, AbstractFile base, String directory ) throws Exception {
AbstractFile dir = base.getChild( directory );
Table table = new Table().setCellPadding(0).setCellSpacing(0).setBorder(0)
.addElement( new TR()
.addElement( new TD( "File" ).setID( StyTdHead ) )
.addElement( new TD().setWidth( 5 ) )
.addElement( new TD( "Status" ).setID( StyTdHead ) ) );
// Parse the incoming multipart, storing files in the dir provided
MultipartParser parser = new MultipartParser( req, 100000000 );
AbstractFile file = null;
Part part;
boolean unzip = false;
ElementContainer fileNames = new ElementContainer();
while ( (part = parser.readNextPart() ) != null ) {
String name = part.getName();
if ( part.isParam() ) {
ParamPart paramPart = (ParamPart) part;
String value = paramPart.getStringValue();
if ( FldUploadUnzip.equals( name ) && FldUploadUnzip.equals( value ) ) unzip = true;
} else if ( part.isFile() ) {
FilePart filePart = (FilePart) part;
String fileName = filePart.getFileName();
if ( fileName != null) { // The part actually contained a file
file = dir.getChild( fileName );
OutputStream stream = file.getOutputStream( false );
filePart.writeTo( stream );
stream.close();
fileNames
.addElement( new BR() )
.addElement( fileName );
};
}
}
if ( file != null ) {
if ( unzip ) { // unzip the uploaded file
AbstractFile.unzip( file.getInputStream(), "", dir );
file.delete();
};
table.addElement( new TR()
.addElement( new TD( "" + file ) )
.addElement( new TD() )
.addElement( new TD( unzip ? "uploaded, unzipped" : "uploaded" ) ) );
};
new Html()
.addElement( new ClearElement( getHeadElements( "FB: " + dir ) ) )
.addElement( new Body()
.addElement( new ClearElement( showTopLine( req, base ) ) )
.addElement( "Uploaded to directory: " + dir )
.addElement( table )
.addElement( new Form()
.addElement( new Input( Input.SUBMIT, CmdDirectoryList, "Go on" ) ) )
)
.output( resp.getWriter() );
}
/**
* @param rootFile
* @param req an {@link HttpServletRequest} object that contains the request the client has made of the servlet
* @param resp an {@link HttpServletResponse} object that contains the response the servlet sends to the object
* @exception Exception if the request could not be handled
*/
protected void cmdRootDialog(HttpServletRequest req, HttpServletResponse resp, AbstractFile rootFile ) throws Exception {
resp.getWriter().write(
"<html>" + getHeadElements( "FB: Add new root" ) +
"<body>\n" + showTopLine( req, rootFile) +
"<form method=POST action=\"?\">\n" +
" <input type=hidden name=" + CmdRootAdd + ">\n" +
" <table border=0 cellspacing=0 cellpadding=2>\n" +
" <tr><td colspan=2>Access local directory on WWW-server:</td></tr>\n" +
" <tr><td>Name:</td><td><input type=text name=" + FldLocalFile + "></td></tr>\n" +
" <tr><td colspan=2></td></tr>\n" +
" <tr><td colspan=2>Access directory on SMB / CIFS server:</td></tr>\n" +
" <tr><td>Domain:</td><td><input type=text name=" + FldDomain + "></td></tr>\n" +
" <tr><td>Server:</td><td><input type=text name=" + FldServer + "></td></tr>\n" +
" <tr><td>Port:</td><td><input type=text name=" + FldPort + "></td></tr>\n" +
" <tr><td>Share:</td><td><input type=text name=" + FldShare + "></td></tr>\n" +
" <tr><td>User:</td><td><input type=text name=" + FldUser + "></td></tr>\n" +
" <tr><td>Password:</td><td><input type=password name=" + FldPass + "></td></tr>\n" +
" <tr><td colspan=2></td></tr>\n" +
" <tr><td colspan=2><input type=submit value=\"Add new Root\"></td></tr>\n" +
" </table>\n" +
"</body></html>" );
}
/**
*
* @param req an {@link HttpServletRequest} object that contains the request the client has made of the servlet
* @param resp an {@link HttpServletResponse} object that contains the response the servlet sends to the object
* @exception Exception if the request for the GET could not be handled
*/
protected void cmdRootAdd(HttpServletRequest req, HttpServletResponse resp) throws Exception {
AbstractFile base;
String localFile = req.getParameter( "FldLocalFile" ).trim();
if ( ! "".equals( localFile ) ) { // Local file
File file = new File( localFile );
if ( ! file.isDirectory() ) throw new Exception( "Local file is not a directory" );
base = new AbstractFile.AFFile( file );
} else { // SMB file
// user = <user>:<pwd>@
String pwd = req.getParameter( FldPass );
String user = req.getParameter( FldUser );
// domain = <domain>;
String domain = req.getParameter( FldDomain );
if ( pwd.length() > 0 ) pwd = ":" + pwd;
if ( user.length() > 0 ) user = user + pwd + "@";
if ( domain.length() > 0 ) domain = domain + ";";
// share = <share>/
String share = req.getParameter( FldShare );
while ( share.startsWith( "/" ) ) share = share.substring( 1 );
while ( share.endsWith( "/" ) ) share = share.substring( 0, share.length() -1 );
if ( share.length() > 0 ) share += "/";
// server = server:<port>
String port = req.getParameter( FldPort ).trim();
String server = req.getParameter( FldServer );
server += ( port.length() > 0 ) ? ":" + port : "";
String url = "smb://" + domain + user + server + "/" + share;
base = new AbstractFile.AFSmbFile( url );
};
Vector rootFiles = getRootFiles( req );
rootFiles.add( base );
resp.sendRedirect( servletPath + "/" + (rootFiles.size() - 1) + "/?" + CmdDirectoryList + "=" );
}
/**
*
* @param req an {@link HttpServletRequest} object that contains the request the client has made of the servlet
* @exception ServletException if the request for the GET could not be handled
*/
protected Vector getRootFiles(HttpServletRequest req) {
Vector rootFiles = (Vector) req.getSession().getAttribute( AtrRootFiles );
if ( rootFiles == null ) rootFiles = new Vector();
req.getSession().setAttribute( AtrRootFiles, rootFiles );
return rootFiles;
}
/**
*
* @param req an {@link HttpServletRequest} object that contains the request the client has made of the servlet
* @param resp an {@link HttpServletResponse} object that contains the response the servlet sends to the object
* @exception ServletException if the request for the GET could not be handled
*/
protected String showTopLine( HttpServletRequest req, AbstractFile selectedRoot ) throws Exception {
String select = "<select name=\"" + FldRootFiles + "\">\n";
Vector rootFiles = getRootFiles( req );
for ( int i=0; i<rootFiles.size(); i++ ) {
AbstractFile file = (AbstractFile) rootFiles.elementAt( i );
select += "<option value=" + i + (file == selectedRoot ? " selected" : "") + ">" + file.toString() + "</option>\n";
};
select += "</select>\n";
return
"<table border=0 cellpadding=1 cellspacing=2 width=100% bgcolor=#c0c0c0>\n" +
" <tr><td><center id=" + StyTitle + ">File Browser - Rolf Breuning</center></td></tr>\n" +
" <tr><td>" +
" <form method=POST>\n" + select +
" <input type=submit name=" + CmdRootSelect + " value=\"Select root\">\n" +
" <input type=submit name=" + CmdRootAddDialog + " value=\"Add new root...\">\n" +
" </form>" +
" </td></tr>" +
"</table><br>";
}
/**
*
* @param req an {@link HttpServletRequest} object that contains the request the client has made of the servlet
* @param resp an {@link HttpServletResponse} object that contains the response the servlet sends to the object
* @exception IOException if an input or output error is detected when the servlet handles the GET request
* @exception ServletException if the request for the GET could not be handled
*/
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType( "text/html; charset=" + Encoding );
if ( req.getCharacterEncoding() == null ) req.setCharacterEncoding( Encoding );
// req = ServletUtil.getMultipartRequest( req, uploadDir.getAbsolutePath(), "" + ++uploadAccess, 100000000 );
String cmd = (String) req.getAttribute( Cmd );
if ( cmd == null ) cmd = getStringStartingWith( req.getParameterNames(), CmdStart );
if ( cmd == null ) cmd = (String) req.getParameter( Cmd );
if ( cmd != null && cmd.indexOf( "." ) >= 0 ) cmd = cmd.substring( 0, cmd.indexOf( "." ) );
servletPath = req.getContextPath() + req.getServletPath();
String pathInfo = req.getPathInfo();
if ( pathInfo.startsWith( "/" ) ) pathInfo = pathInfo.substring( 1 );
int pos = pathInfo.indexOf( "/" );
AbstractFile rootFile = null;
try {
int rootIndex = Integer.parseInt( pathInfo.substring( 0, pos ) );
pathInfo = pathInfo.substring( pos+1 );
rootFile = (AbstractFile) getRootFiles( req ).elementAt( rootIndex );
rootFile.getAttributes().put( AtrRootIndex, new Integer( rootIndex ) );
} catch ( Exception exc ) {};
if ( rootFile == null && ! CmdRootAdd.equals(cmd) ) cmd = CmdRootAddDialog;
if ( cmd == null ) cmd = ( pathInfo.length() == 0 || pathInfo.endsWith( "/" ) ) ? CmdDirectoryList : CmdFileSend;
String contentType = req.getContentType();
if ( contentType != null && contentType.toLowerCase().startsWith( "multipart/form-data" ) ) cmd = CmdFileUpload;
try {
if ( CmdRootAddDialog.equals(cmd) ) cmdRootDialog( req, resp, rootFile );
else if ( CmdRootAdd.equals( cmd ) ) cmdRootAdd( req, resp );
else if ( CmdDirectoryList.equals( cmd ) ) cmdDirectoryList( req, resp, rootFile, pathInfo );
else if ( CmdDirectoryCreate.equals( cmd ) ) cmdDirectoryCreate( req, resp, rootFile, pathInfo );
else if ( CmdRootSelect.equals( cmd ) ) resp.sendRedirect( servletPath + "/" + req.getParameter( FldRootFiles ) + "/" );
else if ( CmdFileSend.equals( cmd ) ) cmdFileSend( req, resp, rootFile, pathInfo );
else if ( CmdFileRemoveDialog.equals( cmd ) ) cmdFileRemoveDialog( req, resp, rootFile, pathInfo );
else if ( CmdFileRemove.equals( cmd ) ) cmdFileRemove( req, resp, rootFile, pathInfo );
else if ( CmdFileRenameDialog.equals( cmd ) ) cmdFileRename( req, resp, rootFile, pathInfo, true );
else if ( CmdFileRename.equals( cmd ) ) cmdFileRename( req, resp, rootFile, pathInfo, false );
else if ( CmdFileUpload.equals( cmd ) ) cmdFileUpload( req, resp, rootFile, pathInfo );
} catch ( Exception exc ) {
throw new ServletException( exc );
};
}
}
-------------- next part --------------
/*
* AbstractFile.java
* This class provides an extendable abstraction of files. An AbstractFile can represent: <ul>
* <li>A local file as implemented by java.lang.File.</li>
* <li>a SMB based file implemented by jcifs.smb.SmbFile </li>
* </ul>
* AbstractFile itself is a superclass providing some basic functions, like createFromURL() and a list of abstract functions
* For each kind of file a subclass has been created (inner subclasses are used only to keep AbstractFile in one file)
* AbstractFile.AFFile / AbstractFile.AFSmbFile implement the abstract functions based on File / SmbFile.
* <br>
* Possible extensions can use registerFactory() to add new schemes and file types - e.g. NFS based or compressed file systems
* AbstractFile also provides generic copy / unzip / zip functions, which facilitate transfer of files / directory trees among various file systems.
*
* Created on 30. Mai 2004, 13:37
*/
package jcifs.util;
import java.io.*;
import java.util.*;
import java.util.regex.*;
import java.util.zip.*;
import jcifs.smb.*;
/**
*
* @author Rolf Breuning (Rolf.Breuning at t-online.de)
*/
public abstract class AbstractFile {
protected static Map factories = new java.util.HashMap();
protected Map attributes; // Extend the file by arbitrary user defined extensions
public static interface AbstractFileFilter {
public boolean accept( AbstractFile file );
};
public static AbstractFileFilter AFFAll = new AbstractFileFilter() {
public boolean accept( AbstractFile file ) { return true; };
};
/**
* Register an AbstractFile as a 'factory' for given 'scheme'.
* The factory will be used to create new AbstractFiles using the AbstractFile.fromURL( url ) method.
* The url for files to be created with the factory have the form [scheme]:[pathname].
* @param scheme String
* @param factory AbstractFile, used as factory
*/
public static void registerFactory( String scheme, AbstractFile factory ) {
factories.put( scheme, factory );
};
static {
registerFactory( AFFile.scheme, new AFFile() );
registerFactory( AFSmbFile.scheme, new AFSmbFile() );
};
/**
* Create a new AbstractFile from the 'url'. 'url' is of the form [scheme]:[pathname].
* The creation will be redirected to the createFromUrl() method of the factory registered for the [scheme].
* @param url String
* @return AbstractFile
*/
public static AbstractFile fromURL( String url ) throws Exception {
String scheme = url.split( ":" ) [0];
AbstractFile factory = (AbstractFile) factories.get( scheme );
return factory.createFromURL( url );
}
/**
* Create a new instance of the receiver's class for the given 'url' of the form [scheme]:[pathname]
* This method allows the receiver to be used as a factory for new abstract files of the same class.
* @param url String
* @throws Exception
* @return
*/
public abstract AbstractFile createFromURL( String url ) throws Exception;
/** Return true if the file / directory represented by the receiver exists
* @throws Exception
* @return */
public abstract boolean exists() throws Exception;
/** Return the absolute url name of the receiver.
* The result ends on "/" for a directory and without "/" for usual files.
* @throws Exception
* @return */
public abstract String getAbsoluteURL() throws Exception;
/** Return a generic map of attributes free for use of the application programmer
* @return */
public Map getAttributes() { if ( attributes == null ) attributes = new java.util.HashMap(); return attributes; }
/** Return the file or directory name, i.e. the last element of the full path. Always without any path separators.
* @throws Exception
* @return */
public abstract String getName();
/** Create a new abstract file or directory defined by the combination of the receiver's url and the 'path'.
* The receiver must be a directory. The 'path' contains directory names and possibly a file name, separated by "/".
* @param path
* @throws Exception
* @return */
public abstract AbstractFile getChild( String path ) throws Exception;
/** Return the directory where the receiver is located in.
* @throws Exception
* @return */
public abstract AbstractFile getParent() throws Exception;
/** The receiver must represent a file. Return an input stream which allows to read the file contents.
* @throws Exception
* @return */
public abstract InputStream getInputStream() throws Exception;
/** The receiver must represent a file. Return an output stream which allows to write to the file.
* If 'append' is true, add any new contents to the end of the file
* @return
* @param append
* @throws Exception
*/
public abstract OutputStream getOutputStream( boolean append ) throws Exception;
/** Return the length of the file or directory in bytes.
* @throws Exception
* @return */
public abstract long length() throws Exception;
/** Return the last modified time of the receiver in milliseconds since January 1st, 1970
* @throws Exception
* @return */
public abstract long lastModified() throws Exception;
/** Return true if the receiver is a directory
* @throws Exception
* @return */
public abstract boolean isDirectory() throws Exception;
/** Return true if the receiver is a file
* @throws Exception
* @return */
public abstract boolean isFile() throws Exception;
/** Delete the receiver. If the receiver is a directory, also delete its contents.
* @throws Exception */
public abstract void delete() throws Exception;
/** Create the receiver directory and if necessary its parents
* @throws Exception */
public abstract void mkdirs() throws Exception;
/** Rename the file identified by the receiver to the 'target' file.
* This effects the actual file identified, both the receiver object and the target object will remain unchanged.
* @param target
* @throws Exception
*/
public abstract void renameTo( AbstractFile target ) throws Exception;
/** List all files or directories which are direct children of the receiver.
* @throws Exception
* @return */
public abstract AbstractFile[] listFiles() throws Exception;
/** List files or directories which are direct children of the receiver and which match the 'filter'.
* @param filter
* @throws Exception
* @return */
public AbstractFile[] listFiles(AbstractFileFilter filter) throws Exception {
AbstractFile files[] = listFiles();
int r = 0;
for ( int i=0; i<files.length; i++ )
if ( filter.accept( files[i] ) ) files[r++] = files[i];
AbstractFile result[] = new AbstractFile[r];
System.arraycopy( files, 0, result, 0, r );
return result;
};
/**
* Copy all bytes from the 'in' stream to the 'out' stream, until the 'in' stream is finished and
* return the number of bytes copied. Use 'buffer' to copy the bytes.
* Depending on the 'in' stream's implementation the method can block (idle or busy)
* until the 'in' stream is finished.
*
* <br>Creation date: (23.08.00 19.14.34)
*
* return long
* @param in java.io.InputStream
* @param out java.io.OutputStream
* @param buffer byte[]
* @exception java.io.IOException The exception description.
*/
public final static long copy(java.io.InputStream in, java.io.OutputStream out, byte buffer[] ) throws java.io.IOException {
int length;
long totalLength = 0;
while ( ( length = in.read( buffer ) ) >= 0 ) {
totalLength += length;
out.write( buffer, 0, length );
};
return totalLength;
}
/** All files in 'files' will be added to the 'zipStream'. All directories in 'files' will be added
* recursively including all files and subdirectories, even empty subdirectories. If 'files' contains a directory
* exactely matching the 'basePath', there will be no entry for this directory, only for the recursive contents.
* <p>
* File names will be stored with their absolute path names. If such a name includes the 'basePath' and /
* or a leading path separator, these parts will be removed from the name. The 'newBasePath' will be added
* as a leading base path.
*
* Creation date: (10.02.2002 21:48:43)
* @param newBasePath
* @param zipStream
* @param baseURL Start of URL pointing to a directory to be removed from the beginning of each file's URL
* @param files Array of AbstracFiles to be copied into the 'zipStream' including all subdirectories
* @throws Exception
*/
public static void zip(ZipOutputStream zipStream, String baseURL, String newBasePath, AbstractFile files[]) throws Exception {
AbstractFile sourceFile;
String sourceURL;
String destEntry;
InputStream sourceStream = null;
// Ersure baseURL is a canonical directory name ending with "/", newBasePath end without "/" -> remaining zip path never starts with "/"
if ( ! baseURL.endsWith( "/" ) ) baseURL += "/";
AbstractFile baseDir = AbstractFile.fromURL( baseURL );
if ( ! baseDir.isDirectory() ) throw new Exception( "'baseURL' must point to valid directory" );
baseURL = baseDir.getAbsoluteURL();
if ( newBasePath.endsWith( "/" ) ) newBasePath = newBasePath.substring( 0, newBasePath.length()-1 );
Vector allFiles = new Vector( Arrays.asList( files ) );
try {
for ( int i=0; i<allFiles.size(); i++ ) { // Note: 'allFiles' may grow when including directories
sourceFile = (AbstractFile) allFiles.elementAt(i);
sourceURL = sourceFile.getAbsoluteURL();
if ( sourceURL.startsWith( baseURL ) ) sourceURL = sourceURL.substring( baseURL.length() );
destEntry = newBasePath + sourceURL;
if ( sourceFile.isDirectory() ) { // directory, add subelements to 'allFiles'
if ( sourceURL.length() > 0 ) zipStream.putNextEntry( new ZipEntry( destEntry ) );
allFiles.addAll( Arrays.asList( sourceFile.listFiles() ) );
} else {
zipStream.putNextEntry( new ZipEntry( destEntry ) );
sourceStream = sourceFile.getInputStream();
copy( sourceStream, zipStream, new byte[16000] );
sourceStream.close();
};
zipStream.closeEntry();
};
} finally {
try { sourceStream.close(); } catch ( Exception exc ) {};
}
}
/** The 'inputStream' contains data of a zip file which can be processed via java.util.ZipInputStream.
* Extract the subdirectory starting with "path" and all files and directories included in this subdirectory
* to the 'directory'. path = "" will extract all files included.
* All necessary directories will be created. The 'inputStream' will be closed at the end.
* <br>
* Example:
* <br>The 'in' stream contains the following files: a/a1.txt, a/a2.txt, b/b1.txt, b/b2.txt
* <br>unzip( in, "b", AbstractFile.fromURL( "file://c:/x/" ) ) is called on a Windows machine
* <br>This will extract b/b1.txt -> c:\x\b1.txt, b/b2.txt -> c:\x\b2.txt.
*
* Creation date: (10.02.2002 21:48:43)
* @param inputStream
* @param directory
* @throws Exception
*/
public static void unzip(InputStream inputStream, String path, AbstractFile directory ) throws Exception {
ZipInputStream in = new ZipInputStream( inputStream );
ZipEntry entry;
if ( path.length() > 0 && ! path.endsWith( "/" ) ) path += "/";
for ( ; ( entry = in.getNextEntry() ) != null ; ) { // Process next entry
String targetName = entry.getName();
if ( ! targetName.startsWith( path ) ) continue;
targetName = targetName.substring( path.length() );
AbstractFile targetFile = directory.getChild( targetName );
if ( entry.isDirectory() ) {
targetFile.mkdirs();
} else {
targetFile.getParent().mkdirs();
OutputStream targetStream = targetFile.getOutputStream( false );
copy( in, targetStream, new byte[16000] );
targetStream.close();
};
in.closeEntry();
};
in.close();
}
public static class AFFile extends AbstractFile {
protected java.io.File file;
protected boolean isDirectory = false; // Valid only if file does not exist
protected static final String scheme = "file";
/** Return a canonical file name from the url. Please note that this even for directories may end without a trailing file separator
* @param url
* @throws Exception
* @return
*/
public static String fileNameFromURL(String url) throws Exception {
String result = url.substring ( (scheme + ":/").length() ).replace('/', File.separatorChar );
return new File( result ).getCanonicalPath();
}
protected AFFile() {}; // For factory creation
public AFFile( String path ) { file = new File( path ); isDirectory = path.endsWith( File.separator ); };
public AFFile( File aFile, boolean isDirectory ) { file = aFile; this.isDirectory = isDirectory; };
public AFFile( File aFile ) { file = aFile; };
public AbstractFile createFromURL(String url) throws Exception { return new AFFile( new File( fileNameFromURL(url) ), url.endsWith( "/" ) ); }
public boolean exists() throws Exception { return file.exists(); }
public String getAbsoluteURL() throws Exception {
String result = "file:/" + file.getAbsolutePath().replace( File.separatorChar, '/' );
if ( ! result.endsWith( "/" ) && isDirectory() ) result += "/";
return result;
}
public String getName() { return file.getName(); }
public AbstractFile getChild(String path) throws Exception { return createFromURL( getAbsoluteURL() + path ); }
public AbstractFile getParent() throws Exception { return new AFFile( file.getParent() ); }
public InputStream getInputStream() throws Exception { return new FileInputStream( file ); }
public OutputStream getOutputStream(boolean append) throws Exception { return new FileOutputStream( file, append ); }
public boolean isDirectory() throws Exception { return file.exists() ? file.isDirectory() : isDirectory; }
public boolean isFile() throws Exception { return file.isFile(); }
public long lastModified() throws Exception { return file.lastModified(); }
public long length() throws Exception { return file.length(); }
public void delete() throws Exception {
if ( file.isDirectory() ) { // recursive delete
String names[] = file.list();
if ( names == null ) throw new IOException( "Could not open file list of directory: " + file.getPath() );
for ( int i=0; i < names.length; i++ ) new AFFile( new File( file, names[i] ) ).delete();
};
if ( ! file.delete() ) throw new IOException( "Could not remove file or directory: " + file.getPath() );
}
public void mkdirs() throws Exception {
if ( exists() && isDirectory() ) return;
if ( ! file.mkdirs() ) throw new Exception("Could not create directory");
}
public AbstractFile[] listFiles() throws Exception {
File files[] = file.listFiles();
AbstractFile result[] = new AbstractFile[ files.length ];
for (int i=0; i<files.length; i++ )
result[i] = new AFFile( files[i] );
return result;
}
public void renameTo(AbstractFile target) throws Exception {
if ( ! (target instanceof AFFile) ) throw new Exception( "target must be of same type than receiver" );
if ( ! file.renameTo( ( (AFFile) target).file ) ) throw new Exception( "Could not rename file");
}
public String toString() { return "file:/" + file.getAbsolutePath().replace( File.separatorChar, '/' ); }
}
public static class AFSmbFile extends AbstractFile {
protected SmbFile smbFile;
protected static final String scheme = "smb";
static final Pattern pwdPattern = Pattern.compile( "/|(:[^(/@)]*@)" );
protected AFSmbFile() {}; // For factory creation
public AFSmbFile( String pathname ) throws Exception { smbFile = new SmbFile( pathname ); };
public AFSmbFile( SmbFile file ) { smbFile = file; };
public AbstractFile createFromURL(String url) throws Exception { return new AFSmbFile( url ); }
public boolean exists() throws Exception { return smbFile.exists(); }
public String getAbsoluteURL() throws Exception { return smbFile.getCanonicalPath(); }
public String getName() { return smbFile.getName().replaceAll( "/", "" ); }
public AbstractFile getChild(String path) throws Exception { return createFromURL( getAbsoluteURL() + path ); }
public AbstractFile getParent() throws Exception { return new AFSmbFile( smbFile.getParent() ); }
public InputStream getInputStream() throws Exception { return new SmbFileInputStream( smbFile ); }
public OutputStream getOutputStream(boolean append) throws Exception { return new SmbFileOutputStream( smbFile, append ); }
public boolean isDirectory() throws Exception { return smbFile.isDirectory(); }
public boolean isFile() throws Exception { return smbFile.isFile(); }
public long lastModified() throws Exception { return smbFile.lastModified(); }
public long length() throws Exception { return smbFile.length(); }
public void delete() throws Exception { smbFile.delete(); }
public void mkdirs() throws Exception { if (exists() && isDirectory() ) return; smbFile.mkdirs(); }
public AbstractFile[] listFiles() throws Exception {
SmbFile files[] = smbFile.listFiles();
AbstractFile result[] = new AbstractFile[ files.length ];
String orgPath = smbFile.getPath();
for (int i=0; i<files.length; i++ )
result[i] = new AFSmbFile( orgPath + files[i].getName() );
return result;
}
public void renameTo(AbstractFile target) throws Exception {
if ( ! (target instanceof AFSmbFile) ) throw new Exception( "target must be of same type than receiver" );
smbFile.renameTo( ( (AFSmbFile) target).smbFile );
}
/** Return a string representing the receiver path in the form smb://.... ; suppress password
* @return
*/
public String toString() {
String path = smbFile.getCanonicalPath().substring( 6 ); // remove smb:// from path
Matcher m = pwdPattern.matcher( path );
if ( m.find() && path.charAt( m.start() ) == ':' ) path = m.replaceFirst( ":...@" );
return "smb://" + path;
}
}
}
More information about the jcifs
mailing list