1 /***************************************************************************
2 wxutil.cpp - description
3 -------------------
4 begin : Thu Aug 14 2003
5 copyright : (C) 2003 by ARRL
6 author : Jon Bloom
7 email : jbloom@arrl.org
8 revision : $Id$
9 ***************************************************************************/
10
11 #ifdef HAVE_CONFIG_H
12 #include "sysconfig.h"
13 #endif
14
15 #include "wxutil.h"
16 #include <wx/dir.h>
17 #include <wx/config.h>
18 #include <wx/filename.h>
19 #include "tqsllib.h"
20 #include "tqslerrno.h"
21
22 wxSize
getTextSize(wxWindow * win)23 getTextSize(wxWindow *win) {
24 wxClientDC dc(win);
25 wxCoord char_width, char_height;
26 dc.GetTextExtent(wxString(wxT("M")), &char_width, &char_height);
27 return wxSize(char_width, char_height);
28 }
29
30 // isspace() called on extended chars in UTF-8 raises asserts in
31 // the windows C++ libs. Don't call isspace() if out of range.
32
isspc(int c)33 static inline int isspc(int c) {
34 if (c < 0 || c > 255)
35 return 0;
36 return isspace(c);
37 }
38
39 wxString
wrapString(wxWindow * win,wxString in,int length)40 wrapString(wxWindow *win, wxString in, int length) {
41 wxClientDC dc(win);
42 wxCoord textwidth, textheight;
43 wxString out = wxT("");
44 wxString str = in;
45 do {
46 dc.GetTextExtent(str, &textwidth, &textheight);
47 if (textwidth > length) {
48 int index = 0;
49 do {
50 str = str.Left(str.Length()-1);
51 index++;
52 dc.GetTextExtent(str, &textwidth, &textheight);
53
54 wxString c = wxString(str.Last());
55
56 if (textwidth < length && isspc(c[0]))
57 break;
58 } while (1);
59 if (out != wxT(""))
60 out += wxT("\n");
61 out += str;
62 str = in.Right(index);
63 } else {
64 break;
65 }
66 } while (1);
67 if (out != wxT(""))
68 out += wxT("\n");
69 out += str;
70 return out;
71 }
72
73 // Strip special characters from a string prior to writing to XML
74 wxString
urlEncode(wxString & str)75 urlEncode(wxString& str) {
76 str.Replace(wxT("&"), wxT("&"), true);
77 str.Replace(wxT("\""), wxT("""), true);
78 str.Replace(wxT("'"), wxT("'"), true);
79 str.Replace(wxT("<"), wxT("<"), true);
80 str.Replace(wxT(">"), wxT(">"), true);
81 return str;
82 }
83
84 // Convert UTF-8 string to UCS-2 (MS Unicode default)
85 int
utf8_to_ucs2(const char * in,char * out,size_t buflen)86 utf8_to_ucs2(const char *in, char *out, size_t buflen) {
87 size_t len = 0;
88
89 while (len < buflen) {
90 if ((unsigned char)*in < 0x80) { // ASCII range
91 *out++ = *in;
92 if (*in++ == '\0') // End of string
93 break;
94 len++;
95 } else if (((unsigned char)*in & 0xc0) == 0xc0) { // Two-byte
96 *out++ = ((in[0] & 0x1f) << 6) | (in[1] & 0x3f);
97 in += 2;
98 len++;
99 } else if (((unsigned char)*in & 0xe0) == 0xe0) { // Three-byte
100 unsigned short three = ((in[0] & 0x0f) << 12) |
101 ((in[1] & 0x3f) << 6) |
102 (in[2] & 0x3f);
103 *out++ = (three & 0xff00) >> 8;
104 len++;
105 if (len < buflen) {
106 *out++ = (three & 0xff);
107 len++;
108 }
109 in += 3;
110 } else {
111 in++; // Unknown. Skip input.
112 }
113 }
114 out[len-1] = '\0';
115 return len;
116 }
117 int
getPasswordFromUser(wxString & result,const wxString & message,const wxString & caption,const wxString & defaultValue,wxWindow * parent)118 getPasswordFromUser(wxString& result, const wxString& message, const wxString& caption, const wxString& defaultValue, wxWindow *parent) {
119 long style = wxTextEntryDialogStyle;
120
121 wxPasswordEntryDialog dialog(parent, message, caption, defaultValue, style);
122
123 int ret = dialog.ShowModal();
124 if (ret == wxID_OK)
125 result = dialog.GetValue();
126
127 return ret;
128 }
129
130 static const char *error_strings[] = {
131 __("Memory allocation failure"), /* TQSL_ALLOC_ERROR */
132 __("Unable to initialize random number generator"), /* TQSL_RANDOM_ERROR */
133 __("Invalid argument"), /* TQSL_ARGUMENT_ERROR */
134 __("Operator aborted operation"), /* TQSL_OPERATOR_ABORT */
135 __("No Certificate Request matches the selected Callsign Certificate"),/* TQSL_NOKEY_ERROR */
136 __("Buffer too small"), /* TQSL_BUFFER_ERROR */
137 __("Invalid date format"), /* TQSL_INVALID_DATE */
138 __("Certificate not initialized for signing"), /* TQSL_SIGNINIT_ERROR */
139 __("Password not correct"), /* TQSL_PASSWORD_ERROR */
140 __("Expected name"), /* TQSL_EXPECTED_NAME */
141 __("Name exists"), /* TQSL_NAME_EXISTS */
142 __("Data for this DXCC entity could not be found"), /* TQSL_NAME_NOT_FOUND */
143 __("Invalid time format"), /* TQSL_INVALID_TIME */
144 __("QSO date is not within the date range specified on your Callsign Certificate"), /* TQSL_CERT_DATE_MISMATCH */
145 __("Certificate provider not found"), /* TQSL_PROVIDER_NOT_FOUND */
146 __("No callsign certificate for key"), /* TQSL_CERT_KEY_ONLY */
147 __("Configuration file cannot be opened"), /* TQSL_CONFIG_ERROR */
148 __("Callsign Certificate or Certificate Request not found"),/* TQSL_CERT_NOT_FOUND */
149 __("PKCS#12 file not TQSL compatible"), /* TQSL_PKCS12_ERROR */
150 __("Callsign Certificate not TQSL compatible"), /* TQSL_CERT_TYPE_ERROR */
151 __("Date out of range"), /* TQSL_DATE_OUT_OF_RANGE */
152 __("Duplicate QSO suppressed"), /* TQSL_DUPLICATE_QSO */
153 __("Database error"), /* TQSL_DB_ERROR */
154 __("The selected station location could not be found"), /* TQSL_LOCATION_NOT_FOUND */
155 __("The selected callsign could not be found"), /* TQSL_CALL_NOT_FOUND */
156 __("The TQSL configuration file cannot be parsed"), /* TQSL_CONFIG_SYNTAX_ERROR */
157 __("This file can not be processed due to a system error"), /* TQSL_FILE_SYSTEM_ERROR */
158 __("The format of this file is incorrect."), /* TQSL_FILE_SYNTAX_ERROR */
159 __("Callsign certificate could not be installed"), /* TQSL_CERT_ERROR */
160 };
161
162 static wxString
getLocalizedErrorString_v(int err)163 getLocalizedErrorString_v(int err) {
164 int adjusted_err;
165 wxString buf;
166
167 if (err == 0)
168 return _("NO ERROR");
169 if (err == TQSL_CUSTOM_ERROR) {
170 if (tQSL_CustomError[0] == 0) {
171 return _("Unknown custom error");
172 } else {
173 return wxString::FromUTF8(tQSL_CustomError);
174 }
175 }
176 if (err == TQSL_DB_ERROR && tQSL_CustomError[0] != 0) {
177 return wxString::Format(_("Database Error: %hs"), tQSL_CustomError);
178 }
179
180 if (err == TQSL_SYSTEM_ERROR || err == TQSL_FILE_SYSTEM_ERROR) {
181 if (strlen(tQSL_ErrorFile) > 0) {
182 buf = wxString::Format(_("System error: %hs : %hs"),
183 tQSL_ErrorFile, strerror(tQSL_Errno));
184 tQSL_ErrorFile[0] = '\0';
185 } else {
186 buf = wxString::Format(_("System error: %hs"),
187 strerror(tQSL_Errno));
188 }
189 return buf;
190 }
191 if (err == TQSL_FILE_SYNTAX_ERROR) {
192 if (strlen(tQSL_ErrorFile) > 0) {
193 buf = wxString::Format(_("File syntax error: %hs"),
194 tQSL_ErrorFile);
195 tQSL_ErrorFile[0] = '\0';
196 } else {
197 buf = _("File syntax error");
198 }
199 return buf;
200 }
201 if (err == TQSL_OPENSSL_ERROR) {
202 // Get error details from tqsllib as we have
203 // no visibility into the tqsllib openssl context
204 const char *msg = tqsl_getErrorString();
205 return wxString::FromUTF8(msg);
206 }
207 if (err == TQSL_ADIF_ERROR) {
208 if (strlen(tQSL_ErrorFile) > 0) {
209 buf = wxString::Format(wxT("%hs: %hs"), tQSL_ErrorFile, tqsl_adifGetError(tQSL_ADIF_Error));
210 tQSL_ErrorFile[0] = '\0';
211 } else {
212 buf = wxString::FromUTF8(tqsl_adifGetError(tQSL_ADIF_Error));
213 }
214 return buf;
215 }
216 if (err == TQSL_CABRILLO_ERROR) {
217 if (strlen(tQSL_ErrorFile) > 0) {
218 buf = wxString::Format(wxT("%hs: %hs"),
219 tQSL_ErrorFile, tqsl_cabrilloGetError(tQSL_Cabrillo_Error));
220 tQSL_ErrorFile[0] = '\0';
221 } else {
222 buf = wxString::FromUTF8(tqsl_cabrilloGetError(tQSL_Cabrillo_Error));
223 }
224 return buf;
225 }
226 if (err == TQSL_OPENSSL_VERSION_ERROR) {
227 // No visibility into the tqsllib openssl context
228 const char *msg = tqsl_getErrorString();
229 return wxString::FromUTF8(msg);
230 }
231 if (err == TQSL_CERT_NOT_FOUND && tQSL_ImportCall[0] != '\0') {
232 return wxString::Format(_("Callsign Certificate or Certificate Request not found for callsign %hs serial %ld"),
233 tQSL_ImportCall, tQSL_ImportSerial);
234 }
235 adjusted_err = err - TQSL_ERROR_ENUM_BASE;
236 if (adjusted_err < 0 ||
237 adjusted_err >=
238 static_cast<int>(sizeof error_strings / sizeof error_strings[0])) {
239 return wxString::Format(_("Invalid error code: %d"), err);
240 }
241 return wxGetTranslation(wxString::FromUTF8(error_strings[adjusted_err]));
242 }
243
244 wxString
getLocalizedErrorString()245 getLocalizedErrorString() {
246 wxString cp = getLocalizedErrorString_v(tQSL_Error);
247 tQSL_Error = TQSL_NO_ERROR;
248 tQSL_Errno = 0;
249 tQSL_ErrorFile[0] = 0;
250 tQSL_CustomError[0] = 0;
251 return cp;
252 }
253