Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
rt/transports/http/src/main/java/org/apache/cxf/transport/https/AllowAllHostnameVerifier.java
### 代码内容：
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.cxf.transport.https;

import java.security.cert.Certificate;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;

/**
 * Allow all hostnames. This is only suitable for use in testing, and NOT in production!
 */
class AllowAllHostnameVerifier implements javax.net.ssl.HostnameVerifier {

    @Override
    public boolean verify(String host, SSLSession session) {
        try {
            Certificate[] certs = session.getPeerCertificates();
            return certs != null && certs[0] instanceof X509Certificate;
        } catch (SSLException e) {
            return false;
        }
    }
}
## 内容2
### 文件路径：
rt/transports/http/src/main/java/org/apache/cxf/transport/https/HttpsURLConnectionFactory.java
### 代码内容：
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.cxf.transport.https;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.logging.Handler;
import java.util.logging.Logger;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;

import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.ReflectionInvokationHandler;
import org.apache.cxf.common.util.ReflectionUtil;
import org.apache.cxf.configuration.jsse.SSLUtils;
import org.apache.cxf.configuration.jsse.TLSClientParameters;

/**
 * This HttpsURLConnectionFactory implements the HttpURLConnectionFactory
 * for using the given SSL Policy to configure TLS connections for "https:"
 * URLs.
 */
public class HttpsURLConnectionFactory {

    /**
     * This constant holds the URL Protocol Identifier for HTTPS
     */
    public static final String HTTPS_URL_PROTOCOL_ID = "https";

    private static final Logger LOG =
        LogUtils.getL7dLogger(HttpsURLConnectionFactory.class);

    private static boolean weblogicWarned;

    /**
     * Cache the last SSLContext to avoid recreation
     */
    SSLSocketFactory socketFactory;
    int lastTlsHash;

    /**
     * This constructor initialized the factory with the configured TLS
     * Client Parameters for the HTTPConduit for which this factory is used.
     */
    public HttpsURLConnectionFactory() {
    }

    /**
     * Create a HttpURLConnection, proxified if necessary.
     *
     *
     * @param proxy This parameter is non-null if connection should be proxied.
     * @param url   The target URL.
     *
     * @return The HttpURLConnection for the given URL.
     * @throws IOException
     */
    public HttpURLConnection createConnection(TLSClientParameters tlsClientParameters,
            Proxy proxy, URL url) throws IOException {

        HttpURLConnection connection =
            (HttpURLConnection) (proxy != null
                                   ? url.openConnection(proxy)
                                   : url.openConnection());
        if (HTTPS_URL_PROTOCOL_ID.equals(url.getProtocol())) {

            if (tlsClientParameters == null) {
                tlsClientParameters = new TLSClientParameters();
            }

            try {
                decorateWithTLS(tlsClientParameters, connection);
            } catch (Throwable ex) {
                if (ex instanceof IOException) {
                    throw (IOException) ex;
                }
                IOException ioException = new IOException("Error while initializing secure socket", ex);
                throw ioException;
            }
        }

        return connection;
    }

    /**
     * This method assigns the various TLS parameters on the HttpsURLConnection
     * from the TLS Client Parameters. Connection parameter is of supertype HttpURLConnection,
     * which allows internal cast to potentially divergent subtype (https) implementations.
     */
    protected synchronized void decorateWithTLS(TLSClientParameters tlsClientParameters,
            HttpURLConnection connection) throws GeneralSecurityException {

        int hash = tlsClientParameters.hashCode();
        if (hash != lastTlsHash) {
            lastTlsHash = hash;
            socketFactory = null;
        }

        // always reload socketFactory from HttpsURLConnection.defaultSSLSocketFactory and
        // tlsClientParameters.sslSocketFactory to allow runtime configuration change
        if (tlsClientParameters.isUseHttpsURLConnectionDefaultSslSocketFactory()) {
            socketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();

        } else if (tlsClientParameters.getSSLSocketFactory() != null) {
            // see if an SSLSocketFactory was set. This allows easy interop
            // with not-yet-commons-ssl.jar, or even just people who like doing their
            // own JSSE.
            socketFactory = tlsClientParameters.getSSLSocketFactory();

        } else if (socketFactory == null) {
            // ssl socket factory not yet instantiated, create a new one with tlsClientParameters's Trust
            // Managers, Key Managers, etc

            SSLContext ctx =
                org.apache.cxf.transport.https.SSLUtils.getSSLContext(tlsClientParameters);

            String[] cipherSuites =
                SSLUtils.getCiphersuitesToInclude(tlsClientParameters.getCipherSuites(),
                                                  tlsClientParameters.getCipherSuitesFilter(),
                                                  ctx.getSocketFactory().getDefaultCipherSuites(),
                                                  SSLUtils.getSupportedCipherSuites(ctx),
                                                  LOG);
            // The SSLSocketFactoryWrapper enables certain cipher suites
            // from the policy.
            String protocol = tlsClientParameters.getSecureSocketProtocol() != null ? tlsClientParameters
                .getSecureSocketProtocol() : "TLS";
            socketFactory = new SSLSocketFactoryWrapper(ctx.getSocketFactory(), cipherSuites,
                                                        protocol);
            //recalc the hashcode since some of the above MAY have changed the tlsClientParameters
            lastTlsHash = tlsClientParameters.hashCode();
        } else {
           // ssl socket factory already initialized, reuse it to benefit of keep alive
        }

        HostnameVerifier verifier = org.apache.cxf.transport.https.SSLUtils
            .getHostnameVerifier(tlsClientParameters);

        if (connection instanceof HttpsURLConnection) {
            // handle the expected case (javax.net.ssl)
            HttpsURLConnection conn = (HttpsURLConnection) connection;
            conn.setHostnameVerifier(verifier);
            conn.setSSLSocketFactory(socketFactory);
        } else {
            // handle the deprecated sun case and other possible hidden API's
            // that are similar to the Sun cases
            try {
                Method method = connection.getClass().getMethod("getHostnameVerifier");

                InvocationHandler handler = new ReflectionInvokationHandler(verifier) {
                    public Object invoke(Object proxy,
                                         Method method,
                                         Object[] args) throws Throwable {
                        try {
                            return super.invoke(proxy, method, args);
                        } catch (Exception ex) {
                            return true;
                        }
                    }
                };
                Object proxy = java.lang.reflect.Proxy.newProxyInstance(this.getClass().getClassLoader(),
                                                                        new Class[] {method.getReturnType()},
                                                                        handler);

                method = connection.getClass().getMethod("setHostnameVerifier", method.getReturnType());
                method.invoke(connection, proxy);
            } catch (Exception ex) {
                //Ignore this one
            }
            try {
                Method getSSLSocketFactory = connection.getClass().getMethod("getSSLSocketFactory");
                Method setSSLSocketFactory = connection.getClass()
                    .getMethod("setSSLSocketFactory", getSSLSocketFactory.getReturnType());
                if (getSSLSocketFactory.getReturnType().isInstance(socketFactory)) {
                    setSSLSocketFactory.invoke(connection, socketFactory);
                } else {
                    //need to see if we can create one - mostly the weblogic case.   The
                    //weblogic SSLSocketFactory has a protected constructor that can take
                    //a JSSE SSLSocketFactory so we'll try and use that
                    Constructor<?> c = getSSLSocketFactory.getReturnType()
                        .getDeclaredConstructor(SSLSocketFactory.class);
                    ReflectionUtil.setAccessible(c);
                    setSSLSocketFactory.invoke(connection, c.newInstance(socketFactory));
                }
            } catch (Exception ex) {
                if (connection.getClass().getName().contains("weblogic")) {
                    if (!weblogicWarned) {
                        weblogicWarned = true;
                        LOG.warning("Could not configure SSLSocketFactory on Weblogic.  "
                                    + " Use the Weblogic control panel to configure the SSL settings.");
                    }
                    return;
                }
                //if we cannot set the SSLSocketFactory, we're in serious trouble.
                throw new IllegalArgumentException("Error decorating connection class "
                        + connection.getClass().getName(), ex);
            }
        }
    }

    /*
     *  For development and testing only
     */
    protected void addLogHandler(Handler handler) {
        LOG.addHandler(handler);
    }

}

## 内容3
### 文件路径：
rt/transports/http/src/main/java/org/apache/cxf/transport/https/httpclient/DefaultHostnameVerifier.java
### 代码内容：
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */

package org.apache.cxf.transport.https.httpclient;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.cert.Certificate;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.naming.InvalidNameException;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.security.auth.x500.X500Principal;

import org.apache.cxf.common.logging.LogUtils;

/**
 * Default {@link javax.net.ssl.HostnameVerifier} implementation.
 * Copied from httpclient.
 */
public final class DefaultHostnameVerifier implements HostnameVerifier {

    enum TYPE { IPv4, IPv6, DNS };

    static final int DNS_NAME_TYPE = 2;
    static final int IP_ADDRESS_TYPE = 7;

    private static final Logger LOG = LogUtils.getL7dLogger(DefaultHostnameVerifier.class);

    private final PublicSuffixMatcher publicSuffixMatcher;

    public DefaultHostnameVerifier(final PublicSuffixMatcher publicSuffixMatcher) {
        this.publicSuffixMatcher = publicSuffixMatcher;
    }

    public DefaultHostnameVerifier() {
        this(null);
    }

    @Override
    public boolean verify(final String host, final SSLSession session) {
        try {
            final Certificate[] certs = session.getPeerCertificates();
            final X509Certificate x509 = (X509Certificate) certs[0];
            verify(host, x509);
            return true;
        } catch (final SSLException ex) {
            if (LOG.isLoggable(Level.FINE)) {
                LOG.log(Level.FINE, ex.getMessage(), ex);
            }
            return false;
        }
    }

