GESTIONNAIRE DE FICHIERS DE CONFIGURATION

cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 - 19 janv. 2007 à 09:20
cs_ezekiel62 Messages postés 10 Date d'inscription vendredi 9 mai 2008 Statut Membre Dernière intervention 1 décembre 2008 - 23 juil. 2008 à 14:13
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/41171-gestionnaire-de-fichiers-de-configuration

cs_ezekiel62 Messages postés 10 Date d'inscription vendredi 9 mai 2008 Statut Membre Dernière intervention 1 décembre 2008
23 juil. 2008 à 14:13
Ce projet semble fort interessant, mais ne se compile pas sous Delphi5...
erf...
Vais essayer d'étudier la source quand même
beau boulot...
sylvunix Messages postés 93 Date d'inscription mardi 11 avril 2006 Statut Membre Dernière intervention 4 mars 2009
24 janv. 2007 à 21:39
f0xi,

Moi qui me disait perfectionniste, je pense que je suis largement battu ! Mais je prends note ...

J'aimerais faire évoluer cette classe en offrant la possibilité de stocker des données cryptées, comme un mot de passe par exemple, en utilisant un algorithme DES. Il y aurait un attribut ClefPrivee dans la classe et on pourrait utiliser le TId comme clef publique.

Qu'en penses-tu ?
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
24 janv. 2007 à 20:20
petite modif qu'on peu appliquer a GenerateID :
(on a pas besoin d'une locale Tid puisqu'on as deja result)

function GenerateId : TId;
type
QuadWord = array[0..3] of word;
ArrChar = array[0..7] of char;
var
QW1,QW2 : QuadWord;
Uid : int64;
pB : ^byte;
N : integer;
begin
repeat
// Initialisation
QW1 := QuadWord( $5C951D1DE74FCC32 xor Random(High(int64)) );
QW2 := QuadWord( $0A5628FAD43E96CB xor Random(High(int64)) );

// Un algorithme simple de chiffrement
QW2[0] := word( (QW2[3] shl 13) or (QW1[0] shr 3) );
QW1[3] := word( (QW1[2] shl 15) or (QW2[3] shr 1) );
QW2[1] := word( (QW2[0] shl 9) or (QW1[1] shr 7) );
QW1[2] := word( (QW1[1] shl 12) or (QW2[2] shr 4) );
QW2[2] := word( (QW2[1] shl 5) or (QW1[2] shr 11) );
QW1[1] := word( (QW1[0] shl 8) or (QW2[1] shr 8) );
QW2[3] := word( (QW2[2] shl 2) or (QW1[3] shr 14) );
QW1[0] := word( (QW1[3] shl 4) or (QW2[0] shr 12) );

// Finalisation
Uid := int64(QW1) xor int64(QW2);

// Suppression des 00
pB := @Uid;
for N := 0 to 7 do begin
if pB^ <= $0F then pB^ := $0F+(random($E9)+1);
inc(pB);
end;

// Conversion du résultat en TId
result := IntToId(Uid);

// Si l'unicité du TId est vérifiée, on le mémorise en on quitte
if IdTable.IndexOf(result) = -1 then begin
IdTable.Add(Result);
Exit;
end;

// Répéter l'opération jusqu'à ce qu'un TId unique soit trouvé
until True;
end;
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
20 janv. 2007 à 03:21
ouai c'est sur que le truc pourris des record pour les config c'est carrement pas exploitable a sec par d'autre logiciel...
sylvunix Messages postés 93 Date d'inscription mardi 11 avril 2006 Statut Membre Dernière intervention 4 mars 2009
19 janv. 2007 à 17:48
f0xi,

Chapeau pour ta génération de TId, je n'avais même pas envisagé d'aller si loin.

Cependant, ta méthode de sauvegarde ne fonctionnera pas avec une arborescence d'objets, comme TConfiguration, auxquels sont attachés des listes de variables.

De plus, mes fichiers sont actuellement sauvegardés au format xml avec une structure propre donc effectivement réexploitables par d'autres logiciels.
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
19 janv. 2007 à 16:09
mais a un moment, je viens de penser que ça faisait beaucoup de travail pour pas grand chose en fait.

car si tu veux tu as beaucoup plus cours pour faire une config.

