Recent

Author Topic: Find unknown string in a string  (Read 10069 times)

Zath

  • Sr. Member
  • ****
  • Posts: 391
Find unknown string in a string
« on: June 17, 2015, 12:55:08 am »
How do I find the red text in this string ?
The string remains static on a machine but the values in red can be different on different machines.
I'm trying to read the values in for a ADO connection and are reading in the text file with AssignFile and Reset.

Provider=SQLOLEDB.1;Password=blahblah;Persist Security Info=True;User ID=sa;

Thanks.

kpeters58

  • Sr. Member
  • ****
  • Posts: 267
Re: Find unknown string in a string
« Reply #1 on: June 17, 2015, 01:14:57 am »
there are many ways to skin that cat....

here's one of them:

Code: [Select]
function TForm1.GetValueForKey(const Key: String): String;
const
   S = 'Provider=SQLOLEDB.1;Password=blahblah;Persist Security Info=True;User ID=sa;';
var
  str:      String;
  sl:       TStringList;

begin
  Result := '';
  str    := StringReplace(S, ';', ',', [rfReplaceAll]);
  sl     := TStringList.Create;
  try
    sl.CommaText := str;
    Result := sl.Values[Key];
  finally
    if Assigned(sl) then
      sl.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Showmessage('Password: ' + GetValueForKey('Password'));
end;
Lazarus 2.0.4/FPC 3.0.4/Win 64

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Re: Find unknown string in a string
« Reply #2 on: June 17, 2015, 01:17:22 am »
TSttringList has properties Delimiter and DelimitedText so there is no need to change semicolons to commas.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

kpeters58

  • Sr. Member
  • ****
  • Posts: 267
Re: Find unknown string in a string
« Reply #3 on: June 17, 2015, 01:45:19 am »
setting DelimitedText calls StringReplace itself and does a lot of other things as well.... should be quite a bit slower from the looks of it
Lazarus 2.0.4/FPC 3.0.4/Win 64

eny

  • Hero Member
  • *****
  • Posts: 1646
Re: Find unknown string in a string
« Reply #4 on: June 17, 2015, 03:11:39 am »
Quick and dirty:
Code: [Select]
uses StrUtils, ...;
...
procedure TfrmMain1.Button1Click(Sender: TObject);
var s : string;
    pw: string;
begin
  s := 'Provider=SQLOLEDB.1;Password=blahblah;Persist Security Info=True;User ID=sa;';
  pw := ExtractWord(2, ExtractWord(2, s, [';']), ['=']);
  ShowMessage(pw);
end;

And the actual way it should be coded:
Code: [Select]
uses RegExpr, ...;
...
procedure TfrmMain1.Button2Click(Sender: TObject);
var s : string;
    re: TRegExpr;
begin
  s := 'Provider=SQLOLEDB.1;Password=blahblah;Persist Security Info=True;User ID=sa;';
  re := TRegExpr.Create;
  re.Expression := '^Provider=(.*);Password=(.*);Persist Security Info=(.*);User ID=(.*);$';
  if re.Exec(s) then
    ShowMessage('Provider = ' + re.Match[1] + LineEnding +
                'Password = ' + re.Match[2] + LineEnding +
                'User Id  = ' + re.Match[4] );

  re.Free;
end;
« Last Edit: June 17, 2015, 03:25:42 am by eny »
All posts based on: Win10 (Win64); Lazarus 3_4  (x64) 25-05-2024 (unless specified otherwise...)

kpeters58

  • Sr. Member
  • ****
  • Posts: 267
Re: Find unknown string in a string
« Reply #5 on: June 17, 2015, 04:41:39 am »
Hmm - 'should be coded' is a rather strong expression...

Both position based methods you have suggested fail miserably if the order of parameters is changed.

Since ADO connection parameters can be specified in any order, this *should* be supported, so that users can work with any valid connection string without having to remember which parameter should be in which position so the code doesn't break....
Lazarus 2.0.4/FPC 3.0.4/Win 64

Basile B.

  • Guest
Re: Find unknown string in a string
« Reply #6 on: June 17, 2015, 06:46:43 am »
Another quick solution (among many others, as mentioned previously) is to use a TStringList to parse the text as KeyValue pairs (since you have an equal symbol, this fits perfectly):

Code: [Select]
program Project1;

uses classes;

const txt = 'Provider=SQLOLEDB.1;Password=blahblah;' +
            'Persist Security Info=True;User ID=sa;';
var
  str: TStringList;

begin
  str := TStringList.Create;
  str.Delimiter:=';';
  str.StrictDelimiter:=true;
  str.DelimitedText:= txt;
  writeln( str.Values['Provider'] );
  writeln( str.Values['Password'] );
  writeln( str.Values['Persist Security Info'] );
  writeln( str.Values['User ID'] );
  readln;
  str.Free;
end.

output:
Code: [Select]
SQLOLEDB.1
blahblah
True
sa

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Find unknown string in a string
« Reply #7 on: June 17, 2015, 07:22:12 am »
It seems to me a password that contains a semicolon might cause a problem. As in "blah;blah".

eny

  • Hero Member
  • *****
  • Posts: 1646
Re: Find unknown string in a string
« Reply #8 on: June 17, 2015, 11:23:16 am »
Hmm - 'should be coded' is a rather strong expression...
Nope.
This is the exact reason why regular expressions were introduced.

