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

org.parosproxy.paros.model.HistoryReference Maven / Gradle / Ivy

Go to download

The Zed Attack Proxy (ZAP) is an easy to use integrated penetration testing tool for finding vulnerabilities in web applications. It is designed to be used by people with a wide range of security experience and as such is ideal for developers and functional testers who are new to penetration testing. ZAP provides automated scanners as well as a set of tools that allow you to find security vulnerabilities manually.

The newest version!
/*
 *
 * Paros and its related class files.
 *
 * Paros is an HTTP/HTTPS proxy for assessing web application security.
 * Copyright (C) 2003-2004 Chinotec Technologies Company
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the Clarified Artistic License
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * Clarified Artistic License for more details.
 *
 * You should have received a copy of the Clarified Artistic License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
// ZAP: 2011/07/23 Added TYPE_FUZZER
// ZAP: 2011/12/04 Support deleting alerts
// ZAP: 2012/03/15 Changed the method getDisplay to use the class StringBuilder
//      instead of StringBuffer.
// ZAP: 2012/04/23 Added @Override annotation to the appropriate method.
// ZAP: 2012/05/28 Added some JavaDoc
// ZAP: 2012/06/13 Optimized alerts related code
// ZAP: 2012/08/07 Deleted some not used Spider Related constants
// ZAP: 2012/10/08 Issue 391: Performance improvements
// ZAP: 2012/02/26 Cache the response body length as part of Issue 539
// ZAP: 2013/08/07 Added TYPE_AUTHENTICATION
// ZAP: 2013/11/16 Issue 869: Differentiate proxied requests from (ZAP) user requests
// ZAP: 2013/11/16 Issue 892: Cache of response body length in HistoryReference might not be correct
// ZAP: 2014/04/10 Changed to use HttpMessageCachedData and expose the cached data
// ZAP: 2014/04/10 Issue 1042: Having significant issues opening a previous session
// ZAP: 2014/05/23 Issue 1209: Reliability becomes Confidence and add levels
// ZAP: 2014/06/10 Added TYPE_ACCESS_CONTROL
// ZAP: 2014/06/16 Issue 990: Allow to delete alerts through the API
// ZAP: 2014/08/14 Issue 1311: Differentiate temporary internal messages from temporary scanner
// messages
// ZAP: 2014/12/11 Update the flag webSocketUpgrade sooner to avoid re-reading the message from
// database
// ZAP: 2015/02/09 Issue 1525: Introduce a database interface layer to allow for alternative
// implementations
// ZAP: 2016/04/12 Update the SiteNode when deleting alerts
// ZAP: 2016/05/27 Moved the temporary types to this class
// ZAP: 2016/05/30 Add new type for CONNECT requests received by the proxy
// ZAP: 2016/06/15 Add TYPE_SEQUENCE_TEMPORARY
// ZAP: 2016/06/20 Add TYPE_ZEST_SCRIPT and deprecate TYPE_RESERVED_11
// ZAP: 2016/08/30 Use a Set instead of a List for the alerts
// ZAP: 2017/02/07 Add TYPE_SPIDER_AJAX_TEMPORARY.
// ZAP: 2017/03/19 Add TYPE_SPIDER_TEMPORARY.
// ZAP: 2017/05/03 Notify tag changes.
// ZAP: 2017/05/17 Allow to obtain the tags of a message.
// ZAP: 2017/05/31 Add a multi-catch for a specific handler.
// ZAP: 2017/06/08 Allow to keep the HttpMessage in memory for immediate reuse.
// ZAP: 2017/06/13 Notify when a note is set.
// ZAP: 2017/07/04 Notify when a HistoryReference is deleted.
// ZAP: 2017/08/18 Add TYPE_FUZZER_TEMPORARY.
// ZAP: 2018/02/14 Remove unnecessary boxing / unboxing
// ZAP: 2019/01/09 Add TYPE_CALLBACK.
// ZAP: 2019/06/01 Normalise line endings.
// ZAP: 2019/06/05 Normalise format/style.
// ZAP: 2020/11/26 Use Log4j 2 classes for logging.
// ZAP: 2021/07/07 Add TYPE_OAST.
// ZAP: 2022/02/28 Remove code deprecated in 2.6.0
// ZAP: 2022/06/27 Add TYPE_PARAM_DIGGER.
// ZAP: 2022/09/21 Use format specifiers instead of concatenation when logging.
// ZAP: 2023/01/10 Tidy up logger.
package org.parosproxy.paros.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import org.apache.commons.httpclient.URI;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.parosproxy.paros.core.scanner.Alert;
import org.parosproxy.paros.db.DatabaseException;
import org.parosproxy.paros.db.RecordAlert;
import org.parosproxy.paros.db.RecordHistory;
import org.parosproxy.paros.db.RecordTag;
import org.parosproxy.paros.db.TableAlert;
import org.parosproxy.paros.db.TableHistory;
import org.parosproxy.paros.db.TableTag;
import org.parosproxy.paros.network.HttpMalformedHeaderException;
import org.parosproxy.paros.network.HttpMessage;
import org.zaproxy.zap.ZAP;
import org.zaproxy.zap.eventBus.Event;
import org.zaproxy.zap.model.Target;

/**
 * This class abstracts a reference to a http message stored in database. It reads the whole http
 * message from database when getHttpMessage() is called.
 */
