Solved

IniFile to HashStringList

Posted on 2004-09-15
10
755 Views
Last Modified: 2010-04-05
Does anyone have a function/procedure on how to read through an ini file into a THashStringList?

I've got an ini file which contains registration information and database settings for programs. This file get's decrypted, read, then re-encypted. This works fine in my user registration dll, however I'd have to rewrite the encypt/decrypt routines into each application, this is not efficient. And I'd rather not have to keep un-encrypting the inifile as I don't want end-users to even really look at it at all, but instead use my GUI.

I figure the best way to do this would be to have a function in a DLL called LoadIniFile and call it on start of my program to load the IniFile into a HashStringList in the .dll (I have a unit for storing information globally). I can then have a function called GetIniValue which accepts a string and returns a string (This does restrict me to not having 'Sections' like an IniFile normally would do), unless a 3d HashStringList can be created rather than a 2d? Anyway my question is how to read an IniFile into a HashStringList.

Thanks
0
Comment
Question by:Narusegawa
  • 6
  • 3
10 Comments
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12063299
The IniFiles unit has a class called TCustomIniFile that you can use to build your own special-formatted ini files. The same unit also has a TMemIniFile which reads a whole INI file and can write it too. Based on these two classes you might even create your own INIfile class that reads/writes the file in encrypted form.

However, encrypting data in an INI file defeats the purpose of using an INI file. Basically, an INI file is a configuration file that allows you to change the configuration without starting the application. If you want to store data in encrypted form, just dump it in a custom file format, like a stream.

Another solution if you're using Delphi 7 is to use XML instead, for storing configuration data. This allows you to divide the data on multiple levels, noy just section.key=value levels. And with XML you can just read/write the contents in encrypted form quite easily.
0
 

Author Comment

by:Narusegawa
ID: 12063320
IniFiles and Registry are the only methods I know of storing configuration information using Delphi 6, and as my programs are ran on network shares, IniFiles seem to be the best way for me. Never created a custom file format myself and really wouldn't know where to start.
0
 
LVL 3

Expert Comment

by:Tyrsis
ID: 12065215
This is actually pretty simple.  Though it's unclear how you want to load the data.  If the ini file is encrypted then you have to change LoadFromFile to LoadFromStream.  And you have to decrypt the ini file and put it into a TMemoryStream.  Then call hsl.LoadFromStream(myStream);  
var
    hsl : THashedStringList;
    r : Integer;
begin
    hsl := THashedStringList.Create;
    hsl.LoadFromFile('myini.ini');

    r := 0;
    while r < hsl.Count - 1 do
    begin
        if(hsl[r][1] = '[') then // Remove any sections
        begin
            hsl.Delete(r);
            continue;
        end;

        Inc(r);
    end;
end;

Once this is done hsl contains your ini file.  Just call hsl.IndexOf('key') which returns the value of key.  
0
 

Author Comment

by:Narusegawa
ID: 12065562
Just a quick thought, and thanks for that Tyrsis. Is it possible to load an ini file to memory? I use the following on ini files currently...

    FIniFile := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
    edRegName.Text := Trim(FIniFile.ReadString('Registration','RegName',''));
    FIniFile.Free;

As I understand it the .Free clears the inifile in memory. Is there a way to keep this in memory, but close the link to the physical file.
0
 
LVL 17

Accepted Solution

by:
Wim ten Brink earned 50 total points
ID: 12065617
XML is a nice custom file format and Delphi 6/7 has some support for it. But if you're unfamiliar with XML, it tends to be a bit complex.

The TMemIniFile class has two methods GetStrings/SetStrings which you can set to fill it with the contents of the INI file you like.

Something like:

var MemIniFile:TMemIniFile;
begin
  MemIniFile := TMemIniFile.Create('');
  MemIniFile.SetStrings(YourUnencryptedStringList);
  <blah>
  MemIniFile.GetStrings(YourUnencryptedStringList);
  MemIniFile.Free;
