source: Common/UCommon.pas@ 554

Last change on this file since 554 was 552, checked in by chronos, 4 years ago
  • Modified: Update Common package.
File size: 18.5 KB
Line 
1unit UCommon;
2
3{$mode delphi}
4
5interface
6
7uses
8 {$ifdef Windows}Windows,{$endif}
9 {$ifdef Linux}baseunix,{$endif}
10 Classes, SysUtils, StrUtils, Dialogs, Process, LCLIntf,
11 FileUtil; //, ShFolder, ShellAPI;
12
13type
14 TArrayOfByte = array of Byte;
15 TArrayOfString = array of string;
16 TExceptionEvent = procedure(Sender: TObject; E: Exception) of object;
17
18 TUserNameFormat = (
19 unfNameUnknown = 0, // Unknown name type.
20 unfNameFullyQualifiedDN = 1, // Fully qualified distinguished name
21 unfNameSamCompatible = 2, // Windows NT® 4.0 account name
22 unfNameDisplay = 3, // A "friendly" display name
23 unfNameUniqueId = 6, // GUID string that the IIDFromString function returns
24 unfNameCanonical = 7, // Complete canonical name
25 unfNameUserPrincipal = 8, // User principal name
26 unfNameCanonicalEx = 9,
27 unfNameServicePrincipal = 10, // Generalized service principal name
28 unfDNSDomainName = 11);
29
30 TFilterMethod = function (FileName: string): Boolean of object;
31 TFileNameMethod = procedure (FileName: string) of object;
32
33var
34 ExceptionHandler: TExceptionEvent;
35 DLLHandle1: HModule;
36
37{$IFDEF Windows}
38 GetUserNameEx: procedure (NameFormat: DWORD;
39 lpNameBuffer: LPSTR; nSize: PULONG); stdcall;
40{$ENDIF}
41
42function AddLeadingZeroes(const aNumber, Length : integer) : string;
43function BinToInt(BinStr: string): Int64;
44function BinToHexString(Source: AnsiString): string;
45//function DelTree(DirName : string): Boolean;
46//function GetSpecialFolderPath(Folder: Integer): string;
47function BCDToInt(Value: Byte): Byte;
48function CompareByteArray(Data1, Data2: TArrayOfByte): Boolean;
49procedure CopyStringArray(Dest: TStringArray; Source: array of string);
50function CombinePaths(Path1, Path2: string): string;
51function ComputerName: string;
52procedure DeleteFiles(APath, AFileSpec: string);
53procedure ExecuteProgram(Executable: string; Parameters: array of string);
54procedure FileDialogUpdateFilterFileType(FileDialog: TOpenDialog);
55procedure FreeThenNil(var Obj);
56function GetDirCount(Dir: string): Integer;
57function GetUserName: string;
58function GetBitCount(Variable: QWord; MaxIndex: Integer): Integer;
59function GetBit(Variable: QWord; Index: Byte): Boolean;
60function GetStringPart(var Text: string; Separator: string): string;
61function GenerateNewName(OldName: string): string;
62function GetFileFilterItemExt(Filter: string; Index: Integer): string;
63function IntToBin(Data: Int64; Count: Byte): string;
64function LastPos(const SubStr: String; const S: String): Integer;
65function LoadFileToStr(const FileName: TFileName): AnsiString;
66function LoggedOnUserNameEx(Format: TUserNameFormat): string;
67function MergeArray(A, B: array of string): TArrayOfString;
68function OccurenceOfChar(What: Char; Where: string): Integer;
69procedure OpenWebPage(URL: string);
70procedure OpenFileInShell(FileName: string);
71function PosFromIndex(SubStr: string; Text: string;
72 StartIndex: Integer): Integer;
73function PosFromIndexReverse(SubStr: string; Text: string;
74 StartIndex: Integer): Integer;
75function RemoveQuotes(Text: string): string;
76procedure SaveStringToFile(S, FileName: string);
77procedure SetBit(var Variable: Int64; Index: Byte; State: Boolean); overload;
78procedure SetBit(var Variable: QWord; Index: Byte; State: Boolean); overload;
79procedure SetBit(var Variable: Cardinal; Index: Byte; State: Boolean); overload;
80procedure SetBit(var Variable: Word; Index: Byte; State: Boolean); overload;
81procedure SearchFiles(AList: TStrings; Dir: string;
82 FilterMethod: TFilterMethod = nil; FileNameMethod: TFileNameMethod = nil);
83function SplitString(var Text: string; Count: Word): string;
84function StripTags(const S: string): string;
85function TryHexToInt(Data: string; var Value: Integer): Boolean;
86function TryBinToInt(Data: string; var Value: Integer): Boolean;
87procedure SortStrings(Strings: TStrings);
88
89
90implementation
91
92function BinToInt(BinStr : string) : Int64;
93var
94 i : byte;
95 RetVar : Int64;
96begin
97 BinStr := UpperCase(BinStr);
98 if BinStr[length(BinStr)] = 'B' then Delete(BinStr,length(BinStr),1);
99 RetVar := 0;
100 for i := 1 to length(BinStr) do begin
101 if not (BinStr[i] in ['0','1']) then begin
102 RetVar := 0;
103 Break;
104 end;
105 RetVar := (RetVar shl 1) + (byte(BinStr[i]) and 1) ;
106 end;
107
108 Result := RetVar;
109end;
110
111function BinToHexString(Source: AnsiString): string;
112var
113 I: Integer;
114begin
115 Result := '';
116 for I := 1 to Length(Source) do begin
117 Result := Result + LowerCase(IntToHex(Ord(Source[I]), 2));
118 end;
119end;
120
121
122procedure DeleteFiles(APath, AFileSpec: string);
123var
124 SearchRec: TSearchRec;
125 Find: Integer;
126 Path: string;
127begin
128 Path := IncludeTrailingPathDelimiter(APath);
129
130 Find := FindFirst(Path + AFileSpec, faAnyFile xor faDirectory, SearchRec);
131 while Find = 0 do begin
132 DeleteFile(Path + SearchRec.Name);
133
134 Find := SysUtils.FindNext(SearchRec);
135 end;
136 FindClose(SearchRec);
137end;
138
139
140function GetFileFilterItemExt(Filter: string; Index: Integer): string;
141var
142 List: TStringList;
143begin
144 try
145 List := TStringList.Create;
146 List.Text := StringReplace(Filter, '|', #10, [rfReplaceAll]);
147 Result := List[Index * 2 + 1];
148 finally
149 List.Free;
150 end;
151end;
152
153procedure FileDialogUpdateFilterFileType(FileDialog: TOpenDialog);
154var
155 FileExt: string;
156begin
157 FileExt := GetFileFilterItemExt(FileDialog.Filter, FileDialog.FilterIndex - 1);
158 Delete(FileExt, 1, 1); // Remove symbol '*'
159 if FileExt <> '.*' then
160 FileDialog.FileName := ChangeFileExt(FileDialog.FileName, FileExt)
161end;
162
163function GenerateNewName(OldName: string): string;
164var
165 I: Integer;
166 Number: Integer;
167begin
168 Number := 1;
169 // Find number on end
170 if Length(OldName) > 0 then begin
171 I := Length(OldName);
172 while (I > 1) and ((OldName[I] >= '0') and (OldName[I] <= '9')) do Dec(I);
173 TryStrToInt(Copy(OldName, I + 1, Length(OldName) - I), Number);
174 Inc(Number)
175 end;
176 Result := Copy(OldName, 1, I) + IntToStr(Number);
177end;
178
179(*function DelTree(DirName : string): Boolean;
180var
181 SHFileOpStruct : TSHFileOpStruct;
182 DirBuf : array [0..255] of char;
183begin
184 DirName := UTF8Decode(DirName);
185 try
186 Fillchar(SHFileOpStruct,Sizeof(SHFileOpStruct),0) ;
187 FillChar(DirBuf, Sizeof(DirBuf), 0 ) ;
188 StrPCopy(DirBuf, DirName) ;
189 with SHFileOpStruct do begin
190 Wnd := 0;
191 pFrom := @DirBuf;
192 wFunc := FO_DELETE;
193 fFlags := FOF_ALLOWUNDO;
194 fFlags := fFlags or FOF_NOCONFIRMATION;
195 fFlags := fFlags or FOF_SILENT;
196 end;
197 Result := (SHFileOperation(SHFileOpStruct) = 0) ;
198 except
199 Result := False;
200 end;
201end;*)
202
203function LastPos(const SubStr: String; const S: String): Integer;
204begin
205 Result := Pos(ReverseString(SubStr), ReverseString(S));
206 if (Result <> 0) then
207 Result := ((Length(S) - Length(SubStr)) + 1) - Result + 1;
208end;
209
210function BCDToInt(Value: Byte): Byte;
211begin
212 Result := (Value shr 4) * 10 + (Value and 15);
213end;
214
215(*function GetSpecialFolderPath(Folder: Integer): string;
216const
217 SHGFP_TYPE_CURRENT = 0;
218var
219 Path: array[0..MAX_PATH] of Char;
220begin
221 Result := 'C:\Test';
222 if SUCCEEDED(SHGetFolderPath(0, Folder, 0, SHGFP_TYPE_CURRENT, @path[0])) then
223 Result := path
224 else
225 Result := '';
226end;*)
227
228function IntToBin(Data: Int64; Count: Byte): string;
229var
230 I: Integer;
231begin
232 Result := '';
233 for I := 0 to Count - 1 do
234 Result := IntToStr((Data shr I) and 1) + Result;
235end;
236
237function IntToHex(Data: Cardinal; Count: Byte): string;
238const
239 Chars: array[0..15] of Char = '0123456789ABCDEF';
240var
241 I: Integer;
242begin
243 Result := '';
244 for I := 0 to Count - 1 do
245 Result := Result + Chars[(Data shr (I * 4)) and 15];
246end;
247
248function TryHexToInt(Data: string; var Value: Integer): Boolean;
249var
250 I: Integer;
251begin
252 Data := UpperCase(Data);
253 Result := True;
254 Value := 0;
255 for I := 0 to Length(Data) - 1 do begin
256 if (Data[I + 1] >= '0') and (Data[I + 1] <= '9') then
257 Value := Value or (Ord(Data[I + 1]) - Ord('0')) shl ((Length(Data) - I - 1) * 4)
258 else if (Data[I + 1] >= 'A') and (Data[I + 1] <= 'F') then
259 Value := Value or (Ord(Data[I + 1]) - Ord('A') + 10) shl ((Length(Data) - I - 1) * 4)
260 else Result := False;
261 end;
262end;
263
264function TryBinToInt(Data: string; var Value: Integer): Boolean;
265var
266 I: Integer;
267begin
268 Result := True;
269 Value := 0;
270 for I := 0 to Length(Data) - 1 do begin
271 if (Data[I + 1] >= '0') and (Data[I + 1] <= '1') then
272 Value := Value or (Ord(Data[I + 1]) - Ord('0')) shl ((Length(Data) - I - 1))
273 else Result := False;
274 end;
275end;
276
277function CompareByteArray(Data1, Data2: TArrayOfByte): Boolean;
278var
279 I: Integer;
280begin
281 if Length(Data1) = Length(Data2) then begin
282 Result := True;
283 for I := 0 to Length(Data1) - 1 do begin
284 if Data1[I] <> Data2[I] then begin
285 Result := False;
286 Break;
287 end
288 end;
289 end else Result := False;
290end;
291
292function Explode(Separator: char; Data: string): TArrayOfString;
293begin
294 SetLength(Result, 0);
295 while Pos(Separator, Data) > 0 do begin
296 SetLength(Result, Length(Result) + 1);
297 Result[High(Result)] := Copy(Data, 1, Pos(Separator, Data) - 1);
298 Delete(Data, 1, Pos(Separator, Data));
299 end;
300 SetLength(Result, Length(Result) + 1);
301 Result[High(Result)] := Data;
302end;
303
304{$IFDEF Windows}
305function GetUserName: string;
306const
307 MAX_USERNAME_LENGTH = 256;
308var
309 L: LongWord;
310begin
311 L := MAX_USERNAME_LENGTH + 2;
312 SetLength(Result, L);
313 if Windows.GetUserName(PChar(Result), L) and (L > 0) then begin
314 SetLength(Result, StrLen(PChar(Result)));
315 Result := UTF8Encode(Result);
316 end else Result := '';
317end;
318
319function GetVersionInfo: TOSVersionInfo;
320begin
321 Result.dwOSVersionInfoSize := SizeOf(Result);
322 if GetVersionEx(Result) then begin
323 end;
324end;
325{$endif}
326
327function ComputerName: string;
328{$ifdef mswindows}
329const
330 INFO_BUFFER_SIZE = 32767;
331var
332 Buffer : array[0..INFO_BUFFER_SIZE] of WideChar;
333 Ret : DWORD;
334begin
335 Ret := INFO_BUFFER_SIZE;
336 If (GetComputerNameW(@Buffer[0],Ret)) then begin
337 Result := UTF8Encode(WideString(Buffer));
338 end
339 else begin
340 Result := 'ERROR_NO_COMPUTERNAME_RETURNED';
341 end;
342end;
343{$endif}
344{$ifdef unix}
345var
346 Name: UtsName;
347begin
348 fpuname(Name);
349 Result := Name.Nodename;
350end;
351{$endif}
352
353{$ifdef windows}
354function LoggedOnUserNameEx(Format: TUserNameFormat): string;
355const
356 MaxLength = 1000;
357var
358 UserName: array[0..MaxLength] of Char;
359 VersionInfo: TOSVersionInfo;
360 Size: DWORD;
361begin
362 VersionInfo := GetVersionInfo;
363 if VersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then begin
364 Size := MaxLength;
365 GetUserNameEx(Integer(Format), @UserName, @Size);
366 //ShowMessage(SysErrorMessage(GetLastError));
367 if GetLastError = 0 then Result := UTF8Encode(UserName)
368 else Result := GetUserName;
369 end else Result := GetUserName;
370end;
371{$ELSE}
372function GetUserName: string;
373begin
374 Result := '';
375end;
376
377function LoggedOnUserNameEx(Format: TUserNameFormat): string;
378begin
379 Result := '';
380end;
381
382{$ENDIF}
383
384function SplitString(var Text: string; Count: Word): string;
385begin
386 Result := Copy(Text, 1, Count);
387 Delete(Text, 1, Count);
388end;
389
390function GetBitCount(Variable: QWord; MaxIndex: Integer): Integer;
391var
392 I: Integer;
393begin
394 Result := 0;
395 for I := 0 to MaxIndex - 1 do
396 if ((Variable shr I) and 1) = 1 then Inc(Result);
397end;
398
399function GetBit(Variable:QWord;Index:Byte):Boolean;
400begin
401 Result := ((Variable shr Index) and 1) = 1;
402end;
403
404procedure SetBit(var Variable: Int64; Index: Byte; State: Boolean);
405begin
406 Variable := (Variable and ((1 shl Index) xor High(QWord))) or (Int64(State) shl Index);
407end;
408
409procedure SetBit(var Variable:QWord;Index:Byte;State:Boolean); overload;
410begin
411 Variable := (Variable and ((1 shl Index) xor High(QWord))) or (QWord(State) shl Index);
412end;
413
414procedure SetBit(var Variable:Cardinal;Index:Byte;State:Boolean); overload;
415begin
416 Variable := (Variable and ((1 shl Index) xor High(Cardinal))) or (Cardinal(State) shl Index);
417end;
418
419procedure SetBit(var Variable:Word;Index:Byte;State:Boolean); overload;
420begin
421 Variable := (Variable and ((1 shl Index) xor High(Word))) or (Word(State) shl Index);
422end;
423
424function AddLeadingZeroes(const aNumber, Length : integer) : string;
425begin
426 Result := SysUtils.Format('%.*d', [Length, aNumber]) ;
427end;
428
429procedure LoadLibraries;
430begin
431 {$IFDEF Windows}
432 DLLHandle1 := LoadLibrary('secur32.dll');
433 if DLLHandle1 <> 0 then
434 begin
435 @GetUserNameEx := GetProcAddress(DLLHandle1, 'GetUserNameExA');
436 end;
437 {$ENDIF}
438end;
439
440procedure FreeLibraries;
441begin
442 {$IFDEF Windows}
443 if DLLHandle1 <> 0 then FreeLibrary(DLLHandle1);
444 {$ENDIF}
445end;
446
447procedure ExecuteProgram(Executable: string; Parameters: array of string);
448var
449 Process: TProcess;
450 I: Integer;
451begin
452 try
453 Process := TProcess.Create(nil);
454 Process.Executable := Executable;
455 for I := 0 to Length(Parameters) - 1 do
456 Process.Parameters.Add(Parameters[I]);
457 Process.Options := [poNoConsole];
458 Process.Execute;
459 finally
460 Process.Free;
461 end;
462end;
463
464procedure FreeThenNil(var Obj);
465begin
466 TObject(Obj).Free;
467 TObject(Obj) := nil;
468end;
469
470procedure OpenWebPage(URL: string);
471begin
472 OpenURL(URL);
473end;
474
475procedure OpenFileInShell(FileName: string);
476begin
477 ExecuteProgram('cmd.exe', ['/c', 'start', FileName]);
478end;
479
480function RemoveQuotes(Text: string): string;
481begin
482 Result := Text;
483 if (Pos('"', Text) = 1) and (Text[Length(Text)] = '"') then
484 Result := Copy(Text, 2, Length(Text) - 2);
485end;
486
487function OccurenceOfChar(What: Char; Where: string): Integer;
488var
489 I: Integer;
490begin
491 Result := 0;
492 for I := 1 to Length(Where) do
493 if Where[I] = What then Inc(Result);
494end;
495
496function GetDirCount(Dir: string): Integer;
497begin
498 Result := OccurenceOfChar(DirectorySeparator, Dir);
499 if Copy(Dir, Length(Dir), 1) = DirectorySeparator then
500 Dec(Result);
501end;
502
503function MergeArray(A, B: array of string): TArrayOfString;
504var
505 I: Integer;
506begin
507 SetLength(Result, Length(A) + Length(B));
508 for I := 0 to Length(A) - 1 do
509 Result[I] := A[I];
510 for I := 0 to Length(B) - 1 do
511 Result[Length(A) + I] := B[I];
512end;
513
514function LoadFileToStr(const FileName: TFileName): AnsiString;
515var
516 FileStream: TFileStream;
517 Read: Integer;
518begin
519 Result := '';
520 FileStream := TFileStream.Create(FileName, fmOpenRead);
521 try
522 if FileStream.Size > 0 then begin
523 SetLength(Result, FileStream.Size);
524 Read := FileStream.Read(Pointer(Result)^, FileStream.Size);
525 SetLength(Result, Read);
526 end;
527 finally
528 FileStream.Free;
529 end;
530end;
531
532function DefaultSearchFilter(const FileName: string): Boolean;
533begin
534 Result := True;
535end;
536
537procedure SaveStringToFile(S, FileName: string);
538var
539 F: TextFile;
540begin
541 AssignFile(F, FileName);
542 try
543 ReWrite(F);
544 Write(F, S);
545 finally
546 CloseFile(F);
547 end;
548end;
549
550procedure SearchFiles(AList: TStrings; Dir: string;
551 FilterMethod: TFilterMethod = nil; FileNameMethod: TFileNameMethod = nil);
552var
553 SR: TSearchRec;
554begin
555 Dir := IncludeTrailingPathDelimiter(Dir);
556 if FindFirst(Dir + '*', faAnyFile, SR) = 0 then
557 try
558 repeat
559 if (SR.Name = '.') or (SR.Name = '..') or (Assigned(FilterMethod) and (not FilterMethod(SR.Name) or
560 not FilterMethod(Copy(Dir, 3, Length(Dir)) + SR.Name))) then Continue;
561 if Assigned(FileNameMethod) then
562 FileNameMethod(Dir + SR.Name);
563 AList.Add(Dir + SR.Name);
564 if (SR.Attr and faDirectory) <> 0 then
565 SearchFiles(AList, Dir + SR.Name, FilterMethod);
566 until FindNext(SR) <> 0;
567 finally
568 FindClose(SR);
569 end;
570end;
571
572function GetStringPart(var Text: string; Separator: string): string;
573var
574 P: Integer;
575begin
576 P := Pos(Separator, Text);
577 if P > 0 then begin
578 Result := Copy(Text, 1, P - 1);
579 Delete(Text, 1, P - 1 + Length(Separator));
580 end else begin
581 Result := Text;
582 Text := '';
583 end;
584 Result := Trim(Result);
585 Text := Trim(Text);
586end;
587
588function StripTags(const S: string): string;
589var
590 Len: Integer;
591
592 function ReadUntil(const ReadFrom: Integer; const C: Char): Integer;
593 var
594 J: Integer;
595 begin
596 for J := ReadFrom to Len do
597 if (S[j] = C) then
598 begin
599 Result := J;
600 Exit;
601 end;
602 Result := Len + 1;
603 end;
604
605var
606 I, APos: Integer;
607begin
608 Len := Length(S);
609 I := 0;
610 Result := '';
611 while (I <= Len) do begin
612 Inc(I);
613 APos := ReadUntil(I, '<');
614 Result := Result + Copy(S, I, APos - i);
615 I := ReadUntil(APos + 1, '>');
616 end;
617end;
618
619function PosFromIndex(SubStr: string; Text: string;
620 StartIndex: Integer): Integer;
621var
622 I, MaxLen: SizeInt;
623 Ptr: PAnsiChar;
624begin
625 Result := 0;
626 if (StartIndex < 1) or (StartIndex > Length(Text) - Length(SubStr)) then Exit;
627 if Length(SubStr) > 0 then begin
628 MaxLen := Length(Text) - Length(SubStr) + 1;
629 I := StartIndex;
630 Ptr := @Text[StartIndex];
631 while (I <= MaxLen) do begin
632 if (SubStr[1] = Ptr^) and (CompareByte(Substr[1], Ptr^, Length(SubStr)) = 0) then begin
633 Result := I;
634 Exit;
635 end;
636 Inc(I);
637 Inc(Ptr);
638 end;
639 end;
640end;
641
642function PosFromIndexReverse(SubStr: string; Text: string;
643 StartIndex: Integer): Integer;
644var
645 I: SizeInt;
646 Ptr: PAnsiChar;
647begin
648 Result := 0;
649 if (StartIndex < 1) or (StartIndex > Length(Text)) then Exit;
650 if Length(SubStr) > 0 then begin
651 I := StartIndex;
652 Ptr := @Text[StartIndex];
653 while (I > 0) do begin
654 if (SubStr[1] = Ptr^) and (CompareByte(Substr[1], Ptr^, Length(SubStr)) = 0) then begin
655 Result := I;
656 Exit;
657 end;
658 Dec(I);
659 Dec(Ptr);
660 end;
661 end;
662end;
663
664procedure CopyStringArray(Dest: TStringArray; Source: array of string);
665var
666 I: Integer;
667begin
668 SetLength(Dest, Length(Source));
669 for I := 0 to Length(Dest) - 1 do
670 Dest[I] := Source[I];
671end;
672
673function CombinePaths(Path1, Path2: string): string;
674begin
675 Result := Path1;
676 if Result <> '' then Result := Result + DirectorySeparator + Path2
677 else Result := Path2;
678end;
679
680procedure SortStrings(Strings: TStrings);
681var
682 Tmp: TStringList;
683begin
684 Strings.BeginUpdate;
685 try
686 if Strings is TStringList then begin
687 TStringList(Strings).Sort;
688 end else begin
689 Tmp := TStringList.Create;
690 try
691 Tmp.Assign(Strings);
692 Tmp.Sort;
693 Strings.Assign(Tmp);
694 finally
695 Tmp.Free;
696 end;
697 end;
698 finally
699 Strings.EndUpdate;
700 end;
701end;
702
703
704initialization
705
706LoadLibraries;
707
708
709finalization
710
711FreeLibraries;
712
713end.
Note: See TracBrowser for help on using the repository browser.