en gros ça donne :


type
TConfiguration = record
UnBooleen : boolean;
UneChaine : string[64];
UnFlottant : single;
UnEntier : integer;
end;

procedure SaveConfigToFile(const Config : TConfiguration; const FileName : string);
var TFS : TFileStream;
begin
TFS := TFileStream.Create(FileName, fmCreate);
try
TFS.WriteBuffer(Config, SizeOf(TConfiguration));
finally
TFS.Free;
end;
end;

procedure LoadConfigFromFile(var Config : TConfiguration; const FileName : string);
var TFS : TFileStream;
begin
TFS := TFileStream.Create(FileName, fmRead);
try
TFS.ReadBuffer(Config, SizeOf(TConfiguration));
finally
TFS.Free;
end;
end;

et hop, tu l'as ta config ... :)
par contre, interdiction d'aller modifier le fichier de config directement dans le bloc note.
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
19 janv. 2007 à 15:48
hi!

les deux valeurs pour QW1 et QW2 sont des valeurs qui sont choisis pour avoir un certain nombre de bit a 0 et a 1 a peu prés equilibré, avec suffisement de valeur correspondante et decalé par rapport a QW1 et QW2.

si on applique un QW1 XOR QW2 cela nous donneras une valeur comprise entre de High(cardinal) et high(int64)

QW1 = 01011100 10010101 00011101 00011101 11100111 01001111 11001100 00110010
QW2 = 00001010 01010110 00101000 11111010 11010100 00111110 10010110 11001011
XOR = 01010110 11000011 00110101 11100111 00110011 01110001 01011010 11111001
en gros ça nous donne une valeur qui fait :
6 blocs de 4 zero et 4 un
2 bloc de 2 zero et 6 un
ce qui nous donne une bonne base a vide pour passer dans le hacheur par la suite.

IDTABLE nous assure l'unicitée de l'ID qui en decoule, mais les collisions seront plus rare qu'avec un simple random, ce qui nous donne un generateur assé performant et fiable.

c'est le principe des hash, une simple modification de 1 bit donne une clef differente.
tigris1 Messages postés 57 Date d'inscription dimanche 27 mars 2005 Statut Membre Dernière intervention 15 janvier 2009
19 janv. 2007 à 14:05
Très intéressant, très utile, très pratique et qui peut donner des idées pour une utilisation élargie à d'autres besoins que la configuration.

Le code semble bien écrit, bien lisible et très commenté.

Merci pour ce joli travail dont je ne manquerai pas de m'en inspiré à l'occasion.

tigris1
sylvunix Messages postés 93 Date d'inscription mardi 11 avril 2006 Statut Membre Dernière intervention 4 mars 2009
19 janv. 2007 à 12:05
Merci f0xi pour tes critiques (constructives).

Sur la génération des TId, je savais que j'étais un peu léger mais cela fonctionnant j'ai oublié de remettre cette portion de code en question.

Je suis intrigué par le choix de tes valeurs $5C951D1DE74FCC32 et $0A5628FAD43E96CB dans les lignes :

QW1 := QuadWord( $5C951D1DE74FCC32 xor Random(High(int64)) );
QW2 := QuadWord( $0A5628FAD43E96CB xor Random(High(int64)) );

Cela correspond-il à un délire de hamster sur le clavier ou y a-t-il une astuce qui m'aurait échappé ?

Je teste tout cela et je déposerai une mise à jour la semaine prochaine ...
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
19 janv. 2007 à 10:42
hey, ça m'a l'air pas mal du tout ça.

par contre je vois quelques erreurs.

du genre, on appel pas Destroy directement pour detruire une instance d'objet mais Free!
cela evite certaines erreur car Free fait quelques verifications avant de d'appeler Destroy.


plutot que de faire :
Reponse := MessageDlg('Enregistrer les modifications dans le fichier de configuration ?', mtInformation, [mbYes,mbNo,mbCancel], 0);
if Reponse = mrCancel then exit;
if Reponse = mrYes then menuEnregistrerSousClick(Sender);

fait plutot :

case MessageDlg('Enregistrer les modifications dans le fichier de configuration ?', mtInformation, [mbYes,mbNo,mbCancel], 0) of
mrCancel : exit;
mrYes : menuEnregistrerSousClick(Sender);
end;