end;

And around this code you should load the encrypted file into YourUnencryptedStringList and save it back to file at the end again.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:Narusegawa
ID: 12065931
Would something like the following work:

    FStringList := TStringList.Create;
    FStringList.LoadFromFile(ChangeFileExt(Application.ExeName,'.ini'));
    Variables.FMemIniFile.Create('');
    Variables.FMemIniFile.SetStrings(FStringList);
    FStringList.Free;

I'm trying the above but it crashes when I load my program up. I have the above in the .dpr file. But that shouldn't make a difference.
0
 

Author Comment

by:Narusegawa
ID: 12066125
I just played a little, and the following works though. Now to just convert my project to reference the FMemIniFile instead. And a procedure to write back any changes to the inifile once I exit the program.

    FStringList := TStringList.Create;
    FStringList.LoadFromFile(ChangeFileExt(Application.ExeName,'.ini'));
    Variables.FMemIniFile := TMemIniFile.Create('');
    Variables.FMemIniFile.SetStrings(FStringList);
    FStringList.Free;

Now I'm right in understanding that if I call Variables.FMemIniFile.Free I will clear the IniFile in Memory contents? So I shouldn't do that until I exit the program (in a clean way). Obviously a crash wouldn't save changes.
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12068562
Basically, you should save the INI file after you've made changes to some of the values in it. In general, INI files are configured through some configuration form. When that form closes, save the INI file. Not before, not after.
You could also save the settings when the application ends, but that's a bit useless if no settings have changed. So in general save settings after they've changed.
0
 

Author Comment

by:Narusegawa
ID: 12110439
Thanks Workshop_Alex. Your a star!

How would I write that TMemIniFile data back to an IniFile again?

I've loaded it with the following:

  if FileExists(ChangeFileExt(Application.ExeName,'.ini')) then
  begin
    _DecryptFile(ChangeFileExt(Application.ExeName,'.ini'),Variables.FPassword);
    FStringList := TStringList.Create;
    FStringList.LoadFromFile(ChangeFileExt(Application.ExeName,'.ini'));
    Variables.FMemIniFile := TMemIniFile.Create('');
    Variables.FMemIniFile.SetStrings(FStringList);
    FStringList.Free;
    _EncryptFile(ChangeFileExt(Application.ExeName,'.ini'),Variables.FPassword);
  end;

I can't call .create on FMemIniFile again because it already exists.

Thanks
0
 

Author Comment

by:Narusegawa
ID: 12110630
I've figured it out, I've got 2 functions now. These let me load the IniFile in and save to it later on. While maintaining it's encryption. Only thing I'm trying to figure out now is how to read the entire contents of FMemIniFile (A TMemIniFile) into something like a StringGrid (So the IniFile can be administered using a GUI form I'm designing). It's a generic optinos form that's in my .dll file so I can reuse this on all programs, each program will have it's own options screen at some point but this is for those that don't. If that makes sense. I'll probably post a question about loading a TMemIniFile into a StringGrid later on seperately.

procedure LoadIniFile();
begin
  if FileExists(ChangeFileExt(Application.ExeName,'.ini')) then
  begin
    _DecryptFile(ChangeFileExt(Application.ExeName,'.ini'),Variables.FPassword);
    Variables.FMemIniFile := TMemIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
    _EncryptFile(ChangeFileExt(Application.ExeName,'.ini'),Variables.FPassword);
  end;
end;

function SaveIniFile():boolean;
begin
  if FileExists(ChangeFileExt(Application.ExeName,'.ini')) then
    begin
      _DecryptFile(ChangeFileExt(Application.ExeName,'.ini'),Variables.FPassword);
    end;
  try
    begin
      FMemIniFile.UpdateFile;
      FMemIniFile.Free();
      result := true;
    end
  except
    result := false;
  end;
  _EncryptFile(ChangeFileExt(Application.ExeName,'.ini'),Variables.FPassword);
end;
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now