Index: /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/FCKeditor.java
===================================================================
--- /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/FCKeditor.java (revision 1875)
+++ /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/FCKeditor.java (revision 1875)
@@ -0,0 +1,275 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+
+package net.fckeditor;
+
+import javax.servlet.http.HttpServletRequest;
+
+import net.fckeditor.handlers.PropertiesLoader;
+import net.fckeditor.tool.Compatibility;
+import net.fckeditor.tool.Utils;
+import net.fckeditor.tool.XHtmlTagTool;
+
+/**
+ * FCKeditor control class.
+ *
+ * It creates the html code for the FCKeditor based on the following things:
+ *
true
.
+ *
+ * @param request
+ * Servlet request from user
+ * @return true
if user can upload to the server else false
+ */
+ public boolean isEnabledForFileUpload(final HttpServletRequest request);
+
+ /**
+ * Authenticates/enables the current user for browsing files.true
.
+ *
+ * @param request
+ * Servlet request from user
+ * @return true
if use can browse the server else false
+ */
+ public boolean isEnabledForFileBrowsing(final HttpServletRequest request);
+
+ /**
+ * Getter for the user dependent 'BaseDir'.null
, {@link ConnectorHandler} will used
+ * the default one! That's useful, if the implementation doesn't bother you.null
or the 'BaseDir' string for the current user.
+ */
+ public String getUserFilesPath(final HttpServletRequest request);
+}
Index: /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/connector/ConnectorServlet.java
===================================================================
--- /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/connector/ConnectorServlet.java (revision 1875)
+++ /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/connector/ConnectorServlet.java (revision 1875)
@@ -0,0 +1,302 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+package net.fckeditor.connector;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.fckeditor.handlers.CommandHandler;
+import net.fckeditor.handlers.ConnectorHandler;
+import net.fckeditor.handlers.ExtensionsHandler;
+import net.fckeditor.handlers.ResourceTypeHandler;
+import net.fckeditor.handlers.SessionDataHandler;
+import net.fckeditor.response.UploadResponse;
+import net.fckeditor.response.XmlResponse;
+import net.fckeditor.tool.Utils;
+import net.fckeditor.tool.UtilsFile;
+import net.fckeditor.tool.UtilsResponse;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.io.FilenameUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Servlet to upload and browse files.+ <servlet> + <servlet-name>Connector</servlet-name> + <servlet-class>net.fckeditor.connector.ConnectorServlet</servlet-class> + <init-param> + <param-name>baseDir</param-name> + <param-value>/UserFiles/</param-value> + </init-param> + <init-param> + <param-name>debug</param-name> + <param-value>false</param-value> + </init-param> + <load-on-startup>1</load-on-startup> + </servlet> + + <servlet-mapping> + <servlet-name>Connector</servlet-name> + <url-pattern>/editor/filemanager/browser/default/connectors/jsp/connector</url-pattern> + </servlet-mapping> ++
+FCKConfig.LinkBrowserURL = FCKConfig.BasePath + "filemanager/browser/default/browser.html?Connector=connectors/jsp/connector" ; +FCKConfig.ImageBrowserURL = FCKConfig.BasePath + "filemanager/browser/default/browser.html?Type=Image&Connector=connectors/jsp/connector" ; +FCKConfig.FlashBrowserURL = FCKConfig.BasePath + "filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/jsp/connector" ; ++Also, since the servlet manage a file upload using the Jakarta Common fileupload library, you need to put in your
WEB-INF/lib/
the commons-fileupload.jar
.
+ext1|ext2|ext3
+ */
+ public static void setExtensionsAllowed(final ResourceTypeHandler type, final String extensionsList) {
+ if (extensionsList != null) {
+ extensionsAllowed.put(type, Utils.getSet(extensionsList));
+ extensionsDenied.get(type).clear();
+ }
+ }
+
+ /**
+ * Getter for the denied extensions of a file type.
+ *
+ * @param type
+ * The file type.
+ * @return Set of denied extensions or an empty set.
+ */
+ public static Setext1|ext2|ext3
+ */
+ public static void setExtensionsDenied(final ResourceTypeHandler type, final String extensionsList) {
+ if (extensionsList != null) {
+ extensionsDenied.put(type, Utils.getSet(extensionsList));
+ extensionsAllowed.get(type).clear();
+ }
+ }
+
+ /**
+ * Checks, if an extension is allowed for a file type.
+ *
+ * @param type
+ * @param extension
+ * @return True, false. False is returned too, if 'type' or 'extensions' is null.
+ */
+ public static boolean isAllowed(final ResourceTypeHandler type, final String extension) {
+ if (type == null || extension == null)
+ return false;
+ String ext = extension.toLowerCase();
+ Set
+ * The usage is quite easy but can be tricky since varargs are used in the class
+ * constructor.
The requestor expects a JS method callback with variable
+ * arguments size.
+ *
+ * e.g.
+ * window.parent.OnUploadCompleted(101,'some/url/file.img','file.img','no error');
+ *
+ * The UploadResponse constructor behaves the same way by simply calling it
+ * with:
+ * UploadResponse ur = new UploadResonse(EN_SOME_ERROR,"/some/url/file.img","file.img","no error"):
+ *
+ * Put the desired parameters in the constructor. You may omit them from
+ * right to left but you have to remain the order.
e.g.
+ * UploadResponse(EN_OK,"/some/url/to/pic.jpg","pic")
or
+ * UploadResponse(EN_OK)
but not
+ * UploadResponse(EN_OK,"some error message")
+ *
+ * Use, if possible, the pre-defined error numbers or upload responses. + *
+ *
+ * If you need to set error number and message only, use constructor with
+ * one paremeter and call {@link UploadResponse#setCustomMessage(String)}.
+ *
+ * @param arguments
+ * possible argument order:
+ *
+ * Simple usage:
+ *
+ *
+ * In this example we set all the attribute for the fckedit tag.
+ *
+ *
+ * Advanced usage of the tag:
+ *
+ *
+ * Use the class like this:
+ *
+ * Known limitations:
+ *
+ * Requirements:
+ *
+ * The latest version can be found at http://schmidt.devlib.org/image-info/.
+ *
+ * Written by Marco Schmidt.
+ *
+ * This class is contributed to the Public Domain.
+ * Use it at your own risk.
+ *
+ * History:
+ * int errorNumber, String fileUrl, String filename, String customMessage
+ * @throws IllegalArgumentException
+ * if amount of arguments is less than 1 and above 4
+ * @throws IllegalArgumentException
+ * if the first argument is not an error number (int)
+ */
+
+ public UploadResponse(Object... arguments) throws IllegalArgumentException {
+ if (arguments.length < 1 || arguments.length > 4)
+ throw new IllegalArgumentException(
+ "The amount of arguments has to be between 1 and 4");
+
+ parameters = new Object[arguments.length];
+
+ if (!(arguments[0] instanceof Integer))
+ throw new IllegalArgumentException(
+ "The first argument has to be an error number (int)");
+
+ System.arraycopy(arguments, 0, parameters, 0, arguments.length);
+ }
+
+ /**
+ * Sets the message in the UploadResponse.
+ *
+ * Methods automatically determines how many arguments are set and puts the
+ * message at the end.
+ *
+ * @param customMassage
+ * the message you want to pass to the user
+ */
+ public void setCustomMessage(final String customMassage) {
+ if (Utils.isNotEmpty(customMassage)) {
+ if (parameters.length == 1) {
+ Object errorNumber = parameters[0];
+ parameters = new Object[4];
+ parameters[0] = errorNumber;
+ parameters[1] = null;
+ parameters[2] = null;
+ }
+ parameters[3] = customMassage;
+ }
+ }
+
+ /**
+ * Assembles the JavaScript method for the user callback
+ */
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer(75);
+ sb.append("");
+
+ return sb.toString();
+ }
+}
Index: /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/response/XmlResponse.java
===================================================================
--- /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/response/XmlResponse.java (revision 1875)
+++ /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/response/XmlResponse.java (revision 1875)
@@ -0,0 +1,223 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+package net.fckeditor.response;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.StringWriter;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import net.fckeditor.handlers.CommandHandler;
+import net.fckeditor.handlers.ResourceTypeHandler;
+import net.fckeditor.tool.Utils;
+
+import org.apache.commons.io.filefilter.DirectoryFileFilter;
+import org.apache.commons.io.filefilter.FileFileFilter;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * static error objects won't probably provided due to performance reasons of
+ * Document instance creation
+ *
+ * TODO document me!
+ * @author mosipov
+ *
+ */
+public class XmlResponse {
+
+ private Document document;
+ private Element errorElement;
+ private Element foldersElement;
+ private Element filesElement;
+
+ /** Error number OK */
+ public static final int EN_OK = 0;
+
+ /** Error number ERROR */
+ public static final int EN_ERROR = 1;
+
+ /** Error number ALREADY EXISTS */
+ public static final int EN_ALREADY_EXISTS = 101;
+
+ /** Error number INVALID FOLDER NAME */
+ public static final int EN_INVALID_FOLDER_NAME = 102;
+
+ /** Error number SECURITY ERROR */
+ public static final int EN_SECURITY_ERROR = 103;
+
+ /** Error number UNKNOWN ERROR */
+ public static final int EN_UKNOWN = 110;
+
+ /**
+ *
+ * @param command
+ * @param resourceType
+ * @param currentFolder
+ * @param constructedUrl
+ */
+ public XmlResponse(CommandHandler command, ResourceTypeHandler resourceType,
+ String currentFolder, String constructedUrl) {
+
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory
+ .newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ document = builder.newDocument();
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+
+ Element root = document.createElement("Connector");
+ document.appendChild(root);
+ root.setAttribute("command", command.toString());
+ root.setAttribute("resourceType", resourceType.toString());
+
+ Element currentFolderElement = document.createElement("CurrentFolder");
+ currentFolderElement.setAttribute("path", currentFolder);
+
+ currentFolderElement.setAttribute("url", constructedUrl);
+ root.appendChild(currentFolderElement);
+
+ }
+
+ /**
+ * TODO document me!
+ * @param number
+ * @param text
+ */
+ public XmlResponse(int number, String text) {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory
+ .newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ document = builder.newDocument();
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+
+ Element root = document.createElement("Connector");
+ document.appendChild(root);
+ setError(number, text);
+ }
+
+ /***
+ * TODO document me!
+ * @param number
+ */
+ public XmlResponse(int number) {
+ this(number, null);
+ }
+
+ public void setError(int number, String text) {
+
+ if (errorElement == null) {
+ errorElement = document.createElement("Error");
+ document.getDocumentElement().appendChild(errorElement);
+ }
+
+ errorElement.setAttribute("number", String.valueOf(number));
+ if (Utils.isNotEmpty(text))
+ errorElement.setAttribute("text", text);
+
+ }
+
+ public void setError(int number) {
+ setError(number, null);
+ }
+
+ public void setFolders(File dir) {
+
+ if (foldersElement != null) {
+ Element parent = (Element) foldersElement.getParentNode();
+ parent.removeChild(foldersElement);
+ }
+
+ foldersElement = document.createElement("Folders");
+ document.getDocumentElement().appendChild(foldersElement);
+
+ String[] fileList = dir.list(DirectoryFileFilter.DIRECTORY);
+ for (String file : fileList) {
+ Element folderElement = document.createElement("Folder");
+ folderElement.setAttribute("name", file);
+ foldersElement.appendChild(folderElement);
+ }
+ }
+
+ public void setFiles(File dir) {
+
+ if (filesElement != null) {
+ Element parent = (Element) filesElement.getParentNode();
+ parent.removeChild(filesElement);
+ }
+
+ filesElement = document.createElement("Files");
+ document.getDocumentElement().appendChild(filesElement);
+
+ File[] fileList = dir.listFiles((FileFilter) FileFileFilter.FILE);
+ long length;
+ for (File file : fileList) {
+ Element fileElement = document.createElement("File");
+ fileElement.setAttribute("name", file.getName());
+ if (file.length() < 1024)
+ length = 1L;
+ else
+ length = file.length()/1024;
+ fileElement.setAttribute("size", String.valueOf(length));
+ filesElement.appendChild(fileElement);
+ }
+ }
+
+ public void setFoldersAndFiles(File dir) {
+ setFolders(dir);
+ setFiles(dir);
+ }
+
+ @Override
+ public String toString() {
+ document.getDocumentElement().normalize();
+ TransformerFactory factory = TransformerFactory.newInstance();
+
+ StringWriter sw = new StringWriter();
+
+ try {
+ Transformer transformer = factory.newTransformer();
+
+ DOMSource source = new DOMSource(document);
+ StreamResult result = new StreamResult(sw);
+
+ transformer.transform(source, result);
+ } catch (TransformerException e) {
+ throw new RuntimeException(e);
+ }
+
+ return sw.toString();
+ }
+
+}
Index: /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tags/CheckTag.java
===================================================================
--- /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tags/CheckTag.java (revision 1875)
+++ /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tags/CheckTag.java (revision 1875)
@@ -0,0 +1,114 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+package net.fckeditor.tags;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspTagException;
+import javax.servlet.jsp.JspWriter;
+import javax.servlet.jsp.tagext.TagSupport;
+
+import net.fckeditor.handlers.PropertiesLoader;
+import net.fckeditor.handlers.SessionDataHandler;
+import net.fckeditor.tool.Compatibility;
+
+/**
+ * CheckTag.java - TODO DOCUMENTME!
+ *
+ * @version $Id$
+ */
+public class CheckTag extends TagSupport {
+
+ private static final long serialVersionUID = -6834095891675681686L;
+
+ private static final String FILE_UPLOAD = "FileUpload";
+ private static final String FILE_BROWSING = "FileBrowsing";
+ private static final String COMPATIBLE_BROWSER = "CompatibleBrowser";
+ private static final String PROPERTY_MESSAGE_FILE_BROWSING_DISABLED = "message.enabled_tag.connector.file_browsing.disabled";
+ private static final String PROPERTY_MESSAGE_FILE_BROWSING_ENABLED = "message.enabled_tag.connector.file_browsing.enabled";
+ private static final String PROPERTY_MESSAGE_FILE_UPLOAD_DISABLED = "message.enabled_tag.connector.file_upload.disalbed";
+ private static final String PROPERTY_MESSAGE_FILE_UPLOAD_ENABLED = "message.enabled_tag.connector.file_upload.enabled";
+ private static final String PROPERTY_MESSAGE_NOT_COMPATIBLE_BROWSER = "message.enabled_tag.compatible_browser.no";
+ private static final String PROPERTY_MESSAGE_COMPATIBLE_BROWSER = "message.enabled_tag.compatible_browser.yes";
+ private static Set
+ *
+ * FCKeditor Tag class to access the
+ * {@linkplain net.fckeditor.FCKeditor container}.
+ *
+ * <FCK:editor
+ * instanceName="EditorAccessibility"
+ * width="80%"
+ * height="120"
+ * toolbarSet="Accessibility"
+ * ">This is another test. <BR><BR>The "Second" row.</BR></FCK:editor">
+ *
+ *
+ *
+ * <FCK:editor instanceName="EditorDefault" basePath="/fckeditor/"
+ * styleNames=";Style 1;Style 2; Style 3"
+ * fontNames=";Arial;Courier New;Times New Roman;Verdana" >
+ * This is some <B>sample text</B>.
+ * </FCK:editor>
+ *
+ *
+ * In this example we set the id and the basePath of the editor (since it is
+ * /fckeditor/ we could have omitted it because it's already the default value).
+ * Then we used the the optional attributes to set some advanced configuration
+ * settings.
+ *
+ * @version $Id: EditorTag.java 1842 2008-03-29 16:32:15Z th-schwarz $
+ */
+public class EditorTag extends TagSupport {
+
+ private static final long serialVersionUID = -173091731589866140L;
+
+ private String instanceName;
+ private String width;
+ private String height;
+ private String toolbarSet;
+ private String value;
+ private String basePath;
+
+ /** The underlying FCKeditor object */
+ private FCKeditor fckEditor;
+
+ /**
+ * Sets the name for the given editor instance
+ *
+ * @param instanceName
+ * some name without whitespaces
+ */
+ public void setInstanceName(String instanceName) {
+ this.instanceName = instanceName;
+ }
+
+ /**
+ * Sets the width of the textarea
+ *
+ * @param width
+ * width of the editor instance
+ *
+ */
+ public void setWidth(String width) {
+ this.width = width;
+ }
+
+ /**
+ * Sets the height of the textarea
+ *
+ * @param height
+ * height of the editor instance
+ */
+ public void setHeight(String height) {
+ this.height = height;
+ }
+
+ /**
+ * Sets the name of the toolbar to display
+ *
+ * @param toolbarSet
+ * toolbar set of the editor instance
+ */
+ public void setToolbarSet(String toolbarSet) {
+ this.toolbarSet = toolbarSet;
+ }
+
+ /**
+ * Sets the editor document content
+ *
+ * @param value
+ * any HTML string
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Sets the dir where the FCKeditor files reside on the server
+ *
+ * @param basePath
+ * basePath of the editor instance (e.g. /fckeditor)
+ */
+ public void setBasePath(String basePath) {
+ this.basePath = basePath;
+ }
+
+ void setConfigParamAll(MapPackage Specification
+
+This taglibrary is compliant to the taglib 1.1 specification.
+To use it put the FCKeditor.jar inside the WEB-INF/lib
dir and FCKeditor.tld inside the WEB-INF
directory of your website.
+Put the following declaration in each page that use the tags:
+
+<%@ taglib uri="http://fckeditor.net/tags-fckeditor" prefix="FCK" %>
+
+
+Related Documentation
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+
+
+
+
+
+
+
Index: /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/Compatibility.java
===================================================================
--- /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/Compatibility.java (revision 1875)
+++ /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/Compatibility.java (revision 1875)
@@ -0,0 +1,107 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+package net.fckeditor.tool;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Compatibility check.
+ *
+ * @version $Id$
+ */
+public class Compatibility {
+
+ /**
+ * Checks, if a browser's user agent string is compatible for the FCKeditor.
+ * Adapted from: http://dev.fckeditor.net/browser/FCKeditor/releases/stable/fckeditor.php
+ *
+ * @param userAgentString
+ * @return true, if compatible, otherwise false
+ */
+ public static boolean check(final String userAgentString) {
+ if (Utils.isEmpty(userAgentString))
+ return false;
+
+ float version;
+
+ // IE 5.5+, check special keys like 'Opera' and 'mac', because there are some
+ // other browsers, containing 'MSIE' in there agent string!
+ if (userAgentString.indexOf("Opera") < 0 && userAgentString.indexOf("mac") < 0) {
+ version = getBrowserVersion(userAgentString, ".*MSIE ([\\d]+.[\\d]+).*");
+ if (version != -1f && version >= 5.5f)
+ return true;
+ }
+
+ // for mozilla only, because all firefox versions are supported
+ version = getBrowserVersion(userAgentString, ".*Gecko/([\\d]+).*");
+ if (version != -1f && version >= 20030210f)
+ return true;
+
+ // Opera 9.5+
+ version = getBrowserVersion(userAgentString, "Opera/([\\d]+.[\\d]+).*");
+ if (version != -1f && version >= 9.5f)
+ return true;
+ version = getBrowserVersion(userAgentString, ".*Opera ([\\d]+.[\\d]+)");
+ if (version != -1f && version >= 9.5f)
+ return true;
+
+ // Safari 3+
+ version = getBrowserVersion(userAgentString, ".*AppleWebKit/([\\d]+).*");
+ if (version != -1f && version >= 522f)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Just a wrapper to {@link #check(String)}.
+ *
+ * @param request
+ */
+ public static boolean isCompatibleBrowser(final HttpServletRequest request) {
+ return (request == null) ? false : check(request.getHeader("user-agent"));
+ }
+
+ /**
+ * Helper method to get the the browser version from 'userAgent' with the regular expression
+ * 'regex'. The first group of the matches has to be the version number!
+ *
+ * @param userAgent
+ * @param regex
+ * @return The browser version, or -1f, if version con't find out.
+ */
+ private static float getBrowserVersion(final String userAgent, final String regex) {
+ Pattern pattern = Pattern.compile(regex);
+ Matcher matcher = pattern.matcher(userAgent);
+ if (matcher.matches()) {
+ try {
+ return Float.parseFloat(matcher.group(1));
+ } catch (NumberFormatException e) {
+ return -1f;
+ }
+ }
+ return -1f;
+ }
+
+}
Index: /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/Utils.java
===================================================================
--- /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/Utils.java (revision 1875)
+++ /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/Utils.java (revision 1875)
@@ -0,0 +1,129 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+package net.fckeditor.tool;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+
+
+
+/**
+ * Some static helper methods.
+ *
+ * @version $Id$
+ */
+public class Utils {
+
+ /**
+ * Constructs a set of uppercased strings from a 'delimiter' separated
+ * string.
+ *
+ * @param stringList
+ * @param delimiter
+ * The delimiter. It shouldn't be empty!
+ * @return An emtpy list, if 'stringList' is empty, or an lowercased set of
+ * strings.
+ * @throws IllegalArgumentException
+ * if 'delimiter' is empty.
+ */
+ public static Settrue
if the String is empty or null
+ */
+ public static boolean isEmpty(final String str) {
+ return str == null || str.length() == 0;
+ }
+
+ /**
+ * Just a wrapper to {@link #isEmpty(String)}.
+ *
+ * @param str
+ * @return true
if the String is not empty and not null.
+ */
+ public static boolean isNotEmpty(final String str) {
+ return !isEmpty(str);
+ }
+
+ /**
+ * Replaces all 'search' with 'replacement' in 'string'.
+ * Usage:
+ *
+ *
+ * Utils.replaceAll(null, *, *) = ""
+ * Utils.replaceAll("", *, *) = ""
+ * Utils.replaceAll("foo", null, *) = "foo"
+ * Utils.replaceAll("foo", "o", "a") = "faa"
+ *
+ *
+ * @param string
+ * @param search
+ * @param replacement
+ * @return replaced String
+ */
+ public static String replaceAll(final String string, final String search,
+ final String replacement) {
+ if (isEmpty(string))
+ return "";
+ if (isEmpty(search))
+ return string;
+ if (string.indexOf(search) == -1)
+ return string;
+ StringBuffer sb = new StringBuffer(string);
+ int pos = sb.indexOf(search);
+
+ while (pos != -1) {
+ sb.replace(pos, pos + search.length(), replacement);
+ pos = sb.indexOf(search);
+ }
+ return sb.toString();
+ }
+}
Index: /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/UtilsFile.java
===================================================================
--- /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/UtilsFile.java (revision 1875)
+++ /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/UtilsFile.java (revision 1875)
@@ -0,0 +1,144 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+package net.fckeditor.tool;
+
+import java.io.File;
+import java.io.InputStream;
+
+import org.apache.commons.io.FilenameUtils;
+import org.devlib.schmidt.imageinfo.ImageInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.fckeditor.handlers.ConnectorHandler;
+
+/**
+ * Some static helper methods in conjunction with files.
+ *
+ * @version $Id$
+ */
+public class UtilsFile {
+
+ private static final Logger logger = LoggerFactory.getLogger(UtilsFile.class);
+
+ /**
+ * Do a cleanup of the file name to avoid possible problems.
+ * The force single Extension property will be respected!
+ *
+ * @param fileName
+ * @return folder name where \ / | : ? * " < > 'control chars' replaced by '_'
+ */
+ public static String sanitizeFileName(final String fileName) {
+ if (fileName == null)
+ return null;
+ if (fileName.equals(""))
+ return "";
+
+ String name = (ConnectorHandler.isForceSingleExtension()) ? UtilsFile.forceSingleExtension(fileName)
+ : fileName;
+
+ // Remove \ / | : ? * " < > with _
+ return name.replaceAll("\\/|\\/|\\||:|\\?|\\*|\"|<|>|\\p{Cntrl}", "_");
+ }
+
+ /**
+ * Do a cleanup of the folder name to avoid possible problems.
+ *
+ * @param folderName
+ * @return folder name where . \ / | : ? * " < > 'control chars' replaced by '_'
+ */
+ public static String sanitizeFolderName(final String folderName) {
+ if (folderName == null)
+ return null;
+ if (folderName.equals(""))
+ return "";
+
+ // Remove . \ / | : ? * " < > with _
+ return folderName.replaceAll("\\.|\\/|\\/|\\||:|\\?|\\*|\"|<|>|\\p{Cntrl}", "_");
+ }
+
+ /**
+ * Checks if the underlying file of the InputStrem is an image.
+ *
+ * @param in
+ * @return True
, if the underlying file is an image, or false
.
+ */
+ public static boolean isImage(final InputStream in) {
+ ImageInfo ii = new ImageInfo();
+ ii.setInput(in);
+ return ii.check();
+ }
+
+ /**
+ * TODO - document me!
+ *
+ * @param path
+ * @return true
if path corresponds to rules or
+ * false
.
+ */
+ public static boolean isValidPath(final String path) {
+ if (Utils.isEmpty(path))
+ return false;
+ if (!path.startsWith("/"))
+ return false;
+ if (!path.endsWith("/"))
+ return false;
+
+ if (!path.equals(FilenameUtils.separatorsToUnix(FilenameUtils
+ .normalize(path))))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * TODO - document me!
+ *
+ * @param filename
+ * @return string with a single dot only
+ */
+ public static String forceSingleExtension(final String filename) {
+ return filename.replaceAll("\\.(?![^.]+$)", "_");
+ }
+
+ /**
+ * TODO - document me!
+ *
+ * @param filename
+ * @return true
if filename contains severals dots else
+ * false
+ */
+ public static boolean isSingleExtension(final String filename) {
+ return filename.matches("[^\\.]+\\.[^\\.]+");
+ }
+
+ /**
+ * TODO - document me!
+ * @param dir
+ */
+ public static void checkDirAndCreate(File dir) {
+ if (!dir.exists()) {
+ dir.mkdirs();
+ logger.debug("Dir '{}' successfully created", dir);
+ }
+ }
+
+}
Index: /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/UtilsResponse.java
===================================================================
--- /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/UtilsResponse.java (revision 1875)
+++ /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/UtilsResponse.java (revision 1875)
@@ -0,0 +1,85 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+package net.fckeditor.tool;
+
+import javax.servlet.http.HttpServletRequest;
+
+import net.fckeditor.handlers.ConnectorHandler;
+import net.fckeditor.handlers.ResourceTypeHandler;
+
+/**
+ * Some static helper methods in conjunction with the servlet response.
+ *
+ * @version $Id$
+ */
+public class UtilsResponse {
+
+ /**
+ * TODO - document me!
+ *
+ * @param request
+ * @param resourceType
+ * @param urlPath TODO
+ * @param prependContextPath
+ * @param fullUrl
+ * @return
+ */
+ public static String constructResponseUrl(HttpServletRequest request,
+ ResourceTypeHandler resourceType, String urlPath,
+ boolean prependContextPath, boolean fullUrl) {
+
+ StringBuffer sb = new StringBuffer();
+
+ if (fullUrl) {
+ String address = request.getRequestURL().toString();
+ sb.append(address.substring(0, address.indexOf('/', 8))
+ + request.getContextPath());
+ }
+
+ if (prependContextPath && !fullUrl)
+ sb.append(request.getContextPath());
+
+ sb.append(ConnectorHandler.getUserFilesPath(request));
+ sb.append(resourceType.getPath());
+
+ if (Utils.isNotEmpty(urlPath))
+ sb.append(urlPath);
+
+ return sb.toString();
+ }
+
+ /**
+ * TODO - document me!
+ *
+ * @param request
+ * @param resourceType
+ * @param prependContextPath
+ * @param fullUrl
+ * @return
+ */
+ public static String constructResponseUrl(HttpServletRequest request,
+ ResourceTypeHandler resourceType, boolean prependContextPath,
+ boolean fullUrl) {
+ return constructResponseUrl(request, resourceType, null,
+ prependContextPath, fullUrl);
+ }
+
+}
Index: /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/XHtmlTagTool.java
===================================================================
--- /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/XHtmlTagTool.java (revision 1875)
+++ /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/java/net/fckeditor/tool/XHtmlTagTool.java (revision 1875)
@@ -0,0 +1,135 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2008 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ * - GNU General Public License Version 2 or later (the "GPL")
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * - Mozilla Public License Version 1.1 or later (the "MPL")
+ * http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ */
+package net.fckeditor.tool;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Tool to construct a XHTML-tag.
+ *
+ * Usage:
+ *
+ * XHtmlTagTool tag = XHtmlTagTool("a", "link");
+ * tag.addAttribute("href", "http://google.com");
+ * tag.toString(); : <a href="http://google.com">link</a>
+ *
+ *
+ * Hint:
+ *
+ *
+ *
+ * @version $Id$
+ */
+public class XHtmlTagTool {
+
+ /** Name of the tag. */
+ private String name;
+
+ /** Container for the attributes. */
+ private Map
+ * ImageInfo ii = new ImageInfo();
+ * ii.setInput(in); // in can be InputStream or RandomAccessFile
+ * ii.setDetermineImageNumber(true); // default is false
+ * ii.setCollectComments(true); // default is false
+ * if (!ii.check()) {
+ * System.err.println("Not a supported image file format.");
+ * return;
+ * }
+ * System.out.println(ii.getFormatName() + ", " + ii.getMimeType() +
+ * ", " + ii.getWidth() + " x " + ii.getHeight() + " pixels, " +
+ * ii.getBitsPerPixel() + " bits per pixel, " + ii.getNumberOfImages() +
+ * " image(s), " + ii.getNumberOfComments() + " comment(s).");
+ * // there are other properties, check out the API documentation
+ *
+ * You can also use this class as a command line program.
+ * Call it with a number of image file names and URLs as parameters:
+ *
+ * java ImageInfo *.jpg *.png *.gif http://somesite.tld/image.jpg
+ *
+ * or call it without parameters and pipe data to it:
+ *
+ * java ImageInfo < image.jpg
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * @author Marco Schmidt
+ */
+public class ImageInfo {
+ /**
+ * Return value of {@link #getFormat()} for JPEG streams.
+ * ImageInfo can extract physical resolution and comments
+ * from JPEGs (only from APP0 headers).
+ * Only one image can be stored in a file.
+ * It is determined whether the JPEG stream is progressive
+ * (see {@link #isProgressive()}).
+ */
+ public static final int FORMAT_JPEG = 0;
+
+ /**
+ * Return value of {@link #getFormat()} for GIF streams.
+ * ImageInfo can extract comments from GIFs and count the number
+ * of images (GIFs with more than one image are animations).
+ * It is determined whether the GIF stream is interlaced (see {@link #isProgressive()}).
+ */
+ public static final int FORMAT_GIF = 1;
+
+ /**
+ * Return value of {@link #getFormat()} for PNG streams.
+ * PNG only supports one image per file.
+ * Both physical resolution and comments can be stored with PNG,
+ * but ImageInfo is currently not able to extract those.
+ * It is determined whether the PNG stream is interlaced (see {@link #isProgressive()}).
+ */
+ public static final int FORMAT_PNG = 2;
+
+ /**
+ * Return value of {@link #getFormat()} for BMP streams.
+ * BMP only supports one image per file.
+ * BMP does not allow for comments.
+ * The physical resolution can be stored.
+ */
+ public static final int FORMAT_BMP = 3;
+
+ /**
+ * Return value of {@link #getFormat()} for PCX streams.
+ * PCX does not allow for comments or more than one image per file.
+ * However, the physical resolution can be stored.
+ */
+ public static final int FORMAT_PCX = 4;
+
+ /**
+ * Return value of {@link #getFormat()} for IFF streams.
+ */
+ public static final int FORMAT_IFF = 5;
+
+ /**
+ * Return value of {@link #getFormat()} for RAS streams.
+ * Sun Raster allows for one image per file only and is not able to
+ * store physical resolution or comments.
+ */
+ public static final int FORMAT_RAS = 6;
+
+ /** Return value of {@link #getFormat()} for PBM streams. */
+ public static final int FORMAT_PBM = 7;
+
+ /** Return value of {@link #getFormat()} for PGM streams. */
+ public static final int FORMAT_PGM = 8;
+
+ /** Return value of {@link #getFormat()} for PPM streams. */
+ public static final int FORMAT_PPM = 9;
+
+ /** Return value of {@link #getFormat()} for PSD streams. */
+ public static final int FORMAT_PSD = 10;
+
+/* public static final int COLOR_TYPE_UNKNOWN = -1;
+ public static final int COLOR_TYPE_TRUECOLOR_RGB = 0;
+ public static final int COLOR_TYPE_PALETTED = 1;
+ public static final int COLOR_TYPE_GRAYSCALE= 2;
+ public static final int COLOR_TYPE_BLACK_AND_WHITE = 3;*/
+
+ /**
+ * The names of all supported file formats.
+ * The FORMAT_xyz int constants can be used as index values for
+ * this array.
+ */
+ private static final String[] FORMAT_NAMES =
+ {"JPEG", "GIF", "PNG", "BMP", "PCX",
+ "IFF", "RAS", "PBM", "PGM", "PPM",
+ "PSD"};
+
+ /**
+ * The names of the MIME types for all supported file formats.
+ * The FORMAT_xyz int constants can be used as index values for
+ * this array.
+ */
+ private static final String[] MIME_TYPE_STRINGS =
+ {"image/jpeg", "image/gif", "image/png", "image/bmp", "image/pcx",
+ "image/iff", "image/ras", "image/x-portable-bitmap", "image/x-portable-graymap", "image/x-portable-pixmap",
+ "image/psd"};
+
+ private int width;
+ private int height;
+ private int bitsPerPixel;
+ //private int colorType = COLOR_TYPE_UNKNOWN;
+ private boolean progressive;
+ private int format;
+ private InputStream in;
+ private DataInput din;
+ private boolean collectComments = true;
+ private Vector comments;
+ private boolean determineNumberOfImages;
+ private int numberOfImages;
+ private int physicalHeightDpi;
+ private int physicalWidthDpi;
+
+ private void addComment(String s) {
+ if (comments == null) {
+ comments = new Vector();
+ }
+ comments.addElement(s);
+ }
+
+ /**
+ * Call this method after you have provided an input stream or file
+ * using {@link #setInput(InputStream)} or {@link #setInput(DataInput)}.
+ * If true is returned, the file format was known and information
+ * on the file's content can be retrieved using the various getXyz methods.
+ * @return if information could be retrieved from input
+ */
+ public boolean check() {
+ format = -1;
+ width = -1;
+ height = -1;
+ bitsPerPixel = -1;
+ numberOfImages = 1;
+ physicalHeightDpi = -1;
+ physicalWidthDpi = -1;
+ comments = null;
+ try {
+ int b1 = read() & 0xff;
+ int b2 = read() & 0xff;
+ if (b1 == 0x47 && b2 == 0x49) {
+ return checkGif();
+ }
+ else
+ if (b1 == 0x89 && b2 == 0x50) {
+ return checkPng();
+ }
+ else
+ if (b1 == 0xff && b2 == 0xd8) {
+ return checkJpeg();
+ }
+ else
+ if (b1 == 0x42 && b2 == 0x4d) {
+ return checkBmp();
+ }
+ else
+ if (b1 == 0x0a && b2 < 0x06) {
+ return checkPcx();
+ }
+ else
+ if (b1 == 0x46 && b2 == 0x4f) {
+ return checkIff();
+ }
+ else
+ if (b1 == 0x59 && b2 == 0xa6) {
+ return checkRas();
+ }
+ else
+ if (b1 == 0x50 && b2 >= 0x31 && b2 <= 0x36) {
+ return checkPnm(b2 - '0');
+ }
+ else
+ if (b1 == 0x38 && b2 == 0x42) {
+ return checkPsd();
+ }
+ else {
+ return false;
+ }
+ } catch (IOException ioe) {
+ return false;
+ }
+ }
+
+ private boolean checkBmp() throws IOException {
+ byte[] a = new byte[44];
+ if (read(a) != a.length) {
+ return false;
+ }
+ width = getIntLittleEndian(a, 16);
+ height = getIntLittleEndian(a, 20);
+ if (width < 1 || height < 1) {
+ return false;
+ }
+ bitsPerPixel = getShortLittleEndian(a, 26);
+ if (bitsPerPixel != 1 && bitsPerPixel != 4 &&
+ bitsPerPixel != 8 && bitsPerPixel != 16 &&
+ bitsPerPixel != 24 && bitsPerPixel != 32) {
+ return false;
+ }
+ int x = (int)(getIntLittleEndian(a, 36) * 0.0254);
+ if (x > 0) {
+ setPhysicalWidthDpi(x);
+ }
+ int y = (int)(getIntLittleEndian(a, 40) * 0.0254);
+ if (y > 0) {
+ setPhysicalHeightDpi(y);
+ }
+ format = FORMAT_BMP;
+ return true;
+ }
+
+ private boolean checkGif() throws IOException {
+ final byte[] GIF_MAGIC_87A = {0x46, 0x38, 0x37, 0x61};
+ final byte[] GIF_MAGIC_89A = {0x46, 0x38, 0x39, 0x61};
+ byte[] a = new byte[11]; // 4 from the GIF signature + 7 from the global header
+ if (read(a) != 11) {
+ return false;
+ }
+ if ((!equals(a, 0, GIF_MAGIC_89A, 0, 4)) &&
+ (!equals(a, 0, GIF_MAGIC_87A, 0, 4))) {
+ return false;
+ }
+ format = FORMAT_GIF;
+ width = getShortLittleEndian(a, 4);
+ height = getShortLittleEndian(a, 6);
+ int flags = a[8] & 0xff;
+ bitsPerPixel = ((flags >> 4) & 0x07) + 1;
+ //progressive = (flags & 0x02) != 0;
+ if (!determineNumberOfImages) {
+ return true;
+ }
+ // skip global color palette
+ if ((flags & 0x80) != 0) {
+ int tableSize = (1 << ((flags & 7) + 1)) * 3;
+ skip(tableSize);
+ }
+ numberOfImages = 0;
+ int blockType;
+ do
+ {
+ blockType = read();
+ switch(blockType)
+ {
+ case(0x2c): // image separator
+ {
+ if (read(a, 0, 9) != 9) {
+ return false;
+ }
+ flags = a[8] & 0xff;
+ progressive = (flags & 0x40) != 0;
+ /*int locWidth = getShortLittleEndian(a, 4);
+ int locHeight = getShortLittleEndian(a, 6);
+ System.out.println("LOCAL: " + locWidth + " x " + locHeight);*/
+ int localBitsPerPixel = (flags & 0x07) + 1;
+ if (localBitsPerPixel > bitsPerPixel) {
+ bitsPerPixel = localBitsPerPixel;
+ }
+ if ((flags & 0x80) != 0) {
+ skip((1 << localBitsPerPixel) * 3);
+ }
+ skip(1); // initial code length
+ int n;
+ do
+ {
+ n = read();
+ if (n > 0) {
+ skip(n);
+ }
+ else
+ if (n == -1) {
+ return false;
+ }
+ }
+ while (n > 0);
+ numberOfImages++;
+ break;
+ }
+ case(0x21): // extension
+ {
+ int extensionType = read();
+ if (collectComments && extensionType == 0xfe) {
+ StringBuffer sb = new StringBuffer();
+ int n;
+ do
+ {
+ n = read();
+ if (n == -1) {
+ return false;
+ }
+ if (n > 0) {
+ for (int i = 0; i < n; i++) {
+ int ch = read();
+ if (ch == -1) {
+ return false;
+ }
+ sb.append((char)ch);
+ }
+ }
+ }
+ while (n > 0);
+ } else {
+ int n;
+ do
+ {
+ n = read();
+ if (n > 0) {
+ skip(n);
+ }
+ else
+ if (n == -1) {
+ return false;
+ }
+ }
+ while (n > 0);
+ }
+ break;
+ }
+ case(0x3b): // end of file
+ {
+ break;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+ }
+ while (blockType != 0x3b);
+ return true;
+ }
+
+ private boolean checkIff() throws IOException {
+ byte[] a = new byte[10];
+ // read remaining 2 bytes of file id, 4 bytes file size
+ // and 4 bytes IFF subformat
+ if (read(a, 0, 10) != 10) {
+ return false;
+ }
+ final byte[] IFF_RM = {0x52, 0x4d};
+ if (!equals(a, 0, IFF_RM, 0, 2)) {
+ return false;
+ }
+ int type = getIntBigEndian(a, 6);
+ if (type != 0x494c424d && // type must be ILBM...
+ type != 0x50424d20) { // ...or PBM
+ return false;
+ }
+ // loop chunks to find BMHD chunk
+ do {
+ if (read(a, 0, 8) != 8) {
+ return false;
+ }
+ int chunkId = getIntBigEndian(a, 0);
+ int size = getIntBigEndian(a, 4);
+ if ((size & 1) == 1) {
+ size++;
+ }
+ if (chunkId == 0x424d4844) { // BMHD chunk
+ if (read(a, 0, 9) != 9) {
+ return false;
+ }
+ format = FORMAT_IFF;
+ width = getShortBigEndian(a, 0);
+ height = getShortBigEndian(a, 2);
+ bitsPerPixel = a[8] & 0xff;
+ return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel < 33);
+ } else {
+ skip(size);
+ }
+ } while (true);
+ }
+
+ private boolean checkJpeg() throws IOException {
+ byte[] data = new byte[12];
+ while (true) {
+ if (read(data, 0, 4) != 4) {
+ return false;
+ }
+ int marker = getShortBigEndian(data, 0);
+ int size = getShortBigEndian(data, 2);
+ if ((marker & 0xff00) != 0xff00) {
+ return false; // not a valid marker
+ }
+ if (marker == 0xffe0) { // APPx
+ if (size < 14) {
+ // not an APPx header as we know it, skip
+ skip(size - 2);
+ continue;
+ }
+ if (read(data, 0, 12) != 12) {
+ return false;
+ }
+ final byte[] APP0_ID = {0x4a, 0x46, 0x49, 0x46, 0x00};
+ if (equals(APP0_ID, 0, data, 0, 5)) {
+ //System.out.println("data 7=" + data[7]);
+ if (data[7] == 1) {
+ setPhysicalWidthDpi(getShortBigEndian(data, 8));
+ setPhysicalHeightDpi(getShortBigEndian(data, 10));
+ }
+ else
+ if (data[7] == 2) {
+ int x = getShortBigEndian(data, 8);
+ int y = getShortBigEndian(data, 10);
+ setPhysicalWidthDpi((int)(x * 2.54f));
+ setPhysicalHeightDpi((int)(y * 2.54f));
+ }
+ }
+ skip(size - 14);
+ }
+ else
+ if (collectComments && size > 2 && marker == 0xfffe) { // comment
+ size -= 2;
+ byte[] chars = new byte[size];
+ if (read(chars, 0, size) != size) {
+ return false;
+ }
+ String comment = new String(chars, "iso-8859-1");
+ comment = comment.trim();
+ addComment(comment);
+ }
+ else
+ if (marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4 && marker != 0xffc8) {
+ if (read(data, 0, 6) != 6) {
+ return false;
+ }
+ format = FORMAT_JPEG;
+ bitsPerPixel = (data[0] & 0xff) * (data[5] & 0xff);
+ progressive = marker == 0xffc2 || marker == 0xffc6 ||
+ marker == 0xffca || marker == 0xffce;
+ width = getShortBigEndian(data, 3);
+ height = getShortBigEndian(data, 1);
+ return true;
+ } else {
+ skip(size - 2);
+ }
+ }
+ }
+
+ private boolean checkPcx() throws IOException {
+ byte[] a = new byte[64];
+ if (read(a) != a.length) {
+ return false;
+ }
+ if (a[0] != 1) { // encoding, 1=RLE is only valid value
+ return false;
+ }
+ // width / height
+ int x1 = getShortLittleEndian(a, 2);
+ int y1 = getShortLittleEndian(a, 4);
+ int x2 = getShortLittleEndian(a, 6);
+ int y2 = getShortLittleEndian(a, 8);
+ if (x1 < 0 || x2 < x1 || y1 < 0 || y2 < y1) {
+ return false;
+ }
+ width = x2 - x1 + 1;
+ height = y2 - y1 + 1;
+ // color depth
+ int bits = a[1];
+ int planes = a[63];
+ if (planes == 1 &&
+ (bits == 1 || bits == 2 || bits == 4 || bits == 8)) {
+ // paletted
+ bitsPerPixel = bits;
+ } else
+ if (planes == 3 && bits == 8) {
+ // RGB truecolor
+ bitsPerPixel = 24;
+ } else {
+ return false;
+ }
+ setPhysicalWidthDpi(getShortLittleEndian(a, 10));
+ setPhysicalHeightDpi(getShortLittleEndian(a, 10));
+ format = FORMAT_PCX;
+ return true;
+ }
+
+ private boolean checkPng() throws IOException {
+ final byte[] PNG_MAGIC = {0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
+ byte[] a = new byte[27];
+ if (read(a) != 27) {
+ return false;
+ }
+ if (!equals(a, 0, PNG_MAGIC, 0, 6)) {
+ return false;
+ }
+ format = FORMAT_PNG;
+ width = getIntBigEndian(a, 14);
+ height = getIntBigEndian(a, 18);
+ bitsPerPixel = a[22] & 0xff;
+ int colorType = a[23] & 0xff;
+ if (colorType == 2 || colorType == 6) {
+ bitsPerPixel *= 3;
+ }
+ progressive = (a[26] & 0xff) != 0;
+ return true;
+ }
+
+ private boolean checkPnm(int id) throws IOException {
+ if (id < 1 || id > 6) {
+ return false;
+ }
+ final int[] PNM_FORMATS = {FORMAT_PBM, FORMAT_PGM, FORMAT_PPM};
+ format = PNM_FORMATS[(id - 1) % 3];
+ boolean hasPixelResolution = false;
+ String s;
+ while (true)
+ {
+ s = readLine();
+ if (s != null) {
+ s = s.trim();
+ }
+ if (s == null || s.length() < 1) {
+ continue;
+ }
+ if (s.charAt(0) == '#') { // comment
+ if (collectComments && s.length() > 1) {
+ addComment(s.substring(1));
+ }
+ continue;
+ }
+ if (!hasPixelResolution) { // split "343 966" into width=343, height=966
+ int spaceIndex = s.indexOf(' ');
+ if (spaceIndex == -1) {
+ return false;
+ }
+ String widthString = s.substring(0, spaceIndex);
+ spaceIndex = s.lastIndexOf(' ');
+ if (spaceIndex == -1) {
+ return false;
+ }
+ String heightString = s.substring(spaceIndex + 1);
+ try {
+ width = Integer.parseInt(widthString);
+ height = Integer.parseInt(heightString);
+ } catch (NumberFormatException nfe) {
+ return false;
+ }
+ if (width < 1 || height < 1) {
+ return false;
+ }
+ if (format == FORMAT_PBM) {
+ bitsPerPixel = 1;
+ return true;
+ }
+ hasPixelResolution = true;
+ }
+ else
+ {
+ int maxSample;
+ try {
+ maxSample = Integer.parseInt(s);
+ } catch (NumberFormatException nfe) {
+ return false;
+ }
+ if (maxSample < 0) {
+ return false;
+ }
+ for (int i = 0; i < 25; i++) {
+ if (maxSample < (1 << (i + 1))) {
+ bitsPerPixel = i + 1;
+ if (format == FORMAT_PPM) {
+ bitsPerPixel *= 3;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ }
+
+ private boolean checkPsd() throws IOException {
+ byte[] a = new byte[24];
+ if (read(a) != a.length) {
+ return false;
+ }
+ final byte[] PSD_MAGIC = {0x50, 0x53};
+ if (!equals(a, 0, PSD_MAGIC, 0, 2)) {
+ return false;
+ }
+ format = FORMAT_PSD;
+ width = getIntBigEndian(a, 16);
+ height = getIntBigEndian(a, 12);
+ int channels = getShortBigEndian(a, 10);
+ int depth = getShortBigEndian(a, 20);
+ bitsPerPixel = channels * depth;
+ return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 64);
+ }
+
+ private boolean checkRas() throws IOException {
+ byte[] a = new byte[14];
+ if (read(a) != a.length) {
+ return false;
+ }
+ final byte[] RAS_MAGIC = {0x6a, (byte)0x95};
+ if (!equals(a, 0, RAS_MAGIC, 0, 2)) {
+ return false;
+ }
+ format = FORMAT_RAS;
+ width = getIntBigEndian(a, 2);
+ height = getIntBigEndian(a, 6);
+ bitsPerPixel = getIntBigEndian(a, 10);
+ return (width > 0 && height > 0 && bitsPerPixel > 0 && bitsPerPixel <= 24);
+ }
+
+ /**
+ * Run over String list, return false iff at least one of the arguments
+ * equals true
as argument to identify animated GIFs
+ * ({@link #getNumberOfImages()} will return a value larger than 1
).-1
.
+ * -c
.
+ * @param args string list to check
+ */
+ private static boolean determineVerbosity(String[] args) {
+ if (args != null && args.length > 0) {
+ for (int i = 0; i < args.length; i++) {
+ if ("-c".equals(args[i])) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static boolean equals(byte[] a1, int offs1, byte[] a2, int offs2, int num) {
+ while (num-- > 0) {
+ if (a1[offs1++] != a2[offs2++]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * If {@link #check()} was successful, returns the image's number of bits per pixel.
+ * Does not include transparency information like the alpha channel.
+ * @return number of bits per image pixel
+ */
+ public int getBitsPerPixel() {
+ return bitsPerPixel;
+ }
+
+ /**
+ * Returns the index'th comment retrieved from the file.
+ * @param index int index of comment to return
+ * @throws IllegalArgumentException if index is smaller than 0 or larger than or equal
+ * to the number of comments retrieved
+ * @see #getNumberOfComments
+ */
+ public String getComment(int index) {
+ if (comments == null || index < 0 || index >= comments.size()) {
+ throw new IllegalArgumentException("Not a valid comment index: " + index);
+ }
+ return (String)comments.elementAt(index);
+ }
+
+ /**
+ * If {@link #check()} was successful, returns the image format as one
+ * of the FORMAT_xyz constants from this class.
+ * Use {@link #getFormatName()} to get a textual description of the file format.
+ * @return file format as a FORMAT_xyz constant
+ */
+ public int getFormat() {
+ return format;
+ }
+
+ /**
+ * If {@link #check()} was successful, returns the image format's name.
+ * Use {@link #getFormat()} to get a unique number.
+ * @return file format name
+ */
+ public String getFormatName() {
+ if (format >= 0 && format < FORMAT_NAMES.length) {
+ return FORMAT_NAMES[format];
+ } else {
+ return "?";
+ }
+ }
+
+ /**
+ * If {@link #check()} was successful, returns one the image's vertical
+ * resolution in pixels.
+ * @return image height in pixels
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ private static int getIntBigEndian(byte[] a, int offs) {
+ return
+ (a[offs] & 0xff) << 24 |
+ (a[offs + 1] & 0xff) << 16 |
+ (a[offs + 2] & 0xff) << 8 |
+ a[offs + 3] & 0xff;
+ }
+
+ private static int getIntLittleEndian(byte[] a, int offs) {
+ return
+ (a[offs + 3] & 0xff) << 24 |
+ (a[offs + 2] & 0xff) << 16 |
+ (a[offs + 1] & 0xff) << 8 |
+ a[offs] & 0xff;
+ }
+
+ /**
+ * If {@link #check()} was successful, returns a String with the
+ * MIME type of the format.
+ * @return MIME type, e.g. image/jpeg
+ */
+ public String getMimeType() {
+ if (format >= 0 && format < MIME_TYPE_STRINGS.length) {
+ if (format == FORMAT_JPEG && progressive)
+ {
+ return "image/pjpeg";
+ }
+ return MIME_TYPE_STRINGS[format];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * If {@link #check()} was successful and {@link #setCollectComments(boolean)} was called with
+ * true
as argument, returns the number of comments retrieved
+ * from the input image stream / file.
+ * Any number >= 0 and smaller than this number of comments is then a
+ * valid argument for the {@link #getComment(int)} method.
+ * @return number of comments retrieved from input image
+ */
+ public int getNumberOfComments()
+ {
+ if (comments == null) {
+ return 0;
+ } else {
+ return comments.size();
+ }
+ }
+
+ /**
+ * Returns the number of images in the examined file.
+ * Assumes that setDetermineImageNumber(true);
was called before
+ * a successful call to {@link #check()}.
+ * This value can currently be only different from 1
for GIF images.
+ * @return number of images in file
+ */
+ public int getNumberOfImages()
+ {
+ return numberOfImages;
+ }
+
+ /**
+ * Returns the physical height of this image in dots per inch (dpi).
+ * Assumes that {@link #check()} was successful.
+ * Returns -1
on failure.
+ * @return physical height (in dpi)
+ * @see #getPhysicalWidthDpi()
+ * @see #getPhysicalHeightInch()
+ */
+ public int getPhysicalHeightDpi() {
+ return physicalHeightDpi;
+ }
+
+ /**
+ * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch)
+ * or -1 if no value could be found.
+ * @return physical height (in dpi)
+ * @see #getPhysicalHeightDpi()
+ * @see #getPhysicalWidthDpi()
+ * @see #getPhysicalWidthInch()
+ */
+ public float getPhysicalHeightInch() {
+ int h = getHeight();
+ int ph = getPhysicalHeightDpi();
+ if (h > 0 && ph > 0) {
+ return ((float)h) / ((float)ph);
+ } else {
+ return -1.0f;
+ }
+ }
+
+ /**
+ * If {@link #check()} was successful, returns the physical width of this image in dpi (dots per inch)
+ * or -1 if no value could be found.
+ * @return physical width (in dpi)
+ * @see #getPhysicalHeightDpi()
+ * @see #getPhysicalWidthInch()
+ * @see #getPhysicalHeightInch()
+ */
+ public int getPhysicalWidthDpi() {
+ return physicalWidthDpi;
+ }
+
+ /**
+ * Returns the physical width of an image in inches, or
+ * -1.0f
if width information is not available.
+ * Assumes that {@link #check} has been called successfully.
+ * @return physical width in inches or -1.0f
on failure
+ * @see #getPhysicalWidthDpi
+ * @see #getPhysicalHeightInch
+ */
+ public float getPhysicalWidthInch() {
+ int w = getWidth();
+ int pw = getPhysicalWidthDpi();
+ if (w > 0 && pw > 0) {
+ return ((float)w) / ((float)pw);
+ } else {
+ return -1.0f;
+ }
+ }
+
+ private static int getShortBigEndian(byte[] a, int offs) {
+ return
+ (a[offs] & 0xff) << 8 |
+ (a[offs + 1] & 0xff);
+ }
+
+ private static int getShortLittleEndian(byte[] a, int offs) {
+ return (a[offs] & 0xff) | (a[offs + 1] & 0xff) << 8;
+ }
+
+ /**
+ * If {@link #check()} was successful, returns one the image's horizontal
+ * resolution in pixels.
+ * @return image width in pixels
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * Returns whether the image is stored in a progressive (also called: interlaced) way.
+ * @return true for progressive/interlaced, false otherwise
+ */
+ public boolean isProgressive()
+ {
+ return progressive;
+ }
+
+ /**
+ * To use this class as a command line application, give it either
+ * some file names as parameters (information on them will be
+ * printed to standard output, one line per file) or call
+ * it with no parameters. It will then check data given to it
+ * via standard input.
+ * @param args the program arguments which must be file names
+ */
+ public static void main(String[] args) {
+ ImageInfo imageInfo = new ImageInfo();
+ imageInfo.setDetermineImageNumber(true);
+ boolean verbose = determineVerbosity(args);
+ if (args.length == 0) {
+ run(null, System.in, imageInfo, verbose);
+ } else {
+ int index = 0;
+ while (index < args.length) {
+ InputStream in = null;
+ try {
+ String name = args[index++];
+ System.out.print(name + ";");
+ if (name.startsWith("http://")) {
+ in = new URL(name).openConnection().getInputStream();
+ } else {
+ in = new FileInputStream(name);
+ }
+ run(name, in, imageInfo, verbose);
+ in.close();
+ } catch (IOException e) {
+ System.out.println(e);
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException ee) {
+ }
+ }
+ }
+ }
+ }
+
+ private static void print(String sourceName, ImageInfo ii, boolean verbose) {
+ if (verbose) {
+ printVerbose(sourceName, ii);
+ } else {
+ printCompact(sourceName, ii);
+ }
+ }
+
+ private static void printCompact(String sourceName, ImageInfo imageInfo) {
+ final String SEP = "\t";
+ System.out.println(
+ sourceName + SEP +
+ imageInfo.getFormatName() + SEP +
+ imageInfo.getMimeType() + SEP +
+ imageInfo.getWidth() + SEP +
+ imageInfo.getHeight() + SEP +
+ imageInfo.getBitsPerPixel() + SEP +
+ imageInfo.getNumberOfImages() + SEP +
+ imageInfo.getPhysicalWidthDpi() + SEP +
+ imageInfo.getPhysicalHeightDpi() + SEP +
+ imageInfo.getPhysicalWidthInch() + SEP +
+ imageInfo.getPhysicalHeightInch() + SEP +
+ imageInfo.isProgressive()
+ );
+ }
+
+ private static void printLine(int indentLevels, String text, float value, float minValidValue) {
+ if (value < minValidValue) {
+ return;
+ }
+ printLine(indentLevels, text, Float.toString(value));
+ }
+
+ private static void printLine(int indentLevels, String text, int value, int minValidValue) {
+ if (value >= minValidValue) {
+ printLine(indentLevels, text, Integer.toString(value));
+ }
+ }
+
+ private static void printLine(int indentLevels, String text, String value) {
+ if (value == null || value.length() == 0) {
+ return;
+ }
+ while (indentLevels-- > 0) {
+ System.out.print("\t");
+ }
+ if (text != null && text.length() > 0) {
+ System.out.print(text);
+ System.out.print(" ");
+ }
+ System.out.println(value);
+ }
+
+ private static void printVerbose(String sourceName, ImageInfo ii) {
+ printLine(0, null, sourceName);
+ printLine(1, "File format: ", ii.getFormatName());
+ printLine(1, "MIME type: ", ii.getMimeType());
+ printLine(1, "Width (pixels): ", ii.getWidth(), 1);
+ printLine(1, "Height (pixels): ", ii.getHeight(), 1);
+ printLine(1, "Bits per pixel: ", ii.getBitsPerPixel(), 1);
+ printLine(1, "Progressive: ", ii.isProgressive() ? "yes" : "no");
+ printLine(1, "Number of images: ", ii.getNumberOfImages(), 1);
+ printLine(1, "Physical width (dpi): ", ii.getPhysicalWidthDpi(), 1);
+ printLine(1, "Physical height (dpi): ", ii.getPhysicalHeightDpi(), 1);
+ printLine(1, "Physical width (inches): ", ii.getPhysicalWidthInch(), 1.0f);
+ printLine(1, "Physical height (inches): ", ii.getPhysicalHeightInch(), 1.0f);
+ int numComments = ii.getNumberOfComments();
+ printLine(1, "Number of textual comments: ", numComments, 1);
+ if (numComments > 0) {
+ for (int i = 0; i < numComments; i++) {
+ printLine(2, null, ii.getComment(i));
+ }
+ }
+ }
+
+ private int read() throws IOException {
+ if (in != null) {
+ return in.read();
+ } else {
+ return din.readByte();
+ }
+ }
+
+ private int read(byte[] a) throws IOException {
+ if (in != null) {
+ return in.read(a);
+ } else {
+ din.readFully(a);
+ return a.length;
+ }
+ }
+
+ private int read(byte[] a, int offset, int num) throws IOException {
+ if (in != null) {
+ return in.read(a, offset, num);
+ } else {
+ din.readFully(a, offset, num);
+ return num;
+ }
+ }
+
+ private String readLine() throws IOException {
+ return readLine(new StringBuffer());
+ }
+
+ private String readLine(StringBuffer sb) throws IOException {
+ boolean finished;
+ do {
+ int value = read();
+ finished = (value == -1 || value == 10);
+ if (!finished) {
+ sb.append((char)value);
+ }
+ } while (!finished);
+ return sb.toString();
+ }
+
+ private static void run(String sourceName, InputStream in, ImageInfo imageInfo, boolean verbose) {
+ imageInfo.setInput(in);
+ imageInfo.setDetermineImageNumber(true);
+ imageInfo.setCollectComments(verbose);
+ if (imageInfo.check()) {
+ print(sourceName, imageInfo, verbose);
+ }
+ }
+
+ /**
+ * Specify whether textual comments are supposed to be extracted from input.
+ * Default is false
.
+ * If enabled, comments will be added to an internal list.
+ * @param newValue if true
, this class will read comments
+ * @see #getNumberOfComments
+ * @see #getComment
+ */
+ public void setCollectComments(boolean newValue)
+ {
+ collectComments = newValue;
+ }
+
+ /**
+ * Specify whether the number of images in a file is to be
+ * determined - default is false
.
+ * This is a special option because some file formats require running over
+ * the entire file to find out the number of images, a rather time-consuming
+ * task.
+ * Not all file formats support more than one image.
+ * If this method is called with true
as argument,
+ * the actual number of images can be queried via
+ * {@link #getNumberOfImages()} after a successful call to
+ * {@link #check()}.
+ * @param newValue will the number of images be determined?
+ * @see #getNumberOfImages
+ */
+ public void setDetermineImageNumber(boolean newValue)
+ {
+ determineNumberOfImages = newValue;
+ }
+
+ /**
+ * Set the input stream to the argument stream (or file).
+ * Note that {@link java.io.RandomAccessFile} implements
+ * {@link java.io.DataInput}.
+ * @param dataInput the input stream to read from
+ */
+ public void setInput(DataInput dataInput) {
+ din = dataInput;
+ in = null;
+ }
+
+ /**
+ * Set the input stream to the argument stream (or file).
+ * @param inputStream the input stream to read from
+ */
+ public void setInput(InputStream inputStream) {
+ in = inputStream;
+ din = null;
+ }
+
+ private void setPhysicalHeightDpi(int newValue) {
+ physicalWidthDpi = newValue;
+ }
+
+ private void setPhysicalWidthDpi(int newValue) {
+ physicalHeightDpi = newValue;
+ }
+
+ private void skip(int num) throws IOException {
+ while (num > 0) {
+ long result;
+ if (in != null) {
+ result = in.skip(num);
+ } else {
+ result = din.skipBytes(num);
+ }
+ if (result > 0) {
+ num -= result;
+ } else {
+ if (in != null) {
+ result = in.read();
+ } else {
+ result = din.readByte();
+ }
+ if (result == -1) {
+ throw new IOException("Premature end of input.");
+ } else {
+ num--;
+ }
+ }
+ }
+ }
+}
Index: /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/resources/META-INF/FCKeditor.tld
===================================================================
--- /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/resources/META-INF/FCKeditor.tld (revision 1875)
+++ /FCKeditor.Java/branches/2.4/fckeditor-java/src/main/resources/META-INF/FCKeditor.tld (revision 1875)
@@ -0,0 +1,128 @@
+
+