source: Network/synapse/synautil.pas

Last change on this file was 300, checked in by chronos, 13 years ago
  • Added: Synapse library with package file. Cryptlib units are not included in package file list.
File size: 48.7 KB
Line 
1{==============================================================================|
2| Project : Ararat Synapse | 004.013.000 |
3|==============================================================================|
4| Content: support procedures and functions |
5|==============================================================================|
6| Copyright (c)1999-2008, Lukas Gebauer |
7| All rights reserved. |
8| |
9| Redistribution and use in source and binary forms, with or without |
10| modification, are permitted provided that the following conditions are met: |
11| |
12| Redistributions of source code must retain the above copyright notice, this |
13| list of conditions and the following disclaimer. |
14| |
15| Redistributions in binary form must reproduce the above copyright notice, |
16| this list of conditions and the following disclaimer in the documentation |
17| and/or other materials provided with the distribution. |
18| |
19| Neither the name of Lukas Gebauer nor the names of its contributors may |
20| be used to endorse or promote products derived from this software without |
21| specific prior written permission. |
22| |
23| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
24| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
27| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
28| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
29| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
30| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
33| DAMAGE. |
34|==============================================================================|
35| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
36| Portions created by Lukas Gebauer are Copyright (c) 1999-2008. |
37| Portions created by Hernan Sanchez are Copyright (c) 2000. |
38| All Rights Reserved. |
39|==============================================================================|
40| Contributor(s): |
41| Hernan Sanchez (hernan.sanchez@iname.com) |
42|==============================================================================|
43| History: see HISTORY.HTM from distribution package |
44| (Found at URL: http://www.ararat.cz/synapse/) |
45|==============================================================================}
46
47{:@abstract(Support procedures and functions)}
48
49{$IFDEF FPC}
50 {$MODE DELPHI}
51{$ENDIF}
52{$Q-}
53{$R-}
54{$H+}
55
56unit synautil;
57
58interface
59
60uses
61{$IFDEF WIN32}
62 Windows,
63{$ELSE}
64 {$IFDEF FPC}
65 UnixUtil, Unix, BaseUnix,
66 {$ELSE}
67 Libc,
68 {$ENDIF}
69{$ENDIF}
70{$IFDEF CIL}
71 System.IO,
72{$ENDIF}
73 SysUtils, Classes, SynaFpc;
74
75{$IFDEF VER100}
76type
77 int64 = integer;
78{$ENDIF}
79
80{:Return your timezone bias from UTC time in minutes.}
81function TimeZoneBias: integer;
82
83{:Return your timezone bias from UTC time in string representation like "+0200".}
84function TimeZone: string;
85
86{:Returns current time in format defined in RFC-822. Useful for SMTP messages,
87 but other protocols use this time format as well. Results contains the timezone
88 specification. Four digit year is used to break any Y2K concerns. (Example
89 'Fri, 15 Oct 1999 21:14:56 +0200')}
90function Rfc822DateTime(t: TDateTime): string;
91
92{:Returns date and time in format defined in C compilers in format "mmm dd hh:nn:ss"}
93function CDateTime(t: TDateTime): string;
94
95{:Returns date and time in format defined in format 'yymmdd hhnnss'}
96function SimpleDateTime(t: TDateTime): string;
97
98{:Returns date and time in format defined in ANSI C compilers in format
99 "ddd mmm d hh:nn:ss yyyy" }
100function AnsiCDateTime(t: TDateTime): string;
101
102{:Decode three-letter string with name of month to their month number. If string
103 not match any month name, then is returned 0. For parsing are used predefined
104 names for English, French and German and names from system locale too.}
105function GetMonthNumber(Value: AnsiString): integer;
106
107{:Return decoded time from given string. Time must be witch separator ':'. You
108 can use "hh:mm" or "hh:mm:ss".}
109function GetTimeFromStr(Value: string): TDateTime;
110
111{:Decode string in format "m-d-y" to TDateTime type.}
112function GetDateMDYFromStr(Value: string): TDateTime;
113
114{:Decode various string representations of date and time to Tdatetime type.
115 This function do all timezone corrections too! This function can decode lot of
116 formats like:
117 @longcode(#
118 ddd, d mmm yyyy hh:mm:ss
119 ddd, d mmm yy hh:mm:ss
120 ddd, mmm d yyyy hh:mm:ss
121 ddd mmm dd hh:mm:ss yyyy #)
122
123and more with lot of modifications, include:
124@longcode(#
125Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
126Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
127Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() Format
128#)
129Timezone corrections known lot of symbolic timezone names (like CEST, EDT, etc.)
130or numeric representation (like +0200). By convention defined in RFC timezone
131 +0000 is GMT and -0000 is current your system timezone.}
132function DecodeRfcDateTime(Value: string): TDateTime;
133
134{:Return current system date and time in UTC timezone.}
135function GetUTTime: TDateTime;
136
137{:Set Newdt as current system date and time in UTC timezone. This function work
138 only if you have administrator rights!}
139function SetUTTime(Newdt: TDateTime): Boolean;
140
141{:Return current value of system timer with precizion 1 millisecond. Good for
142 measure time difference.}
143function GetTick: LongWord;
144
145{:Return difference between two timestamps. It working fine only for differences
146 smaller then maxint. (difference must be smaller then 24 days.)}
147function TickDelta(TickOld, TickNew: LongWord): LongWord;
148
149{:Return two characters, which ordinal values represents the value in byte
150 format. (High-endian)}
151function CodeInt(Value: Word): Ansistring;
152
153{:Decodes two characters located at "Index" offset position of the "Value"
154 string to Word values.}
155function DecodeInt(const Value: Ansistring; Index: Integer): Word;
156
157{:Return four characters, which ordinal values represents the value in byte
158 format. (High-endian)}
159function CodeLongInt(Value: LongInt): Ansistring;
160
161{:Decodes four characters located at "Index" offset position of the "Value"
162 string to LongInt values.}
163function DecodeLongInt(const Value: Ansistring; Index: Integer): LongInt;
164
165{:Dump binary buffer stored in a string to a result string.}
166function DumpStr(const Buffer: Ansistring): string;
167
168{:Dump binary buffer stored in a string to a result string. All bytes with code
169 of character is written as character, not as hexadecimal value.}
170function DumpExStr(const Buffer: Ansistring): string;
171
172{:Dump binary buffer stored in a string to a file with DumpFile filename.}
173procedure Dump(const Buffer: AnsiString; DumpFile: string);
174
175{:Dump binary buffer stored in a string to a file with DumpFile filename. All
176 bytes with code of character is written as character, not as hexadecimal value.}
177procedure DumpEx(const Buffer: AnsiString; DumpFile: string);
178
179{:Like TrimLeft, but remove only spaces, not control characters!}
180function TrimSPLeft(const S: string): string;
181
182{:Like TrimRight, but remove only spaces, not control characters!}
183function TrimSPRight(const S: string): string;
184
185{:Like Trim, but remove only spaces, not control characters!}
186function TrimSP(const S: string): string;
187
188{:Returns a portion of the "Value" string located to the left of the "Delimiter"
189 string. If a delimiter is not found, results is original string.}
190function SeparateLeft(const Value, Delimiter: string): string;
191
192{:Returns the portion of the "Value" string located to the right of the
193 "Delimiter" string. If a delimiter is not found, results is original string.}
194function SeparateRight(const Value, Delimiter: string): string;
195
196{:Returns parameter value from string in format:
197 parameter1="value1"; parameter2=value2}
198function GetParameter(const Value, Parameter: string): string;
199
200{:parse value string with elements differed by Delimiter into stringlist.}
201procedure ParseParametersEx(Value, Delimiter: string; const Parameters: TStrings);
202
203{:parse value string with elements differed by ';' into stringlist.}
204procedure ParseParameters(Value: string; const Parameters: TStrings);
205
206{:Index of string in stringlist with same beginning as Value is returned.}
207function IndexByBegin(Value: string; const List: TStrings): integer;
208
209{:Returns only the e-mail portion of an address from the full address format.
210 i.e. returns 'nobody@@somewhere.com' from '"someone" <nobody@@somewhere.com>'}
211function GetEmailAddr(const Value: string): string;
212
213{:Returns only the description part from a full address format. i.e. returns
214 'someone' from '"someone" <nobody@@somewhere.com>'}
215function GetEmailDesc(Value: string): string;
216
217{:Returns a string with hexadecimal digits representing the corresponding values
218 of the bytes found in "Value" string.}
219function StrToHex(const Value: Ansistring): string;
220
221{:Returns a string of binary "Digits" representing "Value".}
222function IntToBin(Value: Integer; Digits: Byte): string;
223
224{:Returns an integer equivalent of the binary string in "Value".
225 (i.e. ('10001010') returns 138)}
226function BinToInt(const Value: string): Integer;
227
228{:Parses a URL to its various components.}
229function ParseURL(URL: string; var Prot, User, Pass, Host, Port, Path,
230 Para: string): string;
231
232{:Replaces all "Search" string values found within "Value" string, with the
233 "Replace" string value.}
234function ReplaceString(Value, Search, Replace: AnsiString): AnsiString;
235
236{:It is like RPos, but search is from specified possition.}
237function RPosEx(const Sub, Value: string; From: integer): Integer;
238
239{:It is like POS function, but from right side of Value string.}
240function RPos(const Sub, Value: String): Integer;
241
242{:Like @link(fetch), but working with binary strings, not with text.}
243function FetchBin(var Value: string; const Delimiter: string): string;
244
245{:Fetch string from left of Value string.}
246function Fetch(var Value: string; const Delimiter: string): string;
247
248{:Fetch string from left of Value string. This function ignore delimitesr inside
249 quotations.}
250function FetchEx(var Value: string; const Delimiter, Quotation: string): string;
251
252{:If string is binary string (contains non-printable characters), then is
253 returned true.}
254function IsBinaryString(const Value: string): Boolean;
255
256{:return position of string terminator in string. If terminator found, then is
257 returned in terminator parameter.
258 Possible line terminators are: CRLF, LFCR, CR, LF}
259function PosCRLF(const Value: AnsiString; var Terminator: AnsiString): integer;
260
261{:Delete empty strings from end of stringlist.}
262Procedure StringsTrim(const value: TStrings);
263
264{:Like Pos function, buf from given string possition.}
265function PosFrom(const SubStr, Value: String; From: integer): integer;
266
267{$IFNDEF CIL}
268{:Increase pointer by value.}
269function IncPoint(const p: pointer; Value: integer): pointer;
270{$ENDIF}
271
272{:Get string between PairBegin and PairEnd. This function respect nesting.
273 For example:
274 @longcode(#
275 Value is: 'Hi! (hello(yes!))'
276 pairbegin is: '('
277 pairend is: ')'
278 In this case result is: 'hello(yes!)'#)}
279function GetBetween(const PairBegin, PairEnd, Value: string): string;
280
281{:Return count of Chr in Value string.}
282function CountOfChar(const Value: string; Chr: char): integer;
283
284{:Remove quotation from Value string. If Value is not quoted, then return same
285 string without any modification. }
286function UnquoteStr(const Value: string; Quote: Char): string;
287
288{:Quote Value string. If Value contains some Quote chars, then it is doubled.}
289function QuoteStr(const Value: string; Quote: Char): string;
290
291{:Convert lines in stringlist from 'name: value' form to 'name=value' form.}
292procedure HeadersToList(const Value: TStrings);
293
294{:Convert lines in stringlist from 'name=value' form to 'name: value' form.}
295procedure ListToHeaders(const Value: TStrings);
296
297{:swap bytes in integer.}
298function SwapBytes(Value: integer): integer;
299
300{:read string with requested length form stream.}
301function ReadStrFromStream(const Stream: TStream; len: integer): AnsiString;
302
303{:write string to stream.}
304procedure WriteStrToStream(const Stream: TStream; Value: AnsiString);
305
306{:Return filename of new temporary file in Dir (if empty, then default temporary
307 directory is used) and with optional filename prefix.}
308function GetTempFile(const Dir, prefix: AnsiString): AnsiString;
309
310{:Return padded string. If length is greater, string is truncated. If length is
311 smaller, string is padded by Pad character.}
312function PadString(const Value: AnsiString; len: integer; Pad: AnsiChar): AnsiString;
313
314{:Read header from "Value" stringlist beginning at "Index" position. If header
315 is Splitted into multiple lines, then this procedure de-split it into one line.}
316function NormalizeHeader(Value: TStrings; var Index: Integer): string;
317
318var
319 {:can be used for your own months strings for @link(getmonthnumber)}
320 CustomMonthNames: array[1..12] of string;
321
322implementation
323
324{==============================================================================}
325
326const
327 MyDayNames: array[1..7] of AnsiString =
328 ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
329var
330 MyMonthNames: array[0..6, 1..12] of AnsiString =
331 (
332 ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', //rewrited by system locales
333 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
334 ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', //English
335 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
336 ('jan', 'fév', 'mar', 'avr', 'mai', 'jun', //French
337 'jul', 'aoû', 'sep', 'oct', 'nov', 'déc'),
338 ('jan', 'fev', 'mar', 'avr', 'mai', 'jun', //French#2
339 'jul', 'aou', 'sep', 'oct', 'nov', 'dec'),
340 ('Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jun', //German
341 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'),
342 ('Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', //German#2
343 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'),
344 ('Led', 'Úno', 'Bøe', 'Dub', 'Kvì', 'Èen', //Czech
345 'Èec', 'Srp', 'Záø', 'Øíj', 'Lis', 'Pro')
346 );
347
348
349{==============================================================================}
350
351function TimeZoneBias: integer;
352{$IFNDEF WIN32}
353{$IFNDEF FPC}
354var
355 t: TTime_T;
356 UT: TUnixTime;
357begin
358 __time(@T);
359 localtime_r(@T, UT);
360 Result := ut.__tm_gmtoff div 60;
361{$ELSE}
362begin
363 Result := TZSeconds div 60;
364{$ENDIF}
365{$ELSE}
366var
367 zoneinfo: TTimeZoneInformation;
368 bias: Integer;
369begin
370 case GetTimeZoneInformation(Zoneinfo) of
371 2:
372 bias := zoneinfo.Bias + zoneinfo.DaylightBias;
373 1:
374 bias := zoneinfo.Bias + zoneinfo.StandardBias;
375 else
376 bias := zoneinfo.Bias;
377 end;
378 Result := bias * (-1);
379{$ENDIF}
380end;
381
382{==============================================================================}
383
384function TimeZone: string;
385var
386 bias: Integer;
387 h, m: Integer;
388begin
389 bias := TimeZoneBias;
390 if bias >= 0 then
391 Result := '+'
392 else
393 Result := '-';
394 bias := Abs(bias);
395 h := bias div 60;
396 m := bias mod 60;
397 Result := Result + Format('%.2d%.2d', [h, m]);
398end;
399
400{==============================================================================}
401
402function Rfc822DateTime(t: TDateTime): string;
403var
404 wYear, wMonth, wDay: word;
405begin
406 DecodeDate(t, wYear, wMonth, wDay);
407 Result := Format('%s, %d %s %s %s', [MyDayNames[DayOfWeek(t)], wDay,
408 MyMonthNames[1, wMonth], FormatDateTime('yyyy hh":"nn":"ss', t), TimeZone]);
409end;
410
411{==============================================================================}
412
413function CDateTime(t: TDateTime): string;
414var
415 wYear, wMonth, wDay: word;
416begin
417 DecodeDate(t, wYear, wMonth, wDay);
418 Result:= Format('%s %2d %s', [MyMonthNames[1, wMonth], wDay,
419 FormatDateTime('hh":"nn":"ss', t)]);
420end;
421
422{==============================================================================}
423
424function SimpleDateTime(t: TDateTime): string;
425begin
426 Result := FormatDateTime('yymmdd hhnnss', t);
427end;
428
429{==============================================================================}
430
431function AnsiCDateTime(t: TDateTime): string;
432var
433 wYear, wMonth, wDay: word;
434begin
435 DecodeDate(t, wYear, wMonth, wDay);
436 Result := Format('%s %s %d %s', [MyDayNames[DayOfWeek(t)], MyMonthNames[1, wMonth],
437 wDay, FormatDateTime('hh":"nn":"ss yyyy ', t)]);
438end;
439
440{==============================================================================}
441
442function DecodeTimeZone(Value: string; var Zone: integer): Boolean;
443var
444 x: integer;
445 zh, zm: integer;
446 s: string;
447begin
448 Result := false;
449 s := Value;
450 if (Pos('+', s) = 1) or (Pos('-',s) = 1) then
451 begin
452 if s = '-0000' then
453 Zone := TimeZoneBias
454 else
455 if Length(s) > 4 then
456 begin
457 zh := StrToIntdef(s[2] + s[3], 0);
458 zm := StrToIntdef(s[4] + s[5], 0);
459 zone := zh * 60 + zm;
460 if s[1] = '-' then
461 zone := zone * (-1);
462 end;
463 Result := True;
464 end
465 else
466 begin
467 x := 32767;
468 if s = 'NZDT' then x := 13;
469 if s = 'IDLE' then x := 12;
470 if s = 'NZST' then x := 12;
471 if s = 'NZT' then x := 12;
472 if s = 'EADT' then x := 11;
473 if s = 'GST' then x := 10;
474 if s = 'JST' then x := 9;
475 if s = 'CCT' then x := 8;
476 if s = 'WADT' then x := 8;
477 if s = 'WAST' then x := 7;
478 if s = 'ZP6' then x := 6;
479 if s = 'ZP5' then x := 5;
480 if s = 'ZP4' then x := 4;
481 if s = 'BT' then x := 3;
482 if s = 'EET' then x := 2;
483 if s = 'MEST' then x := 2;
484 if s = 'MESZ' then x := 2;
485 if s = 'SST' then x := 2;
486 if s = 'FST' then x := 2;
487 if s = 'CEST' then x := 2;
488 if s = 'CET' then x := 1;
489 if s = 'FWT' then x := 1;
490 if s = 'MET' then x := 1;
491 if s = 'MEWT' then x := 1;
492 if s = 'SWT' then x := 1;
493 if s = 'UT' then x := 0;
494 if s = 'UTC' then x := 0;
495 if s = 'GMT' then x := 0;
496 if s = 'WET' then x := 0;
497 if s = 'WAT' then x := -1;
498 if s = 'BST' then x := -1;
499 if s = 'AT' then x := -2;
500 if s = 'ADT' then x := -3;
501 if s = 'AST' then x := -4;
502 if s = 'EDT' then x := -4;
503 if s = 'EST' then x := -5;
504 if s = 'CDT' then x := -5;
505 if s = 'CST' then x := -6;
506 if s = 'MDT' then x := -6;
507 if s = 'MST' then x := -7;
508 if s = 'PDT' then x := -7;
509 if s = 'PST' then x := -8;
510 if s = 'YDT' then x := -8;
511 if s = 'YST' then x := -9;
512 if s = 'HDT' then x := -9;
513 if s = 'AHST' then x := -10;
514 if s = 'CAT' then x := -10;
515 if s = 'HST' then x := -10;
516 if s = 'EAST' then x := -10;
517 if s = 'NT' then x := -11;
518 if s = 'IDLW' then x := -12;
519 if x <> 32767 then
520 begin
521 zone := x * 60;
522 Result := True;
523 end;
524 end;
525end;
526
527{==============================================================================}
528
529function GetMonthNumber(Value: AnsiString): integer;
530var
531 n: integer;
532 function TestMonth(Value: AnsiString; Index: Integer): Boolean;
533 var
534 n: integer;
535 begin
536 Result := False;
537 for n := 0 to 6 do
538 if Value = AnsiUppercase(MyMonthNames[n, Index]) then
539 begin
540 Result := True;
541 Break;
542 end;
543 end;
544begin
545 Result := 0;
546 Value := AnsiUppercase(Value);
547 for n := 1 to 12 do
548 if TestMonth(Value, n) or (Value = AnsiUppercase(CustomMonthNames[n])) then
549 begin
550 Result := n;
551 Break;
552 end;
553end;
554
555{==============================================================================}
556
557function GetTimeFromStr(Value: string): TDateTime;
558var
559 x: integer;
560begin
561 x := rpos(':', Value);
562 if (x > 0) and ((Length(Value) - x) > 2) then
563 Value := Copy(Value, 1, x + 2);
564 Value := ReplaceString(Value, ':', TimeSeparator);
565 Result := -1;
566 try
567 Result := StrToTime(Value);
568 except
569 on Exception do ;
570 end;
571end;
572
573{==============================================================================}
574
575function GetDateMDYFromStr(Value: string): TDateTime;
576var
577 wYear, wMonth, wDay: word;
578 s: string;
579begin
580 Result := 0;
581 s := Fetch(Value, '-');
582 wMonth := StrToIntDef(s, 12);
583 s := Fetch(Value, '-');
584 wDay := StrToIntDef(s, 30);
585 wYear := StrToIntDef(Value, 1899);
586 if wYear < 1000 then
587 if (wYear > 99) then
588 wYear := wYear + 1900
589 else
590 if wYear > 50 then
591 wYear := wYear + 1900
592 else
593 wYear := wYear + 2000;
594 try
595 Result := EncodeDate(wYear, wMonth, wDay);
596 except
597 on Exception do ;
598 end;
599end;
600
601{==============================================================================}
602
603function DecodeRfcDateTime(Value: string): TDateTime;
604var
605 day, month, year: Word;
606 zone: integer;
607 x, y: integer;
608 s: string;
609 t: TDateTime;
610begin
611// ddd, d mmm yyyy hh:mm:ss
612// ddd, d mmm yy hh:mm:ss
613// ddd, mmm d yyyy hh:mm:ss
614// ddd mmm dd hh:mm:ss yyyy
615// Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
616// Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
617// Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() Format
618
619 Result := 0;
620 if Value = '' then
621 Exit;
622 day := 0;
623 month := 0;
624 year := 0;
625 zone := 0;
626 Value := ReplaceString(Value, ' -', ' #');
627 Value := ReplaceString(Value, '-', ' ');
628 Value := ReplaceString(Value, ' #', ' -');
629 while Value <> '' do
630 begin
631 s := Fetch(Value, ' ');
632 s := uppercase(s);
633 // timezone
634 if DecodetimeZone(s, x) then
635 begin
636 zone := x;
637 continue;
638 end;
639 x := StrToIntDef(s, 0);
640 // day or year
641 if x > 0 then
642 if (x < 32) and (day = 0) then
643 begin
644 day := x;
645 continue;
646 end
647 else
648 begin
649 if (year = 0) and ((month > 0) or (x > 12)) then
650 begin
651 year := x;
652 if year < 32 then
653 year := year + 2000;
654 if year < 1000 then
655 year := year + 1900;
656 continue;
657 end;
658 end;
659 // time
660 if rpos(':', s) > Pos(':', s) then
661 begin
662 t := GetTimeFromStr(s);
663 if t <> -1 then
664 Result := t;
665 continue;
666 end;
667 //timezone daylight saving time
668 if s = 'DST' then
669 begin
670 zone := zone + 60;
671 continue;
672 end;
673 // month
674 y := GetMonthNumber(s);
675 if (y > 0) and (month = 0) then
676 month := y;
677 end;
678 if year = 0 then
679 year := 1980;
680 if month < 1 then
681 month := 1;
682 if month > 12 then
683 month := 12;
684 if day < 1 then
685 day := 1;
686 x := MonthDays[IsLeapYear(year), month];
687 if day > x then
688 day := x;
689 Result := Result + Encodedate(year, month, day);
690 zone := zone - TimeZoneBias;
691 x := zone div 1440;
692 Result := Result - x;
693 zone := zone mod 1440;
694 t := EncodeTime(Abs(zone) div 60, Abs(zone) mod 60, 0, 0);
695 if zone < 0 then
696 t := 0 - t;
697 Result := Result - t;
698end;
699
700{==============================================================================}
701
702function GetUTTime: TDateTime;
703{$IFDEF WIN32}
704{$IFNDEF FPC}
705var
706 st: TSystemTime;
707begin
708 GetSystemTime(st);
709 result := SystemTimeToDateTime(st);
710{$ELSE}
711var
712 st: SysUtils.TSystemTime;
713 stw: Windows.TSystemTime;
714begin
715 GetSystemTime(stw);
716 st.Year := stw.wYear;
717 st.Month := stw.wMonth;
718 st.Day := stw.wDay;
719 st.Hour := stw.wHour;
720 st.Minute := stw.wMinute;
721 st.Second := stw.wSecond;
722 st.Millisecond := stw.wMilliseconds;
723 result := SystemTimeToDateTime(st);
724{$ENDIF}
725{$ELSE}
726{$IFNDEF FPC}
727var
728 TV: TTimeVal;
729begin
730 gettimeofday(TV, nil);
731 Result := UnixDateDelta + (TV.tv_sec + TV.tv_usec / 1000000) / 86400;
732{$ELSE}
733var
734 TV: TimeVal;
735begin
736 fpgettimeofday(@TV, nil);
737 Result := UnixDateDelta + (TV.tv_sec + TV.tv_usec / 1000000) / 86400;
738{$ENDIF}
739{$ENDIF}
740end;
741
742{==============================================================================}
743
744function SetUTTime(Newdt: TDateTime): Boolean;
745{$IFDEF WIN32}
746{$IFNDEF FPC}
747var
748 st: TSystemTime;
749begin
750 DateTimeToSystemTime(newdt,st);
751 Result := SetSystemTime(st);
752{$ELSE}
753var
754 st: SysUtils.TSystemTime;
755 stw: Windows.TSystemTime;
756begin
757 DateTimeToSystemTime(newdt,st);
758 stw.wYear := st.Year;
759 stw.wMonth := st.Month;
760 stw.wDay := st.Day;
761 stw.wHour := st.Hour;
762 stw.wMinute := st.Minute;
763 stw.wSecond := st.Second;
764 stw.wMilliseconds := st.Millisecond;
765 Result := SetSystemTime(stw);
766{$ENDIF}
767{$ELSE}
768{$IFNDEF FPC}
769var
770 TV: TTimeVal;
771 d: double;
772 TZ: Ttimezone;
773 PZ: PTimeZone;
774begin
775 TZ.tz_minuteswest := 0;
776 TZ.tz_dsttime := 0;
777 PZ := @TZ;
778 gettimeofday(TV, PZ);
779 d := (newdt - UnixDateDelta) * 86400;
780 TV.tv_sec := trunc(d);
781 TV.tv_usec := trunc(frac(d) * 1000000);
782 Result := settimeofday(TV, TZ) <> -1;
783{$ELSE}
784var
785 TV: TimeVal;
786 d: double;
787begin
788 d := (newdt - UnixDateDelta) * 86400;
789 TV.tv_sec := trunc(d);
790 TV.tv_usec := trunc(frac(d) * 1000000);
791 Result := fpsettimeofday(@TV, nil) <> -1;
792{$ENDIF}
793{$ENDIF}
794end;
795
796{==============================================================================}
797
798{$IFNDEF WIN32}
799function GetTick: LongWord;
800var
801 Stamp: TTimeStamp;
802begin
803 Stamp := DateTimeToTimeStamp(Now);
804 Result := Stamp.Time;
805end;
806{$ELSE}
807function GetTick: LongWord;
808var
809 tick, freq: TLargeInteger;
810{$IFDEF VER100}
811 x: TLargeInteger;
812{$ENDIF}
813begin
814 if Windows.QueryPerformanceFrequency(freq) then
815 begin
816 Windows.QueryPerformanceCounter(tick);
817{$IFDEF VER100}
818 x.QuadPart := (tick.QuadPart / freq.QuadPart) * 1000;
819 Result := x.LowPart;
820{$ELSE}
821 Result := Trunc((tick / freq) * 1000) and High(LongWord)
822{$ENDIF}
823 end
824 else
825 Result := Windows.GetTickCount;
826end;
827{$ENDIF}
828
829{==============================================================================}
830
831function TickDelta(TickOld, TickNew: LongWord): LongWord;
832begin
833//if DWord is signed type (older Deplhi),
834// then it not work properly on differencies larger then maxint!
835 Result := 0;
836 if TickOld <> TickNew then
837 begin
838 if TickNew < TickOld then
839 begin
840 TickNew := TickNew + LongWord(MaxInt) + 1;
841 TickOld := TickOld + LongWord(MaxInt) + 1;
842 end;
843 Result := TickNew - TickOld;
844 if TickNew < TickOld then
845 if Result > 0 then
846 Result := 0 - Result;
847 end;
848end;
849
850{==============================================================================}
851
852function CodeInt(Value: Word): Ansistring;
853begin
854 setlength(result, 2);
855 result[1] := AnsiChar(Value div 256);
856 result[2] := AnsiChar(Value mod 256);
857// Result := AnsiChar(Value div 256) + AnsiChar(Value mod 256)
858end;
859
860{==============================================================================}
861
862function DecodeInt(const Value: Ansistring; Index: Integer): Word;
863var
864 x, y: Byte;
865begin
866 if Length(Value) > Index then
867 x := Ord(Value[Index])
868 else
869 x := 0;
870 if Length(Value) >= (Index + 1) then
871 y := Ord(Value[Index + 1])
872 else
873 y := 0;
874 Result := x * 256 + y;
875end;
876
877{==============================================================================}
878
879function CodeLongInt(Value: Longint): Ansistring;
880var
881 x, y: word;
882begin
883 // this is fix for negative numbers on systems where longint = integer
884 x := (Value shr 16) and integer($ffff);
885 y := Value and integer($ffff);
886 setlength(result, 4);
887 result[1] := AnsiChar(x div 256);
888 result[2] := AnsiChar(x mod 256);
889 result[3] := AnsiChar(y div 256);
890 result[4] := AnsiChar(y mod 256);
891end;
892
893{==============================================================================}
894
895function DecodeLongInt(const Value: Ansistring; Index: Integer): LongInt;
896var
897 x, y: Byte;
898 xl, yl: Byte;
899begin
900 if Length(Value) > Index then
901 x := Ord(Value[Index])
902 else
903 x := 0;
904 if Length(Value) >= (Index + 1) then
905 y := Ord(Value[Index + 1])
906 else
907 y := 0;
908 if Length(Value) >= (Index + 2) then
909 xl := Ord(Value[Index + 2])
910 else
911 xl := 0;
912 if Length(Value) >= (Index + 3) then
913 yl := Ord(Value[Index + 3])
914 else
915 yl := 0;
916 Result := ((x * 256 + y) * 65536) + (xl * 256 + yl);
917end;
918
919{==============================================================================}
920
921function DumpStr(const Buffer: Ansistring): string;
922var
923 n: Integer;
924begin
925 Result := '';
926 for n := 1 to Length(Buffer) do
927 Result := Result + ' +#$' + IntToHex(Ord(Buffer[n]), 2);
928end;
929
930{==============================================================================}
931
932function DumpExStr(const Buffer: Ansistring): string;
933var
934 n: Integer;
935 x: Byte;
936begin
937 Result := '';
938 for n := 1 to Length(Buffer) do
939 begin
940 x := Ord(Buffer[n]);
941 if x in [65..90, 97..122] then
942 Result := Result + ' +''' + char(x) + ''''
943 else
944 Result := Result + ' +#$' + IntToHex(Ord(Buffer[n]), 2);
945 end;
946end;
947
948{==============================================================================}
949
950procedure Dump(const Buffer: AnsiString; DumpFile: string);
951var
952 f: Text;
953begin
954 AssignFile(f, DumpFile);
955 if FileExists(DumpFile) then
956 DeleteFile(DumpFile);
957 Rewrite(f);
958 try
959 Writeln(f, DumpStr(Buffer));
960 finally
961 CloseFile(f);
962 end;
963end;
964
965{==============================================================================}
966
967procedure DumpEx(const Buffer: AnsiString; DumpFile: string);
968var
969 f: Text;
970begin
971 AssignFile(f, DumpFile);
972 if FileExists(DumpFile) then
973 DeleteFile(DumpFile);
974 Rewrite(f);
975 try
976 Writeln(f, DumpExStr(Buffer));
977 finally
978 CloseFile(f);
979 end;
980end;
981
982{==============================================================================}
983
984function TrimSPLeft(const S: string): string;
985var
986 I, L: Integer;
987begin
988 Result := '';
989 if S = '' then
990 Exit;
991 L := Length(S);
992 I := 1;
993 while (I <= L) and (S[I] = ' ') do
994 Inc(I);
995 Result := Copy(S, I, Maxint);
996end;
997
998{==============================================================================}
999
1000function TrimSPRight(const S: string): string;
1001var
1002 I: Integer;
1003begin
1004 Result := '';
1005 if S = '' then
1006 Exit;
1007 I := Length(S);
1008 while (I > 0) and (S[I] = ' ') do
1009 Dec(I);
1010 Result := Copy(S, 1, I);
1011end;
1012
1013{==============================================================================}
1014
1015function TrimSP(const S: string): string;
1016begin
1017 Result := TrimSPLeft(s);
1018 Result := TrimSPRight(Result);
1019end;
1020
1021{==============================================================================}
1022
1023function SeparateLeft(const Value, Delimiter: string): string;
1024var
1025 x: Integer;
1026begin
1027 x := Pos(Delimiter, Value);
1028 if x < 1 then
1029 Result := Value
1030 else
1031 Result := Copy(Value, 1, x - 1);
1032end;
1033
1034{==============================================================================}
1035
1036function SeparateRight(const Value, Delimiter: string): string;
1037var
1038 x: Integer;
1039begin
1040 x := Pos(Delimiter, Value);
1041 if x > 0 then
1042 x := x + Length(Delimiter) - 1;
1043 Result := Copy(Value, x + 1, Length(Value) - x);
1044end;
1045
1046{==============================================================================}
1047
1048function GetParameter(const Value, Parameter: string): string;
1049var
1050 s: string;
1051 v: string;
1052begin
1053 Result := '';
1054 v := Value;
1055 while v <> '' do
1056 begin
1057 s := Trim(FetchEx(v, ';', '"'));
1058 if Pos(Uppercase(parameter), Uppercase(s)) = 1 then
1059 begin
1060 Delete(s, 1, Length(Parameter));
1061 s := Trim(s);
1062 if s = '' then
1063 Break;
1064 if s[1] = '=' then
1065 begin
1066 Result := Trim(SeparateRight(s, '='));
1067 Result := UnquoteStr(Result, '"');
1068 break;
1069 end;
1070 end;
1071 end;
1072end;
1073
1074{==============================================================================}
1075
1076procedure ParseParametersEx(Value, Delimiter: string; const Parameters: TStrings);
1077var
1078 s: string;
1079begin
1080 Parameters.Clear;
1081 while Value <> '' do
1082 begin
1083 s := Trim(FetchEx(Value, Delimiter, '"'));
1084 Parameters.Add(s);
1085 end;
1086end;
1087
1088{==============================================================================}
1089
1090procedure ParseParameters(Value: string; const Parameters: TStrings);
1091begin
1092 ParseParametersEx(Value, ';', Parameters);
1093end;
1094
1095{==============================================================================}
1096
1097function IndexByBegin(Value: string; const List: TStrings): integer;
1098var
1099 n: integer;
1100 s: string;
1101begin
1102 Result := -1;
1103 Value := uppercase(Value);
1104 for n := 0 to List.Count -1 do
1105 begin
1106 s := UpperCase(List[n]);
1107 if Pos(Value, s) = 1 then
1108 begin
1109 Result := n;
1110 Break;
1111 end;
1112 end;
1113end;
1114
1115{==============================================================================}
1116
1117function GetEmailAddr(const Value: string): string;
1118var
1119 s: string;
1120begin
1121 s := SeparateRight(Value, '<');
1122 s := SeparateLeft(s, '>');
1123 Result := Trim(s);
1124end;
1125
1126{==============================================================================}
1127
1128function GetEmailDesc(Value: string): string;
1129var
1130 s: string;
1131begin
1132 Value := Trim(Value);
1133 s := SeparateRight(Value, '"');
1134 if s <> Value then
1135 s := SeparateLeft(s, '"')
1136 else
1137 begin
1138 s := SeparateLeft(Value, '<');
1139 if s = Value then
1140 begin
1141 s := SeparateRight(Value, '(');
1142 if s <> Value then
1143 s := SeparateLeft(s, ')')
1144 else
1145 s := '';
1146 end;
1147 end;
1148 Result := Trim(s);
1149end;
1150
1151{==============================================================================}
1152
1153function StrToHex(const Value: Ansistring): string;
1154var
1155 n: Integer;
1156begin
1157 Result := '';
1158 for n := 1 to Length(Value) do
1159 Result := Result + IntToHex(Byte(Value[n]), 2);
1160 Result := LowerCase(Result);
1161end;
1162
1163{==============================================================================}
1164
1165function IntToBin(Value: Integer; Digits: Byte): string;
1166var
1167 x, y, n: Integer;
1168begin
1169 Result := '';
1170 x := Value;
1171 repeat
1172 y := x mod 2;
1173 x := x div 2;
1174 if y > 0 then
1175 Result := '1' + Result
1176 else
1177 Result := '0' + Result;
1178 until x = 0;
1179 x := Length(Result);
1180 for n := x to Digits - 1 do
1181 Result := '0' + Result;
1182end;
1183
1184{==============================================================================}
1185
1186function BinToInt(const Value: string): Integer;
1187var
1188 n: Integer;
1189begin
1190 Result := 0;
1191 for n := 1 to Length(Value) do
1192 begin
1193 if Value[n] = '0' then
1194 Result := Result * 2
1195 else
1196 if Value[n] = '1' then
1197 Result := Result * 2 + 1
1198 else
1199 Break;
1200 end;
1201end;
1202
1203{==============================================================================}
1204
1205function ParseURL(URL: string; var Prot, User, Pass, Host, Port, Path,
1206 Para: string): string;
1207var
1208 x, y: Integer;
1209 sURL: string;
1210 s: string;
1211 s1, s2: string;
1212begin
1213 Prot := 'http';
1214 User := '';
1215 Pass := '';
1216 Port := '80';
1217 Para := '';
1218
1219 x := Pos('://', URL);
1220 if x > 0 then
1221 begin
1222 Prot := SeparateLeft(URL, '://');
1223 sURL := SeparateRight(URL, '://');
1224 end
1225 else
1226 sURL := URL;
1227 if UpperCase(Prot) = 'HTTPS' then
1228 Port := '443';
1229 if UpperCase(Prot) = 'FTP' then
1230 Port := '21';
1231 x := Pos('@', sURL);
1232 y := Pos('/', sURL);
1233 if (x > 0) and ((x < y) or (y < 1))then
1234 begin
1235 s := SeparateLeft(sURL, '@');
1236 sURL := SeparateRight(sURL, '@');
1237 x := Pos(':', s);
1238 if x > 0 then
1239 begin
1240 User := SeparateLeft(s, ':');
1241 Pass := SeparateRight(s, ':');
1242 end
1243 else
1244 User := s;
1245 end;
1246 x := Pos('/', sURL);
1247 if x > 0 then
1248 begin
1249 s1 := SeparateLeft(sURL, '/');
1250 s2 := SeparateRight(sURL, '/');
1251 end
1252 else
1253 begin
1254 s1 := sURL;
1255 s2 := '';
1256 end;
1257 if Pos('[', s1) = 1 then
1258 begin
1259 Host := Separateleft(s1, ']');
1260 Delete(Host, 1, 1);
1261 s1 := SeparateRight(s1, ']');
1262 if Pos(':', s1) = 1 then
1263 Port := SeparateRight(s1, ':');
1264 end
1265 else
1266 begin
1267 x := Pos(':', s1);
1268 if x > 0 then
1269 begin
1270 Host := SeparateLeft(s1, ':');
1271 Port := SeparateRight(s1, ':');
1272 end
1273 else
1274 Host := s1;
1275 end;
1276 Result := '/' + s2;
1277 x := Pos('?', s2);
1278 if x > 0 then
1279 begin
1280 Path := '/' + SeparateLeft(s2, '?');
1281 Para := SeparateRight(s2, '?');
1282 end
1283 else
1284 Path := '/' + s2;
1285 if Host = '' then
1286 Host := 'localhost';
1287end;
1288
1289{==============================================================================}
1290
1291function ReplaceString(Value, Search, Replace: AnsiString): AnsiString;
1292var
1293 x, l, ls, lr: Integer;
1294begin
1295 if (Value = '') or (Search = '') then
1296 begin
1297 Result := Value;
1298 Exit;
1299 end;
1300 ls := Length(Search);
1301 lr := Length(Replace);
1302 Result := '';
1303 x := Pos(Search, Value);
1304 while x > 0 do
1305 begin
1306 {$IFNDEF CIL}
1307 l := Length(Result);
1308 SetLength(Result, l + x - 1);
1309 Move(Pointer(Value)^, Pointer(@Result[l + 1])^, x - 1);
1310 {$ELSE}
1311 Result:=Result+Copy(Value,1,x-1);
1312 {$ENDIF}
1313 {$IFNDEF CIL}
1314 l := Length(Result);
1315 SetLength(Result, l + lr);
1316 Move(Pointer(Replace)^, Pointer(@Result[l + 1])^, lr);
1317 {$ELSE}
1318 Result:=Result+Replace;
1319 {$ENDIF}
1320 Delete(Value, 1, x - 1 + ls);
1321 x := Pos(Search, Value);
1322 end;
1323 Result := Result + Value;
1324end;
1325
1326{==============================================================================}
1327
1328function RPosEx(const Sub, Value: string; From: integer): Integer;
1329var
1330 n: Integer;
1331 l: Integer;
1332begin
1333 result := 0;
1334 l := Length(Sub);
1335 for n := From - l + 1 downto 1 do
1336 begin
1337 if Copy(Value, n, l) = Sub then
1338 begin
1339 result := n;
1340 break;
1341 end;
1342 end;
1343end;
1344
1345{==============================================================================}
1346
1347function RPos(const Sub, Value: String): Integer;
1348begin
1349 Result := RPosEx(Sub, Value, Length(Value));
1350end;
1351
1352{==============================================================================}
1353
1354function FetchBin(var Value: string; const Delimiter: string): string;
1355var
1356 s: string;
1357begin
1358 Result := SeparateLeft(Value, Delimiter);
1359 s := SeparateRight(Value, Delimiter);
1360 if s = Value then
1361 Value := ''
1362 else
1363 Value := s;
1364end;
1365
1366{==============================================================================}
1367
1368function Fetch(var Value: string; const Delimiter: string): string;
1369begin
1370 Result := FetchBin(Value, Delimiter);
1371 Result := TrimSP(Result);
1372 Value := TrimSP(Value);
1373end;
1374
1375{==============================================================================}
1376
1377function FetchEx(var Value: string; const Delimiter, Quotation: string): string;
1378var
1379 b: Boolean;
1380begin
1381 Result := '';
1382 b := False;
1383 while Length(Value) > 0 do
1384 begin
1385 if b then
1386 begin
1387 if Pos(Quotation, Value) = 1 then
1388 b := False;
1389 Result := Result + Value[1];
1390 Delete(Value, 1, 1);
1391 end
1392 else
1393 begin
1394 if Pos(Delimiter, Value) = 1 then
1395 begin
1396 Delete(Value, 1, Length(delimiter));
1397 break;
1398 end;
1399 b := Pos(Quotation, Value) = 1;
1400 Result := Result + Value[1];
1401 Delete(Value, 1, 1);
1402 end;
1403 end;
1404end;
1405
1406{==============================================================================}
1407
1408function IsBinaryString(const Value: string): Boolean;
1409var
1410 n: integer;
1411begin
1412 Result := False;
1413 for n := 1 to Length(Value) do
1414 if Value[n] in [#0..#8, #10..#31] then
1415 //ignore null-terminated strings
1416 if not ((n = Length(value)) and (Value[n] = #0)) then
1417 begin
1418 Result := True;
1419 Break;
1420 end;
1421end;
1422
1423{==============================================================================}
1424
1425function PosCRLF(const Value: AnsiString; var Terminator: AnsiString): integer;
1426var
1427 n, l: integer;
1428begin
1429 Result := -1;
1430 Terminator := '';
1431 l := length(value);
1432 for n := 1 to l do
1433 if value[n] in [#$0d, #$0a] then
1434 begin
1435 Result := n;
1436 Terminator := Value[n];
1437 if n <> l then
1438 case value[n] of
1439 #$0d:
1440 if value[n + 1] = #$0a then
1441 Terminator := #$0d + #$0a;
1442 #$0a:
1443 if value[n + 1] = #$0d then
1444 Terminator := #$0a + #$0d;
1445 end;
1446 Break;
1447 end;
1448end;
1449
1450{==============================================================================}
1451
1452Procedure StringsTrim(const Value: TStrings);
1453var
1454 n: integer;
1455begin
1456 for n := Value.Count - 1 downto 0 do
1457 if Value[n] = '' then
1458 Value.Delete(n)
1459 else
1460 Break;
1461end;
1462
1463{==============================================================================}
1464
1465function PosFrom(const SubStr, Value: String; From: integer): integer;
1466var
1467 ls,lv: integer;
1468begin
1469 Result := 0;
1470 ls := Length(SubStr);
1471 lv := Length(Value);
1472 if (ls = 0) or (lv = 0) then
1473 Exit;
1474 if From < 1 then
1475 From := 1;
1476 while (ls + from - 1) <= (lv) do
1477 begin
1478 {$IFNDEF CIL}
1479 if CompareMem(@SubStr[1],@Value[from],ls) then
1480 {$ELSE}
1481 if SubStr = copy(Value, from, ls) then
1482 {$ENDIF}
1483 begin
1484 result := from;
1485 break;
1486 end
1487 else
1488 inc(from);
1489 end;
1490end;
1491
1492{==============================================================================}
1493
1494{$IFNDEF CIL}
1495function IncPoint(const p: pointer; Value: integer): pointer;
1496begin
1497 Result := PAnsiChar(p) + Value;
1498end;
1499{$ENDIF}
1500
1501{==============================================================================}
1502//improved by 'DoggyDawg'
1503function GetBetween(const PairBegin, PairEnd, Value: string): string;
1504var
1505 n: integer;
1506 x: integer;
1507 s: string;
1508 lenBegin: integer;
1509 lenEnd: integer;
1510 str: string;
1511 max: integer;
1512begin
1513 lenBegin := Length(PairBegin);
1514 lenEnd := Length(PairEnd);
1515 n := Length(Value);
1516 if (Value = PairBegin + PairEnd) then
1517 begin
1518 Result := '';//nothing between
1519 exit;
1520 end;
1521 if (n < lenBegin + lenEnd) then
1522 begin
1523 Result := Value;
1524 exit;
1525 end;
1526 s := SeparateRight(Value, PairBegin);
1527 if (s = Value) then
1528 begin
1529 Result := Value;
1530 exit;
1531 end;
1532 n := Pos(PairEnd, s);
1533 if (n = 0) then
1534 begin
1535 Result := Value;
1536 exit;
1537 end;
1538 Result := '';
1539 x := 1;
1540 max := Length(s) - lenEnd + 1;
1541 for n := 1 to max do
1542 begin
1543 str := copy(s, n, lenEnd);
1544 if (str = PairEnd) then
1545 begin
1546 Dec(x);
1547 if (x <= 0) then
1548 Break;
1549 end;
1550 str := copy(s, n, lenBegin);
1551 if (str = PairBegin) then
1552 Inc(x);
1553 Result := Result + s[n];
1554 end;
1555end;
1556
1557{==============================================================================}
1558
1559function CountOfChar(const Value: string; Chr: char): integer;
1560var
1561 n: integer;
1562begin
1563 Result := 0;
1564 for n := 1 to Length(Value) do
1565 if Value[n] = chr then
1566 Inc(Result);
1567end;
1568
1569{==============================================================================}
1570// ! do not use AnsiExtractQuotedStr, it's very buggy and can crash application!
1571function UnquoteStr(const Value: string; Quote: Char): string;
1572var
1573 n: integer;
1574 inq, dq: Boolean;
1575 c, cn: char;
1576begin
1577 Result := '';
1578 if Value = '' then
1579 Exit;
1580 if Value = Quote + Quote then
1581 Exit;
1582 inq := False;
1583 dq := False;
1584 for n := 1 to Length(Value) do
1585 begin
1586 c := Value[n];
1587 if n <> Length(Value) then
1588 cn := Value[n + 1]
1589 else
1590 cn := #0;
1591 if c = quote then
1592 if dq then
1593 dq := False
1594 else
1595 if not inq then
1596 inq := True
1597 else
1598 if cn = quote then
1599 begin
1600 Result := Result + Quote;
1601 dq := True;
1602 end
1603 else
1604 inq := False
1605 else
1606 Result := Result + c;
1607 end;
1608end;
1609
1610{==============================================================================}
1611
1612function QuoteStr(const Value: string; Quote: Char): string;
1613var
1614 n: integer;
1615begin
1616 Result := '';
1617 for n := 1 to length(value) do
1618 begin
1619 Result := result + Value[n];
1620 if value[n] = Quote then
1621 Result := Result + Quote;
1622 end;
1623 Result := Quote + Result + Quote;
1624end;
1625
1626{==============================================================================}
1627
1628procedure HeadersToList(const Value: TStrings);
1629var
1630 n, x, y: integer;
1631 s: string;
1632begin
1633 for n := 0 to Value.Count -1 do
1634 begin
1635 s := Value[n];
1636 x := Pos(':', s);
1637 if x > 0 then
1638 begin
1639 y:= Pos('=',s);
1640 if not ((y > 0) and (y < x)) then
1641 begin
1642 s[x] := '=';
1643 Value[n] := s;
1644 end;
1645 end;
1646 end;
1647end;
1648
1649{==============================================================================}
1650
1651procedure ListToHeaders(const Value: TStrings);
1652var
1653 n, x: integer;
1654 s: string;
1655begin
1656 for n := 0 to Value.Count -1 do
1657 begin
1658 s := Value[n];
1659 x := Pos('=', s);
1660 if x > 0 then
1661 begin
1662 s[x] := ':';
1663 Value[n] := s;
1664 end;
1665 end;
1666end;
1667
1668{==============================================================================}
1669
1670function SwapBytes(Value: integer): integer;
1671var
1672 s: AnsiString;
1673 x, y, xl, yl: Byte;
1674begin
1675 s := CodeLongInt(Value);
1676 x := Ord(s[4]);
1677 y := Ord(s[3]);
1678 xl := Ord(s[2]);
1679 yl := Ord(s[1]);
1680 Result := ((x * 256 + y) * 65536) + (xl * 256 + yl);
1681end;
1682
1683{==============================================================================}
1684
1685function ReadStrFromStream(const Stream: TStream; len: integer): AnsiString;
1686var
1687 x: integer;
1688{$IFDEF CIL}
1689 buf: Array of Byte;
1690{$ENDIF}
1691begin
1692{$IFDEF CIL}
1693 Setlength(buf, Len);
1694 x := Stream.read(buf, Len);
1695 SetLength(buf, x);
1696 Result := StringOf(Buf);
1697{$ELSE}
1698 Setlength(Result, Len);
1699 x := Stream.read(PAnsiChar(Result)^, Len);
1700 SetLength(Result, x);
1701{$ENDIF}
1702end;
1703
1704{==============================================================================}
1705
1706procedure WriteStrToStream(const Stream: TStream; Value: AnsiString);
1707{$IFDEF CIL}
1708var
1709 buf: Array of Byte;
1710{$ENDIF}
1711begin
1712{$IFDEF CIL}
1713 buf := BytesOf(Value);
1714 Stream.Write(buf,length(Value));
1715{$ELSE}
1716 Stream.Write(PAnsiChar(Value)^, Length(Value));
1717{$ENDIF}
1718end;
1719
1720{==============================================================================}
1721function GetTempFile(const Dir, prefix: AnsiString): AnsiString;
1722{$IFNDEF FPC}
1723{$IFDEF WIN32}
1724var
1725 Path: AnsiString;
1726 x: integer;
1727{$ENDIF}
1728{$ENDIF}
1729begin
1730{$IFDEF FPC}
1731 Result := GetTempFileName(Dir, Prefix);
1732{$ELSE}
1733 {$IFNDEF WIN32}
1734 Result := tempnam(Pointer(Dir), Pointer(prefix));
1735 {$ELSE}
1736 {$IFDEF CIL}
1737 Result := System.IO.Path.GetTempFileName;
1738 {$ELSE}
1739 if Dir = '' then
1740 begin
1741 SetLength(Path, MAX_PATH);
1742 x := GetTempPath(Length(Path), PChar(Path));
1743 SetLength(Path, x);
1744 end
1745 else
1746 Path := Dir;
1747 x := Length(Path);
1748 if Path[x] <> '\' then
1749 Path := Path + '\';
1750 SetLength(Result, MAX_PATH + 1);
1751 GetTempFileName(PChar(Path), PChar(Prefix), 0, PChar(Result));
1752 Result := PChar(Result);
1753 SetFileattributes(PChar(Result), GetFileAttributes(PChar(Result)) or FILE_ATTRIBUTE_TEMPORARY);
1754 {$ENDIF}
1755 {$ENDIF}
1756{$ENDIF}
1757end;
1758
1759{==============================================================================}
1760
1761function PadString(const Value: AnsiString; len: integer; Pad: AnsiChar): AnsiString;
1762begin
1763 if length(value) >= len then
1764 Result := Copy(value, 1, len)
1765 else
1766 Result := Value + StringOfChar(Pad, len - length(value));
1767end;
1768
1769{==============================================================================}
1770
1771function NormalizeHeader(Value: TStrings; var Index: Integer): string;
1772var
1773 s, t: string;
1774 n: Integer;
1775begin
1776 s := Value[Index];
1777 Inc(Index);
1778 if s <> '' then
1779 while (Value.Count - 1) > Index do
1780 begin
1781 t := Value[Index];
1782 if t = '' then
1783 Break;
1784 for n := 1 to Length(t) do
1785 if t[n] = #9 then
1786 t[n] := ' ';
1787 if not(t[1] in [' ', '"', ':', '=']) then
1788 Break
1789 else
1790 begin
1791 s := s + ' ' + Trim(t);
1792 Inc(Index);
1793 end;
1794 end;
1795 Result := TrimRight(s);
1796end;
1797
1798{==============================================================================}
1799var
1800 n: integer;
1801begin
1802 for n := 1 to 12 do
1803 begin
1804 CustomMonthNames[n] := ShortMonthNames[n];
1805 MyMonthNames[0, n] := ShortMonthNames[n];
1806 end;
1807end.
Note: See TracBrowser for help on using the repository browser.