<commit_before>--Obtained from http://code.google.com/p/prosody-modules/source/browse/mod_websocket/mod_websocket.lua
--Author appears to be <NAME> <<EMAIL>>
--Code had no license in attribution in header, emailed Ali 4-17-12 to see if he wanted any since we will have to modify this heavily and probably re-release
--Changes to support latest WebSocket RFC by <NAME> <<EMAIL>>

module.host = "*" -- Global module

local logger = require "util.logger";
local log = logger.init("mod_websocket");
local httpserver = require "net.httpserver";
local lxp = require "lxp";
local new_xmpp_stream = require "util.xmppstream".new;
local st = require "util.stanza";
local sm = require "core.sessionmanager";
local sha1 = require "util.hashes".sha1;
local base64 = require "util.encodings".base64;

local sessions = {};
local default_headers = { };


local stream_callbacks = { default_ns = "jabber:client",
		streamopened = sm.streamopened,
		streamclosed = sm.streamclosed,
		handlestanza = core_process_stanza };
function stream_callbacks.error(session, error, data)
	if error == "no-stream" then
		session.log("debug", "Invalid opening stream header");
		session:close("invalid-namespace");
	elseif session.close then
		(session.log or log)("debug", "Client XML parse error: %s", tostring(error));
		session:close("xml-not-well-formed");
	end
end


local function session_reset_stream(session)
	local stream = new_xmpp_stream(session, stream_callbacks);
	session.stream = stream;

	session.notopen = true;

