| [17] | 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 |   DotPos: longint;
 | 
|---|
 | 142 | begin
 | 
|---|
 | 143 |   result := false;
 | 
|---|
 | 144 |   // must be a @...
 | 
|---|
 | 145 |   AtPos := s.CharPosition( 0, '@' );
 | 
|---|
 | 146 |   if AtPos = -1 then
 | 
|---|
 | 147 |     // no @
 | 
|---|
 | 148 |     exit;
 | 
|---|
 | 149 |   if AtPos = 0 then
 | 
|---|
 | 150 |     // can't be the first char though
 | 
|---|
 | 151 |     exit;
 | 
|---|
 | 152 | 
 | 
|---|
 | 153 |   // there is; there must be only one though...
 | 
|---|
 | 154 |   SecondAtPos := s.CharPosition( AtPos + 1, '@' );
 | 
|---|
 | 155 |   if SecondAtPos <> -1 then
 | 
|---|
 | 156 |     // there's a second @
 | 
|---|
 | 157 |     exit;
 | 
|---|
 | 158 | 
 | 
|---|
 | 159 |   Result := IsDomainName( s, AtPos + 1 );
 | 
|---|
 | 160 | end;
 | 
|---|
 | 161 | 
 | 
|---|
 | 162 | // Returns true if S contains a URL.
 | 
|---|
 | 163 | // MAY MODIFY CONTENTS OF S
 | 
|---|
 | 164 | function IsURL( s: TAstring ): boolean;
 | 
|---|
 | 165 | begin
 | 
|---|
 | 166 |   if s.StartsWith( 'www.' ) then
 | 
|---|
 | 167 |   begin
 | 
|---|
 | 168 |     if not IsDomainName( s, 4 ) then
 | 
|---|
 | 169 |       exit;
 | 
|---|
 | 170 |     s.InsertString( 0, 'http://' );
 | 
|---|
 | 171 |     result := true;
 | 
|---|
 | 172 |     exit;
 | 
|---|
 | 173 |   end;
 | 
|---|
 | 174 | 
 | 
|---|
 | 175 |   if s.StartsWith( 'ftp.' ) then
 | 
|---|
 | 176 |   begin
 | 
|---|
 | 177 |     if not IsDomainName( s, 4 ) then
 | 
|---|
 | 178 |       exit;
 | 
|---|
 | 179 |     s.InsertString( 0, 'ftp://' );
 | 
|---|
 | 180 |     result := true;
 | 
|---|
 | 181 |     exit;
 | 
|---|
 | 182 |   end;
 | 
|---|
 | 183 | 
 | 
|---|
 | 184 |   if    S.StartsWith( 'http://' )
 | 
|---|
 | 185 |      or S.StartsWith( 'https://' )
 | 
|---|
 | 186 |      or S.StartsWith( 'ftp://' )
 | 
|---|
 | 187 |      or S.StartsWith( 'mailto:' )
 | 
|---|
 | 188 |      or S.StartsWith( 'news:' ) then
 | 
|---|
 | 189 |   begin
 | 
|---|
 | 190 |     result := true;
 | 
|---|
 | 191 |     exit;
 | 
|---|
 | 192 |   end;
 | 
|---|
 | 193 | 
 | 
|---|
 | 194 |   if IsEmailAddress( s ) then
 | 
|---|
 | 195 |   begin
 | 
|---|
 | 196 |     s.InsertString( 0, 'mailto:' );
 | 
|---|
 | 197 |     result := true;
 | 
|---|
 | 198 |     exit;
 | 
|---|
 | 199 |   end;
 | 
|---|
 | 200 | 
 | 
|---|
 | 201 |   result := false;
 | 
|---|
 | 202 | end;
 | 
|---|
 | 203 | 
 | 
|---|
 | 204 | const
 | 
|---|
 | 205 |   StartPunctuationChars: set of char =
 | 
|---|
 | 206 |     [ '(', '[', '{', '<', '''', '"' ];
 | 
|---|
 | 207 | 
 | 
|---|
 | 208 |   EndPunctuationChars: set of char =
 | 
|---|
 | 209 |     [ ')', ']', '}', '>', '''', '"', '.', ',', ':', ';', '!', '?' ];
 | 
|---|
 | 210 | 
 | 
|---|
 | 211 | procedure TrimPunctuation( s: TAString );
 | 
|---|
 | 212 | var
 | 
|---|
 | 213 |   c: char;
 | 
|---|
 | 214 |   ChangesMade: boolean;
 | 
|---|
 | 215 | begin
 | 
|---|
 | 216 |   while s.Length > 0 do
 | 
|---|
 | 217 |   begin
 | 
|---|
 | 218 |     ChangesMade := false;
 | 
|---|
 | 219 | 
 | 
|---|
 | 220 |     if s[ 0 ] in StartPunctuationChars then
 | 
|---|
 | 221 |     begin
 | 
|---|
 | 222 |       ChangesMade := true;
 | 
|---|
 | 223 |       s.Delete( 0, 1 );
 | 
|---|
 | 224 |     end;
 | 
|---|
 | 225 | 
 | 
|---|
 | 226 |     if s.Length = 0 then
 | 
|---|
 | 227 |       exit;
 | 
|---|
 | 228 | 
 | 
|---|
 | 229 |     if s[ s.Length - 1 ] in EndPunctuationChars then
 | 
|---|
 | 230 |     begin
 | 
|---|
 | 231 |       ChangesMade := true;
 | 
|---|
 | 232 |       s.Delete( s.Length - 1, 1 );
 | 
|---|
 | 233 |     end;
 | 
|---|
 | 234 | 
 | 
|---|
 | 235 |     if not ChangesMade then
 | 
|---|
 | 236 |       exit; // done
 | 
|---|
 | 237 |   end;
 | 
|---|
 | 238 | end;
 | 
|---|
 | 239 | 
 | 
|---|
 | 240 | end.
 | 
|---|