Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F20320883
context.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
48 KB
Subscribers
None
context.cpp
View Options
/*
context.cpp - wraps a gpgme key context
Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
This file is part of GPGME++.
GPGME++ is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
GPGME++ 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 Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with GPGME++; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include
"config-gpgme++.h"
#include
<context.h>
#include
<eventloopinteractor.h>
#include
<trustitem.h>
#include
<assuanresult.h>
#include
<keylistresult.h>
#include
<keygenerationresult.h>
#include
<importresult.h>
#include
<decryptionresult.h>
#include
<verificationresult.h>
#include
<signingresult.h>
#include
<encryptionresult.h>
#include
<engineinfo.h>
#include
<editinteractor.h>
#include
<vfsmountresult.h>
#include
<interfaces/assuantransaction.h>
#include
<defaultassuantransaction.h>
#include
"callbacks.h"
#include
"data_p.h"
#include
"context_p.h"
#include
"util.h"
#include
<gpgme.h>
#include
<boost/scoped_array.hpp>
#include
<istream>
#ifndef NDEBUG
#include
<iostream>
using
std
::
cerr
;
using
std
::
endl
;
#endif
#include
<cassert>
#include
<qglobal.h>
namespace
GpgME
{
static
inline
unsigned
int
xtoi_1
(
const
char
*
str
)
{
const
unsigned
int
ch
=
*
str
;
const
unsigned
int
result
=
ch
<=
'9'
?
ch
-
'0'
:
ch
<=
'F'
?
ch
-
'A'
+
10
:
/* else */
ch
-
'a'
+
10
;
return
result
<
16
?
result
:
0
;
}
static
inline
int
xtoi_2
(
const
char
*
str
)
{
return
xtoi_1
(
str
)
*
16U
+
xtoi_1
(
str
+
1
);
}
#ifdef HAVE_GPGME_ASSUAN_ENGINE
static
void
percent_unescape
(
std
::
string
&
s
,
bool
plus2space
)
{
std
::
string
::
iterator
src
=
s
.
begin
(),
dest
=
s
.
begin
(),
end
=
s
.
end
();
while
(
src
!=
end
)
{
if
(
*
src
==
'%'
&&
end
-
src
>
2
)
{
*
dest
++
=
xtoi_2
(
&*++
src
);
src
+=
2
;
}
else
if
(
*
src
==
'+'
&&
plus2space
)
{
*
dest
++
=
' '
;
++
src
;
}
else
{
*
dest
++
=
*
src
++
;
}
}
s
.
erase
(
dest
,
end
);
}
#endif
void
initializeLibrary
()
{
gpgme_check_version
(
0
);
}
Error
initializeLibrary
(
int
)
{
if
(
gpgme_check_version
(
GPGME_VERSION
))
{
return
Error
();
}
else
{
return
Error
::
fromCode
(
GPG_ERR_USER_1
);
}
}
static
void
format_error
(
gpgme_error_t
err
,
std
::
string
&
str
)
{
char
buffer
[
1024
];
gpgme_strerror_r
(
err
,
buffer
,
sizeof
buffer
);
buffer
[
sizeof
buffer
-
1
]
=
'\0'
;
str
=
buffer
;
}
const
char
*
Error
::
source
()
const
{
return
gpgme_strsource
((
gpgme_error_t
)
mErr
);
}
const
char
*
Error
::
asString
()
const
{
if
(
mMessage
.
empty
())
{
format_error
(
static_cast
<
gpgme_error_t
>
(
mErr
),
mMessage
);
}
return
mMessage
.
c_str
();
}
int
Error
::
code
()
const
{
return
gpgme_err_code
(
mErr
);
}
int
Error
::
sourceID
()
const
{
return
gpgme_err_source
(
mErr
);
}
bool
Error
::
isCanceled
()
const
{
return
code
()
==
GPG_ERR_CANCELED
;
}
int
Error
::
toErrno
()
const
{
//#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
return
gpgme_err_code_to_errno
(
static_cast
<
gpgme_err_code_t
>
(
code
()));
//#else
// return gpg_err_code_to_errno( static_cast<gpg_err_code_t>( code() ) );
//#endif
}
// static
bool
Error
::
hasSystemError
()
{
#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
return
gpgme_err_code_from_syserror
()
==
GPG_ERR_MISSING_ERRNO
;
#else
return
gpg_err_code_from_syserror
()
==
GPG_ERR_MISSING_ERRNO
;
#endif
}
// static
void
Error
::
setSystemError
(
gpg_err_code_t
err
)
{
setErrno
(
gpgme_err_code_to_errno
(
err
));
}
// static
void
Error
::
setErrno
(
int
err
)
{
#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
gpgme_err_set_errno
(
err
);
#else
gpg_err_set_errno
(
err
);
#endif
}
// static
Error
Error
::
fromSystemError
(
unsigned
int
src
)
{
#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
return
Error
(
gpgme_err_make
(
static_cast
<
gpgme_err_source_t
>
(
src
),
gpgme_err_code_from_syserror
()));
#else
return
Error
(
gpg_err_make
(
static_cast
<
gpg_err_source_t
>
(
src
),
gpg_err_code_from_syserror
()));
#endif
}
// static
Error
Error
::
fromErrno
(
int
err
,
unsigned
int
src
)
{
//#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
return
Error
(
gpgme_err_make
(
static_cast
<
gpgme_err_source_t
>
(
src
),
gpgme_err_code_from_errno
(
err
)));
//#else
// return Error( gpg_err_make( static_cast<gpg_err_source_t>( src ), gpg_err_from_from_errno( err ) ) );
//#endif
}
// static
Error
Error
::
fromCode
(
unsigned
int
err
,
unsigned
int
src
)
{
//#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
return
Error
(
gpgme_err_make
(
static_cast
<
gpgme_err_source_t
>
(
src
),
static_cast
<
gpgme_err_code_t
>
(
err
)));
//#else
// return Error( gpg_err_make( static_cast<gpg_err_source_t>( src ), static_cast<gpgme_err_code_t>( err ) ) );
//#endif
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Error
&
err
)
{
return
os
<<
"GpgME::Error("
<<
err
.
encodedError
()
<<
" ("
<<
err
.
asString
()
<<
"))"
;
}
Context
::
Context
(
gpgme_ctx_t
ctx
)
:
d
(
new
Private
(
ctx
))
{
}
Context
::~
Context
()
{
delete
d
;
}
Context
*
Context
::
createForProtocol
(
Protocol
proto
)
{
gpgme_ctx_t
ctx
=
0
;
if
(
gpgme_new
(
&
ctx
)
!=
0
)
{
return
0
;
}
switch
(
proto
)
{
case
OpenPGP
:
if
(
gpgme_set_protocol
(
ctx
,
GPGME_PROTOCOL_OpenPGP
)
!=
0
)
{
gpgme_release
(
ctx
);
return
0
;
}
break
;
case
CMS
:
if
(
gpgme_set_protocol
(
ctx
,
GPGME_PROTOCOL_CMS
)
!=
0
)
{
gpgme_release
(
ctx
);
return
0
;
}
break
;
default
:
return
0
;
}
return
new
Context
(
ctx
);
}
std
::
auto_ptr
<
Context
>
Context
::
createForEngine
(
Engine
eng
,
Error
*
error
)
{
gpgme_ctx_t
ctx
=
0
;
if
(
const
gpgme_error_t
err
=
gpgme_new
(
&
ctx
))
{
if
(
error
)
{
*
error
=
Error
(
err
);
}
return
std
::
auto_ptr
<
Context
>
();
}
switch
(
eng
)
{
case
AssuanEngine
:
#ifdef HAVE_GPGME_ASSUAN_ENGINE
if
(
const
gpgme_error_t
err
=
gpgme_set_protocol
(
ctx
,
GPGME_PROTOCOL_ASSUAN
))
{
gpgme_release
(
ctx
);
if
(
error
)
{
*
error
=
Error
(
err
);
}
return
std
::
auto_ptr
<
Context
>
();
}
break
;
#else
if
(
error
)
{
*
error
=
Error
::
fromCode
(
GPG_ERR_NOT_SUPPORTED
);
}
return
std
::
auto_ptr
<
Context
>
();
#endif
case
G13Engine
:
#ifdef HAVE_GPGME_G13_VFS
if
(
const
gpgme_error_t
err
=
gpgme_set_protocol
(
ctx
,
GPGME_PROTOCOL_G13
))
{
gpgme_release
(
ctx
);
if
(
error
)
{
*
error
=
Error
(
err
);
}
return
std
::
auto_ptr
<
Context
>
();
}
break
;
#else
if
(
error
)
{
*
error
=
Error
::
fromCode
(
GPG_ERR_NOT_SUPPORTED
);
}
return
std
::
auto_ptr
<
Context
>
();
#endif
default
:
if
(
error
)
{
*
error
=
Error
::
fromCode
(
GPG_ERR_INV_ARG
);
}
return
std
::
auto_ptr
<
Context
>
();
}
if
(
error
)
{
*
error
=
Error
();
}
return
std
::
auto_ptr
<
Context
>
(
new
Context
(
ctx
));
}
//
//
// Context::Private
//
//
Context
::
Private
::
Private
(
gpgme_ctx_t
c
)
:
ctx
(
c
),
iocbs
(
0
),
lastop
(
None
),
lasterr
(
GPG_ERR_NO_ERROR
),
lastAssuanInquireData
(
Data
::
null
),
lastAssuanTransaction
(),
lastEditInteractor
(),
lastCardEditInteractor
()
{
}
Context
::
Private
::~
Private
()
{
if
(
ctx
)
{
gpgme_release
(
ctx
);
}
ctx
=
0
;
delete
iocbs
;
}
//
//
// Context attributes:
//
//
Protocol
Context
::
protocol
()
const
{
gpgme_protocol_t
p
=
gpgme_get_protocol
(
d
->
ctx
);
switch
(
p
)
{
case
GPGME_PROTOCOL_OpenPGP
:
return
OpenPGP
;
case
GPGME_PROTOCOL_CMS
:
return
CMS
;
default
:
return
UnknownProtocol
;
}
}
void
Context
::
setArmor
(
bool
useArmor
)
{
gpgme_set_armor
(
d
->
ctx
,
int
(
useArmor
));
}
bool
Context
::
armor
()
const
{
return
gpgme_get_armor
(
d
->
ctx
);
}
void
Context
::
setTextMode
(
bool
useTextMode
)
{
gpgme_set_textmode
(
d
->
ctx
,
int
(
useTextMode
));
}
bool
Context
::
textMode
()
const
{
return
gpgme_get_textmode
(
d
->
ctx
);
}
void
Context
::
setOffline
(
bool
useOfflineMode
)
{
#ifdef HAVE_GPGME_CTX_OFFLINE
gpgme_set_offline
(
d
->
ctx
,
int
(
useOfflineMode
));
#else
Q_UNUSED
(
useOfflineMode
);
#endif
}
bool
Context
::
offline
()
const
{
#ifdef HAVE_GPGME_CTX_OFFLINE
return
gpgme_get_offline
(
d
->
ctx
);
#else
return
false
;
#endif
}
void
Context
::
setIncludeCertificates
(
int
which
)
{
if
(
which
==
DefaultCertificates
)
{
#ifdef HAVE_GPGME_INCLUDE_CERTS_DEFAULT
which
=
GPGME_INCLUDE_CERTS_DEFAULT
;
#else
which
=
1
;
#endif
}
gpgme_set_include_certs
(
d
->
ctx
,
which
);
}
int
Context
::
includeCertificates
()
const
{
return
gpgme_get_include_certs
(
d
->
ctx
);
}
void
Context
::
setKeyListMode
(
unsigned
int
mode
)
{
gpgme_set_keylist_mode
(
d
->
ctx
,
add_to_gpgme_keylist_mode_t
(
0
,
mode
));
}
void
Context
::
addKeyListMode
(
unsigned
int
mode
)
{
const
unsigned
int
cur
=
gpgme_get_keylist_mode
(
d
->
ctx
);
gpgme_set_keylist_mode
(
d
->
ctx
,
add_to_gpgme_keylist_mode_t
(
cur
,
mode
));
}
unsigned
int
Context
::
keyListMode
()
const
{
return
convert_from_gpgme_keylist_mode_t
(
gpgme_get_keylist_mode
(
d
->
ctx
));
}
void
Context
::
setProgressProvider
(
ProgressProvider
*
provider
)
{
gpgme_set_progress_cb
(
d
->
ctx
,
provider
?
&
progress_callback
:
0
,
provider
);
}
ProgressProvider
*
Context
::
progressProvider
()
const
{
void
*
pp
=
0
;
gpgme_progress_cb_t
pcb
=
&
progress_callback
;
gpgme_get_progress_cb
(
d
->
ctx
,
&
pcb
,
&
pp
);
return
static_cast
<
ProgressProvider
*>
(
pp
);
}
void
Context
::
setPassphraseProvider
(
PassphraseProvider
*
provider
)
{
gpgme_set_passphrase_cb
(
d
->
ctx
,
provider
?
&
passphrase_callback
:
0
,
provider
);
}
PassphraseProvider
*
Context
::
passphraseProvider
()
const
{
void
*
pp
=
0
;
gpgme_passphrase_cb_t
pcb
=
&
passphrase_callback
;
gpgme_get_passphrase_cb
(
d
->
ctx
,
&
pcb
,
&
pp
);
return
static_cast
<
PassphraseProvider
*>
(
pp
);
}
void
Context
::
setManagedByEventLoopInteractor
(
bool
manage
)
{
if
(
!
EventLoopInteractor
::
instance
())
{
#ifndef NDEBUG
cerr
<<
"Context::setManagedByEventLoopInteractor(): "
"You must create an instance of EventLoopInteractor "
"before using anything that needs one."
<<
endl
;
#endif
return
;
}
if
(
manage
)
{
EventLoopInteractor
::
instance
()
->
manage
(
this
);
}
else
{
EventLoopInteractor
::
instance
()
->
unmanage
(
this
);
}
}
bool
Context
::
managedByEventLoopInteractor
()
const
{
return
d
->
iocbs
!=
0
;
}
void
Context
::
installIOCallbacks
(
gpgme_io_cbs
*
iocbs
)
{
if
(
!
iocbs
)
{
uninstallIOCallbacks
();
return
;
}
gpgme_set_io_cbs
(
d
->
ctx
,
iocbs
);
delete
d
->
iocbs
;
d
->
iocbs
=
iocbs
;
}
void
Context
::
uninstallIOCallbacks
()
{
static
gpgme_io_cbs
noiocbs
=
{
0
,
0
,
0
,
0
,
0
};
// io.add == 0 means disable io callbacks:
gpgme_set_io_cbs
(
d
->
ctx
,
&
noiocbs
);
delete
d
->
iocbs
;
d
->
iocbs
=
0
;
}
Error
Context
::
setLocale
(
int
cat
,
const
char
*
val
)
{
return
Error
(
d
->
lasterr
=
gpgme_set_locale
(
d
->
ctx
,
cat
,
val
));
}
EngineInfo
Context
::
engineInfo
()
const
{
#ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO
return
EngineInfo
(
gpgme_ctx_get_engine_info
(
d
->
ctx
));
#else
return
EngineInfo
();
#endif
}
Error
Context
::
setEngineFileName
(
const
char
*
filename
)
{
#ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO
const
char
*
const
home_dir
=
engineInfo
().
homeDirectory
();
return
Error
(
gpgme_ctx_set_engine_info
(
d
->
ctx
,
gpgme_get_protocol
(
d
->
ctx
),
filename
,
home_dir
));
#else
return
Error
::
fromCode
(
GPG_ERR_NOT_IMPLEMENTED
);
#endif
}
Error
Context
::
setEngineHomeDirectory
(
const
char
*
home_dir
)
{
#ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO
const
char
*
const
filename
=
engineInfo
().
fileName
();
return
Error
(
gpgme_ctx_set_engine_info
(
d
->
ctx
,
gpgme_get_protocol
(
d
->
ctx
),
filename
,
home_dir
));
#else
return
Error
::
fromCode
(
GPG_ERR_NOT_IMPLEMENTED
);
#endif
}
//
//
// Key Management
//
//
Error
Context
::
startKeyListing
(
const
char
*
pattern
,
bool
secretOnly
)
{
d
->
lastop
=
Private
::
KeyList
;
return
Error
(
d
->
lasterr
=
gpgme_op_keylist_start
(
d
->
ctx
,
pattern
,
int
(
secretOnly
)));
}
Error
Context
::
startKeyListing
(
const
char
*
patterns
[],
bool
secretOnly
)
{
d
->
lastop
=
Private
::
KeyList
;
#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
if
(
!
patterns
||
!
patterns
[
0
]
||
!
patterns
[
1
])
{
// max. one pattern -> use the non-ext version
return
startKeyListing
(
patterns
?
patterns
[
0
]
:
0
,
secretOnly
);
}
#endif
return
Error
(
d
->
lasterr
=
gpgme_op_keylist_ext_start
(
d
->
ctx
,
patterns
,
int
(
secretOnly
),
0
));
}
Key
Context
::
nextKey
(
GpgME
::
Error
&
e
)
{
d
->
lastop
=
Private
::
KeyList
;
gpgme_key_t
key
;
e
=
Error
(
d
->
lasterr
=
gpgme_op_keylist_next
(
d
->
ctx
,
&
key
));
return
Key
(
key
,
false
);
}
KeyListResult
Context
::
endKeyListing
()
{
d
->
lasterr
=
gpgme_op_keylist_end
(
d
->
ctx
);
return
keyListResult
();
}
KeyListResult
Context
::
keyListResult
()
const
{
return
KeyListResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
Key
Context
::
key
(
const
char
*
fingerprint
,
GpgME
::
Error
&
e
,
bool
secret
/*, bool forceUpdate*/
)
{
d
->
lastop
=
Private
::
KeyList
;
gpgme_key_t
key
;
e
=
Error
(
d
->
lasterr
=
gpgme_get_key
(
d
->
ctx
,
fingerprint
,
&
key
,
int
(
secret
)
/*, int( forceUpdate )*/
));
return
Key
(
key
,
false
);
}
KeyGenerationResult
Context
::
generateKey
(
const
char
*
parameters
,
Data
&
pubKey
)
{
d
->
lastop
=
Private
::
KeyGen
;
Data
::
Private
*
const
dp
=
pubKey
.
impl
();
d
->
lasterr
=
gpgme_op_genkey
(
d
->
ctx
,
parameters
,
dp
?
dp
->
data
:
0
,
0
);
return
KeyGenerationResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
Error
Context
::
startKeyGeneration
(
const
char
*
parameters
,
Data
&
pubKey
)
{
d
->
lastop
=
Private
::
KeyGen
;
Data
::
Private
*
const
dp
=
pubKey
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_genkey_start
(
d
->
ctx
,
parameters
,
dp
?
dp
->
data
:
0
,
0
));
}
KeyGenerationResult
Context
::
keyGenerationResult
()
const
{
if
(
d
->
lastop
&
Private
::
KeyGen
)
{
return
KeyGenerationResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
else
{
return
KeyGenerationResult
();
}
}
Error
Context
::
exportPublicKeys
(
const
char
*
pattern
,
Data
&
keyData
)
{
d
->
lastop
=
Private
::
Export
;
Data
::
Private
*
const
dp
=
keyData
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_export
(
d
->
ctx
,
pattern
,
0
,
dp
?
dp
->
data
:
0
));
}
Error
Context
::
exportPublicKeys
(
const
char
*
patterns
[],
Data
&
keyData
)
{
d
->
lastop
=
Private
::
Export
;
#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
if
(
!
patterns
||
!
patterns
[
0
]
||
!
patterns
[
1
])
{
// max. one pattern -> use the non-ext version
return
exportPublicKeys
(
patterns
?
patterns
[
0
]
:
0
,
keyData
);
}
#endif
Data
::
Private
*
const
dp
=
keyData
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_export_ext
(
d
->
ctx
,
patterns
,
0
,
dp
?
dp
->
data
:
0
));
}
Error
Context
::
startPublicKeyExport
(
const
char
*
pattern
,
Data
&
keyData
)
{
d
->
lastop
=
Private
::
Export
;
Data
::
Private
*
const
dp
=
keyData
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_export_start
(
d
->
ctx
,
pattern
,
0
,
dp
?
dp
->
data
:
0
));
}
Error
Context
::
startPublicKeyExport
(
const
char
*
patterns
[],
Data
&
keyData
)
{
d
->
lastop
=
Private
::
Export
;
#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
if
(
!
patterns
||
!
patterns
[
0
]
||
!
patterns
[
1
])
{
// max. one pattern -> use the non-ext version
return
startPublicKeyExport
(
patterns
?
patterns
[
0
]
:
0
,
keyData
);
}
#endif
Data
::
Private
*
const
dp
=
keyData
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_export_ext_start
(
d
->
ctx
,
patterns
,
0
,
dp
?
dp
->
data
:
0
));
}
ImportResult
Context
::
importKeys
(
const
Data
&
data
)
{
d
->
lastop
=
Private
::
Import
;
const
Data
::
Private
*
const
dp
=
data
.
impl
();
d
->
lasterr
=
gpgme_op_import
(
d
->
ctx
,
dp
?
dp
->
data
:
0
);
return
ImportResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
ImportResult
Context
::
importKeys
(
const
std
::
vector
<
Key
>
&
kk
)
{
d
->
lastop
=
Private
::
Import
;
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_IMPLEMENTED
);
bool
shouldHaveResult
=
false
;
#ifdef HAVE_GPGME_OP_IMPORT_KEYS
const
boost
::
scoped_array
<
gpgme_key_t
>
keys
(
new
gpgme_key_t
[
kk
.
size
()
+
1
]);
gpgme_key_t
*
keys_it
=
&
keys
[
0
];
for
(
std
::
vector
<
Key
>::
const_iterator
it
=
kk
.
begin
(),
end
=
kk
.
end
()
;
it
!=
end
;
++
it
)
{
if
(
it
->
impl
())
{
*
keys_it
++
=
it
->
impl
();
}
}
*
keys_it
++
=
0
;
d
->
lasterr
=
gpgme_op_import_keys
(
d
->
ctx
,
keys
.
get
());
shouldHaveResult
=
true
;
#endif
if
((
gpgme_err_code
(
d
->
lasterr
)
==
GPG_ERR_NOT_IMPLEMENTED
||
gpgme_err_code
(
d
->
lasterr
)
==
GPG_ERR_NOT_SUPPORTED
)
&&
protocol
()
==
CMS
)
{
// ok, try the workaround (export+import):
std
::
vector
<
const
char
*>
fprs
;
for
(
std
::
vector
<
Key
>::
const_iterator
it
=
kk
.
begin
(),
end
=
kk
.
end
()
;
it
!=
end
;
++
it
)
{
if
(
const
char
*
fpr
=
it
->
primaryFingerprint
())
{
if
(
*
fpr
)
{
fprs
.
push_back
(
fpr
);
}
}
else
if
(
const
char
*
keyid
=
it
->
keyID
())
{
if
(
*
keyid
)
{
fprs
.
push_back
(
keyid
);
}
}
}
fprs
.
push_back
(
0
);
Data
data
;
Data
::
Private
*
const
dp
=
data
.
impl
();
const
gpgme_keylist_mode_t
oldMode
=
gpgme_get_keylist_mode
(
d
->
ctx
);
gpgme_set_keylist_mode
(
d
->
ctx
,
GPGME_KEYLIST_MODE_EXTERN
);
d
->
lasterr
=
gpgme_op_export_ext
(
d
->
ctx
,
&
fprs
[
0
],
0
,
dp
?
dp
->
data
:
0
);
gpgme_set_keylist_mode
(
d
->
ctx
,
oldMode
);
if
(
!
d
->
lasterr
)
{
data
.
seek
(
0
,
SEEK_SET
);
d
->
lasterr
=
gpgme_op_import
(
d
->
ctx
,
dp
?
dp
->
data
:
0
);
shouldHaveResult
=
true
;
}
}
if
(
shouldHaveResult
)
{
return
ImportResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
else
{
return
ImportResult
(
Error
(
d
->
lasterr
));
}
}
Error
Context
::
startKeyImport
(
const
Data
&
data
)
{
d
->
lastop
=
Private
::
Import
;
const
Data
::
Private
*
const
dp
=
data
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_import_start
(
d
->
ctx
,
dp
?
dp
->
data
:
0
));
}
Error
Context
::
startKeyImport
(
const
std
::
vector
<
Key
>
&
kk
)
{
d
->
lastop
=
Private
::
Import
;
#ifdef HAVE_GPGME_OP_IMPORT_KEYS
const
boost
::
scoped_array
<
gpgme_key_t
>
keys
(
new
gpgme_key_t
[
kk
.
size
()
+
1
]);
gpgme_key_t
*
keys_it
=
&
keys
[
0
];
for
(
std
::
vector
<
Key
>::
const_iterator
it
=
kk
.
begin
(),
end
=
kk
.
end
()
;
it
!=
end
;
++
it
)
{
if
(
it
->
impl
())
{
*
keys_it
++
=
it
->
impl
();
}
}
*
keys_it
++
=
0
;
return
Error
(
d
->
lasterr
=
gpgme_op_import_keys_start
(
d
->
ctx
,
keys
.
get
()));
#else
(
void
)
kk
;
return
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_IMPLEMENTED
));
#endif
}
ImportResult
Context
::
importResult
()
const
{
if
(
d
->
lastop
&
Private
::
Import
)
{
return
ImportResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
else
{
return
ImportResult
();
}
}
Error
Context
::
deleteKey
(
const
Key
&
key
,
bool
allowSecretKeyDeletion
)
{
d
->
lastop
=
Private
::
Delete
;
return
Error
(
d
->
lasterr
=
gpgme_op_delete
(
d
->
ctx
,
key
.
impl
(),
int
(
allowSecretKeyDeletion
)));
}
Error
Context
::
startKeyDeletion
(
const
Key
&
key
,
bool
allowSecretKeyDeletion
)
{
d
->
lastop
=
Private
::
Delete
;
return
Error
(
d
->
lasterr
=
gpgme_op_delete_start
(
d
->
ctx
,
key
.
impl
(),
int
(
allowSecretKeyDeletion
)));
}
Error
Context
::
passwd
(
const
Key
&
key
)
{
d
->
lastop
=
Private
::
Passwd
;
#ifdef HAVE_GPGME_OP_PASSWD
return
Error
(
d
->
lasterr
=
gpgme_op_passwd
(
d
->
ctx
,
key
.
impl
(),
0U
));
#else
(
void
)
key
;
return
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_IMPLEMENTED
));
#endif
}
Error
Context
::
startPasswd
(
const
Key
&
key
)
{
d
->
lastop
=
Private
::
Passwd
;
#ifdef HAVE_GPGME_OP_PASSWD
return
Error
(
d
->
lasterr
=
gpgme_op_passwd_start
(
d
->
ctx
,
key
.
impl
(),
0U
));
#else
(
void
)
key
;
return
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_IMPLEMENTED
));
#endif
}
Error
Context
::
edit
(
const
Key
&
key
,
std
::
auto_ptr
<
EditInteractor
>
func
,
Data
&
data
)
{
d
->
lastop
=
Private
::
Edit
;
d
->
lastEditInteractor
=
func
;
Data
::
Private
*
const
dp
=
data
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_edit
(
d
->
ctx
,
key
.
impl
(),
d
->
lastEditInteractor
.
get
()
?
edit_interactor_callback
:
0
,
d
->
lastEditInteractor
.
get
()
?
d
->
lastEditInteractor
->
d
:
0
,
dp
?
dp
->
data
:
0
));
}
Error
Context
::
startEditing
(
const
Key
&
key
,
std
::
auto_ptr
<
EditInteractor
>
func
,
Data
&
data
)
{
d
->
lastop
=
Private
::
Edit
;
d
->
lastEditInteractor
=
func
;
Data
::
Private
*
const
dp
=
data
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_edit_start
(
d
->
ctx
,
key
.
impl
(),
d
->
lastEditInteractor
.
get
()
?
edit_interactor_callback
:
0
,
d
->
lastEditInteractor
.
get
()
?
d
->
lastEditInteractor
->
d
:
0
,
dp
?
dp
->
data
:
0
));
}
EditInteractor
*
Context
::
lastEditInteractor
()
const
{
return
d
->
lastEditInteractor
.
get
();
}
std
::
auto_ptr
<
EditInteractor
>
Context
::
takeLastEditInteractor
()
{
return
d
->
lastEditInteractor
;
}
Error
Context
::
cardEdit
(
const
Key
&
key
,
std
::
auto_ptr
<
EditInteractor
>
func
,
Data
&
data
)
{
d
->
lastop
=
Private
::
CardEdit
;
d
->
lastCardEditInteractor
=
func
;
Data
::
Private
*
const
dp
=
data
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_card_edit
(
d
->
ctx
,
key
.
impl
(),
d
->
lastCardEditInteractor
.
get
()
?
edit_interactor_callback
:
0
,
d
->
lastCardEditInteractor
.
get
()
?
d
->
lastCardEditInteractor
->
d
:
0
,
dp
?
dp
->
data
:
0
));
}
Error
Context
::
startCardEditing
(
const
Key
&
key
,
std
::
auto_ptr
<
EditInteractor
>
func
,
Data
&
data
)
{
d
->
lastop
=
Private
::
CardEdit
;
d
->
lastCardEditInteractor
=
func
;
Data
::
Private
*
const
dp
=
data
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_card_edit_start
(
d
->
ctx
,
key
.
impl
(),
d
->
lastCardEditInteractor
.
get
()
?
edit_interactor_callback
:
0
,
d
->
lastCardEditInteractor
.
get
()
?
d
->
lastCardEditInteractor
->
d
:
0
,
dp
?
dp
->
data
:
0
));
}
EditInteractor
*
Context
::
lastCardEditInteractor
()
const
{
return
d
->
lastCardEditInteractor
.
get
();
}
std
::
auto_ptr
<
EditInteractor
>
Context
::
takeLastCardEditInteractor
()
{
return
d
->
lastCardEditInteractor
;
}
Error
Context
::
startTrustItemListing
(
const
char
*
pattern
,
int
maxLevel
)
{
d
->
lastop
=
Private
::
TrustList
;
return
Error
(
d
->
lasterr
=
gpgme_op_trustlist_start
(
d
->
ctx
,
pattern
,
maxLevel
));
}
TrustItem
Context
::
nextTrustItem
(
Error
&
e
)
{
gpgme_trust_item_t
ti
=
0
;
e
=
Error
(
d
->
lasterr
=
gpgme_op_trustlist_next
(
d
->
ctx
,
&
ti
));
return
TrustItem
(
ti
);
}
Error
Context
::
endTrustItemListing
()
{
return
Error
(
d
->
lasterr
=
gpgme_op_trustlist_end
(
d
->
ctx
));
}
#ifdef HAVE_GPGME_ASSUAN_ENGINE
static
gpgme_error_t
assuan_transaction_data_callback
(
void
*
opaque
,
const
void
*
data
,
size_t
datalen
)
{
assert
(
opaque
);
AssuanTransaction
*
t
=
static_cast
<
AssuanTransaction
*>
(
opaque
);
return
t
->
data
(
static_cast
<
const
char
*>
(
data
),
datalen
).
encodedError
();
}
static
gpgme_error_t
assuan_transaction_inquire_callback
(
void
*
opaque
,
const
char
*
name
,
const
char
*
args
,
gpgme_data_t
*
r_data
)
{
assert
(
opaque
);
Context
::
Private
*
p
=
static_cast
<
Context
::
Private
*>
(
opaque
);
AssuanTransaction
*
t
=
p
->
lastAssuanTransaction
.
get
();
assert
(
t
);
Error
err
;
if
(
name
)
{
p
->
lastAssuanInquireData
=
t
->
inquire
(
name
,
args
,
err
);
}
else
{
p
->
lastAssuanInquireData
=
Data
::
null
;
}
if
(
!
p
->
lastAssuanInquireData
.
isNull
())
{
*
r_data
=
p
->
lastAssuanInquireData
.
impl
()
->
data
;
}
return
err
.
encodedError
();
}
static
gpgme_error_t
assuan_transaction_status_callback
(
void
*
opaque
,
const
char
*
status
,
const
char
*
args
)
{
assert
(
opaque
);
AssuanTransaction
*
t
=
static_cast
<
AssuanTransaction
*>
(
opaque
);
std
::
string
a
=
args
;
percent_unescape
(
a
,
true
);
// ### why doesn't gpgme do this??
return
t
->
status
(
status
,
a
.
c_str
()).
encodedError
();
}
#endif
AssuanResult
Context
::
assuanTransact
(
const
char
*
command
)
{
return
assuanTransact
(
command
,
std
::
auto_ptr
<
AssuanTransaction
>
(
new
DefaultAssuanTransaction
));
}
AssuanResult
Context
::
assuanTransact
(
const
char
*
command
,
std
::
auto_ptr
<
AssuanTransaction
>
transaction
)
{
d
->
lastop
=
Private
::
AssuanTransact
;
d
->
lastAssuanTransaction
=
transaction
;
if
(
!
d
->
lastAssuanTransaction
.
get
())
{
return
AssuanResult
(
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_INV_ARG
)));
}
#ifdef HAVE_GPGME_ASSUAN_ENGINE
d
->
lasterr
=
gpgme_op_assuan_transact
(
d
->
ctx
,
command
,
assuan_transaction_data_callback
,
d
->
lastAssuanTransaction
.
get
(),
assuan_transaction_inquire_callback
,
d
,
// sic!
assuan_transaction_status_callback
,
d
->
lastAssuanTransaction
.
get
());
#else
(
void
)
command
;
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_SUPPORTED
);
#endif
return
AssuanResult
(
d
->
ctx
,
d
->
lasterr
);
}
Error
Context
::
startAssuanTransaction
(
const
char
*
command
)
{
return
startAssuanTransaction
(
command
,
std
::
auto_ptr
<
AssuanTransaction
>
(
new
DefaultAssuanTransaction
));
}
Error
Context
::
startAssuanTransaction
(
const
char
*
command
,
std
::
auto_ptr
<
AssuanTransaction
>
transaction
)
{
d
->
lastop
=
Private
::
AssuanTransact
;
d
->
lastAssuanTransaction
=
transaction
;
if
(
!
d
->
lastAssuanTransaction
.
get
())
{
return
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_INV_ARG
));
}
#ifdef HAVE_GPGME_ASSUAN_ENGINE
return
Error
(
d
->
lasterr
=
gpgme_op_assuan_transact_start
(
d
->
ctx
,
command
,
assuan_transaction_data_callback
,
d
->
lastAssuanTransaction
.
get
(),
assuan_transaction_inquire_callback
,
d
,
// sic!
assuan_transaction_status_callback
,
d
->
lastAssuanTransaction
.
get
()));
#else
(
void
)
command
;
return
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_SUPPORTED
));
#endif
}
AssuanResult
Context
::
assuanResult
()
const
{
if
(
d
->
lastop
&
Private
::
AssuanTransact
)
{
return
AssuanResult
(
d
->
ctx
,
d
->
lasterr
);
}
else
{
return
AssuanResult
();
}
}
AssuanTransaction
*
Context
::
lastAssuanTransaction
()
const
{
return
d
->
lastAssuanTransaction
.
get
();
}
std
::
auto_ptr
<
AssuanTransaction
>
Context
::
takeLastAssuanTransaction
()
{
return
d
->
lastAssuanTransaction
;
}
DecryptionResult
Context
::
decrypt
(
const
Data
&
cipherText
,
Data
&
plainText
)
{
d
->
lastop
=
Private
::
Decrypt
;
const
Data
::
Private
*
const
cdp
=
cipherText
.
impl
();
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
d
->
lasterr
=
gpgme_op_decrypt
(
d
->
ctx
,
cdp
?
cdp
->
data
:
0
,
pdp
?
pdp
->
data
:
0
);
return
DecryptionResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
Error
Context
::
startDecryption
(
const
Data
&
cipherText
,
Data
&
plainText
)
{
d
->
lastop
=
Private
::
Decrypt
;
const
Data
::
Private
*
const
cdp
=
cipherText
.
impl
();
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_decrypt_start
(
d
->
ctx
,
cdp
?
cdp
->
data
:
0
,
pdp
?
pdp
->
data
:
0
));
}
DecryptionResult
Context
::
decryptionResult
()
const
{
if
(
d
->
lastop
&
Private
::
Decrypt
)
{
return
DecryptionResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
else
{
return
DecryptionResult
();
}
}
VerificationResult
Context
::
verifyDetachedSignature
(
const
Data
&
signature
,
const
Data
&
signedText
)
{
d
->
lastop
=
Private
::
Verify
;
const
Data
::
Private
*
const
sdp
=
signature
.
impl
();
const
Data
::
Private
*
const
tdp
=
signedText
.
impl
();
d
->
lasterr
=
gpgme_op_verify
(
d
->
ctx
,
sdp
?
sdp
->
data
:
0
,
tdp
?
tdp
->
data
:
0
,
0
);
return
VerificationResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
VerificationResult
Context
::
verifyOpaqueSignature
(
const
Data
&
signedData
,
Data
&
plainText
)
{
d
->
lastop
=
Private
::
Verify
;
const
Data
::
Private
*
const
sdp
=
signedData
.
impl
();
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
d
->
lasterr
=
gpgme_op_verify
(
d
->
ctx
,
sdp
?
sdp
->
data
:
0
,
0
,
pdp
?
pdp
->
data
:
0
);
return
VerificationResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
Error
Context
::
startDetachedSignatureVerification
(
const
Data
&
signature
,
const
Data
&
signedText
)
{
d
->
lastop
=
Private
::
Verify
;
const
Data
::
Private
*
const
sdp
=
signature
.
impl
();
const
Data
::
Private
*
const
tdp
=
signedText
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_verify_start
(
d
->
ctx
,
sdp
?
sdp
->
data
:
0
,
tdp
?
tdp
->
data
:
0
,
0
));
}
Error
Context
::
startOpaqueSignatureVerification
(
const
Data
&
signedData
,
Data
&
plainText
)
{
d
->
lastop
=
Private
::
Verify
;
const
Data
::
Private
*
const
sdp
=
signedData
.
impl
();
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_verify_start
(
d
->
ctx
,
sdp
?
sdp
->
data
:
0
,
0
,
pdp
?
pdp
->
data
:
0
));
}
VerificationResult
Context
::
verificationResult
()
const
{
if
(
d
->
lastop
&
Private
::
Verify
)
{
return
VerificationResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
else
{
return
VerificationResult
();
}
}
std
::
pair
<
DecryptionResult
,
VerificationResult
>
Context
::
decryptAndVerify
(
const
Data
&
cipherText
,
Data
&
plainText
)
{
d
->
lastop
=
Private
::
DecryptAndVerify
;
const
Data
::
Private
*
const
cdp
=
cipherText
.
impl
();
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
d
->
lasterr
=
gpgme_op_decrypt_verify
(
d
->
ctx
,
cdp
?
cdp
->
data
:
0
,
pdp
?
pdp
->
data
:
0
);
return
std
::
make_pair
(
DecryptionResult
(
d
->
ctx
,
Error
(
d
->
lasterr
)),
VerificationResult
(
d
->
ctx
,
Error
(
d
->
lasterr
)));
}
Error
Context
::
startCombinedDecryptionAndVerification
(
const
Data
&
cipherText
,
Data
&
plainText
)
{
d
->
lastop
=
Private
::
DecryptAndVerify
;
const
Data
::
Private
*
const
cdp
=
cipherText
.
impl
();
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_decrypt_verify_start
(
d
->
ctx
,
cdp
?
cdp
->
data
:
0
,
pdp
?
pdp
->
data
:
0
));
}
#ifdef HAVE_GPGME_OP_GETAUDITLOG
unsigned
int
to_auditlog_flags
(
unsigned
int
flags
)
{
unsigned
int
result
=
0
;
if
(
flags
&
Context
::
HtmlAuditLog
)
{
result
|=
GPGME_AUDITLOG_HTML
;
}
if
(
flags
&
Context
::
AuditLogWithHelp
)
{
result
|=
GPGME_AUDITLOG_WITH_HELP
;
}
return
result
;
}
#endif
// HAVE_GPGME_OP_GETAUDITLOG
Error
Context
::
startGetAuditLog
(
Data
&
output
,
unsigned
int
flags
)
{
d
->
lastop
=
Private
::
GetAuditLog
;
#ifdef HAVE_GPGME_OP_GETAUDITLOG
Data
::
Private
*
const
odp
=
output
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_getauditlog_start
(
d
->
ctx
,
odp
?
odp
->
data
:
0
,
to_auditlog_flags
(
flags
)));
#else
(
void
)
output
;
(
void
)
flags
;
return
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_IMPLEMENTED
));
#endif
}
Error
Context
::
getAuditLog
(
Data
&
output
,
unsigned
int
flags
)
{
d
->
lastop
=
Private
::
GetAuditLog
;
#ifdef HAVE_GPGME_OP_GETAUDITLOG
Data
::
Private
*
const
odp
=
output
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_getauditlog
(
d
->
ctx
,
odp
?
odp
->
data
:
0
,
to_auditlog_flags
(
flags
)));
#else
(
void
)
output
;
(
void
)
flags
;
return
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_IMPLEMENTED
));
#endif
}
void
Context
::
clearSigningKeys
()
{
gpgme_signers_clear
(
d
->
ctx
);
}
Error
Context
::
addSigningKey
(
const
Key
&
key
)
{
return
Error
(
d
->
lasterr
=
gpgme_signers_add
(
d
->
ctx
,
key
.
impl
()));
}
Key
Context
::
signingKey
(
unsigned
int
idx
)
const
{
gpgme_key_t
key
=
gpgme_signers_enum
(
d
->
ctx
,
idx
);
return
Key
(
key
,
false
);
}
std
::
vector
<
Key
>
Context
::
signingKeys
()
const
{
std
::
vector
<
Key
>
result
;
gpgme_key_t
key
;
for
(
unsigned
int
i
=
0
;
(
key
=
gpgme_signers_enum
(
d
->
ctx
,
i
))
;
++
i
)
{
result
.
push_back
(
Key
(
key
,
false
));
}
return
result
;
}
void
Context
::
clearSignatureNotations
()
{
#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
gpgme_sig_notation_clear
(
d
->
ctx
);
#endif
}
GpgME
::
Error
Context
::
addSignatureNotation
(
const
char
*
name
,
const
char
*
value
,
unsigned
int
flags
)
{
#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
return
Error
(
gpgme_sig_notation_add
(
d
->
ctx
,
name
,
value
,
add_to_gpgme_sig_notation_flags_t
(
0
,
flags
)));
#else
(
void
)
name
;
(
void
)
value
;
(
void
)
flags
;
return
Error
(
make_error
(
GPG_ERR_NOT_IMPLEMENTED
));
#endif
}
GpgME
::
Error
Context
::
addSignaturePolicyURL
(
const
char
*
url
,
bool
critical
)
{
#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
return
Error
(
gpgme_sig_notation_add
(
d
->
ctx
,
0
,
url
,
critical
?
GPGME_SIG_NOTATION_CRITICAL
:
0
));
#else
(
void
)
url
;
(
void
)
critical
;
return
Error
(
make_error
(
GPG_ERR_NOT_IMPLEMENTED
));
#endif
}
const
char
*
Context
::
signaturePolicyURL
()
const
{
#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
for
(
gpgme_sig_notation_t
n
=
gpgme_sig_notation_get
(
d
->
ctx
)
;
n
;
n
=
n
->
next
)
{
if
(
!
n
->
name
)
{
return
n
->
value
;
}
}
#endif
return
0
;
}
Notation
Context
::
signatureNotation
(
unsigned
int
idx
)
const
{
#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
for
(
gpgme_sig_notation_t
n
=
gpgme_sig_notation_get
(
d
->
ctx
)
;
n
;
n
=
n
->
next
)
{
if
(
n
->
name
)
{
if
(
idx
--
==
0
)
{
return
Notation
(
n
);
}
}
}
#endif
return
Notation
();
}
std
::
vector
<
Notation
>
Context
::
signatureNotations
()
const
{
std
::
vector
<
Notation
>
result
;
#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
for
(
gpgme_sig_notation_t
n
=
gpgme_sig_notation_get
(
d
->
ctx
)
;
n
;
n
=
n
->
next
)
{
if
(
n
->
name
)
{
result
.
push_back
(
Notation
(
n
));
}
}
#endif
return
result
;
}
static
gpgme_sig_mode_t
sigmode2sigmode
(
SignatureMode
mode
)
{
switch
(
mode
)
{
default
:
case
NormalSignatureMode
:
return
GPGME_SIG_MODE_NORMAL
;
case
Detached
:
return
GPGME_SIG_MODE_DETACH
;
case
Clearsigned
:
return
GPGME_SIG_MODE_CLEAR
;
}
}
SigningResult
Context
::
sign
(
const
Data
&
plainText
,
Data
&
signature
,
SignatureMode
mode
)
{
d
->
lastop
=
Private
::
Sign
;
const
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
Data
::
Private
*
const
sdp
=
signature
.
impl
();
d
->
lasterr
=
gpgme_op_sign
(
d
->
ctx
,
pdp
?
pdp
->
data
:
0
,
sdp
?
sdp
->
data
:
0
,
sigmode2sigmode
(
mode
));
return
SigningResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
Error
Context
::
startSigning
(
const
Data
&
plainText
,
Data
&
signature
,
SignatureMode
mode
)
{
d
->
lastop
=
Private
::
Sign
;
const
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
Data
::
Private
*
const
sdp
=
signature
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_sign_start
(
d
->
ctx
,
pdp
?
pdp
->
data
:
0
,
sdp
?
sdp
->
data
:
0
,
sigmode2sigmode
(
mode
)));
}
SigningResult
Context
::
signingResult
()
const
{
if
(
d
->
lastop
&
Private
::
Sign
)
{
return
SigningResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
else
{
return
SigningResult
();
}
}
static
gpgme_encrypt_flags_t
encryptflags2encryptflags
(
Context
::
EncryptionFlags
flags
)
{
unsigned
int
result
=
0
;
if
(
flags
&
Context
::
AlwaysTrust
)
{
result
|=
GPGME_ENCRYPT_ALWAYS_TRUST
;
}
#ifdef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO
if
(
flags
&
Context
::
NoEncryptTo
)
{
result
|=
GPGME_ENCRYPT_NO_ENCRYPT_TO
;
}
#endif
return
static_cast
<
gpgme_encrypt_flags_t
>
(
result
);
}
EncryptionResult
Context
::
encrypt
(
const
std
::
vector
<
Key
>
&
recipients
,
const
Data
&
plainText
,
Data
&
cipherText
,
EncryptionFlags
flags
)
{
d
->
lastop
=
Private
::
Encrypt
;
#ifndef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO
if
(
flags
&
NoEncryptTo
)
{
return
EncryptionResult
(
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_IMPLEMENTED
)));
}
#endif
const
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
Data
::
Private
*
const
cdp
=
cipherText
.
impl
();
gpgme_key_t
*
const
keys
=
new
gpgme_key_t
[
recipients
.
size
()
+
1
];
gpgme_key_t
*
keys_it
=
keys
;
for
(
std
::
vector
<
Key
>::
const_iterator
it
=
recipients
.
begin
()
;
it
!=
recipients
.
end
()
;
++
it
)
{
if
(
it
->
impl
())
{
*
keys_it
++
=
it
->
impl
();
}
}
*
keys_it
++
=
0
;
d
->
lasterr
=
gpgme_op_encrypt
(
d
->
ctx
,
keys
,
encryptflags2encryptflags
(
flags
),
pdp
?
pdp
->
data
:
0
,
cdp
?
cdp
->
data
:
0
);
delete
[]
keys
;
return
EncryptionResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
Error
Context
::
encryptSymmetrically
(
const
Data
&
plainText
,
Data
&
cipherText
)
{
d
->
lastop
=
Private
::
Encrypt
;
const
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
Data
::
Private
*
const
cdp
=
cipherText
.
impl
();
return
Error
(
d
->
lasterr
=
gpgme_op_encrypt
(
d
->
ctx
,
0
,
(
gpgme_encrypt_flags_t
)
0
,
pdp
?
pdp
->
data
:
0
,
cdp
?
cdp
->
data
:
0
));
}
Error
Context
::
startEncryption
(
const
std
::
vector
<
Key
>
&
recipients
,
const
Data
&
plainText
,
Data
&
cipherText
,
EncryptionFlags
flags
)
{
d
->
lastop
=
Private
::
Encrypt
;
#ifndef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO
if
(
flags
&
NoEncryptTo
)
{
return
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_IMPLEMENTED
));
}
#endif
const
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
Data
::
Private
*
const
cdp
=
cipherText
.
impl
();
gpgme_key_t
*
const
keys
=
new
gpgme_key_t
[
recipients
.
size
()
+
1
];
gpgme_key_t
*
keys_it
=
keys
;
for
(
std
::
vector
<
Key
>::
const_iterator
it
=
recipients
.
begin
()
;
it
!=
recipients
.
end
()
;
++
it
)
{
if
(
it
->
impl
())
{
*
keys_it
++
=
it
->
impl
();
}
}
*
keys_it
++
=
0
;
d
->
lasterr
=
gpgme_op_encrypt_start
(
d
->
ctx
,
keys
,
encryptflags2encryptflags
(
flags
),
pdp
?
pdp
->
data
:
0
,
cdp
?
cdp
->
data
:
0
);
delete
[]
keys
;
return
Error
(
d
->
lasterr
);
}
EncryptionResult
Context
::
encryptionResult
()
const
{
if
(
d
->
lastop
&
Private
::
Encrypt
)
{
return
EncryptionResult
(
d
->
ctx
,
Error
(
d
->
lasterr
));
}
else
{
return
EncryptionResult
();
}
}
std
::
pair
<
SigningResult
,
EncryptionResult
>
Context
::
signAndEncrypt
(
const
std
::
vector
<
Key
>
&
recipients
,
const
Data
&
plainText
,
Data
&
cipherText
,
EncryptionFlags
flags
)
{
d
->
lastop
=
Private
::
SignAndEncrypt
;
const
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
Data
::
Private
*
const
cdp
=
cipherText
.
impl
();
gpgme_key_t
*
const
keys
=
new
gpgme_key_t
[
recipients
.
size
()
+
1
];
gpgme_key_t
*
keys_it
=
keys
;
for
(
std
::
vector
<
Key
>::
const_iterator
it
=
recipients
.
begin
()
;
it
!=
recipients
.
end
()
;
++
it
)
{
if
(
it
->
impl
())
{
*
keys_it
++
=
it
->
impl
();
}
}
*
keys_it
++
=
0
;
d
->
lasterr
=
gpgme_op_encrypt_sign
(
d
->
ctx
,
keys
,
encryptflags2encryptflags
(
flags
),
pdp
?
pdp
->
data
:
0
,
cdp
?
cdp
->
data
:
0
);
delete
[]
keys
;
return
std
::
make_pair
(
SigningResult
(
d
->
ctx
,
Error
(
d
->
lasterr
)),
EncryptionResult
(
d
->
ctx
,
Error
(
d
->
lasterr
)));
}
Error
Context
::
startCombinedSigningAndEncryption
(
const
std
::
vector
<
Key
>
&
recipients
,
const
Data
&
plainText
,
Data
&
cipherText
,
EncryptionFlags
flags
)
{
d
->
lastop
=
Private
::
SignAndEncrypt
;
const
Data
::
Private
*
const
pdp
=
plainText
.
impl
();
Data
::
Private
*
const
cdp
=
cipherText
.
impl
();
gpgme_key_t
*
const
keys
=
new
gpgme_key_t
[
recipients
.
size
()
+
1
];
gpgme_key_t
*
keys_it
=
keys
;
for
(
std
::
vector
<
Key
>::
const_iterator
it
=
recipients
.
begin
()
;
it
!=
recipients
.
end
()
;
++
it
)
{
if
(
it
->
impl
())
{
*
keys_it
++
=
it
->
impl
();
}
}
*
keys_it
++
=
0
;
d
->
lasterr
=
gpgme_op_encrypt_sign_start
(
d
->
ctx
,
keys
,
encryptflags2encryptflags
(
flags
),
pdp
?
pdp
->
data
:
0
,
cdp
?
cdp
->
data
:
0
);
delete
[]
keys
;
return
Error
(
d
->
lasterr
);
}
Error
Context
::
createVFS
(
const
char
*
containerFile
,
const
std
::
vector
<
Key
>
&
recipients
)
{
d
->
lastop
=
Private
::
CreateVFS
;
#ifdef HAVE_GPGME_G13_VFS
gpgme_key_t
*
const
keys
=
new
gpgme_key_t
[
recipients
.
size
()
+
1
];
gpgme_key_t
*
keys_it
=
keys
;
for
(
std
::
vector
<
Key
>::
const_iterator
it
=
recipients
.
begin
()
;
it
!=
recipients
.
end
()
;
++
it
)
{
if
(
it
->
impl
())
{
*
keys_it
++
=
it
->
impl
();
}
}
*
keys_it
++
=
0
;
gpgme_error_t
op_err
;
d
->
lasterr
=
gpgme_op_vfs_create
(
d
->
ctx
,
keys
,
containerFile
,
0
,
&
op_err
);
delete
[]
keys
;
Error
error
(
d
->
lasterr
);
if
(
error
)
{
return
error
;
}
return
Error
(
d
->
lasterr
=
op_err
);
#else
Q_UNUSED
(
containerFile
);
Q_UNUSED
(
recipients
);
return
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_SUPPORTED
));
#endif
}
VfsMountResult
Context
::
mountVFS
(
const
char
*
containerFile
,
const
char
*
mountDir
)
{
d
->
lastop
=
Private
::
MountVFS
;
#ifdef HAVE_GPGME_G13_VFS
gpgme_error_t
op_err
;
d
->
lasterr
=
gpgme_op_vfs_mount
(
d
->
ctx
,
containerFile
,
mountDir
,
0
,
&
op_err
);
return
VfsMountResult
(
d
->
ctx
,
Error
(
d
->
lasterr
),
Error
(
op_err
));
#else
Q_UNUSED
(
containerFile
);
Q_UNUSED
(
mountDir
);
return
VfsMountResult
(
d
->
ctx
,
Error
(
d
->
lasterr
=
make_error
(
GPG_ERR_NOT_SUPPORTED
)),
Error
());
#endif
}
Error
Context
::
cancelPendingOperation
()
{
#ifdef HAVE_GPGME_CANCEL_ASYNC
return
Error
(
gpgme_cancel_async
(
d
->
ctx
));
#else
return
Error
(
gpgme_cancel
(
d
->
ctx
));
#endif
}
bool
Context
::
poll
()
{
gpgme_error_t
e
=
GPG_ERR_NO_ERROR
;
const
bool
finished
=
gpgme_wait
(
d
->
ctx
,
&
e
,
0
);
if
(
finished
)
{
d
->
lasterr
=
e
;
}
return
finished
;
}
Error
Context
::
wait
()
{
gpgme_error_t
e
=
GPG_ERR_NO_ERROR
;
gpgme_wait
(
d
->
ctx
,
&
e
,
1
);
return
Error
(
d
->
lasterr
=
e
);
}
Error
Context
::
lastError
()
const
{
return
Error
(
d
->
lasterr
);
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
Protocol
proto
)
{
os
<<
"GpgME::Protocol("
;
switch
(
proto
)
{
case
OpenPGP
:
os
<<
"OpenPGP"
;
break
;
case
CMS
:
os
<<
"CMS"
;
break
;
default
:
case
UnknownProtocol
:
os
<<
"UnknownProtocol"
;
break
;
}
return
os
<<
')'
;
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
Engine
eng
)
{
os
<<
"GpgME::Engine("
;
switch
(
eng
)
{
case
GpgEngine
:
os
<<
"GpgEngine"
;
break
;
case
GpgSMEngine
:
os
<<
"GpgSMEngine"
;
break
;
case
GpgConfEngine
:
os
<<
"GpgConfEngine"
;
break
;
case
AssuanEngine
:
os
<<
"AssuanEngine"
;
break
;
default
:
case
UnknownEngine
:
os
<<
"UnknownEngine"
;
break
;
}
return
os
<<
')'
;
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
Context
::
CertificateInclusion
incl
)
{
os
<<
"GpgME::Context::CertificateInclusion("
<<
static_cast
<
int
>
(
incl
);
switch
(
incl
)
{
case
Context
::
DefaultCertificates
:
os
<<
"(DefaultCertificates)"
;
break
;
case
Context
::
AllCertificatesExceptRoot
:
os
<<
"(AllCertificatesExceptRoot)"
;
break
;
case
Context
::
AllCertificates
:
os
<<
"(AllCertificates)"
;
break
;
case
Context
::
NoCertificates
:
os
<<
"(NoCertificates)"
;
break
;
case
Context
::
OnlySenderCertificate
:
os
<<
"(OnlySenderCertificate)"
;
break
;
}
return
os
<<
')'
;
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
KeyListMode
mode
)
{
os
<<
"GpgME::KeyListMode("
;
#define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
CHECK
(
Local
);
CHECK
(
Extern
);
CHECK
(
Signatures
);
CHECK
(
Validate
);
CHECK
(
Ephemeral
);
#undef CHECK
return
os
<<
')'
;
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
SignatureMode
mode
)
{
os
<<
"GpgME::SignatureMode("
;
switch
(
mode
)
{
#define CHECK( x ) case x: os << #x; break
CHECK
(
NormalSignatureMode
);
CHECK
(
Detached
);
CHECK
(
Clearsigned
);
#undef CHECK
default
:
os
<<
"???"
"("
<<
static_cast
<
int
>
(
mode
)
<<
')'
;
break
;
}
return
os
<<
')'
;
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
Context
::
EncryptionFlags
flags
)
{
os
<<
"GpgME::Context::EncryptionFlags("
;
#define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
CHECK
(
AlwaysTrust
);
#undef CHECK
return
os
<<
')'
;
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
Context
::
AuditLogFlags
flags
)
{
os
<<
"GpgME::Context::AuditLogFlags("
;
#define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
CHECK
(
HtmlAuditLog
);
CHECK
(
AuditLogWithHelp
);
#undef CHECK
return
os
<<
')'
;
}
}
// namespace GpgME
GpgME
::
Error
GpgME
::
setDefaultLocale
(
int
cat
,
const
char
*
val
)
{
return
Error
(
gpgme_set_locale
(
0
,
cat
,
val
));
}
GpgME
::
EngineInfo
GpgME
::
engineInfo
(
GpgME
::
Protocol
proto
)
{
gpgme_engine_info_t
ei
=
0
;
if
(
gpgme_get_engine_info
(
&
ei
))
{
return
EngineInfo
();
}
const
gpgme_protocol_t
p
=
proto
==
CMS
?
GPGME_PROTOCOL_CMS
:
GPGME_PROTOCOL_OpenPGP
;
for
(
gpgme_engine_info_t
i
=
ei
;
i
;
i
=
i
->
next
)
{
if
(
i
->
protocol
==
p
)
{
return
EngineInfo
(
i
);
}
}
return
EngineInfo
();
}
GpgME
::
Error
GpgME
::
checkEngine
(
GpgME
::
Protocol
proto
)
{
const
gpgme_protocol_t
p
=
proto
==
CMS
?
GPGME_PROTOCOL_CMS
:
GPGME_PROTOCOL_OpenPGP
;
return
Error
(
gpgme_engine_check_version
(
p
));
}
static
const
gpgme_protocol_t
UNKNOWN_PROTOCOL
=
static_cast
<
gpgme_protocol_t
>
(
255
);
static
gpgme_protocol_t
engine2protocol
(
const
GpgME
::
Engine
engine
)
{
switch
(
engine
)
{
case
GpgME
::
GpgEngine
:
return
GPGME_PROTOCOL_OpenPGP
;
case
GpgME
::
GpgSMEngine
:
return
GPGME_PROTOCOL_CMS
;
case
GpgME
::
GpgConfEngine
:
#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
return
GPGME_PROTOCOL_GPGCONF
;
#else
break
;
#endif
case
GpgME
::
AssuanEngine
:
#ifdef HAVE_GPGME_ASSUAN_ENGINE
return
GPGME_PROTOCOL_ASSUAN
;
#else
break
;
#endif
case
GpgME
::
G13Engine
:
#ifdef HAVE_GPGME_G13_VFS
return
GPGME_PROTOCOL_G13
;
#else
break
;
#endif
case
GpgME
::
UnknownEngine
:
;
}
return
UNKNOWN_PROTOCOL
;
}
GpgME
::
EngineInfo
GpgME
::
engineInfo
(
GpgME
::
Engine
engine
)
{
gpgme_engine_info_t
ei
=
0
;
if
(
gpgme_get_engine_info
(
&
ei
))
{
return
EngineInfo
();
}
const
gpgme_protocol_t
p
=
engine2protocol
(
engine
);
for
(
gpgme_engine_info_t
i
=
ei
;
i
;
i
=
i
->
next
)
{
if
(
i
->
protocol
==
p
)
{
return
EngineInfo
(
i
);
}
}
return
EngineInfo
();
}
GpgME
::
Error
GpgME
::
checkEngine
(
GpgME
::
Engine
engine
)
{
const
gpgme_protocol_t
p
=
engine2protocol
(
engine
);
return
Error
(
gpgme_engine_check_version
(
p
));
}
static
const
unsigned
long
supported_features
=
0
|
GpgME
::
ValidatingKeylistModeFeature
|
GpgME
::
CancelOperationFeature
|
GpgME
::
WrongKeyUsageFeature
#ifdef HAVE_GPGME_INCLUDE_CERTS_DEFAULT
|
GpgME
::
DefaultCertificateInclusionFeature
#endif
#ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO
|
GpgME
::
GetSetEngineInfoFeature
#endif
#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
|
GpgME
::
ClearAddGetSignatureNotationsFeature
#endif
#ifdef HAVE_GPGME_DATA_SET_FILE_NAME
|
GpgME
::
SetDataFileNameFeeature
#endif
#ifdef HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS
|
GpgME
::
SignatureNotationsKeylistModeFeature
#endif
#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS
|
GpgME
::
KeySignatureNotationsFeature
#endif
#ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED
|
GpgME
::
KeyIsQualifiedFeature
#endif
#ifdef HAVE_GPGME_SIG_NOTATION_CRITICAL
|
GpgME
::
SignatureNotationsCriticalFlagFeature
#endif
#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
|
GpgME
::
SignatureNotationsFlagsFeature
#endif
#ifdef HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE
|
GpgME
::
SignatureNotationsHumanReadableFlagFeature
#endif
#ifdef HAVE_GPGME_SUBKEY_T_IS_QUALIFIED
|
GpgME
::
SubkeyIsQualifiedFeature
#endif
#ifdef HAVE_GPGME_ENGINE_INFO_T_HOME_DIR
|
GpgME
::
EngineInfoHomeDirFeature
#endif
#ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME
|
GpgME
::
DecryptionResultFileNameFeature
#endif
#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
|
GpgME
::
DecryptionResultRecipientsFeature
#endif
#ifdef HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME
|
GpgME
::
VerificationResultFileNameFeature
#endif
#ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS
|
GpgME
::
SignaturePkaFieldsFeature
#endif
#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
|
GpgME
::
SignatureAlgorithmFieldsFeature
#endif
#ifdef HAVE_GPGME_GET_FDPTR
|
GpgME
::
FdPointerFeature
#endif
#ifdef HAVE_GPGME_OP_GETAUDITLOG
|
GpgME
::
AuditLogFeature
#endif
#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
|
GpgME
::
GpgConfEngineFeature
#endif
#ifdef HAVE_GPGME_CANCEL_ASYNC
|
GpgME
::
CancelOperationAsyncFeature
#endif
#ifdef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO
|
GpgME
::
NoEncryptToEncryptionFlagFeature
#endif
#ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY
|
GpgME
::
CardKeyFeature
#endif
#ifdef HAVE_GPGME_ASSUAN_ENGINE
|
GpgME
::
AssuanEngineFeature
#endif
#ifdef HAVE_GPGME_KEYLIST_MODE_EPHEMERAL
|
GpgME
::
EphemeralKeylistModeFeature
#endif
#ifdef HAVE_GPGME_OP_IMPORT_KEYS
|
GpgME
::
ImportFromKeyserverFeature
#endif
#ifdef HAVE_GPGME_G13_VFS
|
GpgME
::
G13VFSFeature
#endif
#ifdef HAVE_GPGME_OP_PASSWD
|
GpgME
::
PasswdFeature
#endif
;
static
const
unsigned
long
supported_features2
=
0
;
bool
GpgME
::
hasFeature
(
unsigned
long
features
)
{
return
features
==
(
features
&
supported_features
);
}
bool
GpgME
::
hasFeature
(
unsigned
long
features
,
unsigned
long
features2
)
{
return
features
==
(
features
&
supported_features
)
&&
features2
==
(
features2
&
supported_features2
)
;
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Fri, Mar 14, 4:41 AM (1 d, 10 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
cd/26/ecda85cf161746d665ca743756b0
Attached To
rM GPGME
Event Timeline
Log In to Comment