Software /
code /
prosody
File
util/human/io.lua @ 11516:83822be7704d
util.xmppstream: Send <?xml?> declaration in same call as stream open
If network_settings.opportunistic_writes is enabled then this would
previously have resulted in two socket writes, and possibly two packets
being sent. This caused some issues in older versions of Gajim, which
apparently expected the stream opening in the first packet, and thus it
could not connect.
With this change and opportunistic_writes enabled, the first packet
should contain both the xml declaration and the stream open tag.
Without opportunistic_writes, there should be no observable change.
Tested with Gajim 1.1.2 (on same machine). Unsure if loopback behaves
differently than the network here.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Wed, 14 Apr 2021 15:21:13 +0200 |
parent | 10917:1eb83bc6f706 |
child | 11892:e712133b4de1 |
line wrap: on
line source
local array = require "util.array"; local function getchar(n) local stty_ret = os.execute("stty raw -echo 2>/dev/null"); local ok, char; if stty_ret == true or stty_ret == 0 then ok, char = pcall(io.read, n or 1); os.execute("stty sane"); else ok, char = pcall(io.read, "*l"); if ok then char = char:sub(1, n or 1); end end if ok then return char; end end local function getline() local ok, line = pcall(io.read, "*l"); if ok then return line; end end local function getpass() local stty_ret, _, status_code = os.execute("stty -echo 2>/dev/null"); if status_code then -- COMPAT w/ Lua 5.1 stty_ret = status_code; end if stty_ret ~= 0 then io.write("\027[08m"); -- ANSI 'hidden' text attribute end local ok, pass = pcall(io.read, "*l"); if stty_ret == 0 then os.execute("stty sane"); else io.write("\027[00m"); end io.write("\n"); if ok then return pass; end end local function show_yesno(prompt) io.write(prompt, " "); local choice = getchar():lower(); io.write("\n"); if not choice:match("%a") then choice = prompt:match("%[.-(%U).-%]$"); if not choice then return nil; end end return (choice == "y"); end local function read_password() local password; while true do io.write("Enter new password: "); password = getpass(); if not password then print("No password - cancelled"); return; end io.write("Retype new password: "); if getpass() ~= password then if not show_yesno [=[Passwords did not match, try again? [Y/n]]=] then return; end else break; end end return password; end local function show_prompt(prompt) io.write(prompt, " "); local line = getline(); line = line and line:gsub("\n$",""); return (line and #line > 0) and line or nil; end local function printf(fmt, ...) print(fmt:format(...)); end local function padright(s, width) return s..string.rep(" ", width-#s); end local function padleft(s, width) return string.rep(" ", width-#s)..s; end local function new_table(col_specs, max_width) max_width = max_width or tonumber(os.getenv("COLUMNS")) or 80; local separator = " | "; local widths = {}; local total_width = max_width - #separator * (#col_specs-1); local free_width = total_width; -- Calculate width of fixed-size columns for i = 1, #col_specs do local width = col_specs[i].width or "0"; if not(type(width) == "string" and width:sub(-1) == "%") then local title = col_specs[i].title; width = math.max(tonumber(width), title and (#title+1) or 0); widths[i] = width; free_width = free_width - width; if i > 1 then free_width = free_width - #separator; end end end -- Calculate width of %-based columns for i = 1, #col_specs do if not widths[i] then local pc_width = tonumber((col_specs[i].width:gsub("%%$", ""))); widths[i] = math.floor(free_width*(pc_width/100)); end end return function (row) local titles; if not row then titles, row = true, array.pluck(col_specs, "title", ""); end local output = {}; for i, column in ipairs(col_specs) do local width = widths[i]; local v = (not titles and column.mapper or tostring)(row[not titles and column.key or i] or "", row); if #v < width then if column.align == "right" then v = padleft(v, width); else v = padright(v, width); end elseif #v > width then v = v:sub(1, width-1) .. "…"; end table.insert(output, v); end return table.concat(output, separator); end; end return { getchar = getchar; getline = getline; getpass = getpass; show_yesno = show_yesno; read_password = read_password; show_prompt = show_prompt; printf = printf; padleft = padleft; padright = padright; table = new_table; };