From 4ce63eeb3718a369d84d23a6004858c96d96b931 Mon Sep 17 00:00:00 2001 From: Adwait Rawat Date: Mon, 10 Oct 2022 22:18:01 +0200 Subject: [PATCH] Allow to sign commits --- data/org.gnome.gitg.gschema.xml.in | 3 + gitg/commit/gitg-commit-dialog.vala | 16 + gitg/commit/gitg-commit.vala | 5 + gitg/meson.build | 1 - gitg/resources/ui/gitg-commit-dialog.ui | 19 +- libgitg/gitg-gpg-utils.vala | 63 ++ libgitg/gitg-stage.vala | 75 +- libgitg/meson.build | 2 + meson.build | 1 + vapi/gpg-error.vapi | 422 ++++++++ vapi/gpgme.deps | 1 + vapi/gpgme.vapi | 1225 +++++++++++++++++++++++ 12 files changed, 1822 insertions(+), 11 deletions(-) create mode 100644 libgitg/gitg-gpg-utils.vala create mode 100644 vapi/gpg-error.vapi create mode 100644 vapi/gpgme.deps create mode 100644 vapi/gpgme.vapi diff --git a/data/org.gnome.gitg.gschema.xml.in b/data/org.gnome.gitg.gschema.xml.in index b0d240a8..103bcd0f 100644 --- a/data/org.gnome.gitg.gschema.xml.in +++ b/data/org.gnome.gitg.gschema.xml.in @@ -371,5 +371,8 @@ false + + false + diff --git a/gitg/commit/gitg-commit-dialog.vala b/gitg/commit/gitg-commit-dialog.vala index 935bc83d..0b3f888a 100644 --- a/gitg/commit/gitg-commit-dialog.vala +++ b/gitg/commit/gitg-commit-dialog.vala @@ -57,6 +57,9 @@ class Dialog : Gtk.Dialog [GtkChild (name = "check_button_sign_off")] private unowned Gtk.CheckButton d_check_button_sign_off; + [GtkChild (name = "check_button_sign_commit")] + private Gtk.CheckButton d_check_button_sign_commit; + [GtkChild (name = "image_avatar")] private unowned Gtk.Image d_image_avatar; @@ -218,6 +221,8 @@ class Dialog : Gtk.Dialog public bool sign_off { get; set; } + public bool sign_commit { get; set; } + public int max_number_commit_messages { get; set; } public int max_number_days_commit_messages { get; set; } @@ -478,6 +483,11 @@ class Dialog : Gtk.Dialog BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); + d_check_button_sign_commit.bind_property("active", + this, "sign-commit", + BindingFlags.BIDIRECTIONAL | + BindingFlags.SYNC_CREATE); + d_commit_settings = new Settings(Gitg.Config.APPLICATION_ID + ".state.commit"); d_commit_settings.bind("sign-off", @@ -486,6 +496,12 @@ class Dialog : Gtk.Dialog SettingsBindFlags.GET | SettingsBindFlags.SET); + d_commit_settings.bind("sign-commit", + this, + "sign-commit", + SettingsBindFlags.GET | + SettingsBindFlags.SET); + d_message_settings = new Settings(Gitg.Config.APPLICATION_ID + ".preferences.commit.message"); d_message_settings.bind("max-number-days-commit-messages", diff --git a/gitg/commit/gitg-commit.vala b/gitg/commit/gitg-commit.vala index cb561a09..e1fc374b 100644 --- a/gitg/commit/gitg-commit.vala +++ b/gitg/commit/gitg-commit.vala @@ -1099,6 +1099,11 @@ namespace GitgCommit opts |= Gitg.StageCommitOptions.SIGN_OFF; } + if (dlg.sign_commit) + { + opts |= Gitg.StageCommitOptions.SIGN_COMMIT; + } + if (skip_hooks) { opts |= Gitg.StageCommitOptions.SKIP_HOOKS; diff --git a/gitg/meson.build b/gitg/meson.build index 4b108a14..cc01887d 100644 --- a/gitg/meson.build +++ b/gitg/meson.build @@ -73,7 +73,6 @@ deps = [ libpeas_dep, libdazzle_dep, json_glib_dependency, - valac.find_library ('posix'), ] diff --git a/gitg/resources/ui/gitg-commit-dialog.ui b/gitg/resources/ui/gitg-commit-dialog.ui index a2014a60..443add8a 100644 --- a/gitg/resources/ui/gitg-commit-dialog.ui +++ b/gitg/resources/ui/gitg-commit-dialog.ui @@ -246,6 +246,23 @@ 1 + + + Add si_gnature + True + True + False + True + start + True + + + 0 + 7 + 2 + 1 + + True @@ -280,7 +297,7 @@ 2 - 6 + 7 1 1 diff --git a/libgitg/gitg-gpg-utils.vala b/libgitg/gitg-gpg-utils.vala new file mode 100644 index 00000000..82cf02a4 --- /dev/null +++ b/libgitg/gitg-gpg-utils.vala @@ -0,0 +1,63 @@ + +/* + * This file is part of gitg + * + * Copyright (C) 2022 - Alberto Fanjul + * + * gitg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * gitg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gitg. If not, see . + */ + +using GPG; + +namespace Gitg +{ + +public class GPGUtils +{ + public static string sign_commit_object(string commit_content, + string signing_key) throws Error + { + check_version(); + Data plain_data; + Data signed_data; + Data.create(out signed_data); + Data.create_from_memory(out plain_data, commit_content.data, false); + Context context; + Context.Context(out context); + context.set_armor(true); + Key key; + context.get_key(signing_key, out key, true); + if (key != null) + context.signers_add(key); + context.op_sign(plain_data, signed_data, SigMode.DETACH); + return get_string_from_data(signed_data); + } + + private static string get_string_from_data(Data data) { + data.seek(0); + uint8[] buf = new uint8[256]; + ssize_t? len = null; + string res = ""; + do { + len = data.read(buf); + if (len > 0) { + string part = (string) buf; + part = part.substring(0, (long) len); + res += part; + } + } while (len > 0); + return res; + } +} +} diff --git a/libgitg/gitg-stage.vala b/libgitg/gitg-stage.vala index 367fca2c..42f53008 100644 --- a/libgitg/gitg-stage.vala +++ b/libgitg/gitg-stage.vala @@ -26,7 +26,8 @@ public enum StageCommitOptions NONE = 0, SIGN_OFF = 1 << 0, AMEND = 1 << 1, - SKIP_HOOKS = 1 << 2 + SKIP_HOOKS = 1 << 2, + SIGN_COMMIT= 1 << 3 } public errordomain StageError @@ -34,7 +35,10 @@ public errordomain StageError PRE_COMMIT_HOOK_FAILED, COMMIT_MSG_HOOK_FAILED, NOTHING_TO_COMMIT, - INDEX_ENTRY_NOT_FOUND + INDEX_ENTRY_NOT_FOUND, + SIGN_CONFIG_NOT_FOUND, + SIGN_CONFIG_ERROR, + UPDATE_REF_ERROR } public class PatchSet @@ -92,6 +96,8 @@ public class PatchSet public class Stage : Object { + private const string CONFIG_USER_SIGNINGKEY = "user.signingkey"; + private weak Repository d_repository; private Mutex d_index_mutex; private Ggit.Tree? d_head_tree; @@ -400,6 +406,7 @@ public class Stage : Object yield Async.thread(() => { bool skip_hooks = (options & StageCommitOptions.SKIP_HOOKS) != 0; bool amend = (options & StageCommitOptions.AMEND) != 0; + bool sign_commit = (options & StageCommitOptions.SIGN_COMMIT) != 0; // Write tree from index var conf = d_repository.get_config().snapshot(); @@ -448,13 +455,63 @@ public class Stage : Object pars = parents; } - ret = d_repository.create_commit_from_ids(reference.get_name(), - author, - committer, - encoding, - emsg, - treeoid, - pars); + if (sign_commit) + { + string signing_key; + try { + signing_key = conf.get_string(CONFIG_USER_SIGNINGKEY); + } catch (Error e) { + throw new StageError.SIGN_CONFIG_NOT_FOUND(_("setup “%s” to do a signed commit"), CONFIG_USER_SIGNINGKEY); + } + + Ggit.Commit[] parent_commits = new Ggit.Commit[pars.length]; + for (int i = 0; i < pars.length; i++) { + Ggit.Commit commit = d_repository.lookup(pars[i]); + parent_commits[i] = commit; + } + + var data = d_repository.create_commit_buffer(author, + committer, + encoding, + emsg, + d_repository.lookup_tree(treeoid), + parent_commits); + + string signature; + try { + signature = Gitg.GPGUtils.sign_commit_object(data, signing_key); + } catch (Error e) { + throw new StageError.SIGN_CONFIG_ERROR(_("error signing the commit “%s”"), e.message); + } + + ret = d_repository.create_commit_with_signature(data, signature, null); + + Ggit.Ref? resolved; + if (reference.get_reference_type() == Ggit.RefType.SYMBOLIC) + { + try + { + resolved = reference.resolve(); + } catch (Error e) { + throw new StageError.UPDATE_REF_ERROR(_("error updating current ref “%s”"), reference.get_name()); + } + } + else + { + resolved = reference; + } + resolved.set_target(ret, null); + } + else + { + ret = d_repository.create_commit_from_ids(reference.get_name(), + author, + committer, + encoding, + emsg, + treeoid, + pars); + } } else { diff --git a/libgitg/meson.build b/libgitg/meson.build index 9be08659..c572867f 100644 --- a/libgitg/meson.build +++ b/libgitg/meson.build @@ -14,6 +14,7 @@ common_deps = [ gtk_dep, libgit2_glib_dep, libdazzle_dep, + gpgme_dependency, ] sources = files( @@ -52,6 +53,7 @@ sources = files( 'gitg-diff-view-options.vala', 'gitg-diff-view.vala', 'gitg-font-manager.vala', + 'gitg-gpg-utils.vala', 'gitg-hook.vala', 'gitg-init.vala', 'gitg-label-renderer.vala', diff --git a/meson.build b/meson.build index 059f556e..6fd945ea 100644 --- a/meson.build +++ b/meson.build @@ -137,6 +137,7 @@ libsecret_dep = dependency('libsecret-1') libxml_dep = dependency('libxml-2.0', version: '>= 2.9.0') libdazzle_dep = dependency('libdazzle-1.0') json_glib_dependency = dependency('json-glib-1.0') +gpgme_dependency = dependency('gpgme') config_dep = valac.find_library('config', dirs: vapi_dir) gitg_platform_support_dep = valac.find_library('gitg-platform-support', dirs: vapi_dir) diff --git a/vapi/gpg-error.vapi b/vapi/gpg-error.vapi new file mode 100644 index 00000000..42734a4a --- /dev/null +++ b/vapi/gpg-error.vapi @@ -0,0 +1,422 @@ +/* gpg-error.vapi + * + * Copyright (C) 2009 Sebastian Reichel + * Copyright (C) 2022 Itay Grudev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +[CCode (cheader_filename = "gpg-error.h")] +namespace GPGError { + /** + * The error value type gpg_error_t + */ + [SimpleType] + [CCode (cname = "gpg_error_t", has_type_id = false)] + public struct Error { + public GPGError.ErrorCode code { + [CCode (cname = "gpg_err_code")] + get; + } + } + + /** + * The error code type gpg_err_code_t. + */ + [CCode (cname = "gpg_err_code_t", cprefix = "GPG_ERR_", has_type_id = false)] + public enum ErrorCode { + NO_ERROR, + GENERAL, + UNKNOWN_PACKET, + UNKNOWN_VERSION, + PUBKEY_ALGO, + DIGEST_ALGO, + BAD_PUBKEY, + BAD_SECKEY, + BAD_SIGNATURE, + NO_PUBKEY, + CHECKSUM, + BAD_PASSPHRASE, + CIPHER_ALGO, + KEYRING_OPEN, + INV_PACKET, + INV_ARMOR, + NO_USER_ID, + NO_SECKEY, + WRONG_SECKEY, + BAD_KEY, + COMPR_ALGO, + NO_PRIME, + NO_ENCODING_METHOD, + NO_ENCRYPTION_SCHEME, + NO_SIGNATURE_SCHEME, + INV_ATTR, + NO_VALUE, + NOT_FOUND, + VALUE_NOT_FOUND, + SYNTAX, + BAD_MPI, + INV_PASSPHRASE, + SIG_CLASS, + RESOURCE_LIMIT, + INV_KEYRING, + TRUSTDB, + BAD_CERT, + INV_USER_ID, + UNEXPECTED, + TIME_CONFLICT, + KEYSERVER, + WRONG_PUBKEY_ALGO, + TRIBUTE_TO_D_A, + WEAK_KEY, + INV_KEYLEN, + INV_ARG, + BAD_URI, + INV_URI, + NETWORK, + UNKNOWN_HOST, + SELFTEST_FAILED, + NOT_ENCRYPTED, + NOT_PROCESSED, + UNUSABLE_PUBKEY, + UNUSABLE_SECKEY, + INV_VALUE, + BAD_CERT_CHAIN, + MISSING_CERT, + NO_DATA, + BUG, + NOT_SUPPORTED, + INV_OP, + TIMEOUT, + INTERNAL, + EOF_GCRYPT, + INV_OBJ, + TOO_SHORT, + TOO_LARGE, + NO_OBJ, + NOT_IMPLEMENTED, + CONFLICT, + INV_CIPHER_MODE, + INV_FLAG, + INV_HANDLE, + TRUNCATED, + INCOMPLETE_LINE, + INV_RESPONSE, + NO_AGENT, + AGENT, + INV_DATA, + ASSUAN_SERVER_FAULT, + ASSUAN, + INV_SESSION_KEY, + INV_SEXP, + UNSUPPORTED_ALGORITHM, + NO_PIN_ENTRY, + PIN_ENTRY, + BAD_PIN, + INV_NAME, + BAD_DATA, + INV_PARAMETER, + WRONG_CARD, + NO_DIRMNGR, + DIRMNGR, + CERT_REVOKED, + NO_CRL_KNOWN, + CRL_TOO_OLD, + LINE_TOO_LONG, + NOT_TRUSTED, + CANCELED, + BAD_CA_CERT, + CERT_EXPIRED, + CERT_TOO_YOUNG, + UNSUPPORTED_CERT, + UNKNOWN_SEXP, + UNSUPPORTED_PROTECTION, + CORRUPTED_PROTECTION, + AMBIGUOUS_NAME, + CARD, + CARD_RESET, + CARD_REMOVED, + INV_CARD, + CARD_NOT_PRESENT, + NO_PKCS15_APP, + NOT_CONFIRMED, + CONFIGURATION, + NO_POLICY_MATCH, + INV_INDEX, + INV_ID, + NO_SCDAEMON, + SCDAEMON, + UNSUPPORTED_PROTOCOL, + BAD_PIN_METHOD, + CARD_NOT_INITIALIZED, + UNSUPPORTED_OPERATION, + WRONG_KEY_USAGE, + NOTHING_FOUND, + WRONG_BLOB_TYPE, + MISSING_VALUE, + HARDWARE, + PIN_BLOCKED, + USE_CONDITIONS, + PIN_NOT_SYNCED, + INV_CRL, + BAD_BER, + INV_BER, + ELEMENT_NOT_FOUND, + IDENTIFIER_NOT_FOUND, + INV_TAG, + INV_LENGTH, + INV_KEYINFO, + UNEXPECTED_TAG, + NOT_DER_ENCODED, + NO_CMS_OBJ, + INV_CMS_OBJ, + UNKNOWN_CMS_OBJ, + UNSUPPORTED_CMS_OBJ, + UNSUPPORTED_ENCODING, + UNSUPPORTED_CMS_VERSION, + UNKNOWN_ALGORITHM, + INV_ENGINE, + PUBKEY_NOT_TRUSTED, + DECRYPT_FAILED, + KEY_EXPIRED, + SIG_EXPIRED, + ENCODING_PROBLEM, + INV_STATE, + DUP_VALUE, + MISSING_ACTION, + MODULE_NOT_FOUND, + INV_OID_STRING, + INV_TIME, + INV_CRL_OBJ, + UNSUPPORTED_CRL_VERSION, + INV_CERT_OBJ, + UNKNOWN_NAME, + LOCALE_PROBLEM, + NOT_LOCKED, + PROTOCOL_VIOLATION, + INV_MAC, + INV_REQUEST, + UNKNOWN_EXTN, + UNKNOWN_CRIT_EXTN, + LOCKED, + UNKNOWN_OPTION, + UNKNOWN_COMMAND, + UNFINISHED, + BUFFER_TOO_SHORT, + SEXP_INV_LEN_SPEC, + SEXP_STRING_TOO_LONG, + SEXP_UNMATCHED_PAREN, + SEXP_NOT_CANONICAL, + SEXP_BAD_CHARACTER, + SEXP_BAD_QUOTATION, + SEXP_ZERO_PREFIX, + SEXP_NESTED_DH, + SEXP_UNMATCHED_DH, + SEXP_UNEXPECTED_PUNC, + SEXP_BAD_HEX_CHAR, + SEXP_ODD_HEX_NUMBERS, + SEXP_BAD_OCT_CHAR, + ASS_GENERAL, + ASS_ACCEPT_FAILED, + ASS_CONNECT_FAILED, + ASS_INV_RESPONSE, + ASS_INV_VALUE, + ASS_INCOMPLETE_LINE, + ASS_LINE_TOO_LONG, + ASS_NESTED_COMMANDS, + ASS_NO_DATA_CB, + ASS_NO_INQUIRE_CB, + ASS_NOT_A_SERVER, + ASS_NOT_A_CLIENT, + ASS_SERVER_START, + ASS_READ_ERROR, + ASS_WRITE_ERROR, + ASS_TOO_MUCH_DATA, + ASS_UNEXPECTED_CMD, + ASS_UNKNOWN_CMD, + ASS_SYNTAX, + ASS_CANCELED, + ASS_NO_INPUT, + ASS_NO_OUTPUT, + ASS_PARAMETER, + ASS_UNKNOWN_INQUIRE, + USER_1, + USER_2, + USER_3, + USER_4, + USER_5, + USER_6, + USER_7, + USER_8, + USER_9, + USER_10, + USER_11, + USER_12, + USER_13, + USER_14, + USER_15, + USER_16, + MISSING_ERRNO, + UNKNOWN_ERRNO, + EOF, + E2BIG, + EACCES, + EADDRINUSE, + EADDRNOTAVAIL, + EADV, + EAFNOSUPPORT, + EAGAIN, + EALREADY, + EAUTH, + EBACKGROUND, + EBADE, + EBADF, + EBADFD, + EBADMSG, + EBADR, + EBADRPC, + EBADRQC, + EBADSLT, + EBFONT, + EBUSY, + ECANCELED, + ECHILD, + ECHRNG, + ECOMM, + ECONNABORTED, + ECONNREFUSED, + ECONNRESET, + ED, + EDEADLK, + EDEADLOCK, + EDESTADDRREQ, + EDIED, + EDOM, + EDOTDOT, + EDQUOT, + EEXIST, + EFAULT, + EFBIG, + EFTYPE, + EGRATUITOUS, + EGREGIOUS, + EHOSTDOWN, + EHOSTUNREACH, + EIDRM, + EIEIO, + EILSEQ, + EINPROGRESS, + EINTR, + EINVAL, + EIO, + EISCONN, + EISDIR, + EISNAM, + EL2HLT, + EL2NSYNC, + EL3HLT, + EL3RST, + ELIBACC, + ELIBBAD, + ELIBEXEC, + ELIBMAX, + ELIBSCN, + ELNRNG, + ELOOP, + EMEDIUMTYPE, + EMFILE, + EMLINK, + EMSGSIZE, + EMULTIHOP, + ENAMETOOLONG, + ENAVAIL, + ENEEDAUTH, + ENETDOWN, + ENETRESET, + ENETUNREACH, + ENFILE, + ENOANO, + ENOBUFS, + ENOCSI, + ENODATA, + ENODEV, + ENOENT, + ENOEXEC, + ENOLCK, + ENOLINK, + ENOMEDIUM, + ENOMEM, + ENOMSG, + ENONET, + ENOPKG, + ENOPROTOOPT, + ENOSPC, + ENOSR, + ENOSTR, + ENOSYS, + ENOTBLK, + ENOTCONN, + ENOTDIR, + ENOTEMPTY, + ENOTNAM, + ENOTSOCK, + ENOTSUP, + ENOTTY, + ENOTUNIQ, + ENXIO, + EOPNOTSUPP, + EOVERFLOW, + EPERM, + EPFNOSUPPORT, + EPIPE, + EPROCLIM, + EPROCUNAVAIL, + EPROGMISMATCH, + EPROGUNAVAIL, + EPROTO, + EPROTONOSUPPORT, + EPROTOTYPE, + ERANGE, + EREMCHG, + EREMOTE, + EREMOTEIO, + ERESTART, + EROFS, + ERPCMISMATCH, + ESHUTDOWN, + ESOCKTNOSUPPORT, + ESPIPE, + ESRCH, + ESRMNT, + ESTALE, + ESTRPIPE, + ETIME, + ETIMEDOUT, + ETOOMANYREFS, + ETXTBSY, + EUCLEAN, + EUNATCH, + EUSERS, + EWOULDBLOCK, + EXDEV, + EXFULL, + CODE_DIM + } +} diff --git a/vapi/gpgme.deps b/vapi/gpgme.deps new file mode 100644 index 00000000..a0f4f82b --- /dev/null +++ b/vapi/gpgme.deps @@ -0,0 +1 @@ +gpg-error diff --git a/vapi/gpgme.vapi b/vapi/gpgme.vapi new file mode 100644 index 00000000..bff0c745 --- /dev/null +++ b/vapi/gpgme.vapi @@ -0,0 +1,1225 @@ +/* libgpgme.vapi + * + * Copyright (C) 2009 Sebastian Reichel + * Copyright (C) 2022 Itay Grudev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +/** + * GPGME is an API wrapper around GnuPG, which parses the output of GnuPG. + */ +[CCode (lower_case_cprefix = "gpgme_", cheader_filename = "gpgme.h")] +namespace GPG { + /** + * EngineInfo as List + */ + [CCode (cname = "struct _gpgme_engine_info")] + public struct EngineInfo { + /** + * Next entry in the list + */ + EngineInfo* next; + + /** + * The protocol ID + */ + Protocol protocol; + + /** + * filename of the engine binary + */ + string file_name; + + /** + * version string of the installed binary + */ + string version; + + /** + * minimum version required for gpgme + */ + string req_version; + + /** + * home directory to be used or null for default + */ + string? home_dir; + } + + /** + * A Key from the Keyring + */ + [CCode (cname = "struct _gpgme_key", ref_function = "gpgme_key_ref", ref_function_void = true, unref_function = "gpgme_key_unref", free_function = "gpgme_key_release")] + public class Key { + public bool revoked; + public bool expired; + public bool disabled; + public bool invalid; + public bool can_encrypt; + public bool can_sign; + public bool can_certify; + public bool secret; + public bool can_authenticate; + public bool is_qualified; + public Protocol protocol; + + /** + * If protocol is CMS, this string contains the issuer's serial + */ + public string issuer_serial; + + /** + * If protocol is CMS, this string contains the issuer's name + */ + public string issuer_name; + + /** + * If protocol is CMS, this string contains the chain ID. + */ + public string chain_id; + + /** + * If protocol is OpenPGP, this field contains the owner trust level + */ + public Validity owner_trust; + + /** + * The key's subkeys + */ + [CCode(array_null_terminated = true)] + public SubKey[] subkeys; + + /** + * The key's user ids + */ + [CCode(array_null_terminated = true)] + public UserID[] uids; + + public KeylistMode keylist_mode; + } + + /** + * A signature notation + */ + [CCode (cname = "struct _gpgme_sig_notation")] + public struct SigNotation { + /** + * The next SigNotation from the list + */ + SigNotation* next; + + /** + * If name is a null pointer value contains a policy url rather than a notation + */ + string? name; + + /** + * The value of the notation data + */ + string value; + + /** + * The length of the name of the notation data + */ + int name_len; + + /** + * The length of the value of the notation data + */ + int value_len; + + /** + * The accumulated flags + */ + SigNotationFlags flags; + + /** + * notation data is human readable + */ + bool human_readable; + + /** + * notation data is critical + */ + bool critical; + } + + /** + * A subkey from a Key + */ + [CCode (cname = "struct _gpgme_subkey")] + public struct SubKey { + SubKey* next; + bool revoked; + bool expired; + bool disabled; + bool invalid; + bool can_encrypt; + bool can_sign; + bool can_certify; + bool secret; + bool can_authenticate; + bool is_qualified; + bool is_cardkey; + PublicKeyAlgorithm algo; + uint length; + string keyid; + + /** + * Fingerprint of the key in hex form + */ + string fpr; + + /** + * The creation timestamp. + * -1 = invalid, + * 0 = not available + */ + long timestamp; + + /** + * The expiration timestamp. + * 0 = key does not expire + */ + long expires; + + /** + * The serial number of the smartcard holding this key or null + */ + string? card_number; + } + + /** + * A signature on a UserID + */ + [CCode (cname = "struct _gpgme_key_sig")] + public struct KeySig { + /** + * The next signature from the list + */ + KeySig* next; + bool revoked; + bool expired; + bool invalid; + bool exportable; + PublicKeyAlgorithm algo; + string keyid; + + /** + * The creation timestamp. + * -1 = invalid, + * 0 = not available + */ + long timestamp; + + /** + * The expiration timestamp. + * 0 = key does not expire + */ + long expires; + + GPGError.Error status; + + string uid; + string name; + string email; + string comment; + + /** + * Crypto backend specific signature class + */ + uint sig_class; + + SigNotation notations; + } + + /** + * A UserID from a Key + */ + [CCode (cname = "struct _gpgme_user_id")] + public struct UserID { + /** + * The next UserID from the list + */ + UserID* next; + + bool revoked; + bool invalid; + Validity validity; + string uid; + string name; + string email; + string comment; + + KeySig signatures; + } + + /** + * verify result of OP + */ + [CCode (cname = "struct _gpgme_op_verify_result")] + public struct VerifyResult { + Signature* signatures; + + /** + * The original file name of the plaintext message, if available + */ + string? file_name; + } + + /** + * sign result of OP + */ + [CCode (cname = "struct _gpgme_op_sign_result")] + public struct SignResult { + InvalidKey invalid_signers; + Signature* signatures; + } + + /** + * encrypt result of OP + */ + [CCode (cname = "struct _gpgme_op_encrypt_result")] + public struct EncryptResult { + /** + * The list of invalid repipients + */ + InvalidKey invalid_signers; + } + + /** + * decrypt result of OP + */ + [CCode (cname = "struct _gpgme_op_decrypt_result")] + public struct DecryptResult { + string unsupported_algorithm; + bool wrong_key_usage; + Recipient recipients; + string file_name; + } + + /** + * An receipient + */ + [CCode (cname = "struct _gpgme_recipient")] + public struct Recipient { + Recipient *next; + string keyid; + PublicKeyAlgorithm pubkey_algo; + GPGError.Error status; + } + + /** + * list of invalid keys + */ + [CCode (cname = "struct _gpgme_invalid_key")] + public struct InvalidKey { + InvalidKey *next; + string fpr; + GPGError.Error reason; + } + + /** + * A Signature + */ + [CCode (cname = "struct _gpgme_signature")] + public struct Signature { + /** + * The next signature in the list + */ + Signature *next; + + /** + * A summary of the signature status + */ + Sigsum summary; + + /** + * Fingerprint or key ID of the signature + */ + string fpr; + + /** + * The Error status of the signature + */ + GPGError.Error status; + + /** + * Notation data and policy URLs + */ + SigNotation notations; + + /** + * Signature creation time + */ + ulong timestamp; + + /** + * Signature expiration time or 0 + */ + ulong exp_timestamp; + + /** + * Key should not have been used for signing + */ + bool wrong_key_usage; + + /** + * PKA status + */ + PKAStatus pka_trust; + + /** + * Validity has been verified using the chain model + */ + bool chain_model; + + /** + * Validity + */ + Validity validity; + + /** + * Validity reason + */ + GPGError.Error validity_reason; + + /** + * public key algorithm used to create the signature + */ + PublicKeyAlgorithm pubkey_algo; + + /** + * The hash algorithm used to create the signature + */ + HashAlgorithm hash_algo; + + /** + * The mailbox from the PKA information or null + */ + string? pka_address; + } + + /** + * PKA Status + */ + public enum PKAStatus { + NOT_AVAILABLE, + BAD, + OKAY, + RFU + } + + /** + * Flags used for the summary field in a Signature + */ + [CCode (cname = "gpgme_sigsum_t", cprefix = "GPGME_SIGSUM_")] + public enum Sigsum { + /** + * The signature is fully valid + */ + VALID, + + /** + * The signature is good + */ + GREEN, + + /** + * The signature is bad + */ + RED, + + /** + * One key has been revoked + */ + KEY_REVOKED, + + /** + * One key has expired + */ + KEY_EXPIRED, + + /** + * The signature has expired + */ + SIG_EXPIRED, + + /** + * Can't verfiy - missing key + */ + KEY_MISSING, + + /** + * CRL not available + */ + CRL_MISSING, + + /** + * Available CRL is too old + */ + CRL_TOO_OLD, + + /** + * A policy was not met + */ + BAD_POLICY, + + /** + * A system error occured + */ + SYS_ERROR + } + + /** + * Encoding modes of Data objects + */ + [CCode (cname = "gpgme_data_encoding_t", cprefix = "GPGME_DATA_ENCODING_")] + public enum DataEncoding { + /** + * Not specified + */ + NONE, + /** + * Binary encoded + */ + BINARY, + /** + * Base64 encoded + */ + BASE64, + /** + * Either PEM or OpenPGP Armor + */ + ARMOR, + /** + * LF delimited URL list + */ + URL, + /** + * LF percent escaped, delimited URL list + */ + URLESC, + /** + * Nul determined URL list + */ + URL0 + } + + /** + * Public Key Algorithms from libgcrypt + */ + [CCode (cname = "gpgme_pubkey_algo_t", cprefix = "GPGME_PK_")] + public enum PublicKeyAlgorithm { + RSA, + RSA_E, + RSA_S, + ELG_E, + DSA, + ELG + } + + /** + * Hash Algorithms from libgcrypt + */ + [CCode (cname = "gpgme_hash_algo_t", cprefix = "GPGME_MD_")] + public enum HashAlgorithm { + NONE, + MD5, + SHA1, + RMD160, + MD2, + TIGER, + HAVAL, + SHA256, + SHA384, + SHA512, + MD4, + CRC32, + CRC32_RFC1510, + CRC24_RFC2440 + } + + /** + * Signature modes + */ + [CCode (cname = "gpgme_sig_mode_t", cprefix = "GPGME_SIG_MODE_")] + public enum SigMode { + NORMAL, + DETACH, + CLEAR + } + + /** + * Validities for a trust item or key + */ + [CCode (cname = "gpgme_validity_t", cprefix = "GPGME_VALIDITY_")] + public enum Validity { + UNKNOWN, + UNDEFINED, + NEVER, + MARGINAL, + FULL, + ULTIMATE + } + + /** + * Protocols + */ + [CCode (cname = "gpgme_protocol_t", cprefix = "GPGME_PROTOCOL_")] + public enum Protocol { + /** + * Default Mode + */ + OpenPGP, + /** + * Cryptographic Message Syntax + */ + CMS, + /** + * Special code for gpgconf + */ + GPGCONF, + /** + * Low-level access to an Assuan server + */ + ASSUAN, + UNKNOWN + } + + /** + * Keylist modes used by Context + */ + [CCode (cname = "gpgme_keylist_mode_t", cprefix = "GPGME_KEYLIST_MODE_")] + public enum KeylistMode { + LOCAL, + EXTERN, + SIGS, + SIG_NOTATIONS, + EPHEMERAL, + VALIDATE + } + + /** + * Export modes used by Context + */ + [CCode (cname = "gpgme_export_mode_t", cprefix = "GPGME_EXPORT_MODE_")] + public enum ExportMode { + EXTERN + } + + /** + * Audit log function flags + */ + [CCode (cprefix = "GPGME_AUDITLOG_")] + public enum AuditLogFlag { + HTML, + WITH_HELP + } + + /** + * Signature notation flags + */ + [CCode (cname = "gpgme_sig_notation_flags_t", cprefix = "GPGME_SIG_NOTATION_")] + public enum SigNotationFlags { + HUMAN_READABLE, + CRITICAL + } + + /** + * Encryption Flags + */ + [CCode (cname = "gpgme_encrypt_flags_t", cprefix = "GPGME_ENCRYPT_")] + public enum EncryptFlags { + ALWAYS_TRUST, + NO_ENCRYPT_TO + } + + /** + * Edit Operation Stati + */ + [CCode (cname = "gpgme_status_code_t", cprefix = "GPGME_STATUS_")] + public enum StatusCode { + EOF, + ENTER, + LEAVE, + ABORT, + GOODSIG, + BADSIG, + ERRSIG, + BADARMOR, + RSA_OR_IDEA, + KEYEXPIRED, + KEYREVOKED, + TRUST_UNDEFINED, + TRUST_NEVER, + TRUST_MARGINAL, + TRUST_FULLY, + TRUST_ULTIMATE, + SHM_INFO, + SHM_GET, + SHM_GET_BOOL, + SHM_GET_HIDDEN, + NEED_PASSPHRASE, + VALIDSIG, + SIG_ID, + SIG_TO, + ENC_TO, + NODATA, + BAD_PASSPHRASE, + NO_PUBKEY, + NO_SECKEY, + NEED_PASSPHRASE_SYM, + DECRYPTION_FAILED, + DECRYPTION_OKAY, + MISSING_PASSPHRASE, + GOOD_PASSPHRASE, + GOODMDC, + BADMDC, + ERRMDC, + IMPORTED, + IMPORT_OK, + IMPORT_PROBLEM, + IMPORT_RES, + FILE_START, + FILE_DONE, + FILE_ERROR, + BEGIN_DECRYPTION, + END_DECRYPTION, + BEGIN_ENCRYPTION, + END_ENCRYPTION, + DELETE_PROBLEM, + GET_BOOL, + GET_LINE, + GET_HIDDEN, + GOT_IT, + PROGRESS, + SIG_CREATED, + SESSION_KEY, + NOTATION_NAME, + NOTATION_DATA, + POLICY_URL, + BEGIN_STREAM, + END_STREAM, + KEY_CREATED, + USERID_HINT, + UNEXPECTED, + INV_RECP, + NO_RECP, + ALREADY_SIGNED, + SIGEXPIRED, + EXPSIG, + EXPKEYSIG, + TRUNCATED, + ERROR, + NEWSIG, + REVKEYSIG, + SIG_SUBPACKET, + NEED_PASSPHRASE_PIN, + SC_OP_FAILURE, + SC_OP_SUCCESS, + CARDCTRL, + BACKUP_KEY_CREATED, + PKA_TRUST_BAD, + PKA_TRUST_GOOD, + PLAINTEXT + } + + /** + * The Context object represents a GPG instance + */ + [Compact] + [CCode (cname = "struct gpgme_context", free_function = "gpgme_release", cprefix = "gpgme_")] + public class Context { + /** + * Create a new context, returns Error Status Code + */ + [CCode (cname = "gpgme_new")] + public static GPGError.Error Context(out Context ctx); + + public GPGError.Error set_protocol(Protocol p); + public Protocol get_protocol(); + + public void set_armor(bool yes); + public bool get_armor(); + + public void set_textmode(bool yes); + public bool get_textmode(); + + public GPGError.Error set_keylist_mode(KeylistMode mode); + public KeylistMode get_keylist_mode(); + + /** + * Include up to nr_of_certs certificates in an S/MIME message, + * Use "-256" to use the backend's default. + */ + public void set_include_certs(int nr_of_certs = -256); + + /** + * Return the number of certs to include in an S/MIME message + */ + public int get_include_certs(); + + /** + * Set callback function for requesting passphrase. hook_value will be + * passed as first argument. + */ + public void set_passphrase_cb(passphrase_callback cb, void* hook_value = null); + + /** + * Get callback function and hook_value + */ + public void get_passphrase_cb(out passphrase_callback cb, out void* hook_value); + + public GPGError.Error set_locale(int category, string val); + + /** + * Get information about the configured engines. The returned data is valid + * until the next set_engine_info() call. + */ + [CCode (cname = "gpgme_ctx_get_engine_info")] + public EngineInfo* get_engine_info(); + + /** + * Set information about the configured engines. The string parameters may not + * be free'd after this calls, because they are not copied. + */ + [CCode (cname = "gpgme_ctx_set_engine_info")] + public GPGError.Error set_engine_info(Protocol proto, string file_name, string home_dir); + + /** + * Delete all signers + */ + public void signers_clear(); + + /** + * Add key to list of signers + */ + public GPGError.Error signers_add(Key key); + + /** + * Get the n-th signer's key + */ + public Key* signers_enum(int n); + + /** + * Clear all notation data + */ + public void sig_notation_clear(); + + /** + * Add human readable notation data. If name is null, + * then value val should be a policy URL. The HUMAN_READABLE + * flag is forced to be true for notation data and false + * for policy URLs. + */ + public GPGError.Error sig_notation_add(string name, string val, SigNotationFlags flags); + + /** + * Get sig notations + */ + public SigNotation* sig_notation_get(); + + /** + * Get key with the fingerprint FPR from the crypto backend. + * If SECRET is true, get the secret key. + */ + public GPGError.Error get_key(string fpr, out Key key, bool secret); + + /** + * process the pending operation and, if hang is true, wait for + * the pending operation to finish. + */ + public Context* wait(out GPGError.Error status, bool hang); + + /** + * Retrieve a pointer to the results of the signing operation + */ + public SignResult* op_sign_result(); + + /** + * Sign the plaintext PLAIN and store the signature in SIG. + */ + public GPGError.Error op_sign(Data plain, Data sig, SigMode mode); + + /** + * Retrieve a pointer to the result of the verify operation + */ + public VerifyResult* op_verify_result(); + + /** + * Verify that SIG is a valid signature for SIGNED_TEXT. + */ + public GPGError.Error op_verify(Data sig, Data signed_text, Data? plaintext); + + /** + * Retrieve a pointer to the result of the encrypt operation + */ + public EncryptResult* op_encrypt_result(); + + /** + * Encrypt plaintext PLAIN for the recipients RECP and store the + * resulting ciphertext in CIPHER. + */ + public GPGError.Error op_encrypt([CCode (array_length = false)] Key[] recp, EncryptFlags flags, Data plain, Data cipher); + + /** + * Retrieve a pointer to the result of the decrypt operation + */ + public DecryptResult* op_decrypt_result(); + + /** + * Decrypt ciphertext CIPHER and store the resulting plaintext + * in PLAIN. + */ + public GPGError.Error op_decrypt(Data cipher, Data plain); + + /** + * Export the keys found by PATTERN into KEYDATA. If PATTERN is + * NULL all keys will be exported. + */ + public GPGError.Error op_export(string? pattern, ExportMode mode, Data keydata); + + /** + * Import the keys in KEYDATA. + */ + public GPGError.Error op_import(Data keydata); + + /** + * Get result of last op_import. + */ + public unowned ImportResult op_import_result(); + + /** + * Initiates a key listing operation. It sets everything up, so that + * subsequent invocations of op_keylist_next() return the keys in the list. + * + * If pattern is NULL, all available keys are returned. Otherwise, pattern + * contains an engine specific expression that is used to limit the list to + * all keys matching the pattern. + * + * If secret_only is not 0, the list is restricted to secret keys only. + * + * The context will be busy until either all keys are received (and + * op_keylist_next() returns GPG_ERR_EOF), or gpgme_op_keylist_end is called + * to finish the operation. + * + * The function returns the error code GPG_ERR_INV_VALUE if ctx is not a valid + * pointer, and passes through any errors that are reported by the crypto engine + * support routines. + */ + public GPGError.Error op_keylist_start(string? pattern = null, int secret_only = 0); + + /** + * returns the next key in the list created by a previous op_keylist_start() + * operation in the context ctx. The key will have one reference for the user. + * + * If the last key in the list has already been returned, op_keylist_next() + * returns GPG_ERR_EOF. + * + * The function returns the error code GPG_ERR_INV_VALUE if ctx or r_key is + * not a valid pointer, and GPG_ERR_ENOMEM if there is not enough memory for + * the operation. + */ + public GPGError.Error op_keylist_next(out Key key); + + /** + * ends a pending key list operation in the context. + * + * After the operation completed successfully, the result of the key listing + * operation can be retrieved with op_keylist_result(). + * + * The function returns the error code GPG_ERR_INV_VALUE if ctx is not a valid + * pointer, and GPG_ERR_ENOMEM if at some time during the operation there was + * not enough memory available. + */ + public GPGError.Error op_keylist_end(); + + /** + * The function op_keylist_result() returns a KeylistResult holding the result of + * a op_keylist_*() operation. The returned KeylistResult is only valid if the last + * operation on the context was a key listing operation, and if this operation + * finished successfully. The returned KeylistResult is only valid until the next + * operation is started on the context. + */ + public KeylistResult op_keylist_result(); + } + + [Flags] + [CCode (cname="unsigned int")] + public enum ImportStatusFlags { + /** + * The key was new. + */ + [CCode (cname = "GPGME_IMPORT_NEW")] + NEW, + /** + * The key contained new user IDs. + */ + [CCode (cname = "GPGME_IMPORT_UID")] + UID, + /** + * The key contained new signatures. + */ + [CCode (cname = "GPGME_IMPORT_SIG")] + SIG, + /** + * The key contained new sub keys. + */ + [CCode (cname = "GPGME_IMPORT_SUBKEY")] + SUBKEY, + /** + * The key contained a secret key. + */ + [CCode (cname = "GPGME_IMPORT_SECRET")] + SECRET + } + + [Compact] + [CCode (cname = "struct _gpgme_import_status")] + public class ImportStatus { + /** + * This is a pointer to the next status structure in the linked list, or null + * if this is the last element. + */ + public ImportStatus? next; + + /** + * fingerprint of the key that was considered. + */ + public string fpr; + + /** + * If the import was not successful, this is the error value that caused the + * import to fail. Otherwise the error code is GPG_ERR_NO_ERROR. + */ + public GPGError.Error result; + + /** + * Flags what parts of the key have been imported. May be 0, if the key has + * already been known. + */ + public ImportStatusFlags status; + } + + [Compact] + [CCode (cname = "struct _gpgme_op_import_result")] + public class ImportResult { + /** + * The total number of considered keys. + */ + public int considered; + + /** + * The number of keys without user ID. + */ + public int no_user_id; + + /** + * The total number of imported keys. + */ + public int imported; + + /** + * The number of imported RSA keys. + */ + public int imported_rsa; + + /** + * The number of unchanged keys. + */ + public int unchanged; + + /** + * The number of new user IDs. + */ + public int new_user_ids; + + /** + * The number of new sub keys. + */ + public int new_sub_keys; + + /** + * The number of new signatures. + */ + public int new_signatures; + + /** + * The number of new revocations. + */ + public int new_revocations; + + /** + * The total number of secret keys read. + */ + public int secret_read; + + /** + * The number of imported secret keys. + */ + public int secret_imported; + + /** + * The number of unchanged secret keys. + */ + public int secret_unchanged; + + /** + * The number of keys not imported. + */ + public int not_imported; + + /* + * A linked list of ImportStatus objects which + * contains more information about the keys for + * which an import was attempted. + */ + public ImportStatus imports; + } + + [Compact] + [CCode (cname = "struct _gpgme_op_keylist_result")] + public class KeylistResult { + uint truncated; + } + + + /** + * Data Object, contains encrypted and/or unencrypted data + */ + [Compact] + [CCode (cname = "struct gpgme_data", free_function = "gpgme_data_release", cprefix = "gpgme_data_")] + public class Data { + /** + * Create a new data buffer, returns Error Status Code. + */ + [CCode (cname = "gpgme_data_new")] + public static GPGError.Error create(out Data d); + + /** + * Create a new data buffer filled with SIZE bytes starting + * from BUFFER. If COPY is false, COPYING is delayed until + * necessary and the data is taken from the original location + * when needed. Returns Error Status Code. + */ + [CCode (cname = "gpgme_data_new_from_mem")] + public static GPGError.Error create_from_memory(out Data d, uint8[] buffer, bool copy); + + /** + * Create a new data buffer filled with the content of the file. + * COPY must be non-zero. For delayed read, please use + * create_from_fd or create_from stream instead. + */ + [CCode (cname = "gpgme_data_new_from_file")] + public static GPGError.Error create_from_file(out Data d, string filename, int copy = 1); + + + /** + * Destroy the object and return a pointer to its content. + * It's size is returned in R_LEN. + */ + [CCode (cname = "gpgme_data_release_and_get_mem")] + public string release_and_get_mem(out size_t len); + + /** + * Read up to SIZE bytes into buffer BUFFER from the data object. + * Return the number of characters read, 0 on EOF and -1 on error. + * If an error occurs, errno is set. + */ + public ssize_t read(uint8[] buf); + + /** + * Write up to SIZE bytes from buffer BUFFER to the data object. + * Return the number of characters written, or -1 on error. + * If an error occurs, errno is set. + */ + public ssize_t write(uint8[] buf); + + /** + * Set the current position from where the next read or write + * starts in the data object to OFFSET, relativ to WHENCE. + */ + public long seek(long offset, int whence=0); + + /** + * Get the encoding attribute of the buffer + */ + public DataEncoding *get_encoding(); + + /** + * Set the encoding attribute of the buffer to ENC + */ + public GPGError.Error set_encoding(DataEncoding enc); + } + + [CCode (cname = "gpgme_get_protocol_name")] + public unowned string get_protocol_name(Protocol p); + + [CCode (cname = "gpgme_pubkey_algo_name")] + public unowned string get_public_key_algorithm_name(PublicKeyAlgorithm algo); + + [CCode (cname = "gpgme_hash_algo_name")] + public unowned string get_hash_algorithm_name(HashAlgorithm algo); + + [CCode (cname = "gpgme_passphrase_cb_t", has_target = false)] + public delegate GPGError.Error passphrase_callback(void* hook, string uid_hint, string passphrase_info, bool prev_was_bad, int fd); + + /** + * Get version of libgpgme + * Always call this function before using gpgme, it initializes some stuff + */ + [CCode (cname = "gpgme_check_version")] + public unowned string check_version(string? required_version = null); + + /** + * Verify that the engine implementing proto is installed and + * available. + */ + [CCode (cname = "gpgme_engine_check_version")] + public GPGError.Error engine_check_version(Protocol proto); + + /** + * Get information about the configured engines. The returned data is valid + * until the next set_engine_info() call. + */ + [CCode (cname = "gpgme_get_engine_info")] + public GPGError.Error get_engine_info(out EngineInfo? engine_info); + + /** + * Return the error string for ERR in the user-supplied buffer BUF + * of size BUFLEN. This function is thread-safe, if a thread-safe + * strerror_r() function is provided by the system. If the function + * succeeds, 0 is returned and BUF contains the string describing + * the error. If the buffer was not large enough, ERANGE is returned + * and BUF contains as much of the beginning of the error string as + * fits into the buffer. Returns Error Status Code. + */ + [CCode (cname = "gpgme_strerror_r")] + public int strerror_r(GPGError.Error err, uint8[] buf); + + /** + * Like strerror_r, but returns a pointer to the string. This method + * is not thread safe! + */ + [CCode (cname = "gpgme_strerror")] + public unowned string strerror(GPGError.Error err); +}