Java Code Examples for javax.servlet.http.Cookie#getSecure()

The following examples show how to use javax.servlet.http.Cookie#getSecure() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: DefaultWebApplicationResponse.java    From piranha with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
/**
 * Write out a cookie.
 *
 * @param cookie the cookie.
 * @throws IOException when an I/O error occurs.
 */
private void writeCookie(Cookie cookie) throws IOException {
    outputStream.write("Set-Cookie: ".getBytes());
    outputStream.write(cookie.getName().getBytes());
    outputStream.write("=".getBytes());
    if (cookie.getValue() != null) {
        outputStream.write(cookie.getValue().getBytes());
    }

    if (cookie.getSecure()) {
        outputStream.write("; Secure".getBytes());
    }

    if (cookie.isHttpOnly()) {
        outputStream.write("; HttpOnly".getBytes());
    }

    if (cookie.getPath() != null) {
        outputStream.write(("; Path=" + cookie.getPath()).getBytes());
    }

    outputStream.write("\n".getBytes());
}
 
Example 2
Source File: CookieUtil.java    From khan-session with GNU Lesser General Public License v2.1 6 votes vote down vote up
/**
 * Create Cookie header
 *
 * @param cookie
 * @param isHttpOnly
 * @return
 */
public static String createCookieHeader(Cookie cookie, boolean isHttpOnly) {
    StringBuilder sb = new StringBuilder();
    sb = sb.append(cookie.getName()).append("=").append(cookie.getValue());

    if (cookie.getDomain() != null && !cookie.getDomain().equals("") ) {
        sb.append(";Domain=").append(cookie.getDomain());
    }
    if (cookie.getPath() != null && !cookie.getPath().equals("")) {
        sb.append(";Path=").append(cookie.getPath());
    }
    if (cookie.getComment() != null && !cookie.getComment().equals("")) {
        sb.append(";Comment=").append(cookie.getComment());
    }
    if (cookie.getMaxAge() > -1) {
        sb.append(";Max-Age=").append(cookie.getMaxAge());
    }
    if (cookie.getSecure()) {
        sb.append(";Secure");
    }
    if (isHttpOnly) {
        sb.append(";HttpOnly");
    }

    return sb.toString();
}
 
Example 3
Source File: MockHttpServletResponse.java    From spring-analysis-note with MIT License 5 votes vote down vote up
private String getCookieHeader(Cookie cookie) {
	StringBuilder buf = new StringBuilder();
	buf.append(cookie.getName()).append('=').append(cookie.getValue() == null ? "" : cookie.getValue());
	if (StringUtils.hasText(cookie.getPath())) {
		buf.append("; Path=").append(cookie.getPath());
	}
	if (StringUtils.hasText(cookie.getDomain())) {
		buf.append("; Domain=").append(cookie.getDomain());
	}
	int maxAge = cookie.getMaxAge();
	if (maxAge >= 0) {
		buf.append("; Max-Age=").append(maxAge);
		buf.append("; Expires=");
		HttpHeaders headers = new HttpHeaders();
		headers.setExpires(maxAge > 0 ? System.currentTimeMillis() + 1000L * maxAge : 0);
		buf.append(headers.getFirst(HttpHeaders.EXPIRES));
	}

	if (cookie.getSecure()) {
		buf.append("; Secure");
	}
	if (cookie.isHttpOnly()) {
		buf.append("; HttpOnly");
	}
	if (cookie instanceof MockCookie) {
		MockCookie mockCookie = (MockCookie) cookie;
		if (StringUtils.hasText(mockCookie.getSameSite())) {
			buf.append("; SameSite=").append(mockCookie.getSameSite());
		}
	}
	return buf.toString();
}
 
