From e1496dd08eea459ff30655a7ea2753edb95871ef Mon Sep 17 00:00:00 2001 From: Georgy A. Shepelev Date: Tue, 29 Sep 2009 22:08:17 +0400 Subject: [PATCH] xdm: Adding an option to show stars instead of the password itself. xdm: The behaviour can be controlled via 'xlogin*echoPasswd' option xdm: in Xresource file. The default option value is 'false'. xdm: Adding utf8-support in all prompt-/greeting-strings that belongs xdm: to the login widget. Signed-off-by: Georgy A. Shepelev Tested-by: Georgy A. Shepelev --- greeter/Login.c | 219 +++++++++++++++++++++++++++++++++---------------------- greeter/Login.h | 2 + greeter/greet.c | 6 +- 3 files changed, 138 insertions(+), 89 deletions(-) diff --git a/greeter/Login.c b/greeter/Login.c index fefa29d..33ddcee 100644 --- a/greeter/Login.c +++ b/greeter/Login.c @@ -224,7 +224,9 @@ static XtResource resources[] = { {XtNallowNullPasswd, XtCAllowNullPasswd, XtRBoolean, sizeof (Boolean), offset(allow_null_passwd), XtRImmediate, (XtPointer) False}, {XtNallowRootLogin, XtCAllowRootLogin, XtRBoolean, sizeof(Boolean), - offset(allow_root_login), XtRImmediate, (XtPointer) True} + offset(allow_root_login), XtRImmediate, (XtPointer) True}, + {XtNechoPasswd, XtCEchoPasswd, XtRBoolean, sizeof(Boolean), + offset(echo_passwd), XtRImmediate, (XtPointer)False} }; #undef offset @@ -280,7 +282,7 @@ XmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len); # define DRAW_STRING(f, x, y, m, l) \ /* Debug("DRAW_STRING(%s, %d, %d, %s, %d)\n", #f, x, y, m, l); */ \ - XftDrawString8 (w->login.draw, &w->login.f##color, w->login.f##Face, \ + XftDrawStringUtf8 (w->login.draw, &w->login.f##color, w->login.f##Face, \ x, y, (FcChar8 *) m, l) #else @@ -352,14 +354,35 @@ XmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len); static inline int max (int a, int b) { return a > b ? a : b; } #endif -static void -realizeValue (LoginWidget w, int cursor, int promptNum, GC gc) +static void realizeValue(LoginWidget w, int cursor, int promptNum, GC gc) { - loginPromptState state = w->login.prompts[promptNum].state; + loginPromptState state = PROMPT_STATE(w, promptNum); char *text = VALUE_TEXT(w, promptNum); int x, y, height, width, curoff; XDM_ASSERT(promptNum >= 0 && promptNum <= LAST_PROMPT); + /* replace all password characters with asterisks */ + if ((promptNum == LOGIN_PROMPT_PASSWORD) && (w->login.echo_passwd == True)) + { + Cardinal length = strlen(text); + Cardinal i = 0; + + text = XtMalloc(length + 1); + + if (text == NULL) + { + LogOutOfMem("realizeValue"); + + return; + } + + while (i < length) + { + text[i++] = '*'; + } + + text[i] = 0; + } x = VALUE_X (w,promptNum); y = PROMPT_Y (w,promptNum); @@ -373,54 +396,70 @@ realizeValue (LoginWidget w, int cursor, int promptNum, GC gc) width -= (w->login.logoWidth + 2*(w->login.logoPadding)); #endif if (cursor > VALUE_SHOW_START(w, promptNum)) - curoff = TEXT_WIDTH (text, text, cursor); + { + curoff = TEXT_WIDTH(text, text, cursor); + } else - curoff = 0; + { + curoff = 0; + } - if (gc == w->login.bgGC) { - if (curoff < width) { - XFillRectangle (XtDisplay (w), XtWindow (w), gc, - x + curoff, y - TEXT_Y_INC(w), - width - curoff, height); - } - } else if ((state == LOGIN_PROMPT_ECHO_ON) || (state == LOGIN_TEXT_INFO)) { - int textwidth; - int offset = max(cursor, VALUE_SHOW_START(w, promptNum)); - int textlen = strlen (text + offset); - - textwidth = TEXT_WIDTH (text, text + offset, textlen); - - if (textwidth > (width - curoff)) { - /* Recalculate amount of text that can fit in field */ - offset = VALUE_SHOW_START(w, promptNum); - textlen = strlen (text + offset); - - while ((textlen > 0) && (textwidth > width)) - { - if (offset < PROMPT_CURSOR(w, promptNum)) { - offset++; + if (gc == w->login.bgGC) + { + if (curoff < width) + { + XFillRectangle(XtDisplay(w), XtWindow(w), gc, x + curoff, y - TEXT_Y_INC(w), + width - curoff, height); } - textlen--; + } + else if ((state == LOGIN_PROMPT_ECHO_ON) || (state == LOGIN_TEXT_INFO) || + ((promptNum == LOGIN_PROMPT_PASSWORD) && (w->login.echo_passwd == True))) + { + int textwidth; + int offset = max(cursor, VALUE_SHOW_START(w, promptNum)); + int textlen = strlen(text + offset); + textwidth = TEXT_WIDTH (text, text + offset, textlen); - } - VALUE_SHOW_START(w, promptNum) = offset; - VALUE_SHOW_END(w, promptNum) = offset + textlen; + if (textwidth > (width - curoff)) + { + /* Recalculate amount of text that can fit in field */ + offset = VALUE_SHOW_START(w, promptNum); + textlen = strlen(text + offset); - /* Erase old string */ - XFillRectangle (XtDisplay (w), XtWindow (w), w->login.bgGC, - x, y - TEXT_Y_INC(w), width, height); + while ((textlen > 0) && (textwidth > width)) + { + if (offset < PROMPT_CURSOR(w, promptNum)) + { + offset++; + } + textlen--; + textwidth = TEXT_WIDTH(text, text + offset, textlen); + } - DRAW_STRING(text, x, y, text + offset, textlen); - } else { - DRAW_STRING(text, x + curoff, y, text + offset, textlen); - } + VALUE_SHOW_START(w, promptNum) = offset; + VALUE_SHOW_END(w, promptNum) = offset + textlen; + + /* Erase old string */ + XFillRectangle(XtDisplay(w), XtWindow(w), w->login.bgGC, x, y - TEXT_Y_INC(w), + width, height); + + DRAW_STRING(text, x, y, text + offset, textlen); + } + else + { + DRAW_STRING(text, x + curoff, y, text + offset, textlen); + } } + /* free memory */ + if ((promptNum == LOGIN_PROMPT_PASSWORD) && (w->login.echo_passwd == True)) + { + XtFree(text); + } } -static void -EraseValue (LoginWidget w, int cursor, int promptNum) +static void EraseValue(LoginWidget w, int cursor, int promptNum) { realizeValue(w, cursor, promptNum, w->login.bgGC); } @@ -436,14 +475,14 @@ DrawValue (LoginWidget w, int cursor, int promptNum) #endif /* DANCING */ } -static void -realizeCursor (LoginWidget w, GC gc) +static void realizeCursor(LoginWidget w, GC gc) { int x, y; int height, width; - if (w->login.state != PROMPTING) { - return; + if (w->login.state != PROMPTING) + { + return; } x = VALUE_X (w, w->login.activePrompt); @@ -451,46 +490,54 @@ realizeCursor (LoginWidget w, GC gc) height = (F_ASCENT(text) + F_DESCENT(text)); width = 1; - switch (PROMPT_STATE(w, w->login.activePrompt)) { - case LOGIN_PROMPT_NOT_SHOWN: - case LOGIN_TEXT_INFO: - return; - case LOGIN_PROMPT_ECHO_ON: - if (CUR_PROMPT_CURSOR(w) > 0) { - x += TEXT_WIDTH (text, - VALUE_TEXT(w, w->login.activePrompt) - + VALUE_SHOW_START(w, w->login.activePrompt), - PROMPT_CURSOR(w, w->login.activePrompt) - - VALUE_SHOW_START(w, w->login.activePrompt) ); + switch (PROMPT_STATE(w, w->login.activePrompt)) + { + case LOGIN_PROMPT_NOT_SHOWN: + case LOGIN_TEXT_INFO: + return; + + case LOGIN_PROMPT_ECHO_ON: + { + if (CUR_PROMPT_CURSOR(w) > 0) + { + x += TEXT_WIDTH(text, VALUE_TEXT(w, w->login.activePrompt) + + VALUE_SHOW_START(w, w->login.activePrompt), + PROMPT_CURSOR(w, w->login.activePrompt) - + VALUE_SHOW_START(w, w->login.activePrompt)); + } + break; + } + + case LOGIN_PROMPT_ECHO_OFF: + { + if ((w->login.activePrompt == LOGIN_PROMPT_PASSWORD) && (w->login.echo_passwd == True)) + { + int len = PROMPT_CURSOR(w, w->login.activePrompt) - + VALUE_SHOW_START(w, w->login.activePrompt); + + x += len*TEXT_WIDTH(text, "*", 1); + } + else + { + /* Move cursor one pixel per character to give some feedback without + giving away the password length */ + x += PROMPT_CURSOR(w, w->login.activePrompt); + } + break; + } } - break; - case LOGIN_PROMPT_ECHO_OFF: - /* Move cursor one pixel per character to give some feedback without - giving away the password length */ - x += PROMPT_CURSOR(w, w->login.activePrompt); - break; - } - XFillRectangle (XtDisplay (w), XtWindow (w), gc, - x, y+1 - F_ASCENT(text), width, height-1); - XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x-1 , y - F_ASCENT(text)); - XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x+1 , y - F_ASCENT(text)); - XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x-1 , y - F_ASCENT(text)+height); - XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x+1 , y - F_ASCENT(text)+height); - XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x-2 , y - F_ASCENT(text)); - XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x+2 , y - F_ASCENT(text)); - XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x-2 , y - F_ASCENT(text)+height); - XDrawPoint (XtDisplay (w), XtWindow (w), gc, - x+2 , y - F_ASCENT(text)+height); - - XFlush (XtDisplay(w)); + XFillRectangle(XtDisplay(w), XtWindow(w), gc, x, y + 1 - F_ASCENT(text), width, height - 1); + XDrawPoint(XtDisplay(w), XtWindow(w), gc, x - 1, y - F_ASCENT(text)); + XDrawPoint(XtDisplay(w), XtWindow(w), gc, x + 1, y - F_ASCENT(text)); + XDrawPoint(XtDisplay(w), XtWindow(w), gc, x - 1, y - F_ASCENT(text) + height); + XDrawPoint(XtDisplay(w), XtWindow(w), gc, x + 1, y - F_ASCENT(text) + height); + XDrawPoint(XtDisplay(w), XtWindow(w), gc, x - 2, y - F_ASCENT(text)); + XDrawPoint(XtDisplay(w), XtWindow(w), gc, x + 2, y - F_ASCENT(text)); + XDrawPoint(XtDisplay(w), XtWindow(w), gc, x - 2, y - F_ASCENT(text) + height); + XDrawPoint(XtDisplay(w), XtWindow(w), gc, x + 2, y - F_ASCENT(text) + height); + + XFlush(XtDisplay(w)); } static void @@ -1615,7 +1662,7 @@ XmuXftTextWidth(Display *dpy, XftFont *font, FcChar8 *string, int len) { XGlyphInfo extents; - XftTextExtents8 (dpy, font, string, len, &extents); + XftTextExtentsUtf8 (dpy, font, string, len, &extents); return extents.xOff; } @@ -1800,7 +1847,7 @@ SkipXpmLoad: VALUE_TEXT_MAX(w, LOGIN_PROMPT_PASSWORD) = sizeof(w->login.data.passwd); VALUE_SHOW_START(w, LOGIN_PROMPT_PASSWORD) = 0; - SetPrompt(gnew, LOGIN_PROMPT_PASSWORD, NULL, LOGIN_PROMPT_ECHO_OFF, False); + SetPrompt(gnew, LOGIN_PROMPT_PASSWORD, NULL, LOGIN_PROMPT_ECHO_OFF, False); SetPrompt(gnew, LOGIN_PROMPT_USERNAME, NULL, LOGIN_PROMPT_ECHO_ON, False); if (w->core.width == 0) diff --git a/greeter/Login.h b/greeter/Login.h index 7d04a1a..2e79e5e 100644 --- a/greeter/Login.h +++ b/greeter/Login.h @@ -105,6 +105,7 @@ from The Open Group. # define XtNallowAccess "allowAccess" # define XtNallowNullPasswd "allowNullPasswd" # define XtNallowRootLogin "allowRootLogin" +# define XtNechoPasswd "echoPasswd" # define XtNface "face" # define XtCFace "Face" @@ -145,6 +146,7 @@ from The Open Group. # define XtCAllowAccess "AllowAccess" # define XtCAllowNullPasswd "AllowNullPasswd" # define XtCAllowRootLogin "AllowRootLogin" +# define XtCEchoPasswd "EchoPasswd" # define XtNchangePasswdMessage "changePasswdMessage" # define XtCChangePasswdMessage "ChangePasswdMessage" diff --git a/greeter/greet.c b/greeter/greet.c index 17d21c8..bc3d00f 100644 --- a/greeter/greet.c +++ b/greeter/greet.c @@ -507,9 +507,9 @@ greet_user_rtn GreetUser( const char * login_prompt; - SetPrompt(login, 0, NULL, LOGIN_PROMPT_NOT_SHOWN, False); + SetPrompt(login, LOGIN_PROMPT_USERNAME, NULL, LOGIN_PROMPT_NOT_SHOWN, False); login_prompt = GetPrompt(login, LOGIN_PROMPT_USERNAME); - SetPrompt(login, 1, NULL, LOGIN_PROMPT_NOT_SHOWN, False); + SetPrompt(login, LOGIN_PROMPT_PASSWORD, NULL, LOGIN_PROMPT_NOT_SHOWN, False); # define RUN_AND_CHECK_PAM_ERROR(function, args) \ do { \ @@ -714,7 +714,7 @@ static int pamconv(int num_msg, char *username; int promptId = 0; loginPromptState pStyle = LOGIN_PROMPT_ECHO_OFF; - + if ((pam_get_item(*pamhp, PAM_USER, (void *) &username) == PAM_SUCCESS) && (username != NULL) && (*username != '\0')) { SetPrompt(login, LOGIN_PROMPT_USERNAME, -- 1.6.0.3