    public void verify(
            final String host, final X509Certificate cert) throws SSLException {
        TYPE hostFormat = TYPE.DNS;
        if (InetAddressUtils.isIPv4Address(host)) {
            hostFormat = TYPE.IPv4;
        } else {
            String s = host;
            if (s.startsWith("[") && s.endsWith("]")) {
                s = host.substring(1, host.length() - 1);
            }
            if (InetAddressUtils.isIPv6Address(s)) {
                hostFormat = TYPE.IPv6;
            }
        }
        final int subjectType = hostFormat == TYPE.IPv4 || hostFormat == TYPE.IPv6 ? IP_ADDRESS_TYPE : DNS_NAME_TYPE;
        final List<String> subjectAlts = extractSubjectAlts(cert, subjectType);
        if (subjectAlts != null && !subjectAlts.isEmpty()) {
            switch (hostFormat) {
            case IPv4:
                matchIPAddress(host, subjectAlts);
                break;
            case IPv6:
                matchIPv6Address(host, subjectAlts);
                break;
            default:
                matchDNSName(host, subjectAlts, this.publicSuffixMatcher);
            }
        } else {
            // CN matching has been deprecated by rfc2818 and can be used
            // as fallback only when no subjectAlts are available
            final X500Principal subjectPrincipal = cert.getSubjectX500Principal();
            final String cn = extractCN(subjectPrincipal.getName(X500Principal.RFC2253));
            if (cn == null) {
                throw new SSLException("Certificate subject for <" + host + "> doesn't contain "
                    + "a common name and does not have alternative names");
            }
            matchCN(host, cn, this.publicSuffixMatcher);
        }
    }

    static void matchIPAddress(final String host, final List<String> subjectAlts) throws SSLException {
        for (int i = 0; i < subjectAlts.size(); i++) {
            final String subjectAlt = subjectAlts.get(i);
            if (host.equals(subjectAlt)) {
                return;
            }
        }
        throw new SSLException("Certificate for <" + host + "> doesn't match any "
            + "of the subject alternative names: " + subjectAlts);
    }

    static void matchIPv6Address(final String host, final List<String> subjectAlts) throws SSLException {
        final String normalisedHost = normaliseAddress(host);
        for (int i = 0; i < subjectAlts.size(); i++) {
            final String subjectAlt = subjectAlts.get(i);
            final String normalizedSubjectAlt = normaliseAddress(subjectAlt);
            if (normalisedHost.equals(normalizedSubjectAlt)) {
                return;
            }
        }
        throw new SSLException("Certificate for <" + host + "> doesn't match any "
            + "of the subject alternative names: " + subjectAlts);
    }

    static void matchDNSName(final String host, final List<String> subjectAlts,
                             final PublicSuffixMatcher publicSuffixMatcher) throws SSLException {
        final String normalizedHost = host.toLowerCase(Locale.ROOT);
        for (int i = 0; i < subjectAlts.size(); i++) {
            final String subjectAlt = subjectAlts.get(i);
            final String normalizedSubjectAlt = subjectAlt.toLowerCase(Locale.ROOT);
            if (matchIdentityStrict(normalizedHost, normalizedSubjectAlt, publicSuffixMatcher)) {
                return;
            }
        }
        throw new SSLException("Certificate for <" + host + "> doesn't match any "
            + "of the subject alternative names: " + subjectAlts);
    }

    static void matchCN(final String host, final String cn,
                 final PublicSuffixMatcher publicSuffixMatcher) throws SSLException {
        if (!matchIdentityStrict(host, cn, publicSuffixMatcher)) {
            throw new SSLException("Certificate for <" + host + "> doesn't match "
                + "common name of the certificate subject: " + cn);
        }
    }

    static boolean matchDomainRoot(final String host, final String domainRoot) {
        if (domainRoot == null) {
            return false;
        }
        return host.endsWith(domainRoot) && (host.length() == domainRoot.length()
                || host.charAt(host.length() - domainRoot.length() - 1) == '.');
    }

    private static boolean matchIdentity(final String host, final String identity,
                                         final PublicSuffixMatcher publicSuffixMatcher,
                                         final boolean strict) {
        if (publicSuffixMatcher != null && host.contains(".")
            && !matchDomainRoot(host, publicSuffixMatcher.getDomainRoot(identity, DomainType.ICANN))) {
            return false;
        }

        // RFC 2818, 3.1. Server Identity
        // "...Names may contain the wildcard
        // character * which is considered to match any single domain name
        // component or component fragment..."
        // Based on this statement presuming only singular wildcard is legal
        final int asteriskIdx = identity.indexOf('*');
        if (asteriskIdx != -1) {
            final String prefix = identity.substring(0, asteriskIdx);
            final String suffix = identity.substring(asteriskIdx + 1);
            if (!prefix.isEmpty() && !host.startsWith(prefix)) {
                return false;
            }
            if (!suffix.isEmpty() && !host.endsWith(suffix)) {
                return false;
            }
            // Additional sanity checks on content selected by wildcard can be done here
            if (strict) {
                final String remainder = host.substring(
                        prefix.length(), host.length() - suffix.length());
                if (remainder.contains(".")) {
                    return false;
                }
            }
            return true;
        }
        return host.equalsIgnoreCase(identity);
    }

    static boolean matchIdentity(final String host, final String identity,
                                 final PublicSuffixMatcher publicSuffixMatcher) {
        return matchIdentity(host, identity, publicSuffixMatcher, false);
    }

    static boolean matchIdentity(final String host, final String identity) {
        return matchIdentity(host, identity, null, false);
    }

    static boolean matchIdentityStrict(final String host, final String identity,
                                       final PublicSuffixMatcher publicSuffixMatcher) {
        return matchIdentity(host, identity, publicSuffixMatcher, true);
    }

    static boolean matchIdentityStrict(final String host, final String identity) {
        return matchIdentity(host, identity, null, true);
    }

    static String extractCN(final String subjectPrincipal) throws SSLException {
        if (subjectPrincipal == null) {
            return null;
        }
        try {
            final LdapName subjectDN = new LdapName(subjectPrincipal);
            final List<Rdn> rdns = subjectDN.getRdns();
            for (int i = rdns.size() - 1; i >= 0; i--) {
                final Rdn rds = rdns.get(i);
                final Attributes attributes = rds.toAttributes();
                final Attribute cn = attributes.get("cn");
                if (cn != null) {
                    try {
                        final Object value = cn.get();
                        if (value != null) {
                            return value.toString();
                        }
                    } catch (NoSuchElementException ignore) {
                        //
                    } catch (NamingException ignore) {
                        //
                    }
                }
            }
            return null;
        } catch (InvalidNameException e) {
            throw new SSLException(subjectPrincipal + " is not a valid X500 distinguished name");
        }
    }

    static List<String> extractSubjectAlts(final X509Certificate cert, final int subjectType) {
        Collection<List<?>> c = null;
        try {
            c = cert.getSubjectAlternativeNames();
        } catch (final CertificateParsingException ignore) {
            //
        }
        List<String> subjectAltList = null;
        if (c != null) {
            for (final List<?> aC : c) {
                final List<?> list = aC;
                final int type = ((Integer) list.get(0)).intValue();
                if (type == subjectType) {
                    final String s = (String) list.get(1);
                    if (subjectAltList == null) {
                        subjectAltList = new ArrayList<>();
                    }
                    subjectAltList.add(s);
                }
            }
        }
        return subjectAltList;
    }

    /*
     * Normalize IPv6 or DNS name.
     */
    static String normaliseAddress(final String hostname) {
        if (hostname == null) {
            return hostname;
        }
        try {
            final InetAddress inetAddress = InetAddress.getByName(hostname);
            return inetAddress.getHostAddress();
        } catch (final UnknownHostException unexpected) { // Should not happen, because we check for IPv6 address above
            return hostname;
        }
    }
}

Output:
【漏洞类型】主机名验证绕过漏洞

【严重性】High

【漏洞摘要】主机名验证绕过漏洞会导致攻击者通过中间人攻击（Man-in-the-Middle, MITM）来窃取或篡改数据。在原始代码中，`AllowAllHostnameVerifier`类总是返回`true`，这意味着无论主机名是什么，都会认为是有效的。这种行为在生产环境中是极其危险的，因为它允许任何证书与任何主机名匹配。此外，在`HttpsURLConnectionFactory`类中，当使用非标准的`HttpsURLConnection`实现时，即使主机名验证失败，也可能失败地捕获异常并返回`true`，从而绕过了主机名验证。

【关键代码模式】
- `AllowAllHostnameVerifier`类中的`verify`方法。
- `HttpsURLConnectionFactory`类中的`decorateWithTLS`方法，特别是在处理非标准的`HttpsURLConnection`实现时。
- `InetAddressUtils.isIPv4Address`和`InetAddressUtils.isIPv6Address`方法的使用，尤其是在`DefaultHostnameVerifier`类中。

【修复方法说明】修复方法通过在`AllowAllHostnameVerifier`类中添加对主机名的严格验证，并在`HttpsURLConnectionFactory`类中改进异常处理，确保在主机名验证失败时返回`false`。这遵循了最佳实践，即始终对主机名进行严格的验证，以防止MITM攻击。


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
History.md
### 代码内容：
HEAD
===================

 * basicAuth: use basic-auth-connect
 * cookieParser: use cookie-parser
 * compress: use compression
 * csrf: use csurf
 * dep: cookie-signature@1.0.3
 * errorHandler: use errorhandler
 * favicon: use static-favicon
 * logger: use morgan
 * methodOverride: use method-override
 * responseTime: use response-time
 * session: use express-session
 * timeout: use connect-timeout
 * vhost: use vhost

2.13.1 / 2014-03-05
===================

 * cookieSession: compare full value rather than crc32
 * deps: raw-body@1.1.3

2.13.0 / 2014-02-14
===================

 * fix typo in memory store warning #974 @rvagg
 * compress: use compressible
 * directory: add template option #990 @gottaloveit @Earl-Brown
 * csrf: prevent deprecated warning with old sessions

2.12.0 / 2013-12-10
===================

 * bump qs
 * directory: sort folders before files
 * directory: add folder icons
 * directory: de-duplicate icons, details/mobile views #968 @simov
 * errorHandler: end default 404 handler with a newline #972 @rlidwka
 * session: remove long cookie expire check #870 @undoZen

2.11.2 / 2013-12-01
===================

 * bump raw-body