Example 4
Source File: MockHttpServletResponse.java    From spring-analysis-note with MIT License 5 votes vote down vote up
private String getCookieHeader(Cookie cookie) {
	StringBuilder buf = new StringBuilder();
	buf.append(cookie.getName()).append('=').append(cookie.getValue() == null ? "" : cookie.getValue());
	if (StringUtils.hasText(cookie.getPath())) {
		buf.append("; Path=").append(cookie.getPath());
	}
	if (StringUtils.hasText(cookie.getDomain())) {
		buf.append("; Domain=").append(cookie.getDomain());
	}
	int maxAge = cookie.getMaxAge();
	if (maxAge >= 0) {
		buf.append("; Max-Age=").append(maxAge);
		buf.append("; Expires=");
		HttpHeaders headers = new HttpHeaders();
		headers.setExpires(maxAge > 0 ? System.currentTimeMillis() + 1000L * maxAge : 0);
		buf.append(headers.getFirst(HttpHeaders.EXPIRES));
	}

	if (cookie.getSecure()) {
		buf.append("; Secure");
	}
	if (cookie.isHttpOnly()) {
		buf.append("; HttpOnly");
	}
	if (cookie instanceof MockCookie) {
		MockCookie mockCookie = (MockCookie) cookie;
		if (StringUtils.hasText(mockCookie.getSameSite())) {
			buf.append("; SameSite=").append(mockCookie.getSameSite());
		}
	}
	return buf.toString();
}
 
Example 5
Source File: MockHttpServletResponse.java    From java-technology-stack with MIT License 5 votes vote down vote up
private String getCookieHeader(Cookie cookie) {
	StringBuilder buf = new StringBuilder();
	buf.append(cookie.getName()).append('=').append(cookie.getValue() == null ? "" : cookie.getValue());
	if (StringUtils.hasText(cookie.getPath())) {
		buf.append("; Path=").append(cookie.getPath());
	}
	if (StringUtils.hasText(cookie.getDomain())) {
		buf.append("; Domain=").append(cookie.getDomain());
	}
	int maxAge = cookie.getMaxAge();
	if (maxAge >= 0) {
		buf.append("; Max-Age=").append(maxAge);
		buf.append("; Expires=");
		HttpHeaders headers = new HttpHeaders();
		headers.setExpires(maxAge > 0 ? System.currentTimeMillis() + 1000L * maxAge : 0);
		buf.append(headers.getFirst(HttpHeaders.EXPIRES));
	}

	if (cookie.getSecure()) {
		buf.append("; Secure");
	}
	if (cookie.isHttpOnly()) {
		buf.append("; HttpOnly");
	}
	if (cookie instanceof MockCookie) {
		MockCookie mockCookie = (MockCookie) cookie;
		if (StringUtils.hasText(mockCookie.getSameSite())) {
			buf.append("; SameSite=").append(mockCookie.getSameSite());
		}
	}
	return buf.toString();
}
 
Example 6
Source File: MockHttpServletResponse.java    From java-technology-stack with MIT License 5 votes vote down vote up
private String getCookieHeader(Cookie cookie) {
	StringBuilder buf = new StringBuilder();
	buf.append(cookie.getName()).append('=').append(cookie.getValue() == null ? "" : cookie.getValue());
	if (StringUtils.hasText(cookie.getPath())) {
		buf.append("; Path=").append(cookie.getPath());
	}
	if (StringUtils.hasText(cookie.getDomain())) {
		buf.append("; Domain=").append(cookie.getDomain());
	}
	int maxAge = cookie.getMaxAge();
	if (maxAge >= 0) {
		buf.append("; Max-Age=").append(maxAge);
		buf.append("; Expires=");
		HttpHeaders headers = new HttpHeaders();
		headers.setExpires(maxAge > 0 ? System.currentTimeMillis() + 1000L * maxAge : 0);
		buf.append(headers.getFirst(HttpHeaders.EXPIRES));
	}

	if (cookie.getSecure()) {
		buf.append("; Secure");
	}
	if (cookie.isHttpOnly()) {
		buf.append("; HttpOnly");
	}
	if (cookie instanceof MockCookie) {
		MockCookie mockCookie = (MockCookie) cookie;
		if (StringUtils.hasText(mockCookie.getSameSite())) {
			buf.append("; SameSite=").append(mockCookie.getSameSite());
		}
	}
	return buf.toString();
}
 
