/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/textarea/trunk/FCKeditor/connector/src/java/org/sakaiproject/connector/fck/FCKConnectorServlet.java $
* $Id: FCKConnectorServlet.java 130297 2013-10-09 21:02:55Z matthew@longsight.com $
***********************************************************************************
*
* Copyright (c) 2006, 2007, 2008, 2009 The Sakai Foundation
*
* Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.sakaiproject.connector.fck;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.codec.binary.Base64;
import org.sakaiproject.authz.api.SecurityAdvisor;
import org.sakaiproject.authz.api.SecurityService;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.component.cover.ServerConfigurationService;
import org.sakaiproject.content.api.ContentCollection;
import org.sakaiproject.content.api.ContentCollectionEdit;
import org.sakaiproject.content.api.ContentHostingService;
import org.sakaiproject.content.api.ContentResource;
import org.sakaiproject.entity.api.Entity;
import org.sakaiproject.entity.api.ResourceProperties;
import org.sakaiproject.entity.api.ResourcePropertiesEdit;
import org.sakaiproject.entitybroker.entityprovider.extension.EntityData;
import org.sakaiproject.event.api.NotificationService;
import org.sakaiproject.exception.IdUsedException;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.site.api.SiteService;
import org.sakaiproject.tool.api.SessionManager;
import org.sakaiproject.util.ResourceLoader;
import org.sakaiproject.util.StringUtil;
import org.sakaiproject.util.Validator;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.sakaiproject.api.app.messageforums.entity.DecoratedForumInfo;
import org.sakaiproject.api.app.messageforums.entity.DecoratedTopicInfo;
/**
* Conenctor Servlet to upload and browse files to a Sakai worksite for the FCK editor.<br>
*
* This servlet accepts 4 commands used to retrieve and create files and folders from a worksite resource.
* The allowed commands are:
* <ul>
* <li>GetFolders: Retrive the list of directory under the current folder
* <li>GetFoldersAndFiles: Retrive the list of files and directory under the current folder
* <li>CreateFolder: Create a new directory under the current folder
* <li>FileUpload: Send a new file to the server (must be sent with a POST)
* </ul>
*
* The current user must have a valid sakai session with permissions to access the realm associated
* with the resource.
*
* @author Joshua Ryan (joshua.ryan@asu.edu) merged servlets and Sakai-ified them
*
* This connector is loosely based on two servlets found on the FCK website http://www.fckeditor.net/
* written by Simone Chiaretta (simo@users.sourceforge.net)
*
*/
public class FCKConnectorServlet extends HttpServlet {
private static Log M_log = LogFactory.getLog(FCKConnectorServlet.class);
private static final long serialVersionUID = 1L;
private static final String MFORUM_FORUM_PREFIX = "/direct/forum/";
private static final String MFORUM_TOPIC_PREFIX = "/direct/forum_topic/";
private static final String MFORUM_MESSAGE_PREFIX = "/direct/forum_message/";
private static final String FCK_ADVISOR_BASE = "fck.security.advisor.";
private static final String CK_ADVISOR_BASE = "ck.security.advisor.";
private static final String FCK_EXTRA_COLLECTIONS_BASE = "fck.extra.collections.";
private String serverUrlPrefix = "";
private ContentHostingService contentHostingService = null;
private SecurityService securityService = null;
private SessionManager sessionManager = null;
private NotificationService notificationService = null;
private SiteService siteService = null;
private SecurityAdvisor contentNewAdvisor = null;
private ResourceLoader resourceBundle;
/**
* Injects dependencies using the ComponentManager cover.
*
* @param beanName The name of the bean to get.
* @return the bean
*/
private Object inject(String beanName) {
Object bean = null;
bean = ComponentManager.get(beanName);
if (bean == null) {
throw new IllegalStateException("FAILURE to inject dependency during initialization of the FCKConnectorServlet");
}
return bean;
}
/**
* Ensures all necessary dependencies are loaded.
*/
private void initialize() {
if (contentHostingService == null) {
contentHostingService = (ContentHostingService) inject("org.sakaiproject.content.api.ContentHostingService");
}
if (securityService == null) {
securityService = (SecurityService) inject("org.sakaiproject.authz.api.SecurityService");
}
if (sessionManager == null) {
sessionManager = (SessionManager) inject("org.sakaiproject.tool.api.SessionManager");
}
if (notificationService == null) {
notificationService = (NotificationService) inject("org.sakaiproject.event.api.NotificationService");
}
if (siteService == null) {
siteService = (SiteService) inject("org.sakaiproject.site.api.SiteService");
}
if (resourceBundle == null) {
resourceBundle = new ResourceLoader("org.sakaiproject.connector.fck.Messages");
}
if (contentNewAdvisor == null) {
contentNewAdvisor = new SecurityAdvisor(){
public SecurityAdvice isAllowed(String userId, String function, String reference){
try {
securityService.popAdvisor();
return securityService.unlock(userId, "content.new".equals(function)?"content.read":function, reference)?
SecurityAdvice.ALLOWED:SecurityAdvice.NOT_ALLOWED;
} catch (Exception ex) {
return SecurityAdvice.NOT_ALLOWED;
} finally {
securityService.pushAdvisor(this);
}
}
};
}
}
public void init() throws ServletException {
super.init();
initialize();
}
/**
* pops a special private advisor when necessary
* @param thisDir Directory where this is referencing
* @param collectionBase base of the collection
*/
private void popPrivateAdvisor(String thisDir, String collectionBase) {
if (thisDir.startsWith("/private/")) {
SecurityAdvisor advisor = (SecurityAdvisor) sessionManager.getCurrentSession().getAttribute(FCK_ADVISOR_BASE + collectionBase);
if (advisor != null) {
securityService.popAdvisor(advisor);
}
advisor = (SecurityAdvisor) sessionManager.getCurrentSession().getAttribute(CK_ADVISOR_BASE + collectionBase);
if (advisor != null) {
securityService.popAdvisor(advisor);
}
}
}
/**
* pushes a special private advisor when necessary
* @param thisDir Directory where this is referencing
* @param collectionBase base of the collection
*/
private void pushPrivateAdvisor(String thisDir, String collectionBase) {
if (thisDir.startsWith("/private/")) {
SecurityAdvisor advisor = (SecurityAdvisor) sessionManager.getCurrentSession().getAttribute(FCK_ADVISOR_BASE + collectionBase);
if (advisor != null) {
securityService.pushAdvisor(advisor);
}
advisor = (SecurityAdvisor) sessionManager.getCurrentSession().getAttribute(CK_ADVISOR_BASE + collectionBase);
if (advisor != null) {
securityService.pushAdvisor(advisor);
}
}
}
/**
* Manage the Get requests (GetFolders, GetFoldersAndFiles, CreateFolder).<br>
*
* The servlet accepts commands sent in the following format:<br>
* connector?Command=CommandName&Type=ResourceType&CurrentFolder=FolderPath<br><br>
* It executes the command and then return the results to the client in XML format.
*
* Valid values for Type are: Image, File, Flash and Link
*
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
initialize();
response.setContentType("text/xml; charset=UTF-8");
response.setHeader("Cache-Control","no-cache");
PrintWriter out = null;
String commandStr = request.getParameter("Command");
String type = request.getParameter("Type");
String currentFolder = request.getParameter("CurrentFolder");
serverUrlPrefix = ServerConfigurationService.getServerUrl();
String collectionBase = request.getPathInfo();
Document document = null;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.newDocument();
}
catch (ParserConfigurationException pce) {
pce.printStackTrace();
}
Node root = createCommonXml(document, commandStr, type, currentFolder,
contentHostingService.getUrl(currentFolder));
//To support meletedocs, the call to getFolders has to be able to retrieve all folders that are part of melete private (which will be passed in) as
//well as ones that are not. This is why the advisor is being manipulated inside the getfolders method.
if ("GetFolders".equals(commandStr)) {
getFolders(currentFolder, root, document, collectionBase);
}
else if ("GetFoldersAndFiles".equals(commandStr)) {
getFolders(currentFolder, root, document, collectionBase);
//Might need this advisor for files
pushPrivateAdvisor(currentFolder,collectionBase);
getFiles(currentFolder, root, document, type);
popPrivateAdvisor(currentFolder,collectionBase);
}
else if ("GetFoldersFilesAssignsTestsTopics".equals(commandStr)) {
ConnectorHelper thisConnectorHelper = new ConnectorHelper();
thisConnectorHelper.init();
getFolders(currentFolder, root, document, collectionBase);
//Might need this advisor for files
pushPrivateAdvisor(currentFolder,collectionBase);
getFilesOnly(currentFolder, root, document, type);
popPrivateAdvisor(currentFolder,collectionBase);
getAssignmentsOnly(currentFolder, root, document, type, thisConnectorHelper);
getTestsOnly(currentFolder, root, document, type, thisConnectorHelper);
getForumsAndThreads(currentFolder, root, document, type, thisConnectorHelper);
}
else if ("GetResourcesAssignsTestsTopics".equals(commandStr)) {
ConnectorHelper thisConnectorHelper = new ConnectorHelper();
thisConnectorHelper.init();
pushPrivateAdvisor(currentFolder,collectionBase);
getResources(currentFolder, root, document, collectionBase, type);
popPrivateAdvisor(currentFolder,collectionBase);
getAssignmentsOnly(currentFolder, root, document, type, thisConnectorHelper);
getTestsOnly(currentFolder, root, document, type, thisConnectorHelper);
getForumsAndThreads(currentFolder, root, document, type, thisConnectorHelper);
}
else if ("GetResources".equals(commandStr)) {
pushPrivateAdvisor(currentFolder,collectionBase);
getResources(currentFolder, root, document, collectionBase, type);
popPrivateAdvisor(currentFolder,collectionBase);
}
else if ("CreateFolder".equals(commandStr)) {
String newFolderStr = request.getParameter("NewFolderName");
String status = "110";
pushPrivateAdvisor(currentFolder,collectionBase);
try {
ContentCollectionEdit edit = contentHostingService
.addCollection(currentFolder + Validator.escapeResourceName(newFolderStr) + Entity.SEPARATOR);
ResourcePropertiesEdit resourceProperties = edit.getPropertiesEdit();
resourceProperties.addProperty (ResourceProperties.PROP_DISPLAY_NAME, newFolderStr);
String altRoot = getAltReferenceRoot(currentFolder);
if (altRoot != null)
resourceProperties.addProperty (ContentHostingService.PROP_ALTERNATE_REFERENCE, altRoot);
contentHostingService.commitCollection(edit);
status="0";
}
catch (IdUsedException iue) {
status = "101";
}
catch(PermissionException pex) {
status = "103";
}
catch (Exception e) {
status = "102";
}
setCreateFolderResponse(status, root, document);
popPrivateAdvisor(currentFolder,collectionBase);
}
document.getDocumentElement().normalize();
try {
out = response.getWriter();
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(out);
transformer.transform(source, result);
}
catch (Exception ex) {
ex.printStackTrace();
}
finally {
if (out != null) {
out.close();
}
}
//Pop the advisor if we need to
popPrivateAdvisor(currentFolder,collectionBase);
}
/**
* Manage the Post requests (FileUpload).<br>
*
* The servlet accepts commands sent in the following format:<br>
* connector?Command=FileUpload&Type=ResourceType&CurrentFolder=FolderPath<br><br>
* It stores the file (renaming it in case a file with the same name exists) and then return an HTML file
* with a javascript command in it.
*
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
initialize();
response.setContentType("text/html; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
PrintWriter out = null;
String command = request.getParameter("Command");
String currentFolder = request.getParameter("CurrentFolder");
String collectionBase = request.getPathInfo();
pushPrivateAdvisor(currentFolder,collectionBase);
String fileName = "";
String errorMessage = "";
String status="0";
ContentResource attachment = null;
if (!"FileUpload".equals(command) && !"QuickUpload".equals(command) && !("QuickUploadEquation").equals(command) && !("QuickUploadAttachment").equals(command)) {
status = "203";
}
else {
DiskFileUpload upload = new DiskFileUpload();
String mime="";
InputStream requestStream = null;
byte [] bytes=null;
try {
//Special case for uploading fmath equations
if (("QuickUploadEquation").equals(command)) {
String image = request.getParameter("image");
String type = request.getParameter("type");
// size protection
if(image==null || image.length()>1000000) return;
bytes = Base64.decodeBase64(image);
fileName = "fmath-equation-"+request.getParameter("name");
if ("PNG".equals(type)) {
mime = "image/png";
if (fileName.indexOf(".") == -1) {
fileName+=".png";
}
}
else {
mime = "image/jpeg";
if (fileName.indexOf(".") == -1) {
fileName+=".jpg";
}
}
}
else {
//If this is a multipart request
if (ServletFileUpload.isMultipartContent(request)) {
List items = upload.parseRequest(request);
Map fields = new HashMap();
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
fields.put(item.getFieldName(), item.getString());
}
else {
fields.put(item.getFieldName(), item);
}
}
FileItem uplFile = (FileItem)fields.get("NewFile");
String filePath = uplFile.getName();
filePath = filePath.replace('\\','/');
String[] pathParts = filePath.split("/");
fileName = pathParts[pathParts.length-1];
mime = uplFile.getContentType();
requestStream = uplFile.getInputStream();
}
else {
requestStream = request.getInputStream();
mime = request.getHeader("Content-Type");
}
}
//If there's no filename, make a guid name with the mime extension?
if ("".equals (fileName)) {
fileName = UUID.randomUUID().toString();
}
String nameWithoutExt = fileName;
String ext = "";
if (fileName.lastIndexOf(".") > 0) {
nameWithoutExt = fileName.substring(0, fileName.lastIndexOf("."));
ext = fileName.substring(fileName.lastIndexOf("."));
}
int counter = 1;
boolean done = false;
while(!done) {
try {
ResourcePropertiesEdit resourceProperties = contentHostingService.newResourceProperties();
resourceProperties.addProperty (ResourceProperties.PROP_DISPLAY_NAME, fileName);
if ("QuickUploadEquation".equals(command) || "QuickUploadAttachment".equals(command)) {
attachment = bypassAddAttachment(request,fileName,mime,bytes,requestStream,resourceProperties);
} else {
String altRoot = getAltReferenceRoot(currentFolder);
if (altRoot != null)
resourceProperties.addProperty (ContentHostingService.PROP_ALTERNATE_REFERENCE, altRoot);
int noti = NotificationService.NOTI_NONE;
if (bytes != null) {
contentHostingService.addResource(currentFolder+fileName, mime, bytes, resourceProperties, noti);
}
else if (requestStream != null) {
contentHostingService.addResource(currentFolder+fileName, mime, requestStream, resourceProperties, noti);
}
else {
//Nothing to do
}
}
done = true;
}
catch (IdUsedException iue) {
//the name is already used, so we do a slight rename to prevent the colision
fileName = nameWithoutExt + "(" + counter + ")" + ext;
status = "201";
counter++;
}
catch (Exception ex) {
//this user can't write where they are trying to write.
done = true;
ex.printStackTrace();
status = "203";
}
}
}
catch (Exception ex) {
ex.printStackTrace();
status = "203";
}
}
try {
out = response.getWriter();
if ("QuickUploadEquation".equals(command) || "QuickUploadAttachment".equals(command)) {
out.println(attachment!=null?attachment.getUrl():"");
}
else {
out.println("<script type=\"text/javascript\">");
out.println("(function(){ var d = document.domain ; while ( true ) {");
out.println("try { var test = parent.document.domain ; break ; } catch( e ) {}");
out.println("d = d.replace( /.*?(?:\\.|$)/, '' ) ; if ( d.length == 0 ) break ;");
out.println("try { document.domain = d ; } catch (e) { break ; }}})() ;");
out.println("window.parent.OnUploadCompleted(" + status + ",'"
+ (attachment!=null?attachment.getUrl():"")
+ "','" + fileName + "','" + errorMessage + "');");
out.println("</script>");
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (out != null) {
out.close();
}
}
popPrivateAdvisor(currentFolder,collectionBase);
}
private void setCreateFolderResponse(String status, Node root, Document doc) {
Element element = doc.createElement("Error");
element.setAttribute("number", status);
root.appendChild(element);
}
private void getFolders(String dir, Node root, Document doc, String collectionBase) {
Element folders = doc.createElement("Folders");
root.appendChild(folders);
ContentCollection collection = null;
Map<String, String> map = null;
List <Iterator> foldersIterator = new ArrayList <Iterator> ();
try {
//hides the real root level stuff and just shows the users the
//the root folders of all the top collections they actually have access to.
int dirlength = dir.split("/").length;
if (dirlength == 2 || dir.startsWith("/private/")) {
List<String> collections = new ArrayList<String>();
map = contentHostingService.getCollectionMap();
for (String key : map.keySet()) {
if (!contentHostingService.isInDropbox((String)key)) {
collections.add(key);
}
}
List extras = (List) sessionManager.getCurrentSession()
.getAttribute(FCK_EXTRA_COLLECTIONS_BASE + collectionBase);
if (extras != null) {
collections.addAll(extras);
}
foldersIterator.add(collections.iterator());
}
if (dirlength > 2) {
pushPrivateAdvisor(dir,collectionBase);
collection = contentHostingService.getCollection(dir);
if (collection != null && collection.getMembers() != null) {
foldersIterator.add(collection.getMembers().iterator());
}
popPrivateAdvisor(dir,collectionBase);
}
}
catch (Exception e) {
e.printStackTrace();
//not a valid collection? file list will be empty and so will the doc
}
for (Iterator folderIterator : foldersIterator ) {
if (folderIterator != null) {
String current = null;
// create a SortedSet using the elements that are going to be added to the XML doc
SortedSet<Element> sortedFolders = new TreeSet<Element>(new SortElementsForDisplay());
while (folderIterator.hasNext()) {
try {
current = (String) folderIterator.next();
pushPrivateAdvisor(current,collectionBase);
ContentCollection myCollection = contentHostingService.getCollection(current);
Element element=doc.createElement("Folder");
element.setAttribute("url", current);
String collectionName = myCollection.getProperties().getProperty(myCollection.getProperties().getNamePropDisplayName());
if (current.contains("/meleteDocs/")) {
if (resourceBundle != null)
collectionName = resourceBundle.getString("melete_collectionname");
else
collectionName = "Melete Files";
}
element.setAttribute("name",collectionName);
// by adding the folders to this collection, they will be sorted for display
sortedFolders.add(element);
popPrivateAdvisor(current,collectionBase);
}
catch (Exception e) {
//do nothing, we either don't have access to the collction or it's a resource
M_log.debug("No access to display collection" + e.getMessage());
}
}
// now append the folderse to the parent document in sorted order
for (Element folder: sortedFolders) {
folders.appendChild(folder);
}
}
}
}
private void getResources(String dir, Node root, Document doc, String collectionBase, String type) {
Element folders = doc.createElement("Folders");
root.appendChild(folders);
ContentCollection collection = null;
Map<String, String> map = null;
Iterator foldersIterator = null;
try {
//hides the real root level stuff and just shows the users the
//the root folders of all the top collections they actually have access to.
if (dir.split("/").length == 2) {
List<String> collections = new ArrayList<String>();
map = contentHostingService.getCollectionMap();
if (map != null && map.keySet() != null) {
collections.addAll(map.keySet());
}
List extras = (List) sessionManager.getCurrentSession()
.getAttribute(FCK_EXTRA_COLLECTIONS_BASE + collectionBase);
if (extras != null) {
collections.addAll(extras);
}
foldersIterator = collections.iterator();
}
else if (dir.split("/").length > 2) {
collection = contentHostingService.getCollection(dir);
if (collection != null && collection.getMembers() != null) {
foldersIterator = collection.getMembers().iterator();
}
}
}
catch (Exception e) {
e.printStackTrace();
//not a valid collection? file list will be empty and so will the doc
}
if (foldersIterator != null) {
String current = null;
// create a SortedSet using the elements that are going to be added to the XML doc
SortedSet<Element> sortedFolders = new TreeSet<Element>(new SortElementsForDisplay());
while (foldersIterator.hasNext()) {
try {
current = (String) foldersIterator.next();
ContentCollection myCollection = contentHostingService.getCollection(current);
Element element=doc.createElement("Folder");
element.setAttribute("path", current);
element.setAttribute("url", contentHostingService.getUrl(current));
element.setAttribute("name", myCollection.getProperties().getProperty(
myCollection.getProperties().getNamePropDisplayName()));
// by adding the folders to this collection, they will be sorted for display
sortedFolders.add(element);
}
catch (Exception e) {
//do nothing, we either don't have access to the collction or it's a resource
}
}
// now append the folderse to the parent document in sorted order
for (Element folder: sortedFolders) {
Node addedFolder = folders.appendChild(folder);
getResources(folder.getAttribute("path"), addedFolder, doc, collectionBase, type);
}
getFilesOnly(dir, root, doc, type);
}
}
private void getFiles(String dir, Node root, Document doc, String type) {
Element files=doc.createElement("Files");
root.appendChild(files);
ContentCollection collection = null;
try {
collection = contentHostingService.getCollection(dir);
}
catch (Exception e) {
//do nothing, file will be empty and so will doc
}
if (collection != null) {
Iterator iterator = collection.getMemberResources().iterator();
// create a SortedSet using the elements that are going to be added to the XML doc
SortedSet<Element> sortedFiles = new TreeSet<Element>(new SortElementsForDisplay());
while (iterator.hasNext ()) {
try {
ContentResource current = (ContentResource)iterator.next();
String ext = current.getProperties().getProperty(
current.getProperties().getNamePropContentType());
if ( ("File".equals(type) && (ext != null) ) ||
("Flash".equals(type) && ext.equalsIgnoreCase("application/x-shockwave-flash") ) ||
("Image".equals(type) && ext.startsWith("image") ) ||
("Media".equals(type) && (ext.startsWith("video") || ext.startsWith("audio") || ext.equalsIgnoreCase("application/x-shockwave-flash")) ) ||
"Link".equals(type)) {
String id = current.getId();
Element element=doc.createElement("File");
// displaying the id instead of the display name because the url used
// for linking in the FCK editor uses what is returned...
element.setAttribute("name", current.getProperties().getProperty(
current.getProperties().getNamePropDisplayName()));
element.setAttribute("url", current.getUrl());
if (current.getProperties().getProperty(
current.getProperties().getNamePropContentLength()) != null) {
element.setAttribute("size", "" + current.getProperties()
.getPropertyFormatted(current.getProperties()
.getNamePropContentLength()));
}
else {
element.setAttribute("size", "0");
}
// by adding the files to this collection, they will be sorted for display
sortedFiles.add(element);
}
}
catch (ClassCastException e) {
//it's a colleciton not an item
}
catch (Exception e) {
//do nothing, we don't have access to the item
}
}
// now append the files to the parent document in sorted order
for (Element file: sortedFiles) {
files.appendChild(file);
}
}
}
private void getFilesOnly(String dir, Node root, Document doc, String type) {
Element files=doc.createElement("Files");
root.appendChild(files);
ContentCollection collection = null;
List myAssignments = null;
List myTests = null;
List myTopics = null;
String siteId = null;
String[] f = dir.split("/");
siteId = f[2];
try {
collection = contentHostingService.getCollection(dir);
}
catch (Exception e) {
//do nothing, file will be empty and so will doc
}
if (collection != null) {
Iterator iterator = collection.getMemberResources().iterator();
while (iterator.hasNext ()) {
try {
ContentResource current = (ContentResource)iterator.next();
String ext = current.getProperties().getProperty(
current.getProperties().getNamePropContentType());
if ( ("File".equals(type) && (ext != null) ) ||
("Flash".equals(type) && ext.equalsIgnoreCase("application/x-shockwave-flash") ) ||
("Image".equals(type) && ext.startsWith("image") ) ||
"Link".equals(type)) {
String id = current.getId();
Element element=doc.createElement("File");
// displaying the id instead of the display name because the url used
// for linking in the FCK editor uses what is returned...
element.setAttribute("name", current.getProperties().getProperty(
current.getProperties().getNamePropDisplayName()));
element.setAttribute("url", current.getUrl());
if (current.getProperties().getProperty(
current.getProperties().getNamePropContentLength()) != null) {
element.setAttribute("size", "" + current.getProperties()
.getPropertyFormatted(current.getProperties()
.getNamePropContentLength()));
}
else {
element.setAttribute("size", "0");
}
files.appendChild(element);
}
}
catch (ClassCastException e) {
//it's a colleciton not an item
}
catch (Exception e) {
//do nothing, we don't have access to the item
}
}
}
}
private void getAssignmentsOnly(String dir, Node root, Document doc, String type, ConnectorHelper ch) {
List myAssignments = null;
String siteId = null;
String[] f = dir.split("/");
siteId = f[2];
SortedSet<Element> sortedItems = new TreeSet<Element>(new SortElementsForDisplay());
Element assignments=doc.createElement("Assignments");
root.appendChild(assignments);
myAssignments = ch.getSiteAssignments(siteId);
Iterator assignmentsIterator = myAssignments.iterator();
while(assignmentsIterator.hasNext()){
String[] thisAssignmentReference = (String[]) assignmentsIterator.next();
Element element=doc.createElement("Assignment");
element.setAttribute("name",thisAssignmentReference[0]);
element.setAttribute("url",serverUrlPrefix + thisAssignmentReference[1]);
element.setAttribute("size", "0");
sortedItems.add(element);
}
for (Element item: sortedItems) {
assignments.appendChild(item);
}
}
private void getTestsOnly(String dir, Node root, Document doc, String type, ConnectorHelper ch) {
List myTests = null;
String siteId = null;
String[] f = dir.split("/");
siteId = f[2];
SortedSet<Element> sortedItems = new TreeSet<Element>(new SortElementsForDisplay());
Element assessments=doc.createElement("Assessments");
root.appendChild(assessments);
myTests = ch.getPublishedAssements(siteId);
Iterator assessmentIterator = myTests.iterator();
while(assessmentIterator.hasNext()){
String[] thisAssessmentReference = (String[]) assessmentIterator.next();
Element element=doc.createElement("Assessment");
element.setAttribute("name",thisAssessmentReference[0]);
element.setAttribute("url",serverUrlPrefix + thisAssessmentReference[1]);
element.setAttribute("size", "0");
sortedItems.add(element);
}
for (Element item: sortedItems) {
assessments.appendChild(item);
}
}
private void getForumsAndThreads(String dir, Node root, Document doc, String type, ConnectorHelper ch) {
String siteId = null;
String[] f = dir.split("/");
siteId = f[2];
Element msgForums=doc.createElement("MsgForums");
root.appendChild(msgForums);
List theseMsgForums = ch.getForumTopicReferences(siteId);
if(theseMsgForums==null){
return;
}
SortedSet<Element> sortedForums = new TreeSet<Element>(new SortElementsForDisplay());
Iterator msgForumsIterator = theseMsgForums.iterator();
while(msgForumsIterator.hasNext()){
DecoratedForumInfo thisForumBean = (DecoratedForumInfo) ((EntityData) msgForumsIterator.next()).getData();
Element forumElement = doc.createElement("mForum");
forumElement.setAttribute("url", serverUrlPrefix + MFORUM_FORUM_PREFIX+String.valueOf(thisForumBean.getForumId()));
forumElement.setAttribute("name",thisForumBean.getForumTitle());
SortedSet<Element> sortedTopics = new TreeSet<Element>(new SortElementsForDisplay());
Iterator<DecoratedTopicInfo> topicIterator = thisForumBean.getTopics().iterator();
while(topicIterator.hasNext()){
DecoratedTopicInfo thisTopicBean = topicIterator.next();
Element topicElement = doc.createElement("mTopic");
topicElement.setAttribute("url", serverUrlPrefix + MFORUM_TOPIC_PREFIX+String.valueOf(thisTopicBean.getTopicId()));
topicElement.setAttribute("name", thisTopicBean.getTopicTitle());
// SortedSet<Element> sortedMessages = new TreeSet<Element>(new SortElementsForDisplay());
//
// Iterator thisMessageIterator = thisTopicBean.getMessages().iterator();
// while(thisMessageIterator.hasNext()){
// MessageBean thisMessageBean = (MessageBean) thisMessageIterator.next();
// Element messageElement = doc.createElement("mMessage");
// messageElement.setAttribute("url", serverUrlPrefix + MFORUM_MESSAGE_PREFIX+String.valueOf(thisMessageBean.getMessageId()));
// messageElement.setAttribute("name", thisMessageBean.getMessageLabel());
// sortedMessages.add(messageElement);
// }
//
// for (Element item: sortedMessages) {
// topicElement.appendChild(item);
// }
sortedTopics.add(topicElement);
}
for (Element item: sortedTopics) {
forumElement.appendChild(item);
}
sortedForums.add(forumElement);
}
for (Element item: sortedForums) {
msgForums.appendChild(item);
}
}
private Node createCommonXml(Document doc,String commandStr, String type, String currentPath, String currentUrl ) {
Element root = doc.createElement("Connector");
doc.appendChild(root);
root.setAttribute("command", commandStr);
root.setAttribute("resourceType", type);
Element element = doc.createElement("CurrentFolder");
element.setAttribute("path", currentPath);
element.setAttribute("url", currentUrl);
root.appendChild(element);
return root;
}
private String getAltReferenceRoot (String id) {
String altRoot = null;
try {
altRoot = StringUtil.trimToNull(contentHostingService.getProperties(id)
.getProperty(ContentHostingService.PROP_ALTERNATE_REFERENCE));
}
catch (Exception e) {
// do nothing, we either didn't have permission or the id is bogus
}
if (altRoot != null && !"/".equals(altRoot) && !"".equals(altRoot)) {
if (!altRoot.startsWith(Entity.SEPARATOR))
altRoot = Entity.SEPARATOR + altRoot;
if (altRoot.endsWith(Entity.SEPARATOR))
altRoot = altRoot.substring(0, altRoot.length() - Entity.SEPARATOR.length());
return altRoot;
}
else
return null;
}
private ContentResource bypassAddAttachment(HttpServletRequest request, String fileName, String mimeType, byte[] bytes, InputStream requestStream, ResourceProperties props) throws Exception {
try {
securityService.pushAdvisor(contentNewAdvisor);
String path = request.getPathInfo();
String resourceId = Validator.escapeResourceName(fileName);
String siteId = "";
if(path.contains("/user/")){
siteId = siteService.getSite("~" + path.replaceAll("\\/user\\/(.*)\\/", "$1")).getId();
} else {
siteId = siteService.getSite(path.replaceAll("\\/group\\/(.*)\\/", "$1")).getId();
}
String toolName = "fckeditor";
if (bytes != null) {
return contentHostingService.addAttachmentResource(resourceId, siteId, toolName, mimeType, new ByteArrayInputStream(bytes), props);
}
else if (requestStream != null) {
return contentHostingService.addAttachmentResource(resourceId, siteId, toolName, mimeType, requestStream, props);
}
} catch (Exception ex) {
throw ex;
} finally {
securityService.popAdvisor(contentNewAdvisor);
}
return null;
}
}