Skip to content

Commit

Permalink
Merge branch 'staging' of github.com:joomla/joomla-cms into com_contact
Browse files Browse the repository at this point in the history
  • Loading branch information
zero-24 committed Aug 16, 2017
2 parents f19528b + 810b274 commit 56c6c4c
Show file tree
Hide file tree
Showing 20 changed files with 131 additions and 67 deletions.
3 changes: 1 addition & 2 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,5 @@ There are other branches available which serve specific purposes.
| Branch | Purpose |
| ------ | ------- |
| staging | Current codebase. Branch for the next minor Joomla version. New backward compatible features go into this branch. |
| master | Each commit made to staging gets tested if it passes unit tests and codestyle rules. It is then merged into master. This is done automatically. |
| 3.8-dev | Branch for the next minor Joomla version. The 3.8.0 release will only include compatibility features for 4.0. Commits to staging will be applied to this branch as well. |
| 3.9-dev | Branch for the next minor Joomla version. The 3.9.0 release will only include compatibility features for 4.0. Commits to staging will be applied to this branch as well. |
| 4.0-dev | Branch for the next major Joomla version. New features go into this branch. Commits to staging will be applied to this branch as well. |
2 changes: 1 addition & 1 deletion administrator/components/com_fields/helpers/fields.php
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ public static function getFieldTypes()
*
* @return void
*
* @since __DEPLOY_VERSION__
* @since 3.8.0
*/
public static function clearFieldsCache()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public static function addSubmenu($vName = 'install')
$vName == 'database'
);
JHtmlSidebar::addEntry(
JText::_('COM_INSTALLER_SUBMENU_WARNINGS'),
JText::_('COM_INSTALLER_SUBMENU_WARNINGS'),
'index.php?option=com_installer&view=warnings',
$vName == 'warnings'
);
Expand Down
11 changes: 7 additions & 4 deletions administrator/components/com_installer/models/database.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public function getItems()

return false;
}

return $changeSet;
}

Expand Down Expand Up @@ -309,16 +310,18 @@ private function prepareUtf8mb4StatusTable()
if ($count > 1)
{
// Table messed up somehow, clear it
$db->setQuery('DELETE FROM ' . $db->quoteName('#__utf8_conversion')
. ';')->execute();
$db->setQuery('DELETE FROM ' . $db->quoteName('#__utf8_conversion') . ';')
->execute();
$db->setQuery('INSERT INTO ' . $db->quoteName('#__utf8_conversion')
. ' (' . $db->quoteName('converted') . ') VALUES (0);')->execute();
. ' (' . $db->quoteName('converted') . ') VALUES (0);'
)->execute();
}
elseif ($count == 0)
{
// Record missing somehow, fix this
$db->setQuery('INSERT INTO ' . $db->quoteName('#__utf8_conversion')
. ' (' . $db->quoteName('converted') . ') VALUES (0);')->execute();
. ' (' . $db->quoteName('converted') . ') VALUES (0);'
)->execute();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ protected function _getList($query, $limitstart = 0, $limit = 0)
{
// Check if search string exists in any of the fields to be searched.
$found = 0;

foreach ($searchFields as $key => $field)
{
if (!$found && preg_match('/' . $escapedSearchString . '/i', $item->{$field}))
Expand Down
1 change: 1 addition & 0 deletions administrator/components/com_installer/models/update.php
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ public function getForm($data = array(), $loadData = true)

return false;
}

// Check the session for previously entered form data.
$data = $this->loadFormData();

Expand Down
5 changes: 3 additions & 2 deletions administrator/components/com_installer/models/updatesites.php
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,9 @@ protected function getJoomlaUpdateSitesIds($column = 0)
. '(' . $db->qn('e.type') . ' = ' . $db->quote('file') . ' AND ' . $db->qn('e.element') . ' = ' . $db->quote('joomla') . ')'
. ' OR (' . $db->qn('e.type') . ' = ' . $db->quote('package') . ' AND ' . $db->qn('e.element') . ' = ' . $db->quote('pkg_en-GB') . ')'
. ' OR (' . $db->qn('e.type') . ' = ' . $db->quote('component') . ' AND ' . $db->qn('e.element') . ' = ' . $db->quote('com_joomlaupdate') . ')'
. ')');

. ')'
);

$db->setQuery($query);

return $db->loadColumn($column);
Expand Down
9 changes: 8 additions & 1 deletion administrator/components/com_media/controllers/file.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ public function upload()
$this->setRedirect('index.php?option=com_media&folder=' . $this->folder);
}

