1/*
2 * Copyright 2003-2004 Waldemar Kornewald. All rights reserved.
3 * Copyright 2017 Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8#include "MessageDriverSettingsUtils.h"
9
10#include <PPPDefs.h>
11#include <settings_tools.h>
12#include <File.h>
13#include <Message.h>
14#include <String.h>
15
16#include <cstdio>
17
18
19static bool AddParameters(const BMessage& message, driver_settings *to);
20
21
22bool
23FindMessageParameter(const char *name, const BMessage& message, BMessage *save,
24	int32 *startIndex)
25{
26	// XXX: this should be removed when we can replace BMessage with something better
27	BString string;
28	int32 index = startIndex ? *startIndex : 0;
29	for(; message.FindMessage(MDSU_PARAMETERS, index, save) == B_OK; index++) {
30		if(save->FindString(MDSU_NAME, &string) == B_OK
31				&& string.ICompare(name) == 0) {
32			if(startIndex)
33				*startIndex = index;
34			return true;
35		}
36	}
37
38	return false;
39}
40
41
42static
43bool
44AddValues(const BMessage& message, driver_parameter *parameter)
45{
46	const char *value;
47	for(int32 index = 0; message.FindString(MDSU_VALUES, index, &value) == B_OK;
48			index++)
49		if(!add_driver_parameter_value(value, parameter))
50			return false;
51
52	return true;
53}
54
55
56inline
57bool
58AddParameters(const BMessage& message, driver_parameter *to)
59{
60	if(!to)
61		return false;
62
63	return AddParameters(message,
64		reinterpret_cast<driver_settings*>(&to->parameter_count));
65}
66
67
68static
69bool
70AddParameters(const BMessage& message, driver_settings *to)
71{
72	const char *name;
73	BMessage current;
74	driver_parameter *parameter;
75	for(int32 index = 0; message.FindMessage(MDSU_PARAMETERS, index,
76			&current) == B_OK; index++) {
77		name = current.FindString(MDSU_NAME);
78		parameter = new_driver_parameter(name);
79		if(!AddValues(current, parameter))
80			return false;
81
82		AddParameters(current, parameter);
83		add_driver_parameter(parameter, to);
84	}
85
86	return true;
87}
88
89
90driver_settings*
91MessageToDriverSettings(const BMessage& message)
92{
93	driver_settings *settings = new_driver_settings();
94
95	if(!AddParameters(message, settings)) {
96		free_driver_settings(settings);
97		return NULL;
98	}
99
100	return settings;
101}
102
103
104static
105bool
106AddParameter(const driver_parameter *parameter, BMessage *message)
107{
108	if(!parameter || !message)
109		return false;
110
111	if(parameter->name)
112		message->AddString(MDSU_NAME, parameter->name);
113	else
114		return false;
115
116	for(int32 index = 0; index < parameter->value_count; index++)
117		if(parameter->values[index])
118			message->AddString(MDSU_VALUES, parameter->values[index]);
119
120	for(int32 index = 0; index < parameter->parameter_count; index++) {
121		BMessage parameterMessage;
122		AddParameter(&parameter->parameters[index], &parameterMessage);
123		message->AddMessage(MDSU_PARAMETERS, &parameterMessage);
124	}
125
126	return true;
127}
128
129
130bool
131ReadMessageDriverSettings(const char *name, BMessage *message)
132{
133	if(!name || !message)
134		return false;
135
136	void *handle = load_driver_settings(name);
137	if(!handle)
138		return false;
139	const driver_settings *settings = get_driver_settings(handle);
140	if(!settings) {
141		unload_driver_settings(handle);
142		return false;
143	}
144
145	for(int32 index = 0; index < settings->parameter_count; index++) {
146		BMessage parameter;
147		AddParameter(&settings->parameters[index], &parameter);
148		message->AddMessage(MDSU_PARAMETERS, &parameter);
149	}
150
151	unload_driver_settings(handle);
152
153	return true;
154}
155
156
157static
158void
159EscapeWord(BString& word)
160{
161	word.ReplaceAll("\\", "\\\\");
162	word.ReplaceAll("#", "\\#");
163	word.ReplaceAll("\"", "\\\"");
164	word.ReplaceAll("\'", "\\\'");
165}
166
167
168static
169bool
170WriteParameter(BFile& file, const BMessage& parameter, int32 level)
171{
172	const char *name;
173	if(parameter.FindString(MDSU_NAME, &name) != B_OK || !name)
174		return false;
175
176	BString line, word(name);
177	EscapeWord(word);
178	bool needsEscaping = word.FindFirst(' ') >= 0;
179	line.SetTo('\t', level);
180	if(needsEscaping)
181		line << '\"';
182	line << word;
183	if(needsEscaping)
184		line << '\"';
185
186	for(int32 index = 0; parameter.FindString(MDSU_VALUES, index, &name) == B_OK;
187			index++)
188		if(name) {
189			line << ' ';
190			word = name;
191			EscapeWord(word);
192			needsEscaping = word.FindFirst(' ') >= 0;
193			if(needsEscaping)
194				line << '\"';
195			line << word;
196			if(needsEscaping)
197				line << '\"';
198		}
199
200	type_code type;
201	int32 parameterCount;
202	parameter.GetInfo(MDSU_PARAMETERS, &type, &parameterCount);
203
204	if(parameterCount > 0)
205		line << " {";
206
207	line << '\n';
208	file.Write(line.String(), line.Length());
209
210	if(parameterCount > 0) {
211		BMessage subParameter;
212		for(int32 index = 0; parameter.FindMessage(MDSU_PARAMETERS, index,
213				&subParameter) == B_OK; index++)
214			WriteParameter(file, subParameter, level + 1);
215
216		line.SetTo('\t', level);
217		line << "}\n";
218		file.Write(line.String(), line.Length());
219	}
220
221	return true;
222}
223
224
225bool
226WriteMessageDriverSettings(BFile& file, const BMessage& message)
227{
228	if(file.InitCheck() != B_OK || !file.IsWritable())
229		return false;
230
231	file.SetSize(0);
232	file.Seek(0, SEEK_SET);
233
234	BMessage parameter;
235	for(int32 index = 0; message.FindMessage(MDSU_PARAMETERS, index, &parameter) == B_OK;
236			index++) {
237		if(index > 0)
238			file.Write("\n", 1);
239		WriteParameter(file, parameter, 0);
240	}
241
242	return true;
243}
244