mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Partial fix for AWC-999: Content upload guesses character encoding and offers the user the chance to change it.
TODO: Fix the "Modify Content Properties" to include the encoding as a changeable option. Modified other entry points of content into the system. All calls to ContentWriter.setEncoding("UTF-8") need some serious examination. It is no longer necessary to assume anything about the encoding. The worst case scenario is that we guess the encoding from the stream without giving the user the chance to change it. This works for most non-interactive scenarios like CIFS, WebDAV and FTP, now. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6113 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -25,6 +25,8 @@
|
||||
package org.alfresco.web.bean.ajax;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.HashMap;
|
||||
@@ -125,8 +127,31 @@ public class FileUploadBean
|
||||
NodeRef containerRef = pathToNodeRef(fc, currentPath);
|
||||
if (containerRef != null)
|
||||
{
|
||||
// Try and extract metadata from the file
|
||||
// Guess the mimetype
|
||||
String mimetype = Repository.getMimeTypeForFileName(fc, filename);
|
||||
|
||||
// Now guess the encoding
|
||||
String encoding = "UTF-8";
|
||||
InputStream is = null;
|
||||
try
|
||||
{
|
||||
is = new FileInputStream(file);
|
||||
encoding = Repository.guessEncoding(fc, is, mimetype);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// Bad as it is, it's not terminal
|
||||
logger.error("Failed to guess character encoding of file: " + file, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (is != null)
|
||||
{
|
||||
try { is.close(); } catch (Throwable e) {}
|
||||
}
|
||||
}
|
||||
|
||||
// Try and extract metadata from the file
|
||||
ContentReader cr = new FileContentReader(file);
|
||||
cr.setMimetype(mimetype);
|
||||
|
||||
@@ -170,7 +195,7 @@ public class FileUploadBean
|
||||
// get a writer for the content and put the file
|
||||
ContentWriter writer = services.getContentService().getWriter(fileNodeRef, ContentModel.PROP_CONTENT, true);
|
||||
writer.setMimetype(mimetype);
|
||||
writer.setEncoding("UTF-8");
|
||||
writer.setEncoding(encoding);
|
||||
writer.putContent(file);
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,10 @@
|
||||
*/
|
||||
package org.alfresco.web.bean.content;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
@@ -68,6 +71,7 @@ public class AddContentDialog extends BaseContentWizard
|
||||
// Try and extract metadata from the file
|
||||
ContentReader cr = new FileContentReader(this.file);
|
||||
cr.setMimetype(this.mimeType);
|
||||
cr.setEncoding(this.encoding);
|
||||
// create properties for content type
|
||||
Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>(5, 1.0f);
|
||||
|
||||
@@ -148,9 +152,29 @@ public class AddContentDialog extends BaseContentWizard
|
||||
// NOTE: This is a far from ideal solution but will do until we have
|
||||
// a pure JSF upload solution working. This method is only called
|
||||
// after a file is uploaded, so we can calculate the mime type and
|
||||
// determine whether to enable inline editing in here.
|
||||
this.mimeType = Repository.getMimeTypeForFileName(
|
||||
FacesContext.getCurrentInstance(), this.fileName);
|
||||
// determine whether to enable inline editing in here.
|
||||
FacesContext fc = FacesContext.getCurrentInstance();
|
||||
this.mimeType = Repository.getMimeTypeForFileName(fc, this.fileName);
|
||||
this.encoding = "UTF-8";
|
||||
InputStream is = null;
|
||||
try
|
||||
{
|
||||
if (this.file != null)
|
||||
{
|
||||
is = new BufferedInputStream(new FileInputStream(this.file));
|
||||
this.encoding = Repository.guessEncoding(fc, is, this.mimeType);
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// Not terminal
|
||||
logger.error("Failed to get encoding from file: " + this.fileName, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { is.close(); } catch (Throwable e) {} // Includes NPE
|
||||
}
|
||||
|
||||
this.inlineEdit = (this.mimeType.equals(MimetypeMap.MIMETYPE_HTML));
|
||||
|
||||
// get the file upload message
|
||||
|
@@ -26,6 +26,7 @@ package org.alfresco.web.bean.content;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -68,6 +69,7 @@ public abstract class BaseContentWizard extends BaseWizardBean
|
||||
protected String title;
|
||||
protected String description;
|
||||
protected String mimeType;
|
||||
protected String encoding;
|
||||
protected String objectType;
|
||||
protected boolean inlineEdit;
|
||||
protected boolean otherPropertiesChoiceVisible = true;
|
||||
@@ -159,7 +161,23 @@ public abstract class BaseContentWizard extends BaseWizardBean
|
||||
{
|
||||
this.mimeType = mimeType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Returns the encoding currently selected
|
||||
*/
|
||||
public String getEncoding()
|
||||
{
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param encoding the document's encoding
|
||||
*/
|
||||
public void setEncoding(String encoding)
|
||||
{
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the object type currenty selected
|
||||
*/
|
||||
@@ -250,6 +268,18 @@ public abstract class BaseContentWizard extends BaseWizardBean
|
||||
this.showOtherProperties = showOthers;
|
||||
}
|
||||
|
||||
public List<SelectItem> getEncodings()
|
||||
{
|
||||
Map<String, Charset> availableCharsets = Charset.availableCharsets();
|
||||
List<SelectItem> items = new ArrayList<SelectItem>(availableCharsets.size());
|
||||
for (Charset charset : availableCharsets.values())
|
||||
{
|
||||
SelectItem item = new SelectItem(charset.name(), charset.displayName());
|
||||
items.add(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns a list of object types to allow the user to select from
|
||||
*/
|
||||
@@ -407,7 +437,7 @@ public abstract class BaseContentWizard extends BaseWizardBean
|
||||
ContentWriter writer = contentService.getWriter(fileNodeRef, ContentModel.PROP_CONTENT, true);
|
||||
// set the mimetype and encoding
|
||||
writer.setMimetype(this.mimeType);
|
||||
writer.setEncoding("UTF-8");
|
||||
writer.setEncoding(this.encoding);
|
||||
if (fileContent != null)
|
||||
{
|
||||
writer.putContent(fileContent);
|
||||
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.web.bean.generator;
|
||||
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.context.FacesContext;
|
||||
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.web.app.servlet.FacesHelper;
|
||||
import org.alfresco.web.ui.repo.component.UICharsetSelector;
|
||||
import org.alfresco.web.ui.repo.component.property.PropertySheetItem;
|
||||
import org.alfresco.web.ui.repo.component.property.UIPropertySheet;
|
||||
import org.alfresco.web.ui.repo.converter.CharsetConverter;
|
||||
|
||||
/**
|
||||
* Generates a Charset selector component.
|
||||
*
|
||||
* @since 2.1
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class CharsetSelectorGenerator extends BaseComponentGenerator
|
||||
{
|
||||
public UIComponent generate(FacesContext context, String id)
|
||||
{
|
||||
UIComponent component = context.getApplication().createComponent(UICharsetSelector.COMPONENT_TYPE);
|
||||
FacesHelper.setupComponentId(context, component, id);
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupConverter(FacesContext context,
|
||||
UIPropertySheet propertySheet, PropertySheetItem property,
|
||||
PropertyDefinition propertyDef, UIComponent component)
|
||||
{
|
||||
if (propertySheet.inEditMode() == false)
|
||||
{
|
||||
if (property.getConverter() != null)
|
||||
{
|
||||
// create and add the custom converter
|
||||
createAndSetConverter(context, property.getConverter(), component);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there isn't a custom converter add the mime type converter as a default
|
||||
createAndSetConverter(context, CharsetConverter.CONVERTER_ID, component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupMandatoryValidation(FacesContext context,
|
||||
UIPropertySheet propertySheet, PropertySheetItem item,
|
||||
UIComponent component, boolean realTimeChecking, String idSuffix)
|
||||
{
|
||||
// a mime type selector will always have one value or another
|
||||
// so there is no need to create a mandatory validation rule.
|
||||
}
|
||||
}
|
@@ -22,7 +22,9 @@
|
||||
* http://www.alfresco.com/legal/licensing" */
|
||||
package org.alfresco.web.bean.repository;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -37,6 +39,7 @@ import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.configuration.ConfigurableService;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.content.encoding.ContentCharsetFinder;
|
||||
import org.alfresco.repo.content.metadata.MetadataExtracter;
|
||||
import org.alfresco.repo.content.metadata.MetadataExtracterRegistry;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
@@ -507,6 +510,21 @@ public final class Repository
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the characterset from the stream
|
||||
*
|
||||
* @param context the Faces Context
|
||||
* @param is the stream of characters or data
|
||||
* @param mimetype the stream's mimetype, or <tt>null</tt> if unknown
|
||||
* @return Returns the guessed characterset and never <tt>null</tt>
|
||||
*/
|
||||
public static String guessEncoding(FacesContext context, InputStream is, String mimetype)
|
||||
{
|
||||
ContentCharsetFinder charsetFinder = getServiceRegistry(context).getMimetypeService().getContentCharsetFinder();
|
||||
Charset charset = charsetFinder.getCharset(is, mimetype);
|
||||
return charset.name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query a list of Person type nodes from the repo
|
||||
|
@@ -37,7 +37,6 @@ import org.alfresco.service.cmr.avm.AVMService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.web.app.AlfrescoNavigationHandler;
|
||||
import org.alfresco.web.bean.content.AddContentDialog;
|
||||
|
||||
/**
|
||||
@@ -101,7 +100,7 @@ public class AddAvmContentDialog extends AddContentDialog
|
||||
// get a writer for the content and put the file
|
||||
ContentWriter writer = contentService.getWriter(fileNodeRef, ContentModel.PROP_CONTENT, true);
|
||||
writer.setMimetype(this.mimeType);
|
||||
writer.setEncoding("UTF-8");
|
||||
writer.setEncoding(this.encoding);
|
||||
if (fileContent != null)
|
||||
{
|
||||
writer.putContent(fileContent);
|
||||
|
Reference in New Issue
Block a user