| 1 | unit AStringUtilityUnit; | 
|---|
| 2 |  | 
|---|
| 3 | // Utilities for TAString | 
|---|
| 4 |  | 
|---|
| 5 | interface | 
|---|
| 6 |  | 
|---|
| 7 | uses | 
|---|
| 8 | Classes, | 
|---|
| 9 | ACLString; | 
|---|
| 10 |  | 
|---|
| 11 | // Puts specified program command line parameter | 
|---|
| 12 | // into AString | 
|---|
| 13 | procedure AString_ParamStr( item: byte; | 
|---|
| 14 | S: TAString ); | 
|---|
| 15 |  | 
|---|
| 16 | // Splits up an AString at the given separator CHAR | 
|---|
| 17 | // Puts the individual strings into List, truncating | 
|---|
| 18 | // each string at 255 chars max. | 
|---|
| 19 | procedure AStringToList( S: TAstring; | 
|---|
| 20 | List: TStrings; | 
|---|
| 21 | const Separator: char ); | 
|---|
| 22 |  | 
|---|
| 23 | // Converts the given stringlist to an AString | 
|---|
| 24 | // with the given separator between entries | 
|---|
| 25 | procedure ListToAString( List: TStrings; | 
|---|
| 26 | S: TAstring; | 
|---|
| 27 | const Separator: char ); | 
|---|
| 28 |  | 
|---|
| 29 | // Adds the given value to an AString containing | 
|---|
| 30 | // a list with entries separated by separator | 
|---|
| 31 | Procedure AddToListAString( S: TAString; | 
|---|
| 32 | const NewValue: string; | 
|---|
| 33 | const Separator: char ); | 
|---|
| 34 |  | 
|---|
| 35 | // returns true if there appears to be a domain name | 
|---|
| 36 | // in S starting at StartingAt | 
|---|
| 37 | // must contain at least one period and | 
|---|
| 38 | // some characters before and after it. | 
|---|
| 39 | // ie. a.b | 
|---|
| 40 | function IsDomainName( s: TAstring; | 
|---|
| 41 | StartingAt: longint ): boolean; | 
|---|
| 42 |  | 
|---|
| 43 | // return true if S appears to be an email address | 
|---|
| 44 | // a@b.c | 
|---|
| 45 | function IsEmailAddress( s: TAstring ): boolean; | 
|---|
| 46 |  | 
|---|
| 47 | // Returns true if S contains a URL. | 
|---|
| 48 | // MAY MODIFY CONTENTS OF S | 
|---|
| 49 | function IsURL( s: TAstring ): boolean; | 
|---|
| 50 |  | 
|---|
| 51 | // Trims punctuation characters from start and end of s | 
|---|
| 52 | // such as braces, periods, commas. | 
|---|
| 53 | procedure TrimPunctuation( s: TAString ); | 
|---|
| 54 |  | 
|---|
| 55 | implementation | 
|---|
| 56 |  | 
|---|
| 57 | uses | 
|---|
| 58 | ACLUtility; | 
|---|
| 59 |  | 
|---|
| 60 | procedure AString_ParamStr( item: byte; | 
|---|
| 61 | S: TAString ); | 
|---|
| 62 | var | 
|---|
| 63 | p: pchar; | 
|---|
| 64 | l: longint; | 
|---|
| 65 | begin | 
|---|
| 66 | GetCommandLineParameter( item, p, l ); | 
|---|
| 67 | S.AssignPCharLen( p, l ); | 
|---|
| 68 | end; | 
|---|
| 69 |  | 
|---|
| 70 | procedure AStringToList( S: TAstring; | 
|---|
| 71 | List: TStrings; | 
|---|
| 72 | const Separator: char ); | 
|---|
| 73 | var | 
|---|
| 74 | Item: TAString; | 
|---|
| 75 | i: longint; | 
|---|
| 76 | begin | 
|---|
| 77 | List.Clear; | 
|---|
| 78 | Item := TAString.Create; | 
|---|
| 79 |  | 
|---|
| 80 | i := 0; | 
|---|
| 81 | while i < S.Length do | 
|---|
| 82 | begin | 
|---|
| 83 | S.ExtractNextValue( i, Item, Separator ); | 
|---|
| 84 | List.Add( Item.AsString ); | 
|---|
| 85 | end; | 
|---|
| 86 |  | 
|---|
| 87 | Item.Destroy; | 
|---|
| 88 | end; | 
|---|
| 89 |  | 
|---|
| 90 | Procedure AddToListAString( S: TAString; | 
|---|
| 91 | const NewValue: string; | 
|---|
| 92 | const Separator: char ); | 
|---|
| 93 | Begin | 
|---|
| 94 | if S.Length > 0 then | 
|---|
| 95 | S.AddString( Separator ); | 
|---|
| 96 | S.AddString( NewValue ); | 
|---|
| 97 | End; | 
|---|
| 98 |  | 
|---|
| 99 | procedure ListToAString( List: TStrings; | 
|---|
| 100 | S: TAstring; | 
|---|
| 101 | const Separator: char ); | 
|---|
| 102 | Var | 
|---|
| 103 | i: longint; | 
|---|
| 104 | Begin | 
|---|
| 105 | S.Clear; | 
|---|
| 106 | for i := 0 to List.Count - 1 do | 
|---|
| 107 | AddToListAString( S, List[ i ], Separator ); | 
|---|
| 108 | End; | 
|---|
| 109 |  | 
|---|
| 110 | function IsDomainName( s: TAstring; | 
|---|
| 111 | StartingAt: longint ): boolean; | 
|---|
| 112 | var | 
|---|
| 113 | DotPos: longint; | 
|---|
| 114 | begin | 
|---|
| 115 | Result := false; | 
|---|
| 116 |  | 
|---|
| 117 | // must be a dot in the domain... | 
|---|
| 118 | DotPos := s.CharPosition( StartingAt, '.' ); | 
|---|
| 119 | if DotPos = -1 then | 
|---|
| 120 | // nope | 
|---|
| 121 | exit; | 
|---|
| 122 |  | 
|---|
| 123 | // must be some text between start and dot, | 
|---|
| 124 | // and between dot and end | 
|---|
| 125 | // ie. a.b not .b or a. | 
|---|
| 126 |  | 
|---|
| 127 | if DotPos = StartingAt then | 
|---|
| 128 | // no a | 
|---|
| 129 | exit; | 
|---|
| 130 | if DotPos = s.Length - 1 then | 
|---|
| 131 | // no b; | 
|---|
| 132 | exit; | 
|---|
| 133 |  | 
|---|
| 134 | Result := true; | 
|---|
| 135 | end; | 
|---|
| 136 |  | 
|---|
| 137 | function IsEmailAddress( s: TAstring ): boolean; | 
|---|
| 138 | var | 
|---|
| 139 | AtPos: longint; | 
|---|
| 140 | SecondAtPos: longint; | 
|---|
| 141 | begin | 
|---|
| 142 | result := false; | 
|---|
| 143 | // must be a @... | 
|---|
| 144 | AtPos := s.CharPosition( 0, '@' ); | 
|---|
| 145 | if AtPos = -1 then | 
|---|
| 146 | // no @ | 
|---|
| 147 | exit; | 
|---|
| 148 | if AtPos = 0 then | 
|---|
| 149 | // can't be the first char though | 
|---|
| 150 | exit; | 
|---|
| 151 |  | 
|---|
| 152 | // there is; there must be only one though... | 
|---|
| 153 | SecondAtPos := s.CharPosition( AtPos + 1, '@' ); | 
|---|
| 154 | if SecondAtPos <> -1 then | 
|---|
| 155 | // there's a second @ | 
|---|
| 156 | exit; | 
|---|
| 157 |  | 
|---|
| 158 | Result := IsDomainName( s, AtPos + 1 ); | 
|---|
| 159 | end; | 
|---|
| 160 |  | 
|---|
| 161 | // Returns true if S contains a URL. | 
|---|
| 162 | // MAY MODIFY CONTENTS OF S | 
|---|
| 163 | function IsURL( s: TAstring ): boolean; | 
|---|
| 164 | begin | 
|---|
| 165 | if s.StartsWith( 'www.' ) then | 
|---|
| 166 | begin | 
|---|
| 167 | if not IsDomainName( s, 4 ) then | 
|---|
| 168 | exit; | 
|---|
| 169 | s.InsertString( 0, 'http://' ); | 
|---|
| 170 | result := true; | 
|---|
| 171 | exit; | 
|---|
| 172 | end; | 
|---|
| 173 |  | 
|---|
| 174 | if s.StartsWith( 'ftp.' ) then | 
|---|
| 175 | begin | 
|---|
| 176 | if not IsDomainName( s, 4 ) then | 
|---|
| 177 | exit; | 
|---|
| 178 | s.InsertString( 0, 'ftp://' ); | 
|---|
| 179 | result := true; | 
|---|
| 180 | exit; | 
|---|
| 181 | end; | 
|---|
| 182 |  | 
|---|
| 183 | if    S.StartsWith( 'http://' ) | 
|---|
| 184 | or S.StartsWith( 'https://' ) | 
|---|
| 185 | or S.StartsWith( 'ftp://' ) | 
|---|
| 186 | or S.StartsWith( 'mailto:' ) | 
|---|
| 187 | or S.StartsWith( 'news:' ) then | 
|---|
| 188 | begin | 
|---|
| 189 | result := true; | 
|---|
| 190 | exit; | 
|---|
| 191 | end; | 
|---|
| 192 |  | 
|---|
| 193 | if IsEmailAddress( s ) then | 
|---|
| 194 | begin | 
|---|
| 195 | s.InsertString( 0, 'mailto:' ); | 
|---|
| 196 | result := true; | 
|---|
| 197 | exit; | 
|---|
| 198 | end; | 
|---|
| 199 |  | 
|---|
| 200 | result := false; | 
|---|
| 201 | end; | 
|---|
| 202 |  | 
|---|
| 203 | const | 
|---|
| 204 | StartPunctuationChars: set of char = | 
|---|
| 205 | [ '(', '[', '{', '<', '''', '"' ]; | 
|---|
| 206 |  | 
|---|
| 207 | EndPunctuationChars: set of char = | 
|---|
| 208 | [ ')', ']', '}', '>', '''', '"', '.', ',', ':', ';', '!', '?' ]; | 
|---|
| 209 |  | 
|---|
| 210 | procedure TrimPunctuation( s: TAString ); | 
|---|
| 211 | var | 
|---|
| 212 | ChangesMade: boolean; | 
|---|
| 213 | begin | 
|---|
| 214 | while s.Length > 0 do | 
|---|
| 215 | begin | 
|---|
| 216 | ChangesMade := false; | 
|---|
| 217 |  | 
|---|
| 218 | if s[ 0 ] in StartPunctuationChars then | 
|---|
| 219 | begin | 
|---|
| 220 | ChangesMade := true; | 
|---|
| 221 | s.Delete( 0, 1 ); | 
|---|
| 222 | end; | 
|---|
| 223 |  | 
|---|
| 224 | if s.Length = 0 then | 
|---|
| 225 | exit; | 
|---|
| 226 |  | 
|---|
| 227 | if s[ s.Length - 1 ] in EndPunctuationChars then | 
|---|
| 228 | begin | 
|---|
| 229 | ChangesMade := true; | 
|---|
| 230 | s.Delete( s.Length - 1, 1 ); | 
|---|
| 231 | end; | 
|---|
| 232 |  | 
|---|
| 233 | if not ChangesMade then | 
|---|
| 234 | exit; // done | 
|---|
| 235 | end; | 
|---|
| 236 | end; | 
|---|
| 237 |  | 
|---|
| 238 | end. | 
|---|