3090 lines · 116.7 KB · Java
RawDownload
    /**     *  Translation function for converting string into     *  a byte array. Search-and-replace EOLN. Encode into the     *  target format. Append terminating NUL bytes.     *     *  Java to Native string conversion     */    private byte[] translateTransferableString(String str,                                               long format) throws IOException    {        Long lFormat = Long.valueOf(format);        String charset = getBestCharsetForTextFormat(lFormat, null);        // Search and replace EOLN. Note that if EOLN is "\n", then we        // never added an entry to nativeEOLNs anyway, so we'll skip this        // code altogether.        // windows: "abc\nde"->"abc\r\nde"        String eoln = (String)nativeEOLNs.get(lFormat);        if (eoln != null) {            int length = str.length();            StringBuffer buffer =                new StringBuffer(length * 2); // 2 is a heuristic            for (int i = 0; i < length; i++) {                // Fix for 4914613 - skip native EOLN                if (str.startsWith(eoln, i)) {                    buffer.append(eoln);                    i += eoln.length() - 1;                    continue;                }                char c = str.charAt(i);                if (c == '\n') {                    buffer.append(eoln);                } else {                    buffer.append(c);                }            }            str = buffer.toString();        }         // Encode text in target format.        byte[] bytes = str.getBytes(charset);         // Append terminating NUL bytes. Note that if terminators is 0,        // the we never added an entry to nativeTerminators anyway, so        // we'll skip code altogether.        // "abcde" -> "abcde\0"        Integer terminators = (Integer)nativeTerminators.get(lFormat);        if (terminators != null) {            int numTerminators = terminators.intValue();            byte[] terminatedBytes =                new byte[bytes.length + numTerminators];            System.arraycopy(bytes, 0, terminatedBytes, 0, bytes.length);            for (int i = bytes.length; i < terminatedBytes.length; i++) {                terminatedBytes[i] = 0x0;            }            bytes = terminatedBytes;        }        return bytes;    }     /**     * Translating either a byte array or an InputStream into an String.     * Strip terminators and search-and-replace EOLN.     *     * Native to Java string conversion     */    private String translateBytesOrStreamToString(InputStream str,  byte[] bytes,                                                    long format,                                                    Transferable localeTransferable)            throws IOException    {        // A String holds all of its data in memory at one time, so        // we can't avoid reading the entire InputStream at this point.        if (bytes == null) {            bytes = inputStreamToByteArray(str);        }        str.close();         Long lFormat = Long.valueOf(format);        String charset = getBestCharsetForTextFormat(lFormat, localeTransferable);         // Locate terminating NUL bytes. Note that if terminators is 0,        // the we never added an entry to nativeTerminators anyway, so        // we'll skip code altogether.         // In other words: we are doing char alignment here basing on suggestion        // that count of zero-'terminators' is a number of bytes in one symbol        // for selected charset (clipboard format). It is not complitly true for        // multibyte coding like UTF-8, but helps understand the procedure.        // "abcde\0" -> "abcde"         String eoln = (String)nativeEOLNs.get(lFormat);        Integer terminators = (Integer)nativeTerminators.get(lFormat);        int count;        if (terminators != null) {            int numTerminators = terminators.intValue();search:            for (count = 0; count < (bytes.length - numTerminators + 1); count += numTerminators) {                for (int i = count; i < count + numTerminators; i++) {                    if (bytes[i] != 0x0) {                        continue search;                    }                }                // found terminators                break search;            }        } else {            count = bytes.length;        }         // Decode text to chars. Don't include any terminators.        String converted = new String(bytes, 0, count, charset);         // Search and replace EOLN. Note that if EOLN is "\n", then we        // never added an entry to nativeEOLNs anyway, so we'll skip this        // code altogether.        // Count of NUL-terminators and EOLN coding are platform-specific and        // loaded from flavormap.properties file        // windows: "abc\r\nde" -> "abc\nde"         if (eoln != null) {             /* Fix for 4463560: replace EOLNs symbol-by-symbol instead             * of using buf.replace()             */             char[] buf = converted.toCharArray();            char[] eoln_arr = eoln.toCharArray();            converted = null;            int j = 0;            boolean match;             for (int i = 0; i < buf.length; ) {                // Catch last few bytes                if (i + eoln_arr.length > buf.length) {                    buf[j++] = buf[i++];                    continue;                }                 match = true;                for (int k = 0, l = i; k < eoln_arr.length; k++, l++) {                    if (eoln_arr[k] != buf[l]) {                        match = false;                        break;                    }                }                if (match) {                    buf[j++] = '\n';                    i += eoln_arr.length;                } else {                    buf[j++] = buf[i++];                }            }            converted = new String(buf, 0, j);        }         return converted;    }      /**     * Primary translation function for translating a Transferable into     * a byte array, given a source DataFlavor and target format.     */    public byte[] translateTransferable(Transferable contents,                                        DataFlavor flavor,                                        long format) throws IOException    {        // Obtain the transfer data in the source DataFlavor.        //        // Note that we special case DataFlavor.plainTextFlavor because        // StringSelection supports this flavor incorrectly -- instead of        // returning an InputStream as the DataFlavor representation class        // states, it returns a Reader. Instead of using this broken        // functionality, we request the data in stringFlavor (the other        // DataFlavor which StringSelection supports) and use the String        // translator.        Object obj;        boolean stringSelectionHack;        try {            obj = contents.getTransferData(flavor);            if (obj == null) {                return null;            }            if (flavor.equals(DataFlavor.plainTextFlavor) &&                !(obj instanceof InputStream))            {                obj = contents.getTransferData(DataFlavor.stringFlavor);                if (obj == null) {                    return null;                }                stringSelectionHack = true;            } else {                stringSelectionHack = false;            }        } catch (UnsupportedFlavorException e) {            throw new IOException(e.getMessage());        }         // Source data is a String. Search-and-replace EOLN. Encode into the        // target format. Append terminating NUL bytes.        if (stringSelectionHack ||            (String.class.equals(flavor.getRepresentationClass()) &&             isFlavorCharsetTextType(flavor) && isTextFormat(format))) {             String str = removeSuspectedData(flavor, contents, (String)obj);             return translateTransferableString(                str,                format);         // Source data is a Reader. Convert to a String and recur. In the        // future, we may want to rewrite this so that we encode on demand.        } else if (flavor.isRepresentationClassReader()) {            if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {                throw new IOException                    ("cannot transfer non-text data as Reader");            }             Reader r = (Reader)obj;            StringBuffer buf = new StringBuffer();            int c;            while ((c = r.read()) != -1) {                buf.append((char)c);            }            r.close();             return translateTransferableString(                buf.toString(),                format);         // Source data is a CharBuffer. Convert to a String and recur.        } else if (flavor.isRepresentationClassCharBuffer()) {            if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {                throw new IOException                    ("cannot transfer non-text data as CharBuffer");            }             CharBuffer buffer = (CharBuffer)obj;            int size = buffer.remaining();            char[] chars = new char[size];            buffer.get(chars, 0, size);             return translateTransferableString(                new String(chars),                format);         // Source data is a char array. Convert to a String and recur.        } else if (charArrayClass.equals(flavor.getRepresentationClass())) {            if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {                throw new IOException                    ("cannot transfer non-text data as char array");            }             return translateTransferableString(                new String((char[])obj),                format);         // Source data is a ByteBuffer. For arbitrary flavors, simply return        // the array. For text flavors, decode back to a String and recur to        // reencode according to the requested format.        } else if (flavor.isRepresentationClassByteBuffer()) {            ByteBuffer buffer = (ByteBuffer)obj;            int size = buffer.remaining();            byte[] bytes = new byte[size];            buffer.get(bytes, 0, size);             if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {                String sourceEncoding = DataTransferer.getTextCharset(flavor);                return translateTransferableString(                    new String(bytes, sourceEncoding),                    format);            } else {                return bytes;            }         // Source data is a byte array. For arbitrary flavors, simply return        // the array. For text flavors, decode back to a String and recur to        // reencode according to the requested format.        } else if (byteArrayClass.equals(flavor.getRepresentationClass())) {            byte[] bytes = (byte[])obj;             if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {                String sourceEncoding = DataTransferer.getTextCharset(flavor);                return translateTransferableString(                    new String(bytes, sourceEncoding),                    format);            } else {                return bytes;            }        // Source data is Image        } else if (DataFlavor.imageFlavor.equals(flavor)) {            if (!isImageFormat(format)) {                throw new IOException("Data translation failed: " +                                      "not an image format");            }             Image image = (Image)obj;            byte[] bytes = imageToPlatformBytes(image, format);             if (bytes == null) {                throw new IOException("Data translation failed: " +                    "cannot convert java image to native format");            }            return bytes;        }         ByteArrayOutputStream bos = new ByteArrayOutputStream();         // Target data is a file list. Source data must be a        // java.util.List which contains java.io.File or String instances.        if (isFileFormat(format)) {            if (!DataFlavor.javaFileListFlavor.equals(flavor)) {                throw new IOException("data translation failed");            }             final List list = (List)obj;             final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents);             final ArrayList<String> fileList = castToFiles(list, userProtectionDomain);             bos = convertFileListToBytes(fileList);          // Target data is a URI list. Source data must be a        // java.util.List which contains java.io.File or String instances.        } else if (isURIListFormat(format)) {            if (!DataFlavor.javaFileListFlavor.equals(flavor)) {                throw new IOException("data translation failed");            }            String nat = getNativeForFormat(format);            String targetCharset = null;            if (nat != null) {                try {                    targetCharset = new DataFlavor(nat).getParameter("charset");                } catch (ClassNotFoundException cnfe) {                    throw new IOException(cnfe);                }            }            if (targetCharset == null) {                targetCharset = "UTF-8";            }            final List list = (List)obj;            final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents);            final ArrayList<String> fileList = castToFiles(list, userProtectionDomain);            final ArrayList<String> uriList = new ArrayList<String>(fileList.size());            for (String fileObject : fileList) {                final URI uri = new File(fileObject).toURI();                // Some implementations are fussy about the number of slashes (file:///path/to/file is best)                try {                    uriList.add(new URI(uri.getScheme(), "", uri.getPath(), uri.getFragment()).toString());                } catch (URISyntaxException uriSyntaxException) {                    throw new IOException(uriSyntaxException);                  }              }             byte[] eoln = "\r\n".getBytes(targetCharset);            for (int i = 0; i < uriList.size(); i++) {                byte[] bytes = uriList.get(i).getBytes(targetCharset);                bos.write(bytes, 0, bytes.length);                bos.write(eoln, 0, eoln.length);            }         // Source data is an InputStream. For arbitrary flavors, just grab the        // bytes and dump them into a byte array. For text flavors, decode back        // to a String and recur to reencode according to the requested format.        } else if (flavor.isRepresentationClassInputStream()) {            InputStream is = (InputStream)obj;            boolean eof = false;            int avail = is.available();            byte[] tmp = new byte[avail > 8192 ? avail : 8192];            do {                int ret;                if (!(eof = (ret = is.read(tmp, 0, tmp.length)) == -1)) {                    bos.write(tmp, 0, ret);                }            } while (!eof);            is.close();             if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {                byte[] bytes = bos.toByteArray();                bos.close();                String sourceEncoding = DataTransferer.getTextCharset(flavor);                return translateTransferableString(                    new String(bytes, sourceEncoding),                    format);            }         // Source data is an RMI object        } else if (flavor.isRepresentationClassRemote()) {            Object mo = RMI.newMarshalledObject(obj);            ObjectOutputStream oos = new ObjectOutputStream(bos);            oos.writeObject(mo);            oos.close();         // Source data is Serializable        } else if (flavor.isRepresentationClassSerializable()) {            ObjectOutputStream oos = new ObjectOutputStream(bos);            oos.writeObject(obj);            oos.close();         } else {            throw new IOException("data translation failed");        }         byte[] ret = bos.toByteArray();        bos.close();        return ret;    }     protected abstract ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList) throws IOException;     private String removeSuspectedData(DataFlavor flavor, final Transferable contents, final String str)            throws IOException    {        if (null == System.getSecurityManager()            || !flavor.isMimeTypeEqual("text/uri-list"))        {            return str;        }          String ret_val = "";        final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents);         try {            ret_val = (String) AccessController.doPrivileged(new PrivilegedExceptionAction() {                    public Object run() {                         StringBuffer allowedFiles = new StringBuffer(str.length());                        String [] uriArray = str.split("(\\s)+");                         for (String fileName : uriArray)                        {                            File file = new File(fileName);                            if (file.exists() &&                                !(isFileInWebstartedCache(file) ||                                isForbiddenToRead(file, userProtectionDomain)))                            {                                 if (0 != allowedFiles.length())                                {                                    allowedFiles.append("\\r\\n");                                }                                 allowedFiles.append(fileName);                            }                        }                         return allowedFiles.toString();                    }                });        } catch (PrivilegedActionException pae) {            throw new IOException(pae.getMessage(), pae);        }         return ret_val;    }     private static ProtectionDomain getUserProtectionDomain(Transferable contents) {        return contents.getClass().getProtectionDomain();    }     private boolean isForbiddenToRead (File file, ProtectionDomain protectionDomain)    {        if (null == protectionDomain) {            return false;        }        try {            FilePermission filePermission =                    new FilePermission(file.getCanonicalPath(), "read, delete");            if (protectionDomain.implies(filePermission)) {                return false;            }        } catch (IOException e) {}         return true;    }     private ArrayList<String> castToFiles(final List files,                                          final ProtectionDomain userProtectionDomain) throws IOException    {        final ArrayList<String> fileList = new ArrayList<String>();        try {            AccessController.doPrivileged(new PrivilegedExceptionAction() {                public Object run() throws IOException {                    for (Object fileObject : files)                    {                        File file = castToFile(fileObject);                        if (file != null &&                            (null == System.getSecurityManager() ||                            !(isFileInWebstartedCache(file) ||                            isForbiddenToRead(file, userProtectionDomain))))                        {                            fileList.add(file.getCanonicalPath());                        }                    }                    return null;                }            });

Lines 1001–1500 of 3090. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t