2.11.1 / 2013-11-27
===================

 * bump raw-body
 * errorHandler: use `res.setHeader()` instead of `res.writeHead()` #949 @lo1tuma

2.11.0 / 2013-10-29
===================

 * update bytes
 * update uid2
 * update negotiator
 * sessions: add rolling session option #944 @ilmeo
 * sessions: property set cookies when given FQDN
 * cookieSessions: properly set cookies when given FQDN #948 @bmancini55
 * proto: fix FQDN mounting when multiple handlers #945 @bmancini55

2.10.1 / 2013-10-23
===================

 * fixed; fixed a bug with static middleware at root and trailing slashes #942 (@dougwilson)

2.10.0 / 2013-10-22
===================

 * fixed: set headers written by writeHead before emitting 'header'
 * fixed: mounted path should ignore querystrings on FQDNs #940 (@dougwilson)
 * fixed: parsing protocol-relative URLs with @ as pathnames #938 (@dougwilson)
 * fixed: fix static directory redirect for mount's root #937 (@dougwilson)
 * fixed: setting set-cookie header when mixing arrays and strings #893 (@anuj123)
 * bodyParser: optional verify function for urlencoded and json parsers for signing request bodies
 * compress: compress checks content-length to check threshold
 * compress: expose `res.flush()` for flushing responses
 * cookieParser: pass options into node-cookie #803 (@cauldrath)
 * errorHandler: replace `\n`s with `<br/>`s in error handler

2.9.2 / 2013-10-18
==================

 * warn about multiparty and limit middleware deprecation for v3
 * fix fully qualified domain name mounting. #920 (@dougwilson)
 * directory: Fix potential security issue with serving files outside the root. #929 (@dougwilson)
 * logger: store IP at beginning in case socket prematurely closes #930 (@dougwilson)

2.9.1 / 2013-10-15
==================

 * update multiparty
 * compress: Set vary header only if Content-Type passes filter #904
 * directory: Fix directory middleware URI escaping #917 (@dougwilson)
 * directory: Fix directory seperators for Windows #914 (@dougwilson)
 * directory: Keep query string intact during directory redirect #913 (@dougwilson)
 * directory: Fix paths in links #730 (@JacksonTian)
 * errorHandler: Don't escape text/plain as HTML #875 (@johan)
 * logger: Write '0' instead of '-' when response time is zero #910 (@dougwilson)
 * logger: Log even when connections are aborted #760 (@dylanahsmith)
 * methodOverride: Check req.body is an object #907 (@kbjr)
 * multipart: Add .type back to file parts for backwards compatibility #912 (@dougwilson)
 * multipart: Allow passing options to the Multiparty constructor #902 (@niftylettuce)

2.9.0 / 2013-09-07
==================

 * multipart: add docs regarding tmpfiles
 * multipart: add .name back to file parts
 * multipart: use multiparty instead of formidable

2.8.8 / 2013-09-02
==================

 * csrf: change to math.random() salt and remove csrfToken() callback

2.8.7 / 2013-08-28
==================

 * csrf: prevent salt generation on every request, and add async req.csrfToken(fn)

2.8.6 / 2013-08-28
==================

 * csrf: refactor to use HMAC tokens (BREACH attack)
 * compress: add compression of SVG and common font files by default.

2.8.5 / 2013-08-11
==================

 * add: compress Dart source files by default
 * update fresh

2.8.4 / 2013-07-08
==================

 * update send

2.8.3 / 2013-07-04
==================

 * add a name back to static middleware ("staticMiddleware")
 * fix .hasBody() utility to require transfer-encoding or content-length

2.8.2 / 2013-07-03
==================

 * update send
 * update cookie dep.
 * add better debug() for middleware
 * add whitelisting of supported methods to methodOverride()

2.8.1 / 2013-06-27
==================

 * fix: escape req.method in 404 response

2.8.0 / 2013-06-26
==================

 * add `threshold` option to `compress()` to prevent compression of small responses
 * add support for vendor JSON mime types in json()
 * add X-Forwarded-Proto initial https proxy support
 * change static redirect to 303
 * change octal escape sequences for strict mode
 * change: replace utils.uid() with uid2 lib
 * remove other "static" function name. Fixes #794
 * fix: hasBody() should return false if Content-Length: 0

2.7.11 / 2013-06-02
==================

 * update send

2.7.10 / 2013-05-21
==================

 * update qs
 * update formidable
 * fix: write/end to noop() when request aborted

2.7.9 / 2013-05-07
==================

  * update qs
  * drop support for node < v0.8

2.7.8 / 2013-05-03
==================

  * update qs

2.7.7 / 2013-04-29
==================

  * update qs dependency
  * remove "static" function name. Closes #794
  * update node-formidable
  * update buffer-crc32

2.7.6 / 2013-04-15
==================

  * revert cookie signature which was creating session race conditions

2.7.5 / 2013-04-12
==================

  * update cookie-signature
  * limit: do not consume request in node 0.10.x

2.7.4 / 2013-04-01
==================

  * session: add long expires check and prevent excess set-cookie
  * session: add console.error() of session#save() errors

2.7.3 / 2013-02-19
==================

  * add name to compress middleware
  * add appending Accept-Encoding to Vary when set but missing
  * add tests for csrf middleware
  * add 'next' support for connect() server handler
  * change utils.uid() to return url-safe chars. Closes #753
  * fix treating '.' as a regexp in vhost()
  * fix duplicate bytes dep in package.json. Closes #743
  * fix #733 - parse x-forwarded-proto in a more generally compatibly way
  * revert "add support for `next(status[, msg])`"; makes composition hard

2.7.2 / 2013-01-04
==================

  * add support for `next(status[, msg])` back
  * add utf-8 meta tag to support foreign characters in filenames/directories
  * change `timeout()` 408 to 503
  * replace 'node-crc' with 'buffer-crc32', fixes licensing
  * fix directory.html IE support

2.7.1 / 2012-12-05
==================

  * add directory() tests
  * add support for bodyParser to ignore Content-Type if no body is present (jquery primarily does this poorely)
  * fix errorHandler signature

2.7.0 / 2012-11-13
==================

  * add support for leading JSON whitespace
  * add logging of `req.ip` when present
  * add basicAuth support for `:`-delimited string
  * update cookie module. Closes #688

2.6.2 / 2012-11-01
==================

  * add `debug()` for disconnected session store
  * fix session regeneration bug. Closes #681

2.6.1 / 2012-10-25
==================

  * add passing of `connect.timeout()` errors to `next()`
  * replace signature utils with cookie-signature module

2.6.0 / 2012-10-09
==================

  * add `defer` option to `multipart()` [Blake Miner]
  * fix mount path case sensitivity. Closes #663
  * fix default of ascii encoding from `logger()`, now utf8. Closes #293

2.5.0 / 2012-09-27
==================

  * add `err.status = 400` to multipart() errors
  * add double-encoding protection to `compress()`. Closes #659
  * add graceful handling cookie parsing errors [shtylman]
  * fix typo X-Response-time to X-Response-Time

2.4.6 / 2012-09-18
==================

  * update qs

2.4.5 / 2012-09-03
==================

  * add session store "connect" / "disconnect" support [louischatriot]
  * fix `:url` log token

2.4.4 / 2012-08-21
==================

  * fix `static()` pause regression from "send" integration

2.4.3 / 2012-08-07
==================

  * fix `.write()` encoding for zlib inconstancy. Closes #561

2.4.2 / 2012-07-25
==================

  * remove limit default from `urlencoded()`
  * remove limit default from `json()`
  * remove limit default from `multipart()`
  * fix `cookieSession()` clear cookie path / domain bug. Closes #636

2.4.1 / 2012-07-24
==================

  * fix `options` mutation in `static()`

2.4.0 / 2012-07-23
==================

  * add `connect.timeout()`
  * add __GET__ / __HEAD__ check to `directory()`. Closes #634
  * add "pause" util dep
  * update send dep for normalization bug

2.3.9 / 2012-07-16
==================

  * add more descriptive invalid json error message
  * update send dep for root normalization regression
  * fix staticCache fresh dep

2.3.8 / 2012-07-12
==================

  * fix `connect.static()` 404 regression, pass `next()`. Closes #629

2.3.7 / 2012-07-05
==================

  * add `json()` utf-8 illustration test. Closes #621
  * add "send" dependency
  * change `connect.static()` internals to use "send"
  * fix `session()` req.session generation with pathname mismatch
  * fix `cookieSession()` req.session generation with pathname mismatch
  * fix mime export. Closes #618

2.3.6 / 2012-07-03
==================

  * Fixed cookieSession() with cookieParser() secret regression. Closes #602
  * Fixed set-cookie header fields on cookie.path mismatch. Closes #615

2.3.5 / 2012-06-28
==================

  * Remove `logger()` mount check
  * Fixed `staticCache()` dont cache responses with set-cookie. Closes #607
  * Fixed `staticCache()` when Cookie is present

2.3.4 / 2012-06-22
==================

  * Added `err.buf` to urlencoded() and json()
  * Update cookie to 0.0.4. Closes #604
  * Fixed: only send 304 if original response in 2xx or 304 [timkuijsten]

2.3.3 / 2012-06-11
==================

  * Added ETags back to `static()` [timkuijsten]
  * Replaced `utils.parseRange()` with `range-parser` module
  * Replaced `utils.parseBytes()` with `bytes` module
  * Replaced `utils.modified()` with `fresh` module
  * Fixed `cookieSession()` regression with invalid cookie signing [shtylman]

2.3.2 / 2012-06-08
==================

  * expose mime module
  * Update crc dep (which bundled nodeunit)

2.3.1 / 2012-06-06
==================

  * Added `secret` option to `cookieSession` middleware [shtylman]
  * Added `secret` option to `session` middleware [shtylman]
  * Added `req.remoteUser` back to `basicAuth()` as alias of `req.user`
  * Performance: improve signed cookie parsing
  * Update `cookie` dependency [shtylman]

2.3.0 / 2012-05-20
==================

  * Added limit option to `json()`
  * Added limit option to `urlencoded()`
  * Added limit option to `multipart()`
  * Fixed: remove socket error event listener on callback
  * Fixed __ENOTDIR__ error on `static` middleware