if (!$files)
{
// If we could not get any data from the request we can not upload it.
JFactory::getApplication()->enqueueMessage(JText::_('COM_MEDIA_ERROR_WARNFILENOTSAFE'), 'error');

return false;
}

// Authorize the user
if (!$this->authoriseUser('create'))
{
Expand Down Expand Up @@ -143,7 +151,6 @@ public function upload()
if (!MediaHelper::canUpload($file, $err))
{
// The file can't be uploaded

return false;
}

Expand Down
1 change: 1 addition & 0 deletions administrator/language/en-GB/en-GB.com_media.ini
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ COM_MEDIA_ERROR_UNABLE_TO_DELETE=" Unable to delete: "
COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE="Unable to upload file."
COM_MEDIA_ERROR_UPLOAD_INPUT="Please input a file to upload"
COM_MEDIA_ERROR_WARNFILENAME="File name must only contain alphanumeric characters and no spaces."
COM_MEDIA_ERROR_WARNFILENOTSAFE="You have tried to upload file(s) that are not safe."
COM_MEDIA_ERROR_WARNFILETOOLARGE="This file is too large to upload."
COM_MEDIA_ERROR_WARNFILETYPE="This file type is not supported."
COM_MEDIA_ERROR_WARNIEXSS="Possible IE XSS Attack found."
Expand Down
2 changes: 1 addition & 1 deletion administrator/manifests/files/joomla.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<authorUrl>www.joomla.org</authorUrl>
<copyright>(C) 2005 - 2017 Open Source Matters. All rights reserved</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<version>3.8.0-dev</version>
<version>3.8.0-beta3-dev</version>
<creationDate>August 2017</creationDate>
<description>FILES_JOOMLA_XML_DESCRIPTION</description>

Expand Down
2 changes: 1 addition & 1 deletion build/bump.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ function usage($command)
'major' => $versionSubParts[0],
'minor' => $versionSubParts[1],
'patch' => $versionSubParts[2],
'extra' => !empty($versionParts[2]) ? $versionParts[2] : (!empty($versionParts[1]) ? $versionParts[1] : ''),
'extra' => (!empty($versionParts[1]) ? $versionParts[1] : '') . (!empty($versionParts[2]) ? (!empty($versionParts[1]) ? '-' : '') . $versionParts[2] : ''),
'release' => $versionSubParts[0] . '.' . $versionSubParts[1] . '.' . $versionSubParts[2],
'dev_devel' => $versionSubParts[2] . (!empty($versionParts[1]) ? '-' . $versionParts[1] : '') . (!empty($versionParts[2]) ? '-' . $versionParts[2] : ''),
'dev_status' => $dev_status,
Expand Down
6 changes: 3 additions & 3 deletions installation/controller/removefolder.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function execute()
// Check whether the folder still exists.
if (!file_exists($path))
{
$app->sendJsonResponse(new Exception(JText::sprintf('INSTL_COMPLETE_ERROR_FOLDER_ALREADY_REMOVED'), 500));
$app->sendJsonResponse(new Exception(JText::sprintf('INSTL_COMPLETE_ERROR_FOLDER_ALREADY_REMOVED', 'installation'), 500));
}

// Check whether we need to use FTP.
Expand Down Expand Up @@ -117,12 +117,12 @@ public function execute()
// If an error was encountered return an error.
if (!$return)
{
$app->sendJsonResponse(new Exception(JText::_('INSTL_COMPLETE_ERROR_FOLDER_DELETE'), 500));
$app->sendJsonResponse(new Exception(JText::sprintf('INSTL_COMPLETE_ERROR_FOLDER_DELETE', 'installation'), 500));
}

// Create a response body.
$r = new stdClass;
$r->text = JText::_('INSTL_COMPLETE_FOLDER_REMOVED');
$r->text = JText::sprintf('INSTL_COMPLETE_FOLDER_REMOVED', 'installation');

/*
* Send the response.
Expand Down
22 changes: 8 additions & 14 deletions installation/language/en-GB/en-GB.ini
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ INSTL_DATABASE="Database Configuration"
INSTL_DATABASE_ERROR_POSTGRESQL_QUERY="PostgreSQL database query failed."
INSTL_DATABASE_HOST_DESC="This is usually &quot;localhost&quot; or a name provided by your host."
INSTL_DATABASE_HOST_LABEL="Host Name"
INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE="We were not able to create the file. Please manually create a file named &quot;%s&quot; and upload it to the &quot;installation&quot; folder of your Joomla site."
INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE="In order to confirm that you are the owner of this website please delete the file named &quot;%s&quot; we have just created in the &quot;installation&quot; folder of your Joomla site."
INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE="We were not able to create the file. Please manually create a file named &quot;%1$s&quot; and upload it to the &quot;%2$s&quot; folder of your Joomla site."
INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE="In order to confirm that you are the owner of this website please delete the file named &quot;%1$s&quot; we have just created in the &quot;%2$s&quot; folder of your Joomla site."
INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_GENERAL_MESSAGE="You are trying to use a database host which is not on your local server. For security reasons, you need to verify the ownership of your web hosting account. <a href="_QQ_"%s"_QQ_">Please read the documentation</a> for more information."
INSTL_DATABASE_NAME_DESC="Some hosts allow only a certain DB name per site. Use table prefix in this case for distinct Joomla! sites."
INSTL_DATABASE_NAME_LABEL="Database Name"
Expand Down Expand Up @@ -122,20 +122,14 @@ INSTL_EMAIL_NOT_SENT="Email could not be sent."

;Complete view
INSTL_COMPLETE_ADMINISTRATION_LOGIN_DETAILS="Administration Login Details"
; The word 'installation' should not be translated as it is a physical folder.
INSTL_COMPLETE_ERROR_FOLDER_ALREADY_REMOVED="The installation folder has already been deleted."
; The word 'installation' should not be translated as it is a physical folder.
INSTL_COMPLETE_ERROR_FOLDER_DELETE="Installation folder could not be deleted. Please manually delete the folder."
; The word 'installation' should not be translated as it is a physical folder.
INSTL_COMPLETE_FOLDER_REMOVED="Installation folder removed."
INSTL_COMPLETE_ERROR_FOLDER_ALREADY_REMOVED="The &quot;%s&quot; folder has already been deleted."
INSTL_COMPLETE_ERROR_FOLDER_DELETE="&quot;%s&quot; folder could not be deleted. Please manually delete the folder."
INSTL_COMPLETE_FOLDER_REMOVED="&quot;%s&quot; folder removed."
INSTL_COMPLETE_LANGUAGE_1="Joomla! in your own language and/or automatic basic native multilingual site creation"
; The word 'installation' should not be translated as it is a physical folder.
INSTL_COMPLETE_LANGUAGE_DESC="Before removing the installation folder you can install extra languages. If you want to add extra languages to your Joomla! application select the following button."
INSTL_COMPLETE_LANGUAGE_DESC="Before removing the &quot;%s&quot; folder you can install extra languages. If you want to add extra languages to your Joomla! application select the following button."
INSTL_COMPLETE_LANGUAGE_DESC2="Note: you will need internet access for Joomla! to download and install the new languages. <br />Some server configurations won't allow Joomla! to install the languages. If this is your case, don't worry, you will be able to install them later using the Joomla! Administrator."
; The word 'installation' should not be translated as it is a physical folder.
INSTL_COMPLETE_REMOVE_FOLDER="Remove installation folder"
; The word 'installation' should not be translated as it is a physical folder.
INSTL_COMPLETE_REMOVE_INSTALLATION="PLEASE REMEMBER TO COMPLETELY REMOVE THE INSTALLATION FOLDER.<br />You will not be able to proceed beyond this point until the installation folder has been removed. This is a security feature of Joomla!"
INSTL_COMPLETE_REMOVE_FOLDER="Remove &quot;%s&quot; folder"
INSTL_COMPLETE_REMOVE_INSTALLATION="PLEASE REMEMBER TO COMPLETELY REMOVE THE INSTALLATION FOLDER.<br />You will not be able to proceed beyond this point until the &quot;%s&quot; folder has been removed. This is a security feature of Joomla!"
INSTL_COMPLETE_TITLE="Congratulations! Joomla! is now installed."
INSTL_COMPLETE_INSTALL_LANGUAGES="Extra steps: Install languages"

Expand Down
36 changes: 32 additions & 4 deletions installation/model/database.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,14 @@ public function initialise($options)
if (!JFile::write($remoteDbPath, ''))
{
// Request to create the file manually
JFactory::getApplication()->enqueueMessage(JText::sprintf('INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE', $remoteDbFile), 'error');
JFactory::getApplication()->enqueueMessage(
JText::sprintf(
'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE',
$remoteDbFile,
'installation'
),
'error'
);

JFactory::getSession()->set('remoteDbFileUnwritable', true);

Expand All @@ -215,7 +222,14 @@ public function initialise($options)
JFactory::getSession()->set('remoteDbFileWrittenByJoomla', true);

// Request to delete that file
JFactory::getApplication()->enqueueMessage(JText::sprintf('INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE', $remoteDbFile), 'error');
JFactory::getApplication()->enqueueMessage(
JText::sprintf(
'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE',
$remoteDbFile,
'installation'
),
'error'
);

return false;
}
Expand All @@ -225,7 +239,14 @@ public function initialise($options)
// Add the general message
JFactory::getApplication()->enqueueMessage($generalRemoteDatabaseMessage, 'warning');

JFactory::getApplication()->enqueueMessage(JText::sprintf('INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE', $remoteDbFile), 'error');
JFactory::getApplication()->enqueueMessage(
JText::sprintf(
'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE',
$remoteDbFile,
'installation'
),
'error'
);

return false;
}
Expand All @@ -235,7 +256,14 @@ public function initialise($options)
// Add the general message
JFactory::getApplication()->enqueueMessage($generalRemoteDatabaseMessage, 'warning');

JFactory::getApplication()->enqueueMessage(JText::sprintf('INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE', $remoteDbFile), 'error');
JFactory::getApplication()->enqueueMessage(
JText::sprintf(
'INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE',
$remoteDbFile,
'installation'
),
'error'
);

return false;
}
Expand Down
6 changes: 3 additions & 3 deletions installation/view/complete/tmpl/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class="form-validate form-horizontal">
<hr class="hr-condensed" />
<div class="row-fluid">
<div class="span6">
<p><?php echo JText::_('INSTL_COMPLETE_LANGUAGE_DESC'); ?></p>
<p><?php echo JText::sprintf('INSTL_COMPLETE_LANGUAGE_DESC', 'installation'); ?></p>
<p><a href="#" class="btn btn-primary" id="instLangs" onclick="return Install.goToPage('languages');"><span class="icon-arrow-right icon-white"></span> <?php echo JText::_('INSTL_COMPLETE_INSTALL_LANGUAGES'); ?></a></p>
</div>
<div class="alert alert-info span6">
Expand All @@ -34,8 +34,8 @@ class="form-validate form-horizontal">
</div>
<div class="row-fluid">
<div class="alert">
<p><?php echo JText::_('INSTL_COMPLETE_REMOVE_INSTALLATION'); ?></p>
<input type="button" class="btn btn-warning" name="instDefault" onclick="Install.removeFolder(this);" value="<?php echo JText::_('INSTL_COMPLETE_REMOVE_FOLDER'); ?>" />
<p><?php echo JText::sprintf('INSTL_COMPLETE_REMOVE_INSTALLATION', 'installation'); ?></p>
<input type="button" class="btn btn-warning" name="instDefault" onclick="Install.removeFolder(this);" value="<?php echo JText::sprintf('INSTL_COMPLETE_REMOVE_FOLDER', 'installation'); ?>" />
</div>
</div>
<div class="row-fluid">
Expand Down
4 changes: 2 additions & 2 deletions installation/view/remove/tmpl/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
<h3><?php echo JText::_('INSTL_COMPLETE_TITLE'); ?></h3>
</div>
<div class="alert">
<p><?php echo JText::_('INSTL_COMPLETE_REMOVE_INSTALLATION'); ?></p>
<input type="button" class="btn btn-warning" name="instDefault" onclick="Install.removeFolder(this);" value="<?php echo JText::_('INSTL_COMPLETE_REMOVE_FOLDER'); ?>" />
<p><?php echo JText::sprintf('INSTL_COMPLETE_REMOVE_INSTALLATION', 'installation'); ?></p>
<input type="button" class="btn btn-warning" name="instDefault" onclick="Install.removeFolder(this);" value="<?php echo JText::sprintf('INSTL_COMPLETE_REMOVE_FOLDER', 'installation'); ?>" />
</div>
<div class="btn-toolbar">
<div class="btn-group">
Expand Down
41 changes: 25 additions & 16 deletions layouts/joomla/content/readmore.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,29 @@
?>

<p class="readmore">
<a class="btn" href="<?php echo $displayData['link']; ?>" itemprop="url">
<span class="icon-chevron-right" aria-hidden="true"></span>
<?php if (!$params->get('access-view')) :
echo JText::_('COM_CONTENT_REGISTER_TO_READ_MORE');
elseif ($readmore = $item->alternative_readmore) :
echo $readmore;
if ($params->get('show_readmore_title', 0) != 0) :
echo JHtml::_('string.truncate', $item->title, $params->get('readmore_limit'));
endif;
elseif ($params->get('show_readmore_title', 0) == 0) :
echo JText::sprintf('COM_CONTENT_READ_MORE_TITLE');
else :
echo JText::_('COM_CONTENT_READ_MORE');
echo JHtml::_('string.truncate', $item->title, $params->get('readmore_limit'));
endif; ?>
</a>
<?php if (!$params->get('access-view')) : ?>
<a class="btn" href="<?php echo $displayData['link']; ?>" itemprop="url" aria-label="<?php echo JText::_('COM_CONTENT_REGISTER_TO_READ_MORE'); ?> <?php echo htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8'); ?>">
<span class="icon-chevron-right" aria-hidden="true"></span>
<?php echo JText::_('COM_CONTENT_REGISTER_TO_READ_MORE'); ?>
</a>
<?php elseif ($readmore = $item->alternative_readmore) : ?>
<a class="btn" href="<?php echo $displayData['link']; ?>" itemprop="url" aria-label="<?php echo htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8'); ?>">
<span class="icon-chevron-right" aria-hidden="true"></span>
<?php echo $readmore; ?>
<?php if ($params->get('show_readmore_title', 0) != 0) : ?>
<?php echo JHtml::_('string.truncate', $item->title, $params->get('readmore_limit')); ?>
<?php endif; ?>
</a>
<?php elseif ($params->get('show_readmore_title', 0) == 0) : ?>
<a class="btn" href="<?php echo $displayData['link']; ?>" itemprop="url" aria-label="<?php echo JText::_('COM_CONTENT_READ_MORE'); ?> <?php echo htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8'); ?>">
<span class="icon-chevron-right" aria-hidden="true"></span>
<?php echo JText::sprintf('COM_CONTENT_READ_MORE_TITLE'); ?>
</a>
<?php else : ?>
<a class="btn" href="<?php echo $displayData['link']; ?>" itemprop="url" aria-label="<?php echo JText::_('COM_CONTENT_READ_MORE'); ?> <?php echo htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8'); ?>">
<span class="icon-chevron-right" aria-hidden="true"></span>
<?php echo JText::_('COM_CONTENT_READ_MORE'); ?>
<?php echo JHtml::_('string.truncate', $item->title, $params->get('readmore_limit')); ?>
</a>
<?php endif; ?>
</p>
32 changes: 26 additions & 6 deletions libraries/src/Crypt/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
# Important Security Information

If you're going to use JCrypt in any of your plugins, make *sure* you use **JCryptCipherCrypto**; it's the only one that's cryptographically secure. (It's [version 1.1 of Defuse Security's encryption library](https://github.com/defuse/php-encryption)).
If you're going to use JCrypt in any of your extensions, make *sure* you use **CryptoCipher** or **SodiumCipher**; These are the only two which are cryptographically secure.

```php
$cipher = new JCryptCipherCrypto();
use Joomla\CMS\Crypt\Cipher\SodiumCipher;

$cipher = new SodiumCipher;
$key = $cipher->generateKey();
$data = 'My encrypted data.';

$cipher->setNonce(\Sodium\randombytes_buf(\Sodium\CRYPTO_BOX_NONCEBYTES));

$encrypted = $cipher->encrypt($data, $key);
$decrypted = $cipher->decrypt($encrypted, $key);

if ($decrypted !== $data)
{
throw new RuntimeException('The data was not decrypted correctly.');
}
```

```php
use Joomla\CMS\Crypt\Cipher\CryptoCipher;

$cipher = new CryptoCipher();
$key = $cipher->generateKey(); // Store this for long-term use

$message = "We're all living on a yellow submarine!";
Expand All @@ -13,10 +33,10 @@ $decrypted = $cipher->decrypt($ciphertext, $key);

## Avoid these Ciphers if Possible

* `JcryptCipher3Des`
* `JcryptCipherBlowfish`
* `JcryptCipherMcrypt`
* `JcryptCipherRijndael256`
* `JCryptCipher3Des`
* `JCryptCipherBlowfish`
* `JCryptCipherMcrypt`
* `JCryptCipherRijndael256`

All of these ciphers are vulnerable to something called a [chosen-ciphertext attack](https://en.wikipedia.org/wiki/Chosen-ciphertext_attack). The only provable way to prevent chosen-ciphertext attacks is to [use authenticated encryption](https://paragonie.com/blog/2015/05/using-encryption-and-authentication-correctly), preferrably in an [Encrypt-then-MAC construction](http://www.thoughtcrime.org/blog/the-cryptographic-doom-principle/).

Expand Down

0 comments on commit 56c6c4c

Please sign in to comment.