<commit_before>/*
 * Zed Attack Proxy (ZAP) and its related class files.
 * 
 * ZAP is an HTTP/HTTPS proxy for assessing web application security.
 * 
 * Licensed 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.zaproxy.zap.extension.websocket.db;

import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;

import org.apache.commons.collections.map.LRUMap;
import org.apache.log4j.Logger;
import org.hsqldb.jdbc.JDBCBlob;
import org.hsqldb.jdbc.JDBCClob;
import org.parosproxy.paros.db.DatabaseException;
import org.parosproxy.paros.db.DbUtils;
import org.parosproxy.paros.db.paros.ParosAbstractTable;
import org.parosproxy.paros.network.HttpMalformedHeaderException;
import org.zaproxy.zap.extension.websocket.WebSocketChannelDTO;
import org.zaproxy.zap.extension.websocket.WebSocketMessage;
import org.zaproxy.zap.extension.websocket.WebSocketMessageDTO;

/**
 * Manages writing and reading WebSocket messages to the database.
 */
public class TableWebSocket extends ParosAbstractTable {
	private static final Logger logger = Logger.getLogger(TableWebSocket.class);
	
	private Set<Integer> channelIds;
	private LRUMap channelCache;
    
    private PreparedStatement psInsertMessage;
    
	private PreparedStatement psSelectChannels;
	
    private PreparedStatement psInsertChannel;
	private PreparedStatement psUpdateChannel;
	
	private PreparedStatement psUpdateHistoryFk;

	private PreparedStatement psDeleteChannel;
	private PreparedStatement psDeleteMessagesByChannelId;

	private PreparedStatement psInsertFuzz;
	
	private PreparedStatement psSelectMessage;
	
	private PreparedStatement psSelectMaxChannelId;

	private Queue<WebSocketMessageDTO> messagesBuffer = new LinkedList<>();
	private Queue<WebSocketChannelDTO> channelsBuffer = new LinkedList<>();
	
    /**
     * Create tables if not already available
     */
    @Override
    protected void reconnect(Connection conn) throws DatabaseException {
    	try {
			if (!DbUtils.hasTable(conn, "WEBSOCKET_CHANNEL")) {
				// need to create the tables			
				PreparedStatement stmt = conn
						.prepareStatement("CREATE CACHED TABLE websocket_channel ("
								+ "channel_id BIGINT PRIMARY KEY,"
								+ "host VARCHAR(255) NOT NULL,"
								+ "port INTEGER NOT NULL,"
								+ "url VARCHAR(255) NOT NULL,"
								+ "start_timestamp TIMESTAMP NOT NULL,"
								+ "end_timestamp TIMESTAMP NULL,"
								+ "history_id INTEGER NULL,"
								+ "FOREIGN KEY (history_id) REFERENCES HISTORY(HISTORYID) ON DELETE SET NULL ON UPDATE SET NULL"
								+ ")");
				DbUtils.executeAndClose(stmt);
				
				stmt = conn.prepareStatement("CREATE CACHED TABLE websocket_message ("
								+ "message_id BIGINT NOT NULL,"
								+ "channel_id BIGINT NOT NULL,"
								+ "timestamp TIMESTAMP NOT NULL,"
								+ "opcode TINYINT NOT NULL,"
								+ "payload_utf8 CLOB(16M) NULL,"
								+ "payload_bytes BLOB(16M) NULL,"
								+ "payload_length BIGINT NOT NULL,"
								+ "is_outgoing BOOLEAN NOT NULL,"
								+ "PRIMARY KEY (message_id, channel_id),"
								+ "FOREIGN KEY (channel_id) REFERENCES websocket_channel(channel_id)"<commit_msg>signalr connections can use way longer URLs, especially if bearer tokens are present<commit_after>/*
 * Zed Attack Proxy (ZAP) and its related class files.
 * 
 * ZAP is an HTTP/HTTPS proxy for assessing web application security.
 * 
 * Licensed 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.zaproxy.zap.extension.websocket.db;

import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;

import org.apache.commons.collections.map.LRUMap;
import org.apache.log4j.Logger;
import org.hsqldb.jdbc.JDBCBlob;
import org.hsqldb.jdbc.JDBCClob;
import org.parosproxy.paros.db.DatabaseException;
import org.parosproxy.paros.db.DbUtils;
import org.parosproxy.paros.db.paros.ParosAbstractTable;
import org.parosproxy.paros.network.HttpMalformedHeaderException;
import org.zaproxy.zap.extension.websocket.WebSocketChannelDTO;
import org.zaproxy.zap.extension.websocket.WebSocketMessage;
import org.zaproxy.zap.extension.websocket.WebSocketMessageDTO;

/**
 * Manages writing and reading WebSocket messages to the database.
 */
public class TableWebSocket extends ParosAbstractTable {
	private static final Logger logger = Logger.getLogger(TableWebSocket.class);
	
	private Set<Integer> channelIds;
	private LRUMap channelCache;
    
    private PreparedStatement psInsertMessage;
    
	private PreparedStatement psSelectChannels;
	
    private PreparedStatement psInsertChannel;
	private PreparedStatement psUpdateChannel;
	
	private PreparedStatement psUpdateHistoryFk;

	private PreparedStatement psDeleteChannel;
	private PreparedStatement psDeleteMessagesByChannelId;

	private PreparedStatement psInsertFuzz;
	
	private PreparedStatement psSelectMessage;
	
	private PreparedStatement psSelectMaxChannelId;

	private Queue<WebSocketMessageDTO> messagesBuffer = new LinkedList<>();
	private Queue<WebSocketChannelDTO> channelsBuffer = new LinkedList<>();
	
    /**
     * Create tables if not already available
     */
    @Override
    protected void reconnect(Connection conn) throws DatabaseException {
    	try {
			if (!DbUtils.hasTable(conn, "WEBSOCKET_CHANNEL")) {
				// need to create the tables			
				PreparedStatement stmt = conn
						.prepareStatement("CREATE CACHED TABLE websocket_channel ("
								+ "channel_id BIGINT PRIMARY KEY,"
								+ "host VARCHAR(255) NOT NULL,"
								+ "port INTEGER NOT NULL,"
								+ "url VARCHAR(2048) NOT NULL,"
								+ "start_timestamp TIMESTAMP NOT NULL,"
								+ "end_timestamp TIMESTAMP NULL,"
								+ "history_id INTEGER NULL,"
								+ "FOREIGN KEY (history_id) REFERENCES HISTORY(HISTORYID) ON DELETE SET NULL ON UPDATE SET NULL"
								+ ")");
				DbUtils.executeAndClose(stmt);
				
				stmt = conn.prepareStatement("CREATE CACHED TABLE websocket_message ("
								+ "message_id BIGINT NOT NULL,"
								+ "channel_id BIGINT NOT NULL,"
								+ "timestamp TIMESTAMP NOT NULL,"
								+ "opcode TINYINT NOT NULL,"
								+ "payload_utf8 CLOB(16M) NULL,"
								+ "payload_bytes BLOB(16M) NULL,"
								+ "payload_length BIGINT NOT NULL,"
								+ "is_outgoing BOOLEAN NOT NULL,"
								+ "PRIMARY KEY (message_id, channel_id),"
								+ "FOREIGN KEY (channel_id) REFERENCES websocket_channel(channel_id)"
{'fraction_non_alphanumeric': 0.0845440881763527, 'fraction_numerical': 0.004133266533066132, 'mean_word_length': 4.006269592476489, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4152846', 'n_tokens_mistral': 2720, 'n_tokens_neox': 2298, 'n_words': 673}