read client-side missing pgp keys from addressbook and offer user to import them

This commit is contained in:
Ralf Becker 2015-05-20 21:20:10 +00:00
parent 6537acb11f
commit 8b88959e69
2 changed files with 151 additions and 5 deletions

View File

@ -284,7 +284,7 @@ class addressbook_bo extends addressbook_so
);
//_debug_array($this->contact_fields);
$this->own_account_acl = $GLOBALS['egw_info']['server']['own_account_acl'];
if (!is_array($this->own_account_acl)) $this->own_account_acl = unserialize($this->own_account_acl);
if (!is_array($this->own_account_acl)) $this->own_account_acl = json_php_unserialize($this->own_account_acl, true);
// we have only one acl (n_fn) for the whole name, as not all backends store every part in an own field
if ($this->own_account_acl && in_array('n_fn',$this->own_account_acl))
{
@ -2368,4 +2368,123 @@ class addressbook_bo extends addressbook_so
//error_log(__METHOD__.'('.array2string($owner).') returning '.array2string($ctag));
return $ctag;
}
static public $pgp_key_regexp = '/-----BEGIN PGP PUBLIC KEY BLOCK-----.*-----END PGP PUBLIC KEY BLOCK-----\r?\n/s';
/**
* Search addressbook for PGP public keys of given recipients
*
* EMail addresses are lowercased to make search case-insensitive
*
* @param string|int|array $recipients (array of) email addresses or numeric account-ids
* @return array email|account_id => key pairs
*/
public function ajax_get_pgp_keys($recipients)
{
if (!$recipients) return array();
if (!is_array($recipients)) $recipients = array($recipients);
$criteria = $result = array();
foreach($recipients as &$recipient)
{
if (is_numeric($recipient))
{
$criteria['account_id'][] = (int)$recipient;
}
else
{
$criteria['contact_email'][] = $recipient = strtolower($recipient);
}
}
foreach($this->search($criteria, array('account_id', 'contact_email', 'contact_pubkey'), '', '', '', false, 'OR', false,
"contact_pubkey LIKE '%-----BEGIN PGP PUBLIC KEY BLOCK-----%'") as $contact)
{
$matches = null;
if (preg_match(self::$pgp_key_regexp, $contact['pubkey'], $matches))
{
$contact['email'] = strtolower($contact['email']);
if (empty($criteria['account_id']) || in_array($contact['email'], $recipients))
{
$result[$contact['email']] = $matches[0];
}
else
{
$result[$contact['account_id']] = $matches[0];
}
}
}
//error_log(__METHOD__."(".array2string($recipients).") returning ".array2string($result));
egw_json_response::get()->data($result);
}
/**
* Set PGP keys for given email or account_id, if user has necessary rights
*
* @param array $keys email|account_id => public key pairs to store
* @param boolean $allow_user_updates =null for admins, set config to allow regular users to store their pgp key
* @return int number of pgp keys stored
*/
public function ajax_set_pgp_keys($keys, $allow_user_updates=null)
{
if (isset($allow_user_updates) && isset($GLOBALS['egw_info']['user']['apps']['admin']))
{
$update = false;
if ($allow_user_updates && !in_array('contact_pubkey', $this->own_account_acl))
{
$this->own_account_acl[] = 'contact_pubkey';
$update = true;
}
elseif (!$allow_user_updates && ($key = array_search('contact_pubkey', $this->own_account_acl)) !== false)
{
unset($this->own_account_acl[$key]);
$update = true;
}
if ($update)
{
config::save_value('own_account_acl', $this->own_account_acl, 'phpgwapi');
}
}
$criteria = array();
foreach($keys as $recipient => $key)
{
if (!preg_match(self::$pgp_key_regexp, $key)) continue;
if (is_numeric($recipient))
{
$criteria['contact_email'][] = $recipient;
}
else
{
$criteria['account_id'][] = (int)$recipient;
}
}
if (!$criteria) return 0;
$updated = 0;
foreach($this->search($criteria, false, '', '', '', false, 'OR') as $contact)
{
if ($contact['account_id'] && isset($keys[$contact['account_id']]))
{
$key = $keys[$contact['account_id']];
}
elseif (isset($keys[$contact['email']]))
{
$key = $keys[$contact['email']];
}
if (empty($contact['pubkey']) || !preg_match(self::$pgp_key_regexp, $contact['pubkey']))
{
$contact['pubkey'] .= $key;
}
else
{
$contact['pubkey'] = preg_replace(self::$pgp_key_regexp, $key, $contact['pubkey']);
}
if ($this->check_perms(EGW_ACL_EDIT, $contact) && $this->save($contact))
{
++$updated;
}
}
return $updated;
}
}

View File

@ -409,7 +409,7 @@ var AppJS = Class.extend(
self._refresh_fav_nm();
}
});
// Bind favorite de-select
var egw_fw = egw_getFramework();
if(egw_fw && egw_fw.applications[this.appname] && egw_fw.applications[this.appname].browser
@ -938,12 +938,12 @@ var AppJS = Class.extend(
*/
mailvelopeGetCheckRecipients: function(_recipients)
{
// replace rfc822 addresses with raw email, as Mailvelop does not like them
// replace rfc822 addresses with raw email, as Mailvelop does not like them and lowercase all email
var rfc822_preg = /<([^'" <>]+)>$/;
var recipients = _recipients.map(function(_recipient)
{
var matches = _recipient.match(rfc822_preg);
return matches ? matches[1] : _recipient;
return matches ? matches[1].toLowerCase() : _recipient.toLowerCase();
});
// check if we have keys for all recipients
@ -954,6 +954,7 @@ var AppJS = Class.extend(
var reject = _reject;
self.mailvelopeOpenKeyring().then(function(_keyring)
{
var keyring = _keyring;
_keyring.validKeyForAddress(recipients).then(function(_status)
{
var no_key = [];
@ -963,7 +964,33 @@ var AppJS = Class.extend(
}
if (no_key.length)
{
reject(new Error(self.egw.lang('No key for recipient: '+no_key.join(', '))));
// server addressbook on server for missing public keys
self.egw.json('addressbook.addressbook_bo.ajax_get_pgp_keys', [no_key]).sendRequest().then(function(_data)
{
var data = _data.response['0'].data;
var promises = [];
for(var email in data)
{
promises.push(keyring.importPublicKey(data[email]).then(function(_result)
{
if (_result == 'IMPORTED')
{
no_key.splice(no_key.indexOf(email),1);
}
}));
}
Promise.all(promises).then(function()
{
if (no_key.length)
{
reject(new Error(self.egw.lang('No key for recipient: '+no_key.join(', '))));
}
else
{
resolve(recipients);
}
});
});
}
else
{