我想知道如何使用Elixir中的十六进制字符串。具体来说,我对从Hex转换为ASCII感兴趣。
在Ruby中,实现可能是:
SpannableString string = new SpannableString("your text here");
string.setSpan(new StrikethroughSpan(), 0, string.length(), 0);
textView.setText(string);
如何使用Elixir完成此任务?我试过了:
["001C7F616A8B002128C1A33E8100"].pack('H*').gsub(/[^[:print:]]/, '.')
但这不是字符串十六进制的正确表示。感谢您的时间和帮助!
所以我取得了一些进展,但目前正在努力解决这个问题。
到目前为止,这是我的解决方案:
<<00, 01, C7, F6...>>
答案 0 :(得分:1)
这是问题的另一种解决方案。在我们开始之前要做几件事:
您可以将case: :mixed
传递给Base.decode16/2
:Base.decode16(string, case: :mixed)
,因此,您之前不需要大肆宣传。
如果您要加注无效的字符串,请不要打扰检查,只需直接调用decode16,因为它也会检查大小。
这意味着我们可以从:
开始decoded = Base.decode16!(string, case: :mixed)
现在您需要替换不可打印的字符。不要使用String.printable?/1
因为它是关于UTF-8而不是ASCII。我们需要实现自己的功能,但更有意义的是:提升或替换它们?如果有人发送无效数据,似乎必须将其视为错误?如果是这样的话:
def validate_ascii!(<<h, t::binary>>) when h <= 127 do
validate_ascii!(t)
end
def validate_ascii!(<<>>) do
true
end
def validate_ascii!(rest) do
raise "invalid ascii on string starting at: #{rest}"
end
或者你可以删除最后一个子句,它也会失败。
现在我们可以把它放在一起:
decoded = Base.decode16!(string, case: :mixed)
validate_ascii!(decoded)
decoded
编辑:如果你需要用点替换非ascii:
def keep_ascii(<<h, t::binary>>, acc) when h <= 127 do
keep_ascii(t, acc <> <<h>>)
end
def keep_ascii(<<_, t::binary>>, acc) do
keep_ascii(t, acc <> ".")
end
def keep_ascii(<<>>, acc) do
acc
end
答案 1 :(得分:0)
解决方案最终如下,但如果有更清洁或更好的解决方案,我会非常有兴趣了解它。
defmodule ElixirNetworkTools do
@doc """
The decode function takes a hexadecimal payload, such as one generated
by Snort, and returns the ASCII representation of the string.
## Example
iex> ElixirNetworkTools.decode("436F6E74656E742D4C656E6774683A203132")
{:ok, "Content-Length: 12"}
"""
def decode(payload) do
case _validate_length_of_snort(payload) do
:error -> raise "Invalid length hex string. Must be even length. Exiting"
_ -> nil
end
decoded = String.upcase(payload)
|> _do_decode
|> to_string
{:ok, decoded}
end
@doc """
Internal function used to manually process the hexadecimal payload,
and builds a char list of the printable characters. If a character is
not printable, we instead use periods.
## Example
iex> ElixirNetworkTools._do_decode("436F6E74656E742D4C656E6774683A203132")
["Content-Length: 12"]
"""
def _do_decode(payload) do
Base.decode16!(payload)
|> String.chunk(:printable)
|> Enum.map(fn(chunk) ->
case String.printable? chunk do
true -> chunk
_ -> "."
end
end)
end
@doc """
Internal function used to validate the length of the hexadecimal payload.
Hexadecimal strings should have an even number of characters.
## Example
iex> ElixirNetworkTools._validate_length_of_snort("436F6E74656E742D4C656E6774683A203132")
:ok
"""
def _validate_length_of_snort(payload) do
String.length(payload)
|> rem(2)
|> case do
0 -> :ok
_ -> :error
end
end
end