2.2.2 / 2012-05-07
==================

  * Added support to csrf middle for pre-flight CORS requests
  * Updated `engines` to allow newer version of node
  * Removed duplicate repo prop. Closes #560

2.2.1 / 2012-04-28
==================

  * Fixed `static()` redirect when mounted. Closes #554

2.2.0 / 2012-04-25
==================

  * Added `make benchmark`
  * Perf: memoize url parsing (~20% increase)
  * Fixed `connect(fn, fn2, ...)`. Closes #549

2.1.3 / 2012-04-20
==================

  * Added optional json() `reviver` function to be passed to JSON.parse [jed]
  * Fixed: emit drain in compress middleware [nsabovic]

2.1.2 / 2012-04-11
==================

  * Fixed cookieParser() `req.cookies` regression

2.1.1 / 2012-04-11
==================

  * Fixed `session()` browser-session length cookies & examples
  * Fixed: make `query()` "self-aware" [jed]

2.1.0 / 2012-04-05
==================

  * Added `debug()` calls to `.use()` (`DEBUG=connect:displatcher`)
  * Added `urlencoded()` support for GET
  * Added `json()` support for GET. Closes #497
  * Added `strict` option to `json()`
  * Changed: `session()` only set-cookie when modified
  * Removed `Session#lastAccess` property. Closes #399

2.0.3 / 2012-03-20
==================

  * Added: `cookieSession()` only sets cookie on change. Closes #442
  * Added `connect:dispatcher` debug() probes

2.0.2 / 2012-03-04
==================

  * Added test for __ENAMETOOLONG__ now that node is fixed
  * Fixed static() index "/" check on windows. Closes #498
  * Fixed Content-Range behaviour to match RFC2616 [matthiasdg / visionmedia]

2.0.1 / 2012-02-29
==================

  * Added test coverage for `vhost()` middleware
  * Changed `cookieParser()` signed cookie support to use SHA-2 [senotrusov]
  * Fixed `static()` Range: respond with 416 when unsatisfiable
  * Fixed `vhost()` middleware. Closes #494

2.0.0 / 2011-10-05
==================

  * Added `cookieSession()` middleware for cookie-only sessions
  * Added `compress()` middleware for gzip / deflate support
  * Added `session()` "proxy" setting to trust `X-Forwarded-Proto`
  * Added `json()` middleware to parse "application/json"
  * Added `urlencoded()` middleware to parse "application/x-www-form-urlencoded"
  * Added `multipart()` middleware to parse "multipart/form-data"
  * Added `cookieParser(secret)` support so anything using this middleware may access signed cookies
  * Added signed cookie support to `cookieParser()`
  * Added support for JSON-serialized cookies to `cookieParser()`
  * Added `err.status` support in Connect's default end-point
  * Added X-Cache MISS / HIT to `staticCache()`
  * Added public `res.headerSent` checking nodes `res._headerSent` until node does
  * Changed `basicAuth()` req.remoteUser to req.user
  * Changed: default `session()` to a browser-session cookie. Closes #475
  * Changed: no longer lowercase cookie names
  * Changed `bodyParser()` to use `json()`, `urlencoded()`, and `multipart()`
  * Changed: `errorHandler()` is now a development-only middleware
  * Changed middleware to `next()` errors when possible so applications can unify logging / handling
  * Removed `http[s].Server` inheritance, now just a function, making it easy to have an app providing both http and https
  * Removed `.createServer()` (use `connect()`)
  * Removed `secret` option from `session()`, use `cookieParser(secret)`
  * Removed `connect.session.ignore` array support
  * Removed `router()` middleware. Closes #262
  * Fixed: set-cookie only once for browser-session cookies
  * Fixed FQDN support. dont add leading "/"
  * Fixed 404 XSS attack vector. Closes #473
  * Fixed __HEAD__ support for 404s and 500s generated by Connect's end-point

1.8.5 / 2011-12-22
==================

  * Fixed: actually allow empty body for json

1.8.4 / 2011-12-22
==================

  * Changed: allow empty body for json/urlencoded requests. Backport for #443

1.8.3 / 2011-12-16
==================

  * Fixed `static()` _index.html_ support on windows

1.8.2 / 2011-12-03
==================

  * Fixed potential security issue, store files in req.files. Closes #431 [reported by dobesv]

1.8.1 / 2011-11-21
==================

  * Added nesting support for _multipart/form-data_ [jackyz]

1.8.0 / 2011-11-17
==================

  * Added _multipart/form-data_ support to `bodyParser()` using formidable

1.7.3 / 2011-11-11
==================

  * Fixed `req.body`, always default to {}
  * Fixed HEAD support for 404s and 500s

1.7.2 / 2011-10-24
==================

  * "node": ">= 0.4.1 < 0.7.0"
  * Added `static()` redirect option. Closes #398
  * Changed `limit()`: respond with 413 when content-length exceeds the limit
  * Removed socket error listener in static(). Closes #389
  * Fixed `staticCache()` Age header field
  * Fixed race condition causing errors reported in #329.

1.7.1 / 2011-09-12
==================

  * Added: make `Store` inherit from `EventEmitter`
  * Added session `Store#load(sess, fn)` to fetch a `Session` instance
  * Added backpressure support to `staticCache()`
  * Changed `res.socket.destroy()` to `req.socket.destroy()`

1.7.0 / 2011-08-31
==================

  * Added `staticCache()` middleware, a memory cache for `static()`
  * Added public `res.headerSent` checking nodes `res._headerSent` (remove when node adds this)
  * Changed: ignore error handling middleware when header is sent
  * Changed: dispatcher errors after header is sent destroy the sock

1.6.4 / 2011-08-26
==================

  * Revert "Added double-next reporting"

1.6.3 / 2011-08-26
==================

  * Added double-`next()` reporting
  * Added `immediate` option to `logger()`. Closes #321
  * Dependency `qs >= 0.3.1`

1.6.2 / 2011-08-11
==================

  * Fixed `connect.static()` null byte vulnerability
  * Fixed `connect.directory()` null byte vulnerability
  * Changed: 301 redirect in `static()` to postfix "/" on directory. Closes #289

1.6.1 / 2011-08-03
==================

  * Added: allow retval `== null` from logger callback to ignore line
  * Added `getOnly` option to `connect.static.send()`
  * Added response "header" event allowing augmentation
  * Added `X-CSRF-Token` header field check
  * Changed dep `qs >= 0.3.0`
  * Changed: persist csrf token. Closes #322
  * Changed: sort directory middleware files alphabetically

1.6.0 / 2011-07-10
==================

  * Added :response-time to "dev" logger format
  * Added simple `csrf()` middleware. Closes #315
  * Fixed `res._headers` logger regression. Closes #318
  * Removed support for multiple middleware being passed to `.use()`

1.5.2 / 2011-07-06
==================

  * Added `filter` function option to `directory()` [David Rio Deiros]
  * Changed: re-write of the `logger()` middleware, with extensible tokens and formats
  * Changed: `static.send()` ".." in path without root considered malicious
  * Fixed quotes in docs. Closes #312
  * Fixed urls when mounting `directory()`, use `originalUrl` [Daniel Dickison]

1.5.1 / 2011-06-20
==================

  * Added malicious path check to `directory()` middleware
  * Added `utils.forbidden(res)`
  * Added `connect.query()` middleware

1.5.0 / 2011-06-20
==================

  * Added `connect.directory()` middleware for serving directory listings

1.4.6 / 2011-06-18
==================

  * Fixed `connect.static()` root with `..`
  * Fixed `connect.static()` __EBADF__

1.4.5 / 2011-06-17
==================

  * Fixed EBADF in `connect.static()`. Closes #297

1.4.4 / 2011-06-16
==================

  * Changed `connect.static()` to check resolved dirname. Closes #294

1.4.3 / 2011-06-06
==================

  * Fixed fd leak in `connect.static()` when the socket is closed
  * Fixed; `bodyParser()` ignoring __GET/HEAD__. Closes #285

1.4.2 / 2011-05-27
==================

  * Changed to `devDependencies`
  * Fixed stream creation on `static()` __HEAD__ request. [Andreas Lind Petersen]
  * Fixed Win32 support for `static()`
  * Fixed monkey-patch issue. Closes #261

1.4.1 / 2011-05-08
==================

  * Added "hidden" option to `static()`. ignores hidden files by default. Closes   * Added; expose `connect.static.mime.define()`. Closes #251
  * Fixed `errorHandler` middleware for missing stack traces. [aseemk]
#274

1.4.0 / 2011-04-25
==================

  * Added route-middleware `next('route')` support to jump passed the route itself
  * Added Content-Length support to `limit()`
  * Added route-specific middleware support (used to be in express)
  * Changed; refactored duplicate session logic
  * Changed; prevent redefining `store.generate` per request
  * Fixed; `static()` does not set Content-Type when explicitly set [nateps]
  * Fixed escape `errorHandler()` {error} contents
  * NOTE: `router` will be removed in 2.0

1.3.0 / 2011-04-06
==================

  * Added `router.remove(path[, method])` to remove a route

1.2.3 / 2011-04-05
==================

  * Fixed basicAuth realm issue when passing strings. Closes #253

1.2.2 / 2011-04-05
==================

  * Added `basicAuth(username, password)` support
  * Added `errorHandler.title` defaulting to "Connect"
  * Changed `errorHandler` css

1.2.1 / 2011-03-30
==================

  * Fixed `logger()` https `remoteAddress` logging [Alexander Simmerl]

1.2.0 / 2011-03-30
==================

  * Added `router.lookup(path[, method])`
  * Added `router.match(url[, method])`
  * Added basicAuth async support. Closes #223

1.1.5 / 2011-03-27
==================

  * Added; allow `logger()` callback function to return an empty string to ignore logging
  * Fixed; utilizing `mime.charsets.lookup()` for `static()`. Closes 245

1.1.4 / 2011-03-23
==================

  * Added `logger()` support for format function
  * Fixed `logger()` to support mess of writeHead()/progressive api for node 0.4.x