Example 7
Source File: AwsHttpServletResponse.java    From aws-serverless-java-container with Apache License 2.0 5 votes vote down vote up
@SuppressFBWarnings("COOKIE_USAGE")
@Override
public void addCookie(Cookie cookie) {
    if (request != null && request.getDispatcherType() == DispatcherType.INCLUDE && isCommitted()) {
        throw new IllegalStateException("Cannot add Cookies for include request when response is committed");
    }
    String cookieData = cookie.getName() + "=" + cookie.getValue();
    if (cookie.getPath() != null) {
        cookieData += "; Path=" + cookie.getPath();
    }
    if (cookie.getSecure()) {
        cookieData += "; Secure";
    }
    if (cookie.isHttpOnly()) {
        cookieData += "; HttpOnly";
    }
    if (cookie.getDomain() != null && !"".equals(cookie.getDomain().trim())) {
        cookieData += "; Domain=" + cookie.getDomain();
    }

    if (cookie.getMaxAge() > 0) {
        cookieData += "; Max-Age=" + cookie.getMaxAge();

        // we always set the timezone to GMT
        TimeZone gmtTimeZone = TimeZone.getTimeZone(COOKIE_DEFAULT_TIME_ZONE);
        Calendar currentTimestamp = Calendar.getInstance(gmtTimeZone);
        currentTimestamp.add(Calendar.SECOND, cookie.getMaxAge());
        SimpleDateFormat cookieDateFormatter = new SimpleDateFormat(HEADER_DATE_PATTERN);
        cookieDateFormatter.setTimeZone(gmtTimeZone);
        cookieData += "; Expires=" + cookieDateFormatter.format(currentTimestamp.getTime());
    }

    setHeader(HttpHeaders.SET_COOKIE, cookieData, false);
}
 
Example 8
Source File: CookieHelper.java    From kisso with Apache License 2.0 5 votes vote down vote up
/**
 * <p>
 * 解决 servlet 3.0 以下版本不支持 HttpOnly
 * </p>
 *
 * @param response HttpServletResponse类型的响应
 * @param cookie   要设置httpOnly的cookie对象
 */
public static void addHttpOnlyCookie(HttpServletResponse response, Cookie cookie) {
    if (cookie == null) {
        return;
    }
    /**
     * 依次取得cookie中的名称、值、 最大生存时间、路径、域和是否为安全协议信息
     */
    String cookieName = cookie.getName();
    String cookieValue = cookie.getValue();
    int maxAge = cookie.getMaxAge();
    String path = cookie.getPath();
    String domain = cookie.getDomain();
    boolean isSecure = cookie.getSecure();
    StringBuffer sf = new StringBuffer();
    sf.append(cookieName + "=" + cookieValue + ";");
    if (maxAge >= 0) {
        sf.append("Max-Age=" + cookie.getMaxAge() + ";");
    }
    if (domain != null) {
        sf.append("domain=" + domain + ";");
    }
    if (path != null) {
        sf.append("path=" + path + ";");
    }
    if (isSecure) {
        sf.append("secure;HTTPOnly;");
    } else {
        sf.append("HTTPOnly;");
    }
    response.addHeader("Set-Cookie", sf.toString());
}
 
Example 9
Source File: CookieHelper.java    From ymate-platform-v2 with Apache License 2.0 5 votes vote down vote up
/**
 * @param key    键
 * @param value  值
 * @param maxAge 过期时间
 * @return 添加或重设Cookie
 */
public CookieHelper setCookie(String key, String value, int maxAge) {
    Cookie _cookie = new Cookie(__owner.getModuleCfg().getCookiePrefix() + key, StringUtils.isBlank(value) ? "" : encodeValue(value));
    _cookie.setMaxAge(maxAge);
    _cookie.setPath(__owner.getModuleCfg().getCookiePath());
    _cookie.setSecure(__request.isSecure());
    if (StringUtils.isNotBlank(__owner.getModuleCfg().getCookieDomain())) {
        _cookie.setDomain(__owner.getModuleCfg().getCookieDomain());
    }
    //
    if (__useHttpOnly) {
        StringBuilder _cookieSB = new StringBuilder();
        _cookieSB.append(_cookie.getName()).append("=").append(_cookie.getValue()).append("; ");
        if (maxAge == 0) {
            _cookieSB.append("Expires=Thu Jan 01 08:00:00 CST 1970; ");
        } else if (maxAge > 0) {
            _cookieSB.append("Max-Age=").append(_cookie.getMaxAge()).append("; ");
        }
        if (StringUtils.isNotBlank(_cookie.getDomain())) {
            _cookieSB.append("Domain=").append(_cookie.getDomain()).append("; ");
        }
        _cookieSB.append("Path=").append(_cookie.getPath()).append("; ");
        if (_cookie.getSecure()) {
            _cookieSB.append("Secure; ");
        }
        _cookieSB.append("HttpOnly;");
        //
        __response.addHeader("Set-Cookie", _cookieSB.toString());
    } else {
        __response.addCookie(_cookie);
    }
    return this;
}
 
