1 /*
2  * strings.c: Implementation of default UI strings
3  *
4  * Copyright (C) 2017 Frank Morgner <frankmorgner@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 
21 #include "libopensc/internal.h"
22 #include "ui/strings.h"
23 #include <locale.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 enum ui_langs {
28 	EN,
29 	DE,
30 };
31 
get_inserted_text(struct sc_pkcs15_card * p15card,struct sc_atr * atr)32 static const char *get_inserted_text(struct sc_pkcs15_card *p15card, struct sc_atr *atr)
33 {
34 	static char text[3*SC_MAX_ATR_SIZE] = {0};
35 	const char prefix[] = "ATR: ";
36 
37 	if (p15card && p15card->card
38 			&& p15card->card->name) {
39 		return p15card->card->name;
40 	} else if (p15card && p15card->card
41 			&& p15card->card->reader && p15card->card->reader->name) {
42 		return p15card->card->reader->name;
43 	}
44 
45 	if (!atr)
46 		return NULL;
47 
48 	strcpy(text, prefix);
49 	sc_bin_to_hex(atr->value, atr->len, text + (sizeof prefix) - 1,
50 			sizeof(text) - (sizeof prefix) - 1, ':');
51 
52 	return text;
53 }
54 
get_removed_text(struct sc_pkcs15_card * p15card)55 static const char *get_removed_text(struct sc_pkcs15_card *p15card)
56 {
57 	if (p15card && p15card->card && p15card->card->reader
58 			&& p15card->card->reader->name) {
59 		return p15card->card->reader->name;
60 	}
61 
62 	return NULL;
63 }
64 
ui_get_config_str(struct sc_context * ctx,struct sc_atr * atr,const char * flag_name,const char * ret_default)65 static const char *ui_get_config_str(struct sc_context *ctx,
66 		struct sc_atr *atr, const char *flag_name, const char *ret_default)
67 {
68 	const char *ret = ret_default;
69 
70 	scconf_block *atrblock = _sc_match_atr_block(ctx, NULL, atr);
71 
72 	if (atrblock)
73 		ret = scconf_get_str(atrblock, flag_name, ret_default);
74 
75 	return ret;
76 }
77 
find_lang_str(const char * str,enum ui_langs * lang)78 static int find_lang_str(const char *str, enum ui_langs *lang)
79 {
80 	if (str) {
81 		if (0 == strncmp(str, "de", 2)) {
82 			if (lang) {
83 				*lang = DE;
84 			}
85 			return 1;
86 		} else if (0 == strncmp(str, "en", 2)) {
87 			if (lang) {
88 				*lang = EN;
89 			}
90 			return 1;
91 		}
92 	}
93 
94 	return 0;
95 }
96 
ui_get_str(struct sc_context * ctx,struct sc_atr * atr,struct sc_pkcs15_card * p15card,enum ui_str id)97 const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr,
98 		struct sc_pkcs15_card *p15card, enum ui_str id)
99 {
100 	enum ui_langs lang = EN;
101 	const char *str, *option;
102 
103 	/* load option strings */
104 	switch (id) {
105 		case MD_PINPAD_DLG_TITLE:
106 			option = "md_pinpad_dlg_title";
107 			break;
108 		case MD_PINPAD_DLG_MAIN:
109 			option = "md_pinpad_dlg_main";
110 			break;
111 		case MD_PINPAD_DLG_CONTENT_USER:
112 			option = "md_pinpad_dlg_content_user";
113 			break;
114 		case MD_PINPAD_DLG_CONTENT_USER_SIGN:
115 			option = "md_pinpad_dlg_content_user_sign";
116 			break;
117 		case MD_PINPAD_DLG_CONTENT_ADMIN:
118 			option = "md_pinpad_dlg_content_admin";
119 			break;
120 		case MD_PINPAD_DLG_EXPANDED:
121 			option = "md_pinpad_dlg_expanded";
122 			break;
123 		case MD_PINPAD_DLG_ICON:
124 			option = "md_pinpad_dlg_icon";
125 			break;
126 		case NOTIFY_CARD_INSERTED:
127 			option = "notify_card_inserted";
128 			break;
129 		case NOTIFY_CARD_INSERTED_TEXT:
130 			option = "notify_card_inserted_text";
131 			break;
132 		case NOTIFY_CARD_REMOVED:
133 			option = "notify_card_removed";
134 			break;
135 		case NOTIFY_CARD_REMOVED_TEXT:
136 			option = "notify_card_removed_text";
137 			break;
138 		case NOTIFY_PIN_GOOD:
139 			option = "notify_pin_good";
140 			break;
141 		case NOTIFY_PIN_GOOD_TEXT:
142 			option = "notify_pin_good_text";
143 			break;
144 		case NOTIFY_PIN_BAD:
145 			option = "notify_pin_bad";
146 			break;
147 		case NOTIFY_PIN_BAD_TEXT:
148 			option = "notify_pin_bad_text";
149 			break;
150 		case MD_PINPAD_DLG_VERIFICATION:
151 			option = "md_pinpad_dlg_verification";
152 			break;
153 		default:
154 			option = NULL;
155 			break;
156 	}
157 
158 	/* load language */
159 	/* card's language supersedes system's language */
160 	if (!p15card || !p15card->tokeninfo
161 			|| !find_lang_str(p15card->tokeninfo->preferred_language, &lang)) {
162 #ifdef _WIN32
163 		LANGID langid = GetUserDefaultUILanguage();
164 		if ((langid & LANG_GERMAN) == LANG_GERMAN) {
165 			lang = DE;
166 		}
167 #else
168 		/* LANGUAGE supersedes locale */
169 		if (!find_lang_str(getenv("LANGUAGE"), &lang)) {
170 			/* XXX Should we use LC_MESSAGES instead? */
171 			find_lang_str(setlocale(LC_ALL, ""), &lang);
172 		}
173 #endif
174 	}
175 
176 	/* load default strings */
177 	switch (lang) {
178 		case DE:
179 			switch (id) {
180 				case MD_PINPAD_DLG_TITLE:
181 					str = "Windows-Sicherheit";
182 					break;
183 				case MD_PINPAD_DLG_MAIN:
184 					str = "OpenSC Smartcard-Anbieter";
185 					break;
186 				case MD_PINPAD_DLG_CONTENT_USER:
187 					str = "Bitte geben Sie Ihre PIN auf dem PIN-Pad ein.";
188 					break;
189 				case MD_PINPAD_DLG_CONTENT_USER_SIGN:
190 					str = "Bitte geben Sie Ihre PIN für die digitale Signatur auf dem PIN-Pad ein.";
191 					break;
192 				case MD_PINPAD_DLG_CONTENT_ADMIN:
193 					str = "Bitte geben Sie Ihre PIN zum Entsperren der Nutzer-PIN auf dem PIN-Pad ein.";
194 					break;
195 				case MD_PINPAD_DLG_EXPANDED:
196 					str = "Dieses Fenster wird automatisch geschlossen, wenn die PIN am PIN-Pad eingegeben wurde (Timeout typischerweise nach 30 Sekunden).";
197 					break;
198 				case NOTIFY_CARD_INSERTED:
199 					if (p15card && p15card->card && p15card->card->name) {
200 						str = "Smartcard kann jetzt verwendet werden";
201 					} else {
202 						str = "Smartcard erkannt";
203 					}
204 					break;
205 				case NOTIFY_CARD_INSERTED_TEXT:
206 					str = get_inserted_text(p15card, atr);
207 					break;
208 				case NOTIFY_CARD_REMOVED:
209 					str = "Smartcard entfernt";
210 					break;
211 				case NOTIFY_CARD_REMOVED_TEXT:
212 					str = get_removed_text(p15card);
213 					break;
214 				case NOTIFY_PIN_GOOD:
215 					str = "PIN verifiziert";
216 					break;
217 				case NOTIFY_PIN_GOOD_TEXT:
218 					str = "Smartcard ist entsperrt";
219 					break;
220 				case NOTIFY_PIN_BAD:
221 					str = "PIN nicht verifiziert";
222 					break;
223 				case NOTIFY_PIN_BAD_TEXT:
224 					str = "Smartcard ist gesperrt";
225 					break;
226 				case MD_PINPAD_DLG_VERIFICATION:
227 					str = "Sofort PIN am PIN-Pad abfragen";
228 					break;
229 
230 				case MD_PINPAD_DLG_CONTROL_COLLAPSED:
231 				case MD_PINPAD_DLG_CONTROL_EXPANDED:
232 					str = "Weitere Informationen";
233 					break;
234 				case MD_PINPAD_DLG_CANCEL:
235 					str = "Abbrechen";
236 					break;
237 				case NOTIFY_EXIT:
238 					str = "Beenden";
239 					break;
240 				default:
241 					str = NULL;
242 					break;
243 			}
244 			break;
245 		case EN:
246 		default:
247 			switch (id) {
248 				case MD_PINPAD_DLG_TITLE:
249 					str = "Windows Security";
250 					break;
251 				case MD_PINPAD_DLG_MAIN:
252 					str = "OpenSC Smart Card Provider";
253 					break;
254 				case MD_PINPAD_DLG_CONTENT_USER:
255 					str = "Please enter your PIN on the PIN pad.";
256 					break;
257 				case MD_PINPAD_DLG_CONTENT_USER_SIGN:
258 					str = "Please enter your digital signature PIN on the PIN pad.";
259 					break;
260 				case MD_PINPAD_DLG_CONTENT_ADMIN:
261 					str = "Please enter your PIN to unblock the user PIN on the PIN pad.";
262 					break;
263 				case MD_PINPAD_DLG_EXPANDED:
264 					str = "This window will be closed automatically after the PIN has been submitted on the PIN pad (timeout typically after 30 seconds).";
265 					break;
266 				case NOTIFY_CARD_INSERTED:
267 					if (p15card && p15card->card && p15card->card->name) {
268 						str = "Smart card is ready to use";
269 					} else {
270 						str = "Smart card detected";
271 					}
272 					break;
273 				case NOTIFY_CARD_INSERTED_TEXT:
274 					str = get_inserted_text(p15card, atr);
275 					break;
276 				case NOTIFY_CARD_REMOVED:
277 					str = "Smart card removed";
278 					break;
279 				case NOTIFY_CARD_REMOVED_TEXT:
280 					str = get_removed_text(p15card);
281 					break;
282 				case NOTIFY_PIN_GOOD:
283 					str = "PIN verified";
284 					break;
285 				case NOTIFY_PIN_GOOD_TEXT:
286 					str = "Smart card is unlocked";
287 					break;
288 				case NOTIFY_PIN_BAD:
289 					str = "PIN not verified";
290 					break;
291 				case NOTIFY_PIN_BAD_TEXT:
292 					str = "Smart card is locked";
293 					break;
294 				case MD_PINPAD_DLG_VERIFICATION:
295 					str = "Immediately request PIN on PIN-Pad";
296 					break;
297 
298 				case MD_PINPAD_DLG_CONTROL_COLLAPSED:
299 				case MD_PINPAD_DLG_CONTROL_EXPANDED:
300 					str = "Click here for more information";
301 					break;
302 				case MD_PINPAD_DLG_CANCEL:
303 					str = "Cancel";
304 					break;
305 				case NOTIFY_EXIT:
306 					str = "Exit";
307 					break;
308 				default:
309 					str = NULL;
310 					break;
311 			}
312 			break;
313 	}
314 
315 	/* user's strings supersede default strings */
316 	if (option != NULL) {
317 		/* overwrite str with the user's choice */
318 		str = ui_get_config_str(ctx, atr, option, str);
319 	}
320 
321 	return str;
322 }
323