1.1.3 / 2011-03-21
==================

  * Changed; `limit()` now calls `req.destroy()`

1.1.2 / 2011-03-21
==================

  * Added request "limit" event to `limit()` middleware
  * Changed; `limit()` middleware will `next(err)` on failure

1.1.1 / 2011-03-18
==================

  * Fixed session middleware for HTTPS. Closes #241 [reported by mt502]

1.1.0 / 2011-03-17
==================

  * Added `Session#reload(fn)`

1.0.6 / 2011-03-09
==================

  * Fixed `res.setHeader()` patch, preserve casing

1.0.5 / 2011-03-09
==================

  * Fixed; `logger()` using `req.originalUrl` instead of `req.url`

1.0.4 / 2011-03-09
==================

  * Added `res.charset`
  * Added conditional sessions example
  * Added support for `session.ignore` to be replaced. Closes #227
  * Fixed `Cache-Control` delimiters. Closes #228

1.0.3 / 2011-03-03
==================

  * Fixed; `static.send()` invokes callback with connection error

1.0.2 / 2011-03-02
==================

  * Fixed exported connect function
  * Fixed package.json; node ">= 0.4.1 < 0.5.0"

1.0.1 / 2011-03-02
==================

  * Added `Session#save(fn)`. Closes #213
  * Added callback support to `connect.static.send()` for express
  * Added `connect.static.send()` "path" option
  * Fixed content-type in `static()` for _index.html_

