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