--TODO:	might not be necessary, don't understand yet
--	(added based on http://hg.prosody.im/0.8/rev/ccf417c7b5d4)
--[[
	function session.reset_stream()
		session.notopen = true;
		session.stream:reset()
	end
]]--

	function session.data(conn, data)
		data, _ = data:gsub("[%z\255]", "")
		log( "debug", "Parsing: %s", data:gsub("%c", ""));

--TODO: implement frame decoding here

		local ok, err = stream:feed(data);
		if not ok then
			log("debug", "Received invalid XML (%s) %d bytes: %s", tostring(err), #data,
				data:sub(1, 300):gsub("[\r\n]+", " "):gsub("[%z\1-\31]", "_"):gsub("%c", ""));
			session:close("xml-not-well-formed");
		end
	end
end

local stream_xmlns_attr = {xmlns='urn:ietf:params:xml:ns:xmpp-streams'};
local default_stream_attr = { ["xmlns:stream"] = "http://etherx.jabber.org/streams", xmlns = stream_callbacks.default_ns, version = "1.0", id = "" };
local function session_close(session, reason)
	local log = session.log or log;
	if session.conn then
		if session.notopen then
			session.send("<?xml version='1.0'?>");
			session.send(st.stanza("stream:stream", default_stream_attr):top_tag());
		end
		if reason then
			if type(reason) == "string" then -- assume stream error
				log("info", "Disconnecting client, <stream:error> is: %s", reason);
				session.send(st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' }));
			elseif type(reason) == "table" then
				if reason.condition then
					local stanza = st.stanza("stream:error"):tag(reason.condition, stream_xmlns_attr):up();
					if reason.text then
						stanza:tag("text", stream_xmlns_attr):text(reason.text):up();
					end
					if reason.extra then
						stanza:add_child(reason.extra);
					end
					log("info", "Disconnecting client, <stream:error> is: %s", tostring(stanza));
					session.send(stanza);
				elseif reason.name then -- a stanza
					log("info", "Disconnecting client, <stream:error> is: %s", tostring(reason));
					session.send(reason);
				end
			end
		end
		session.send("</stream:stream>");
		session.conn:close();
--TODO: figure out how to suppress here that happens here
		if websocket_listener then
			websocket_listener.ondisconnect(session.conn, (reason and (reason.text or reason.condition)) or reason or "session closed");
		end
	end
end<commit_msg>Work on decoding websockets data frame<commit_after>--Obtained from http://code.google.com/p/prosody-modules/source/browse/mod_websocket/mod_websocket.lua
--Author appears to be <NAME> <<EMAIL>>
--Code had no license in attribution in header, emailed Ali 4-17-12 to see if he wanted any since we will have to modify this heavily and probably re-release
--Changes to support latest WebSocket RFC by <NAME> <<EMAIL>>

module.host = "*" -- Global module

local logger = require "util.logger";
local log = logger.init("mod_websocket");
local httpserver = require "net.httpserver";
local lxp = require "lxp";
local new_xmpp_stream = require "util.xmppstream".new;
local st = require "util.stanza";
local sm = require "core.sessionmanager";
local sha1 = require "util.hashes".sha1;
local base64 = require "util.encodings".base64;
local binaryXOR = require "util.sasl.scram".binaryXOR;

local sessions = {};
local default_headers = { };


local stream_callbacks = { default_ns = "jabber:client",
		streamopened = sm.streamopened,
		streamclosed = sm.streamclosed,
		handlestanza = core_process_stanza };
function stream_callbacks.error(session, error, data)
	if error == "no-stream" then
		session.log("debug", "Invalid opening stream header");
		session:close("invalid-namespace");
	elseif session.close then
		(session.log or log)("debug", "Client XML parse error: %s", tostring(error));
		session:close("xml-not-well-formed");
	end
end


local function session_reset_stream(session)
	local stream = new_xmpp_stream(session, stream_callbacks);
	session.stream = stream;

	session.notopen = true;

--TODO:	might not be necessary, don't understand yet
--	(added based on http://hg.prosody.im/0.8/rev/ccf417c7b5d4)
--[[
	function session.reset_stream()
		session.notopen = true;
		session.stream:reset()
	end
]]--

	function session.data(conn, data)
--strip 0, 255 out of data string (attempt for basic compliance with old rfc, i think)
--		data, _ = data:gsub("[%z\255]", "")

		log( "debug", "Parsing: %s", data:gsub("%c", ""));

--TODO:	implement frame decoding here
--RFC:	http://tools.ietf.org/html/rfc6455#section-5
log( "debug", "DATA FRAME:" );
log( "debug", "FIRST  BYTE[bits] (FIN[1], RSV1[1], RSV2[1], RSV3[1], Opcode[4]):	" .. string.format( "%02X", data:byte( 1, 1 ) ) );
log( "debug", "SECOND BYTE[bits] (Mask[1], Payload Length[7]):				" .. string.format( "%02X", data:byte( 2, 2 ) ) );
local mask = data:byte( 3, 3 ) * 16777216;
local mask = mask + data:byte( 4, 4 ) * 65536;
local mask = mask + data:byte( 5, 5 ) * 256;
local mask = mask + data:byte( 6, 6 );
log( "debug", "MASK (assumed 7 bit payload): " .. mask );
local x = 7;
repeat
	log( "debug", "VARIABLE PAYLOAD: (MUST STILL DECODE):					" .. string.format( "%02X%02X", data:byte( x, x ), data:byte( x+1, x+1 ) ) );
	x = x+2;
until x >= #data

		local ok, err = stream:feed(data);
		if not ok then
			log("debug", "Received invalid XML (%s) %d bytes: %s", tostring(err), #data,
				data:sub(1, 300):gsub("[\r\n]+", " "):gsub("[%z\1-\31]", "_"):gsub("%c", ""));
			session:close("xml-not-well-formed");
		end
	end
end

local stream_xmlns_attr = {xmlns='urn:ietf:params:xml:ns:xmpp-streams'};
local default_stream_attr = { ["xmlns:stream"] = "http://etherx.jabber.org/streams", xmlns = stream_callbacks.default_ns, version = "1.0", id = "" };
local function session_close(session, reason)
	local log = session.log or log;
	if session.conn then
		if session.notopen then
			session.send("<?xml version='1.0'?>");
			session.send(st.stanza("stream:stream", default_stream_attr):top_tag());
		end
		if reason then
			if type(reason) == "string" then -- assume stream error
				log("info", "Disconnecting client, <stream:error> is: %s", reason);
				session.send(st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' }));
			elseif type(reason) == "table" then
				if reason.condition then
					local stanza = st.stanza("stream:error"):tag(reason.condition, stream_xmlns_attr):up();
					if reason.text then
						stanza:tag("text", stream_xmlns_attr):text(reason.text):up();
					end
					if reason.extra then
						stanza:add_child(reason.extra);
					end
					log("info", "Disconnecting client, <stream:error> is: %s", tostring(stanza));
					session.send(stanza);
				elseif reason.name then -- a stanza
					log("info", "Disconnecting client, <stream:error> is: %s", tostring(reason));
					session.send(reason);
				end
			end
		end
		session.send("</stream:stream>");
		session.conn:close();
--TODO: figure out how to suppress error that happens here
		if websocket_listener then
			websocket_listener.ondisconnect(session.conn, (reason and (reason.text or reason.condition)) or reason or "session closed");
		end
	end
end
{'fraction_non_alphanumeric': 0.15968555672885135, 'fraction_numerical': 0.014783526927138331, 'mean_word_length': 4.520725388601036, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 2, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 24}, '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': '1043515', 'n_tokens_mistral': 3194, 'n_tokens_neox': 2889, 'n_words': 762}