1.0.0 / 2011-03-01
==================

  * Added `stack`, `message`, and `dump` errorHandler option aliases
  * Added `req.originalMethod` to methodOverride
  * Added `favicon()` maxAge option support
  * Added `connect()` alternative to `connect.createServer()`
  * Added new [documentation](http://senchalabs.github.com/connect)
  * Added Range support to `static()`
  * Added HTTPS support
  * Rewrote session middleware. The session API now allows for
    session-specific cookies, so you may alter each individually.
    Click to view the new [session api](http://senchalabs.github.com/connect/middleware-session.html).
  * Added middleware self-awareness. This helps prevent
    middleware breakage when used within mounted servers.
    For example `cookieParser()` will not parse cookies more
    than once even when within a mounted server.
  * Added new examples in the `./examples` directory
  * Added [limit()](http://senchalabs.github.com/connect/middleware-limit.html) middleware
  * Added [profiler()](http://senchalabs.github.com/connect/middleware-profiler.html) middleware
  * Added [responseTime()](http://senchalabs.github.com/connect/middleware-responseTime.html) middleware
  * Renamed `staticProvider` to `static`
  * Renamed `bodyDecoder` to `bodyParser`
  * Renamed `cookieDecoder` to `cookieParser`
  * Fixed ETag quotes. [reported by papandreou]
  * Fixed If-None-Match comma-delimited ETag support. [reported by papandreou]
  * Fixed; only set req.originalUrl once. Closes #124
  * Fixed symlink support for `static()`. Closes #123

0.5.10 / 2011-02-14
==================

  * Fixed SID space issue. Closes #196
  * Fixed; proxy `res.end()` to commit session data
  * Fixed directory traversal attack in `staticProvider`. Closes #198

0.5.9 / 2011-02-09
==================

  * qs >= 0.0.4

0.5.8 / 2011-02-04
==================

  * Added `qs` dependency
  * Fixed router race-condition causing possible failure
    when `next()`ing to one or more routes with parallel
    requests

0.5.7 / 2011-02-01
==================

  * Added `onvhost()` call so Express (and others) can know when they are
  * Revert "Added stylus support" (use the middleware which ships with stylus)
  * Removed custom `Server#listen()` to allow regular `http.Server#listen()` args to work properly
  * Fixed long standing router issue (#83) that causes '.' to be disallowed within named placeholders in routes [Andreas Lind Petersen]
  * Fixed `utils.uid()` length error [Jxck]
mounted

0.5.6 / 2011-01-23
==================

  * Added stylus support to `compiler`
  * _favicon.js_ cleanup
  * _compiler.js_ cleanup
  * _bodyDecoder.js_ cleanup

0.5.5 / 2011-01-13
==================

  * Changed; using sha256 HMAC instead of md5. [Paul Querna]
  * Changed; generated a longer random UID, without time influence. [Paul Querna]
  * Fixed; session middleware throws when secret is not present. [Paul Querna]

0.5.4 / 2011-01-07
==================

  * Added; throw when router path or callback is missing
  * Fixed; `next(err)` on cookie parse exception instead of ignoring
  * Revert "Added utils.pathname(), memoized url.parse(str).pathname"

0.5.3 / 2011-01-05
==================

  * Added _docs/api.html_
  * Added `utils.pathname()`, memoized url.parse(str).pathname
  * Fixed `session.id` issue. Closes #183
  * Changed; Defaulting `staticProvider` maxAge to 0 not 1 year. Closes #179
  * Removed bad outdated docs, we need something new / automated eventually

0.5.2 / 2010-12-28
==================

  * Added default __OPTIONS__ support to _router_ middleware

0.5.1 / 2010-12-28
==================

  * Added `req.session.id` mirroring `req.sessionID`
  * Refactored router, exposing `connect.router.methods`
  * Exclude non-lib files from npm
  * Removed imposed headers `X-Powered-By`, `Server`, etc

0.5.0 / 2010-12-06
==================

  * Added _./index.js_
  * Added route segment precondition support and example
  * Added named capture group support to router

0.4.0 / 2010-11-29
==================

  * Added `basicAuth` middleware
  * Added more HTTP methods to the `router` middleware

0.3.0 / 2010-07-21
==================

  * Added _staticGzip_ middleware
  * Added `connect.utils` to expose utils
  * Added `connect.session.Session`
  * Added `connect.session.Store`
  * Added `connect.session.MemoryStore`
  * Added `connect.middleware` to expose the middleware getters
  * Added `buffer` option to _logger_ for performance increase
  * Added _favicon_ middleware for serving your own favicon or the connect default
  * Added option support to _staticProvider_, can now pass _root_ and _lifetime_.
  * Added; mounted `Server` instances now have the `route` property exposed for reflection
  * Added support for callback as first arg to `Server#use()`
  * Added support for `next(true)` in _router_ to bypass match attempts
  * Added `Server#listen()` _host_ support
  * Added `Server#route` when `Server#use()` is called with a route on a `Server` instance
  * Added _methodOverride_ X-HTTP-Method-Override support
  * Refactored session internals, adds _secret_ option
  * Renamed `lifetime` option to `maxAge` in _staticProvider_
  * Removed connect(1), it is now [spark(1)](http://github.com/senchalabs/spark)
  * Removed connect(1) dependency on examples, they can all now run with node(1)
  * Remove a typo that was leaking a global.
  * Removed `Object.prototype` forEach() and map() methods
  * Removed a few utils not used
  * Removed `connect.createApp()`
  * Removed `res.simpleBody()`
  * Removed _format_ middleware
  * Removed _flash_ middleware
  * Removed _redirect_ middleware
  * Removed _jsonrpc_ middleware, use [visionmedia/connect-jsonrpc](http://github.com/visionmedia/connect-jsonrpc)
  * Removed _pubsub_ middleware
  * Removed need for `params.{captures,splat}` in _router_ middleware, `params` is an array
  * Changed; _compiler_ no longer 404s
  * Changed; _router_ signature now matches connect middleware signature
  * Fixed a require in _session_ for default `MemoryStore`
  * Fixed nasty request body bug in _router_. Closes #54
  * Fixed _less_ support in _compiler_
  * Fixed bug preventing proper bubbling of exceptions in mounted servers
  * Fixed bug in `Server#use()` preventing `Server` instances as the first arg
  * Fixed **ENOENT** special case, is now treated as any other exception
  * Fixed spark env support

0.2.1 / 2010-07-09
==================

  * Added support for _router_ `next()` to continue calling matched routes
  * Added mime type for _cache.manifest_ files.
  * Changed _compiler_ middleware to use async require
  * Changed session api, stores now only require `#get()`, and `#set()`
  * Fixed _cacheManifest_ by adding `utils.find()` back

0.2.0 / 2010-07-01
==================

  * Added calls to `Session()` casts the given object as a `Session` instance
  * Added passing of `next()` to _router_ callbacks. Closes #46
  * Changed; `MemoryStore#destroy()` removes `req.session`
  * Changed `res.redirect("back")` to default to "/" when Referr?er is not present
  * Fixed _staticProvider_ urlencoded paths issue. Closes #47
  * Fixed _staticProvider_ middleware responding to **GET** requests
  * Fixed _jsonrpc_ middleware `Accept` header check. Closes #43
  * Fixed _logger_ format option
  * Fixed typo in _compiler_ middleware preventing the _dest_ option from working

0.1.0 / 2010-06-25
==================

  * Revamped the api, view the [Connect documentation](http://extjs.github.com/Connect/index.html#Middleware-Authoring) for more info (hover on the right for menu)
  * Added [extended api docs](http://extjs.github.com/Connect/api.html)
  * Added docs for several more middleware layers
  * Added `connect.Server#use()`
  * Added _compiler_ middleware which provides arbitrary static compilation
  * Added `req.originalUrl`
  * Removed _blog_ example
  * Removed _sass_ middleware (use _compiler_)
  * Removed _less_ middleware (use _compiler_)
  * Renamed middleware to be camelcase, _body-decoder_ is now _bodyDecoder_ etc.
  * Fixed `req.url` mutation bug when matching `connect.Server#use()` routes
  * Fixed `mkdir -p` implementation used in _bin/connect_. Closes #39
  * Fixed bug in _bodyDecoder_ throwing exceptions on request empty bodies
  * `make install` installing lib to $LIB_PREFIX aka $HOME/.node_libraries

0.0.6 / 2010-06-22
==================

  * Added _static_ middleware usage example
  * Added support for regular expressions as paths for _router_
  * Added `util.merge()`
  * Increased performance of _static_ by ~ 200 rps
  * Renamed the _rest_ middleware to _router_
  * Changed _rest_ api to accept a callback function
  * Removed _router_ middleware
  * Removed _proto.js_, only `Object#forEach()` remains

0.0.5 / 2010-06-21
==================

  * Added Server#use() which contains the Layer normalization logic
  * Added documentation for several middleware
  * Added several new examples
  * Added _less_ middleware
  * Added _repl_ middleware
  * Added _vhost_ middleware
  * Added _flash_ middleware
  * Added _cookie_ middleware
  * Added _session_ middleware
  * Added `utils.htmlEscape()`
  * Added `utils.base64Decode()`
  * Added `utils.base64Encode()`
  * Added `utils.uid()`
  * Added bin/connect app path and --config path support for .js suffix, although optional. Closes #26
  * Moved mime code to `utils.mime`, ex `utils.mime.types`, and `utils.mime.type()`
  * Renamed req.redirect() to res.redirect(). Closes #29
  * Fixed _sass_ 404 on **ENOENT**
  * Fixed +new Date duplication. Closes #24

0.0.4 / 2010-06-16
==================

  * Added workerPidfile() to bin/connect
  * Added --workers support to bin/connect stop and status commands
  * Added _redirect_ middleware
  * Added better --config support to bin/connect. All flags can be utilized
  * Added auto-detection of _./config.js_
  * Added config example
  * Added `net.Server` support to bin/connect
  * Writing worker pids relative to `env.pidfile`
  * s/parseQuery/parse/g
  * Fixed npm support

0.0.3 / 2010-06-16
==================

  * Fixed node dependency in package.json, now _">= 0.1.98-0"_ to support __HEAD__

0.0.2 / 2010-06-15
==================

  * Added `-V, --version` to bin/connect
  * Added `utils.parseCookie()`
  * Added `utils.serializeCookie()`
  * Added `utils.toBoolean()`
  * Added _sass_ middleware
  * Added _cookie_ middleware
  * Added _format_ middleware
  * Added _lint_ middleware
  * Added _rest_ middleware
  * Added _./package.json_ (npm install connect)
  * Added `handleError()` support
  * Added `process.connectEnv`
  * Added custom log format support to _log_ middleware
  * Added arbitrary env variable support to bin/connect (ext: --logFormat ":method :url")
  * Added -w, --workers to bin/connect
  * Added bin/connect support for --user NAME and --group NAME
  * Fixed url re-writing support

0.0.1 / 2010-06-03
==================

  * Initial release

## 内容2
### 文件路径：
lib/index.js
### 代码内容：
/**
 * Connect is a middleware framework for node,
 * shipping with over 18 bundled middleware and a rich selection of
 * 3rd-party middleware.
 *
 *     var app = connect()
 *       .use(connect.logger('dev'))
 *       .use(connect.static('public'))
 *       .use(function(req, res){
 *         res.end('hello world\n');
 *       })
 *
 *     http.createServer(app).listen(3000);
 *
 * Installation:
 *
 *     $ npm install connect
 *
 * Middleware:
 *
 *  - [basicAuth](https://github.com/expressjs/basic-auth-connect) basic http authentication
 *  - [cookieParser](https://github.com/expressjs/cookie-parser) cookie parser
 *  - [compress](https://github.com/expressjs/compression) Gzip compression middleware
 *  - [csrf](https://github.com/expressjs/csurf) Cross-site request forgery protection
 *  - [errorHandler](https://github.com/expressjs/errorhandler) flexible error handler
 *  - [favicon](https://github.com/expressjs/favicon) efficient favicon server (with default icon)
 *  - [logger](https://github.com/expressjs/morgan) request logger with custom format support
 *  - [methodOverride](https://github.com/expressjs/method-override) faux HTTP method support
 *  - [responseTime](https://github.com/expressjs/response-time) calculates response-time and exposes via X-Response-Time
 *  - [session](https://github.com/expressjs/session) session management support with bundled MemoryStore
 *  - [timeout](https://github.com/expressjs/timeout) request timeouts
 *  - [vhost](https://github.com/expressjs/vhost) virtual host sub-domain mapping middleware
 *  - [bodyParser](bodyParser.html) extensible request body parser
 *  - [json](json.html) application/json parser
 *  - [urlencoded](urlencoded.html) application/x-www-form-urlencoded parser
 *  - [multipart](multipart.html) multipart/form-data parser
 *  - [cookieSession](cookieSession.html) cookie-based session support
 *  - [staticCache](staticCache.html) memory cache layer for the static() middleware
 *  - [static](static.html) streaming static file server supporting `Range` and more
 *  - [directory](directory.html) directory listing middleware
 *  - [limit](limit.html) limit the bytesize of request bodies
 *  - [query](query.html) automatic querystring parser, populating `req.query`
 *
 * Links:
 *
 *   - list of [3rd-party](https://github.com/senchalabs/connect/wiki) middleware
 *   - GitHub [repository](http://github.com/senchalabs/connect)
 *
 */
## 内容3
### 文件路径：
lib/middleware/directory.js
### 代码内容：
// TODO: arrow key navigation
// TODO: make icons extensible

/**
 * Module dependencies.
 */

var fs = require('fs')
  , parse = require('url').parse
  , utils = require('../utils')
  , path = require('path')
  , normalize = path.normalize
  , sep = path.sep
  , extname = path.extname
  , join = path.join;
var Batch = require('batch');
var Negotiator = require('negotiator');

/*!
 * Icon cache.
 */

var cache = {};

/*!
 * Default template.
 */

var defaultTemplate = join(__dirname, '..', 'public', 'directory.html');

/**
 * Media types and the map for content negotiation.
 */

var mediaTypes = [
  'text/html',
  'text/plain',
  'application/json'
];

var mediaType = {
  'text/html': 'html',
  'text/plain': 'plain',
  'application/json': 'json'
};

/**
 * Directory:
 *
 * Serve directory listings with the given `root` path.
 *
 * Options:
 *
 *  - `hidden` display hidden (dot) files. Defaults to false.
 *  - `icons`  display icons. Defaults to false.
 *  - `filter` Apply this filter function to files. Defaults to false.
 *  - `template` Optional path to html template. Defaults to a built-in template.
 *    The following tokens are replaced:
 *      - `{directory}` with the name of the directory.
 *      - `{files}` with the HTML of an unordered list of file links.
 *      - `{linked-path}` with the HTML of a link to the directory.
 *      - `{style}` with the built-in CSS and embedded images.
 *
 * @param {String} root
 * @param {Object} options
 * @return {Function}
 * @api public
 */

exports = module.exports = function directory(root, options){
  options = options || {};

  // root required
  if (!root) throw new Error('directory() root path required');
  var hidden = options.hidden
    , icons = options.icons
    , view = options.view || 'tiles'
    , filter = options.filter
    , root = normalize(root + sep)
    , template = options.template || defaultTemplate;

  return function directory(req, res, next) {
    if ('GET' != req.method && 'HEAD' != req.method) return next();

    var url = parse(req.url)
      , dir = decodeURIComponent(url.pathname)
      , path = normalize(join(root, dir))
      , originalUrl = parse(req.originalUrl)
      , originalDir = decodeURIComponent(originalUrl.pathname)
      , showUp = path != root;

    // null byte(s), bad request
    if (~path.indexOf('\0')) return next(utils.error(400));

    // malicious path, forbidden
    if (0 != path.indexOf(root)) return next(utils.error(403));

    // check if we have a directory
    fs.stat(path, function(err, stat){
      if (err) return 'ENOENT' == err.code
        ? next()
        : next(err);

      if (!stat.isDirectory()) return next();

      // fetch files
      fs.readdir(path, function(err, files){
        if (err) return next(err);
        if (!hidden) files = removeHidden(files);
        if (filter) files = files.filter(filter);
        files.sort();

        // content-negotiation
        var type = new Negotiator(req).preferredMediaType(mediaTypes);

        // not acceptable
        if (!type) return next(utils.error(406));
        exports[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path, view, template);
      });
    });
  };
};

/**
 * Respond with text/html.
 */

exports.html = function(req, res, files, next, dir, showUp, icons, path, view, template){
  fs.readFile(template, 'utf8', function(err, str){
    if (err) return next(err);
    fs.readFile(__dirname + '/../public/style.css', 'utf8', function(err, style){
      if (err) return next(err);
      stat(path, files, function(err, stats){
        if (err) return next(err);
        files = files.map(function(file, i){ return { name: file, stat: stats[i] }; });
        files.sort(fileSort);
        if (showUp) files.unshift({ name: '..' });
        str = str
          .replace('{style}', style.concat(iconStyle(files, icons)))
          .replace('{files}', html(files, dir, icons, view))
          .replace('{directory}', dir)
          .replace('{linked-path}', htmlPath(dir));
        res.setHeader('Content-Type', 'text/html');
        res.setHeader('Content-Length', str.length);
        res.end(str);
      });
    });
  });
};

/**
 * Respond with application/json.
 */

exports.json = function(req, res, files){
  files = JSON.stringify(files);
  res.setHeader('Content-Type', 'application/json');
  res.setHeader('Content-Length', files.length);
  res.end(files);
};

/**
 * Respond with text/plain.
 */

exports.plain = function(req, res, files){
  files = files.join('\n') + '\n';
  res.setHeader('Content-Type', 'text/plain');
  res.setHeader('Content-Length', files.length);
  res.end(files);
};

/**
 * Sort function for with directories first.
 */

function fileSort(a, b) {
  return Number(b.stat && b.stat.isDirectory()) - Number(a.stat && a.stat.isDirectory()) ||
    String(a.name).toLocaleLowerCase().localeCompare(String(b.name).toLocaleLowerCase());
}

/**
 * Map html `dir`, returning a linked path.
 */

function htmlPath(dir) {
  var curr = [];
  return dir.split('/').map(function(part){
    curr.push(encodeURIComponent(part));
    return part ? '<a href="' + curr.join('/') + '">' + part + '</a>' : '';
  }).join(' / ');
}

/**
 * Load icon images, return css string.
 */

function iconStyle (files, useIcons) {
  if (!useIcons) return '';
  var data = {};
  var views = { tiles: [], details: [], mobile: [] };

  for (var i=0; i < files.length; i++) {
    var file = files[i];
    if (file.name == '..') continue;

    var isDir = '..' == file.name || (file.stat && file.stat.isDirectory());
    var icon = isDir ? icons.folder : icons[extname(file.name)] || icons.default;

    var ext = extname(file.name);
    ext = isDir ? '.directory' : (icons[ext] ? ext : '.default');

    if (data[icon]) continue;
    data[icon] = ext + ' .name{background-image: url(data:image/png;base64,' + load(icon)+');}';
    views.tiles.push('.view-tiles ' + data[icon]);
  	views.details.push('.view-details ' + data[icon]);
  	views.mobile.push('#files ' + data[icon]);
  }

  var style = views.tiles.join('\n')
    + '\n'+views.details.join('\n')
    + '\n@media (max-width: 768px) {\n\t'
    + views.mobile.join('\n\t')
    + '\n}';
  return style;
}

/**
 * Map html `files`, returning an html unordered list.
 */

function html(files, dir, useIcons, view) {
  	return '<ul id="files" class="view-'+view+'">'
    + (view == 'details' ? (
      '<li class="header">'
      + '<span class="name">Name</span>'
      + '<span class="size">Size</span>'
      + '<span class="date">Modified</span>'
      + '</li>') : '')
    + files.map(function(file){
    var isDir
      , classes = []
      , path = dir.split('/').map(function (c) { return encodeURIComponent(c); });

    if (useIcons) {
      var ext = extname(file.name);
      isDir = '..' == file.name || (file.stat && file.stat.isDirectory());
      ext = isDir ? '.directory' : (icons[ext] ? ext : '.default');
      classes.push('icon');
      classes.push(ext.replace('.',''));
    }

    path.push(encodeURIComponent(file.name));

    var date = file.name == '..' ? ''
      : file.stat.mtime.toDateString()+' '+file.stat.mtime.toLocaleTimeString();
    var size = file.name == '..' ? '' : file.stat.size;

    return '<li><a href="'
      + utils.normalizeSlashes(normalize(path.join('/')))
      + '" class="'
      + classes.join(' ') + '"'
      + ' title="' + file.name + '">'
      + '<span class="name">'+file.name+'</span>'
      + '<span class="size">'+size+'</span>'
      + '<span class="date">'+date+'</span>'
      + '</a></li>';

  }).join('\n') + '</ul>';
}

/**
 * Load and cache the given `icon`.
 *
 * @param {String} icon
 * @return {String}
 * @api private
 */

function load(icon) {
  if (cache[icon]) return cache[icon];
  return cache[icon] = fs.readFileSync(__dirname + '/../public/icons/' + icon, 'base64');
}

/**
 * Filter "hidden" `files`, aka files
 * beginning with a `.`.
 *
 * @param {Array} files
 * @return {Array}
 * @api private
 */

function removeHidden(files) {
  return files.filter(function(file){
    return '.' != file[0];
  });
}

/**
 * Stat all files and return array of stat
 * in same order.
 */

function stat(dir, files, cb) {
  var batch = new Batch();

  batch.concurrency(10);

  files.forEach(function(file, i){
    batch.push(function(done){
      fs.stat(join(dir, file), done);
    });
  });

  batch.end(cb);
}

/**
 * Icon map.
 */

var icons = {
    '.js': 'page_white_code_red.png'
  , '.c': 'page_white_c.png'
  , '.h': 'page_white_h.png'
  , '.cc': 'page_white_cplusplus.png'
  , '.php': 'page_white_php.png'
  , '.rb': 'page_white_ruby.png'
  , '.cpp': 'page_white_cplusplus.png'
  , '.swf': 'page_white_flash.png'
  , '.pdf': 'page_white_acrobat.png'
  , 'folder': 'folder.png'
  , 'default': 'page_white.png'
};

## 内容4
### 文件路径：
lib/public/directory.html
### 代码内容：
<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>listing directory {directory}</title>
    <style>{style}</style>
    <script>
      function $(id){
        var el = 'string' == typeof id
          ? document.getElementById(id)
          : id;

        el.on = function(event, fn){
          if ('content loaded' == event) {
            event = window.attachEvent ? "load" : "DOMContentLoaded";
          }
          el.addEventListener
            ? el.addEventListener(event, fn, false)
            : el.attachEvent("on" + event, fn);
        };

        el.all = function(selector){
          return $(el.querySelectorAll(selector));
        };

        el.each = function(fn){
          for (var i = 0, len = el.length; i < len; ++i) {
            fn($(el[i]), i);
          }
        };

        el.getClasses = function(){
          return this.getAttribute('class').split(/\s+/);
        };

        el.addClass = function(name){
          var classes = this.getAttribute('class');
          el.setAttribute('class', classes
            ? classes + ' ' + name
            : name);
        };

        el.removeClass = function(name){
          var classes = this.getClasses().filter(function(curr){
            return curr != name;
          });
          this.setAttribute('class', classes.join(' '));
        };

        return el;
      }

      function search() {
        var str = $('search').value
          , links = $('files').all('a');

        links.each(function(link){
          var text = link.textContent;

          if ('..' == text) return;
          if (str.length && ~text.indexOf(str)) {
            link.addClass('highlight');
          } else {
            link.removeClass('highlight');
          }
        });
      }

      $(window).on('content loaded', function(){
        $('search').on('keyup', search);
      });
    </script>
  </head>
  <body class="directory">
    <input id="search" type="text" placeholder="Search" autocomplete="off" />
    <div id="wrapper">
      <h1>{linked-path}</h1>
      {files}
    </div>
  </body>
</html>
## 内容5
### 文件路径：
lib/public/style.css
### 代码内容：
* {
  margin: 0;
  padding: 0;
  outline: 0;
}

body {
  padding: 80px 100px;
  font: 13px "Helvetica Neue", "Lucida Grande", "Arial";
  background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9));
  background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9);
  background-repeat: no-repeat;
  color: #555;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 {
  font-size: 22px;
  color: #343434;
}
h1 em, h2 em {
  padding: 0 5px;
  font-weight: normal;
}
h1 {
  font-size: 60px;
}
h2 {
  margin-top: 10px;
}
h3 {
  margin: 5px 0 10px 0;
  padding-bottom: 5px;
  border-bottom: 1px solid #eee;
  font-size: 18px;
}
ul li {
  list-style: none;
}
ul li:hover {
  cursor: pointer;
  color: #2e2e2e;
}
ul li .path {
  padding-left: 5px;
  font-weight: bold;
}
ul li .line {
  padding-right: 5px;
  font-style: italic;
}
ul li:first-child .path {
  padding-left: 0;
}
p {
  line-height: 1.5;
}
a {
  color: #555;
  text-decoration: none;
}
a:hover {
  color: #303030;
}
#stacktrace {
  margin-top: 15px;
}
.directory h1 {
  margin-bottom: 15px;
  font-size: 18px;
}
ul#files {
  width: 100%;
  height: 100%;
  overflow: hidden;
}
ul#files li {
  float: left;
  width: 30%;
  line-height: 25px;
  margin: 1px;
}
ul#files li a {
  display: block;
  height: 25px;
  border: 1px solid transparent;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
  overflow: hidden;
  white-space: nowrap;
}
ul#files li a:focus,
ul#files li a:hover {
  background: rgba(255,255,255,0.65);
  border: 1px solid #ececec;
}
ul#files li a.highlight {
  -webkit-transition: background .4s ease-in-out;
  background: #ffff4f;
  border-color: #E9DC51;
}
#search {
  display: block;
  position: fixed;
  top: 20px;
  right: 20px;
  width: 90px;
  -webkit-transition: width ease 0.2s, opacity ease 0.4s;
  -moz-transition: width ease 0.2s, opacity ease 0.4s;
  -webkit-border-radius: 32px;
  -moz-border-radius: 32px;
  -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03);
  -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03);
  -webkit-font-smoothing: antialiased;
  text-align: left;
  font: 13px "Helvetica Neue", Arial, sans-serif;
  padding: 4px 10px;
  border: none;
  background: transparent;
  margin-bottom: 0;
  outline: none;
  opacity: 0.7;
  color: #888;
}
#search:focus {
  width: 120px;
  opacity: 1.0;
}

