Skip to content

Commit

Permalink
Add a Value::WebSocket class
Browse files Browse the repository at this point in the history
  • Loading branch information
AI-Mozi committed Sep 1, 2024
1 parent d862526 commit 513e89e
Show file tree
Hide file tree
Showing 2 changed files with 636 additions and 0 deletions.
252 changes: 252 additions & 0 deletions lib/ronin/recon/values/web_socket.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
# frozen_string_literal: true
#
# ronin-recon - A micro-framework and tool for performing reconnaissance.
#
# Copyright (c) 2023-2024 Hal Brodigan ([email protected])
#
# ronin-recon is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ronin-recon is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with ronin-recon. If not, see <https://www.gnu.org/licenses/>.
#

require_relative '../value'

require 'uri'

module Ronin
module Recon
module Values
#
# Represents a WebSocket.
#
# @api public
#
# @since 0.2.0
#
class WebSocket < Value

# Indicates whether the WebSocket uses `ws://` or `wss://`.
#
# @return ['ws', 'wss']
attr_reader :scheme

# The WebSocket's hostname.
#
# @return [String]
attr_reader :host

# The WebSocket's port number.
#
# @return [Integer]
attr_reader :port

# The WebSocket's path.
#
# @return [String]
attr_reader :path

# The WebSocket's query
#
# @return [String]
attr_reader :query

#
# Initializes the WebSocket value.
#
# @param ['ws', 'wss'] scheme
# Indicates whether the WebSocket uses `ws://` or `wss://`.
#
# @param [String] host
# The WebSocket's host.
#
# @param [Integer] port
# The WebSocket's port.
#
# @param [String] path
# The WebSocket's path.
#
# @param [String] query
# The WebSocket's query.
#
def initialize(scheme,host,port,path=nil,query=nil)
@scheme = scheme
@host = host
@port = port
@path = path
@query = query
end

#
# Initializes the 'ws://' WebSocket.
#
# @param [String] host
# The WebSocket's host.
#
# @param [Integer] port
# The WebSocket's port.
#
# @param [String] path
# The WebSocket's path.
#
# @param [String] query
# The WebSocket's query.
#
def self.ws(host,port=80,path=nil,query=nil)
new('ws',host,port,path,query)
end

#
# Initializes the 'wss://' WebSocket.
#
# @param [String] host
# The WebSocket's host.
#
# @param [Integer] port
# The WebSocket's port.
#
# @param [String] path
# The WebSocket's path.
#
# @param [String] query
# The WebSocket's query.
#
def self.wss(host,port=443,path=nil,query=nil)
new('wss',host,port,path,query)
end

#
# Patses a URL.
#
# @param [String] url
# The URL string to parse.
#
# @return [WebSocket]
# The parse WebSocket object.
#
def self.parse(url)
uri = URI(url)

Values::WebSocket.new(uri.scheme,uri.host,uri.port,uri.path,uri.query)
end

#
# Compares the WebSocket to another value.
#
# @param [Value] other
#
# @return [Boolean]
#
def eql?(other)
self.class == other.class &&
@scheme == other.scheme &&
@host == other.host &&
@port == other.port &&
@path == other.path &&
@query == other.query
end

#
# Case equality method used for fuzzy matching.
#
# @param [Value] other
# The other value to compare.
#
# @return [Boolean]
# Imdicates whether the other value same as {WebSocket}
#
def ===(other)
case other
when WebSocket
eql?(other)
else
false
end
end

#
# The "hash" value of the WebSocket.
#
# @return [Integer]
# The hash value of {#scheme}, {#host}, {#port}, {#path} and {#query}.
#
def hash
[self.class, @scheme, @host, @port, @path, @query].hash
end

# Mapping of {#scheme} values to URI classes.
#
# @api private
URI_CLASSES = {
'wss' => URI::WSS,
'ws' => URI::WS
}

#
# Converts the WebSocket to URI.
#
# @return [URI::WS, URI::WSS]
# The URI object for the website.
#
def to_uri
URI_CLASSES.fetch(@scheme).build(host: @host, port: @port, path: @path, query: @query)
end

#
# Converts the WebSocket to a String.
#
# @return [String]
# The base URL value for the WebSocket.
#
def to_s
if ((@scheme == 'wss') && (@port != 443)) ||
((@scheme == 'ws') && (@port != 80))
"#{@scheme}://#{@host}:#{@port}#{@path}#{@query}"
else
"#{@scheme}://#{@host}#{@path}#{@query}"
end
end

#
# Coerces the WebSocket value into JSON.
#
# @return [Hash{Symbol => Object}]
# The Ruby Hash that will be converted into JSON.
#
def as_json
{
type: :web_socket,
scheme: @scheme,
host: @host,
port: @port,
path: @path,
query: @query
}
end

#
# Returns the type or kind of recon value.
#
# @return [:web_socket]
#
# @note
# This is used internally to map a recon value class to a printable
# type.
#
# @api private
#
def self.value_type
:web_socket
end
end
end
end
end
Loading

0 comments on commit 513e89e

Please sign in to comment.