mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
35224: ALF-12038: Remove trailing JSON comma causing IE7 script error 35226: ALF-13401 - Saving PowerPoint (mac 2011) via CIFS fails in Mac OS X Lion 35239: ALF-13409: Further fix to deal with concurrent deletion of a user's site invitations in background 35245: ALF-13281: Enabled use of autocomplete in IE for forms runtime. This change also allows multiple events to be attached per validation handler 35253: ALF-13640: Fixed issues with updating task associations + added new test + fixed existing activiti-component-tests 35271: Translation updates (fixes: ALF-13434) - based on EN r35212. (Dutch still to follow) 35281: ALF-13227: Fix CSS for Wiki layout of nested lists 35284: SPANISH: Update from Gloria 35290: More debug + unit test for mac powerpoint shuffle. 35291: Added isTemporary method 35295: ALF-13453 : Remote Code Execution (can create reverse shell). - Added ability for XMLUtil parse callers to provide an optional array of XMLFilterImpl to be used while parsing. -Added secureParseXSL methods that automatically install an XMLFilterImpl that causes a parse failure if any insecure namespaces are encountered. 35303: Fix for ALF-12444 Node Browser improvement: Index single node and remove single node from indexes Part of ALF-13723 SOLR does not include the same query unit tests as lucene 35305: ALF-13723 SOLR does not include the same query unit tests as lucene - test template 35306: ALF-13723 SOLR does not include the same query unit tests as lucene - template for creating test cores 35323: ALF-13420: Natural sort on form option labels and improvement for CSS - specifically to address transform action in document details. 35328: ALF-13409: Avoid concurrency issues in unit test tear downs by deleting users before sites. User deletion deletes invitations synchronously. Site deletion deletes invitations concurrently to avoid UI timeouts. The potential to access invitations that are being concurrently deleted still exists, but always did! 35331: ALF-12126: Ensure that DND upload is disabled for users with only consumer access 35335: ALF-13708: Merged V3.4-BUG-FIX (3.4.10) to V4.0-BUG-FIX (4.0.2) 35235: ALF-13673: Amp-loaded duplicated mimetypes should be handled - Modified code to allow duplicates to replace parts of the existing mimetype definitions. - A warning is logged each time. 35336: Spanish and Dutch updates from Gloria, based on EN r35212 35355: Merged V3.4-BUG-FIX to V4.0-BUG-FIX 35213: ALF-13686: Merged PATCHES/V3.4.8 to V3.4-BUG-FIX 34943: ALF-13121: Option to create users either as user1 or user1@domain.com after kerberos authentication - New Kerberos subsystem parameter kerberos.authentication.stripUsernameSuffix introduced - When true (the default) the @domain sufix will be stripped from Kerberos authenticated usernames in CIFS, SPP, WebDAV and the Web Client - When false, should enable a multi-domain customer to use Alfresco (says Mr Gninot) 35096: ALF-13121: Added missing stripKerberosUsernameSuffix property to sharepointAuthenticationHandler 35215: ALF-13065: Ensure Wiki new page save button is available on HTML edit action 35219: ALF-11898: Fixed TinyMCE create HTML content problem for Explorer client 35261: Translation updates based on EN r35144 35339: AD 2008 R2, user import via LDAP fails with over 1000 users - Problem discovered by Community user with simple workaround https://forums.alfresco.com/en/viewtopic.php?f=57&t=43960&sid=5569e5cfbccb3776e11ef4a8e9d50378&p=129664#p129664 35353: Merged V3.4 to V3.4-BUG-FIX 35279: ALF-13713: Merged PATCHES/V3.4.8 to V3.4 35146: Merged DEV to PATCHES/V3.4.8 35130: ALF-13472: Webdav Does not allow a user to access spaces without read permission on parent spaces Receiving of indirect lock is wrapped into AuthenticationUtil.runAs() invocation to provide a possibility of getting indirect lock for users with appropriate access rights for requested resource 35280: ALF-10353: Internet Explorer hangs when using the object picker with a larger number of documents - reviewed by DD 35318: ALF-13715: Merged HEAD to V3.4 31743: Fixed ALF-10157: Web Form Details page for the "Selected Web Content Forms": script error appears on help button click: container.jsp (line 382) 35341: ALF-13552: Merged V4.0 to V3.4 35296: ALF-13453: Remote Code Execution (can create reverse shell) - Fix by Shane 35304: ALF-13453: Extra fix to ensure xalan namespace isn't declared with global scope and can't be hijacked by an input stylesheet 35307: ALF-13453: Duplicated extra fix to duplicate code in XSLTRenderingEngine! 35354: Merged V3.4 to V3.4-BUG-FIX (RECORD ONLY) 35266: Merged V3.4-BUG-FIX to V3.4 35261: Translation updates based on EN r35144 35334: Merged V3.4-BUG-FIX to V3.4 35235: ALF-13673: Amp-loaded duplicated mimetypes should be handled - Modified code to allow duplicates to replace parts of the existing mimetype definitions. - A warning is logged each time. 35356: Merged V4.0 to V4.0-BUG-FIX 35292: ALF-13721: Merged PATCHES/V4.0.0 to V4.0 35240: Fix for ALF-13685 The SOLr textContent webscript is not protected by authentication and permission checks. 35242: Fix for ALF-13685 The SOLr textContent webscript is not protected by authentication and permission checks. - /wcs/api/solr and /wcservice/api/solr 35304: ALF-13453: Extra fix to ensure xalan namespace isn't declared with global scope and can't be hijacked by an input stylesheet 35307: ALF-13453: Duplicated extra fix to duplicate code in XSLTRenderingEngine! 35357: Merged V4.0 to V4.0-BUG-FIX (RECORD ONLY) 35048: Merged V4.0-BUG-FIX to V4.0 35031: Fix for ALF-12309: Script errors on site pages 35293: Merged V4.0-BUG-FIX to V4.0 35172: ALF-13626: category.put.json.ftl has wrong bracket 35296: Merged V4.0-BUG-FIX to V4.0 35295: ALF-13453: Remote Code Execution (can create reverse shell) - Fix by Shane git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@35359 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
422 lines
13 KiB
Java
422 lines
13 KiB
Java
/*
|
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
|
*
|
|
* This file is part of Alfresco
|
|
*
|
|
* Alfresco is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Alfresco 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package org.alfresco.web.bean.content;
|
|
|
|
import java.io.Serializable;
|
|
import java.text.MessageFormat;
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.ResourceBundle;
|
|
|
|
import javax.faces.context.FacesContext;
|
|
import javax.faces.event.ValueChangeEvent;
|
|
import javax.faces.model.SelectItem;
|
|
|
|
import org.springframework.extensions.config.Config;
|
|
import org.springframework.extensions.config.ConfigElement;
|
|
import org.springframework.extensions.config.ConfigService;
|
|
import org.alfresco.model.ContentModel;
|
|
import org.alfresco.model.WCMAppModel;
|
|
import org.alfresco.repo.content.MimetypeMap;
|
|
import org.alfresco.service.cmr.model.FileExistsException;
|
|
import org.alfresco.service.namespace.QName;
|
|
import org.alfresco.web.app.AlfrescoNavigationHandler;
|
|
import org.alfresco.web.app.Application;
|
|
import org.alfresco.web.app.servlet.FacesHelper;
|
|
import org.alfresco.web.bean.repository.Node;
|
|
import org.alfresco.web.bean.repository.Repository;
|
|
import org.alfresco.web.data.IDataContainer;
|
|
import org.alfresco.web.data.QuickSort;
|
|
import org.alfresco.web.forms.Form;
|
|
import org.alfresco.web.forms.FormNotFoundException;
|
|
import org.alfresco.web.forms.FormProcessor;
|
|
import org.alfresco.web.forms.FormsService;
|
|
import org.alfresco.util.XMLUtil;
|
|
import org.alfresco.web.ui.common.Utils;
|
|
import org.apache.commons.io.FilenameUtils;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
import org.w3c.dom.Document;
|
|
|
|
/**
|
|
* Bean implementation for the "Create Content Wizard" dialog
|
|
*
|
|
* @author gavinc
|
|
*/
|
|
public class CreateContentWizard extends BaseContentWizard
|
|
{
|
|
private static final long serialVersionUID = -2740634368271194418L;
|
|
|
|
protected String content = null;
|
|
protected List<SelectItem> createMimeTypes;
|
|
|
|
transient protected FormsService formsService;
|
|
protected String formName;
|
|
protected FormProcessor.Session formProcessorSession = null;
|
|
transient protected Document instanceDataDocument = null;
|
|
|
|
private static Log logger = LogFactory.getLog(CreateContentWizard.class);
|
|
|
|
|
|
/**
|
|
* @param formsService The FormsService to set.
|
|
*/
|
|
public void setFormsService(final FormsService formsService)
|
|
{
|
|
this.formsService = formsService;
|
|
}
|
|
|
|
/**
|
|
* @return the formsService
|
|
*/
|
|
private FormsService getFormsService()
|
|
{
|
|
//check for null for cluster environment
|
|
if (formsService == null)
|
|
{
|
|
formsService = (FormsService) FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "FormsService");
|
|
}
|
|
return formsService;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
// Wizard implementation
|
|
|
|
|
|
@Override
|
|
public String finish()
|
|
{
|
|
// if a form is entered, then save the form instance data as XML ...
|
|
if (this.instanceDataDocument != null)
|
|
{
|
|
this.content = XMLUtil.toString(this.instanceDataDocument, true);
|
|
|
|
this.mimeType = MimetypeMap.MIMETYPE_XML; // belts & braces - override mimetype (in case is not set to XML)
|
|
}
|
|
|
|
String result = super.finish();
|
|
|
|
if ((super.createdNode != null) && (this.instanceDataDocument != null))
|
|
{
|
|
final Map<QName, Serializable> props = new HashMap<QName, Serializable>(1, 1.0f);
|
|
props.put(WCMAppModel.PROP_PARENT_FORM_NAME, getFormName());
|
|
props.put(WCMAppModel.PROP_ORIGINAL_PARENT_PATH, "");
|
|
getNodeService().addAspect(super.createdNode, WCMAppModel.ASPECT_FORM_INSTANCE_DATA, props);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
protected String finishImpl(FacesContext context, String outcome)
|
|
throws Exception
|
|
{
|
|
saveContent(null, this.content);
|
|
|
|
// return the default outcome
|
|
return outcome;
|
|
}
|
|
|
|
@Override
|
|
public void init(Map<String, String> parameters)
|
|
{
|
|
super.init(parameters);
|
|
|
|
this.content = null;
|
|
this.inlineEdit = true;
|
|
this.mimeType = MimetypeMap.MIMETYPE_HTML;
|
|
this.formName = "";
|
|
|
|
this.instanceDataDocument = null;
|
|
if (this.formProcessorSession != null)
|
|
{
|
|
this.formProcessorSession.destroy();
|
|
}
|
|
this.formProcessorSession = null;
|
|
}
|
|
|
|
@Override
|
|
public boolean getNextButtonDisabled()
|
|
{
|
|
// TODO: Allow the next button state to be configured so that
|
|
// wizard implementations don't have to worry about
|
|
// checking step numbers
|
|
|
|
boolean disabled = false;
|
|
int step = Application.getWizardManager().getCurrentStep();
|
|
switch(step)
|
|
{
|
|
case 1:
|
|
{
|
|
disabled = (this.fileName == null || this.fileName.length() == 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return disabled;
|
|
}
|
|
|
|
|
|
@Override
|
|
public boolean getFinishButtonDisabled()
|
|
{
|
|
boolean disabled = false;
|
|
int step = Application.getWizardManager().getCurrentStep();
|
|
switch(step)
|
|
{
|
|
case 1:
|
|
{
|
|
disabled = (this.fileName == null || this.fileName.length() == 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return disabled;
|
|
}
|
|
|
|
@Override
|
|
protected String doPostCommitProcessing(FacesContext context, String outcome)
|
|
{
|
|
// as we were successful, go to the set properties dialog if asked
|
|
// to otherwise just return
|
|
if (this.showOtherProperties)
|
|
{
|
|
// check whether the created node is checked out, if a 'check out'
|
|
// rule is present in the space the new node will be and an
|
|
// attempt to modify the properties will cause an error (ALF-438)
|
|
if (getNodeService().hasAspect(this.createdNode, ContentModel.ASPECT_LOCKABLE))
|
|
{
|
|
Utils.addErrorMessage(Application.getMessage(FacesContext.getCurrentInstance(), MSG_NODE_LOCKED));
|
|
return outcome;
|
|
}
|
|
else
|
|
{
|
|
// we are going to immediately edit the properties so we need
|
|
// to setup the BrowseBean context appropriately
|
|
this.browseBean.setDocument(new Node(this.createdNode));
|
|
|
|
return getDefaultFinishOutcome() + AlfrescoNavigationHandler.OUTCOME_SEPARATOR +
|
|
"dialog:setContentProperties";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return outcome;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
// Bean Getters and Setters
|
|
|
|
/**
|
|
* @return Returns the content from the edited form.
|
|
*/
|
|
public String getContent()
|
|
{
|
|
return this.content;
|
|
}
|
|
|
|
/**
|
|
* @param content The content to edit (should be clear initially)
|
|
*/
|
|
public void setContent(String content)
|
|
{
|
|
this.content = content;
|
|
}
|
|
|
|
/**
|
|
* @return Returns a list of mime types to allow the user to select from
|
|
*/
|
|
public List<SelectItem> getCreateMimeTypes()
|
|
{
|
|
if ((this.createMimeTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance())))
|
|
{
|
|
FacesContext context = FacesContext.getCurrentInstance();
|
|
|
|
// add the well known object type to start with
|
|
this.createMimeTypes = new ArrayList<SelectItem>(5);
|
|
|
|
// add the configured create mime types to the list
|
|
ConfigService svc = Application.getConfigService(context);
|
|
Config wizardCfg = svc.getConfig("Content Wizards");
|
|
if (wizardCfg != null)
|
|
{
|
|
ConfigElement typesCfg = wizardCfg.getConfigElement("create-mime-types");
|
|
if (typesCfg != null)
|
|
{
|
|
for (ConfigElement child : typesCfg.getChildren())
|
|
{
|
|
String currentMimeType = child.getAttribute("name");
|
|
if (currentMimeType != null)
|
|
{
|
|
String label = getSummaryMimeType(currentMimeType);
|
|
this.createMimeTypes.add(new SelectItem(currentMimeType, label));
|
|
}
|
|
}
|
|
|
|
// make sure the list is sorted by the label
|
|
QuickSort sorter = new QuickSort(this.objectTypes, "label", true, IDataContainer.SORT_CASEINSENSITIVE);
|
|
sorter.sort();
|
|
}
|
|
else
|
|
{
|
|
logger.warn("Could not find 'create-mime-types' configuration element");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
logger.warn("Could not find 'Content Wizards' configuration section");
|
|
}
|
|
|
|
}
|
|
|
|
return this.createMimeTypes;
|
|
}
|
|
|
|
/**
|
|
* @return Returns the summary data for the wizard.
|
|
*/
|
|
public String getSummary()
|
|
{
|
|
ResourceBundle bundle = Application.getBundle(FacesContext.getCurrentInstance());
|
|
|
|
if (this.instanceDataDocument != null)
|
|
{
|
|
this.mimeType = MimetypeMap.MIMETYPE_XML; // belts & braces - override mimetype (in case is not set to XML)
|
|
}
|
|
|
|
// TODO: show first few lines of content here?
|
|
return buildSummary(
|
|
new String[] {bundle.getString("file_name"),
|
|
bundle.getString("type"),
|
|
bundle.getString("content_type")},
|
|
new String[] {Utils.encode(this.fileName), getSummaryObjectType(),
|
|
getSummaryMimeType(this.mimeType)});
|
|
}
|
|
|
|
/**
|
|
* @return List of UI items to represent the full list of available ECM Forms
|
|
*/
|
|
public List<SelectItem> getFormsList()
|
|
{
|
|
Collection<Form> forms = this.getFormsService().getForms();
|
|
List<SelectItem> items = new ArrayList<SelectItem>(forms.size()+1);
|
|
items.add(new SelectItem("", ""));
|
|
for (Form form : forms)
|
|
{
|
|
items.add(new SelectItem(form.getName(), form.getTitle()));
|
|
}
|
|
return items;
|
|
}
|
|
|
|
public String getFormName()
|
|
{
|
|
return this.formName;
|
|
}
|
|
|
|
public void setFormName(String formName)
|
|
{
|
|
this.formName = formName;
|
|
}
|
|
|
|
public Form getForm() throws FormNotFoundException
|
|
{
|
|
return (this.getFormName() != null
|
|
? getFormsService().getForm(formName)
|
|
: null);
|
|
}
|
|
|
|
public FormProcessor.Session getFormProcessorSession()
|
|
{
|
|
return this.formProcessorSession;
|
|
}
|
|
|
|
public void setFormProcessorSession(final FormProcessor.Session formProcessorSession)
|
|
{
|
|
this.formProcessorSession = formProcessorSession;
|
|
}
|
|
|
|
public Document getInstanceDataDocument()
|
|
{
|
|
if (this.instanceDataDocument == null)
|
|
{
|
|
final String content = this.getContent();
|
|
try
|
|
{
|
|
this.instanceDataDocument = (content != null
|
|
? XMLUtil.parse(content)
|
|
: XMLUtil.newDocument());
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Utils.addErrorMessage("error parsing document", e);
|
|
this.instanceDataDocument = XMLUtil.newDocument();
|
|
}
|
|
}
|
|
return this.instanceDataDocument;
|
|
}
|
|
|
|
/** Overrides in order to strip an xml extension if the user entered it */
|
|
// TODO do we need ? it is currently referenced in create-forms.jsp (copied from wcm create-xml.jsp)
|
|
@Override
|
|
public String getFileName()
|
|
{
|
|
final String result = super.getFileName();
|
|
return (result != null &&
|
|
MimetypeMap.MIMETYPE_XML.equals(this.mimeType) &&
|
|
this.getFormName() != null &&
|
|
"xml".equals(FilenameUtils.getExtension(result).toLowerCase())
|
|
? FilenameUtils.removeExtension(result)
|
|
: result);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------
|
|
// Action event handlers
|
|
|
|
/**
|
|
* Create content type value changed by the user
|
|
*/
|
|
public void createContentChanged(ValueChangeEvent event)
|
|
{
|
|
// clear the content as HTML is not compatible with the plain text box etc.
|
|
this.content = null;
|
|
}
|
|
|
|
@Override
|
|
protected String formatErrorMessage(Throwable exception)
|
|
{
|
|
if (exception instanceof FileExistsException)
|
|
{
|
|
return MessageFormat.format(Application.getMessage(
|
|
FacesContext.getCurrentInstance(), Repository.ERROR_EXISTS),
|
|
((FileExistsException)exception).getName());
|
|
}
|
|
else
|
|
{
|
|
return MessageFormat.format(Application.getMessage(
|
|
FacesContext.getCurrentInstance(), "error_content"),
|
|
exception.getMessage());
|
|
}
|
|
}
|
|
|
|
}
|