/*views*/
#files span {
  display: inline-block;
  overflow: hidden;
  text-overflow: ellipsis;
  text-indent: 10px;
}
#files .name {
  background-repeat: no-repeat;
}
#files .icon .name {
  text-indent: 28px;
}

/*tiles*/
.view-tiles .name {
  width: 100%;
  background-position: 8px 5px;
}
.view-tiles .size,
.view-tiles .date {
  display: none;
}

/*details*/
ul#files.view-details li {
  float: none;
  display: block;
  width: 90%;
}
ul#files.view-details li.header {
  height: 25px;
  background: #000;
  color: #fff;
  font-weight: bold;
}
.view-details .header {
  border-radius: 5px;
}
.view-details .name {
  width: 60%;
  background-position: 8px 5px;
}
.view-details .size {
  width: 10%;
}
.view-details .date {
  width: 30%;
}
.view-details .size,
.view-details .date {
  text-align: right;
  direction: rtl;
}

/*mobile*/
@media (max-width: 768px) {
  body {
    font-size: 13px;
    line-height: 16px;
    padding: 0;
  }
  #search {
    position: static;
    width: 100%;
    font-size: 2em;
    line-height: 1.8em;
    text-indent: 10px;
    border: 0;
    border-radius: 0;
    padding: 10px 0;
    margin: 0;
  }
  #search:focus {
    width: 100%;
    border: 0;
    opacity: 1;
  }
  .directory h1 {
    font-size: 2em;
    line-height: 1.5em;
    color: #fff;
    background: #000;
    padding: 15px 10px;
    margin: 0;
  }
  ul#files {
    border-top: 1px solid #cacaca;
  }
  ul#files li {
    float: none;
    width: auto !important;
    display: block;
    border-bottom: 1px solid #cacaca;
    font-size: 2em;
    line-height: 1.2em;
    text-indent: 0;
    margin: 0;
  }
  ul#files li:nth-child(odd) {
    background: #e0e0e0;
  }
  ul#files li a {
    height: auto;
    border: 0;
    border-radius: 0;
    padding: 15px 10px;
  }
  ul#files li a:focus,
  ul#files li a:hover {
    border: 0;
  }
  #files .header,
  #files .size,
  #files .date {
    display: none !important;
  }
  #files .name {
    float: none;
    display: inline-block;
    width: 100%;
    text-indent: 0;
    background-position: 0 0;
  }
  #files .icon .name {
    text-indent: 41px;
  }
}

