blob: 812bef536bc63c470ed07a6ee6197ba1308de905 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
-- cgit email-filter that shows a Libravatar icon next to author names. Use it
-- with the email-filter or repo.email-filter setting and the lua: prefix.
--
--     email-filter=lua:/path/to/email-libravatar.lua
--
-- SUPPORTED LUA
--
-- Lua 5.1, 5.2, 5.3, 5.4 and LuaJIT. Lua 5.5 is not supported, because luaossl
-- has no 5.5 build.
--
-- DEPENDENCY
--
--     luaossl    OpenSSL binding, provides openssl.digest
--                <https://github.com/wahern/luaossl>
--
--     # Debian and Ubuntu
--     sudo apt install luarocks libssl-dev
--     sudo luarocks --lua-version 5.1 install luaossl
--
--     # Fedora
--     sudo dnf install luarocks openssl-devel
--     sudo luarocks --lua-version 5.1 install luaossl
--
--     # macOS with Homebrew
--     brew install luarocks openssl
--     luarocks install luaossl OPENSSL_DIR="$(brew --prefix openssl)"
--
-- PRIVACY
--
-- Every page view sends the visitor's IP address and a hash of each
-- committer's email to a third-party service. Leave this filter off if that is
-- not acceptable for your instance.
--
-- The secure CDN is always used, so the icon loads over https and is never
-- blocked as mixed content. Addresses are hashed with MD5.

local digest = require("openssl.digest")

--
-- ===== CONFIGURATION =====
--

-- Pixel size of the avatar.
local avatar_size = 13

-- Fallback style for an address with no avatar. See the Libravatar docs for
-- the choices, for example retro, identicon, monsterid or mm.
local default_image = "retro"

-- Avatar endpoint. The secure CDN is used so the image loads over https.
local base_url = "https://seccdn.libravatar.org/avatar/"

-- Text for the image alt attribute.
local alt_text = "Libravatar"

--
-- =========================
--

-- State shared across the open, write and close calls of one invocation.
local buffer = ""
local avatar = nil

local function hash_hex(input)
	local b = digest.new("md5"):final(input)
	local x = ""
	for i = 1, #b do
		x = x .. string.format("%.2x", string.byte(b, i))
	end
	return x
end

-- Take the address, strip the angle brackets if present, then trim and
-- lowercase as the avatar services expect. Returns nil for a missing or empty
-- address.
local function normalize_email(email)
	if email == nil then
		return nil
	end
	local inner = email:match("<(.*)>")
	if inner ~= nil then
		email = inner
	end
	email = (email:gsub("^%s*(.-)%s*$", "%1")):lower()
	if email == "" then
		return nil
	end
	return email
end

function filter_open(email, page)
	buffer = ""
	local addr = normalize_email(email)
	if addr == nil then
		avatar = nil
	else
		avatar = hash_hex(addr)
	end
end

function filter_close()
	if avatar == nil then
		-- No usable address, render the name without an icon.
		html(buffer)
	else
		html("<img src='" .. base_url .. avatar .. "?s=" .. avatar_size .. "&amp;d=" .. default_image ..
			"' width='" .. avatar_size .. "' height='" .. avatar_size .. "' alt='" .. alt_text .. "' /> " .. buffer)
	end
	return 0
end

function filter_write(str)
	buffer = buffer .. str
end