* @brief Parse GPG --with-colons output into a list of UserInfo * @param output Raw output from GPG --with-colons --with-fingerprint * @param secret True if parsing secret keys (--list-secret-keys) * @return QList of parsed UserInfo objects */
| 108 | * @return QList of parsed UserInfo objects |
| 109 | */ |
| 110 | auto parseGpgColonOutput(const QString &output, bool secret) |
| 111 | -> QList<UserInfo> { |
| 112 | QList<UserInfo> users; |
| 113 | |
| 114 | #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) |
| 115 | const QStringList lines = |
| 116 | output.split(Util::newLinesRegex(), Qt::SkipEmptyParts); |
| 117 | #else |
| 118 | const QStringList lines = |
| 119 | output.split(Util::newLinesRegex(), QString::SkipEmptyParts); |
| 120 | #endif |
| 121 | |
| 122 | UserInfo current_user; |
| 123 | |
| 124 | for (const QString &key : lines) { |
| 125 | QStringList props = key.split(':'); |
| 126 | if (props.size() < GPG_MIN_FIELDS) { |
| 127 | continue; |
| 128 | } |
| 129 | |
| 130 | const QString &record_type = props[0]; |
| 131 | const GpgRecordType type = classifyRecord(record_type); |
| 132 | |
| 133 | switch (type) { |
| 134 | case GpgRecordType::Pub: |
| 135 | case GpgRecordType::Sec: |
| 136 | if (!current_user.key_id.isEmpty()) { |
| 137 | users.append(current_user); |
| 138 | } |
| 139 | current_user = UserInfo(); |
| 140 | handlePubSecRecord(props, secret && (type == GpgRecordType::Sec), |
| 141 | current_user); |
| 142 | break; |
| 143 | case GpgRecordType::Uid: |
| 144 | if (current_user.name.isEmpty()) { |
| 145 | handleUidRecord(props, current_user); |
| 146 | } |
| 147 | break; |
| 148 | case GpgRecordType::Fpr: |
| 149 | handleFprRecord(props, current_user); |
| 150 | break; |
| 151 | default: |
| 152 | break; |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | if (!current_user.key_id.isEmpty()) { |
| 157 | users.append(current_user); |
| 158 | } |
| 159 | |
| 160 | return users; |
| 161 | } |
no test coverage detected