## 内容6
### 文件路径：
package.json
### 代码内容：
{
  "name": "connect",
  "version": "2.13.1",
  "description": "High performance middleware framework",
  "keywords": [
    "framework",
    "web",
    "middleware",
    "connect",
    "rack"
  ],
  "repository": "git://github.com/senchalabs/connect.git",
  "author": "TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)",
  "dependencies": {
    "basic-auth-connect": "1.0.0",
    "batch": "0.5.0",
    "cookie-parser": "1.0.1",
    "cookie-signature": "1.0.3",
    "compression": "1.0.0",
    "connect-timeout": "1.0.0",
    "csurf": "1.0.0",
    "errorhandler": "1.0.0",
    "express-session": "1.0.2",
    "method-override": "1.0.0",
    "morgan": "1.0.0",
    "qs": "0.6.6",
    "response-time": "1.0.0",
    "static-favicon": "1.0.0",
    "vhost": "1.0.0",
    "send": "0.1.4",
    "bytes": "0.2.1",
    "fresh": "0.2.0",
    "pause": "0.0.1",
    "debug": ">= 0.7.3 < 1",
    "raw-body": "1.1.3",
    "negotiator": "0.3.0",
    "multiparty": "2.2.0"
  },
  "devDependencies": {
    "should": ">= 2.0.2 < 3",
    "mocha": ">= 1.13.0 < 2",
    "jade": ">= 0.35.0 < 1",
    "dox": ">= 0.4.4 < 1"
  },
  "licenses": [
    {
      "type": "MIT",
      "url": "https://raw.github.com/senchalabs/connect/master/LICENSE"
    }
  ],
  "main": "index",
  "engines": {
    "node": ">= 0.8.0"
  },
  "scripts": {
    "test": "make"
  }
}

Output:
【漏洞类型】路径遍历漏洞

【严重性】High

【漏洞摘要】
这是一个路径遍历漏洞。在`lib/middleware/directory.js`文件中，`fs.readdir(path, function(err, files)`这一行代码会读取`path`目录下的文件列表，并将其渲染为HTML页面。攻击者可以通过构造特定的URL，利用`path`变量中的未验证用户输入，访问服务器上的任意文件。具体来说，攻击者可以利用`..`（双点号）来穿越目录层级，从而访问到不应该公开的文件或目录。

根本原因在于：在读取目录之前，代码没有正确验证`path`是否在指定的`root`目录下。这允许攻击者通过URL路径构造出位于`root`目录之外的路径，进而访问敏感文件。

【关键代码模式】
- `fs.readdir(path, function(err, files))`
- `parse(req.url)`
- `decodeURIComponent(url.pathname)`
- `normalize(join(root, dir))`

【修复方法说明】
修复方法是将`directory`中间件替换为`serve-index`，该中间件已经内置了路径遍历保护机制。这样可以避免手动编写复杂的路径验证逻辑，从而减少漏洞引入的风险。


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
core/src/main/java/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
### 代码内容：
package org.bouncycastle.crypto.generators;

import java.math.BigInteger;

import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.math.Primes;
import org.bouncycastle.math.ec.WNafUtil;

/**
 * an RSA key pair generator.
 */
public class RSAKeyPairGenerator
    implements AsymmetricCipherKeyPairGenerator
{
    private static final BigInteger ONE = BigInteger.valueOf(1);

    private RSAKeyGenerationParameters param;

    public void init(KeyGenerationParameters param)
    {
        this.param = (RSAKeyGenerationParameters)param;
    }

    public AsymmetricCipherKeyPair generateKeyPair()
    {
        AsymmetricCipherKeyPair result = null;
        boolean done = false;

        //
        // p and q values should have a length of half the strength in bits
        //
        int strength = param.getStrength();
        int pbitlength = (strength + 1) / 2;
        int qbitlength = strength - pbitlength;
        int mindiffbits = (strength / 2) - 100;

        if (mindiffbits < strength / 3)
        {
            mindiffbits = strength / 3;
        }

        int minWeight = strength >> 2;

        // d lower bound is 2^(strength / 2)
        BigInteger dLowerBound = BigInteger.valueOf(2).pow(strength / 2);
        // squared bound (sqrt(2)*2^(nlen/2-1))^2
        BigInteger squaredBound = ONE.shiftLeft(strength - 1);
        // 2^(nlen/2 - 100)
        BigInteger minDiff = ONE.shiftLeft(mindiffbits);

        while (!done)
        {
            BigInteger p, q, n, d, e, pSub1, qSub1, gcd, lcm;

            e = param.getPublicExponent();

            p = chooseRandomPrime(pbitlength, e, squaredBound);

            //
            // generate a modulus of the required length
            //
            for (; ; )
            {
                q = chooseRandomPrime(qbitlength, e, squaredBound);

                // p and q should not be too close together (or equal!)
                BigInteger diff = q.subtract(p).abs();
                if (diff.bitLength() < mindiffbits || diff.compareTo(minDiff) <= 0)
                {
                    continue;
                }

                //
                // calculate the modulus
                //
                n = p.multiply(q);

                if (n.bitLength() != strength)
                {
                    //
                    // if we get here our primes aren't big enough, make the largest
                    // of the two p and try again
                    //
                    p = p.max(q);
                    continue;
                }

	            /*
                 * Require a minimum weight of the NAF representation, since low-weight composites may
	             * be weak against a version of the number-field-sieve for factoring.
	             *
	             * See "The number field sieve for integers of low weight", Oliver Schirokauer.
	             */
                if (WNafUtil.getNafWeight(n) < minWeight)
                {
                    p = chooseRandomPrime(pbitlength, e, squaredBound);
                    continue;
                }

                break;
            }

            if (p.compareTo(q) < 0)
            {
                gcd = p;
                p = q;
                q = gcd;
            }

            pSub1 = p.subtract(ONE);
            qSub1 = q.subtract(ONE);
            gcd = pSub1.gcd(qSub1);
            lcm = pSub1.divide(gcd).multiply(qSub1);

            //
            // calculate the private exponent
            //
            d = e.modInverse(lcm);

            if (d.compareTo(dLowerBound) <= 0)
            {
                continue;
            }
            else
            {
                done = true;
            }

            //
            // calculate the CRT factors
            //
            BigInteger dP, dQ, qInv;

            dP = d.remainder(pSub1);
            dQ = d.remainder(qSub1);
            qInv = q.modInverse(p);

            result = new AsymmetricCipherKeyPair(
                new RSAKeyParameters(false, n, e),
                new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
        }

        return result;
    }

    /**
     * Choose a random prime value for use with RSA
     *
     * @param bitlength the bit-length of the returned prime
     * @param e         the RSA public exponent
     * @return A prime p, with (p-1) relatively prime to e
     */
    protected BigInteger chooseRandomPrime(int bitlength, BigInteger e, BigInteger sqrdBound)
    {
        int iterations = getNumberOfIterations(bitlength, param.getCertainty());

        for (int i = 0; i != 5 * bitlength; i++)
        {
            BigInteger p = new BigInteger(bitlength, 1, param.getRandom());

            if (p.mod(e).equals(ONE))
            {
                continue;
            }

            if (p.multiply(p).compareTo(sqrdBound) < 0)
            {
                continue;
            }

            if (!isProbablePrime(p, iterations))
            {
                continue;
            }

            if (!e.gcd(p.subtract(ONE)).equals(ONE))
            {
                continue;
            }

            return p;
        }

        throw new IllegalStateException("unable to generate prime number for RSA key");
    }

    protected boolean isProbablePrime(BigInteger x, int iterations)
    {
        /*
         * Primes class for FIPS 186-4 C.3 primality checking
         */
        return !Primes.hasAnySmallFactors(x) && Primes.isMRProbablePrime(x, param.getRandom(), iterations);
    }

    private static int getNumberOfIterations(int bits, int certainty)
    {
        /*
         * NOTE: We enforce a minimum 'certainty' of 100 for bits >= 1024 (else 80). Where the
         * certainty is higher than the FIPS 186-4 tables (C.2/C.3) cater to, extra iterations
         * are added at the "worst case rate" for the excess.
         */
        if (bits >= 1536)
        {
            return  certainty <= 100 ? 3
                :   certainty <= 128 ? 4
                :   4 + (certainty - 128 + 1) / 2;
        }
        else if (bits >= 1024)
        {
            return  certainty <= 100 ? 4
                :   certainty <= 112 ? 5
                :   5 + (certainty - 112 + 1) / 2;
        }
        else if (bits >= 512)
        {
            return  certainty <= 80  ? 5
                :   certainty <= 100 ? 7
                :   7 + (certainty - 100 + 1) / 2;
        }
        else
        {
            return  certainty <= 80  ? 40
                :   40 + (certainty - 80 + 1) / 2;
        }
    }
}

Output:
【漏洞类型】循环次数过多导致性能问题
【严重性】Medium
【漏洞摘要】原始代码中的`chooseRandomPrime`方法在生成随机素数时，使用了一个固定的循环次数`5 * bitlength`。这个循环次数在生成较大的素数时可能会变得非常大，导致性能问题。此外，`isProbablePrime`方法中的`iterations`参数被硬编码在`chooseRandomPrime`方法中，这可能使得代码在未来的安全配置更新时无法灵活调整。
【关键代码模式】`chooseRandomPrime`方法中的循环次数`5 * bitlength`和`isProbablePrime`方法中的`iterations`参数硬编码。
【修复方法说明】修复方法移除了`chooseRandomPrime`方法中的`iterations`参数硬编码，并将其计算逻辑移到了`isProbablePrime`方法内部，提高了代码的灵活性和性能。