Results 1 to 5 of 5

Thread: QRegularExpressionValidator: am I missing something?!

  1. #1
    Join Date
    Mar 2010
    Posts
    319
    Thanks
    1
    Thanked 14 Times in 12 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Question QRegularExpressionValidator: am I missing something?!

    Hi,

    I am trying to validate (using QRegularExpressionValidator) a URL. It got the regular expression from https://gist.github.com/dperini/729294 and, from what I can tell, it looks good (and it certainly seems to work when I tried using some online regular expression testers). However, my tests using Qt are anything but conclusive. So, could it be that I wrongly 'converted' the regular expression to C++?

    Otherwise, worse is the fact that if I try to enter something like "http://uuuuuuuuuuuuuuuuuuuu", then my test application kind of hangs up. In fact, if I run it in debug mode and pause it, I can see that QRegularExpressionValidator::validate() makes an indirect call to pcre16_exec, which itself makes call to match, which itself makes call to match, which itself makes call to match, etc. Could this be a bug in QRegularExpressionValidator or even pcre16_exec?

    QRegularExpressionValidatorTest.pro:

    Qt Code:
    1. QT += core gui
    2.  
    3. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    4.  
    5. TARGET = QRegularExpressionValidatorTest
    6. TEMPLATE = app
    7.  
    8. SOURCES += main.cpp
    To copy to clipboard, switch view to plain text mode 

    main.cpp:

    Qt Code:
    1. #include <QApplication>
    2. #include <QDesktopWidget>
    3. #include <QDialog>
    4. #include <QLineEdit>
    5. #include <QRegularExpressionValidator>
    6. #include <QVBoxLayout>
    7.  
    8. int main(int pArgC, char *pArgV[])
    9. {
    10. QApplication application(pArgC, pArgV);
    11.  
    12. QDialog *dialog = new QDialog();
    13. QVBoxLayout *dialogLayout = new QVBoxLayout(dialog);
    14.  
    15. dialog->setLayout(dialogLayout);
    16. dialog->setWindowTitle("URL Tester");
    17.  
    18. // We want to validate a URL, the regular expression of which comes from
    19. // https://gist.github.com/dperini/729294
    20. // It is released under the MIT license and is therefore fine for us to use
    21.  
    22. QString urlRegExp = QString() +
    23. "^"
    24. // protocol identifier
    25. "(?:(?:https?|ftp)://)" +
    26. // user:pass authentication
    27. "(?:\\S+(?::\\S*)?@)?" +
    28. "(?:" +
    29. // IP address exclusion
    30. // private & local networks
    31. "(?!(?:10|127)(?:\\.\\d{1,3}){3})" +
    32. "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" +
    33. "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" +
    34. // IP address dotted notation octets
    35. // excludes loopback network 0.0.0.0
    36. // excludes reserved space >= 224.0.0.0
    37. // excludes network & broacast addresses
    38. // (first & last IP address of each class)
    39. "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
    40. "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
    41. "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
    42. "|" +
    43. // host name
    44. "(?:(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)" +
    45. // domain name
    46. "(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)*" +
    47. // TLD identifier
    48. "(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}]{2,}))" +
    49. ")" +
    50. // port number
    51. "(?::\\d{2,5})?" +
    52. // resource path
    53. "(?:/[^\\s]*)?" +
    54. "$";
    55.  
    56. QLineEdit *dialogValue = new QLineEdit(dialog);
    57.  
    58. dialogValue->setValidator(new QRegularExpressionValidator(QRegularExpression(urlRegExp, QRegularExpression::CaseInsensitiveOption), dialog));
    59. dialogValue->setMinimumWidth(qApp->desktop()->availableGeometry().width()/5);
    60.  
    61. dialogLayout->addWidget(dialogValue);
    62.  
    63. dialogLayout->setSizeConstraint(QLayout::SetFixedSize);
    64.  
    65. dialog->show();
    66.  
    67. return application.exec();
    68. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: QRegularExpressionValidator: am I missing something?!

    This code runs fine for me on Linux:
    Qt Code:
    1. #include <QCoreApplication>
    2. #include <QRegularExpression>
    3. #include <QRegularExpressionValidator>
    4. #include <QDebug>
    5.  
    6. int main(int argc, char **argv)
    7. {
    8. QCoreApplication application(argc, argv);
    9.  
    10. // We want to validate a URL, the regular expression of which comes from
    11. // https://gist.github.com/dperini/729294
    12. // It is released under the MIT license and is therefore fine for us to use
    13.  
    14. const QString urlRegExp = "^"
    15. // protocol identifier
    16. "(?:(?:https?|ftp)://)"
    17. // user:pass authentication
    18. "(?:\\S+(?::\\S*)?@)?"
    19. "(?:"
    20. // IP address exclusion
    21. // private & local networks
    22. "(?!(?:10|127)(?:\\.\\d{1,3}){3})"
    23. "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})"
    24. "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})"
    25. // IP address dotted notation octets
    26. // excludes loopback network 0.0.0.0
    27. // excludes reserved space >= 224.0.0.0
    28. // excludes network & broacast addresses
    29. // (first & last IP address of each class)
    30. "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])"
    31. "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}"
    32. "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))"
    33. "|"
    34. // host name
    35. "(?:(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)"
    36. // domain name
    37. "(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)*"
    38. // TLD identifier
    39. "(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}]{2,}))"
    40. ")"
    41. // port number
    42. "(?::\\d{2,5})?"
    43. // resource path
    44. "(?:/[^\\s]*)?"
    45. "$";
    46.  
    47.  
    48. QRegularExpression re(urlRegExp, QRegularExpression::CaseInsensitiveOption);
    49. qDebug() << re.isValid(); // true
    50.  
    51. QString testString("http://uuuuuuuuuuuuuuuuuuuuuuuuu");
    52. QRegularExpressionMatch match = re.match(testString);
    53. qDebug() << match; // QRegularExpressionMatch(Valid, no match)
    54.  
    55. QRegularExpressionValidator validator(re);
    56. int pos = 0;
    57. qDebug() << validator.validate(testString, pos); // 0 == QValidator::Invalid
    58.  
    59.  
    60. // Just for kicks:
    61. QUrl url(testString, QUrl::StrictMode);
    62. qDebug() << url << url.isValid(); // QUrl( "http://uuuuuuuuuuuuuuuuuuuuuuuuu" ) true
    63.  
    64. return 0;
    65. }
    To copy to clipboard, switch view to plain text mode 

    Note that I constructed the regular expression string using C++ string literal concatenation rather than your QString operators not that I expect that to be of any consequence. I say "runs fine" not "works fine" because the test string is a valid URL.

    Is there a reason you cannot use QUrl to do the validation work for you?

  3. #3
    Join Date
    Mar 2010
    Posts
    319
    Thanks
    1
    Thanked 14 Times in 12 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QRegularExpressionValidator: am I missing something?!

    Note that I constructed the regular expression string using C++ string literal concatenation rather than your QString operators not that I expect that to be of any consequence.
    Indeed, I have just replaced 'my' version with yours and, as expected, it didn't make any difference.

    I say "runs fine" not "works fine" because the test string is a valid URL.
    Yes, everything runs fine indeed.

    Is there a reason you cannot use QUrl to do the validation work for you?
    Maybe, I am not sure. The fact is that I need the user to enter the URL. So, for this, I am using QLineEdit and I thought I would validate the user's entry as he enters it. Hence, my use QRegularExpressionValidator as a validator for QLineEdit. Now, are you implying that there is a way to achieve the same using QUrl as some kind of a validator? If so, I imagine that I would need to create my own validator and make it use QUrl to do the validation?

  4. #4
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: QRegularExpressionValidator: am I missing something?!

    The behaviour I see with your original code is that the line edit stops accepting more characters after the 20th 'u' is typed (making the total string length 26). It doesn't hang, backspace works for example. Once the validator stops returning Intermediate and starts returning Invalid the characters get dropped. A quick tweak of my code, shows the validator changing its mind:
    Qt Code:
    1. QString testString("http://");
    2. for (int i = 0; i < 32; ++i) {
    3. testString += "a";
    4. QRegularExpressionValidator validator(re);
    5. int pos = 0;
    6. qDebug() << (i+1) << testString << validator.validate(testString, pos);
    7. }
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. 1 "http://a" 1
    2. 2 "http://aa" 1
    3. 3 "http://aaa" 1
    4. 4 "http://aaaa" 1
    5. 5 "http://aaaaa" 1
    6. 6 "http://aaaaaa" 1
    7. 7 "http://aaaaaaa" 1
    8. 8 "http://aaaaaaaa" 1
    9. 9 "http://aaaaaaaaa" 1
    10. 10 "http://aaaaaaaaaa" 1
    11. 11 "http://aaaaaaaaaaa" 1
    12. 12 "http://aaaaaaaaaaaa" 1
    13. 13 "http://aaaaaaaaaaaaa" 1
    14. 14 "http://aaaaaaaaaaaaaa" 1
    15. 15 "http://aaaaaaaaaaaaaaa" 1
    16. 16 "http://aaaaaaaaaaaaaaaa" 1
    17. 17 "http://aaaaaaaaaaaaaaaaa" 1
    18. 18 "http://aaaaaaaaaaaaaaaaaa" 1
    19. 19 "http://aaaaaaaaaaaaaaaaaaa" 1
    20. 20 "http://aaaaaaaaaaaaaaaaaaaa" 1
    21. 21 "http://aaaaaaaaaaaaaaaaaaaaa" 0
    22. 22 "http://aaaaaaaaaaaaaaaaaaaaaa" 0
    23. 23 "http://aaaaaaaaaaaaaaaaaaaaaaa" 0
    24. 24 "http://aaaaaaaaaaaaaaaaaaaaaaaa" 0
    25. 25 "http://aaaaaaaaaaaaaaaaaaaaaaaaa" 0
    26. 26 "http://aaaaaaaaaaaaaaaaaaaaaaaaaa" 0
    27. 27 "http://aaaaaaaaaaaaaaaaaaaaaaaaaaa" 0
    28. 28 "http://aaaaaaaaaaaaaaaaaaaaaaaaaaaa" 0
    29. 29 "http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 0
    30. 30 "http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 0
    31. 31 "http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 0
    32. 32 "http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 0
    To copy to clipboard, switch view to plain text mode 
    It also gets progressively slower as the string gets longer. Even with 32 'a' chars, adding ".com" will validate (you cannot do it through the line edit though). I can see no reason for this behaviour. It might be some sort of recursion limit in the regex library.

    If so, I imagine that I would need to create my own validator and make it use QUrl to do the validation?
    Yes. Using QUrl will only give Invalid/Valid indication, where a QRegularExpression based approach can give an Intermediate indication for hasPartialMatch().

  5. #5
    Join Date
    Mar 2010
    Posts
    319
    Thanks
    1
    Thanked 14 Times in 12 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QRegularExpressionValidator: am I missing something?!

    I tried the validation using QUrl and it's not sufficient for what I need. As you wrote, a QRegularExpression-based approach allows for intermediate state, which is useful. Also, I noticed that QUrl is too clever when it comes to validation. I mean that it will try to correct a user's mistake if it can. Anyway, QUrl validation is not an option.

    Regarding QRegularExpressionValidator, there is clearly something 'funny' going on, which is the reason I decided to create a bug report for it: https://bugreports.qt-project.org/browse/QTBUG-38034.

Similar Threads

  1. qgif.lib missing
    By stef13013 in forum Qt Programming
    Replies: 0
    Last Post: 18th September 2012, 22:17
  2. setCurveType missing in Qwt 6.0.1?
    By chinalski in forum Qwt
    Replies: 6
    Last Post: 26th February 2012, 15:36
  3. Mac OSX: missing executable ?
    By Hiwa in forum Qt Tools
    Replies: 2
    Last Post: 22nd April 2011, 15:02
  4. Qt Creator Help missing? (QT 2010.02)
    By Asperamanca in forum Qt Tools
    Replies: 0
    Last Post: 22nd July 2010, 08:56
  5. Missing tileVertically()
    By zarkzervo in forum Qt Programming
    Replies: 2
    Last Post: 3rd November 2009, 07:01

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.