Commit 76ee0759 authored by Michael Gratton's avatar Michael Gratton 🤞 Committed by Michael Gratton

Make avatar code a bit more robust in the face of bad input

Don't try to dray null initials, actually return null per API contract
when no initials can be found, don't include non-alphanumerics in the
initials. Add test case.
parent 4e484e23
......@@ -7,41 +7,45 @@
namespace Util.Avatar {
// The following was ported from code written by Felipe Borges for
// The following was based on code written by Felipe Borges for
// gnome-control-enter in panels/user-accounts/user-utils.c commit
// 02c288ab6f069a0c106323a93400f192a63cb67e. The copyright in that
// file is: "Copyright 2009-2010 Red Hat, Inc,"
public Gdk.Pixbuf generate_user_picture(string name, int size) {
string initials = extract_initials_from_name(name);
string font = "Sans %d".printf((int) GLib.Math.ceil(size / 2.5));
Gdk.RGBA color = get_color_for_name(name);
Cairo.Surface surface = new Cairo.ImageSurface(
Cairo.Format.ARGB32, size, size
);
Cairo.Context cr = new Cairo.Context(surface);
cr.rectangle(0, 0, size, size);
/* Fill the background with a colour for the name */
Gdk.RGBA color = get_color_for_name(name);
cr.set_source_rgb(
color.red / 255.0, color.green / 255.0, color.blue / 255.0
);
cr.fill();
/* Draw the initials on top */
cr.set_source_rgb(1.0, 1.0, 1.0);
Pango.Layout layout = Pango.cairo_create_layout(cr);
layout.set_text(initials, -1);
layout.set_font_description(Pango.FontDescription.from_string(font));
int width, height;
layout.get_size(out width, out height);
cr.translate(size / 2, size / 2);
cr.move_to(
-((double) width / Pango.SCALE) / 2,
-((double) height / Pango.SCALE) / 2
);
Pango.cairo_show_layout(cr, layout);
string? initials = extract_initials_from_name(name);
if (initials != null) {
string font = "Sans %d".printf((int) GLib.Math.ceil(size / 2.5));
cr.set_source_rgb(1.0, 1.0, 1.0);
Pango.Layout layout = Pango.cairo_create_layout(cr);
layout.set_text(initials, -1);
layout.set_font_description(Pango.FontDescription.from_string(font));
int width, height;
layout.get_size(out width, out height);
cr.translate(size / 2, size / 2);
cr.move_to(
-((double) width / Pango.SCALE) / 2,
-((double) height / Pango.SCALE) / 2
);
Pango.cairo_show_layout(cr, layout);
}
return Gdk.pixbuf_get_from_surface(
surface, 0, 0, size, size
);
......@@ -72,13 +76,29 @@ namespace Util.Avatar {
string? initials = null;
if (normalized != "") {
GLib.StringBuilder buf = new GLib.StringBuilder();
buf.append_unichar(normalized.get_char(0));
unichar c = 0;
int index = 0;
// Get the first alphanumeric char of the string
for (int i = 0; normalized.get_next_char(ref index, out c); i++) {
if (c.isalnum()) {
buf.append_unichar(c);
break;
}
}
// Get the first alphanumeric char of the last word of the string
index = normalized.last_index_of_char(' ');
for (int i = 0; normalized.get_next_char(ref index, out c); i++) {
if (c.isalnum()) {
buf.append_unichar(c);
break;
}
}
int index = normalized.last_index_of_char(' ');
if (index != -1 && (index + 1) < normalized.length) {
buf.append_unichar(normalized.get_char(index + 1));
if (buf.data.length > 0) {
initials = (string) buf.data;
}
initials = (string) buf.data;
}
return initials;
}
......
/*
* Copyright 2019 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
public class Util.Avatar.Test : TestCase {
public Test() {
base("UtilAvatarTest");
add_test("extract_initials", extract_initials);
}
public void extract_initials() throws GLib.Error {
assert_string("A", extract_initials_from_name("aardvark"));
assert_string("AB", extract_initials_from_name("aardvark baardvark"));
assert_string("AB", extract_initials_from_name("aardvark baardvark"));
assert_string("AC", extract_initials_from_name("aardvark baardvark caardvark"));
assert_string("A", extract_initials_from_name("!aardvark"));
assert_string("AB", extract_initials_from_name("aardvark !baardvark"));
assert_string("AC", extract_initials_from_name("aardvark baardvark !caardvark"));
assert_true(extract_initials_from_name("") == null);
assert_true(extract_initials_from_name(" ") == null);
assert_true(extract_initials_from_name(" ") == null);
assert_true(extract_initials_from_name("!") == null);
assert_true(extract_initials_from_name("!!") == null);
assert_true(extract_initials_from_name("! !") == null);
assert_true(extract_initials_from_name("! !!") == null);
}
}
......@@ -75,6 +75,7 @@ geary_test_client_sources = [
'client/components/client-web-view-test.vala',
'client/components/client-web-view-test-case.vala',
'client/composer/composer-web-view-test.vala',
'client/util/util-avatar-test.vala',
'js/client-page-state-test.vala',
'js/composer-page-state-test.vala',
......
......@@ -43,6 +43,7 @@ int main(string[] args) {
client.add_suite(new ClientWebViewTest().get_suite());
client.add_suite(new ComposerWebViewTest().get_suite());
client.add_suite(new ConfigurationTest().get_suite());
client.add_suite(new Util.Avatar.Test().get_suite());
TestSuite js = new TestSuite("js");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment