All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.webkit.network.DirectoryURLConnection Maven / Gradle / Ivy

There is a newer version: 24-ea+15
Show newest version
/*
 * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.webkit.network;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PushbackInputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.sun.webkit.network.URLs.newURL;

/*
 * Interposing class that will transform the raw stream from a FtpURLConnection
 * or FileURLConnection into an HTML page listing the content of the directory
 */
final class DirectoryURLConnection extends URLConnection {
    // Patterns used to parse the output from a FTP directory list.
    private static final String[] patStrings = {
        // drwxr-xr-x  1 user01        ftp   512 Jan 29 23:32 prog
        // drwxr-xr-x  1 user01        ftp   512 Jan 29 1997 prog
        "([\\-ld](?:[r\\-][w\\-][x\\-]){3})\\s*\\d+ (\\w+)\\s*(\\w+)\\s*(\\d+)\\s*([A-Z][a-z][a-z]\\s*\\d+)\\s*((?:\\d\\d:\\d\\d)|(?:\\d{4}))\\s*(\\p{Print}*)",
        // 04/28/2006  09:12a               3,563 genBuffer.sh
        "(\\d{2}/\\d{2}/\\d{4})\\s*(\\d{2}:\\d{2}[ap])\\s*((?:[0-9,]+)|(?:))\\s*(\\p{Graph}*)",
        // 01-29-97    11:32PM  prog
        "(\\d{2}-\\d{2}-\\d{2})\\s*(\\d{2}:\\d{2}[AP]M)\\s*((?:[0-9,]+)|(?:))\\s*(\\p{Graph}*)"
    };
    private static final int[][] patternGroups = {
        // file, size, date1, date2, permissions
        {7, 4, 5, 6, 1},
        {4, 3, 1, 2, 0},
        {4, 3, 1, 2, 0}
    };
    private static final Pattern[] patterns;
    private static final Pattern linkp = Pattern.compile("(\\p{Print}+) \\-\\> (\\p{Print}+)$");
    // Style sheet to make the TABLE better looking
    private static final String styleSheet =
            "";

    static {
        patterns = new Pattern[patStrings.length];
        for (int i = 0; i < patStrings.length; i++) {
            patterns[i] = Pattern.compile(patStrings[i]);
        }
    }
    private final URLConnection inner;
    private final boolean sure;
    private String dirUrl = null;
    // Set toHTML to false when it is not a directory and we don't want  to
    // change the stream.
    private boolean toHTML = true;
    private final boolean ftp;
    private InputStream ins = null;

    /*
     * We need an interposing InputStream as well. We subclass PushbackInputStream
     * so that we can do some safe read-ahead if we have to guess whether the
     * URL points to a directory or not (the read-ahead is for FTP only).
     */
    private final class DirectoryInputStream extends PushbackInputStream {
        private final byte[] buffer;
        private boolean endOfStream = false;
        private ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
        private PrintStream out = new PrintStream(bytesOut);
        private ByteArrayInputStream bytesIn = null;
        private final StringBuffer tmpString = new StringBuffer();
        private int lineCount = 0;

