QVariant SubkeyListModel::data( const QModelIndex & idx, int role ) const {

    if ( role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::ToolTipRole )
	return QVariant();

    const Subkey subkey = this->subkey( idx );
    if ( subkey.isNull() )
	return QVariant();

    switch ( idx.column() ) {
    case ID:
	return QString::fromLatin1( subkey.keyID() );
    case Type:
	return Formatting::type( subkey );
    case ValidFrom:
	if ( role == Qt::EditRole )
	    return Formatting::creationDate( subkey );
	else
	    return Formatting::creationDateString( subkey );
    case ValidUntil:
	if ( role == Qt::EditRole )
	    return Formatting::expirationDate( subkey );
	else
	    return Formatting::expirationDateString( subkey );
    case Status:
	return Formatting::validityShort( subkey );
    case Bits:
	return subkey.length();
    }

    return QVariant();
}
QString Formatting::toolTip( const Key & key, int flags ) {
    if ( flags == 0 || ( key.protocol() != CMS && key.protocol() != OpenPGP ) )
        return QString();

    const Subkey subkey = key.subkey( 0 );

    QString result;
    if ( flags & Validity ) {
        if ( key.protocol() == OpenPGP || ( key.keyListMode() & Validate ) )
            if ( key.isRevoked() )
                result += make_red( i18n( "This certificate has been revoked." ) );
            else if ( key.isExpired() )
                result += make_red( i18n( "This certificate has expired." ) );
            else if ( key.isDisabled() )
                result += i18n( "This certificate has been disabled locally." );
            else
                result += i18n( "This certificate is currently valid." );
        else
            result += i18n( "The validity of this certificate cannot be checked at the moment." );
    }
    if ( flags == Validity )
        return result;

    result += QLatin1String( "<table border=\"0\">" );
    if ( key.protocol() == CMS ) {
        if ( flags & SerialNumber )
            result += format_row( i18n("Serial number"), key.issuerSerial() );
        if ( flags & Issuer )
            result += format_row( i18n("Issuer"), key.issuerName() );
    }
    if ( flags & UserIDs ) {
        const std::vector<UserID> uids = key.userIDs();
        if ( !uids.empty() )
            result += format_row( key.protocol() == CMS
                                  ? i18n("Subject")
                                  : i18n("User-ID"), prettyUserID( uids.front() ) );
        if ( uids.size() > 1 )
            for ( std::vector<UserID>::const_iterator it = uids.begin() + 1, end = uids.end() ; it != end ; ++it )
                if ( !it->isRevoked() && !it->isInvalid() )
                    result += format_row( i18n("a.k.a."), prettyUserID( *it ) );
    }
    if ( flags & ExpiryDates )
        result += format_row( i18n("Validity"),
                              subkey.neverExpires()
                              ? i18n( "from %1 until forever", time_t2string( subkey.creationTime() ) )
                              : i18n( "from %1 through %2", time_t2string( subkey.creationTime() ), time_t2string( subkey.expirationTime() ) ) );
    if ( flags & CertificateType )
        result += format_row( i18n("Certificate type"), format_keytype( key ) );
    if ( flags & CertificateUsage )
        result += format_row( i18n("Certificate usage"), format_keyusage( key ) );
    if ( flags & Fingerprint )
        result += format_row( i18n("Fingerprint"), key.primaryFingerprint() );
    result += QLatin1String( "</table><br>" );

    return result;
}
Example #3
0
void Key::setFingerprint(const KeyID& keyID, const QCString &fpr)
{
  Subkey *key;
  if ((key = getSubkey(keyID)) != 0) {
    key->setFingerprint(fpr);
  }
  else
    kdDebug(5006) << "Error: Can't set fingerprint. A subkey with key ID 0x"
                  << keyID << " doesn't exist." << endl;
}
QString Formatting::validityShort( const Subkey & subkey ) {
    if ( subkey.isRevoked() )
	return i18n("revoked");
    if ( subkey.isExpired() )
	return i18n("expired");
    if ( subkey.isDisabled() )
	return i18n("disabled");
    if ( subkey.isInvalid() )
	return i18n("invalid");
    return i18nc("as in good/valid signature", "good");
}
QModelIndex SubkeyListModel::index( const Subkey & subkey, int col ) const {
    // O(N), but not sorted, so no better way...
    for ( unsigned int row = 0, end = d->key.numSubkeys() ; row != end ; ++row )
        if ( qstricmp( subkey.keyID(), d->key.subkey( row ).keyID() ) == 0 )
            return index( row, col );
    return QModelIndex();
}
void ChangeExpiryCommand::doStart() {

    const std::vector<Key> keys = d->keys();
    if ( keys.size() != 1 ||
         keys.front().protocol() != GpgME::OpenPGP ||
         !keys.front().hasSecret() ||
         keys.front().subkey(0).isNull() ) {
        d->finished();
        return;
    }

    d->key = keys.front();

    d->ensureDialogCreated();
    assert( d->dialog );
    const Subkey subkey = d->key.subkey(0);
    d->dialog->setDateOfExpiry( subkey.neverExpires() ? QDate() : QDateTime::fromTime_t( d->key.subkey(0).expirationTime() ).date() );
    d->dialog->show();
    
}
QString Formatting::type( const Subkey & subkey ) {
    return QString::fromUtf8( subkey.publicKeyAlgorithmAsString() );
}
Example #8
0
Key *
BaseG::parseKeyData(const QCString &output, int &offset, Key *key /* = 0 */)
// This function parses the data for a single key which is output by GnuPG
// with the following command line arguments:
//   --batch --list-public-keys --with-fingerprint --with-colons
//   --fixed-list-mode [--no-expensive-trust-checks]
// It expects the key data to start at offset and returns the start of
// the next key's data in offset.
// Subkeys are currently ignored.
{
    int index = offset;

    if((strncmp(output.data() + offset, "pub:", 4) != 0)
            && (strncmp(output.data() + offset, "sec:", 4) != 0))
    {
        return 0;
    }

    if(key == 0)
        key = new Key();
    else
        key->clear();

    QCString keyID;
    bool firstKey = true;

    while(true)
    {
        int eol;
        // search the end of the current line
        if((eol = output.find('\n', index)) == -1)
            break;

        bool bIsPublicKey = false;
        if((bIsPublicKey = !strncmp(output.data() + index, "pub:", 4))
                || !strncmp(output.data() + index, "sec:", 4))
        {
            // line contains primary key data
            // Example: pub:f:1024:17:63CB691DFAEBD5FC:860451781::379:-:::scESC:

            // abort parsing if we found the start of the next key
            if(!firstKey)
                break;
            firstKey = false;

            key->setSecret(!bIsPublicKey);

            Subkey *subkey = new Subkey(QCString(), !bIsPublicKey);

            int pos = index + 4; // begin of 2nd field
            int pos2 = output.find(':', pos);
            for(int field = 2; field <= 12; field++)
            {
                switch(field)
                {
                    case 2: // the calculated trust
                        if(pos2 > pos)
                        {
                            switch(output[pos])
                            {
                                case 'o': // unknown (this key is new to the system)
                                    break;
                                case 'i': // the key is invalid, e.g. missing self-signature
                                    subkey->setInvalid(true);
                                    key->setInvalid(true);
                                    break;
                                case 'd': // the key has been disabled
                                    subkey->setDisabled(true);
                                    key->setDisabled(true);
                                    break;
                                case 'r': // the key has been revoked
                                    subkey->setRevoked(true);
                                    key->setRevoked(true);
                                    break;
                                case 'e': // the key has expired
                                    subkey->setExpired(true);
                                    key->setExpired(true);
                                    break;
                                case '-': // undefined (no path leads to the key)
                                case 'q': // undefined (no trusted path leads to the key)
                                case 'n': // don't trust this key at all
                                case 'm': // the key is marginally trusted
                                case 'f': // the key is fully trusted
                                case 'u': // the key is ultimately trusted (secret key available)
                                    // These values are ignored since we determine the key trust
                                    // from the trust values of the user ids.
                                    break;
                                default:
                                    kdDebug(5100) << "Unknown trust value\n";
                            }
                        }
                        break;
                    case 3: // length of key in bits
                        if(pos2 > pos)
                            subkey->setKeyLength(output.mid(pos, pos2 - pos).toUInt());
                        break;
                    case 4: //  the key algorithm
                        if(pos2 > pos)
                            subkey->setKeyAlgorithm(output.mid(pos, pos2 - pos).toUInt());
                        break;
                    case 5: // the long key id
                        keyID = output.mid(pos, pos2 - pos);
                        subkey->setKeyID(keyID);
                        break;
                    case 6: // the creation date (in seconds since 1970-01-01 00:00:00)
                        if(pos2 > pos)
                            subkey->setCreationDate(output.mid(pos, pos2 - pos).toLong());
                        break;
                    case 7: // the expiration date (in seconds since 1970-01-01 00:00:00)
                        if(pos2 > pos)
                            subkey->setExpirationDate(output.mid(pos, pos2 - pos).toLong());
                        else
                            subkey->setExpirationDate(-1);   // key expires never
                        break;
                    case 8: // local ID (ignored)
                    case 9: // Ownertrust (ignored for now)
                    case 10: // User-ID (always empty in --fixed-list-mode)
                    case 11: // signature class (always empty except for key signatures)
                        break;
                    case 12: // key capabilities
                        for(int i = pos; i < pos2; i++)
                            switch(output[i])
                            {
                                case 'e':
                                    subkey->setCanEncrypt(true);
                                    break;
                                case 's':
                                    subkey->setCanSign(true);
                                    break;
                                case 'c':
                                    subkey->setCanCertify(true);
                                    break;
                                case 'E':
                                    key->setCanEncrypt(true);
                                    break;
                                case 'S':
                                    key->setCanSign(true);
                                    break;
                                case 'C':
                                    key->setCanCertify(true);
                                    break;
                                default:
                                    kdDebug(5100) << "Unknown key capability\n";
                            }
                        break;
                }
                pos = pos2 + 1;
                pos2 = output.find(':', pos);
            }
            key->addSubkey(subkey);
        }
        else if(!strncmp(output.data() + index, "uid:", 4))
        {
            // line contains a user id
            // Example: uid:f::::::::Philip R. Zimmermann <*****@*****.**>:

            UserID *userID = new UserID("");

            int pos = index + 4; // begin of 2nd field
            int pos2 = output.find(':', pos);
            for(int field = 2; field <= 10; field++)
            {
                switch(field)
                {
                    case 2: // the calculated trust
                        if(pos2 > pos)
                        {
                            switch(output[pos])
                            {
                                case 'i': // the user id is invalid, e.g. missing self-signature
                                    userID->setInvalid(true);
                                    break;
                                case 'r': // the user id has been revoked
                                    userID->setRevoked(true);
                                    break;
                                case '-': // undefined (no path leads to the key)
                                case 'q': // undefined (no trusted path leads to the key)
                                    userID->setValidity(KPGP_VALIDITY_UNDEFINED);
                                    break;
                                case 'n': // don't trust this key at all
                                    userID->setValidity(KPGP_VALIDITY_NEVER);
                                    break;
                                case 'm': // the key is marginally trusted
                                    userID->setValidity(KPGP_VALIDITY_MARGINAL);
                                    break;
                                case 'f': // the key is fully trusted
                                    userID->setValidity(KPGP_VALIDITY_FULL);
                                    break;
                                case 'u': // the key is ultimately trusted (secret key available)
                                    userID->setValidity(KPGP_VALIDITY_ULTIMATE);
                                    break;
                                default:
                                    kdDebug(5100) << "Unknown trust value\n";
                            }
                        }
                        break;
                    case 3: // these fields are empty
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                    case 9:
                        break;
                    case 10: // User-ID
                        QCString uid = output.mid(pos, pos2 - pos);
                        // replace "\xXX" with the corresponding character;
                        // other escaped characters, i.e. \n, \r etc., are ignored
                        // because they shouldn't appear in user IDs
                        for(int idx = 0 ; (idx = uid.find("\\x", idx)) >= 0 ; ++idx)
                        {
                            char str[2] = "x";
                            str[0] = (char) QString(uid.mid(idx + 2, 2)).toShort(0, 16);
                            uid.replace(idx, 4, str);
                        }
                        QString uidString = QString::fromUtf8(uid.data());
                        // check whether uid was utf-8 encoded
                        bool isUtf8 = true;
                        for(unsigned int i = 0; i + 1 < uidString.length(); ++i)
                        {
                            if(uidString[i].unicode() == 0xdbff &&
                                    uidString[i + 1].row() == 0xde)
                            {
                                // we found a non-Unicode character (see QString::fromUtf8())
                                isUtf8 = false;
                                break;
                            }
                        }
                        if(!isUtf8)
                        {
                            // The user id isn't utf-8 encoded. It was most likely
                            // created with PGP which either used latin1 or koi8-r.
                            kdDebug(5100) << "User Id '" << uid
                                          << "' doesn't seem to be utf-8 encoded." << endl;

                            // We determine the ratio between non-ASCII and ASCII chars.
                            // A koi8-r user id should have lots of non-ASCII chars.
                            int nonAsciiCount = 0, asciiCount = 0;

                            // We only look at the first part of the user id (i. e. everything
                            // before the email address resp. before a comment)
                            for(signed char *ch = (signed char *)uid.data();
                                    *ch && (*ch != '(') && (*ch != '<');
                                    ++ch)
                            {
                                if(((*ch >= 'A') && (*ch <= 'Z'))
                                        || ((*ch >= 'a') && (*ch <= 'z')))
                                    ++asciiCount;
                                else if(*ch < 0)
                                    ++nonAsciiCount;
                            }
                            kdDebug(5100) << "ascii-nonAscii ratio : " << asciiCount
                                          << ":" << nonAsciiCount << endl;
                            if(nonAsciiCount > asciiCount)
                            {
                                // assume koi8-r encoding
                                kdDebug(5100) << "Assume koi8-r encoding." << endl;
                                QTextCodec *codec = QTextCodec::codecForName("KOI8-R");
                                uidString = codec->toUnicode(uid.data());
                                // check the case of the first two characters to find out
                                // whether the user id is probably CP1251 encoded (for some
                                // reason in CP1251 the lower case characters have smaller
                                // codes than the upper case characters, so if the first char
                                // of the koi8-r decoded user id is lower case and the second
                                // char is upper case then it's likely that the user id is
                                // CP1251 encoded)
                                if((uidString.length() >= 2)
                                        && (uidString[0].lower() == uidString[0])
                                        && (uidString[1].upper() == uidString[1]))
                                {
                                    // koi8-r decoded user id has inverted case, so assume
                                    // CP1251 encoding
                                    kdDebug(5100) << "No, it doesn't seem to be koi8-r. "
                                                  "Use CP 1251 instead." << endl;
                                    QTextCodec *codec = QTextCodec::codecForName("CP1251");
                                    uidString = codec->toUnicode(uid.data());
                                }
                            }
                            else
                            {
                                // assume latin1 encoding
                                kdDebug(5100) << "Assume latin1 encoding." << endl;
                                uidString = QString::fromLatin1(uid.data());
                            }
                        }
                        userID->setText(uidString);
                        break;
                }
                pos = pos2 + 1;
                pos2 = output.find(':', pos);
            }

            // user IDs are printed in UTF-8 by gpg (if one uses --with-colons)
            key->addUserID(userID);
        }
        else if(!strncmp(output.data() + index, "fpr:", 4))
        {
            // line contains a fingerprint
            // Example: fpr:::::::::17AFBAAF21064E513F037E6E63CB691DFAEBD5FC:

            if(key == 0)  // invalid key data
                break;

            // search the fingerprint (it's in the 10th field)
            int pos = index + 4;
            for(int i = 0; i < 8; i++)
                pos = output.find(':', pos) + 1;
            int pos2 = output.find(':', pos);

            key->setFingerprint(keyID, output.mid(pos, pos2 - pos));
        }
        index = eol + 1;
    }

    //kdDebug(5100) << "finished parsing key data\n";

    offset = index;

    return key;
}