diff --git a/components/cryptini/latest_stable/cryptini.lpk b/components/cryptini/latest_stable/cryptini.lpk new file mode 100644 index 000000000..a31d78dc5 --- /dev/null +++ b/components/cryptini/latest_stable/cryptini.lpk @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/cryptini/latest_stable/cryptini.pas b/components/cryptini/latest_stable/cryptini.pas new file mode 100644 index 000000000..c769bc1fd --- /dev/null +++ b/components/cryptini/latest_stable/cryptini.pas @@ -0,0 +1,14 @@ +{ This file was automatically created by Lazarus. Do not edit! + This source is only used to compile and install the package. + } + +unit cryptini; + +interface + +uses + ucryptini; + +implementation + +end. diff --git a/components/cryptini/latest_stable/demo/cryptinitest.ico b/components/cryptini/latest_stable/demo/cryptinitest.ico new file mode 100644 index 000000000..9f02c598b Binary files /dev/null and b/components/cryptini/latest_stable/demo/cryptinitest.ico differ diff --git a/components/cryptini/latest_stable/demo/cryptinitest.lpi b/components/cryptini/latest_stable/demo/cryptinitest.lpi new file mode 100644 index 000000000..5c9c44dc9 --- /dev/null +++ b/components/cryptini/latest_stable/demo/cryptinitest.lpi @@ -0,0 +1,283 @@ + + + + + + + + + + <UseAppBundle Value="False"/> + <ResourceType Value="res"/> + <XPManifest> + <TextName Value="CompanyName.ProductName.AppName"/> + <TextDesc Value="Your application description."/> + </XPManifest> + <Icon Value="0"/> + </General> + <VersionInfo> + <UseVersionInfo Value="True"/> + <AutoIncrementBuild Value="True"/> + <MinorVersionNr Value="1"/> + <RevisionNr Value="2"/> + <StringTable Comments="App is GPL licensed" CompanyName="HELENA" FileDescription="Test app for CryptINI unit" InternalName="cryptinitest" LegalCopyright="(c)2016 minesadorada@charcodelvalle.com" LegalTrademarks="none" OriginalFilename="cryptinitest" ProductName="Lazarus" ProductVersion="1.6.0.0"/> + </VersionInfo> + <BuildModes Count="6"> + <Item1 Name="Win64" Default="True"/> + <Item2 Name="Win32"> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="compiled\win32\cryptinitestwin32"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <CodeGeneration> + <TargetCPU Value="i386"/> + <TargetOS Value="win32"/> + </CodeGeneration> + <Linking> + <Debugging> + <GenerateDebugInfo Value="False"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + <Other> + <CustomOptions Value="-FcUTF8"/> + </Other> + </CompilerOptions> + </Item2> + <Item3 Name="Linux64"> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="compiled\linux64\cryptinitestlinux64"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <CodeGeneration> + <TargetCPU Value="x86_64"/> + <TargetOS Value="linux"/> + </CodeGeneration> + <Linking> + <Debugging> + <GenerateDebugInfo Value="False"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + </CompilerOptions> + </Item3> + <Item4 Name="Linux32"> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="compiled\linux32\cryptinitestlinux32"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <CodeGeneration> + <TargetCPU Value="i386"/> + <TargetOS Value="linux"/> + </CodeGeneration> + <Linking> + <Debugging> + <GenerateDebugInfo Value="False"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + <Other> + <CustomOptions Value="-FcUTF8"/> + </Other> + </CompilerOptions> + </Item4> + <Item5 Name="DebugWin64"> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="compiled\debugwin64\dcryptinitestwin64"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Parsing> + <SyntaxOptions> + <IncludeAssertionCode Value="True"/> + </SyntaxOptions> + </Parsing> + <CodeGeneration> + <Checks> + <IOChecks Value="True"/> + <RangeChecks Value="True"/> + <OverflowChecks Value="True"/> + <StackChecks Value="True"/> + </Checks> + <TargetCPU Value="x86_64"/> + <TargetOS Value="win64"/> + </CodeGeneration> + <Linking> + <Debugging> + <GenerateDebugInfo Value="False"/> + <UseHeaptrc Value="True"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + </CompilerOptions> + </Item5> + <Item6 Name="Darwin32"> + <MacroValues Count="1"> + <Macro1 Name="LCLWidgetType" Value="carbon"/> + </MacroValues> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="compiled\darwin32\cryptinitestdarwin32"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <CodeGeneration> + <TargetCPU Value="i386"/> + <TargetOS Value="darwin"/> + </CodeGeneration> + <Linking> + <Debugging> + <GenerateDebugInfo Value="False"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + <Other> + <CustomOptions Value="-FcUTF8"/> + </Other> + </CompilerOptions> + </Item6> + <SharedMatrixOptions Count="1"> + <Item1 ID="543305826982" Modes="Darwin32" Type="IDEMacro" MacroName="LCLWidgetType" Value="carbon"/> + </SharedMatrixOptions> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <DestinationDirectory Value="D:\Lazarusprojects\MDSUM\CryptINI\trunk\latest_stable"/> + <IncludeFileFilter Value="*.(pas|pp|inc|lpr|lfm|lrs|lpi|lpk|xml|sh|ico|exe)"/> + <SaveClosedEditorFilesInfo Value="True"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + </local> + </RunParams> + <RequiredPackages Count="2"> + <Item1> + <PackageName Value="cryptini"/> + </Item1> + <Item2> + <PackageName Value="LCL"/> + </Item2> + </RequiredPackages> + <Units Count="5"> + <Unit0> + <Filename Value="cryptinitest.lpr"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="umainform.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="mainform"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + </Unit1> + <Unit2> + <Filename Value="umemoform.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="ShowINIForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + </Unit2> + <Unit3> + <Filename Value="ukeydialog.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="keydialog"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + </Unit3> + <Unit4> + <Filename Value="uinputsectionvaluesform.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="InputSectionValuesForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="uInputSectionValuesForm"/> + </Unit4> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="compiled\win64\cryptinitestwin64"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <CodeGeneration> + <TargetCPU Value="x86_64"/> + <TargetOS Value="win64"/> + </CodeGeneration> + <Linking> + <Debugging> + <GenerateDebugInfo Value="False"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + </CompilerOptions> + <Debugging> + <Exceptions Count="3"> + <Item1> + <Name Value="EAbort"/> + </Item1> + <Item2> + <Name Value="ECodetoolError"/> + </Item2> + <Item3> + <Name Value="EFOpenError"/> + </Item3> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/components/cryptini/latest_stable/demo/cryptinitest.lpr b/components/cryptini/latest_stable/demo/cryptinitest.lpr new file mode 100644 index 000000000..0f9ae1357 --- /dev/null +++ b/components/cryptini/latest_stable/demo/cryptinitest.lpr @@ -0,0 +1,51 @@ +program cryptinitest; +{ Test App for cryptini unit + + Copyright (C) 2016 Gordon Bamber minesadorada@gmail.com + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +} + +{$ifdef Linux} + {$ifdef FPC_CROSSCOMPILING} + {$ifdef CPUARM} +//if GUI on RPi, then uncomment +//{$linklib GLESv2} + {$endif} + {$linklib libc_nonshared.a} + {$endif} +{$endif} +{$mode objfpc}{$H+} + +uses {$IFDEF UNIX} {$IFDEF UseCThreads} + cthreads, {$ENDIF} {$ENDIF} + Interfaces, // this includes the LCL widgetset + Forms, + umainform, umemoform, ukeydialog, +uInputSectionValuesForm; + +{$R *.res} +begin + Application.Title:='CryptINI Test'; + RequireDerivedFormResource := True; + Application.Initialize; + Application.CreateForm(Tmainform, mainform); + Application.CreateForm(TShowINIForm, ShowINIForm); + Application.CreateForm(Tkeydialog, keydialog); + Application.CreateForm(TInputSectionValuesForm, InputSectionValuesForm); + Application.Run; +end. + + diff --git a/components/cryptini/latest_stable/demo/cryptinitest.lps b/components/cryptini/latest_stable/demo/cryptinitest.lps new file mode 100644 index 000000000..3d9a8e81c --- /dev/null +++ b/components/cryptini/latest_stable/demo/cryptinitest.lps @@ -0,0 +1,500 @@ +<?xml version="1.0" encoding="UTF-8"?> +<CONFIG> + <ProjectSession> + <PathDelim Value="\"/> + <Version Value="10"/> + <BuildModes Active="Darwin32"/> + <Units Count="51"> + <Unit0> + <Filename Value="cryptinitest.lpr"/> + <IsPartOfProject Value="True"/> + <EditorIndex Value="4"/> + <TopLine Value="6"/> + <CursorPos Y="49"/> + <UsageCount Value="116"/> + <Loaded Value="True"/> + </Unit0> + <Unit1> + <Filename Value="umainform.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="mainform"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <TopLine Value="197"/> + <CursorPos X="41" Y="199"/> + <UsageCount Value="116"/> + <Loaded Value="True"/> + <LoadedDesigner Value="True"/> + </Unit1> + <Unit2> + <Filename Value="umemoform.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="ShowINIForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <EditorIndex Value="3"/> + <TopLine Value="55"/> + <CursorPos X="3" Y="68"/> + <UsageCount Value="108"/> + <Loaded Value="True"/> + <LoadedDesigner Value="True"/> + </Unit2> + <Unit3> + <Filename Value="ukeydialog.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="keydialog"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <EditorIndex Value="2"/> + <CursorPos X="12" Y="29"/> + <UsageCount Value="100"/> + <Loaded Value="True"/> + <LoadedDesigner Value="True"/> + </Unit3> + <Unit4> + <Filename Value="uinputsectionvaluesform.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="InputSectionValuesForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="uInputSectionValuesForm"/> + <EditorIndex Value="-1"/> + <TopLine Value="72"/> + <CursorPos Y="84"/> + <UsageCount Value="78"/> + </Unit4> + <Unit5> + <Filename Value="htmlhelp2viewer.pas"/> + <ComponentName Value="HelpViewerForm"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="HtmlHelp2Viewer"/> + <EditorIndex Value="-1"/> + <TopLine Value="58"/> + <CursorPos X="44" Y="82"/> + <UsageCount Value="20"/> + </Unit5> + <Unit6> + <Filename Value="cryptini\ucryptini.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="203"/> + <CursorPos X="37" Y="226"/> + <UsageCount Value="33"/> + </Unit6> + <Unit7> + <Filename Value="cryptinilpk\ucryptini.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="727"/> + <CursorPos X="67" Y="754"/> + <UsageCount Value="24"/> + </Unit7> + <Unit8> + <Filename Value="..\MD5Code\ucryptini.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="360"/> + <CursorPos Y="363"/> + <UsageCount Value="101"/> + <Bookmarks Count="2"> + <Item0 Y="975" ID="1"/> + <Item1 Y="1028"/> + </Bookmarks> + </Unit8> + <Unit9> + <Filename Value="D:\fpc\packages\hash\src\md5.pp"/> + <EditorIndex Value="-1"/> + <TopLine Value="130"/> + <UsageCount Value="5"/> + </Unit9> + <Unit10> + <Filename Value="D:\fpc\packages\fcl-base\src\inifiles.pp"/> + <UnitName Value="IniFiles"/> + <EditorIndex Value="-1"/> + <TopLine Value="100"/> + <CursorPos X="5" Y="188"/> + <UsageCount Value="31"/> + </Unit10> + <Unit11> + <Filename Value="..\..\lazautoupdate\svn\trunk\lazautoupdatesource\packagesource\versionsupport.pas"/> + <UnitName Value="VersionSupport"/> + <EditorIndex Value="-1"/> + <TopLine Value="187"/> + <CursorPos X="45" Y="109"/> + <UsageCount Value="5"/> + </Unit11> + <Unit12> + <Filename Value="D:\lazarus\components\lazproj\lazxproj_src\lazxproj_intf.pas"/> + <UnitName Value="LazXProj_Intf"/> + <EditorIndex Value="-1"/> + <CursorPos X="41" Y="18"/> + <UsageCount Value="5"/> + </Unit12> + <Unit13> + <Filename Value="D:\lazarus\lcl\dialogs.pp"/> + <UnitName Value="Dialogs"/> + <EditorIndex Value="-1"/> + <TopLine Value="685"/> + <CursorPos X="25" Y="704"/> + <UsageCount Value="6"/> + </Unit13> + <Unit14> + <Filename Value="D:\fpc\rtl\objpas\sysutils\sysstrh.inc"/> + <EditorIndex Value="-1"/> + <TopLine Value="65"/> + <CursorPos X="18" Y="115"/> + <UsageCount Value="6"/> + </Unit14> + <Unit15> + <Filename Value="D:\fpc\rtl\objpas\sysutils\sysstr.inc"/> + <EditorIndex Value="-1"/> + <TopLine Value="890"/> + <CursorPos X="3" Y="893"/> + <UsageCount Value="6"/> + </Unit15> + <Unit16> + <Filename Value="D:\lazarus\lcl\include\messagedialogs.inc"/> + <EditorIndex Value="-1"/> + <CursorPos X="3" Y="212"/> + <UsageCount Value="6"/> + </Unit16> + <Unit17> + <Filename Value="..\..\lazautoupdate\svn\trunk\lazautoupdatesource\packagesource\ulazautoupdate.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="461"/> + <CursorPos X="42" Y="469"/> + <UsageCount Value="11"/> + </Unit17> + <Unit18> + <Filename Value="D:\usr\share\fpcsrc\3.0.0\rtl\objpas\sysutils\datih.inc"/> + <EditorIndex Value="-1"/> + <TopLine Value="132"/> + <CursorPos X="84" Y="153"/> + <UsageCount Value="6"/> + </Unit18> + <Unit19> + <Filename Value="D:\usr\share\fpcsrc\3.0.0\rtl\objpas\sysutils\sysinth.inc"/> + <EditorIndex Value="-1"/> + <TopLine Value="43"/> + <CursorPos X="24" Y="57"/> + <UsageCount Value="6"/> + </Unit19> + <Unit20> + <Filename Value="D:\usr\share\fpcsrc\3.0.0\packages\fcl-base\src\blowfish.pp"/> + <UnitName Value="BlowFish"/> + <EditorIndex Value="-1"/> + <TopLine Value="478"/> + <UsageCount Value="6"/> + </Unit20> + <Unit21> + <Filename Value="D:\lazarus\lcl\controls.pp"/> + <UnitName Value="Controls"/> + <EditorIndex Value="-1"/> + <TopLine Value="28"/> + <CursorPos X="3" Y="47"/> + <UsageCount Value="6"/> + </Unit21> + <Unit22> + <Filename Value="..\..\..\..\snippets\uuser.pas"/> + <UnitName Value="uUser"/> + <EditorIndex Value="-1"/> + <TopLine Value="301"/> + <UsageCount Value="6"/> + </Unit22> + <Unit23> + <Filename Value="D:\usr\share\fpcsrc\3.0.0\packages\fcl-base\src\inifiles.pp"/> + <UnitName Value="IniFiles"/> + <EditorIndex Value="-1"/> + <CursorPos Y="20"/> + <UsageCount Value="20"/> + </Unit23> + <Unit24> + <Filename Value="D:\fpc\rtl\objpas\sysutils\sysinth.inc"/> + <EditorIndex Value="-1"/> + <TopLine Value="44"/> + <CursorPos X="3" Y="33"/> + <UsageCount Value="17"/> + </Unit24> + <Unit25> + <Filename Value="D:\fpc\rtl\objpas\classes\classesh.inc"/> + <EditorIndex Value="-1"/> + <TopLine Value="654"/> + <CursorPos X="37" Y="676"/> + <UsageCount Value="12"/> + </Unit25> + <Unit26> + <Filename Value="D:\lazarus\lcl\include\customform.inc"/> + <EditorIndex Value="-1"/> + <TopLine Value="996"/> + <CursorPos Y="1019"/> + <UsageCount Value="7"/> + </Unit26> + <Unit27> + <Filename Value="D:\lazarus\components\lazutils\lazmethodlist.pas"/> + <UnitName Value="LazMethodList"/> + <EditorIndex Value="-1"/> + <TopLine Value="273"/> + <CursorPos Y="308"/> + <UsageCount Value="11"/> + </Unit27> + <Unit28> + <Filename Value="D:\lazarus\lcl\include\wincontrol.inc"/> + <EditorIndex Value="-1"/> + <TopLine Value="6442"/> + <CursorPos Y="6463"/> + <UsageCount Value="7"/> + </Unit28> + <Unit29> + <Filename Value="D:\lazarus\lcl\include\control.inc"/> + <EditorIndex Value="-1"/> + <TopLine Value="3235"/> + <CursorPos Y="3259"/> + <UsageCount Value="7"/> + </Unit29> + <Unit30> + <Filename Value="D:\lazarus\lcl\include\customedit.inc"/> + <EditorIndex Value="-1"/> + <TopLine Value="527"/> + <CursorPos Y="547"/> + <UsageCount Value="7"/> + </Unit30> + <Unit31> + <Filename Value="D:\lazarus\lcl\interfaces\win32\win32wsstdctrls.pp"/> + <UnitName Value="Win32WSStdCtrls"/> + <EditorIndex Value="-1"/> + <TopLine Value="1187"/> + <CursorPos Y="1210"/> + <UsageCount Value="7"/> + </Unit31> + <Unit32> + <Filename Value="D:\lazarus\lcl\interfaces\win32\win32proc.pp"/> + <EditorIndex Value="-1"/> + <TopLine Value="1044"/> + <CursorPos Y="1069"/> + <UsageCount Value="7"/> + </Unit32> + <Unit33> + <Filename Value="D:\lazarus\components\lazutils\lazutf8.pas"/> + <UnitName Value="LazUTF8"/> + <EditorIndex Value="-1"/> + <TopLine Value="3565"/> + <CursorPos Y="3589"/> + <UsageCount Value="7"/> + </Unit33> + <Unit34> + <Filename Value="..\..\golfml\coursewriter\source\2.x\umainform.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="3333"/> + <CursorPos X="31" Y="3328"/> + <UsageCount Value="8"/> + </Unit34> + <Unit35> + <Filename Value="D:\lazarus\components\LazOpkMan-master\LazOpkMan-master\opkman_installer.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="147"/> + <CursorPos X="42" Y="163"/> + <UsageCount Value="8"/> + </Unit35> + <Unit36> + <Filename Value="D:\usr\lib\lazarus\1.6\lcl\lclversion.pas"/> + <UnitName Value="LCLVersion"/> + <EditorIndex Value="-1"/> + <CursorPos X="12" Y="35"/> + <UsageCount Value="20"/> + </Unit36> + <Unit37> + <Filename Value="D:\home\gordon\lazarus_components\LazOpkMan-master\opkman_common.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="227"/> + <UsageCount Value="8"/> + </Unit37> + <Unit38> + <Filename Value="D:\home\gordon\lazarus_components\LazOpkMan-master\opkman_mainfrm.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="19"/> + <UsageCount Value="8"/> + </Unit38> + <Unit39> + <Filename Value="D:\home\gordon\lazarus_components\LazOpkMan-master\opkman_installer.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="139"/> + <CursorPos X="13" Y="168"/> + <UsageCount Value="12"/> + </Unit39> + <Unit40> + <Filename Value="..\..\lazprojx\lazxproj_src\lazxproj_intf.pas"/> + <UnitName Value="LazXProj_Intf"/> + <EditorIndex Value="-1"/> + <CursorPos X="41" Y="18"/> + <UsageCount Value="9"/> + </Unit40> + <Unit41> + <Filename Value="D:\lazarustrunk\components\onlinepackagemanager\opkman_installer.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="139"/> + <CursorPos X="3" Y="145"/> + <UsageCount Value="10"/> + </Unit41> + <Unit42> + <Filename Value="D:\lazarustrunk\components\onlinepackagemanager\opkman_serializablepackages.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="859"/> + <CursorPos X="37" Y="913"/> + <UsageCount Value="10"/> + </Unit42> + <Unit43> + <Filename Value="D:\lazarustrunk\components\onlinepackagemanager\opkman_optionsfrm.pas"/> + <EditorIndex Value="-1"/> + <TopLine Value="165"/> + <UsageCount Value="10"/> + </Unit43> + <Unit44> + <Filename Value="C:\NewPascalDarwin\lazarus\ide\lazarus.pp"/> + <UnitName Value="Lazarus"/> + <EditorIndex Value="-1"/> + <TopLine Value="108"/> + <CursorPos Y="154"/> + <UsageCount Value="10"/> + </Unit44> + <Unit45> + <Filename Value="..\..\..\..\snippets\usefulunits\tcopydir.pas"/> + <UnitName Value="tCopyDir"/> + <EditorIndex Value="-1"/> + <TopLine Value="22"/> + <CursorPos X="5" Y="29"/> + <UsageCount Value="10"/> + </Unit45> + <Unit46> + <Filename Value="..\..\..\..\snippets\usefulunits\uappisrunning.pas"/> + <EditorIndex Value="-1"/> + <CursorPos X="20" Y="8"/> + <UsageCount Value="10"/> + </Unit46> + <Unit47> + <Filename Value="..\..\..\..\snippets\usefulunits\usersupport.pas"/> + <UnitName Value="UserSupport"/> + <EditorIndex Value="-1"/> + <TopLine Value="240"/> + <CursorPos X="48" Y="334"/> + <UsageCount Value="10"/> + </Unit47> + <Unit48> + <Filename Value="..\..\..\..\snippets\usefulunits\utcopydir.pas"/> + <UnitName Value="utCopyDir"/> + <EditorIndex Value="-1"/> + <TopLine Value="44"/> + <CursorPos X="44" Y="60"/> + <UsageCount Value="10"/> + </Unit48> + <Unit49> + <Filename Value="C:\lazarus\examples\htmlhelp_ipro\htmlhelp2unit1.pas"/> + <UnitName Value="HtmlHelp2Unit1"/> + <EditorIndex Value="-1"/> + <TopLine Value="28"/> + <CursorPos X="97" Y="65"/> + <UsageCount Value="10"/> + </Unit49> + <Unit50> + <Filename Value="..\ucryptini.pas"/> + <IsVisibleTab Value="True"/> + <EditorIndex Value="1"/> + <TopLine Value="390"/> + <CursorPos X="19" Y="222"/> + <UsageCount Value="10"/> + <Loaded Value="True"/> + </Unit50> + </Units> + <JumpHistory Count="23" HistoryIndex="22"> + <Position1> + <Filename Value="ukeydialog.pas"/> + <Caret Line="29" Column="12"/> + </Position1> + <Position2> + <Filename Value="umainform.pas"/> + <Caret Line="621" Column="26" TopLine="607"/> + </Position2> + <Position3> + <Filename Value="umainform.pas"/> + <Caret Line="621" Column="26"/> + </Position3> + <Position4> + <Filename Value="umainform.pas"/> + <Caret Line="20" Column="27" TopLine="3"/> + </Position4> + <Position5> + <Filename Value="umainform.pas"/> + <Caret Line="32" Column="21"/> + </Position5> + <Position6> + <Filename Value="umainform.pas"/> + <Caret Line="185" Column="19" TopLine="155"/> + </Position6> + <Position7> + <Filename Value="umainform.pas"/> + <Caret Line="32" Column="24" TopLine="18"/> + </Position7> + <Position8> + <Filename Value="umainform.pas"/> + <Caret Line="234" Column="23" TopLine="222"/> + </Position8> + <Position9> + <Filename Value="umainform.pas"/> + <Caret Line="185" TopLine="167"/> + </Position9> + <Position10> + <Filename Value="umainform.pas"/> + <Caret Line="184" TopLine="166"/> + </Position10> + <Position11> + <Filename Value="umainform.pas"/> + <Caret Line="183" TopLine="165"/> + </Position11> + <Position12> + <Filename Value="umainform.pas"/> + <Caret Line="270" Column="47" TopLine="241"/> + </Position12> + <Position13> + <Filename Value="umainform.pas"/> + <Caret Line="933" Column="43" TopLine="99"/> + </Position13> + <Position14> + <Filename Value="umainform.pas"/> + <Caret Line="191" Column="18" TopLine="179"/> + </Position14> + <Position15> + <Filename Value="umainform.pas"/> + <Caret Line="153" Column="13" TopLine="153"/> + </Position15> + <Position16> + <Filename Value="umainform.pas"/> + <Caret Line="385" Column="9" TopLine="371"/> + </Position16> + <Position17> + <Filename Value="umainform.pas"/> + <Caret Line="11" Column="19"/> + </Position17> + <Position18> + <Filename Value="umainform.pas"/> + <Caret Line="153" Column="13" TopLine="140"/> + </Position18> + <Position19> + <Filename Value="umainform.pas"/> + <Caret Line="395" TopLine="366"/> + </Position19> + <Position20> + <Filename Value="umainform.pas"/> + <Caret Line="154" Column="12" TopLine="125"/> + </Position20> + <Position21> + <Filename Value="umainform.pas"/> + <Caret Line="153" Column="16" TopLine="127"/> + </Position21> + <Position22> + <Filename Value="umainform.pas"/> + <Caret Line="163" TopLine="152"/> + </Position22> + <Position23> + <Filename Value="umainform.pas"/> + <Caret Line="116" Column="24" TopLine="116"/> + </Position23> + </JumpHistory> + </ProjectSession> +</CONFIG> diff --git a/components/cryptini/latest_stable/demo/cryptinitest.res b/components/cryptini/latest_stable/demo/cryptinitest.res new file mode 100644 index 000000000..a09d0d387 Binary files /dev/null and b/components/cryptini/latest_stable/demo/cryptinitest.res differ diff --git a/components/cryptini/latest_stable/demo/uinputsectionvaluesform.lfm b/components/cryptini/latest_stable/demo/uinputsectionvaluesform.lfm new file mode 100644 index 000000000..c7efd9ec2 --- /dev/null +++ b/components/cryptini/latest_stable/demo/uinputsectionvaluesform.lfm @@ -0,0 +1,86 @@ +object InputSectionValuesForm: TInputSectionValuesForm + Left = 1154 + Height = 314 + Top = 456 + Width = 535 + BorderIcons = [biSystemMenu] + BorderStyle = bsSingle + Caption = 'InputSectionValuesForm' + ClientHeight = 314 + ClientWidth = 535 + OnCreate = FormCreate + OnShow = FormShow + Position = poMainFormCenter + LCLVersion = '1.7' + object Grp_NewSectionValues: TGroupBox + Left = 0 + Height = 43 + Top = 0 + Width = 535 + Align = alTop + AutoSize = True + Caption = 'Input new section values' + ChildSizing.HorizontalSpacing = 10 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 4 + ClientHeight = 23 + ClientWidth = 531 + TabOrder = 0 + object Lbl_SectionName: TLabel + Left = 0 + Height = 23 + Top = 0 + Width = 183 + Caption = 'New Section Name:' + ParentColor = False + end + object edt_NewSectionName: TEdit + Left = 193 + Height = 23 + Top = 0 + Width = 159 + AutoSize = False + OnEditingDone = edt_NewSectionNameEditingDone + TabOrder = 0 + Text = 'My New Section' + end + object lbl_Invisible1: TLabel + Left = 362 + Height = 23 + Top = 0 + Width = 80 + ParentColor = False + end + object lbl_Invisible2: TLabel + Left = 452 + Height = 23 + Top = 0 + Width = 79 + ParentColor = False + end + end + object cmd_Close: TBitBtn + Left = 432 + Height = 26 + Top = 272 + Width = 90 + AutoSize = True + Caption = '&Finished' + Kind = bkClose + ModalResult = 11 + TabOrder = 1 + end + object cmd_Cancel: TBitBtn + Left = 344 + Height = 26 + Top = 273 + Width = 82 + AutoSize = True + Cancel = True + DefaultCaption = True + Kind = bkCancel + ModalResult = 2 + TabOrder = 2 + end +end diff --git a/components/cryptini/latest_stable/demo/uinputsectionvaluesform.pas b/components/cryptini/latest_stable/demo/uinputsectionvaluesform.pas new file mode 100644 index 000000000..8a3e51866 --- /dev/null +++ b/components/cryptini/latest_stable/demo/uinputsectionvaluesform.pas @@ -0,0 +1,156 @@ +unit uInputSectionValuesForm; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, + Buttons; + +const + C_NUMBEROFCONTROLS = 8; // Only need to change it here + +type + + { TInputSectionValuesForm } + + TInputSectionValuesForm = class(TForm) + cmd_Cancel: TBitBtn; + cmd_Close: TBitBtn; + edt_NewSectionName: TEdit; + lbl_Invisible2: TLabel; + Lbl_SectionName: TLabel; + Grp_NewSectionValues: TGroupBox; + lbl_Invisible1: TLabel; + procedure edt_NewSectionNameEditingDone(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + private + procedure DisableSectionNameEdit; + procedure InitControls; + procedure ProcessCheckbox(Sender: TObject); + procedure ProcessValueEdit(Sender: TObject); + public + ValueLabelArray: array[0..C_NUMBEROFCONTROLS - 1] of TLabel; + IdentEditArray: array[0..C_NUMBEROFCONTROLS - 1] of TEdit; + ValueEditArray: array[0..C_NUMBEROFCONTROLS - 1] of TEdit; + ValueCheckBoxArray: array[0..C_NUMBEROFCONTROLS - 1] of TCheckBox; + sSectionName: string; + NumberOfControls: integer; + end; + +var + InputSectionValuesForm: TInputSectionValuesForm; + +implementation + +{$R *.lfm} + +{ TInputSectionValuesForm } +procedure TInputSectionValuesForm.InitControls; +var + iCount: integer; +begin + BeginFormUpdate; + NumberOfControls := High(ValueLabelArray) + 1; + for iCount := Low(ValueLabelArray) to High(ValueLabelArray) do + begin + ValueLabelArray[iCount] := TLabel.Create(Grp_NewSectionValues); + ValueLabelArray[iCount].Caption := Format('Key and Value %d', [iCount + 1]); + ValueLabelArray[iCount].Tag := iCount; + ValueLabelArray[iCount].parent := Grp_NewSectionValues; + + IdentEditArray[iCount] := TEdit.Create(Grp_NewSectionValues); + IdentEditArray[iCount].Text := 'Input Key here'; + IdentEditArray[iCount].Tag := iCount; + // IdentEditArray[iCount].OnEditingDone:=@ProcessEdit; + IdentEditArray[iCount].parent := Grp_NewSectionValues; + + ValueEditArray[iCount] := TEdit.Create(Grp_NewSectionValues); + ValueEditArray[iCount].Text := 'Input value here'; + ValueEditArray[iCount].Tag := iCount; + ValueEditArray[iCount].OnEditingDone := @ProcessValueEdit; + ValueEditArray[iCount].parent := Grp_NewSectionValues; + + ValueCheckBoxArray[iCount] := TCheckBox.Create(Grp_NewSectionValues); + ValueCheckBoxArray[iCount].Caption := 'Integer?'; + ValueCheckBoxArray[iCount].Checked := False; + ValueCheckBoxArray[iCount].Tag := iCount; + ValueCheckBoxArray[iCount].TabStop:=FALSE; + ValueCheckBoxArray[iCount].OnClick := @ProcessCheckbox; + ValueCheckBoxArray[iCount].parent := Grp_NewSectionValues; + end; + EndFormUpdate; +end; + +procedure TInputSectionValuesForm.ProcessCheckbox(Sender: TObject); +// Triggered by OnClick event +var + TempCheckBox: TCheckBox; + iTag, iTest: integer; +begin + TempCheckBox := Sender as TCheckBox; + iTag := TempCheckBox.Tag; + // Validate associated Edit text + if ValueCheckBoxArray[iTag].Checked then + if (TryStrToInt(ValueEditArray[iTag].Text, iTest) = False) then + begin + ValueCheckBoxArray[iTag].Checked := False; + ShowMessageFmt('%s is not an Integer! Please edit it first.', + [ValueEditArray[iTag].Text]); + end; +end; + +procedure TInputSectionValuesForm.ProcessValueEdit(Sender: TObject); +// Triggered by OnEditingDone event +var + TempEdit: TEdit; + iTag, iTest: integer; + +begin + TempEdit := Sender as TEdit; + iTag := TempEdit.Tag; + // Auto check/uncheck associated checkbox + if TryStrToInt(TempEdit.Text, iTest) then + ValueCheckBoxArray[iTag].Checked := True + else + ValueCheckBoxArray[iTag].Checked := False; + // cmd_Close.SetFocus; // Enable this if you put a ShowMessage in this proc +end; + +procedure TInputSectionValuesForm.DisableSectionNameEdit; +begin + edt_NewSectionName.Enabled := False; +end; + +procedure TInputSectionValuesForm.FormCreate(Sender: TObject); +begin + Caption := Application.Title + ' - Make New Section'; + Icon := Application.Icon; + InitControls; + sSectionName := edt_NewSectionName.Text; +end; + +procedure TInputSectionValuesForm.edt_NewSectionNameEditingDone(Sender: TObject); +begin + sSectionName := edt_NewSectionName.Text; +end; + +procedure TInputSectionValuesForm.FormShow(Sender: TObject); +var + iCount: integer; +begin + // Reinitialise controls + edt_NewSectionName.Enabled := True; + for iCount := 0 to NumberOfControls - 1 do + begin + ; + IdentEditArray[iCount].Text := Format('Input Key %d here', [iCount + 1]); + ValueEditArray[iCount].Text := Format('Input value %d here', [iCount + 1]); + ValueCheckBoxArray[iCount].Checked := False; + end; + edt_NewSectionName.Text := 'My New Section'; +end; + +end. diff --git a/components/cryptini/latest_stable/demo/ukeydialog.lfm b/components/cryptini/latest_stable/demo/ukeydialog.lfm new file mode 100644 index 000000000..03483d39d --- /dev/null +++ b/components/cryptini/latest_stable/demo/ukeydialog.lfm @@ -0,0 +1,59 @@ +object keydialog: Tkeydialog + Left = 359 + Height = 132 + Top = 268 + Width = 320 + BorderIcons = [biSystemMenu] + BorderStyle = bsDialog + Caption = 'keydialog' + ClientHeight = 132 + ClientWidth = 320 + DefaultMonitor = dmMainForm + OnCreate = FormCreate + OnShow = FormShow + Position = poMainFormCenter + ShowInTaskBar = stNever + LCLVersion = '1.7' + object lbl_info: TLabel + Left = 0 + Height = 15 + Top = 16 + Width = 320 + Alignment = taCenter + AutoSize = False + Caption = 'Choose either a Phrase or a number as your key' + ParentColor = False + end + object edt_key: TEdit + Left = 35 + Height = 23 + Top = 40 + Width = 250 + TabOrder = 0 + Text = 'Type a phrase or number' + end + object BitBtn1: TBitBtn + Left = 123 + Height = 26 + Top = 80 + Width = 82 + AutoSize = True + Cancel = True + DefaultCaption = True + Kind = bkCancel + ModalResult = 2 + TabOrder = 1 + end + object BitBtn2: TBitBtn + Left = 216 + Height = 26 + Top = 80 + Width = 62 + AutoSize = True + Default = True + DefaultCaption = True + Kind = bkOK + ModalResult = 1 + TabOrder = 2 + end +end diff --git a/components/cryptini/latest_stable/demo/ukeydialog.pas b/components/cryptini/latest_stable/demo/ukeydialog.pas new file mode 100644 index 000000000..e319fc494 --- /dev/null +++ b/components/cryptini/latest_stable/demo/ukeydialog.pas @@ -0,0 +1,51 @@ +unit ukeydialog; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, Forms, StdCtrls, + Buttons; + +type + + { Tkeydialog } + + Tkeydialog = class(TForm) + BitBtn1: TBitBtn; + BitBtn2: TBitBtn; + edt_key: TEdit; + lbl_info: TLabel; + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + private + + public + Var sKeyPhrase:String; + end; + +var + keydialog: Tkeydialog; + +implementation + +{$R *.lfm} + +{ Tkeydialog } + +procedure Tkeydialog.FormCreate(Sender: TObject); +begin + Caption := Application.Title + ' Key Chooser'; + Icon := Application.Icon; + sKeyPhrase:='Type a phrase or number'; + edt_key.Text:=sKeyPhrase; +end; + +procedure Tkeydialog.FormShow(Sender: TObject); +begin + edt_key.Text:=sKeyPhrase; +end; + +end. + diff --git a/components/cryptini/latest_stable/demo/umainform.lfm b/components/cryptini/latest_stable/demo/umainform.lfm new file mode 100644 index 000000000..d4f74d5ff --- /dev/null +++ b/components/cryptini/latest_stable/demo/umainform.lfm @@ -0,0 +1,348 @@ +object mainform: Tmainform + Left = 874 + Height = 327 + Top = 158 + Width = 469 + BorderIcons = [biSystemMenu, biMinimize] + BorderStyle = bsSingle + Caption = 'mainform' + ClientHeight = 307 + ClientWidth = 469 + Menu = MainMenu1 + OnCreate = FormCreate + OnDestroy = FormDestroy + OnShow = FormShow + Position = poScreenCenter + LCLVersion = '1.7' + object lbl_Section: TLabel + Left = 8 + Height = 15 + Top = 88 + Width = 74 + Caption = 'Section Name' + ParentColor = False + end + object edt_Section: TEdit + Left = 88 + Height = 23 + Top = 88 + Width = 195 + Font.Style = [fsBold] + ParentFont = False + TabOrder = 0 + Text = 'TestSection' + end + object lbl_Ident: TLabel + Left = 16 + Height = 15 + Top = 116 + Width = 51 + Caption = 'Test Ident' + ParentColor = False + end + object edt_Ident: TEdit + Left = 88 + Height = 23 + Top = 116 + Width = 195 + TabOrder = 1 + Text = 'Password' + end + object lbl_Value: TLabel + Left = 16 + Height = 15 + Top = 144 + Width = 55 + Caption = 'Test String' + ParentColor = False + end + object edt_Value: TEdit + Left = 88 + Height = 23 + Top = 144 + Width = 195 + TabOrder = 2 + Text = 'mypassword' + end + object cmd_Close: TBitBtn + Left = 368 + Height = 26 + Top = 263 + Width = 75 + AutoSize = True + DefaultCaption = True + Kind = bkClose + ModalResult = 11 + OnClick = mnu_fileCloseClick + TabOrder = 3 + end + object lbl_Integer: TLabel + Left = 16 + Height = 15 + Top = 172 + Width = 61 + Caption = 'Test Integer' + ParentColor = False + end + object edt_Integer: TEdit + Left = 88 + Height = 23 + Top = 172 + Width = 195 + OnEditingDone = edt_IntegerEditingDone + TabOrder = 4 + Text = '12345' + end + object cmd_ShowINI: TButton + Left = 16 + Height = 25 + Top = 264 + Width = 186 + Caption = 'Show/Edit INI' + OnClick = cmd_ShowINIClick + TabOrder = 5 + end + object rg_Encryption: TRadioGroup + Left = 16 + Height = 58 + Top = 200 + Width = 76 + AutoFill = True + AutoSize = True + Caption = 'Encryption' + ChildSizing.LeftRightSpacing = 6 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.EnlargeVertical = crsHomogenousChildResize + ChildSizing.ShrinkHorizontal = crsScaleChilds + ChildSizing.ShrinkVertical = crsScaleChilds + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 1 + ClientHeight = 38 + ClientWidth = 72 + ItemIndex = 0 + Items.Strings = ( + 'On' + 'Off' + ) + OnSelectionChanged = rg_EncryptionSelectionChanged + TabOrder = 6 + end + object rg_SectionHashing: TRadioGroup + Left = 96 + Height = 58 + Top = 200 + Width = 105 + AutoFill = True + AutoSize = True + Caption = 'Section Hashing' + ChildSizing.LeftRightSpacing = 6 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.EnlargeVertical = crsHomogenousChildResize + ChildSizing.ShrinkHorizontal = crsScaleChilds + ChildSizing.ShrinkVertical = crsScaleChilds + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 1 + ClientHeight = 38 + ClientWidth = 101 + ItemIndex = 0 + Items.Strings = ( + 'On' + 'Off' + ) + OnSelectionChanged = rg_SectionHashingSelectionChanged + TabOrder = 7 + end + object GroupBox1: TGroupBox + Left = 304 + Height = 163 + Top = 8 + Width = 139 + AutoSize = True + Caption = 'Section Tests' + ChildSizing.VerticalSpacing = 5 + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 1 + ClientHeight = 143 + ClientWidth = 135 + TabOrder = 8 + object cmd_WriteSection: TButton + Left = 0 + Height = 25 + Top = 0 + Width = 135 + AutoSize = True + Caption = 'Write Whole Section' + OnClick = cmd_WriteSectionClick + TabOrder = 0 + end + object cmd_ReadSectionValues: TButton + Left = 0 + Height = 25 + Top = 30 + Width = 135 + AutoSize = True + Caption = 'Read Whole Section' + OnClick = cmd_ReadSectionValuesClick + TabOrder = 1 + end + object cmd_VerifySectionValues: TButton + Left = 0 + Height = 25 + Top = 60 + Width = 135 + AutoSize = True + Caption = 'Verify Whole Section' + OnClick = cmd_VerifySectionValuesClick + TabOrder = 2 + end + object cmd_EraseSection: TButton + Left = 0 + Height = 25 + Top = 90 + Width = 135 + AutoSize = True + Caption = 'Erase Whole Section' + OnClick = cmd_EraseSectionClick + TabOrder = 3 + end + object cmb_Sections: TComboBox + Left = 0 + Height = 23 + Top = 120 + Width = 135 + ItemHeight = 15 + OnSelect = cmb_SectionsSelect + Style = csDropDownList + TabOrder = 4 + end + end + object Grp_DefaultValueTests: TGroupBox + Left = 16 + Height = 70 + Top = 8 + Width = 284 + AutoSize = True + Caption = 'Default Value Tests' + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 3 + ClientHeight = 50 + ClientWidth = 280 + TabOrder = 9 + object cmd_Write: TButton + Left = 0 + Height = 25 + Top = 0 + Width = 91 + AutoSize = True + Caption = 'Write Values' + OnClick = cmd_WriteClick + TabOrder = 0 + end + object cmd_Read: TButton + Left = 91 + Height = 25 + Top = 0 + Width = 96 + AutoSize = True + Caption = 'Read Values' + OnClick = cmd_ReadClick + TabOrder = 1 + end + object cmd_Verify: TButton + Left = 187 + Height = 25 + Top = 0 + Width = 93 + AutoSize = True + Caption = 'Verify Values' + OnClick = cmd_VerifyClick + TabOrder = 2 + end + object cmd_ValueExists: TButton + Left = 0 + Height = 25 + Top = 25 + Width = 91 + AutoSize = True + Caption = 'Values Exist' + OnClick = cmd_ValueExistsClick + TabOrder = 3 + end + object cmd_DeleteValue: TButton + Left = 91 + Height = 25 + Top = 25 + Width = 96 + AutoSize = True + Caption = 'Delete Values' + OnClick = cmd_DeleteValueClick + TabOrder = 4 + end + end + object grp_convert: TGroupBox + Left = 304 + Height = 45 + Top = 176 + Width = 133 + AutoSize = True + Caption = 'Upgrade existing INI' + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 1 + ClientHeight = 25 + ClientWidth = 129 + TabOrder = 10 + object cmd_convertToCryptini: TButton + Left = 0 + Height = 25 + Top = 0 + Width = 129 + AutoSize = True + Caption = 'Convert to CryptINI' + OnClick = cmd_convertToCryptiniClick + TabOrder = 0 + end + end + object MainMenu1: TMainMenu + Left = 432 + object mnu_file: TMenuItem + Caption = '&File' + object mnu_fileClose: TMenuItem + Caption = 'E&xit' + OnClick = mnu_fileCloseClick + end + end + object mnu_options: TMenuItem + Caption = '&Options' + object mnu_optionsEncryptionKey: TMenuItem + Caption = 'Integer En&cryption key...' + OnClick = mnu_optionsEncryptionKeyClick + end + object mnu_optionsEncryptINIFile: TMenuItem + Caption = 'Encrypt INI file' + OnClick = mnu_optionsEncryptINIFileClick + end + object mnu_optionsDecryptINIFile: TMenuItem + Caption = 'Decrypt INI file' + OnClick = mnu_optionsDecryptINIFileClick + end + end + object mnu_help: TMenuItem + Caption = '&Help' + object mnu_helpHelp: TMenuItem + Caption = 'Help' + OnClick = mnu_helpHelpClick + end + object mnu_helpAbout: TMenuItem + Caption = '&About..' + OnClick = mnu_helpAboutClick + end + end + end + object OpenDialog1: TOpenDialog + Title = 'Open existing INI file' + Filter = 'INI file|*.ini|Any File|*.*' + Options = [ofReadOnly, ofNoTestFileCreate, ofEnableSizing, ofViewDetail] + Left = 384 + Top = 8 + end +end diff --git a/components/cryptini/latest_stable/demo/umainform.pas b/components/cryptini/latest_stable/demo/umainform.pas new file mode 100644 index 000000000..03905ac4c --- /dev/null +++ b/components/cryptini/latest_stable/demo/umainform.pas @@ -0,0 +1,993 @@ +unit umainform; + +{$DEFINE USE_DCPCRYPT}// Delete this if you don't have the DCrypt library +// It enables the 'Encrypt INI' and 'Decrypt INI' menu entries +// {$DEFINE USE_THREADSAFE} // Enable this for the thread-safe version + +{ Test App for cryptini unit + + Copyright (C) 2016 Gordon Bamber minesadorada@gmail.com + Encrypt/Decrypt INI code: @Ericktux (http://forum.lazarus.freepascal.org) + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +} +{$mode objfpc}{$H+} + +interface + +uses + SysUtils, LazFileUtils, FileUtil, Forms, Dialogs, StdCtrls, Controls, Classes, + Buttons, ExtCtrls, Menus, ucryptini, umemoform, ukeydialog, + uInputSectionValuesForm; + +const + {$IFDEF WINDOWS} + C_OS = 'win'; + {$ELSE} + C_OS = 'linux'; + {$ENDIF} + {$IFDEF CPU32} + C_BITNESS = '32'; + {$ELSE} + C_BITNESS = '64'; + {$ENDIF} + C_PFX = C_OS + C_BITNESS; + C_KEYPHRASE = 'Rudolph the Red Nosed Reindeer: had a very shiny nose'; + + C_VERSION = '1.0.0.5'; + +type + + { Tmainform } + + Tmainform = class(TForm) + cmd_convertToCryptini: TButton; + cmd_DeleteValue: TButton; + cmd_EraseSection: TButton; + cmd_Read: TButton; + cmd_ReadSectionValues: TButton; + cmd_ShowINI: TButton; + cmd_Close: TBitBtn; + cmd_ValueExists: TButton; + cmd_Verify: TButton; + cmd_VerifySectionValues: TButton; + cmd_Write: TButton; + cmd_WriteSection: TButton; + cmb_Sections: TComboBox; + edt_Value: TEdit; + edt_Section: TEdit; + edt_Ident: TEdit; + edt_Integer: TEdit; + GroupBox1: TGroupBox; + grp_convert: TGroupBox; + Grp_DefaultValueTests: TGroupBox; + lbl_Value: TLabel; + lbl_Section: TLabel; + lbl_Ident: TLabel; + lbl_Integer: TLabel; + MainMenu1: TMainMenu; + mnu_optionsDecryptINIFile: TMenuItem; + mnu_optionsEncryptINIFile: TMenuItem; + mnu_helpAbout: TMenuItem; + mnu_helpHelp: TMenuItem; + mnu_help: TMenuItem; + mnu_optionsEncryptionKey: TMenuItem; + mnu_fileClose: TMenuItem; + mnu_options: TMenuItem; + mnu_file: TMenuItem; + OpenDialog1: TOpenDialog; + rg_Encryption: TRadioGroup; + rg_SectionHashing: TRadioGroup; + procedure cmb_SectionsSelect(Sender: TObject); + procedure cmd_convertToCryptiniClick(Sender: TObject); + procedure cmd_DeleteValueClick(Sender: TObject); + procedure cmd_ReadClick(Sender: TObject); + procedure cmd_ReadSectionValuesClick(Sender: TObject); + procedure cmd_ShowINIClick(Sender: TObject); + procedure cmd_ValueExistsClick(Sender: TObject); + procedure cmd_VerifyClick(Sender: TObject); + procedure cmd_VerifySectionValuesClick(Sender: TObject); + procedure cmd_WriteClick(Sender: TObject); + procedure cmd_EraseSectionClick(Sender: TObject); + procedure cmd_WriteSectionClick(Sender: TObject); + procedure edt_IntegerEditingDone(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure mnu_fileCloseClick(Sender: TObject); + procedure mnu_helpAboutClick(Sender: TObject); + procedure mnu_helpHelpClick(Sender: TObject); + {$IFDEF USE_DCPCRYPT} + procedure mnu_optionsDecryptINIFileClick(Sender: TObject); + procedure mnu_optionsEncryptINIFileClick(Sender: TObject); + {$ENDIF} + procedure mnu_optionsEncryptionKeyClick(Sender: TObject); + procedure rg_EncryptionSelectionChanged(Sender: TObject); + procedure rg_SectionHashingSelectionChanged(Sender: TObject); + private + IniFilePath: string; + {$IFDEF USE_THREADSAFE} + INI: TLockCryptIniFile; + {$ELSE} + INI: TCryptIniFile; + {$ENDIF} + sStoredMD5Hash: string; + sVersion: string; + public + + end; + +var + mainform: Tmainform; + +implementation + +{$R *.lfm} + +{ Tmainform } + +procedure Tmainform.FormCreate(Sender: TObject); +begin + IniFilePath := ProgramDirectory + 'test' + C_PFX + +{$IFDEF WINDOWS} + '.' + +{$ENDIF} + 'ini'; + +{$IFNDEF USE_DCPCRYPT} + mnu_optionsEncryptINIFile.Enabled := False; + mnu_optionsDecryptINIFile.Enabled := False; +{$ENDIF} + + {DEBUG - delete any old versions of the INI + if FileExists(IniFilePath) then + DeleteFile(IniFilePath); + } + Caption := Application.Title; + Icon := Application.Icon; + {$IFDEF USE_THREADSAFE} + INI := TLockCryptIniFile.Create(IniFilePath); + INI.Lock; + {$ELSE} + INI := TCryptIniFile.Create(IniFilePath); + {$ENDIF} + + // Create encryption key for secure Read/WriteInteger + INI.KeyPhrase := C_KEYPHRASE; + + // Or set INI.Key directly (weaker encryption) + // DEBUG: ShowMessageFmt('Key set to %d',[INI.Key]); + + // method: WriteIdent(Const sAuthor,sCopyright,sLicense,sContact:String;Force: boolean=False); + // No need to do this each time + // Comment this line out once you have the MD5Hash from the ini file + if INI.IsVirgin then // DeFlowers + begin + INI.WriteIdent('Gordon Bamber', '(c)2016', 'LGPL', 'minesadorada@gmail.com', True); + // MD5 for this is: 92abf0deecbb25c435bff507a396d92a + end + else + // someone tampered with the ident? + if not INI.VerifyIdent('92abf0deecbb25c435bff507a396d92a') then + begin + ShowMessage('Program ident has been tampered with.' + LineEnding + + 'Restoring correct version.'); + // Last parameter (Optional) forces a rewrite even if FirstRun = 0 + INI.WriteIdent('Gordon Bamber', '(c)2016', 'LGPL', 'minesadorada@gmail.com', True); + end; + + sVersion := C_VERSION; + sStoredMD5Hash := '32-character MD5Hash string'; + INI.ReadSections(cmb_Sections.Items); + cmb_Sections.ItemIndex := 0; + edt_Section.Text := 'TestSection'; +end; + +procedure Tmainform.FormDestroy(Sender: TObject); +begin + If Assigned(INI) then FreeAndNil(INI); +end; + +procedure Tmainform.FormShow(Sender: TObject); +begin + // Test the IsVirgin function + if INI.IsVirgin then + ShowMessage('First time run of this app'); +end; + +procedure Tmainform.mnu_fileCloseClick(Sender: TObject); +begin + Close; +end; + +procedure Tmainform.mnu_helpAboutClick(Sender: TObject); +// Shows ReadUnencryptedString method +var + s: string; +begin + s := Application.Title + LineEnding; + s += 'Version: ' + INI.ReadUnencryptedString('ProgramInfo', IDENT_APPVERSION, '') + LineEnding + LineEnding; + s += INI.ReadUnencryptedString('ProgramInfo', IDENT_COPYRIGHT, ''); + s += ' by ' + INI.ReadUnencryptedString('ProgramInfo', IDENT_AUTHOR, '') + LineEnding; + s += 'Licence: ' + INI.ReadUnencryptedString('ProgramInfo', IDENT_LICENSE, '') + + LineEnding; + s += 'Made with LCL v ' + INI.ReadUnencryptedString('ProgramInfo', IDENT_LCLVERSION, ''); + s += ' FPC v ' + INI.ReadUnencryptedString('ProgramInfo', IDENT_FPCVERSION, '') + + LineEnding; + s += 'Compiled ' + INI.ReadUnencryptedString('ProgramInfo', IDENT_LASTCOMPILED, ''); + s += ' for ' + INI.ReadUnencryptedString('ProgramInfo', IDENT_TARGET, '') + + LineEnding; + s += 'CryptINI Version: ' + INI.CryptINIVersion + LineEnding; + s += 'Cipher in use: ' + INI.CipherType + '. Hash in use: ' + INI.HashType + '.'; + MessageDlg('About ' + Application.Title, s, + mtInformation, [mbOK], 0); +end; + +procedure Tmainform.mnu_helpHelpClick(Sender: TObject); +begin + with ShowINIForm do + begin + MakeReadOnly; + Caption := 'Help for ' + Application.Title; + Memo_INI.Lines.Clear; + Memo_INI.Lines.Add('This test application is to test the Tcryptini class V ' + + INI.CryptINIVersion); + Memo_INI.Lines.Add(''); + Memo_INI.Lines.Add( + 'The obvious test is to click Write, Read then Verify, which uses automatic values.'); + Memo_INI.Lines.Add( + 'Verification of an entry involves reading the value with its built-in MD5Hash'); + Memo_INI.Lines.Add( + 'and then computing a new MD5Hash from the value, and comparing it with the built-in one.'); + Memo_INI.Lines.Add(''); + Memo_INI.Lines.Add( + 'Additionally, if SectionHashing=TRUE then every time a new entry is added to the section,'); + Memo_INI.Lines.Add( + 'all the entries are combined into a section hash, and it is written/updated as an automatic'); + Memo_INI.Lines.Add( + 'new/updated entry: MD5Hash=<32-character hash> ,which you can use in the VerifySection(MD5Has Value) method'); + Memo_INI.Lines.Add(''); + Memo_INI.Lines.Add( + 'There is a new method WriteSectionValues(Section,Strings) which is absent in TINIFile that you may find useful.'); + Memo_INI.Lines.Add( + 'WriteSectionValues works with PlainText TRUE/FALSE and SectionHashing TRUE/FALSE.'); + Memo_INI.Lines.Add(''); + Memo_INI.Lines.Add( + 'Other new methods are EncryptINI and DecryptINI. This acts on the whole INI file,'); + Memo_INI.Lines.Add( + 'with password, new file extension and auto-deleting the "old" file as optional parameters.'); + Memo_INI.Lines.Add('The defaults are the INI.KeyPhrase, ".enc" and no auto-deletion.'); + Memo_INI.Lines.Add(''); + Memo_INI.Lines.Add( + 'Wnen property PlainText=TRUE then TCryptINI behaves just as TINIFile did'); + Memo_INI.Lines.Add( + 'This property can be changed on-the-fly to enable a mixed Crypted/Plaintext INI file.'); + Memo_INI.Lines.Add(''); + Memo_INI.Lines.Add( + 'Note that Integer keys have an automatic "' + INTEGER_MARKER + + '" added in encrypted mode.'); + Memo_INI.Lines.Add( + 'This is so that the ReadSection method can identify them in Encrypted mode.'); + Memo_INI.Lines.Add( + '(Integers are double-encrypted for extra security, so need to be read differently from all other types)'); + Memo_INI.Lines.Add(''); + Memo_INI.Lines.Add( + 'When testing, use the Show/Edit INI button to see the results. This will help you to understand'); + Memo_INI.Lines.Add( + 'how CryptINI works, and what it can do.'); + Memo_INI.Lines.Add(''); + Memo_INI.Lines.Add('CryptINI was designed to solve 2 issues:'); + Memo_INI.Lines.Add( + '1. Making sure the ProgramInfo section is never altered, assuring you attribution stays secure.'); + Memo_INI.Lines.Add( + 'Once you have the MD5Hash of it, you can easily make an "authenticity checker" app using CryptINI'); + Memo_INI.Lines.Add( + '2. Storing Passwords and Scores in an editable INI file which is tamper-proof to the casual hacker.'); + Memo_INI.Lines.Add( + '(If numbers are written using WriteInteger, they are especially difficult to alter)'); + Memo_INI.Lines.Add(''); + Memo_INI.Lines.Add('In this app and ucryptini.pas is a DEFINE: {$DEFINE USE_DCPCRYPT}'); + Memo_INI.Lines.Add( + 'This assumes you have the DCPCrypt runtime/designtime component installed.'); + Memo_INI.Lines.Add( + 'If you haven''t then either install it or comment out the DEFINE and'); + Memo_INI.Lines.Add( + 'remove it from Project Inspector. It is available via OnlinePackageManager'); + Memo_INI.Lines.Add(''); + Memo_INI.Lines.Add('Open ucryptini in a text editor to look at the commented code'); + Memo_INI.Lines.Add('- Enjoy!'); + ShowModal; + end; +end; + +{$IFDEF USE_DCPCRYPT} +procedure Tmainform.mnu_optionsDecryptINIFileClick(Sender: TObject); +begin + if MessageDlg('Delete encrypted INI file?', mtConfirmation, [mbYes, mbNo], 0, mbYes) = + mrYes then + INI.DecryptINI(True) + else + INI.DecryptINI(False); + // Remember to reset the key phrase! + INI.KeyPhrase := C_KEYPHRASE; + + // Update controls + cmb_Sections.Clear; + INI.ReadSections(cmb_Sections.Items); + cmb_Sections.Refresh; + cmb_Sections.ItemIndex := 0; +end; + +procedure Tmainform.mnu_optionsEncryptINIFileClick(Sender: TObject); +begin + if MessageDlg('Delete unencrypted INI file?', mtConfirmation, + [mbYes, mbNo], 0, mbYes) = mrYes then + INI.EncryptINI(True) + else + INI.EncryptINI(False); + Application.ProcessMessages; + // Update controls + cmb_Sections.Clear; + cmb_Sections.ItemIndex := 0; +end; + +{$ENDIF} + +procedure Tmainform.mnu_optionsEncryptionKeyClick(Sender: TObject); +var + s: string; + l: longint; +begin + keydialog.sKeyPhrase := INI.KeyPhrase; + KeyDialog.ShowModal; + if KeyDialog.ModalResult = mrOk then + begin + s := KeyDialog.edt_key.Text; + if TryStrToInt(s, l) then + INI.Key := l + else + INI.Keyphrase := s; + ShowMessage('Key changed successfully'); + end; +end; + +procedure Tmainform.rg_EncryptionSelectionChanged(Sender: TObject); +begin + if rg_Encryption.ItemIndex = 0 then + INI.PlainTextMode := False + else + INI.PlainTextMode := True; + if INI.PlainTextMode = True then + begin + rg_SectionHashing.ItemIndex := 1; + INI.SectionHashing := False; + end; + cmd_Read.Enabled := False; + cmd_Verify.Enabled := False; +end; + +procedure Tmainform.rg_SectionHashingSelectionChanged(Sender: TObject); +begin + if rg_SectionHashing.ItemIndex = 0 then + INI.SectionHashing := True + else + INI.SectionHashing := False; +end; + +procedure Tmainform.cmd_WriteClick(Sender: TObject); +var + s: string; +begin + // Best results when writing to TestSection + if (edt_Section.Text <> 'TestSection') then + if MessageDlg('Please confirm', 'Are you sure you want to write to ' + + edt_Section.Text + '? (It should be "TestSection")', mtConfirmation, + [mbYes, mbNo], 0, mbNo) = mrNo then + begin + edt_Section.Text := 'TestSection'; + ShowMessage('OK. Writing to default section "TestSection" instead'); + end; + INI.SectionHashing := False; + INI.WriteString(edt_Section.Text, edt_Ident.Text, edt_Value.Text); + INI.WriteInteger(edt_Section.Text, 'Integer', StrToInt(edt_Integer.Text)); + // Write other types as a test + INI.WriteBool(edt_Section.Text, 'Boolean', True); + INI.WriteFloat(edt_Section.Text, 'Float', 3.142); + INI.WriteDateTime(edt_Section.Text, 'Date', StrToDate('15/10/2016', + 'dd mm yyyy', '/')); + INI.WriteInt64(edt_Section.Text, 'Int64', 1000); + INI.SectionHashing := True; + INI.MakeSectionHash(edt_Section.Text, True); + cmd_Read.Enabled := True; + cmd_Verify.Enabled := True; + s := 'Values written:' + LineEnding; + s += 'WriteString: ' + edt_Value.Text + LineEnding; + s += 'WriteFloat: 3.142' + LineEnding; + s += 'WriteDateTime: 15/10/2016' + LineEnding; + s += 'WriteInt64: 1000' + LineEnding; + s += 'WriteInteger: ' + edt_Integer.Text + LineEnding; + INI.ReadSections(cmb_Sections.Items); + cmb_Sections.ItemIndex := Pred(cmb_Sections.Items.Count); + ShowMessage(s); +end; + +procedure Tmainform.cmd_EraseSectionClick(Sender: TObject); +begin + if not INI.SectionExists(edt_Section.Text) then + begin + ShowMessage(edt_Section.Text + ' is absent, so nothing to erase!'); + Exit; + end; + if edt_Section.Text = IDENT_SECTION then + if MessageDlg('Please confirm', 'Are you sure you want to delete ' + + IDENT_SECTION + '?', mtConfirmation, [mbCancel, mbYes], 0, mbCancel) = + mrCancel then + exit; + INI.EraseSection(edt_Section.Text); + ShowMessage('Section ' + edt_Section.Text + ' is no more.'); + INI.ReadSections(cmb_Sections.Items); + cmb_Sections.ItemIndex := 0; +end; + +procedure Tmainform.cmd_WriteSectionClick(Sender: TObject); +var + iCount: integer; + sTempSectionName: string; + MyStringList: TStrings; +begin + with InputSectionValuesForm do + begin + ShowModal; + if ModalResult = mrCancel then + Exit; + sTempSectionName := sSectionName; + if sTempSectionName = IDENT_SECTION then + if MessageDlg('Please confirm', 'Are you sure you want to write to ' + + IDENT_SECTION + '?', mtConfirmation, [mbYes, mbCancel], 0, mbCancel) = + mrCancel then + exit; + edt_Section.Text := sSectionName; + MyStringList := TStringList.Create; + try + MyStringList.Clear; + MyStringList.BeginUpdate; + for iCount := 0 to (NumberOfControls - 1) do + MyStringList.Add(IdentEditArray[iCount].Text + '=' + + ValueEditArray[iCount].Text); + MyStringList.EndUpdate; + INI.WriteSectionValues(sSectionName, MyStringList); + INI.UpdateFile; + ShowMessage('Section ' + sTempSectionName + ' written successfully'); + finally + MyStringList.Free; + end; + end; + INI.ReadSections(cmb_Sections.Items); + cmb_Sections.ItemIndex := Pred(cmb_Sections.Items.Count); +end; + +procedure Tmainform.edt_IntegerEditingDone(Sender: TObject); +var + iTest: longint; +begin + if not TryStrToInt(edt_Integer.Text, iTest) then + begin + ShowMessageFmt('%s is not an Integer. Resetting to %s', + [edt_Integer.Text, '12345']); + edt_Integer.Text := '12345'; + end; +end; + +procedure Tmainform.cmd_ReadClick(Sender: TObject); +var + s: string; +begin + if not INI.SectionExists(edt_Section.Text) then + begin + ShowMessage(edt_Section.Text + ' is absent, so nothing to read!'); + Exit; + end; + // Dont read IDENT_SECTION + if edt_Section.Text = IDENT_SECTION then + begin + cmd_ReadSectionValues.Click; + Exit; + end; + if (edt_Section.Text <> 'TestSection') then + if MessageDlg('Please confirm', 'Are you sure you want to read test values from ' + + edt_Section.Text + '?', mtConfirmation, [mbCancel, mbYes], 0, mbCancel) = + mrCancel then + begin + edt_Section.Text := 'TestSection'; + ShowMessage('OK. Reading default section "TestSection" instead'); + end; + + if INI.PlainTextMode then + INI.MD5Hash := 'n/a'; + s := INI.ReadString(edt_Section.Text, edt_Ident.Text, 'unknown'); + ShowMessageFmt('Value of %s in %s is %s %s(MD5 hash: %s)', + [edt_Ident.Text, edt_Section.Text, s, LineEnding, INI.MD5Hash]); + if INI.ReadBool(edt_Section.Text, 'Boolean', False) = True then + ShowMessageFmt('ReadBool is TRUE%s(MD5 hash: %s)', [LineEnding, INI.MD5Hash]) + else + ShowMessageFmt('ReadBool is FALSE%s(MD5 hash: %s)', [LineEnding, INI.MD5Hash]); + ShowMessageFmt('ReadFloat is %.3f%s(MD5 hash: %s)', + [INI.ReadFloat(edt_Section.Text, 'Float', 0), LineEnding, INI.MD5Hash]); + ShowMessageFmt('ReadDateTime is %s%s(MD5 hash: %s)', + [DateToStr(INI.ReadDateTime(edt_Section.Text, 'Date', NOW)), + LineEnding, INI.MD5Hash]); + ShowMessageFmt('ReadInt64 is %d%s(MD5 hash: %s)', + [INI.ReadInt64(edt_Section.Text, 'Int64', 0), LineEnding, INI.MD5Hash]); + ShowMessageFmt('ReadInteger is %d%s(MD5 hash: %s)', + [INI.ReadInteger(edt_Section.Text, 'Integer', 0), LineEnding, INI.MD5Hash]); +end; + +procedure Tmainform.cmb_SectionsSelect(Sender: TObject); +begin + edt_Section.Text := cmb_Sections.Items[cmb_Sections.ItemIndex]; + +end; + +procedure Tmainform.cmd_convertToCryptiniClick(Sender: TObject); +{ +** This routine is a good demonstation of what TCryptINI can do +** It converts old ini files into encrypted ones. + +** Workflow: +0. Inform user what is about to happen and offer bailout (very important!) +1. Backup old ini file +2. Make a working copy +3. Process the working copy +4. Seek approval of changes +5. If yes, Overwrite the old ini file and clean up +} +const + CR = LineEnding; +var + sINIFilePathToConvert, sSourceINIFilePath, s, TempSectionName, sKeyPhrase: string; + sValueEntry, sKey, sValue: string; + INIFileToConvert: TCryptINIFile; + SectionNameList, ValueList: TStrings; + iCount, jCount, lTemp: integer; + dtTemp: TDateTime; +begin + try // - EXCEPT + s := 'This utility will convert a regular INI file to a CryptINI file' + CR; + s += 'using the Password/Keyphrase of your choice.' + CR + CR; + s += 'Your chosen INI file will first be backed up in the same folder,' + CR; + s += 'and a working copy made. After the conversion you will have a' + CR; + s += 'chance to view the changes and either approve or revert them.' + CR + CR; + s += 'If you approve, the original INI file will be overwritten by' + CR; + s += 'the approved working copy.' + CR; + s += 'If you revert, your original INI file will remain intact.' + CR + CR; + s += 'Would you like to continue?' + CR; + if MessageDlg(s, mtConfirmation, [mbYes, mbNo], 0, mbYes) <> mrYes then + Exit; + if OpenDialog1.Execute then + sINIFilePathToConvert := OpenDialog1.FileName + else + Exit; + // Prevent changing this app's INI file + if sINIFilePathToConvert = INI.Filename then + begin + ShowMessage('You cannot choose the INI file for this application! Try again.'); + Exit; + end; + // Make a backup + if CopyFile(sINIFilePathToConvert, ChangeFileExt(sINIFilePathToConvert, '.bak')) then + ShowMessageFmt('Your existing INI file has been backed up to %s', + [ChangeFileExt(sINIFilePathToConvert, '.bak')]) + else + begin + ShowMessage('Could not write to ' + ExtractFileDir(sINIFilePathToConvert) + + ' - Quitting'); + Exit; + end; + // Make a working copy + sSourceINIFilePath := ChangeFileExt(sINIFilePathToConvert, '.src'); + if not CopyFile(sINIFilePathToConvert, sSourceINIFilePath) then + begin + ShowMessage('Could not write to ' + ExtractFileDir(sINIFilePathToConvert) + + ' - Quitting'); + Exit; + end; + // Use the working copy + INIFileToConvert := TCryptINIFile.Create(sSourceINIFilePath); + // Fetch a pass phrase + sKeyPhrase := InputBox('Pass Phrase', + 'Please type in your pass phrase for this INI file', C_KEYPHRASE); + INIFileToConvert.KeyPhrase := sKeyPhrase; + // Create temprary stringlists + SectionNameList := TStringList.Create; + ValueList := TStringList.Create; + try + // Use as a regular TiniFile + INIFileToConvert.PlainTextmode := True; + INIFileToConvert.SectionHashing := False; + SectionNameList.Clear; + // Fetch all the Section names + INIFileToConvert.ReadSections(SectionNameList); + if SectionNameList.Count > 0 then + // For each Sectionnane... + for iCount := 0 to Pred(SectionNameList.Count) do + begin + TempSectionName := SectionNameList[iCount]; + // Don't process ProgramInfo + if TempSectionName = IDENT_SECTION then + Continue; // Dont convert this + ValueList.Clear; + // Fetch all the Key=Values for this Section + INIFileToConvert.ReadSectionValues(TempSectionName, ValueList); + if ValueList.Count > 0 then + // For each Key-Value pair... + for jCount := 0 to Pred(ValueList.Count) do + begin + sValueEntry := ValueList[jCount]; + sKey := ''; + sValue := ''; + // Split into Key and Value + If NOT INI.SplitKeyValue(sValueEntry, sKey, sValue) then Continue; + // We have the valid key and value else skipped + // Don't process MD5Has key + if sKey = IDENT_MD5HASH then + Continue; + // Is it a number? + if TryStrToInt(sValue, lTemp) then // Integer + begin + INIFileToConvert.PlainTextMode := False; + // Is it a Boolean? + if ((lTemp = 0) or (lTemp = 1)) then // Guess a boolean value? + INIFileToConvert.WriteString(TempSectionName, sKey, sValue) + else + begin + // Process Integer Value + INIFileToConvert.PlainTextMode := True; + // Delete unencrypted key without INTEGER_MARKER + INIFileToConvert.DeleteKey(TempSectionName, sKey); + INIFileToConvert.PlainTextMode := False; + // Rewrite encrypted key with INTEGER_MARKER + INIFileToConvert.WriteInteger(TempSectionName, sKey, lTemp); + end; + INIFileToConvert.PlainTextMode := True; + end + else // String,Date + begin + // Process non-numeric values + INIFileToConvert.PlainTextMode := False; + // Is it a DateTime? + if TryStrToDateTime(sValue, dtTemp) then + INIFileToConvert.WriteDateTime(TempSectionName, sKey, dtTemp) + else + // Process String value + INIFileToConvert.WriteString(TempSectionName, sKey, sValue); + INIFileToConvert.PlainTextMode := True; + end; + // Hash the whole Section (Make MD5Hash entry) + INIFileToConvert.MakeSectionHash(TempSectionName, True); + end; + end; + // Conversion is done. Show the user the Working Copy + with ShowINIForm do + begin + MakeReadOnly; // Put memoform into readonly mode + cmd_Abort.Visible := True; // Show the invisible button + Caption := 'Contents of converted INI file'; + Memo_INI.Lines.Clear; + // Check the file is still there :) + if LazFileUtils.FileExistsUTF8(INIFileToConvert.Filename) then + begin + Memo_INI.Lines.LoadFromFile(INIFileToConvert.Filename); + sINIFilePath := INIFileToConvert.Filename; + cmd_Close.Caption := 'Approve conversion'; + // Display the INI to the user + ShowModal; + // Tidy up + cmd_Close.Caption := '&Close'; + cmd_Abort.Visible := False; // Make the button invisible again. + // What did the user decide? + if ModalResult <> mrAbort then // All good - proceed + begin + INIFileToConvert.UpdateFile; + Sleep(100); + // Overwrite old INI file: + if not CopyFile(sSourceINIFilePath, sINIFilePathToConvert) then + begin + ShowMessage('Could not Update ' + ExtractFileDir(sINIFilePathToConvert) + + ' - Quitting'); + Exit; + end; + +{ + // Encrypt file as well? + if MessageDlg( + 'Conversion Successful. Would you like to Encrypt the whole file as well?', + mtConfirmation, [mbYes, mbNo], 0, mbNo) = mrYes then + begin + // User wants to encrypt. Get a new pass phrase. + sKeyPhrase := InputBox('Pass Phrase', + 'Please type in your pass phrase for this INI file', C_KEYPHRASE); + // Work with the (changed) original + INIFileToConvert.Free; // Finished with the working copy + // Load the original + INIFileToConvert := TCryptINIFile.Create(sINIFilePathToConvert); + INIFileToConvert.KeyPhrase:=sKeyPhrase; + // Delete the old INI file or no? + if MessageDlg('Delete unencrypted INI file?', mtConfirmation, + [mbYes, mbNo], 0, mbYes) = mrYes then + INIFileToConvert.EncryptINI(True, sKeyPhrase, '.enc') + else + INIFileToConvert.EncryptINI(False, sKeyPhrase, '.enc'); + end; + } + // All went well - inform the user. + ShowMessage('All operations were successful.' + LineEnding + + 'Click OK to clean up temporary files'); + end + else + // User chose to Revert. sINIFilePathToConvert file is still intact. + + ShowMessage('Conversion aborted. INI file is unchanged.' + + LineEnding + 'Click OK to clean up temporary files'); + + // Tidy up: + // Delete working copy + if not DeleteFile(sSourceINIFilePath) then + begin + ShowMessage('Could not Delete ' + ExtractFileDir(sSourceINIFilePath) + + ' - Quitting'); + Exit; + end; + // Delete backup file as well? + if MessageDlg('Delete backup file?', mtConfirmation, [mbYes, mbNo], 0, mbYes) = + mrYes then + if not DeleteFile(ChangeFileExt(sINIFilePathToConvert, '.bak')) then + begin + ShowMessage('Could not Delete ' + + ExtractFileDir(ChangeFileExt(sINIFilePathToConvert, '.bak'))); + Exit; + end; + end; + end; + finally + ValueList.Free; + SectionNameList.Free; + FreeAndNil(INIFileToConvert); + end; + except + // It's a long routine. Let's hope we don't get here. + On E: Exception do + ShowMessageFmt('An error has occurred that is not your fault.%sThe error is%s', + [CR, E.Message]); + end; +end; + +procedure Tmainform.cmd_DeleteValueClick(Sender: TObject); +begin + if not INI.SectionExists(edt_Section.Text) then + begin + ShowMessage(edt_Section.Text + ' is absent, so nothing to read!'); + Exit; + end; + if (edt_Section.Text <> 'TestSection') then + if MessageDlg('Please confirm', 'Are you sure you want to delete test values from ' + + edt_Section.Text + '?', mtConfirmation, [mbCancel, mbYes], 0, mbCancel) = + mrCancel then + begin + edt_Section.Text := 'TestSection'; + ShowMessage('OK. Deleting values in default section "TestSection" instead'); + end; + ShowMessage('Deleting values "' + edt_Ident.Text + '" and "Integer"'); + INI.DeleteKey(edt_Section.Text, edt_Ident.Text); + INI.DeleteKey(edt_Section.Text, 'Integer'); + if INI.ValueExists(edt_Section.Text, edt_Ident.Text) then + ShowMessage(edt_Ident.Text + ' not deleted!') + else + ShowMessage(edt_Ident.Text + ' deleted'); + if INI.ValueExists(edt_Section.Text, 'Integer') then + ShowMessage('Integer not deleted!') + else + ShowMessage('Integer deleted'); + +end; + +procedure Tmainform.cmd_ReadSectionValuesClick(Sender: TObject); +var + MyStringList: TStrings; + iCount: integer; + TempPlainTextMode: boolean; +begin + if not INI.SectionExists(edt_Section.Text) then + begin + ShowMessage(edt_Section.Text + ' is absent, so nothing to read!'); + Exit; + end; + TempPlainTextMode := INI.PlainTextMode; + if edt_Section.Text = IDENT_SECTION then + INI.PlainTextMode := True; + MyStringList := TStringList.Create; + try + INI.ReadSectionValues(edt_Section.Text, MyStringList); + if MyStringList.Count > 0 then + for iCount := 0 to Pred(MyStringList.Count) do + ShowMessageFmt('Section name: %s%s(Value %d of %d): %s', + [edt_Section.Text, LineEnding, iCount + 1, MyStringList.Count, + MyStringList[iCount]]) + else + ShowMessage('Nothing in this section!'); + finally + MyStringList.Free; + end; + INI.PlainTextMode := TempPlainTextMode; +end; + +procedure Tmainform.cmd_ShowINIClick(Sender: TObject); +var + s: string; +begin + with ShowINIForm do + begin + MakeWriteable; + Caption := 'Contents of ' + INI.Filename; + Memo_INI.Lines.Clear; + {$WARN UNIT_DEPRECATED OFF} + if LazFileUtils.FileExistsUTF8(INI.Filename) then + begin + Memo_INI.Lines.LoadFromFile(INI.Filename); + sINIFilePath := INI.Filename; + ShowModal; + if bDirty then + begin + s := INI.KeyPhrase; + // Reload (with correct keyphrase) + INI.Free; + {$IFDEF USE_THREADSAFE} + INI := TLockCryptIniFile.Create(IniFilePath); + INI.Lock; + {$ELSE} + INI := TCryptIniFile.Create(IniFilePath); + {$ENDIF} + INI.KeyPhrase := s; + end; + end + else + ShowMessage('No INI file to show!'); + end; +end; + +procedure Tmainform.cmd_ValueExistsClick(Sender: TObject); +begin + if not INI.SectionExists(edt_Section.Text) then + begin + ShowMessage(edt_Section.Text + ' is absent, so nothing to read!'); + Exit; + end; + // Dont read IDENT_SECTION + if edt_Section.Text = IDENT_SECTION then + begin + ShowMessage('Switching Encryption mode off to read ' + IDENT_SECTION + 'section'); + rg_Encryption.ItemIndex := 1; + end; + if (edt_Section.Text <> 'TestSection') then + if MessageDlg('Please confirm', 'Are you sure you want to test values from ' + + edt_Section.Text + '?', mtConfirmation, [mbCancel, mbYes], 0, mbCancel) = + mrCancel then + begin + edt_Section.Text := 'TestSection'; + ShowMessage('OK. Reading default section "TestSection" instead'); + end; + + if INI.ValueExists(edt_Section.Text, edt_Ident.Text) then + ShowMessage('Key "' + edt_Ident.Text + '" exists') + else + ShowMessage('Key "' + edt_Ident.Text + '" is absent'); + if INI.ValueExists(edt_Section.Text, 'Integer') then + ShowMessage('Key "Integer" exists') + else + ShowMessage('Key "Integer" is absent'); +end; + +procedure Tmainform.cmd_VerifyClick(Sender: TObject); +var + TRUEFALSE: boolean; +begin + if not INI.SectionExists(edt_Section.Text) then + begin + ShowMessage(edt_Section.Text + ' is absent, so nothing to verify!'); + Exit; + end; + // Dont verify IDENT_SECTION + if edt_Section.Text = IDENT_SECTION then + begin + cmd_VerifySectionValues.Click; + Exit; + end; + if (edt_Section.Text <> 'TestSection') then + if MessageDlg('Please confirm', 'Are you sure you want to verify test values from ' + + edt_Section.Text + '?', mtConfirmation, [mbCancel, mbYes], 0, mbCancel) = + mrCancel then + begin + edt_Section.Text := 'TestSection'; + ShowMessage('OK. Verifying default section "TestSection" instead'); + end; + if INI.PlainTextMode = False then + begin + TRUEFALSE := True; // Assume success, look for failure + // Test all the value types one-by-one + TRUEFALSE := TRUEFALSE and INI.VerifyBool(edt_Section.Text, 'Boolean', True); + if not INI.VerifyBool(edt_Section.Text, 'Boolean', True) then + ShowMessage('Boolean failed to verify'); + TRUEFALSE := TRUEFALSE and INI.VerifyFloat(edt_Section.Text, 'Float', 3.142); + if not INI.VerifyFloat(edt_Section.Text, 'Float', 3.142) then + ShowMessage('Float failed to verify'); + TRUEFALSE := TRUEFALSE and INI.VerifyDateTime(edt_Section.Text, + 'Date', StrToDate('15/10/2016', 'dd mm yyyy', '/')); + if not INI.VerifyDateTime(edt_Section.Text, 'Date', + StrToDate('15/10/2016', 'dd mm yyyy', '/')) then + ShowMessage('Date failed to verify'); + TRUEFALSE := TRUEFALSE and INI.VerifyInt64(edt_Section.Text, 'Int64', 1000); + if not INI.VerifyInt64(edt_Section.Text, 'Int64', 1000) then + ShowMessage('Int64 failed to verify'); + TRUEFALSE := TRUEFALSE and INI.VerifyString(edt_Section.Text, + edt_Ident.Text, edt_Value.Text); + if not INI.VerifyString(edt_Section.Text, edt_Ident.Text, edt_Value.Text) then + ShowMessage('String failed to verify'); + if TRUEFALSE = True then + ShowMessage('Verify: String,Bool,Float,Date and Int64 types all verified OK') + else + ShowMessage('One or more types failed verification'); + // Test the Read/Write/Verify Integer stuff + if INI.VerifyInteger(edt_Section.Text, 'Integer', StrToInt(edt_Integer.Text)) then + ShowMessage('VerifyInteger: ' + edt_Integer.Text + ' verified OK') + else + ShowMessage('VerifyInteger: ' + edt_Integer.Text + ' failed verification'); + end + else + ShowMessage('Verification of regular values only works when PlainTextMode=FALSE'); + // Use the MD5 value from the INI file + if INI.VerifyIdent('92abf0deecbb25c435bff507a396d92a') then + ShowMessage('Ident ' + IDENT_SECTION + ' verified OK') + else + ShowMessage('Ident ' + IDENT_SECTION + ' failed verification'); +end; + +procedure Tmainform.cmd_VerifySectionValuesClick(Sender: TObject); +var + s: string; +begin + if edt_Section.Text = IDENT_SECTION then + begin + if INI.VerifyIdent('92abf0deecbb25c435bff507a396d92a') then + ShowMessage('Ident ' + IDENT_SECTION + ' verified OK') + else + ShowMessage('Ident ' + IDENT_SECTION + ' failed verification'); + Exit; + end; + if not INI.SectionExists(edt_Section.Text) then + begin + ShowMessage(edt_Section.Text + ' is absent, so nothing to verify!'); + Exit; + end; + + s := InputBox('Verify Section', 'Please enter your 32-character MD5Hash here', + sStoredMD5Hash); + if INI.VerifySectionHash(edt_Section.Text, s) then + begin + ShowMessage('Section is verified'); + sStoredMD5Hash := s; + end + else + ShowMessage('MD5Hash value incorrect. Section failed verification'); +end; + +end. diff --git a/components/cryptini/latest_stable/demo/umemoform.lfm b/components/cryptini/latest_stable/demo/umemoform.lfm new file mode 100644 index 000000000..9917bdc55 --- /dev/null +++ b/components/cryptini/latest_stable/demo/umemoform.lfm @@ -0,0 +1,62 @@ +object ShowINIForm: TShowINIForm + Left = 1253 + Height = 540 + Top = 313 + Width = 768 + BorderStyle = bsToolWindow + Caption = 'INI' + ClientHeight = 540 + ClientWidth = 768 + OnCreate = FormCreate + OnShow = FormShow + Position = poMainFormCenter + LCLVersion = '1.7' + object Memo_INI: TMemo + Left = 0 + Height = 482 + Top = 0 + Width = 768 + Align = alTop + Lines.Strings = ( + 'Memo_INI' + ) + OnChange = Memo_INIChange + ScrollBars = ssAutoBoth + TabOrder = 0 + WordWrap = False + end + object cmd_Close: TBitBtn + Left = 347 + Height = 26 + Top = 500 + Width = 75 + AutoSize = True + Caption = '&Close' + Kind = bkClose + ModalResult = 11 + OnClick = cmd_CloseClick + TabOrder = 1 + end + object cmd_saveChanges: TButton + Left = 600 + Height = 25 + Top = 499 + Width = 154 + AutoSize = True + Caption = 'Save Changes and Close' + Enabled = False + OnClick = cmd_saveChangesClick + TabOrder = 2 + end + object cmd_Abort: TBitBtn + Left = 264 + Height = 26 + Top = 500 + Width = 76 + Caption = '&Revert' + Kind = bkAbort + ModalResult = 3 + TabOrder = 3 + Visible = False + end +end diff --git a/components/cryptini/latest_stable/demo/umemoform.pas b/components/cryptini/latest_stable/demo/umemoform.pas new file mode 100644 index 000000000..4f7a2a5a2 --- /dev/null +++ b/components/cryptini/latest_stable/demo/umemoform.pas @@ -0,0 +1,94 @@ +unit umemoform; + +{$mode objfpc}{$H+} + +interface + +uses + Forms, StdCtrls, SysUtils, + Buttons, Classes, Dialogs,Controls; + +type + + { TShowINIForm } + + TShowINIForm = class(TForm) + cmd_Abort: TBitBtn; + cmd_saveChanges: TButton; + cmd_Close: TBitBtn; + Memo_INI: TMemo; + procedure cmd_CloseClick(Sender: TObject); + procedure cmd_saveChangesClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure Memo_INIChange(Sender: TObject); + private + public + bDirty: boolean; + sINIFilePath: string; + // Help = MakeReadonly, OpenINI = MakeWriteable + procedure MakeReadOnly; + procedure MakeWriteable; + end; + +var + ShowINIForm: TShowINIForm; + +implementation +// Uses umainform; +{$R *.lfm} + +{ TShowINIForm } +procedure TShowINIForm.MakeReadOnly; +begin + Memo_INI.Readonly:=TRUE; +end; + +procedure TShowINIForm.MakeWriteable; +begin + Memo_INI.Readonly:=FALSE; +end; + +procedure TShowINIForm.cmd_saveChangesClick(Sender: TObject); +begin + if bDirty then + try + {$I+} + Memo_INI.Lines.SaveToFile(sINIFilePath); + ShowMessage('Changes saved OK.'); + Close; + except + On E: Exception do + ShowMessageFmt('Oops! Error: %s', [E.Message]); + end; +end; + +procedure TShowINIForm.cmd_CloseClick(Sender: TObject); +begin + if bDirty then + If MessageDlg('Discard changes?',mtConfirmation,[MBYES,MBNO],0,MBNO) = mrNo then + Begin + cmd_saveChanges.Click; + Exit; + end; + Close; +end; + +procedure TShowINIForm.FormCreate(Sender: TObject); +begin + Icon := Application.Icon; +end; + +procedure TShowINIForm.FormShow(Sender: TObject); +begin + bDirty := False; + cmd_saveChanges.Enabled := False; +end; + +procedure TShowINIForm.Memo_INIChange(Sender: TObject); +begin + bDirty := True; + cmd_saveChanges.Enabled := True; +end; + +end. diff --git a/components/cryptini/latest_stable/locale/ucryptini.po b/components/cryptini/latest_stable/locale/ucryptini.po new file mode 100644 index 000000000..e535f25d7 --- /dev/null +++ b/components/cryptini/latest_stable/locale/ucryptini.po @@ -0,0 +1,15 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: ucryptini.rsnothingwasen +msgid "Nothing was Entered!" +msgstr "" + +#: ucryptini.rsnotyetinitia +msgid "Not yet initialised" +msgstr "" + +#: ucryptini.rsunknown +msgid "unknown" +msgstr "" + diff --git a/components/cryptini/latest_stable/ucryptini.pas b/components/cryptini/latest_stable/ucryptini.pas new file mode 100644 index 000000000..d9f35c672 --- /dev/null +++ b/components/cryptini/latest_stable/ucryptini.pas @@ -0,0 +1,1477 @@ +unit ucryptini; +{$mode objfpc}{$H+} +{$DEFINE USE_DCPCRYPT} // Delete this if you don't have the DCrypt library + // and CryptINI will use built-in BASE64 instead + // (but turn all project debugging checks off!) + // DCrypt can be downloaded via OnlinePackageManager + // And is vastly preferable to BASE64 +{$IF FPC_VERSION = 3} // inifiles.pp changed in fpc v3.1.? (17 Jan 2016) + {$IF FPC_RELEASE > 0} + {$IF FPC_PATCH > 0} + {$DEFINE FPC311} + {$ENDIF} + {$ENDIF} +{$ENDIF} + +{ 'Paranoid' version of TIniFile + + Copyright (C) 2016 Gordon Bamber minesadorada@gmail.com + Base 64 code by David Barton + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version with the following modification: + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent modules,and + to copy and distribute the resulting executable under terms of your choice, + provided that you also meet, for each linked independent module, the terms + and conditions of the license of that module. An independent module is a + module which is not derived from or based on this library. If you modify + this library, you may extend this exception to your version of the library, + but you are not obligated to do so. If you do not wish to do so, delete this + exception statement from your version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +PURPOSE +======= +This is a TiniFile implementation that is resistant to tampering. +In normal (PlainTextMode = FALSE) mode, any calls to Write values are +accompanied by an embedded MD5 hash value (and also reversed then Base64/IDEA Encrypted) +This is invisible in normal use (i.e. read methods return normal results) +but there are added methods to internally verify any entries. +It also is able to write a standard ident section containing various +details including authorship and copyright. A single function allows +you to check on app startup whether this section has been altered. +It also includes a useful 'First Run' functionality. +It's intended purpose is to store information that cannot be easily altered +in a text editor (such as HiScores etc) by a weekend scripter. +The WriteInteger method is the most secure as it double-encrypts as well as +embedding an MD5Hash value as a checksum. Very handy to save scores etc. +It is paired with ReadInteger and VerifyInteger + +DISCLAIMER +========== +This unit does not claim to pass any security tests nor be used in +any environment where a moderate-level hacker could circumvent it. + +ENCRYPTION +========== +By Default CryptINI uses the DCPCrypt package for string encryption. +The mode is IDEA cipher with an MD5 hash for the key. The EncryptINI +and DecryptINI methods use DCPCrypt RC4 Cipher (With SHA hash) +There is a $DEFINE USE_DCPCRYPT directive at the top of this file. + +If this DEFINE is commented out, then CryptINI will default +to BASE64 string encryption, which is weaker. Encrypt/DecryptINI methods +will be unavailable. +You can then delete any requirement for dcpcrypt in the project inspector. + +FREEPASCAL VERSIONS +=================== +Starting in FPC V3.1.1 there are additional options in TINIFile which +are implemented in TCryptINI if the FPC Version >= 3.1.1 is detected. + +USE AND EXAMPLE CODE +==================== +** You can hard-code an Ident Section in your INI file +** and check if it has been altered +** Typical Form.Create() +procedure TForm1.FormCreate(Sender: TObject); +const + C_KEYPHRASE = 'I do like to be beside the seaside'; // Move this to the top of the unit +Begin + ...other code + // Initialise the encrypted config file + INI := TCryptIniFile.Create(ChangeFileExt(Application.EXEName, '.cfg')); + + // First ever run. INI is absent + If INI.IsVirgin then INI.WriteIdent('minesadorada','(c)2016','minesadorada@charcodelvalle.com','Creative Commons',TRUE);l + + if NOT INI.VerifyIdent('5b319674f5cb55f3ed1e404e33c25868') then // I got this from the INI file + ShowMessage('This is not a genuine copy of ' + Application.Title + '!') + else INI.Deflower; // If not Deflowered then the default ini is used. + + // After first run, use the encrypted version + If NOT INI.IsVirgin then + begin + INI.DecryptINI(TRUE,C_KEYPHRASE); + // Check the unencrypted version.. + if NOT INI.VerifyIdent('5b319674f5cb55f3ed1e404e33c25868') then // I got this from the INI file + ShowMessage('This is not a genuine copy of ' + Application.Title + '!'); + end; + INI.KeyPhrase:=C_KEYPHRASE; // for subsequent read/writes + ...other code +end; + +procedure Tmainform.FormDestroy(Sender: TObject); +const + C_KEYPHRASE = 'I do like to be beside the seaside'; // Move this to the top of the unit +Begin + ...other code + INI.EncryptINI(TRUE,C_KEYPHRASE); + ...other code +end; + + +** Has the Ident been tampered with? Put this in Form.Create +// Use the MD5 value from the INI file (use your own!) +If INI.VerifyIdent('92abf0deecbb25c435bff507a396d92a') then + ShowMessage('Ident verified OK') // do nothing +else + ShowMessage('Ident failed verification'); // Warning message/exit + +** Test for first run +If INI.IsVirgin then // note that doing the test Deflowers the app by default + ShowMessage('First time run of this app'); + +** Toggle to normal UnEncrypted INI use +(by default it is set to FALSE) +INI.PlainTextMode:=TRUE; +INI.WriteString('MySection', 'String', 'MyString'); // just writes normally + +** When PlainTextMode = FALSE (default),Write<anytype> encrypts the value + and prefixes the encrypted value with an MD5Hash +INI.WriteInteger('MySection', 'Integer',1000); +** Note WriteInteger adds a '+' (INTEGER_MARKER) to the written Key + This is so that CryptINI can deal with Integers specially + Using CryptINI in either mode, this is invisible in use + (i.e. don't add a + to the ident for any methods) + +** When PlainTextMode = FALSE (default), use these convenient methods if you like: +INI.ReadUnencryptedString +INI.WriteUnencryptedString +INI.ReadUnEncryptedInteger +INI.WriteUnencryptedInteger + +** Store 'First Run' status using these methods: +INI.IsVirgin +INI.Deflower +INI.ReFlower (useful for testing) + +** You can encrypt and decrypt the entire INI file usine EncryptINI and DecryptINI + This uses a different cipher and hash method, so is extra-secure + cryptINI methods and properties an only work with an unencrypted INI file + So; Decrypt on startup, and Encrypt before exit. + By default the routines use the KeyPhrase property, but you can override this + in the method call along with whether to delete the "old" file and what + file extension to use for the encrypted file. + +** Original IniFiles methods and properties + Just use them as normal. Note: you can mix-and-match Plaintext and Encrypted + in the same INI file. Just toggle the property PlainTextMode before Writing/Reading +} + +interface + +uses + Forms, SysUtils, LazUTF8, LazFileUtils,StrUtils, INIFiles, md5, LCLVersion, + Classes,fileinfo,SyncObjs + // DEBUGGING for ShowMessage:,Dialogs + // ,Dialogs + {$IFDEF USE_DCPCRYPT},DCPidea, DCPmd5,DCPrc4, DCPsha1{$ENDIF} + ; + + +const + // Fixed Ident section values for Read/Write/Verify Ident methods + // Change the values here if you like. + IDENT_SECTION = 'ProgramInfo'; + IDENT_APPNAME = 'App name'; + IDENT_APPVERSION = 'App version'; + IDENT_EXE = 'App Path'; + IDENT_AUTHOR = 'Author'; + IDENT_COPYRIGHT = 'Copyright'; + IDENT_LICENSE = 'License'; + IDENT_CONTACT = 'Contact'; + IDENT_LCLVERSION = 'LCL Version'; + IDENT_FPCVERSION = 'FPC Version'; + IDENT_TARGET = 'Target System'; + IDENT_LASTCOMPILED = 'Last Compiled'; + IDENT_FIRSTRUN = 'FirstRun'; + IDENT_MD5HASH = 'MD5Hash'; + + // You can change these Consts here if you like + INTEGER_MARKER = '+'; // Appended to Crypted Integer Idents + // so that ReadSectionValues,ValueExists and DeleteKey methods will work + DEFAULT_KEYPHRASE = 'Choose a better keyphrase than this!'; // If none specified + {$IFDEF WINDOWS} + DEFAULT_EXT = '.enc'; + {$ELSE} + DEFAULT_EXT = 'enc'; + {$ENDIF} + + {$IFNDEF USE_DCPCRYPT} + // Base64 array of bytes. CHANGE AT YOUR PERIL! + B64: array[0..63] of byte = (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, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 43, 47); + {$ENDIF} + +C_VERSION = '0.1.2'; +{ + VERSION HISTORY + =============== + V 0.0.1: Initial alpha release by (c)2016 minesadorada@charcodelvalle.com (GB) + V 0.0.2: Improved Read/Write/Verify integer values (GB) + V 0.0.3: Section functions added. Integer marker added. (GB) + V 0.0.4: Compatibility test for fpc 3 additions to TIniFiles (GB) + V 0.0.5: Added DCPCrypt units and conditional DEFINES. Added Encrypt/Decrypt INI (GB) + V 0.0.6: ReadBinaryStream and WriteBinaryStream added (GB) + V 0.0.7: ReadSection debugged (GB) + V 0.0.8: Bugfix: FPC Version {DEFINE FPC3} corrected (GB) + V 0.0.9: Added SplitKeyValue procedure. Other fixes and improvements (GB) + V 0.1.0: Added Program Version info to Ident section + V 0.1.2: Added thread-safe TLockCryptINIFile class + for thread-safe operation (GB) + Credit: "Fungus" at http://forum.lazarus.freepascal.org/ + V 0.1.3: ?? +} +type + TCryptIniFile = class(TIniFile) + private + // Md5 Stuff + fMyDigest: TMDDigest; // defined in md5 unit + fMD5String: string; + // For Read/write Integers + fKey: longint; + fKeyPhrase: string; + // Encryption on/off + fPlainText: boolean; + fSectionHashing: boolean; + fVersion: string; + {$IFDEF USE_DCPCRYPT} + DCP_idea1: TDCP_idea; + DCP_md5_1: TDCP_md5; + {$ENDIF} + fHashType:String; + fCipherType:String; + // Functions to convert values + function EncodeString(const sValue: string): string; + function DecodeString(const sValue: string): string; + // Functions to convert Integers only + function EncodeInteger(const iValue: longint): longint; + function DecodeInteger(const iValue: longint): longint; + // Either.. + procedure SetKeyPhrase(AValue: string); // Sets fKey from a string (Preferrred method) + Procedure SetKey(aValue:Integer); // Also sets Keyphrase (weaker) + public + {$IFDEF FPC311} + constructor Create(const AFileName: string; AOptions: TIniFileOptions = []); + override; + {$ELSE} + constructor Create(const AFileName: string; AEscapeLineFeeds : Boolean = False);override; + {$ENDIF} + destructor Destroy; override; + // Overridden TINIFile methods + function ReadInteger(const Section, Ident: string; Default: longint): longint; + override; + procedure WriteInteger(const Section, Ident: string; Value: longint); override; + function ReadString(const Section, Ident, Default: string): string; override; + procedure WriteString(const Section, Ident, Value: string); override; + procedure ReadSection(const Section: string; Strings: TStrings); override; + function ValueExists(const Section, Ident: string): Boolean; override; + procedure DeleteKey(const Section, Ident: String); override; +{$IFDEF FPC311} + procedure ReadSectionValues(const Section: string; Strings: TStrings; + AOptions: TSectionValuesOptions = []); override; +{$ELSE} + procedure ReadSectionValues(const Section: string; Strings: TStrings); override; +{$ENDIF} + function ReadBinaryStream(const Section, Name: string; Value: TStream): Integer; override; + procedure WriteBinaryStream(const Section, Name: string; Value: TStream); override; + + // Added functions + // Compares TestValue's value and MD5Hash with the INI file's version + function VerifyString(const Section, Ident, TestValue: string): boolean; + function VerifyBool(const Section, Ident: string; TestValue: boolean): boolean; + function VerifyInt64(const Section, Ident: string; TestValue: int64): boolean; + function VerifyFloat(const Section, Ident: string; TestValue: double): boolean; + function VerifyDate(const Section, Ident: string; TestValue: TDateTime): boolean; + function VerifyTime(const Section, Ident: string; TestValue: TDateTime): boolean; + function VerifyDateTime(const Section, Ident: string; TestValue: TDateTime): boolean; + // VerifyInteger is more strict + function VerifyInteger(const Section, Ident: string; TestValue: longint): boolean; + + // New functionality. Write a whole section in one go. + procedure WriteSectionValues(const Section: string; Strings: TStrings); + // If SectionHashing = TRUE then MakeSectionHash is called for every write + // Best practioe is to do it only after a bunch of writes + procedure MakeSectionHash(const Section: string; WriteToINI: boolean = True); + function VerifySectionHash(const Section, TestMD5Hash: string): boolean; + // Separates key=value into Skey and sValue + function SplitKeyValue(Const sValueEntry:String;var sKey,sValue:String):Boolean; + // Sets property PlainTextMode to FALSE temporarily to Read/Write normally + // I included these functions for simplicity. They work when PlainTextMode=TRUE or FALSE + function ReadUnencryptedString(const Section, Ident, Default: string): string; + procedure WriteUnencryptedString(const Section, Ident, Value: string); + function ReadUnEncryptedInteger(const Section, Ident: string; + Default: longint): longint; + procedure WriteUnencryptedInteger(const Section, Ident: string; Value: longint); + + // Writes a standard Ident section with MD5 Hash + // This can be done in Form.Create() on program first run + // Or can be done during development, then distribute the prewritten INI file with the exe + procedure WriteIdent(const sAuthor, sCopyright, sLicense, sContact: string; Force: boolean=False); + // Read the MD5Hash from the INI file and pass it as a parameter + // ANY tampering with the [ProgramInfo] ident section info returns a FALSE + // Note not all Key/Values are verified (i.e. Appname etc.) + function VerifyIdent(const sMD5Hash: string): boolean; + + {$IFDEF USE_DCPCRYPT} + // Encrypt and Decrypt the whole file in one go. Very secure via RC4 cipher. + // You can call: + // EncryptINI; (use DEFAULT_KEYPHRASE as the passkey, and delete the old file) + // EncryptINI(FALSE); (don't delete old ini file) + // EncryptINI(TRUE,'bananas'); (delete old file; use "bananas" as the passkey) + // EncryptINI(TRUE,'bananas','.xxx'); (delete old file; use bananas as the passkey, and save as an .xxx file) + // bSuccess:=EncryptINI(optional parameters); (returns FALSE if anything goes wrong) + function EncryptINI(DeleteOld:Boolean = TRUE;sPassword: string = DEFAULT_KEYPHRASE;NewExt:String = DEFAULT_EXT):Boolean; + function DecryptINI(DeleteOld:Boolean = TRUE;sPassword: string = DEFAULT_KEYPHRASE;NewExt:String = DEFAULT_EXT):Boolean; + {$ENDIF} + + // Use to detect or set 'First Run' status + function IsVirgin: boolean; + procedure Deflower; + procedure Reflower; + + // By Default, PlainTextMode = FALSE (Encrypted mode) + property PlainTextMode: boolean read fPlainText write fPlainText; + property MD5Hash: string read fMD5String write fMD5String; + + // Either.. + property KeyPhrase: string read fKeyPhrase write SetKeyPhrase; // also sets Key (preferred property) + // or.. + property Key: longint read fKey write SetKey; // Also sets KeyPhrase (weaker) + + // If SectionHashing=TRUE then a Section hash is written each time any value + // is written. This enables VerifySection. + property SectionHashing: boolean read fSectionHashing write fSectionHashing; + + property HashType:String read fHashType; // Info + property CipherType:String read fCipherType; // Info + property CryptINIVersion: string read fVersion; // Info + property FileName; //inherited +{$IFNDEF FPC311} + // Reflect changes in fpc 3x + property EscapeLineFeeds; + Property CaseSensitive; + Property StripQuotes; +{$ENDIF} +end; + +Type + TLockCryptINIFile = class(TCryptIniFile) + private + FLock: TCriticalSection; + public + destructor Destroy; override; + // Call Lock after creation + procedure Lock; + // Call Unlock before destruction + procedure Unlock; + end; + +resourcestring + rsNotYetInitia = 'Not yet initialised'; + rsNothingWasEn = 'Nothing was Entered!'; + rsUnknown = 'unknown'; + +implementation + +{TLockCryptINIFile} +destructor TLockCryptINIFile.Destroy; +begin + FreeAndNil(FLock); + inherited; +end; + +procedure TLockCryptINIFile.Lock; +begin + if FLock = nil then FLock:= TCriticalSection.Create; + FLock.Acquire; +end; + +procedure TLockCryptINIFile.Unlock; +begin + if FLock <> nil then FLock.Release; +end; + +{TCryptINIFile} +{$IFDEF FPC311} + constructor TCryptIniFile.Create(const AFileName: string; + AOptions: TIniFileOptions = []); + { + TIniFileOption = (ifoStripComments, // Strip comments when reading file + ifoStripInvalid, // Strip invalid lines when reading file. + ifoEscapeLineFeeds, // Escape linefeeds when reading file. + ifoCaseSensitive, // Use Case sensitive section/key names + ifoStripQuotes, // Strip quotes when reading string values. + ifoFormatSettingsActive, // Use format settings when writing date/float etc. + ifoWriteStringBoolean // Write booleans as string + ); + } +begin + // AOptions := AOptions And NOT [ifoWriteStringBoolean]; + inherited Create(AFileName, AOptions); +{$ELSE} +constructor TCryptIniFile.Create(const AFileName: string; AEscapeLineFeeds : Boolean = False); +begin + inherited Create(AFileName,AEscapeLineFeeds); +{$ENDIF} + CacheUpdates := False; + fPlainText := False; + fSectionHashing := True; + fVersion := C_VERSION; + fMD5String := rsNotYetInitia; + fKey := 300554; // Random default key in case user doesn't set one + fKeyPhrase := DEFAULT_KEYPHRASE; +{$IFDEF USE_DCPCRYPT} + DCP_idea1:=TDCP_idea.Create(Nil); + DCP_md5_1:=TDCP_md5.Create(Nil); + If DCP_idea1.SelfTest then + DCP_Idea1.Burn; { Clear all information } + DCP_Idea1.InitStr(fKeyPhrase,TDCP_md5); + fCipherType:=DCP_Idea1.GetAlgorithm; + fHashType:=DCP_md5_1.GetAlgorithm; +{$ELSE} + fHashType:='MD5'; + fCiperType:='BASE64'; +{$ENDIF} +end; + +// ***************************************************************************// + +destructor TCryptIniFile.Destroy; +begin + // Anything to free here? + {$IFDEF USE_DCPCRYPT} + DCP_idea1.Burn; // Clear key info from memory + DCP_idea1.Free; + DCP_md5_1.Burn; // Clear key info from memory + DCP_md5_1.Free; + {$ENDIF} + inherited Destroy; +end; + +// ***************************************************************************// +// Start of internal routines +// ***************************************************************************// +{$IFNDEF USE_DCPCRYPT} // Fallback routines +function B64Encode(pInput: pointer; pOutput: pointer; Size: longint): longint; +var + i, iptr, optr: longint; + Input, Output: PByteArray; +begin + Input := PByteArray(pInput); + Output := PByteArray(pOutput); + iptr := 0; + optr := 0; + for i := 1 to (Size div 3) do + begin + Output^[optr + 0] := B64[Input^[iptr] shr 2]; + Output^[optr + 1] := B64[((Input^[iptr] and 3) shl 4) + (Input^[iptr + 1] shr 4)]; + Output^[optr + 2] := B64[((Input^[iptr + 1] and 15) shl 2) + (Input^[iptr + 2] shr 6)]; + Output^[optr + 3] := B64[Input^[iptr + 2] and 63]; + Inc(optr, 4); + Inc(iptr, 3); + end; + case (Size mod 3) of + 1: + begin + Output^[optr + 0] := B64[Input^[iptr] shr 2]; + Output^[optr + 1] := B64[(Input^[iptr] and 3) shl 4]; + Output^[optr + 2] := byte('='); + Output^[optr + 3] := byte('='); + end; + 2: + begin + Output^[optr + 0] := B64[Input^[iptr] shr 2]; + Output^[optr + 1] := B64[((Input^[iptr] and 3) shl 4) + (Input^[iptr + 1] shr 4)]; + Output^[optr + 2] := B64[(Input^[iptr + 1] and 15) shl 2]; + Output^[optr + 3] := byte('='); + end; + end; + Result := ((Size + 2) div 3) * 4; +end; + +// ***************************************************************************// + +function Base64Encode(const Value: ansistring): ansistring; +begin + SetLength(Result, ((Length(Value) + 2) div 3) * 4); + B64Encode(@Value[1], @Result[1], Length(Value)); +end; + +// ***************************************************************************// + +function B64Decode(pInput: pointer; pOutput: pointer; Size: longint): longint; +var + i, j, iptr, optr: longint; + Temp: array[0..3] of byte; + Input, Output: PByteArray; +begin + Input := PByteArray(pInput); + Output := PByteArray(pOutput); + iptr := 0; + optr := 0; + Result := 0; + for i := 1 to (Size div 4) do + begin + for j := 0 to 3 do + begin + case Input^[iptr] of + 65..90: Temp[j] := Input^[iptr] - Ord('A'); + 97..122: Temp[j] := Input^[iptr] - Ord('a') + 26; + 48..57: Temp[j] := Input^[iptr] - Ord('0') + 52; + 43: Temp[j] := 62; + 47: Temp[j] := 63; + 61: Temp[j] := $FF; + end; + Inc(iptr); + end; + Output^[optr] := (Temp[0] shl 2) or (Temp[1] shr 4); + Result := optr + 1; + if (Temp[2] <> $FF) and (Temp[3] = $FF) then + begin + Output^[optr + 1] := (Temp[1] shl 4) or (Temp[2] shr 2); + Result := optr + 2; + Inc(optr); + end + else if (Temp[2] <> $FF) then + begin + try + Output^[optr + 1] := (Temp[1] shl 4) or (Temp[2] shr 2); + Output^[optr + 2] := (Temp[2] shl 6) or Temp[3]; // Throws error + Result := optr + 3; + Inc(optr, 2); + except + On E: Exception do + Continue; + end; + end; + Inc(optr); + end; +end; + +// ***************************************************************************// + +function Base64Decode(const Value: ansistring): string; +begin + SetLength(Result, (Length(Value) div 4) * 3); + SetLength(Result, B64Decode(@Value[1], @Result[1], Length(Value))); +end; +{$ENDIF} +// ***************************************************************************// + +function CharToBool(AChar: char): boolean; +begin + Result := (Achar = '1'); +end; + +// ***************************************************************************// + +function BoolToChar(ABool: boolean): char; +begin + if ABool then + Result := '1' + else + Result := '0'; +end; + +// ***************************************************************************// +// End of internal routines +// ***************************************************************************// + +Procedure TCryptIniFile.SetKey(aValue:Integer); // Also sets KeyPhrase +begin + fKey:=AValue; + {$IFNDEF USE_DCPCRYPT} + SetKeyPhrase(fKey); // VERY WEAK! + {$ENDIF} +end; + +// ***************************************************************************// + +procedure TCryptIniFile.SetKeyPhrase(AValue: string); +// Hash the phrase to a standard 32 chars +// Then sum the ASCII values to seed the fKey (it never exceeds LongInt) +// Difficult to reverse-engineer even if you have the KeyPhrase +var + aDigest: TMDDigest; // defined in md5 unit + iCount: integer; + lTry: longint; +begin + {$IFDEF USE_DCPCRYPT} + // Use the string directly + fKeyPhrase:=AValue; + if fKeyPhrase = '' then + fKeyPhrase := DEFAULT_KEYPHRASE; // don't allow empty string + DCP_Idea1.Burn; { Clear all stored key information } + DCP_Idea1.InitStr(fKeyPhrase,TDCP_md5); + Exit; // bail out + {$ENDIF} + lTry := 0; + // If it's already a number, just use it. (unless it's zero!) + if ((TryStrToInt(AValue, lTry)) and (lTry <> 0)) then + fKey := lTry + else // It's a string + begin + if AValue = '' then + AValue := rsNothingWasEn; // don't allow empty string + aDigest := MDString(AValue, MD_VERSION_5); + fKeyPhrase := MDPrint(aDigest); // 32 chars + // Mess it up to make a big enough number (96 chars) + fKeyPhrase := fKeyPhrase + ReverseString(fKeyPhrase) + fKeyPhrase; + fKey := 0; + for iCount := 1 to (Length(fKeyPhrase)) do + begin + fKey := fKey + Ord(fKeyPhrase[iCount]); + end; + // Make the number bigger + fKey := fKey * 7; + end; +end; + + +// ***************************************************************************// + +function TCryptIniFile.EncodeString(const sValue: string): string; + // Muddle the String up and encode it in IDEA or Base64 +var + s: string; +begin + s := ReverseString(sValue); + {$IFDEF USE_DCPCRYPT} + DCP_Idea1.Reset;{ Reset any stored chaining information } + Result:=DCP_Idea1.EncryptString(s); + {$ELSE} + Result := Base64Encode(s); + {$ENDIF} +end; + +// ***************************************************************************// + +function TCryptIniFile.DecodeString(const sValue: string): string; + // Decode the IDEA or Base64 then Unmuddle +var + s: string; +begin + {$IFDEF USE_DCPCRYPT} + DCP_Idea1.Reset;{ Reset any stored chaining information } + s:=DCP_Idea1.DecryptString(sValue); + {$ELSE} + s := Base64Decode(sValue); + {$ENDIF} + Result := ReverseString(s); +end; + +// ***************************************************************************// + +function TCryptIniFile.EncodeInteger(const iValue: longint): longint; +begin + //DEBUG: ShowMessageFmt('EncodeInteger value = %d',[iValue]); + // B64Encode(@iValue,@Result,SizeOf(iValue)); deprecated + Result := iValue xor fKey; + // Already IDEA or BASE64 encoded after writing + //DEBUG: ShowMessageFmt('EncodeInteger Result = %d',[Result]); +end; + +// ***************************************************************************// + +function TCryptIniFile.DecodeInteger(const iValue: longint): longint; +begin + // B64Decode(@iValue,@Result,SizeOf(iValue)); deprecated + // Already IDEA or BASE64 decoded before reading + Result := iValue xor fKey; +end; + +// ***************************************************************************// + +procedure TCryptIniFile.Deflower; +// Called by IsVirgin to set FirstRun status to FALSE +var + tempPlainText: boolean; +begin + tempPlainText := fPlainText; + fPlainText := True; + WriteBool(IDENT_SECTION, IDENT_FIRSTRUN, False); + fPlainText := tempPlainText; +end; + +// ***************************************************************************// + +procedure TCryptIniFile.Reflower; +// Set FirstRun status to TRUE +var + tempPlainText: boolean; +begin + tempPlainText := fPlainText; + fPlainText := True; + WriteBool(IDENT_SECTION, IDENT_FIRSTRUN, True); + fPlainText := tempPlainText; +end; + +// ***************************************************************************// + +function TCryptIniFile.IsVirgin: boolean; + // On FirstRun returns TRUE + // Then calls Deflower so subsequent runs will return FALSE +var + tempPlainText: boolean; +begin + tempPlainText := fPlainText; + fPlainText := True; + Result := ReadBool(IDENT_SECTION, IDENT_FIRSTRUN, True); + if Result = True then + Deflower; + fPlainText := tempPlainText; +end; + +// ***************************************************************************// + +function TCryptIniFile.VerifyIdent(const sMD5Hash: string): boolean; + // The sMD5Hash has been previously generated by WriteIdent + // and stored in INI file. Get it from there. +var + s: string; + tempPlainText: boolean; +begin + Result := False; + tempPlainText := fPlainText; // Store old value + fPlainText := True; // Set PlainTextMode ON + // Make a string of all the authorship entries + s := ReadString(IDENT_SECTION, IDENT_AUTHOR, rsUnknown); + s := s + ReadString(IDENT_SECTION, IDENT_COPYRIGHT, rsUnknown); + s := s + ReadString(IDENT_SECTION, IDENT_LICENSE, rsUnknown); + s := s + ReadString(IDENT_SECTION, IDENT_CONTACT, rsUnknown); + // Make up an MD5 hash from the INI values read + fMyDigest := MDString(s, MD_VERSION_5); + fMD5String := MDPrint(fMyDigest); + // Compare it with the value passed in the parameter + if fMD5String = sMD5Hash then + Result := True; + fPlainText := tempPlainText; // Restore old value +end; + +// ***************************************************************************// + +procedure TCryptIniFile.WriteIdent(const sAuthor, sCopyright, sLicense, sContact: string; Force: boolean=False); +// This proc will only write anything if IsVirgin (First Run status) is TRUE +// Or the INI file is empty or altered +var + s: string; + tempPlainText: boolean; + VInfo:TFileVersionInfo; + Version:TProgramVersion; +begin + tempPlainText := fPlainText; // Store old value + fPlainText := True; // Set PlainTextMode ON + if ((ReadBool(IDENT_SECTION, IDENT_FIRSTRUN, True) = True) OR (Force = True)) then + begin // IsVirgin=TRUE so write the section in plaintext + WriteString(IDENT_SECTION, IDENT_AUTHOR, sAuthor); + WriteString(IDENT_SECTION, IDENT_COPYRIGHT, sCopyright); + WriteString(IDENT_SECTION, IDENT_LICENSE, sLicense); + WriteString(IDENT_SECTION, IDENT_CONTACT, sContact); + WriteString(IDENT_SECTION, IDENT_LCLVERSION, lcl_version); + WriteString(IDENT_SECTION, IDENT_FPCVERSION, {$I %FPCVERSION%}); + s:={$I %FPCTARGETCPU%}+' - '+{$I %FPCTARGETOS%}; + WriteString(IDENT_SECTION, IDENT_TARGET, s); + // If you don't need this you can delete 'Forms' from the Uses clause + WriteString(IDENT_SECTION, IDENT_APPNAME,Application.Title); + s:='0.0.0.0'; // Default + VInfo:=TFileVersionInfo.Create(Application); + TRY + VInfo.ReadFileInfo; + If fileinfo.GetProgramVersion(Version) then + s:=ProgramversionToStr(Version); + finally + VInfo.free; + end; + WriteString(IDENT_SECTION,IDENT_APPVERSION,s); + WriteString(IDENT_SECTION, IDENT_EXE, ParamStrUTF8(0)); + WriteBool(IDENT_SECTION,IDENT_FIRSTRUN,TRUE); + s:={$I %DATE%} + ' at ' + {$I %TIME%}; + WriteString(IDENT_SECTION, IDENT_LASTCOMPILED, s); + // Make up the MD5Hash of all the authorship entries + s := sAuthor + sCopyright + sLicense + sContact; + fMyDigest := MDString(s, MD_VERSION_5); + fMD5String := MDPrint(fMyDigest); + WriteString(IDENT_SECTION, IDENT_MD5HASH, fMD5String); + UpdateFile; + end; + fPlainText := tempPlainText; // Restore old value +end; + +// ***************************************************************************// + +procedure TCryptIniFile.WriteUnencryptedString(const Section, Ident, Value: string); +var + tempPlainText: boolean; + // Temporarily sets PlainTextMode = TRUE then restores previous status +begin + tempPlainText := fPlainText; // Store old value + fPlainText := True; // Set PlainTextMode ON + WriteString(Section, Ident, Value); + fPlainText := tempPlainText; // Restore old value +end; + +// ***************************************************************************// + +function TCryptIniFile.ReadUnencryptedString( + const Section, Ident, Default: string): string; + // Temporarily sets PlainTextMode = TRUE then restores previous status +var + tempPlainText: boolean; +begin + tempPlainText := fPlainText; // Store old value + fPlainText := True; // Set PlainTextMode ON + Result := ReadString(Section, Ident, Default); + fPlainText := tempPlainText; // Restore old value +end; + +// ***************************************************************************// + +function TCryptIniFile.ReadUnEncryptedInteger(const Section, Ident: string; + Default: longint): longint; + // Temporarily sets PlainTextMode = TRUE then restores previous status +var + tempPlainText: boolean; +begin + tempPlainText := fPlainText; // Store old value + fPlainText := True; // Set PlainTextMode ON + Result := ReadInteger(Section, Ident, Default); + fPlainText := tempPlainText; // Restore old value +end; + +// ***************************************************************************// + +procedure TCryptIniFile.WriteUnencryptedInteger(const Section, Ident: string; + Value: longint); +// Temporarily sets PlainTextMode = TRUE then restores previous status +var + tempPlainText: boolean; +begin + tempPlainText := fPlainText; // Store old value + fPlainText := True; // Set PlainTextMode ON + WriteInteger(Section, Ident, Value); + fPlainText := tempPlainText; // Restore old value +end; + +(******************************************************************************) +// Subclass of TIniFiles to enable obfuscation of entries +(******************************************************************************) +function TCryptIniFile.ReadInteger(const Section, Ident: string; + Default: longint): longint; + // Unobfuscates the number if PlainTextMode=FALSE +var + s: string; + iTemp: longint; +begin + if fPlainText = True then + begin + // Read result using TiniFile + Result := inherited ReadInteger(Section, Ident, Default); + Exit; + end; + Result := Default; // If all else fails.. + s := ReadString(Section, Ident + INTEGER_MARKER, IntToStr(Default)); + //DEBUG: ShowMessage(s); + if s = IntToStr(Default) then + Exit // nothing there - return Default value + else + begin + if not TryStrToInt(s, iTemp) then + Exit; // Error - return Default value + Result := DecodeInteger(iTemp); // Un-Scramble it + end; +end; + +(******************************************************************************) + +procedure TCryptIniFile.WriteInteger(const Section, Ident: string; Value: longint); +// Obfuscates the number if PlainTextMode=FALSE +begin + if fPlainText = False then + begin + Value := EncodeInteger(Value); // Scramble it + inherited WriteInteger(Section, Ident + INTEGER_MARKER, Value); // Write+ using TiniFile + end + else inherited WriteInteger(Section, Ident, Value); // Write using TiniFile + if SectionHashing = True then + MakeSectionHash(Section, True); + UpdateFile; +end; + +(******************************************************************************) + +function TCryptIniFile.ReadString(const Section, Ident, Default: string): string; + // Behaviour depends on PlainTextMode = FALSE/TRUE +var + s: string; +begin + fMD5String:=''; + // Read value via TIniFile + s := inherited ReadString(Section, Ident, Default); + Result := s; + if fPlainText = True then // Use unencrypted version + Exit; + If (Length(s) < 32) then Exit; + + fMD5String := LeftStr(s, 32); // Grab the MD5 string and store (unencoded) + Result := RightStr(s, Length(s) - 32); // Use the rest + if Result <> EncodeString(Default) then + begin + Result := DecodeString(Result); // Un-Encrypt it + end; +end; + +(******************************************************************************) + +function TCryptIniFile.ValueExists(const Section, Ident: string): Boolean; +// In Encrypted mode Integers have a special marker +Var s:String; +begin + Result:= inherited ValueExists(Section,Ident); //Normal result + if fPlainText = False then + begin + If Ident = '' then // bail out + begin + Result:=FALSE; + exit; + end; + // Test against both Ident and (Ident + INTEGER_MARKER) + s:=Ident; + s := s + INTEGER_MARKER; // Add INTEGER_MARKER + Result:=Result OR inherited ValueExists(Section,s); + end; +end; + +(******************************************************************************) + +procedure TCryptIniFile.DeleteKey(const Section, Ident: String); +// In Encrypted mode Integers have a special marker +Var s:String; +begin + If Ident = '' then exit; // Bail out + inherited DeleteKey(Section,Ident); //Normal behaviour + // Ident might have an INTEGER_MARKER so preceding code didn't delete it + // So delete (Ident + INTEGER_MARKER) if its there + s:=Ident; // Make a copy + // DEBUG: ShowMessage(s); + s := s + INTEGER_MARKER; // Add INTEGER_MARKER + inherited DeleteKey(Section,s); + If SectionHashing then MakeSectionHash(Section,TRUE); + UpdateFile; +end; + +(******************************************************************************) + + procedure TCryptIniFile.WriteString(const Section, Ident, Value: string); +// Writes MD5Digest string + BASE64 or IDEA string +// Behaviour depends on PlainTextMode = FALSE/TRUE +var + s: string; +begin + if fPlainText = True then // Write regular string + begin + // Use regular TiniFile + inherited WriteString(Section, Ident, Value); + UpdateFile; + Exit; + end; + s := EncodeString(Value); // Encode the string (IDEA/BASE64) + fMyDigest := MDString(s, MD_VERSION_5); + fMD5String := MDPrint(fMyDigest); // Get the MD5Hash of the encoded string + s := fMD5String + s; // Prefix it to the encoded string + inherited WriteString(Section, Ident, s); // Write the result using TiniFile + if SectionHashing = True then + MakeSectionHash(Section, True); + UpdateFile; +end; + +(******************************************************************************) + +Function TCryptIniFile.SplitKeyValue(Const sValueEntry:String;var sKey,sValue:String):Boolean; +Var iEqualsPos:Integer; +begin + Result:=FALSE; + If Length(sValueEntry) < 4 then exit; + iEqualsPos := Pos('=', sValueEntry); + if (iEqualsPos >= 2) then + begin + sKey := LeftStr(sValueEntry, iEqualsPos - 1); + sValue := RightStr(sValueEntry, Length(sValueEntry) - iEqualsPos); + Result:=TRUE; + end; +end; + +(******************************************************************************) + +procedure TCryptIniFile.ReadSection(const Section: string; Strings: TStrings); +// If PlainText = FALSE then +// 1. Remove any INTEGER_MARKER +// 2. Remove MD5Hash entry +Var + TempStrings:TStrings; + iCount,iMD5HashEntry: integer; + s: string; +begin + inherited ReadSection(Section, Strings); // Use regular TiniFile + if fPlainText = True then exit;// Return faithful copy + + // Deal with PlainText = FALSE + iMD5HashEntry := -1; // dummy value + TempStrings := TStringList.Create; // Use a copy + TempStrings.BeginUpdate; + try + // Make a Copy + TempStrings.Clear; + TempStrings.AddStrings(Strings); // contains encrypted versions + for iCount := 0 to Pred(TempStrings.Count) do + begin + // Do not retrieve MD5Hash entry + if (Pos(IDENT_MD5HASH, TempStrings[iCount]) = 0) then + begin + s := TempStrings[iCount]; + If RightStr(s,1) = INTEGER_MARKER then + TempStrings[iCount]:=LeftStr(s,Length(s)-1); + end + else + iMD5HashEntry := iCount; + end; + finally + TempStrings.EndUpdate; + // Copy decoded versions back into the calling StringList + if (iMD5HashEntry >= 0) then + TempStrings.Delete(iMD5HashEntry); // Dont return the MD5Hash entry + Strings.Clear; + Strings.AddStrings(TempStrings); + TempStrings.Free; + end; +end; + +procedure TCryptIniFile.WriteSectionValues(const Section: string; Strings: TStrings); +// Writes either normal or Encrypted values depending on property PlainTextMode +// If SectionHashing = TRUE, also writes the MD5Hash entry at the end (for VerifySection method) +var + iCount, iTemp: integer; + s, sKey, sValue: string; + f: double; + TempSectionHashing: boolean; +begin + TempSectionHashing := fSectionHashing; // Preserve property + fSectionHashing := False; // Write section without on-the-fly hashing + for iCount := 0 to Strings.Count - 1 do + begin + s := Strings[iCount]; + // Split key and value + If NOT SplitKeyValue(s,sKey,sValue) then continue; + if TryStrToInt(sValue, iTemp) = True then + begin + WriteInteger(Section, sKey, iTemp); + Continue; + end; + if ((LowerCase(sValue) = 'true') or (LowerCase(sValue) = 'false')) then + begin + if (LowerCase(sValue) = 'true') then + WriteBool(Section, sKey, True) + else + WriteBool(Section, sKey, False); + Continue; + end; + if TryStrToFloat(sValue, f) = True then + begin + WriteFloat(Section, sKey, f); + Continue; + end; + // All other values + WriteString(Section, sKey, sValue); + end; + // Now is the time to write the MD5Hash entry + if TempSectionHashing = True then + begin + fSectionHashing := True; + MakeSectionHash(Section, True); + end; + UpdateFile; + fSectionHashing := TempSectionHashing; // Restore property +end; + +// ***************************************************************************// +{$IFDEF FPC311} + // TSectionValuesOption = (svoIncludeComments,svoIncludeInvalid, svoIncludeQuotes); + procedure TCryptIniFile.ReadSectionValues(const Section: string; + Strings: TStrings; AOptions: TSectionValuesOptions = []); +{$ELSE} + procedure TCryptIniFile.ReadSectionValues(const Section: string; Strings: TStrings); +{$ENDIF} +var + TempStrings: TStrings; + iCount, iMD5HashEntry: integer; + s, sKey, sValue: string; + iTemp: longint; +begin +{$IFDEF FPC311} + inherited ReadSectionValues(Section, Strings, AOptions); +{$ELSE} + inherited ReadSectionValues(Section, Strings); +{$ENDIF} + if fPlainText = True then // Use regular method + begin + // Use regular TiniFile + UpdateFile; + Exit; + end; + iMD5HashEntry := -1; // dummy value + TempStrings := TStringList.Create; // Use a copy + TempStrings.BeginUpdate; + try + // Make a Copy + TempStrings.Clear; + TempStrings.AddStrings(Strings); // contains encrypted versions + // Iterate through the list + for iCount := 0 to Pred(TempStrings.Count) do + begin + // Do not retrieve MD5Hash entry + if (Pos(IDENT_MD5HASH, TempStrings[iCount]) = 0) then + begin + s := TempStrings[iCount]; + // Split key and value + If NOT SplitKeyValue(s,sKey,sValue) then Exit; + // Deal with Integers, which are IDEA or BASE64 encoded then Encrypted + if RightStr(sKey, 1) = INTEGER_MARKER then // It's an Integer value + begin + s := DecodeString(RightStr(sValue, Length(sValue) - 32)); + // Decode (IDEA/BASE64) to a string + if TryStrToInt(s, iTemp) then + begin + iTemp := DecodeInteger(iTemp); // Decrypt the integer + s := IntToStr(iTemp); // String value of decoded integer + end; + sKey := LeftStr(sKey, Length(sKey) - 1); // Trim off the INTEGER_MARKER + end + else + begin + // All but Integers are simply IDEA or BASE64 encoded + s := DecodeString(RightStr(sValue, Length(sValue) - 32)); + end; + // Replace encoded version with decoded version + TempStrings[iCount] := sKey + '=' + s; + end + else + iMD5HashEntry := iCount; + // Grab the sKey and sValue (we only want to decrypt the Value) + end; + finally + TempStrings.EndUpdate; + // Copy decoded versions back into the calling StringList + if (iMD5HashEntry >= 0) then + TempStrings.Delete(iMD5HashEntry); // Dont return the MD5Hash entry + Strings.Clear; + Strings.AddStrings(TempStrings); + TempStrings.Free; + end; +end; + +// ***************************************************************************// + +function TCryptIniFile.ReadBinaryStream(const Section, Name: string; Value: TStream): Integer; +// Force normal TINIFile mode +Var + tempPlainTextMode:Boolean; + tempSectionHashing:Boolean; +begin + tempPlainTextMode:=PlainTextMode; + tempSectionHashing:=SectionHashing; + PlainTextMode:=TRUE; + SectionHashing:=FALSE; + Result:=inherited ReadBinaryStream(Section, Name,Value); + PlainTextMode:=tempPlainTextMode; + SectionHashing:=tempSectionHashing; +end; + +// ***************************************************************************// + +procedure TCryptIniFile.WriteBinaryStream(const Section, Name: string; Value: TStream); +// Force normal TINIFile mode +Var + tempPlainTextMode:Boolean; + tempSectionHashing:Boolean; +begin + tempPlainTextMode:=PlainTextMode; + tempSectionHashing:=SectionHashing; + PlainTextMode:=TRUE; + SectionHashing:=FALSE; + inherited WriteBinaryStream(Section, Name,Value); + PlainTextMode:=tempPlainTextMode; + SectionHashing:=tempSectionHashing; +end; + +// ***************************************************************************// +// ***************************************************************************// + + procedure TCryptIniFile.MakeSectionHash(const Section: string; WriteToINI: boolean); +// VerifySection uses WriteToINI=FALSE +var + TempStrings: TStrings; + iCount: integer; + s: string; + tempPlainText: boolean; +begin + if fSectionHashing = False then Exit; + tempPlainText:=fPlainText; // Store value + TempStrings := TStringList.Create; + TempStrings.BeginUpdate; + try + s := ''; + ReadSectionValues(Section, TempStrings); + for iCount := 0 to Pred(TempStrings.Count) do + // Ignore the MD5Hash entry + if (Pos(IDENT_MD5HASH, TempStrings[iCount]) = 0) then + s := s + TempStrings[iCount]; + //DEBUG: else ShowMessage('Found ' + IDENT_MD5HASH); + fMyDigest := MDString(s, MD_VERSION_5); + fMD5String := MDPrint(fMyDigest); + //DEBUG: ShowMessage(fMD5String); + TempPlainText := fPlainText; // Store old value + fPlainText := True; // Set PlainTextMode ON + // Default WriteToINI = TRUE + if WriteToINI then + WriteString(Section, IDENT_MD5HASH, fMD5String); + fPlainText := tempPlainText; // Restore old value + finally + TempStrings.EndUpdate; + TempStrings.Free; + end; +end; + +function TCryptIniFile.VerifySectionHash(const Section, TestMD5Hash: string): boolean; +begin + Result := False; + if fSectionHashing = False then Exit; + { + if ((fSectionHashing = False) or (fPlainText = True)) then + Exit; + } + fMD5String := ''; + // Rehash, but without writing in order to set fMD5String correctly + MakeSectionHash(Section, False); + //DEBUG: ShowMessage(fMD5String); + //DEBUG: ShowMessage(TestMD5Hash); + if (fMD5String = TestMD5Hash) then + Result := True; +end; + +function TCryptIniFile.VerifyString(const Section, Ident, TestValue: string): boolean; + // Matches both value and Hash +var + sCorrect, sCorrectMD5: string; +begin + Result := False; + if fPlainText = True then + Exit; + // Fetch the MD5 hash of the TestValue string + sCorrect := EncodeString(TestValue); + fMyDigest := MDString(sCorrect, MD_VERSION_5); + sCorrectMD5 := MDPrint(fMyDigest); + + // Read the MD5 hash of the INI string (sets fMD5String) and get the value; + fMD5String := ''; + sCorrect := ReadString(Section, Ident, ''); + // DEBUG + { + ShowMessageFmt('sCorrectMD5=%s, fMD5String=%s, sCorrect=%s, TestValue=%s', + [sCorrectMD5,fMD5String,sCorrect,TestValue]); + } + if ((sCorrectMD5 = fMD5String) and (sCorrect = TestValue)) then + Result := True; +end; + +// ***************************************************************************// + +function TCryptIniFile.VerifyInteger(const Section, Ident: string; + TestValue: longint): boolean; + // Matches both value and Hash +var + iCorrect: longint; + sCorrect, sCorrectMD5: string; +begin + Result := False; + if fPlainText = True then + Exit; + iCorrect:=0; + if TestValue <> 0 then + iCorrect := EncodeInteger(TestValue); // Use fKey to scramble it + // Encode it as a string + sCorrect := EncodeString(IntToStr(iCorrect)); + // Make an MD5 Hash of it (sets fMD5String) + fMyDigest := MDString(sCorrect, MD_VERSION_5); + sCorrectMD5 := MDPrint(fMyDigest); + // Use ReadInteger to get the fMD5String of the INI file entry + // And read the value + iCorrect := ReadInteger(Section, Ident, 9999); // Automatically uses fKey to unscramble + // Value and MD5Hash match? + if ((sCorrectMD5 = fMD5String) and (iCorrect = TestValue)) then + Result := True; +end; + +// ***************************************************************************// + +function TCryptIniFile.VerifyBool(const Section, Ident: string; + TestValue: boolean): boolean; +begin + Result := False; + if fPlainText = True then + Exit; + Result := VerifyString(Section, Ident, BoolToChar(TestValue)); +end; + +// ***************************************************************************// + +function TCryptIniFile.VerifyInt64(const Section, Ident: string; + TestValue: int64): boolean; +begin + Result := False; + if fPlainText = True then + Exit; + Result := VerifyString(Section, Ident, IntToStr(TestValue)); +end; + +// ***************************************************************************// + +function TCryptIniFile.VerifyFloat(const Section, Ident: string; + TestValue: double): boolean; +begin + Result := False; + if fPlainText = True then + Exit; + Result := VerifyString(Section, Ident, FloatToStr(TestValue)); +end; + +// ***************************************************************************// + +function TCryptIniFile.VerifyDate(const Section, Ident: string; + TestValue: TDateTime): boolean; +begin + Result := False; + if fPlainText = True then + Exit; + Result := VerifyString(Section, Ident, DateToStr(TestValue)); +end; + +// ***************************************************************************// + +function TCryptIniFile.VerifyTime(const Section, Ident: string; + TestValue: TDateTime): boolean; +begin + Result := False; + if fPlainText = True then + Exit; + Result := VerifyString(Section, Ident, TimeToStr(TestValue)); +end; + +// ***************************************************************************// + +function TCryptIniFile.VerifyDateTime(const Section, Ident: string; + TestValue: TDateTime): boolean; +begin + Result := False; + if fPlainText = True then + Exit; + Result := VerifyString(Section, Ident, DateTimeToStr(TestValue)); +end; + +// ***************************************************************************// + +{$IFDEF USE_DCPCRYPT} +// TODO? use Stream property (Filename='') +Function TCryptIniFile.EncryptINI(DeleteOld:Boolean = TRUE;sPassword: string = DEFAULT_KEYPHRASE;NewExt:String = DEFAULT_EXT):Boolean; +var + Cipher: TDCP_rc4; + Source,Dest: TFileStream; +begin + CacheUpdates:=FALSE; + UpdateFile; + Result:=FALSE; + If NOT FileExistsUTF8(Filename) then exit; + try + If sPassword = '' then sPassword:=fKeyPhrase; + Source := TFileStream.Create(Filename, fmOpenRead); + // INI.Filename, PATH SOURCE OF FILE + Dest := TFileStream.Create(ChangeFileExt(Filename, NewExt), fmCreate); + // ChangeFileExt(INI.Filename, NewExt), PATH DESTINATION OF FILE + Cipher := TDCP_rc4.Create(Nil); + Cipher.InitStr(sPassword, TDCP_sha1); + // initialize the cipher with a hash of the passphrase + Cipher.EncryptStream(Source, Dest, Source.Size); + // encrypt the contents of the file + Cipher.Burn; + Cipher.Free; + finally + Dest.Free; + Source.Free; + Result:=TRUE; + If DeleteOld then Result:=Result AND DeleteFile(Filename); + end; +end; + +// ***************************************************************************// + +Function TCryptIniFile.DecryptINI(DeleteOld:Boolean = TRUE;sPassword: string = DEFAULT_KEYPHRASE;NewExt:String = DEFAULT_EXT):Boolean; +var + Cipher: TDCP_rc4; + Source,Dest: TFileStream; +begin + Result:=FALSE; + If NOT FileExistsUTF8(ChangeFileExt(Filename, NewExt)) then exit; + try + If sPassword = '' then sPassword:=fKeyPhrase; + Source := TFileStream.Create(ChangeFileExt(Filename, NewExt), fmOpenRead); + // ChangeFileExt(INI.Filename, NewExt), PATH SOURCE OF FILE + Dest := TFileStream.Create(Filename, fmCreate); + // INI.Filename, PATH DESTINATION OF FILE + Cipher := TDCP_rc4.Create(Nil); + Cipher.InitStr(sPassword, TDCP_sha1); + // initialize the cipher with a hash of the passphrase + Cipher.DecryptStream(Source, Dest, Source.Size); + // decrypt the contents of the file + Cipher.Burn; + Cipher.Free; + finally + Dest.Free; + Source.Free; + Result:=TRUE; + If DeleteOld then Result:=Result AND DeleteFile(ChangeFileExt(Filename, NewExt)); + // Re-initialise Decrypted INI from disk + Try + {$IFDEF FPC311} + Create(Filename,Options); + {$else} + Create(Filename,EscapeLineFeeds); + {$endif} + CacheUpdates:=FALSE; + Except + // Eat exception + Result:=FALSE; + end; + end; +end; +{$ENDIF} + +// ***************************************************************************// +// ENDOFFILE +// ***************************************************************************// + +end.