Quote
Both position based methods you have suggested fail miserably if the order of parameters is changed.
The application will crash if lightniing strikes.
So better install lightning rods too.
IOW please study https://en.wikipedia.org/?title=Regular_expression#Basic_concepts
All posts based on: Win10 (Win64); Lazarus 3_4  (x64) 25-05-2024 (unless specified otherwise...)

sfeinst

  • Full Member
  • ***
  • Posts: 237
Re: Find unknown string in a string
« Reply #9 on: June 17, 2015, 02:22:28 pm »
It seems to me a password that contains a semicolon might cause a problem. As in "blah;blah".

In a connection string, if a semicolon is part of the value (as well as a few other characters), then quotes would be used.  If the app in question must handle all values that can be in a connection string, then the use of quotes will also need to be handled by the parser.  As in your example, the actual connection string would probably end up being:
Provider=SQLOLEDB.1;Password="blah;blah";Persist Security Info=True;User ID=sa;

And if a value contains a quote, then single quotes would be used so they also need to be handled as in:
Provider=SQLOLEDB.1;Password='blah"blah';Persist Security Info=True;User ID=sa;

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Find unknown string in a string
« Reply #10 on: June 17, 2015, 03:12:36 pm »
It seems to me a password that contains a semicolon might cause a problem. As in "blah;blah".

In a connection string, if a semicolon is part of the value (as well as a few other characters), then quotes would be used.  If the app in question must handle all values that can be in a connection string, then the use of quotes will also need to be handled by the parser.  As in your example, the actual connection string would probably end up being:
Provider=SQLOLEDB.1;Password="blah;blah";Persist Security Info=True;User ID=sa;

Thank you!

And if a value contains a quote, then single quotes would be used so they also need to be handled as in:
Provider=SQLOLEDB.1;Password='blah"blah';Persist Security Info=True;User ID=sa;

It seems the rule is for when a value begins with a quote.

The rest of the rules.

sfeinst

  • Full Member
  • ***
  • Posts: 237
Re: Find unknown string in a string
« Reply #11 on: June 17, 2015, 03:29:46 pm »
This is a very quick example put together.  I'm sure someone can improve upon it.  But it should parse the conn string without regard to order and embedded values.  It assumes a proper connection string. Probably missed something though:

Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type
StrArr = Array[0..1] of string;
ConnArr = Array of StrArr;

{ TForm1 }

 TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ private declarations }
function SplitConn(AStr: string): ConnArr;
public
{ public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

function TForm1.SplitConn(AStr: string): ConnArr;
var
  ch: char;
  inval: boolean;
  inquote: boolean;
  quoteval: char;
  cnt: integer;
  start: integer;
  len: integer;
begin
  inval := false;
  inquote := false;
  quoteval := ' ';
  cnt := 0;
  start := 1;
  len := 0;
  for ch in AStr do
  begin
    if not inquote then
    begin
      if (ch = '"') or (ch = '''') then
      begin
      inquote := true;
        quoteval := ch;
        Inc(start);
      end
      else if ch = '=' then
      begin
        // end of first item
        Inc(cnt);
        SetLength(Result, cnt);
        Result[cnt-1][0] := Copy(AStr, start, len);
        inval := true;
        start := start + len + 1;
        len := 0;
      end
      else if ch = ';' then
      begin
      if inval then
        begin
          // end of second item
          Result[cnt-1][1] := Copy(AStr, start, len);
          inval := false;
          start := start + len + 1;
          len := 0;
end
        else
        // most likely semi after closing quote so skip past
          Inc(start);
      end
      else
      Inc(len);
    end
    else
    begin
      if quoteval = ch then
      begin
        // end of second item
        Result[cnt-1][1] := Copy(AStr, start, len);
        inval := false;
        start := start + len + 1;
        len := 0;
        inquote := false;
        quoteval := ' ';
      end
      else
      Inc(len);
    end;

  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  data: ConnArr;
  str: string;
  I: integer;
begin
  str := '';
  data := SplitConn(Edit1.Text);
for I := 0 to Length(data) - 1 do
    str := str + data[I][0] + ' has a value of ' + data[I][1] + LineEnding;
  Memo1.Text := str;
end;

end.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Find unknown string in a string
« Reply #12 on: June 17, 2015, 04:16:11 pm »
The problem is a bit more complex than it seems. For instance, the password can have arbitrary values. Assume it begins with both a single and a double quotes "'"blah;blah", or it contains a chain of them.

sfeinst

  • Full Member
  • ***
  • Posts: 237
Re: Find unknown string in a string
« Reply #13 on: June 17, 2015, 04:58:57 pm »
The problem is a bit more complex than it seems. For instance, the password can have arbitrary values. Assume it begins with both a single and a double quotes "'"blah;blah", or it contains a chain of them.

According to MSDN if a value contains both ' and " then whichever is used to quote the value must be doubled inside the value.  So if the value is '"blah;blah  then to quote it with double quotes, it would have to be:
"'""blah;blah"

My code does not handle that.  I'm guessing I would need to keep track of quoteval occurrences in a row before deciding it was closing the quote.  I also read somewhere that there is a possibility of keywords also being enclosed in quotes.  I'm not sure if that is true, but if it is, definitely need to change my function a lot more.

Zath

  • Sr. Member
  • ****
  • Posts: 391
Re: Find unknown string in a string
« Reply #14 on: June 17, 2015, 05:36:49 pm »
Wow, what a response !

For the record, the string will already be accurate and used to connect to the database. Unless a MS SQL database connection can use a semicolon in the password, this will not occur.

 

TinyPortal © 2005-2018