Example 10
Source File: CookieSerializer.java    From cacheonix-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
@SuppressWarnings("RedundantIfStatement")
static boolean equals(final Cookie thisCookie, final Cookie thatCookie) {

   if (thisCookie.getMaxAge() != thatCookie.getMaxAge()) {
      return false;
   }
   if (thisCookie.getSecure() != thatCookie.getSecure()) {
      return false;
   }
   if (thisCookie.getVersion() != thatCookie.getVersion()) {
      return false;
   }
   if (thisCookie.getName() != null ? !thisCookie.getName().equals(
           thatCookie.getName()) : thatCookie.getName() != null) {
      return false;
   }
   if (thisCookie.getValue() != null ? !thisCookie.getValue().equals(
           thatCookie.getValue()) : thatCookie.getValue() != null) {
      return false;
   }
   if (thisCookie.getComment() != null ? !thisCookie.getComment().equals(
           thatCookie.getComment()) : thatCookie.getComment() != null) {
      return false;
   }
   if (thisCookie.getDomain() != null ? !thisCookie.getDomain().equals(
           thatCookie.getDomain()) : thatCookie.getDomain() != null) {
      return false;
   }
   if (thisCookie.getPath() != null ? !thisCookie.getPath().equals(
           thatCookie.getPath()) : thatCookie.getPath() != null) {
      return false;
   }
   return true;
}
 
Example 11
Source File: ResponseImpl.java    From knopflerfish.org with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
public void setCookieHeader(Cookie cookie)
{
  if (cookie == null) {
    return;
  }

  final StringBuffer header = new StringBuffer(32);
  String attrValue;
  int maxAge;
  header.append(cookie.getName() + "=" + cookie.getValue());
  if ((attrValue = cookie.getComment()) != null) {
    header.append(";Comment=" + attrValue);
  }
  if ((attrValue = cookie.getDomain()) != null) {
    header.append(";Domain=" + attrValue);
  }
  if ((maxAge = cookie.getMaxAge()) != -1) {
    if (maxAge > 0) {
      appendCookieExpires(header, maxAge);
    }
    header.append(";Max-Age=" + maxAge);
  }
  if ((attrValue = cookie.getPath()) != null) {
    header.append(";Path=" + attrValue);
  } else {
    header.append(";Path=/");
  }
  if (cookie.getSecure()) {
    header.append(";Secure");
  }
  header.append(";Version=" + cookie.getVersion());

  setHeader("Set-Cookie", header.toString());
}
 
