io.milton.http.fck.FckFileManagerResource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of milton-server-ce Show documentation
Show all versions of milton-server-ce Show documentation
Milton Community Edition: Supports DAV level 1 and is available on Apache2 license
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 io.milton.http.fck;
import io.milton.common.Path;
import io.milton.resource.CollectionResource;
import io.milton.http.FileItem;
import io.milton.resource.GetableResource;
import io.milton.resource.MakeCollectionableResource;
import io.milton.resource.PutableResource;
import io.milton.http.Range;
import io.milton.resource.Resource;
import io.milton.http.Response;
import io.milton.common.Utils;
import io.milton.http.XmlWriter;
import io.milton.http.exceptions.BadRequestException;
import io.milton.http.exceptions.ConflictException;
import io.milton.http.exceptions.NotAuthorizedException;
import io.milton.common.FileUtils;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FckFileManagerResource extends FckCommon implements GetableResource {
private static final Logger log = LoggerFactory.getLogger( FckFileManagerResource.class );
public final static Path URL = Path.path( "/fck_connector.html" );
//public final static Path URL = Path.path("/editor/filemanager/browser/default/connectors/ettrema/connector.html");
public final static String UPLOAD_RESPONSE_TEMPLATE = "";
// public final static String UPLOAD_RESPONSE_TEMPLATE_NORMAL = ""
// + "\n";
// public final static String UPLOAD_RESPONSE_TEMPLATE = ""
// + "\n";
private FckPostParams uploadParams;
public FckFileManagerResource( CollectionResource folder ) {
super( folder, URL );
}
@Override
public String getUniqueId() {
return "fckeditor";
}
@Override
public String processForm( Map parameters, Map files ) throws ConflictException, NotAuthorizedException, BadRequestException {
uploadParams = new FckPostParams( parameters );
uploadParams.processFileUploadCommand( files );
return null;
}
@Override
public void sendContent( OutputStream out, Range range, Map params, String contentType ) throws IOException, NotAuthorizedException, BadRequestException {
log.debug( "sendContent" );
if( uploadParams != null ) {
String s = UPLOAD_RESPONSE_TEMPLATE;
s = s.replace( "[func]", params.get("CKEditorFuncNum") );
s = s.replace( "[code]", uploadParams.code + "" );
if( uploadParams.message == null ) {
uploadParams.message = "";
}
s = s.replace( "[msg]", uploadParams.message );
if( uploadParams.newName == null ) {
uploadParams.newName = "";
}
s = s.replace( "[name]", uploadParams.newName );
out.write( s.getBytes("UTF-8") );
} else {
FckGetParams getParams = new FckGetParams( out, params );
try {
getParams.process();
} catch( ConflictException ex ) {
throw new RuntimeException( ex );
}
}
}
/** See FCK Integration Guide
*
* fckconfig.js -> FCKConfig.LinkUploadURL
*/
abstract static class FckParams {
CollectionResource target; // from params
final Map params;
FckParams( Map params ) {
this.params = params;
}
}
class FckGetParams extends FckParams {
final String command;
final String resourceType;
String sFolder;
final String serverPath;
final String newFolderName;
private final XmlWriter writer;
private final OutputStream out;
FckGetParams( OutputStream out, Map params ) {
super( params );
this.out = out;
writer = new XmlWriter( out );
command = params.get( "Command" );
resourceType = params.get( "Type" );
sFolder = params.get( "CurrentFolder" );
newFolderName = params.get( "NewFolderName" );
if( sFolder != null ) {
sFolder = sFolder.trim();
if( sFolder.length() == 0 ) {
sFolder = null;
}
}
serverPath = params.get( "ServerPath" );
}
void process() throws ConflictException, NotAuthorizedException, BadRequestException {
String relFolder = sFolder.substring( 1 );
Path p = Path.path( relFolder );
Resource r = find( wrappedResource, p );
if( r instanceof CollectionResource ) {
target = (CollectionResource) r;
} else {
log.warn("not found or not CollectionResource: " + r);
}
if( target == null ) {
log.warn( "No PutableResource with that path: " + sFolder );
throw new BadRequestException( "Path not found: " + sFolder );
}
try {
switch (command) {
case "GetFolders":
processGetFoldersCommand(false);
break;
case "GetFoldersAndFiles":
processGetFoldersCommand(true);
break;
case "CreateFolder":
processCreateFolderCommand();
break;
case "FileUpload":
processUploadFolderCommand();
break;
default:
log.warn("Unknown command: " + command);
throw new ConflictException(target);
}
} finally {
writer.flush();
}
}
void initXml() {
writer().writeXMLHeader();
}
void processGetFoldersCommand( boolean includeFiles ) throws NotAuthorizedException, BadRequestException {
initXml();
XmlWriter.Element el = writer().begin( "Connector" );
el.writeAtt( "command", command );
el.writeAtt( "resourceType", resourceType );
el.open();
el = writer().begin( "CurrentFolder" );
el.writeAtt( "path", sFolder );
el.writeAtt( "url", sFolder );
el.noContent();
writer().open( "Folders" );
writer().writeText( "\n" );
for( Resource r : Optional.ofNullable(target.getChildren()).orElse(List.of()) ) {
if( r instanceof CollectionResource ) {
el = writer().begin( "Folder" );
String nm = Utils.escapeXml( r.getName() );
el.writeAtt( "name", nm );
el.noContent();
}
}
writer().close( "Folders" );
if( includeFiles ) {
writer().open( "Files" );
writer().writeText( "\n" );
for( Resource r : Optional.ofNullable(target.getChildren()).orElse(List.of()) ) {
if( !( r instanceof CollectionResource ) ) {
el = writer().begin( "File" );
String nm = Utils.escapeXml( r.getName() );
el.writeAtt( "name", nm );
if( r instanceof GetableResource ) {
GetableResource gr = (GetableResource) r;
Long sz = gr.getContentLength();
String sSize = ( sz == null ? "" : sz.toString() );
el.writeAtt( "size", sSize );
el.noContent();
} else {
el.writeAtt( "size", "" );
}
}
}
writer().close( "Files" );
}
writer().close( "Connector" );
writer().flush();
}
void processCreateFolderCommand() {
log.debug( "processCreateFolderCommand: " + newFolderName );
int errNumber;
try {
if( target.child( newFolderName ) != null ) {
log.debug( "has child" );
errNumber = 101;
} else {
if( target instanceof MakeCollectionableResource ) {
MakeCollectionableResource mk = (MakeCollectionableResource) target;
CollectionResource f = mk.createCollection( newFolderName );
} else {
throw new BadRequestException( target, "Folder does not allow creating subfolders" );
}
log.debug( "add new child ok" );
errNumber = 0;
}
} catch( Throwable e ) {
errNumber = 103;
log.error( "Exception creating new folder: " + newFolderName + " in " + target.getName(), e );
}
initXml();
XmlWriter.Element el = writer().begin( "Connector" );
el.writeAtt( "command", command );
el.writeAtt( "resourceType", resourceType );
el.open();
el = writer().begin( "CurrentFolder" );
el.writeAtt( "path", sFolder );
el.writeAtt( "url", sFolder );
el.noContent();
el = writer().begin( "Error" );
el.writeAtt( "number", "" + errNumber );
el.noContent();
writer().close( "Connector" );
writer().flush();
}
XmlWriter writer() {
return writer;
}
private void processUploadFolderCommand() {
if( uploadParams == null ) {
throw new NullPointerException( "no post for upload command" );
}
StringBuilder sb = new StringBuilder();
sb.append( "\n" );
String s = sb.toString();
try {
out.write( s.getBytes("UTF-8") );
out.flush();
} catch( IOException e ) {
log.warn( "ioexception writing response to upload", e );
}
}
}
private Resource find( CollectionResource wrappedResource, Path p ) throws NotAuthorizedException, BadRequestException {
Resource r = wrappedResource;
for( String s : p.getParts() ) {
if( r instanceof CollectionResource ) {
CollectionResource col = (CollectionResource) r;
r = col.child( s );
if( r == null ) {
log.trace( "not found: " + s + " in path: " + p );
return null;
}
} else {
log.trace( "not a collection: " + r.getName() + " in path: " + p );
return null;
}
}
return r;
}
class FckPostParams extends FckParams {
int code;
String message;
String newName;
FckPostParams( Map params ) {
super( params );
}
void processFileUploadCommand( Map files ) throws ConflictException, NotAuthorizedException, BadRequestException {
Collection col = files.values();
if( col == null || col.isEmpty() ) {
log.debug( "no files uploaded" );
} else {
log.debug( "files: " + col.size() );
for( FileItem f : col ) {
processFileUpload( f );
break; // only file at a time
}
}
}
private void processFileUpload( FileItem f ) throws ConflictException, NotAuthorizedException, BadRequestException {
String sFolder = params.get( "CurrentFolder" );
log.info( "processFileUpload: sFolder: " + sFolder + " - " + sFolder.length() );
String relFolder = sFolder.substring( 1 );
Path p = Path.path( relFolder );
Resource r = find( wrappedResource, p );
if( r instanceof PutableResource ) {
target = (PutableResource) r;
}
if( target == null ) {
log.warn( "No putable folder with that path: " + sFolder );
throw new ConflictException( target );
}
String name = f.getName(); //utilFile().sanitiseName(f.getName());
log.info( "processFileUpload: " + name );
boolean isFirst = true;
while( target.child( name ) != null ) {
name = FileUtils.incrementFileName( name, isFirst );
newName = name;
isFirst = false;
}
PutableResource putable;
if( target instanceof PutableResource) {
putable = (PutableResource) target;
} else {
log.warn("The collection is not putable: " + r.getName() + " - " + r.getClass().getCanonicalName());
throw new ConflictException( r );
}
long size = f.getSize();
try {
Resource newRes = putable.createNew( name, f.getInputStream(), size, null );
} catch( ConflictException ex ) {
throw ex;
} catch( NotAuthorizedException | IOException | BadRequestException ex ) {
throw new RuntimeException( ex );
}
try {
if( newName != null ) { // we renamed the file
uploadResponseOk( name );
} else {
uploadResponseOk();
}
} catch( Throwable ex ) {
log.error( "Exception saving new file", ex );
uploadResponseFailed( ex.getMessage() );
}
}
private void uploadResponseOk() {
uploadResponse( 0, null );
}
private void uploadResponseOk( String newName ) {
uploadResponse( 201, newName );
}
private void uploadResponseFailed( String reason ) {
uploadResponse( 1, reason );
}
private void uploadResponse( int code, String message ) {
this.code = code;
this.message = message;
}
}
@Override
public String getContentType( String accepts ) {
String s;
if( uploadParams != null ) {
s = Response.HTTP;
} else {
s = Response.XML;
}
return s;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy