1 /*
2  * Copyright 2011 kubtek <kubtek@mail.com>
3  *
4  * This file is part of StarDict.
5  *
6  * StarDict is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * StarDict 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with StarDict.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <glib.h>
21 #include <glib/gi18n.h>
22 #include <glib/gstdio.h>
23 #include "dictmanage.h"
24 #include "lib/file-utils.h"
25 #include "conf.h"
26 #include "stardict.h"
27 #include "lib/pluginmanager.h"
28 #include "lib/verify_dict.h"
29 
30 class GetAllDictList {
31 public:
GetAllDictList(std::list<DictItemId> & dict_all_list_)32 	GetAllDictList(std::list<DictItemId> &dict_all_list_) :
33 		dict_all_list(dict_all_list_) {}
operator ()(const std::string & url,bool disable)34 	void operator()(const std::string& url, bool disable) {
35 		dict_all_list.push_back(DictItemId(url));
36 	}
37 private:
38 	std::list<DictItemId> &dict_all_list;
39 };
40 
41 class GetAllPluginList {
42 public:
GetAllPluginList(std::list<DictItemId> & plugin_all_list_)43 	GetAllPluginList(std::list<DictItemId> &plugin_all_list_) :
44 		plugin_all_list(plugin_all_list_) {}
operator ()(const std::string & url,bool disable)45 	void operator()(const std::string& url, bool disable) {
46 		plugin_all_list.push_back(DictItemId(url));
47 	}
48 private:
49 	std::list<DictItemId> &plugin_all_list;
50 };
51 
52 /* List of dictionaries that are present on the hard disk in known directories. */
get_all_dict_list(std::list<DictItemId> & dict_all_list)53 static void get_all_dict_list(std::list<DictItemId> &dict_all_list)
54 {
55 	std::list<std::string> dict_order_list;
56 	std::list<std::string> dict_disable_list;
57 #ifdef _WIN32
58 	std::list<std::string> dict_dirs_list;
59 	{
60 		const std::list<std::string>& dict_dirs_list_rel
61 			= conf->get_strlist("/apps/stardict/manage_dictionaries/dict_dirs_list");
62 		abs_path_to_data_dir(dict_dirs_list_rel, dict_dirs_list);
63 	}
64 #else
65 	const std::list<std::string>& dict_dirs_list
66 		= conf->get_strlist("/apps/stardict/manage_dictionaries/dict_dirs_list");
67 #endif
68 	for_each_file_restricted(
69 		dict_dirs_list, ".ifo",
70 		dict_order_list, dict_disable_list, GetAllDictList(dict_all_list));
71 }
72 
73 /* List of plugins that are present on the hard disk in known directories. */
get_all_plugin_list(std::list<DictItemId> & plugin_all_list)74 static void get_all_plugin_list(std::list<DictItemId> &plugin_all_list)
75 {
76 	std::list<std::string> plugin_order_list;
77 	std::list<std::string> plugin_disable_list;
78 	std::list<std::string> plugins_dirs;
79 	plugins_dirs.push_back(conf_dirs->get_plugin_dir());
80 	for_each_file(plugins_dirs, "." G_MODULE_SUFFIX, plugin_order_list,
81 		plugin_disable_list, GetAllPluginList(plugin_all_list));
82 }
83 
84 /* Remove all items of the var_list that are not in the all_list */
remove_list_items(std::list<DictItemId> & var_list,const std::list<DictItemId> & all_list)85 static void remove_list_items(std::list<DictItemId> &var_list,
86 	const std::list<DictItemId> &all_list)
87 {
88 	for(std::list<DictItemId>::iterator i = var_list.begin(); i != var_list.end();) {
89 		if(all_list.end() == std::find(all_list.begin(), all_list.end(), *i))
90 			i = var_list.erase(i);
91 		else
92 			++i;
93 	}
94 }
95 
96 /* rename IDs in the var_list to match spelling in the all_list
97 On Windows DictItemId-s are compared case-insensitivly,
98 we may modify IDs so they'll be binary equal.
99 all_list - contains all possible IDs, it prescribe the preferrend spelling of them.
100 var_list - list of IDs that should be modified according to the all_list.
101 */
update_list_items(std::list<DictItemId> & var_list,const std::list<DictItemId> & all_list)102 static void update_list_items(std::list<DictItemId> &var_list,
103 	const std::list<DictItemId> &all_list)
104 {
105 #ifdef _WIN32
106 	for(std::list<DictItemId>::iterator i = var_list.begin(); i != var_list.end(); ++i) {
107 		std::list<DictItemId>::const_iterator j = std::find(all_list.begin(), all_list.end(), *i);
108 		g_assert(j != all_list.end());
109 		*i = *j;
110 	}
111 #endif
112 }
113 
get_active_group(void)114 std::list<DictManageGroup>::iterator DictManageInfo::get_active_group(void)
115 {
116 	std::list<DictManageGroup>::iterator i;
117 	for (i = groups.begin(); i != groups.end(); ++i) {
118 		if (i->name == active_group)
119 			break;
120 	}
121 	if (i == groups.end()) {
122 		i = groups.begin();
123 		active_group = (i != groups.end()) ? i->name : "";
124 	}
125 	return i;
126 }
127 
128 std::list<DictManageGroup>::iterator
set_active_group(const std::string & new_group)129 DictManageInfo::set_active_group(const std::string& new_group)
130 {
131 	std::list<DictManageGroup>::iterator i;
132 	for (i = groups.begin(); i != groups.end(); ++i) {
133 		if (i->name == new_group)
134 			break;
135 	}
136 	if (i == groups.end()) {
137 		if (groups.empty()) {
138 			DictManageGroup group;
139 			group.name = _("Default Group");
140 			groups.push_back(group);
141 		}
142 		i = groups.begin();
143 	}
144 	active_group = i->name;
145 	return i;
146 }
147 
148 struct config_ParseUserData {
149 	DictManageInfo *info;
150 	bool in_querydict;
151 	bool in_scandict;
152 };
153 
config_parse_start_element(GMarkupParseContext * context,const gchar * element_name,const gchar ** attribute_names,const gchar ** attribute_values,gpointer user_data,GError ** error)154 static void config_parse_start_element(GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error)
155 {
156 	config_ParseUserData *Data = (config_ParseUserData *)user_data;
157 	if (strcmp(element_name, "dictgroup")==0) {
158 		const char *name = NULL;
159 		size_t i = 0;
160 		while (attribute_names[i]) {
161 			if (strcmp(attribute_names[i], "name")==0) {
162 				name = attribute_values[i];
163 				break;
164 			}
165 			i++;
166 		}
167 		if (!name)
168 			name = _("Default Group");
169 		DictManageGroup group;
170 		group.name = name;
171 		Data->info->groups.push_back(group);
172 	} else if (strcmp(element_name, "querydict")==0) {
173 		Data->in_querydict = true;
174 	} else if (strcmp(element_name, "scandict")==0) {
175 		Data->in_scandict = true;
176 	} else if (strcmp(element_name, "localdict")==0) {
177 		bool enable = true;
178 		const gchar *file = NULL;
179 		size_t i = 0;
180 		while (attribute_names[i]) {
181 			if (strcmp(attribute_names[i], "enable")==0) {
182 				if (strcmp(attribute_values[i], "false")==0) {
183 					enable = false;
184 				}
185 			} else if (strcmp(attribute_names[i], "file")==0) {
186 				file = attribute_values[i];
187 			}
188 			i++;
189 		}
190 		if (file) {
191 			DictManageItem item;
192 			item.type = LOCAL_DICT;
193 			item.enable = enable;
194 #ifdef _WIN32
195 			item.file_or_id = DictItemId(abs_path_to_data_dir(file));
196 #else
197 			item.file_or_id = DictItemId(file);
198 #endif
199 			if (Data->in_querydict) {
200 				Data->info->groups.back().querydict.push_back(item);
201 			} else if (Data->in_scandict) {
202 				Data->info->groups.back().scandict.push_back(item);
203 			}
204 		}
205 	} else if (strcmp(element_name, "virtualdict")==0) {
206 		bool enable = true;
207 		const gchar *id = NULL;
208 		size_t i = 0;
209 		while (attribute_names[i]) {
210 			if (strcmp(attribute_names[i], "enable")==0) {
211 				if (strcmp(attribute_values[i], "false")==0) {
212 					enable = false;
213 				}
214 			} else if (strcmp(attribute_names[i], "id")==0) {
215 				id = attribute_values[i];
216 			}
217 			i++;
218 		}
219 		if (id) {
220 			DictManageItem item;
221 			item.type = VIRTUAL_DICT;
222 			item.enable = enable;
223 #ifdef _WIN32
224 			item.file_or_id = DictItemId(abs_path_to_data_dir(id));
225 #else
226 			item.file_or_id = DictItemId(id);
227 #endif
228 			if (Data->in_querydict) {
229 				Data->info->groups.back().querydict.push_back(item);
230 			} else if (Data->in_scandict) {
231 				Data->info->groups.back().scandict.push_back(item);
232 			}
233 		}
234 	} else if (strcmp(element_name, "netdict")==0) {
235 		bool enable = true;
236 		const gchar *id = NULL;
237 		size_t i = 0;
238 		while (attribute_names[i]) {
239 			if (strcmp(attribute_names[i], "enable")==0) {
240 				if (strcmp(attribute_values[i], "false")==0) {
241 					enable = false;
242 				}
243 			} else if (strcmp(attribute_names[i], "id")==0) {
244 				id = attribute_values[i];
245 			}
246 			i++;
247 		}
248 		if (id) {
249 			DictManageItem item;
250 			item.type = NET_DICT;
251 			item.enable = enable;
252 #ifdef _WIN32
253 			item.file_or_id = DictItemId(abs_path_to_data_dir(id));
254 #else
255 			item.file_or_id = DictItemId(id);
256 #endif
257 			if (Data->in_querydict) {
258 				Data->info->groups.back().querydict.push_back(item);
259 			} else if (Data->in_scandict) {
260 				Data->info->groups.back().scandict.push_back(item);
261 			}
262 		}
263 	}
264 }
265 
config_parse_end_element(GMarkupParseContext * context,const gchar * element_name,gpointer user_data,GError ** error)266 static void config_parse_end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error)
267 {
268 	config_ParseUserData *Data = (config_ParseUserData *)user_data;
269 	if (strcmp(element_name, "querydict")==0) {
270 		Data->in_querydict = false;
271 	} else if (strcmp(element_name, "scandict")==0) {
272 		Data->in_scandict = false;
273 	}
274 }
275 
DictConfigXmlToInfo(const char * configxml,DictManageInfo & info)276 static void DictConfigXmlToInfo(const char *configxml, DictManageInfo &info)
277 {
278 	info.groups.clear();
279 	config_ParseUserData Data;
280 	Data.info = &info;
281 	Data.in_querydict = false;
282 	Data.in_scandict = false;
283 	GMarkupParser parser;
284 	parser.start_element = config_parse_start_element;
285 	parser.end_element = config_parse_end_element;
286 	parser.text = NULL;
287 	parser.passthrough = NULL;
288 	parser.error = NULL;
289 	GMarkupParseContext* context = g_markup_parse_context_new(&parser, (GMarkupParseFlags)0, &Data, NULL);
290 	g_markup_parse_context_parse(context, configxml, -1, NULL);
291 	g_markup_parse_context_end_parse(context, NULL);
292 	g_markup_parse_context_free(context);
293 }
294 
itemlist_to_xml(std::string & newxml,std::list<DictManageItem> & item_list,bool is_query)295 static void itemlist_to_xml(std::string &newxml, std::list<DictManageItem> &item_list, bool is_query)
296 {
297 	if (is_query)
298 		newxml += "<querydict>";
299 	else
300 		newxml += "<scandict>";
301 	gchar *estr;
302 	for (std::list<DictManageItem>::iterator j = item_list.begin(); j != item_list.end(); ++j) {
303 		if (j->type == LOCAL_DICT)
304 			newxml += "<localdict";
305 		else if (j->type == VIRTUAL_DICT)
306 			newxml += "<virtualdict";
307 		else
308 			newxml += "<netdict";
309 		newxml += " enable=\"";
310 		if (j->enable)
311 			newxml += "true";
312 		else
313 			newxml += "false";
314 		if (j->type == LOCAL_DICT)
315 			newxml  += "\" file=\"";
316 		else
317 			newxml += "\" id=\"";
318 #ifdef _WIN32
319 		estr = g_markup_escape_text(rel_path_to_data_dir(j->file_or_id.str()).c_str(), -1);
320 #else
321 		estr = g_markup_escape_text(j->file_or_id.c_str(), -1);
322 #endif
323 		newxml += estr;
324 		g_free(estr);
325 		newxml  += "\"/>";
326 	}
327 	if (is_query)
328 		newxml += "</querydict>";
329 	else
330 		newxml += "</scandict>";
331 }
332 
InfoToConfigXml(std::string & newxml,DictManageInfo & info)333 static void InfoToConfigXml(std::string &newxml, DictManageInfo &info)
334 {
335 	newxml.clear();
336 	gchar *estr;
337 	for (std::list<DictManageGroup>::iterator i = info.groups.begin(); i != info.groups.end(); ++i) {
338 		newxml += "<dictgroup name=\"";
339 		estr = g_markup_escape_text(i->name.c_str(), -1);
340 		newxml += estr;
341 		g_free(estr);
342 		newxml += "\">";
343 		itemlist_to_xml(newxml, i->querydict, true);
344 		itemlist_to_xml(newxml, i->scandict, false);
345 		newxml += "</dictgroup>";
346 	}
347 }
348 
get_dictlist_from_itemlist(std::list<DictItemId> & dict_list,const std::list<DictManageItem> & itemlist)349 static void get_dictlist_from_itemlist(std::list<DictItemId> &dict_list,
350 	const std::list<DictManageItem> &itemlist)
351 {
352 	for (std::list<DictManageItem>::const_iterator i = itemlist.begin(); i != itemlist.end(); ++i) {
353 		if (i->type == LOCAL_DICT && i->enable == true) {
354 			if (std::find(dict_list.begin(), dict_list.end(), i->file_or_id) == dict_list.end()) {
355 				dict_list.push_back(i->file_or_id);
356 			}
357 		}
358 	}
359 }
360 
361 /* remove unavailable dictionaries and plugins */
remove_unavailable_dicts_plugins(std::list<DictManageItem> & dict_list,const std::list<DictItemId> & dict_all_list,const std::list<DictItemId> & plugin_all_list)362 static void remove_unavailable_dicts_plugins(std::list<DictManageItem>& dict_list,
363 	const std::list<DictItemId> &dict_all_list,
364 	const std::list<DictItemId> &plugin_all_list)
365 {
366 	for(std::list<DictManageItem>::iterator i=dict_list.begin();
367 		i!=dict_list.end(); ) {
368 		bool found=false;
369 		switch(i->type) {
370 		case LOCAL_DICT:
371 			found = dict_all_list.end()
372 				!= std::find(dict_all_list.begin(), dict_all_list.end(), i->file_or_id);
373 			break;
374 		case VIRTUAL_DICT:
375 		case NET_DICT:
376 			found = plugin_all_list.end() != std::find(plugin_all_list.begin(),
377 				plugin_all_list.end(), i->file_or_id);
378 			break;
379 		default:
380 			g_error("Unknown plugin type %s\n", i->file_or_id.c_str());
381 			found = false;
382 		}
383 		if(found)
384 			++i;
385 		else
386 			i = dict_list.erase(i);
387 	}
388 }
389 
390 /* update IDs of dictionaries and plugins in dict_list,
391 so they spell as in dict_all_list and plugin_all_list.
392 See update_list_items function. */
update_dicts_plugins(std::list<DictManageItem> & dict_list,const std::list<DictItemId> & dict_all_list,const std::list<DictItemId> & plugin_all_list)393 static void update_dicts_plugins(std::list<DictManageItem>& dict_list,
394 	const std::list<DictItemId> &dict_all_list,
395 	const std::list<DictItemId> &plugin_all_list)
396 {
397 #ifdef _WIN32
398 	std::list<DictItemId>::const_iterator j;
399 	for(std::list<DictManageItem>::iterator i=dict_list.begin();
400 		i!=dict_list.end(); ++i) {
401 		switch(i->type) {
402 		case LOCAL_DICT:
403 			j = std::find(dict_all_list.begin(), dict_all_list.end(), i->file_or_id);
404 			g_assert(j != dict_all_list.end());
405 			break;
406 		case VIRTUAL_DICT:
407 		case NET_DICT:
408 			j = std::find(plugin_all_list.begin(), plugin_all_list.end(), i->file_or_id);
409 			g_assert(j != plugin_all_list.end());
410 			break;
411 		default:
412 			g_error("Unknown plugin type %s\n", i->file_or_id.c_str());
413 		}
414 		i->file_or_id = *j;
415 	}
416 #endif
417 }
418 
UpdateConfigXML(const std::list<DictItemId> & dict_new_install_list,const std::list<DictItemId> & plugin_new_install_list,const StarDictPlugins * oStarDictPlugins)419 void UpdateConfigXML(
420 	const std::list<DictItemId> &dict_new_install_list,
421 	const std::list<DictItemId> &plugin_new_install_list,
422 	const StarDictPlugins* oStarDictPlugins)
423 {
424 	std::list<DictItemId> dict_all_list;
425 	std::list<DictItemId> plugin_all_list;
426 	{
427 #ifdef _WIN32
428 		std::list<std::string> s_dict_all_list;
429 		std::list<std::string> s_plugin_all_list;
430 		{
431 			const std::list<std::string> &dict_all_list_rel
432 				= conf->get_strlist("/apps/stardict/manage_dictionaries/dict_order_list");
433 			const std::list<std::string> &plugin_all_list_rel
434 				= conf->get_strlist("/apps/stardict/manage_plugins/plugin_order_list");
435 			abs_path_to_data_dir(dict_all_list_rel, s_dict_all_list);
436 			abs_path_to_data_dir(plugin_all_list_rel, s_plugin_all_list);
437 		}
438 #else
439 		const std::list<std::string> &s_dict_all_list
440 			= conf->get_strlist("/apps/stardict/manage_dictionaries/dict_order_list");
441 		const std::list<std::string> &s_plugin_all_list
442 			= conf->get_strlist("/apps/stardict/manage_plugins/plugin_order_list");
443 #endif
444 		DictItemId::convert(dict_all_list, s_dict_all_list);
445 		DictItemId::convert(plugin_all_list, s_plugin_all_list);
446 	}
447 	const std::string &configxml
448 		= conf->get_string("/apps/stardict/manage_dictionaries/dict_config_xml");
449 	DictManageInfo dictinfo;
450 	DictConfigXmlToInfo(configxml.c_str(), dictinfo);
451 
452 	// remove dictionaries and plugins that are not available now
453 	for(std::list<DictManageGroup>::iterator igroup=dictinfo.groups.begin();
454 		igroup!=dictinfo.groups.end(); ++igroup) {
455 		remove_unavailable_dicts_plugins(igroup->querydict, dict_all_list, plugin_all_list);
456 		remove_unavailable_dicts_plugins(igroup->scandict, dict_all_list, plugin_all_list);
457 		update_dicts_plugins(igroup->querydict, dict_all_list, plugin_all_list);
458 		update_dicts_plugins(igroup->scandict, dict_all_list, plugin_all_list);
459 	}
460 
461 	std::list<DictManageGroup>::iterator iactivegroup
462 		= dictinfo.set_active_group(
463 			conf->get_string("/apps/stardict/manage_dictionaries/dict_default_group"));
464 
465 	if(conf->get_bool("/apps/stardict/preferences/dictionary/add_new_dict_in_active_group")) {
466 		// add new dictionaries to the active group
467 		for (std::list<DictItemId>::const_iterator j = dict_new_install_list.begin(); j != dict_new_install_list.end(); ++j) {
468 			DictManageItem item;
469 			item.type = LOCAL_DICT;
470 			item.enable = true;
471 			item.file_or_id = *j;
472 			iactivegroup->querydict.push_back(item);
473 			iactivegroup->scandict.push_back(item);
474 		}
475 	}
476 	if(conf->get_bool("/apps/stardict/preferences/dictionary/add_new_plugin_in_active_group")) {
477 		// add new plugins to the active group
478 		for(std::list<DictItemId>::const_iterator j=plugin_new_install_list.begin(); j != plugin_new_install_list.end(); ++j) {
479 			size_t iPlugin;
480 			if(oStarDictPlugins->VirtualDictPlugins.find_dict_by_id(*j, iPlugin)) {
481 				DictManageItem item;
482 				item.type = VIRTUAL_DICT;
483 				item.enable = true;
484 				item.file_or_id = *j;
485 				iactivegroup->querydict.push_back(item);
486 				iactivegroup->scandict.push_back(item);
487 			} else if(oStarDictPlugins->NetDictPlugins.find_dict_by_id(*j, iPlugin)) {
488 				DictManageItem item;
489 				item.type = NET_DICT;
490 				item.enable = true;
491 				item.file_or_id = *j;
492 				iactivegroup->querydict.push_back(item);
493 				iactivegroup->scandict.push_back(item);
494 			}
495 		}
496 	}
497 	std::string newxml;
498 	InfoToConfigXml(newxml, dictinfo);
499 	conf->set_string("/apps/stardict/manage_dictionaries/dict_config_xml", newxml);
500 }
501 
502 /* get a list of all used dictionaries, those that are part of some dictionary group,
503  * not only the active dictionary group */
GetUsedDictList(std::list<DictItemId> & dict_list)504 void GetUsedDictList(std::list<DictItemId> &dict_list)
505 {
506 	dict_list.clear();
507 	for (std::list<DictManageGroup>::iterator i = gpAppFrame->dictinfo.groups.begin(); i != gpAppFrame->dictinfo.groups.end(); ++i) {
508 		get_dictlist_from_itemlist(dict_list, i->querydict);
509 		get_dictlist_from_itemlist(dict_list, i->scandict);
510 	}
511 }
512 
set_dictmask_by_itemlist(const std::list<DictManageItem> & itemlist,bool is_query)513 static void set_dictmask_by_itemlist(const std::list<DictManageItem> &itemlist, bool is_query)
514 {
515 	if (is_query)
516 		gpAppFrame->query_dictmask.clear();
517 	else
518 		gpAppFrame->scan_dictmask.clear();
519 	for (std::list<DictManageItem>::const_iterator i = itemlist.begin(); i != itemlist.end(); ++i) {
520 		if (i->enable) {
521 			if (i->type == LOCAL_DICT) {
522 				size_t iLib;
523 				if (gpAppFrame->oLibs.find_lib_by_id(i->file_or_id, iLib)) {
524 					InstantDictIndex instance_dict_index;
525 					instance_dict_index.type = InstantDictType_LOCAL;
526 					instance_dict_index.index = iLib;
527 					if (is_query)
528 						gpAppFrame->query_dictmask.push_back(instance_dict_index);
529 					else
530 						gpAppFrame->scan_dictmask.push_back(instance_dict_index);
531 				}
532 			} else if (i->type == VIRTUAL_DICT) {
533 				size_t iPlugin;
534 				if (gpAppFrame->oStarDictPlugins->VirtualDictPlugins.find_dict_by_id(i->file_or_id, iPlugin)) {
535 					InstantDictIndex instance_dict_index;
536 					instance_dict_index.type = InstantDictType_VIRTUAL;
537 					instance_dict_index.index = iPlugin;
538 					if (is_query)
539 						gpAppFrame->query_dictmask.push_back(instance_dict_index);
540 					else
541 						gpAppFrame->scan_dictmask.push_back(instance_dict_index);
542 				}
543 			} else {
544 				g_assert(i->type == NET_DICT);
545 				size_t iPlugin;
546 				if (gpAppFrame->oStarDictPlugins->NetDictPlugins.find_dict_by_id(i->file_or_id, iPlugin)) {
547 					InstantDictIndex instance_dict_index;
548 					instance_dict_index.type = InstantDictType_NET;
549 					instance_dict_index.index = iPlugin;
550 					if (is_query)
551 						gpAppFrame->query_dictmask.push_back(instance_dict_index);
552 					else
553 						gpAppFrame->scan_dictmask.push_back(instance_dict_index);
554 				}
555 			}
556 		}
557 	}
558 }
559 
UpdateDictMask()560 void UpdateDictMask()
561 {
562 	std::list<DictManageGroup>::iterator i = gpAppFrame->dictinfo.get_active_group();
563 	set_dictmask_by_itemlist(i->querydict, true);
564 	set_dictmask_by_itemlist(i->scandict, false);
565 	g_free(gpAppFrame->iCurrentIndex);
566 	gpAppFrame->iCurrentIndex = (CurrentIndex*)g_malloc0(sizeof(CurrentIndex) * gpAppFrame->query_dictmask.size());
567 	conf->set_string("/apps/stardict/manage_dictionaries/dict_default_group", gpAppFrame->dictinfo.active_group);
568 }
569 
LoadDictInfo()570 void LoadDictInfo()
571 {
572 	const std::string &configxml
573 		= conf->get_string("/apps/stardict/manage_dictionaries/dict_config_xml");
574 	DictConfigXmlToInfo(configxml.c_str(), gpAppFrame->dictinfo);
575 	gpAppFrame->dictinfo.set_active_group(
576 		conf->get_string("/apps/stardict/manage_dictionaries/dict_default_group"));
577 }
578 
579 /* update manage_dictionaries/dict_order_list configuration option
580  * - add new dictionaries
581  * - remove dictionaries that are no longer available
582  * */
UpdateDictList(std::list<DictItemId> & dict_new_install_list,show_progress_t * sp,bool verify_dict)583 void UpdateDictList(std::list<DictItemId> &dict_new_install_list, show_progress_t *sp, bool verify_dict)
584 {
585 	dict_new_install_list.clear();
586 	std::list<DictItemId> dict_all_list;
587 	get_all_dict_list(dict_all_list);
588 	// verify dictionaries, remove invalid dictionaries from dict_all_list
589 	if (verify_dict) {
590 		std::list<std::string> s_dict_valid_list;
591 		std::list<std::string> s_dict_all_list;
592 		DictItemId::convert(s_dict_all_list, dict_all_list);
593 		filter_verify_dicts(s_dict_all_list, s_dict_valid_list, sp);
594 		DictItemId::convert(dict_all_list, s_dict_valid_list);
595 	}
596 	std::list<DictItemId> dict_order_list;
597 	{
598 #ifdef _WIN32
599 		std::list<std::string> s_dict_order_list;
600 		{
601 			const std::list<std::string>& dict_order_list_rel
602 				= conf->get_strlist("/apps/stardict/manage_dictionaries/dict_order_list");
603 			abs_path_to_data_dir(dict_order_list_rel, s_dict_order_list);
604 		}
605 #else
606 		std::list<std::string> s_dict_order_list(conf->get_strlist("/apps/stardict/manage_dictionaries/dict_order_list"));
607 #endif
608 		DictItemId::convert(dict_order_list, s_dict_order_list);
609 	}
610 	// remove dictionaries that are not available
611 	remove_list_items(dict_order_list, dict_all_list);
612 	update_list_items(dict_order_list, dict_all_list);
613 	// find new dictionaries
614 	for (std::list<DictItemId>::iterator i = dict_all_list.begin(); i != dict_all_list.end(); ++i) {
615 		if (dict_order_list.end() == std::find(dict_order_list.begin(), dict_order_list.end(), *i)) {
616 			dict_new_install_list.push_back(*i);
617 		}
618 	}
619 	dict_order_list.insert(dict_order_list.end(), dict_new_install_list.begin(), dict_new_install_list.end());
620 	{
621 		std::list<std::string> s_dict_order_list;
622 		DictItemId::convert(s_dict_order_list, dict_order_list);
623 #ifdef _WIN32
624 		{
625 			std::list<std::string> dict_order_list_rel;
626 			rel_path_to_data_dir(s_dict_order_list, dict_order_list_rel);
627 			conf->set_strlist("/apps/stardict/manage_dictionaries/dict_order_list", dict_order_list_rel);
628 		}
629 #else
630 		conf->set_strlist("/apps/stardict/manage_dictionaries/dict_order_list", s_dict_order_list);
631 #endif
632 	}
633 }
634 
635 /* update manage_plugins/plugin_order_list configuration list
636  * - add new plug-ins,
637  * - remove plug-ins that are no longer available
638  * update manage_plugins/plugin_disable_list configuration list
639  * - remove plug-ins that are no longer available
640  * */
UpdatePluginList(std::list<DictItemId> & plugin_new_install_list)641 void UpdatePluginList(std::list<DictItemId> &plugin_new_install_list)
642 {
643 	plugin_new_install_list.clear();
644 	std::list<DictItemId> plugin_all_list;
645 	std::list<DictItemId> plugin_order_list;
646 
647 	get_all_plugin_list(plugin_all_list);
648 	{
649 		std::list<std::string> s_plugin_order_list;
650 #ifdef _WIN32
651 		{
652 			const std::list<std::string>& plugin_order_list_rel
653 				= conf->get_strlist("/apps/stardict/manage_plugins/plugin_order_list");
654 			abs_path_to_data_dir(plugin_order_list_rel, s_plugin_order_list);
655 		}
656 #else
657 		s_plugin_order_list = conf->get_strlist("/apps/stardict/manage_plugins/plugin_order_list");
658 #endif
659 		DictItemId::convert(plugin_order_list, s_plugin_order_list);
660 	}
661 	// remove plugins that are not available
662 	remove_list_items(plugin_order_list, plugin_all_list);
663 	update_list_items(plugin_order_list, plugin_all_list);
664 	// find new plugins
665 	for(std::list<DictItemId>::iterator it = plugin_all_list.begin(); it != plugin_all_list.end(); ++it) {
666 		if(plugin_order_list.end() == std::find(plugin_order_list.begin(), plugin_order_list.end(), *it))
667 			plugin_new_install_list.push_back(*it);
668 	}
669 	plugin_order_list.insert(plugin_order_list.end(), plugin_new_install_list.begin(), plugin_new_install_list.end());
670 	{
671 		std::list<std::string> s_plugin_order_list;
672 		DictItemId::convert(s_plugin_order_list, plugin_order_list);
673 #ifdef _WIN32
674 		{
675 			std::list<std::string> plugin_order_list_rel;
676 			rel_path_to_data_dir(s_plugin_order_list, plugin_order_list_rel);
677 			conf->set_strlist("/apps/stardict/manage_plugins/plugin_order_list", plugin_order_list_rel);
678 		}
679 #else
680 		conf->set_strlist("/apps/stardict/manage_plugins/plugin_order_list", s_plugin_order_list);
681 #endif
682 	}
683 
684 	std::list<DictItemId> plugin_disable_list;
685 	{
686 #ifdef _WIN32
687 		std::list<std::string> s_plugin_disable_list;
688 		{
689 			const std::list<std::string> &plugin_disable_list_rel
690 				= conf->get_strlist("/apps/stardict/manage_plugins/plugin_disable_list");
691 			abs_path_to_data_dir(plugin_disable_list_rel, s_plugin_disable_list);
692 		}
693 #else
694 		std::list<std::string> s_plugin_disable_list(
695 			conf->get_strlist("/apps/stardict/manage_plugins/plugin_disable_list"));
696 #endif
697 		DictItemId::convert(plugin_disable_list, s_plugin_disable_list);
698 	}
699 	remove_list_items(plugin_disable_list, plugin_all_list);
700 	update_list_items(plugin_disable_list, plugin_all_list);
701 	{
702 		std::list<std::string> s_plugin_disable_list;
703 		DictItemId::convert(s_plugin_disable_list, plugin_disable_list);
704 #ifdef _WIN32
705 		{
706 			std::list<std::string> plugin_disable_list_rel;
707 			rel_path_to_data_dir(s_plugin_disable_list, plugin_disable_list_rel);
708 			conf->set_strlist("/apps/stardict/manage_plugins/plugin_disable_list",
709 				plugin_disable_list_rel);
710 		}
711 #else
712 		conf->set_strlist("/apps/stardict/manage_plugins/plugin_disable_list",
713 			s_plugin_disable_list);
714 #endif
715 	}
716 }
717 
RemoveCacheFiles(void)718 void RemoveCacheFiles(void)
719 {
720 	/* We may not simply remove all ".oft" and ".clt" files in all known
721 	 * directories, there are resource storage directories! */
722 #ifdef _WIN32
723 	std::list<std::string> dict_list;
724 	{
725 		const std::list<std::string>& dict_list_rel = conf->get_strlist("/apps/stardict/manage_dictionaries/dict_order_list");
726 		abs_path_to_data_dir(dict_list_rel, dict_list);
727 	}
728 #else
729 	const std::list<std::string>& dict_list = conf->get_strlist("/apps/stardict/manage_dictionaries/dict_order_list");
730 #endif
731 	std::list<std::string> dir_list;
732 	glib::CharStr gdir;
733 	/* Collect a list of directories where to remove cache files. */
734 	for(std::list<std::string>::const_iterator it = dict_list.begin(); it != dict_list.end(); ++it) {
735 		gdir.reset(g_path_get_dirname(it->c_str()));
736 		if(dir_list.end() == std::find_if(dir_list.begin(), dir_list.end(), PathComparePred(get_impl(gdir))))
737 			dir_list.push_back(get_impl(gdir));
738 	}
739 	dir_list.push_back(conf_dirs->get_user_cache_dir());
740 	// remove cache files
741 	const gchar *filename;
742 	GDir *dir;
743 	for(std::list<std::string>::const_iterator it = dir_list.begin(); it != dir_list.end(); ++it) {
744 		dir = g_dir_open(it->c_str(), 0, NULL);
745 		if(!dir)
746 			continue;
747 		while ((filename = g_dir_read_name(dir))!=NULL) {
748 			if(!is_path_end_with(filename, ".oft") && !is_path_end_with(filename, ".clt"))
749 				continue;
750 			std::string fullfilename(build_path(*it, filename));
751 			if (!g_file_test(fullfilename.c_str(), G_FILE_TEST_IS_DIR)) {
752 				if(g_unlink(fullfilename.c_str()))
753 					g_warning(_("Unable to remove file: %s"), fullfilename.c_str());
754 			}
755 		}
756 		g_dir_close(dir);
757 	}
758 }
759