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