Example 12
Source File: LegacyCookieProcessor.java    From Tomcat8-Source-Read with MIT License 4 votes vote down vote up
@Override
public String generateHeader(Cookie cookie) {
    /*
     * The spec allows some latitude on when to send the version attribute
     * with a Set-Cookie header. To be nice to clients, we'll make sure the
     * version attribute is first. That means checking the various things
     * that can cause us to switch to a v1 cookie first.
     *
     * Note that by checking for tokens we will also throw an exception if a
     * control character is encountered.
     */
    int version = cookie.getVersion();
    String value = cookie.getValue();
    String path = cookie.getPath();
    String domain = cookie.getDomain();
    String comment = cookie.getComment();

    if (version == 0) {
        // Check for the things that require a v1 cookie
        if (needsQuotes(value, 0) || comment != null || needsQuotes(path, 0) || needsQuotes(domain, 0)) {
            version = 1;
        }
    }

    // Now build the cookie header
    StringBuffer buf = new StringBuffer(); // can't use StringBuilder due to DateFormat

    // Just use the name supplied in the Cookie
    buf.append(cookie.getName());
    buf.append("=");

    // Value
    maybeQuote(buf, value, version);

    // Add version 1 specific information
    if (version == 1) {
        // Version=1 ... required
        buf.append ("; Version=1");

        // Comment=comment
        if (comment != null) {
            buf.append ("; Comment=");
            maybeQuote(buf, comment, version);
        }
    }

    // Add domain information, if present
    if (domain != null) {
        buf.append("; Domain=");
        maybeQuote(buf, domain, version);
    }

    // Max-Age=secs ... or use old "Expires" format
    int maxAge = cookie.getMaxAge();
    if (maxAge >= 0) {
        if (version > 0) {
            buf.append ("; Max-Age=");
            buf.append (maxAge);
        }
        // IE6, IE7 and possibly other browsers don't understand Max-Age.
        // They do understand Expires, even with V1 cookies!
        if (version == 0 || getAlwaysAddExpires()) {
            // Wdy, DD-Mon-YY HH:MM:SS GMT ( Expires Netscape format )
            buf.append ("; Expires=");
            // To expire immediately we need to set the time in past
            if (maxAge == 0) {
                buf.append( ANCIENT_DATE );
            } else {
                COOKIE_DATE_FORMAT.get().format(
                        new Date(System.currentTimeMillis() + maxAge * 1000L),
                        buf,
                        new FieldPosition(0));
            }
        }
    }

    // Path=path
    if (path!=null) {
        buf.append ("; Path=");
        maybeQuote(buf, path, version);
    }

    // Secure
    if (cookie.getSecure()) {
      buf.append ("; Secure");
    }

    // HttpOnly
    if (cookie.isHttpOnly()) {
        buf.append("; HttpOnly");
    }

    SameSiteCookies sameSiteCookiesValue = getSameSiteCookies();

    if (!sameSiteCookiesValue.equals(SameSiteCookies.UNSET)) {
        buf.append("; SameSite=");
        buf.append(sameSiteCookiesValue.getValue());
    }

    return buf.toString();
}
 
Example 13
Source File: RequestUtil.java    From openbd-core with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Encode a cookie as per RFC 2109. The resulting string can be used as the value for a <code>Set-Cookie</code> header.
 * 
 * @param cookie
 *          The cookie to encode.
 * @return A string following RFC 2109.
 */
public static String encodeCookie(Cookie cookie) {

	StringBuilder buf = new StringBuilder(cookie.getName());
	buf.append("=");
	buf.append(cookie.getValue());

	if (cookie.getComment() != null) {
		buf.append("; Comment=\"");
		buf.append(cookie.getComment());
		buf.append("\"");
	}

	if (cookie.getDomain() != null) {
		buf.append("; Domain=\"");
		buf.append(cookie.getDomain());
		buf.append("\"");
	}

	long age = cookie.getMaxAge();
	if (cookie.getMaxAge() >= 0) {
		buf.append("; Max-Age=\"");
		buf.append(age);
		buf.append("\"");
	}

	if (cookie.getPath() != null) {
		buf.append("; Path=\"");
		buf.append(cookie.getPath());
		buf.append("\"");
	}

	if (cookie.getSecure()) {
		buf.append("; Secure");
	}

	if (cookie.getVersion() > 0) {
		buf.append("; Version=\"");
		buf.append(cookie.getVersion());
		buf.append("\"");
	}

	return (buf.toString());
}
 
Example 14
Source File: RequestUtil.java    From olat with Apache License 2.0 4 votes vote down vote up
/**
 * Encode a cookie as per RFC 2109. The resulting string can be used as the value for a <code>Set-Cookie</code> header.
 * 
 * @param cookie
 *            The cookie to encode.
 * @return A string following RFC 2109.
 */
public static String encodeCookie(Cookie cookie) {

    StringBuilder buf = new StringBuilder(cookie.getName());
    buf.append("=");
    buf.append(cookie.getValue());

    if (cookie.getComment() != null) {
        buf.append("; Comment=\"");
        buf.append(cookie.getComment());
        buf.append("\"");
    }

    if (cookie.getDomain() != null) {
        buf.append("; Domain=\"");
        buf.append(cookie.getDomain());
        buf.append("\"");
    }

    if (cookie.getMaxAge() >= 0) {
        buf.append("; Max-Age=\"");
        buf.append(cookie.getMaxAge());
        buf.append("\"");
    }

    if (cookie.getPath() != null) {
        buf.append("; Path=\"");
        buf.append(cookie.getPath());
        buf.append("\"");
    }

    if (cookie.getSecure()) {
        buf.append("; Secure");
    }

    if (cookie.getVersion() > 0) {
        buf.append("; Version=\"");
        buf.append(cookie.getVersion());
        buf.append("\"");
    }

    return (buf.toString());
}
 