case MessageDlg('Enregistrer les modifications dans le fichier de configuration ?', mtInformation, [mbYes,mbNo,mbCancel], 0) of
mrCancel : CanClose := False;
mrYes : menuEnregistrerSousClick(Sender);
end;


pour la classe TConfiguration tu ecris :

// Génère un identifiant unique. La méthode est archaïque mais efficace
Randomize;
Tirage := Random(2147483646);
FId := RightStr('00000000'+IntToStr(Tirage),8);
Tirage := Random(2147483646);
FId := FId+RightStr('00000000'+IntToStr(Tirage),8);

appel randomize dans la zone Initialization de l'unité c'est mieux!

ensuite tu peu faire pour generer un identifiant unique aleatoire :

unit GenID;

interface

uses
Windows, SysUtils, Classes;

type
TID = int64;

function IDToHex(const ID : TID) : string;
function GenerateID(const FlushIDTable : boolean = false) : TID;

implementation

var
__IDTABLE : TStringList;

function IDToHex(const ID : TID) : string;
var
pB : ^byte;
pR : PChar;
N : integer;
const
Dig : array[$0..$F] of char = '0132456789ABCDEF';
begin
SetLength(Result, 16);
pB := @ID;
pR := PChar(Result);
inc(pB,7);
for N := 0 to 7 do begin
pR[0] := Dig[pB^ shr 4];
pR[1] := Dig[pB^ and $F];
inc(pR,2);
dec(pB);
end;
end;

function GenerateID(const FlushIDTable : boolean = false) : TID;
type
QuadWord = array[0..3] of word;
ArrChar = array[0..7] of char;
var
QW1,QW2 : QuadWord;
ID : TID;
pB : ^byte;
N : integer;
S : ArrChar;
label
Generate;
begin
// si on ecrase la table des ID on renvois 0 et on sort;
if FlushIDTable then begin
result := 0;
__IDTABLE.Clear;
exit;
end;

Generate :
// initialisation
QW1 := QuadWord( $5C951D1DE74FCC32 xor Random(High(int64)) );
QW2 := QuadWord( $0A5628FAD43E96CB xor Random(High(int64)) );

// un algorithme simple de chiffrement
QW2[0] := word( (QW2[3] shl 13) or (QW1[0] shr 3) );
QW1[3] := word( (QW1[2] shl 15) or (QW2[3] shr 1) );
QW2[1] := word( (QW2[0] shl 9) or (QW1[1] shr 7) );
QW1[2] := word( (QW1[1] shl 12) or (QW2[2] shr 4) );
QW2[2] := word( (QW2[1] shl 5) or (QW1[2] shr 11) );
QW1[1] := word( (QW1[0] shl 8) or (QW2[1] shr 8) );
QW2[3] := word( (QW2[2] shl 2) or (QW1[3] shr 14) );
QW1[0] := word( (QW1[3] shl 4) or (QW2[0] shr 12) );

// finalisation
ID := TID(QW1) xor TID(QW2);

// suppression des 00
pB := @ID;
for N := 0 to 7 do begin
if pB^ <= $0F then
pB^ := $0F+(random($E9)+1);
inc(pB);
end;

// insertion de S
S := ArrChar(ID);

// verification des doublons
if __IDTABLE.IndexOf(string(S)) = -1 then begin
// ajout
__IDTABLE.Add(string(S));
// retour
result := ID;
// sortie
exit;
end else
// sinon on regenere un ID
goto Generate;
end;

initialization
// initialisation des nombres aleatoire
Randomize;

// creatiob de la table des ID pour garantire la generation
// d'ID unique durant la session.
__IDTABLE := TStringList.Create;
__IDTABLE.Sorted := true;
__IDTABLE.Duplicates := dupIgnore;

finalization
// liberation de la table des ID
__IDTABLE.Free;

end.


sinon le reste semble pas mal, j'ai pas trop fouiner mais tout me semble correct.

voila.
cs_Loda Messages postés 814 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 30 juillet 2009 3
19 janv. 2007 à 09:20
salut,

ça m'as l'air très intéressant.... Je dl le code quand j'aurais un moment.

merci pour ça...

A+
Rejoignez-nous