        private DirectoryInputStream(InputStream ins, boolean guess) {
            super(ins, 512);
            buffer = new byte[512];
            /*
             * If 'guess' is true, it means it's an FTP link and we're not sure
             * this is a directory
             */
            if (guess) {
                StringBuffer line = new StringBuffer();
                int l = 0;
                int c;
                try {
                    l = super.read(buffer, 0, buffer.length);
                } catch (IOException e) {
                }
                if (l <= 0) {
                    toHTML = false;
                } else {
                    for (int i = 0; i < l; i++) {
                        line.append((char) buffer[i]);
                    }
                    String line2 = line.toString();
                    toHTML = false;
                    for (Pattern p : patterns) {
                        Matcher m = p.matcher(line2);
                        if (m.find()) {
                            // One of the patterns matched
                            // Means it's a directory listing
                            toHTML = true;
                            break;
                        }
                    }
                    try {
                        super.unread(buffer, 0, l);
                    } catch (IOException ioe) {
                    // Shouldn't happen
                    }
                }
            }
            if (toHTML) {
                /*
                 * We're good to go. Let's generate the header for the table
                 */
                String parent = null;
                String path;
                URL prevUrl = null;
                if (!dirUrl.endsWith("/")) {
                    dirUrl = dirUrl + "/";
                }
                try {
                    prevUrl = newURL(dirUrl);
                } catch (Exception e) {
                // can't happen
                }
                path = prevUrl.getPath();
                if (path != null && !path.isEmpty()) {
                    int index = path.lastIndexOf("/", path.length() - 2);
                    if (index >= 0) {
                        int removed = path.length() - index - 1;
                        index = dirUrl.indexOf(path);
                        parent = dirUrl.substring(0, index + path.length() - removed) + dirUrl.substring(index + path.length());
                    }
                }
                out.print("index of ");
                out.print(dirUrl);
                out.print("");
                out.print(styleSheet);
                out.print("

Index of "); out.print(dirUrl); out.print("


"); out.print(""); out.print(""); if (parent != null) { lineCount++; out.print(""); } out.close(); bytesIn = new ByteArrayInputStream(bytesOut.toByteArray()); out = null; bytesOut = null; } } private void parseFile(String s) { tmpString.append(s); int i; while ((i = tmpString.indexOf("\n")) >= 0) { String sb = tmpString.substring(0, i); tmpString.delete(0, i + 1); String filename = sb; String size = null; String date = null; boolean dir = false; boolean noaccess = false; URL furl = null; if (filename != null) { lineCount++; try { furl = newURL(dirUrl + URLEncoder.encode(filename, "UTF-8")); URLConnection fconn = furl.openConnection(); fconn.connect(); date = fconn.getHeaderField("last-modified"); size = fconn.getHeaderField("content-length"); if (size == null) { dir = true; } fconn.getInputStream().close(); } catch (IOException e) { // No access right noaccess = true; } if (bytesOut == null) { bytesOut = new ByteArrayOutputStream(); out = new PrintStream(bytesOut); } out.print(""); } else { out.print(""); } out.print(""); } } if (bytesOut != null) { out.close(); bytesIn = new ByteArrayInputStream(bytesOut.toByteArray()); out = null; bytesOut = null; } } private void parseFTP(String s) { tmpString.append(s); int i; while ((i = tmpString.indexOf("\n")) >= 0) { String sb = tmpString.substring(0, i); tmpString.delete(0, i + 1); String filename = null; String link = null; String size = null; String date = null; boolean dir = false; Matcher m = null; for (int j = 0; j < patterns.length; j++) { m = patterns[j].matcher(sb); if (m.find()) { filename = m.group(patternGroups[j][0]); size = m.group(patternGroups[j][1]); date = m.group(patternGroups[j][2]); if (patternGroups[j][3] > 0) { date += (" " + m.group(patternGroups[j][3])); } if (patternGroups[j][4] > 0) { String perms = m.group(patternGroups[j][4]); dir = perms.startsWith("d"); } if ("".equals(size)) { dir = true; size = null; } } } if (filename != null) { m = linkp.matcher(filename); if (m.find()) { // There is a symbolic link filename = m.group(1); link = m.group(2); } if (bytesOut == null) { bytesOut = new ByteArrayOutputStream(); out = new PrintStream(bytesOut); } lineCount++; out.print(""); } else if (dir) { out.print(""); } else { out.print(""); } out.print(""); } } if (bytesOut != null) { out.close(); bytesIn = new ByteArrayInputStream(bytesOut.toByteArray()); out = null; bytesOut = null; } } private void endOfList() { // Let's make sure we don't miss the last line because a new-line // is missing if (ftp) { parseFTP("\n"); } else { parseFile("\n"); } if (bytesOut == null) { bytesOut = new ByteArrayOutputStream(); out = new PrintStream(bytesOut); } out.print("
FileSizeLast Modified
Up to parent directory
"); if (noaccess) { out.print(filename); } else { out.print(""); out.print(filename); out.print(""); } if (dir) { out.print("<Directory>" + (size == null ? " " : size) + "" + (date == null ? " " : date) + "
"); out.print(filename); out.print(""); if (link != null) { out.print(" → " + link + "<Link><Directory>" + size + "" + date + "


"); out.close(); bytesIn = new ByteArrayInputStream(bytesOut.toByteArray()); out = null; bytesOut = null; } @Override public int read(byte[] buf) throws IOException { return read(buf, 0, buf.length); } @Override public int read(byte[] buf, int offset, int length) throws IOException { int l = 0; if (!toHTML) { return super.read(buf, offset, length); } if (bytesIn != null) { l = bytesIn.read(buf, offset, length); if (l == -1) { bytesIn.close(); bytesIn = null; if (endOfStream) { return -1; } } else { return l; } } if (!endOfStream) { l = super.read(buffer, 0, buffer.length); if (l == -1) { endOfStream = true; endOfList(); return read(buf, offset, length); } else { if (ftp) { parseFTP(new String(buffer, 0, l)); } else { parseFile(new String(buffer, 0, l)); } if (bytesIn != null) { return read(buf, offset, length); } } } return 0; } } /* * Constructor to use for an FTP (or FTPS) URLConnection. * Set 'notsure' to true if it is necessary to look ahead to make sure * it is, indeed, a directory. */ DirectoryURLConnection(URLConnection con, boolean notsure) { super(con.getURL()); dirUrl = con.getURL().toExternalForm(); inner = con; sure = !notsure; ftp = true; } /* * Constructor to use for a File URLConnection. */ DirectoryURLConnection(URLConnection con) { super(con.getURL()); dirUrl = con.getURL().toExternalForm(); ftp = false; sure = true; inner = con; } @Override public void connect() throws IOException { inner.connect(); } @Override public InputStream getInputStream() throws IOException { if (ins == null) { if (ftp) { ins = new DirectoryInputStream(inner.getInputStream(), !sure); } else { ins = new DirectoryInputStream(inner.getInputStream(), false); } } return ins; } @Override public String getContentType() { try { if (!sure) { getInputStream(); } } catch (IOException e) { } if (toHTML) { return "text/html"; } return inner.getContentType(); } @Override public String getContentEncoding() { return inner.getContentEncoding(); } @Override public int getContentLength() { return inner.getContentLength(); } @Override public Map> getHeaderFields() { return inner.getHeaderFields(); } @Override public String getHeaderField(String key) { return inner.getHeaderField(key); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy