synautil.pas 47 KB

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