mIRC Home    About    Download    Register    News    Help

Print Thread
$readini vs /writeini #269602 15/11/21 03:58 AM
Joined: Jan 2004
Posts: 1,662
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 1,662
$readini should have the same view of what an itemname is, that /writeini has

The suggested fixes are:

#A. /writeini should not permit the itemname to contain the '=' character, since $readini should sees a different itemname consisting only of the string to the left of the 1st '=' on the line. This also triggers a glitch which could be related to how mIRC caches /writeini

#B. $readini should not handle doublequotes in an itemname differently than /writeini does

#C Since $readini and $ini won't see ;comment lines, /writeini shouldn't handle ;item as if it's a normal item.

==

These use the demo alias at the bottom of this post

(#A) /writeini should not permit the item name to contain the '=' character because $readini should be expecting the 1st '=' on a line to be the delimiter between the itemname and the data. This also causes a quirk where repeating an identical /writeini command results in a duplicate line, which affects whether or not $readini sees the correct item or not.

1. delete test.ini: /remove test.ini
2. run: /ini_test abc=def

There is 1 item in the [section], which $readini can see using the string abc=def used for writing it to disk, but cannot see it using the 'true' itemname: abc

3. Now repeat the Step#2 command, and a duplicate line is written to disk, and only now can $readini see under the correct abc itemname. Repeating #2 extra times does not cause the line to appear more than twice.

4. The reason I'm assuming that this is cache related is that, having 1 or more '=' in the line can be written to disk multiple ways, but only the string to the left of the 1st '=' is the valid item name. However, the /writeini's choice of these various combos and whether the command is repeated to create a duplicate line - affects whether the 'true' itemname works for $readini, or which of the alternative itemname works for $readini.

5. There's another syntax which has the potential to confuse $readini, but I'm not suggesting a change there because 100% disallowing items beginning with [ would break scripts who use $nick as an item name. And that's the situation where the itemname begins with [ and the data ends with ]

As long as the data doesn't end with ] this syntax is perfectly fine, but otherwise it creates a line in testini that looks like [item=data] which is a valid name for a section.

Potential defenses I see against this would be to either ban a section name from containing the '=' character, or to disallow only the combo like /writeini test.ini section [item data]

==

(#B) /writeini creates items which $readini cannot see, if the itemname 'word' begins or ends with a doublequote.

As an aside, it's great that /writeini allows the section name to contain a space and that $readini can see it, like:

//remove test.ini | writeini -n test.ini "section name" item data | echo 4 -s read item from disk: $readini(test.ini,n,section name,item) | filter -fs test.ini *

But since /writeini isn't trying to support an itemname containing a space to the left of the '=', then $readini shouldn't be stripping the leading/trailing doublequote when looking for the item name

1. delete test.ini again: /remove test.ini

2. The /ini_test alias can continue to be used, you can skip the 2nd brown echo used with #A which is not relevant to this #B issue. Now run these and see these items are correctly written to disk:

/ini_test abc
/ini_test abcdef
/ini_test abc"def

3. Now run these and see that /writeini continues to write these itemnames correctly, but $readini cannot see them because it's looking for $noqt(one-word-itemname)

/ini_test abcdef"
/ini_test "abcdef
/ini_test "abc"def"

4. If /writeini's itemname parm looks like a quoted string containing a space, it won't create an itemname containing a space, but instead writes it to disk as if only the 1st word is the item, and the remainder of the quoted string is treated as part of the data:

/ini_test "abc def"

I'm not suggesting that /writeini should support itemnames containing spaces, just that $readini should handle the itemname parm the same way that /writeini does. If /writeini sees the unaltered word#1 as the itemname, then $readini should also see that, and not strip the doublequotes, which prevents it from seeing the actual itemname being written, and either returns $null or returns the wrong item's data.

(#C) This may be considered part of the design without the intent to support writing ;comment lines using /writeini, and if so this is just documenting the behavior for the benefit of later viewers. Even though you can write comments to an .ini using /writeini, it's not the best because /writeini:

* alters the comment slightly
* writes it only at the tail end of the [section]
* won't check to prevent writing an identical comment repeatedly

$readini and $ini correctly don't see a ;comment written by /writeini, however /writeini still alters the line as if it's a normal item. It requires the 'comment' to contain at least 2 words, then writes the itemname as ;firstword and then inserts the '=' between ;firstword and the remainder of the comment.

//var %item ;comment , %data word2 | writeini -n test.ini section %item %data | echo 4 -s #items: $ini(test.ini,section,0) : seeing item %item as: $readini(test.ini,n,section,%item) | filter -fs test.ini *

It's up to the user to make sure they don't write the ;comment item multiple times, because repeating the above commands causes the identical ;item=data line to be written to disk repeatedly, and not limited to being there twice like in the glitch in #A above

===============

Code
alias ini_test {
  var %item $1-
  echo -s ==
  var -s %tmp $gettok($noqt($1),1,61)
  writeini -n test.ini section %item data written as itemname %item
  echo 4 -s seeing item %item as: $readini(test.ini,n,section,%item)
  echo 7 -s seeing item %tmp as: $readini(test.ini,n,section,%tmp)
  filter -fs test.ini *
}

Re: $readini vs /writeini [Re: maroon] #269731 26/12/21 01:41 PM
Joined: Dec 2002
Posts: 5,036
Khaled Offline
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,036
Thanks for your post. The issues you mention are related to historical and Windows INI API backward-compatiblity.

For issues A and C: when the custom INI routines were implemented, I decided to make them as compatible as possible with the Windows INI APIs, to ensure that newer versions of mIRC would continue to work with previous INI files. This meant trying to mimick the same issues as the Windows INI APIs to avoid breaking scripts.

For issue B: $readini was originally a non-bracketed() identifier, so its parameters had to be enclosed in quotes. When $readini() was added, it shared the same core code as $readini, to make sure that they worked in the same way. Fixing this issue is not possible, as far as I can see, because the non-bracketed /writeini has to parse quotes across parameters whereas the bracketed $readini() does not.

As for comments: I could add a check to prevent duplicate comments in a section, which I believe would make it different from the Windows INI API. That said, it's possible that some scripts may try to write a comment, then an item, then another coment, then an item, and that some of the comments above each item might be the same. In which case, such a change would prevent this. So perhaps the change should prevent multiple *consecutive* identical comments.

As for equal signs in item names: the only workable solution to this is to prevent item names from containing equal signs, and reporting an error if a script tries to do this in either /writeini or $readini(), which would break all existing scripts where this currently works.

For the caching issue: this needs to be fixed and will be in the next beta. The fix means that if an item name begins with an equal sign, /writeini will have to report an error, since technically there will be no item name.