Better INI backend for Config::Model

Current ini_file backend built into Config::Model works pretty well, but not for all files. Config::Tiny module (used for reading INI files) makes assumption that a variable name cannot be repeated in one section. This statement is true only for about 99% of INI files. Look at the following fragment of valid Kismet config file:

# Sources are defined as:
# source=sourcetype,interface,name[,initialchannel]
 
source = ipw2100,eth1,intel
source = madwifi,ath0,atheros

As you can see, source variable is repeated – in this case, backend based on Config::Tiny will report only one occurrence of it.

New backend

I decided to write a new backend. Patching Config::Tiny is not a good idea in my humble opinion – modifying this module could break applications dependent on it. Dominique suggested that repeated variables should be handled as lists. I had some trouble with Config::Model docs, but with his help I managed to create a fully working backend today.

Reading file

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
    my $data = {};
    my $section;
 
    foreach ($args{io_handle}->getlines) {
	next if /^[;#]/ ;
	chomp ;
	next if/^\s*$/;
 
	#Update section name
	if(/\[(.*)\]/)
	{
		$section = $1;
		next;
	}
 
	my ($name,$val) = split(/\s*=\s*/);
 
	#Get the 'right' ref
	my $r = $data;
 
	if (defined $section)
	{
		$data->{$section} = {} if not defined $data->{$section};
		$r = $data->{$section}
	}
 
	if (defined $r->{$name})
	{
		$r->{$name} = [$r->{$name}] if ref($r->{$name}) ne 'ARRAY';
		push @{$r->{$name}}, $val;
	}
	else
	{
		$r->{$name} = $val;
	}
    }
    $self->node->load_data($data);

This simple loop goes through all of the lines of a config file and builds a Perl data structure of it. All values are initially stored as strings. When a variable name appears for the second time, it’s converted to an array of values. Finally, data is loaded into a model using load_data method.

Problems

This approach solves only one problem of Config::Tiny – comments in the file are still lost. However, this can be easily solved – all I need to do is store comments separately (like in ShellVar backend). Some basic file validation would be good too.

Files

New backend
Modified Kismet model (source parameter as list)

P.S.
I promised to post some notes about Config::Model docs, but I’ll do it after some more investigation.

One thought on “Better INI backend for Config::Model

  1. Comments extracted from the configuration file can be extracted by the read backend and stored in the new annotation feature provided by Config::Model 1.202. Then they can be written back by the write backend.

    Hope this helps

Leave a Reply

Your email address will not be published. Required fields are marked *