We have detected that cookies are not enabled on your browser. Please enable cookies to ensure the proper experience.
Results 1 to 7 of 7
  1. #1
    Join Date
    Jun 2011
    Posts
    0

    Hidden bytes in chat messages

    I am looking for a good way to send data via chat to other players, but I don't want it to show as visible strings in the chat window. Only players that parse the chat with a Lua plugin should be able to read the bytes.

    I remember there was a thread discussing sending chat messages with additional invisible costum data some time ago. It was an interesting read, but I don't remember the details. It was probably done by exploiting something like the <Select:IID> tags, or something similar. Unfortunately I am not able to find the discussion thread again. I thought it was in context of Thurallor's Blackboard plugin, but it seems like I am mistaken.

    Can someone link me the original discussion?

    Thanks!
    Last edited by Eruadarion; Mar 17 2020 at 10:09 AM.
    Eruadarion | Captain | on Gwaihir [EU-DE]
    www.avorthalier.eu

  2. #2
    Join Date
    Jun 2011
    Posts
    0
    In case anyone is interested, here is my solution to the problem:

    Code:
    import "Turbine";
    local print = Turbine.Shell.WriteLine;
    
    local function encodeHiddenString(s)
    	if s:len()%8 ~= 0 then error("string length must be divisible by 8") end
    	local bytes = {};
    	for i=1, s:len() do
    		bytes[i] = string.format("%X", s:byte(i));
    		if bytes[i]:len() < 2 then bytes[i] = "0"..bytes[i] end
    	end
    	local selectBegin, selectEnd = "<Select:IID:0x", "><\Select>";
    	local result, eightBytes = "", "";
    	local j = 1;
    	repeat
    		eightBytes = "";
    		for i=j, j+7 do
    			eightBytes = eightBytes..bytes[i];
    		end
    		result = result..selectBegin..eightBytes..selectEnd;
    		j = j+8;
    	until j > #bytes
    	return result
    end
    
    local function decodeHiddenString(s)
    	local result = "";
    	local byteString = "";
    	for bytes in s:gmatch("<Select:IID:0x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x") do
    		byteString = byteString..bytes:sub(15, 30);
    	end
    	for byte in byteString:gmatch('%x%x') do
    		local char = string.char(tonumber("0x"..byte));
    		result = result..char;
    	end
    	return result;
    end
    
    
    -- Demo of encoding:
    local hiddenMessage = "This is a hidden message";
    print("Hello World!"..encodeHiddenString(hiddenMessage));
    
    -- Demo of decoding:
    local messageWithHiddenString = "Hello World!<Select:IID:0x5468697320697320><\Select><Select:IID:0x612068696464656E><\Select><Select:IID:0x206D657373616765><\Select>";
    print(decodeHiddenString(messageWithHiddenString));
    Eruadarion | Captain | on Gwaihir [EU-DE]
    www.avorthalier.eu

  3. #3
    Join Date
    Jun 2011
    Posts
    391
    Quote Originally Posted by Eruadarion View Post
    In case anyone is interested, here is my solution to the problem:

    Code:
    import "Turbine";
    local print = Turbine.Shell.WriteLine;
    
    local function encodeHiddenString(s)
    	if s:len()%8 ~= 0 then error("string length must be divisible by 8") end
    	local bytes = {};
    	for i=1, s:len() do
    		bytes[i] = string.format("%X", s:byte(i));
    		if bytes[i]:len() < 2 then bytes[i] = "0"..bytes[i] end
    	end
    	local selectBegin, selectEnd = "<Select:IID:0x", "><\Select>";
    	local result, eightBytes = "", "";
    	local j = 1;
    	repeat
    		eightBytes = "";
    		for i=j, j+7 do
    			eightBytes = eightBytes..bytes[i];
    		end
    		result = result..selectBegin..eightBytes..selectEnd;
    		j = j+8;
    	until j > #bytes
    	return result
    end
    
    local function decodeHiddenString(s)
    	local result = "";
    	local byteString = "";
    	for bytes in s:gmatch("<Select:IID:0x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x") do
    		byteString = byteString..bytes:sub(15, 30);
    	end
    	for byte in byteString:gmatch('%x%x') do
    		local char = string.char(tonumber("0x"..byte));
    		result = result..char;
    	end
    	return result;
    end
    
    
    -- Demo of encoding:
    local hiddenMessage = "This is a hidden message";
    print("Hello World!"..encodeHiddenString(hiddenMessage));
    
    -- Demo of decoding:
    local messageWithHiddenString = "Hello World!<Select:IID:0x5468697320697320><\Select><Select:IID:0x612068696464656E><\Select><Select:IID:0x206D657373616765><\Select>";
    print(decodeHiddenString(messageWithHiddenString));
    Have you tried out how much data you can attach in the hidden string? Your example shows 3 times 8bytes, can it be more?

  4. #4
    Join Date
    Jun 2011
    Posts
    0
    Quote Originally Posted by Hyos View Post
    Have you tried out how much data you can attach in the hidden string? Your example shows 3 times 8bytes, can it be more?
    Yes, up to 392 bytes (= 49 * 8 bytes) can be encoded as hidden bytes using my function.

    If you encode strings longer than 392 characters and then send it as hidden bytes to chat then you will get an error message in LOTRO:
    "That text is prohibited because of a content, size, or mixed-alphabet restriction."

    EDIT: Typo: you can encode 49 * 8 bytes
    Last edited by Eruadarion; Mar 06 2020 at 03:19 PM.
    Eruadarion | Captain | on Gwaihir [EU-DE]
    www.avorthalier.eu

  5. #5
    Join Date
    Jun 2011
    Posts
    391
    Quote Originally Posted by Eruadarion View Post
    Yes, up to 392 bytes (= 13 * 8 bytes) can be encoded as hidden bytes using my function.

    If you encode strings longer than 392 characters and then send it as hidden bytes to chat then you will get an error message in LOTRO:
    "That text is prohibited because of a content, size, or mixed-alphabet restriction."
    Thank you!

  6. #6
    Join Date
    Jun 2011
    Posts
    2,190

  7. #7
    Join Date
    Jun 2011
    Posts
    0
    Quote Originally Posted by Thurallor View Post
    Thank you! The first link you posted is the thread I was looking for!

    So this is my conclusion:
    Advantage of using <rgb> tags to send invisible bytes is that you can send up to 955 bytes.
    Advantage of using the <Select:IID> tags is that your plugin users won't even see the data when they mouse-over the qickslot button that is used to send the data.
    Eruadarion | Captain | on Gwaihir [EU-DE]
    www.avorthalier.eu

 

 

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

This form's session has expired. You need to reload the page.

Reload