eat trailing space in preferred language string
[strongswan.git] / src / libimcv / plugins / imv_test / imv_test_state.c
1 /*
2 * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15 #include "imv_test_state.h"
16
17 #include <utils/lexparser.h>
18 #include <debug.h>
19
20 typedef struct private_imv_test_state_t private_imv_test_state_t;
21
22 /**
23 * Private data of an imv_test_state_t object.
24 */
25 struct private_imv_test_state_t {
26
27 /**
28 * Public members of imv_test_state_t
29 */
30 imv_test_state_t public;
31
32 /**
33 * TNCCS connection ID
34 */
35 TNC_ConnectionID connection_id;
36
37 /**
38 * TNCCS connection state
39 */
40 TNC_ConnectionState state;
41
42 /**
43 * IMV action recommendation
44 */
45 TNC_IMV_Action_Recommendation rec;
46
47 /**
48 * IMV evaluation result
49 */
50 TNC_IMV_Evaluation_Result eval;
51
52 /**
53 * IMC-IMV round-trip count
54 */
55 int rounds;
56
57 };
58
59 typedef struct entry_t entry_t;
60
61 /**
62 * Define an internal reason string entry
63 */
64 struct entry_t {
65 char *lang;
66 char *string;
67 };
68
69 /**
70 * Table of multi-lingual reason string entries
71 */
72 static entry_t reasons[] = {
73 { "en", "IMC Test was not configured with \"command = allow\"" },
74 { "de", "IMC Test wurde nicht mit \"command = allow\" konfiguriert" },
75 { "fr", "IMC Test n'etait pas configuré avec \"command = allow\"" },
76 { "pl", "IMC Test nie zostało skonfigurowany z \"command = allow\"" }
77 };
78
79 METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
80 private_imv_test_state_t *this)
81 {
82 return this->connection_id;
83 }
84
85 METHOD(imv_state_t, change_state, void,
86 private_imv_test_state_t *this, TNC_ConnectionState new_state)
87 {
88 this->state = new_state;
89 }
90
91 METHOD(imv_state_t, get_recommendation, void,
92 private_imv_test_state_t *this, TNC_IMV_Action_Recommendation *rec,
93 TNC_IMV_Evaluation_Result *eval)
94 {
95 *rec = this->rec;
96 *eval = this->eval;
97 }
98
99 METHOD(imv_state_t, set_recommendation, void,
100 private_imv_test_state_t *this, TNC_IMV_Action_Recommendation rec,
101 TNC_IMV_Evaluation_Result eval)
102 {
103 this->rec = rec;
104 this->eval = eval;
105 }
106
107 METHOD(imv_state_t, get_reason_string, bool,
108 private_imv_test_state_t *this, chunk_t preferred_language,
109 chunk_t *reason_string, chunk_t *reason_language)
110 {
111 chunk_t pref_lang, lang;
112 u_char *pos;
113 int i;
114
115 while (eat_whitespace(&preferred_language))
116 {
117 if (!extract_token(&pref_lang, ',', &preferred_language))
118 {
119 /* last entry in a comma-separated list or single entry */
120 pref_lang = preferred_language;
121 }
122
123 /* eat trailing whitespace */
124 pos = pref_lang.ptr + pref_lang.len - 1;
125 while (pref_lang.len && *pos-- == ' ')
126 {
127 pref_lang.len--;
128 }
129
130 for (i = 0 ; i < countof(reasons); i++)
131 {
132 lang = chunk_create(reasons[i].lang, strlen(reasons[i].lang));
133 if (chunk_equals(lang, pref_lang))
134 {
135 *reason_language = lang;
136 *reason_string = chunk_create(reasons[i].string,
137 strlen(reasons[i].string));
138 return TRUE;
139 }
140 }
141 }
142
143 /* no preferred language match found - use the default language */
144 *reason_string = chunk_create(reasons[0].string,
145 strlen(reasons[0].string));
146 *reason_language = chunk_create(reasons[0].lang,
147 strlen(reasons[0].lang));
148 return TRUE;
149 }
150
151 METHOD(imv_state_t, destroy, void,
152 private_imv_test_state_t *this)
153 {
154 free(this);
155 }
156
157 METHOD(imv_test_state_t, set_rounds, void,
158 private_imv_test_state_t *this, int rounds)
159 {
160 this->rounds = rounds;
161 }
162
163 METHOD(imv_test_state_t, another_round, bool,
164 private_imv_test_state_t *this)
165 {
166 return (this->rounds-- > 0);
167 }
168
169 /**
170 * Described in header.
171 */
172 imv_state_t *imv_test_state_create(TNC_ConnectionID connection_id)
173 {
174 private_imv_test_state_t *this;
175
176 INIT(this,
177 .public = {
178 .interface = {
179 .get_connection_id = _get_connection_id,
180 .change_state = _change_state,
181 .get_recommendation = _get_recommendation,
182 .set_recommendation = _set_recommendation,
183 .get_reason_string = _get_reason_string,
184 .destroy = _destroy,
185 },
186 .set_rounds = _set_rounds,
187 .another_round = _another_round,
188 },
189 .state = TNC_CONNECTION_STATE_CREATE,
190 .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
191 .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
192 .connection_id = connection_id,
193 );
194
195 return &this->public.interface;
196 }
197
198