public class HistoryReference {

    /** Temporary type = not retrieved from history. To be deleted. */
    public static final int TYPE_TEMPORARY = 0;

    /**
     * @deprecated Use {@link #TYPE_PROXIED} instead.
     * @see #TYPE_ZAP_USER
     */
    @Deprecated public static final int TYPE_MANUAL = 1;

    /** A HTTP message that was proxied through ZAP. */
    public static final int TYPE_PROXIED = 1;

    /**
     * A HTTP message sent by the user from within ZAP, for example, using "Manual Request Editor"
     * or "Resend" dialogues.
     */
    public static final int TYPE_ZAP_USER = 15;

    public static final int TYPE_SPIDER = 2;
    public static final int TYPE_SCANNER = 3;
    public static final int TYPE_HIDDEN = 6;
    // ZAP: Added TYPE_BRUTE_FORCE
    public static final int TYPE_BRUTE_FORCE = 7;

    /**
     * A HTTP message sent by the fuzzer.
     *
     * 

Used for fuzzer messages that have an {@link Alert}, which outlive the fuzzing sessions. * * @since 1.4.0 * @see #TYPE_FUZZER_TEMPORARY */ public static final int TYPE_FUZZER = 8; /** * A (temporary) HTTP message of the spider. * *

The type is used to off-load the messages (of resources found but not yet fetched) from * the memory. * * @since 2.0.0 * @see #TYPE_SPIDER * @see #TYPE_SPIDER_TEMPORARY * @see #DEFAULT_TEMPORARY_HISTORY_TYPES */ public static final int TYPE_SPIDER_TASK = 9; /** * A HTTP message sent by the AJAX Spider. * * @since 2.0.0 * @see #TYPE_SPIDER_AJAX_TEMPORARY */ public static final int TYPE_SPIDER_AJAX = 10; /** * A (temporary) HTTP message that (attempts to) authenticates a {@link * org.zaproxy.zap.users.User User}. * * @since 2.4.0 * @see #DEFAULT_TEMPORARY_HISTORY_TYPES */ public static final int TYPE_AUTHENTICATION = 11; // ZAP: Added TYPE_ACCESS_CONTROL for use in access control testing methods public static final int TYPE_ACCESS_CONTROL = 13; /** * A HTTP message sent by a Zest script. * *

Not all HTTP messages sent by Zest scripts will have this type, some might use the type(s) * of the underlying component (for example, Zest Active Rules will use the types of the active * scanner, {@link #TYPE_SCANNER_TEMPORARY} or {@link #TYPE_SCANNER}). * * @since 2.6.0 */ public static final int TYPE_ZEST_SCRIPT = 12; /** * A (temporary) HTTP message sent by the (active) scanner. * * @since 2.4.0 * @see #DEFAULT_TEMPORARY_HISTORY_TYPES */ public static final int TYPE_SCANNER_TEMPORARY = 14; /** * The {@code Set} of temporary history types. * * @see #addTemporaryType(int) * @see #getTemporaryTypes() * @see #DEFAULT_TEMPORARY_HISTORY_TYPES */ private static final Set TEMPORARY_HISTORY_TYPES = new HashSet<>(); /** * The {@code Set} with default temporary history types: * *

    *
  • {@link #TYPE_TEMPORARY}; *
  • {@link #TYPE_SCANNER_TEMPORARY}; *
  • {@link #TYPE_AUTHENTICATION}; *
  • {@link #TYPE_SPIDER_TASK}; *
  • {@link #TYPE_SEQUENCE_TEMPORARY}; *
  • {@link #TYPE_SPIDER_AJAX_TEMPORARY}; *
  • {@link #TYPE_SPIDER_TEMPORARY}; *
  • {@link #TYPE_FUZZER_TEMPORARY}; *
* *

Persisted messages with temporary types are deleted when the session is closed. * *

Note: This set does not allow modifications, any attempt to modify it * will result in an {@code UnsupportedOperationException}. * * @since 2.5.0 * @see #getTemporaryTypes() */ public static final Set DEFAULT_TEMPORARY_HISTORY_TYPES; /** * A HTTP CONNECT request received (and processed) by the local proxy. * * @since 2.5.0 */ public static final int TYPE_PROXY_CONNECT = 16; /** * A (temporary) HTTP message created/used when active scanning sequences. * * @since 2.6.0 * @see #DEFAULT_TEMPORARY_HISTORY_TYPES */ public static final int TYPE_SEQUENCE_TEMPORARY = 17; /** * A (temporary) HTTP message of the AJAX spider. * *

Normally a message that was not processed (i.e. not on spider scope). * * @since 2.6.0 * @see #TYPE_SPIDER_AJAX * @see #DEFAULT_TEMPORARY_HISTORY_TYPES */ public static final int TYPE_SPIDER_AJAX_TEMPORARY = 18; /** * A (temporary) HTTP message of the spider. * *

Normally a message that was not processed (i.e. not successfully sent to the server). * * @since 2.6.0 * @see #TYPE_SPIDER * @see #TYPE_SPIDER_TASK * @see #DEFAULT_TEMPORARY_HISTORY_TYPES */ public static final int TYPE_SPIDER_TEMPORARY = 19; /** * A (temporary) HTTP message sent by the fuzzer. * * @since 2.7.0 * @see #TYPE_FUZZER * @see #DEFAULT_TEMPORARY_HISTORY_TYPES */ public static final int TYPE_FUZZER_TEMPORARY = 20; /** * A HTTP message received by the callback handler. * * @since 2.8.0 */ public static final int TYPE_CALLBACK = 21; /** * An HTTP message received by an OAST server that is relayed to ZAP. * * @since 2.11.0 */ public static final int TYPE_OAST = 22; /** * An HTTP message sent by the param digger. * * @since 2.12.0 */ public static final int TYPE_PARAM_DIGGER = 23; private static java.text.DecimalFormat decimalFormat = new java.text.DecimalFormat("##0.###"); private static TableHistory staticTableHistory = null; // ZAP: Support for multiple tags private static TableTag staticTableTag = null; // ZAP: Support for loading alerts from db private static TableAlert staticTableAlert = null; static { Set defaultHistoryTypes = new HashSet<>(); defaultHistoryTypes.add(HistoryReference.TYPE_TEMPORARY); defaultHistoryTypes.add(HistoryReference.TYPE_SCANNER_TEMPORARY); defaultHistoryTypes.add(HistoryReference.TYPE_AUTHENTICATION); defaultHistoryTypes.add(HistoryReference.TYPE_SPIDER_TASK); defaultHistoryTypes.add(HistoryReference.TYPE_SEQUENCE_TEMPORARY); defaultHistoryTypes.add(HistoryReference.TYPE_SPIDER_AJAX_TEMPORARY); defaultHistoryTypes.add(HistoryReference.TYPE_SPIDER_TEMPORARY); defaultHistoryTypes.add(HistoryReference.TYPE_FUZZER_TEMPORARY); DEFAULT_TEMPORARY_HISTORY_TYPES = Collections.unmodifiableSet(defaultHistoryTypes); TEMPORARY_HISTORY_TYPES.addAll(DEFAULT_TEMPORARY_HISTORY_TYPES); } private int historyId = 0; private int historyType = TYPE_PROXIED; private SiteNode siteNode = null; private String display = null; private long sessionId = 0; // ZAP: Support for specific icons private ArrayList icons = null; private ArrayList clearIfManual = null; // ZAP: Support for linking Alerts to Hrefs private Set alerts; private List tags = new ArrayList<>(); private boolean webSocketUpgrade; private static final Logger LOGGER = LogManager.getLogger(HistoryReference.class); private HttpMessage httpMessage; private HttpMessageCachedData httpMessageCachedData; /** * @return Returns the sessionId. */ public long getSessionId() { return sessionId; } public HistoryReference(int historyId) throws HttpMalformedHeaderException, DatabaseException { this(historyId, false); } /** * Constructs a {@code HistoryReference} with the given ID and whether or not the {@code * HttpMessage} read from the database should be kept in memory. * *

Note: This constructor should be used with care as the {@code * HttpMessage} might be kept in memory (until this instance is garbage collected or {@link * #clearHttpMessage() manually cleared}). It should be used only when the contents of the * {@code HttpMessage} are used immediately after creating the {@code HistoryReference}, * avoiding reading the {@code HttpMessage} once again. * * @param historyId the ID of the message persisted to database * @param keepMessage {@code true} if the {@code HttpMessage} should be kept in memory, {@code * false} otherwise. * @throws HttpMalformedHeaderException if an error occurred while parsing the message. * @throws DatabaseException if an error occurred while reading the message. * @since 2.7.0 * @see #getHttpMessage() */ public HistoryReference(int historyId, boolean keepMessage) throws HttpMalformedHeaderException, DatabaseException { RecordHistory history = null; this.icons = new ArrayList<>(); this.clearIfManual = new ArrayList<>(); history = staticTableHistory.read(historyId); if (history == null) { throw new HttpMalformedHeaderException(); } HttpMessage msg = history.getHttpMessage(); // ZAP: Support for multiple tags this.tags = getTags(historyId); build(history.getSessionId(), history.getHistoryId(), history.getHistoryType(), msg); if (keepMessage) { httpMessage = msg; } } public HistoryReference(Session session, int historyType, HttpMessage msg) throws HttpMalformedHeaderException, DatabaseException { RecordHistory history = null; this.icons = new ArrayList<>(); this.clearIfManual = new ArrayList<>(); history = staticTableHistory.write(session.getSessionId(), historyType, msg); build(session.getSessionId(), history.getHistoryId(), history.getHistoryType(), msg); // ZAP: Init HttpMessage HistoryReference field msg.setHistoryRef(this); this.tags = getTags(historyId); // ZAP: Support for loading the alerts from the db List alerts = staticTableAlert.getAlertsBySourceHistoryId(historyId); for (RecordAlert alert : alerts) { this.addAlert(new Alert(alert, this)); } } /** * @return whether the icon has to be cleaned when being manually visited or not. */ public ArrayList getClearIfManual() { return this.clearIfManual; } /** * @return The icon's string path (i.e. /resource/icon/16/xx.png) */ public ArrayList getCustomIcons() { return this.icons; } /** * @param i the icon's URL (i.e. /resource/icon/16/xx.png) * @param c if the icon has to be cleaned when the node is manually visited */ public void setCustomIcon(String i, boolean c) { this.icons.add(i); this.clearIfManual.add(c); } private void build(long sessionId, int historyId, int historyType, HttpMessage msg) { this.sessionId = sessionId; this.historyId = historyId; this.historyType = historyType; this.webSocketUpgrade = msg.isWebSocketUpgrade(); if (historyType == TYPE_PROXIED || historyType == TYPE_ZAP_USER) { this.display = getDisplay(msg); } // ZAP: Init HttpMessage HistoryReference field msg.setHistoryRef(this); // Cache info commonly used so that we dont need to keep reading the HttpMessage from the // db. httpMessageCachedData = new HttpMessageCachedData(msg); } public static void setTableHistory(TableHistory tableHistory) { staticTableHistory = tableHistory; } public static void setTableTag(TableTag tableTag) { staticTableTag = tableTag; } public static void setTableAlert(TableAlert tableAlert) { staticTableAlert = tableAlert; } /** * @return Returns the historyId. */ public int getHistoryId() { return historyId; } /** * Gets the corresponding http message from the database. Try to minimise calls to this method * as much as possible. But also dont cache the HttpMessage either as this can significantly * increase ZAP's memory usage. * * @return the http message * @throws HttpMalformedHeaderException the http malformed header exception * @throws DatabaseException if an error occurred while reading the HTTP message. */ public HttpMessage getHttpMessage() throws HttpMalformedHeaderException, DatabaseException { if (httpMessage != null) { return httpMessage; } // fetch complete message RecordHistory history = staticTableHistory.read(historyId); if (history == null) { throw new HttpMalformedHeaderException( "No history reference for id " + historyId + " type=" + historyType); } // ZAP: Init HttpMessage HistoryReference field history.getHttpMessage().setHistoryRef(this); return history.getHttpMessage(); } /** * Clears the {@code HttpMessage} kept in memory. * * @since 2.7.0 * @see #HistoryReference(int, boolean) */ public void clearHttpMessage() { httpMessage = null; } public URI getURI() { return httpMessageCachedData.getUri(); } @Override public String toString() { if (display != null) { return display; } HttpMessage msg = null; try { msg = getHttpMessage(); display = getDisplay(msg); } catch (HttpMalformedHeaderException | DatabaseException e1) { display = ""; } return display; } /** * @return Returns the historyType. */ public int getHistoryType() { return historyType; } /** * Delete this HistoryReference from database This should typically only be called via the * ExtensionHistory.delete(href) method */ public void delete() { if (historyId > 0) { try { // ZAP: Support for multiple tags staticTableTag.deleteTagsForHistoryID(historyId); staticTableHistory.delete(historyId); notifyEvent(HistoryReferenceEventPublisher.EVENT_REMOVED); } catch (DatabaseException e) { LOGGER.error(e.getMessage(), e); } } } /** * @return Returns the siteNode. */ public SiteNode getSiteNode() { return siteNode; } /** * @param siteNode The siteNode to set. */ public void setSiteNode(SiteNode siteNode) { this.siteNode = siteNode; } private String getDisplay(HttpMessage msg) { StringBuilder sb = new StringBuilder(Integer.toString(historyId)); sb.append(' '); sb.append(msg.getRequestHeader().getPrimeHeader()); if (!msg.getResponseHeader().isEmpty()) { sb.append(" \t=> ").append(msg.getResponseHeader().getPrimeHeader()); sb.append("\t [") .append(decimalFormat.format(msg.getTimeElapsedMillis() / 1000.0)) .append(" s]"); } return sb.toString(); } // ZAP: Support for multiple tags public void addTag(String tag) { if (insertTagDb(tag)) { this.tags.add(tag); notifyEvent(HistoryReferenceEventPublisher.EVENT_TAG_ADDED); } } private boolean insertTagDb(String tag) { try { staticTableTag.insert(historyId, tag); return true; } catch (DatabaseException e) { LOGGER.error("Failed to persist tag: {}", e.getMessage(), e); } return false; } private void notifyEvent(String event) { Map map = new HashMap<>(); map.put( HistoryReferenceEventPublisher.FIELD_HISTORY_REFERENCE_ID, Integer.toString(historyId)); ZAP.getEventBus() .publishSyncEvent( HistoryReferenceEventPublisher.getPublisher(), new Event( HistoryReferenceEventPublisher.getPublisher(), event, new Target(getSiteNode()), map)); } public void deleteTag(String tag) { if (deleteTagDb(tag)) { this.tags.remove(tag); notifyEvent(HistoryReferenceEventPublisher.EVENT_TAG_REMOVED); } } private boolean deleteTagDb(String tag) { try { staticTableTag.delete(historyId, tag); return true; } catch (DatabaseException e) { LOGGER.error("Failed to delete tag: {}", e.getMessage(), e); } return false; } public List getTags() { return this.tags; } // ZAP: Added setNote method to HistoryReference public void setNote(String note) { try { staticTableHistory.updateNote(historyId, note); httpMessageCachedData.setNote(note != null && note.length() > 0); notifyEvent(HistoryReferenceEventPublisher.EVENT_NOTE_SET); } catch (DatabaseException e) { LOGGER.error(e.getMessage(), e); } } public void loadAlerts() { // ZAP: Support for loading the alerts from the db List alerts; try { alerts = staticTableAlert.getAlertsBySourceHistoryId(historyId); for (RecordAlert alert : alerts) { this.addAlert(new Alert(alert, this)); } } catch (DatabaseException e) { LOGGER.error(e.getMessage(), e); } } public synchronized boolean addAlert(Alert alert) { // If this is the first alert if (alerts == null) { alerts = new HashSet<>(); } boolean added = false; if (alerts.add(alert)) { alert.setHistoryRef(this); added = true; } // Try to add to the SiteHNode anyway - that will also check if its already added if (this.siteNode != null) { siteNode.addAlert(alert); } return added; } public synchronized void updateAlert(Alert alert) { // If there are no alerts yet if (alerts == null) { return; } for (Alert a : alerts) { if (a.getAlertId() == alert.getAlertId()) { // Have to use the alertId instead of 'equals' as any of the // other params might have changed this.alerts.remove(a); this.alerts.add(alert); if (this.siteNode != null) { siteNode.updateAlert(alert); } return; } } } public synchronized void deleteAlert(Alert alert) { if (alerts != null) { alerts.remove(alert); if (siteNode != null) { siteNode.deleteAlert(alert); } } } public synchronized void deleteAllAlerts() { if (alerts != null) { alerts.clear(); } } /** * Tells whether or not this history reference has the given alert. * * @param alert the alert to check * @return {@code true} if it has the given alert, {@code false} otherwise. * @since 2.6.0 * @see #hasAlerts() * @see #addAlert(Alert) */ public synchronized boolean hasAlert(Alert alert) { if (alerts == null) { return false; } return alerts.contains(alert); } /** * Tells whether or not this history reference has alerts. * * @return {@code true} if it has alerts, {@code false} otherwise. * @since 2.6.0 * @see #hasAlert(Alert) * @see #addAlert(Alert) */ public synchronized boolean hasAlerts() { if (alerts == null) { return false; } return !alerts.isEmpty(); } public int getHighestAlert() { int i = -1; // If there are no alerts if (alerts == null) return i; for (Alert a : alerts) { if (a.getConfidence() != Alert.CONFIDENCE_FALSE_POSITIVE && a.getRisk() > i) { i = a.getRisk(); } } return i; } /** * Gets the alerts. * *

If alerts where never added, an unmodifiable empty list is returned, otherwise it's * returned a copy of the internal collection. * * @return the alerts * @see #addAlert(Alert) * @see #hasAlerts() * @see #hasAlert(Alert) */ public synchronized List getAlerts() { if (alerts == null) { return Collections.emptyList(); } return new ArrayList<>(this.alerts); } public String getMethod() { return httpMessageCachedData.getMethod(); } public int getStatusCode() { return httpMessageCachedData.getStatusCode(); } public String getReason() { return httpMessageCachedData.getReason(); } public int getRtt() { return httpMessageCachedData.getRtt(); } /** * Sets the tags for the HTTP message. * * @param tags the new tags. * @throws IllegalArgumentException if the given parameter is {@code null}. * @since 2.7.0 * @see #addTag(String) * @see #deleteTag(String) */ public void setTags(List tags) { if (tags == null) { throw new IllegalArgumentException("Parameter tags must not be null."); } for (String tag : tags) { if (!this.tags.contains(tag)) { insertTagDb(tag); } } for (String tag : this.tags) { if (!tags.contains(tag)) { deleteTagDb(tag); } } this.tags = new ArrayList<>(tags); notifyEvent(HistoryReferenceEventPublisher.EVENT_TAGS_SET); } /** * Sets the tags for the HTTP message. * * @param tags the new tags. * @throws IllegalArgumentException if the given parameter is {@code null}. * @deprecated (2.7.0) Use {@link #setTags(List)} instead. */ @Deprecated public void setTags(Vector tags) { setTags((List) tags); } public boolean hasNote() { return httpMessageCachedData.hasNote(); } public long getTimeSentMillis() { return httpMessageCachedData.getTimeSentMillis(); } public long getTimeReceivedMillis() { return httpMessageCachedData.getTimeReceivedMillis(); } public boolean isWebSocketUpgrade() { return webSocketUpgrade; } public int getRequestHeaderLength() { return httpMessageCachedData.getRequestHeaderLength(); } public int getRequestBodyLength() { return httpMessageCachedData.getRequestBodyLength(); } public int getResponseHeaderLength() { return httpMessageCachedData.getResponseHeaderLength(); } public int getResponseBodyLength() { return httpMessageCachedData.getResponseBodyLength(); } public String getRequestBody() { String requestBody = httpMessageCachedData.getRequestBody(); if (requestBody == null) { try { requestBody = getHttpMessage().getRequestBody().toString(); httpMessageCachedData.setRequestBody(requestBody); } catch (HttpMalformedHeaderException | DatabaseException e) { LOGGER.error( "Failed to reload request body from database with history ID: {}", historyId, e); requestBody = ""; } } return requestBody; } /** * Adds the given {@code type} to the set of temporary types. * *

Persisted messages with temporary types are deleted when the session is closed. * * @since 2.5.0 * @param type the history type that will be added * @see #removeTemporaryType(int) * @see #getTemporaryTypes() */ public static void addTemporaryType(int type) { synchronized (TEMPORARY_HISTORY_TYPES) { TEMPORARY_HISTORY_TYPES.add(type); } } /** * Removes the given {@code type} from the set of temporary types. * *

Attempting to remove a default temporary type has no effect. * * @since 2.5.0 * @param type the history type that will be removed * @see #DEFAULT_TEMPORARY_HISTORY_TYPES * @see #addTemporaryType(int) * @see #getTemporaryTypes() */ public static void removeTemporaryType(int type) { Integer typeInteger = type; if (DEFAULT_TEMPORARY_HISTORY_TYPES.contains(typeInteger)) { return; } synchronized (TEMPORARY_HISTORY_TYPES) { TEMPORARY_HISTORY_TYPES.remove(typeInteger); } } /** * Gets the temporary history types. * *

Persisted messages with temporary types are deleted when the session is closed. * * @return a {@code Set} with the temporary history types * @see #addTemporaryType(int) * @see #removeTemporaryType(int) */ public static Set getTemporaryTypes() { synchronized (TEMPORARY_HISTORY_TYPES) { return new HashSet<>(TEMPORARY_HISTORY_TYPES); } } /** * Gets the tags of the message with the given history ID. * * @param historyId the history ID. * @return a {@code List} with the tags of the message, never {@code null}. * @throws DatabaseException if an error occurred while obtaining the tags from the database. * @since 2.7.0 */ public static List getTags(int historyId) throws DatabaseException { if (staticTableTag == null) { return new ArrayList<>(); } List tags = new ArrayList<>(); List rtags = staticTableTag.getTagsForHistoryID(historyId); for (RecordTag rtag : rtags) { tags.add(rtag.getTag()); } return tags; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy