|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<!--<title>Sample - CKEditor</title>-->
|
|
|
|
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
|
|
|
<link rel="stylesheet" type="text/css" href="customize/index.css" />
|
|
|
|
<style>
|
|
|
|
#whatis {
|
|
|
|
padding-left: 15%;
|
|
|
|
padding-right: 15%;
|
|
|
|
font-size: medium;
|
|
|
|
}
|
|
|
|
.create {
|
|
|
|
background-color: rgb(77, 146, 68);
|
|
|
|
background-image: linear-gradient(rgb(39, 100, 0) 0%, rgb(77, 146, 68) 100%);
|
|
|
|
border-bottom-color: rgb(77, 146, 68);
|
|
|
|
color: rgb(243, 243, 243);
|
|
|
|
font-weight:bold;
|
|
|
|
font-size:large;
|
|
|
|
margin-right: 5px;
|
|
|
|
margin-left: 5px;
|
|
|
|
}
|
|
|
|
.buttons {
|
|
|
|
margin-bottom: 50px;
|
|
|
|
margin-top: 20px;
|
|
|
|
}
|
|
|
|
.button {
|
|
|
|
padding: 2px 6px 2px 6px;
|
|
|
|
border-top: 1px solid #CCCCCC;
|
|
|
|
border-right: 1px solid #333333;
|
|
|
|
border-bottom: 1px solid #333333;
|
|
|
|
border-left: 1px solid #CCCCCC;
|
|
|
|
}
|
|
|
|
|
|
|
|
table.scroll {
|
|
|
|
/* width: 100%; */ /* Optional */
|
|
|
|
/* border-collapse: collapse; */
|
|
|
|
border-spacing: 0;
|
|
|
|
border: 2px solid black;
|
|
|
|
margin-top: 20px;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
}
|
|
|
|
|
|
|
|
table.scroll tbody,
|
|
|
|
table.scroll thead { display: block; }
|
|
|
|
|
|
|
|
table.scroll tbody {
|
|
|
|
height: 100px;
|
|
|
|
overflow-y: auto;
|
|
|
|
overflow-x: hidden;
|
|
|
|
}
|
|
|
|
|
|
|
|
tbody { border-top: 2px solid black; }
|
|
|
|
|
|
|
|
tbody td, thead th {
|
|
|
|
/* width: 20%; */ /* Optional */
|
|
|
|
border-right: 1px solid black;
|
|
|
|
/* white-space: nowrap; */
|
|
|
|
padding-top: 0px;
|
|
|
|
padding-bottom: 0px;
|
|
|
|
padding-right: 20px;
|
|
|
|
}
|
|
|
|
|
|
|
|
tbody td:last-child, thead th:last-child {
|
|
|
|
border-right: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
.remove {
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
<script src="/bower_components/requirejs/require.js"></script>
|
|
|
|
<!-- Piwik -->
|
|
|
|
<script type="text/javascript">
|
|
|
|
if (window.location.href.indexOf('cryptpad.fr') !== -1) {
|
|
|
|
// This piwik is only relevant to cryptpad.fr
|
|
|
|
var _paq = _paq || [];
|
|
|
|
_paq.push(['trackPageView']);
|
|
|
|
_paq.push(['enableLinkTracking']);
|
|
|
|
(function() {
|
|
|
|
var u="//piwik.xwiki.com/";
|
|
|
|
_paq.push(['setTrackerUrl', u+'piwik.php']);
|
|
|
|
_paq.push(['setSiteId', 12]);
|
|
|
|
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
|
|
|
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
|
|
|
|
})();
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
<!-- End Piwik Code -->
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<a href="https://github.com/xwiki-labs/cryptpad"><img style="position: absolute; top: 0; left: 0; border: 0;" src="https://camo.githubusercontent.com/121cd7cbdc3e4855075ea8b558508b91ac463ac2/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f6c6566745f677265656e5f3030373230302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_left_green_007200.png"></a>
|
|
|
|
<div id="whatis">
|
|
|
|
<center>
|
|
|
|
<img class="imgcenter" src="/customize/cryptofist_small.png" />
|
|
|
|
<h1>Unity is Strength - Collaboration is Key</h1>
|
|
|
|
</center>
|
|
|
|
<p>CryptPad is the <strong>zero knowledge</strong> realtime collaborative editor.
|
|
|
|
Encryption carried out in your web browser protects the data from the server, the cloud
|
|
|
|
and the NSA. This project uses the <a href="http://ckeditor.com/">CKEditor</a> Visual Editor
|
|
|
|
the <a href="https://github.com/xwiki-contrib/chainpad">ChainPad</a> realtime engine. The secret
|
|
|
|
encryption key is stored in the URL
|
|
|
|
<a href="https://en.wikipedia.org/wiki/Fragment_identifier">fragment identifier</a> which is
|
|
|
|
never sent to the server but is available to javascript so by sharing the URL, you give
|
|
|
|
authorization to others who want to participate.</p>
|
|
|
|
|
|
|
|
</code></pre><h2 id="howitworks">How It Works</h2>
|
|
|
|
<p>CryptPad uses a variant of the
|
|
|
|
<a href="https://en.wikipedia.org/wiki/Operational_transformation">Operational transformation</a>
|
|
|
|
algorithm which is able to find distributed consensus using a Nakamoto Blockchain, a construct
|
|
|
|
popularized by <a href="https://en.wikipedia.org/wiki/Bitcoin">Bitcoin</a>. This way the
|
|
|
|
algorithm can avoid the need for a central server to resolve Operational Transform Edit
|
|
|
|
Conflicts and without the need for resolving conflicts, the server can be kept unaware of the
|
|
|
|
content which is being edited on the pad.</p>
|
|
|
|
|
|
|
|
<p><strong>NOTE</strong> Pads and spreadsheets will be removed after 30 days of inactivity</p>
|
|
|
|
<center>
|
|
|
|
<noscript>
|
|
|
|
<p>
|
|
|
|
<strong>OOPS</strong> In order to do encryption in your browser, Javascript is really
|
|
|
|
<strong>really</strong> required.
|
|
|
|
</p>
|
|
|
|
</noscript>
|
|
|
|
<script>
|
|
|
|
require(['/common/crypto.js', '/api/config?cb=' + Math.random().toString(16).substring(2)], function (Crypto, Config) {
|
|
|
|
document.getElementById('buttons').setAttribute('style', '');
|
|
|
|
document.getElementById('create-pad').setAttribute('href', '/pad/');
|
|
|
|
if(Config.webrtcURL !== '') {
|
|
|
|
document.getElementById('create-rtcpad').setAttribute('href', '/padrtc/');
|
|
|
|
}
|
|
|
|
document.getElementById('create-sheet').setAttribute('href', '/sheet/#' + Crypto.genKey());
|
|
|
|
document.getElementById('create-code').setAttribute('href', '/code/#' + Crypto.genKey());
|
|
|
|
});
|
|
|
|
require([
|
|
|
|
'/customize/DecorateToolbar.js',
|
|
|
|
'/bower_components/jquery/dist/jquery.min.js'
|
|
|
|
], function (Dt) {
|
|
|
|
var $ = window.$;
|
|
|
|
Dt.main($('#bottom-bar'));
|
|
|
|
var localStorageKey = 'CryptPad_RECENTPADS';
|
|
|
|
var recentPadsStr = localStorage[localStorageKey];
|
|
|
|
var recentPads;
|
|
|
|
if (recentPadsStr) { recentPads = JSON.parse(recentPadsStr); }
|
|
|
|
if (!recentPads) { return; }
|
|
|
|
recentPads.sort(function (a,b) { return b[1] - a[1]; });
|
|
|
|
var $table = $('table.scroll');
|
|
|
|
var $tbody = $table.find('tbody');
|
|
|
|
var now = new Date();
|
|
|
|
var hasRecent = false;
|
|
|
|
|
|
|
|
var memorySpan = 1000 * 60 * 60 * 24 * 30; // thirty days
|
|
|
|
|
|
|
|
var forgetPad = function (url) {
|
|
|
|
if (recentPads) {
|
|
|
|
recentPads = recentPads.filter(function (pad) {
|
|
|
|
// remove the pad in question
|
|
|
|
return pad[0] !== url;
|
|
|
|
});
|
|
|
|
localStorage[localStorageKey] = JSON.stringify(recentPads);
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// show recent pads if they exist
|
|
|
|
recentPads.length && recentPads.some(function (pad, index) {
|
|
|
|
if (!pad) return true;
|
|
|
|
if (now.getTime() - pad[1] > memorySpan) return true;
|
|
|
|
|
|
|
|
hasRecent = true;
|
|
|
|
|
|
|
|
// TODO add support for newer types...
|
|
|
|
var name = /\/sheet\//.test(pad[0])?
|
|
|
|
'Sheet':
|
|
|
|
/\/code\//.test(pad[0])?
|
|
|
|
'Code':
|
|
|
|
'Pad';
|
|
|
|
|
|
|
|
var date = new Date(pad[1]).toLocaleDateString();
|
|
|
|
if (date === now.toLocaleDateString()) {
|
|
|
|
date = new Date(pad[1]).toLocaleTimeString().replace(/ /g, '');
|
|
|
|
}
|
|
|
|
|
|
|
|
var id = 'pad-'+index;
|
|
|
|
$tbody.append('<tr id="'+id+'">' +
|
|
|
|
'<td>' + name + '</td>' +
|
|
|
|
'<td><a href="' + pad[0] + '"' + '">' + pad[0] + '</a></td>' +
|
|
|
|
'<td>' + date + '</td>' +
|
|
|
|
'<td class="remove">remove</td>'+
|
|
|
|
'</tr>');
|
|
|
|
|
|
|
|
var $row = $('#'+id);
|
|
|
|
$row.find('.remove').click(function () {
|
|
|
|
forgetPad(pad[0]);
|
|
|
|
$row.fadeOut(750, function () {
|
|
|
|
$row.remove();
|
|
|
|
if (!$table.find('tr').length) { $table.remove(); }
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
if (recentPads.length < 5) {
|
|
|
|
$tbody.attr('style', 'height: ' + (28 * recentPads.length + 2) + 'px');
|
|
|
|
} else {
|
|
|
|
$tbody.attr('style', 'height: ' + (28 * 5) + 'px');
|
|
|
|
}
|
|
|
|
if (hasRecent) {
|
|
|
|
$('table').attr('style', '');
|
|
|
|
$('#tryit').text('Your Recent pads (stored only in browser)');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
<h5 id="tryit">Try it out!</h5>
|
|
|
|
|
|
|
|
<table class="recent scroll" style="display:none">
|
|
|
|
<tbody>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
<div id="buttons" class="buttons" style="display:none;">
|
|
|
|
<a id="create-pad" class="button create" href="pad">CREATE NEW PAD</a>
|
|
|
|
<a id="create-rtcpad" class="button create" href="pad">CREATE NEW WEBRTC PAD</a>
|
|
|
|
<!--<a id="create-sheet" class="button create" href="sheet">CREATE NEW SPREADSHEET</a>-->
|
|
|
|
<a id="create-code" class="button create" href="code">CREATE NEW CODE COLLABORATION PAD</a>
|
|
|
|
</div>
|
|
|
|
</center>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div id="bottom-bar"></div>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
|