#include <QString>
#include <QDebug>

// Note that this function expects the cn and hostname to be of the same case
bool isMatchingHostname(const QString &cn, const QString &hostname)
{
    int wildcard = cn.indexOf(QChar('*'));

    // Check this is a wildcard cert, if not then just compare the strings
    if (wildcard < 0)
        return cn == hostname;

    int firstCnDot = cn.indexOf(QChar('.'));
    int secondCnDot = cn.indexOf(QChar('.'), firstCnDot+1);

    // Check at least 3 components
    if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.length()))
        return false;

    // Check * is last character of 1st component (ie. there's a following .)
    if (wildcard+1 != firstCnDot)
        return false;

    // Check only one star
    if (cn.lastIndexOf(QChar('*')) != wildcard)
        return false;

    // Check characters preceding * (if any) match
    if (wildcard && (hostname.leftRef(wildcard) != cn.leftRef(wildcard)))
        return false;

    // Check characters following first . match
    if (hostname.midRef(hostname.indexOf(QChar('.'))) != cn.midRef(firstCnDot))
        return false;

    // Ok, I guess this was a wildcard CN and the hostname matches.
    return true;
}

// CN, hostname
QString tests_true[] = {
    QString("www.example.com"), QString("www.example.com"),
    QString("*.example.com"), QString("www.example.com"),
    QString("xxx*.example.com"), QString("xxxwww.example.com"),
    QString("f*.example.com"), QString("foo.example.com")
};

QString tests_false[] = {
    QString("xxx.example.com"), QString("www.example.com"),
    QString("*"), QString("www.example.com"),
    QString("*.*.com"), QString("www.example.com"),
    QString("*.example.com"), QString("baa.foo.example.com"),
    QString("f*.example.com"), QString("baa.example.com"),
    QString("*.com"), QString("example.com"),
    QString("*fail.com"), QString("example.com"),
    QString("*.example."), QString("www.example."),
    QString("*.example."), QString("www.example"),
    QString(""), QString("www"),
    QString("*"), QString("www")
};


int main( int argc, char **argv )
{
    qDebug("These should be TRUE");
    for ( int i = 0 ; i < 8 ; i+=2 ) {
        qDebug( "%s", isMatchingHostname(tests_true[i], tests_true[i+1]) ? "TRUE" : "FALSE" );
    }

    qDebug("These should be FALSE");
    for ( int i = 0 ; i < 22 ; i+=2 ) {
        qDebug( "%s", isMatchingHostname(tests_false[i], tests_false[i+1]) ? "TRUE" : "FALSE" );
    }

    return 0;
}