Example 15
Source File: RequestUtil.java    From olat with Apache License 2.0 4 votes vote down vote up
/**
 * Encode a cookie as per RFC 2109. The resulting string can be used as the value for a <code>Set-Cookie</code> header.
 * 
 * @param cookie
 *            The cookie to encode.
 * @return A string following RFC 2109.
 */
public static String encodeCookie(Cookie cookie) {

    StringBuilder buf = new StringBuilder(cookie.getName());
    buf.append("=");
    buf.append(cookie.getValue());

    if (cookie.getComment() != null) {
        buf.append("; Comment=\"");
        buf.append(cookie.getComment());
        buf.append("\"");
    }

    if (cookie.getDomain() != null) {
        buf.append("; Domain=\"");
        buf.append(cookie.getDomain());
        buf.append("\"");
    }

    if (cookie.getMaxAge() >= 0) {
        buf.append("; Max-Age=\"");
        buf.append(cookie.getMaxAge());
        buf.append("\"");
    }

    if (cookie.getPath() != null) {
        buf.append("; Path=\"");
        buf.append(cookie.getPath());
        buf.append("\"");
    }

    if (cookie.getSecure()) {
        buf.append("; Secure");
    }

    if (cookie.getVersion() > 0) {
        buf.append("; Version=\"");
        buf.append(cookie.getVersion());
        buf.append("\"");
    }

    return (buf.toString());
}
 
Example 16
Source File: UserFilter.java    From projectforge-webapp with GNU General Public License v3.0 4 votes vote down vote up
/**
 * User is not logged. Checks a stay-logged-in-cookie.
 * @return user if valid cookie found, otherwise null.
 */
private PFUserDO checkStayLoggedIn(final HttpServletRequest request, final HttpServletResponse response)
{
  final Cookie sessionIdCookie = getCookie(request, "JSESSIONID");
  if (sessionIdCookie != null && sessionIdCookie.getSecure() == false && request.isSecure() == true) {
    // Hack for developers: Safari (may-be also other browsers) don't update unsecure cookies for secure connections. This seems to be
    // occurring
    // if you use ProjectForge on localhost with http and https (e. g. for testing). You have to delete this cookie normally in your
    // browser.
    final Cookie cookie = new Cookie("JSESSIONID", "to be deleted");
    cookie.setMaxAge(0);
    cookie.setPath(sessionIdCookie.getPath()); // Doesn't work for Safari: getPath() returns always null!
    response.addCookie(cookie);
  }
  final Cookie stayLoggedInCookie = getStayLoggedInCookie(request);
  if (stayLoggedInCookie != null) {
    final String value = stayLoggedInCookie.getValue();
    if (StringUtils.isBlank(value) == true) {
      return null;
    }
    final String[] values = value.split(":");
    if (values == null || values.length != 3) {
      log.warn("Invalid cookie found: " + value);
      return null;
    }
    final Integer userId = NumberHelper.parseInteger(values[0]);
    final PFUserDO user = userDao.internalGetById(userId);
    if (user == null) {
      log.warn("Invalid cookie found (user not found): " + value);
      return null;
    }
    if (user.getUsername().equals(values[1]) == false) {
      log.warn("Invalid cookie found (user name wrong, maybe changed): " + value);
      return null;
    }
    if (values[2] == null || values[2].equals(user.getStayLoggedInKey()) == false) {
      log.warn("Invalid cookie found (stay-logged-in key, maybe renewed and/or user password changed): " + value);
      return null;
    }
    if (Login.getInstance().checkStayLoggedIn(user) == false) {
      log.warn("Stay-logged-in wasn't accepted by the login handler: " + user.getUserDisplayname());
      return null;
    }
    addStayLoggedInCookie(request, response, stayLoggedInCookie);
    log.info("User successfully logged in using stay-logged-in method: " + user.getUserDisplayname());
    return user;
  }
  return null;
}