11 Commits

Author SHA1 Message Date
El RIDO
0780e5ace2 skip badges in release export 2019-07-08 20:05:58 +02:00
El RIDO
5d7658b58f switching to pre-rendered logo 2019-07-08 20:00:32 +02:00
El RIDO
1e2014b9fa fixing configuration test generator after PHP refactoring 2019-07-08 19:56:05 +02:00
El RIDO
07018e5876 incrementing version number in preparation of release 2019-07-08 18:35:34 +02:00
El RIDO
6df5127132 move badges to separate document due to data privacy concerns for visitors of the projects main page 2019-07-08 18:20:09 +02:00
El RIDO
8ae87d8653 translate new strings to German 2019-07-07 10:39:14 +02:00
El RIDO
d8ba1b1462 Merge branch 'Quenty31-master' 2019-07-07 10:09:25 +02:00
Quentí
07e0b267f9 Update and corrections
Use of è form for correctly corrèctament
Use of subjunctive after "in case", se per cas + subjectiu
2019-07-06 21:02:58 +02:00
El RIDO
ae456bf7a1 Merge branch 'yvisherve-patch-1' 2019-07-04 06:26:01 +02:00
El RIDO
57417c08cf revert formatting changes for better comparison 2019-07-04 06:25:21 +02:00
Hervé Yvis
943b6bdfc3 Upgrade french translation
Translation of untranslated sentences + Improved translation of one sentence
2019-07-02 01:08:47 +02:00
46 changed files with 144 additions and 466 deletions

1
.gitattributes vendored
View File

@@ -18,3 +18,4 @@ js/test/ export-ignore
.styleci.yml export-ignore
.travis.yml export-ignore
composer.json export-ignore
BADGES.md export-ignore

9
BADGES.md Normal file
View File

@@ -0,0 +1,9 @@
# Badges
[![Build Status](https://travis-ci.org/PrivateBin/PrivateBin.svg?branch=master)](https://travis-ci.org/PrivateBin/PrivateBin) [![Build Status](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/badges/build.png?b=master)](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/build-status/master)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/094500f62abf4c9aa0c8a8a4520e4789)](https://www.codacy.com/app/PrivateBin/PrivateBin)
[![Code Climate](https://codeclimate.com/github/PrivateBin/PrivateBin/badges/gpa.svg)](https://codeclimate.com/github/PrivateBin/PrivateBin)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/?branch=master)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/57c9e74e-c6f9-4de6-a876-df66ec2ea1ff/mini.png)](https://insight.sensiolabs.com/projects/57c9e74e-c6f9-4de6-a876-df66ec2ea1ff)
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/094500f62abf4c9aa0c8a8a4520e4789)](https://www.codacy.com/app/PrivateBin/PrivateBin)
[![Test Coverage](https://codeclimate.com/github/PrivateBin/PrivateBin/badges/coverage.svg)](https://codeclimate.com/github/PrivateBin/PrivateBin/coverage) [![Code Coverage](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/?branch=master)

View File

@@ -165,7 +165,7 @@ CREATE INDEX parent ON prefix_comment(pasteid);
CREATE TABLE prefix_config (
id CHAR(16) NOT NULL, value TEXT, PRIMARY KEY (id)
);
INSERT INTO prefix_config VALUES('VERSION', '1.2.1');
INSERT INTO prefix_config VALUES('VERSION', '1.3');
```
In **PostgreSQL**, the data, attachment, nickname and vizhash columns needs to be TEXT and not BLOB or MEDIUMBLOB.

View File

@@ -1,13 +1,6 @@
# [<img alt="PrivateBin" src="https://cdn.rawgit.com/PrivateBin/assets/master/images/minified/logo.svg" width="500" />](https://privatebin.info/)
[![Build Status](https://travis-ci.org/PrivateBin/PrivateBin.svg?branch=master)](https://travis-ci.org/PrivateBin/PrivateBin) [![Build Status](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/badges/build.png?b=master)](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/build-status/master)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/094500f62abf4c9aa0c8a8a4520e4789)](https://www.codacy.com/app/PrivateBin/PrivateBin)
[![Code Climate](https://codeclimate.com/github/PrivateBin/PrivateBin/badges/gpa.svg)](https://codeclimate.com/github/PrivateBin/PrivateBin)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/?branch=master)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/57c9e74e-c6f9-4de6-a876-df66ec2ea1ff/mini.png)](https://insight.sensiolabs.com/projects/57c9e74e-c6f9-4de6-a876-df66ec2ea1ff)
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/094500f62abf4c9aa0c8a8a4520e4789)](https://www.codacy.com/app/PrivateBin/PrivateBin)
[![Test Coverage](https://codeclimate.com/github/PrivateBin/PrivateBin/badges/coverage.svg)](https://codeclimate.com/github/PrivateBin/PrivateBin/coverage) [![Code Coverage](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/?branch=master)
# [![PrivateBin](https://cdn.rawgit.com/PrivateBin/assets/master/images/preview/logoSmall.png)](https://privatebin.info/)
*Current version: 1.2.1*
*Current version: 1.3*
**PrivateBin** is a minimalist, open source online [pastebin](https://en.wikipedia.org/wiki/Pastebin)
where the server has zero knowledge of pasted data.

View File

@@ -6,7 +6,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
body {

View File

@@ -6,7 +6,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
/* When there is no script at all other */

View File

@@ -6,7 +6,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
/* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved.

View File

@@ -155,11 +155,11 @@
"Could not get paste data: %s":
"Text konnte nicht geladen werden: %s",
"QR code": "QR code",
"I love you too, bot…": "I love you too, bot…",
"I love you too, bot…": "Ich mag Dich auch, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"Diese Webseite verwendet eine unsichere HTTP Verbindung! Bitte benutze sie nur zum Testen.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"<a href=\"%s\">Besuche diesen FAQ Eintrag</a> für weitere Informationen dazu.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Dein Browser benötigt möglicherweise eine HTTPS Verbindung um das WebCrypto API nutzen zu können. Versuche <a href=\"%s\">auf HTTPS zu wechseln</a>."
}

View File

@@ -87,7 +87,7 @@
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
"POUR VOS YEUX UNIQUEMENT. Ne fermez pas cette fenêtre, ce paste ne pourra plus être affiché.",
"Could not decrypt comment; Wrong key?":
"Impossible de déchiffrer le commentaire ; mauvaise clé ?",
"Impossible de déchiffrer le commentaire; mauvaise clé ?",
"Reply":
"Répondre",
"Anonymous":
@@ -139,8 +139,8 @@
"Cloned: '%s'": "Cloner '%s'",
"The cloned file '%s' was attached to this paste.": "Le fichier cloné '%s' a été attaché à ce paste.",
"Attach a file": "Attacher un fichier ",
"alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
"File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
"alternatively drag & drop a file or paste an image from the clipboard": "alternativement, glisser & déposer un fichier ou coller une image à partir du presse-papiers",
"File too large, to display a preview. Please download the attachment.": "Fichier trop volumineux, pour afficher un aperçu. Veuillez télécharger la pièce jointe.",
"Remove attachment": "Enlever l'attachement",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
"Votre navigateur ne supporte pas l'envoi de fichiers chiffrés. Merci d'utiliser un navigateur plus récent.",
@@ -162,13 +162,13 @@
"Si ce message ne disparaîssait pas, jetez un oeil à <a href=\"%s\">cette FAQ pour des idées de résolution</a> (en Anglais).",
"+++ no paste text +++": "+++ pas de paste-text +++",
"Could not get paste data: %s":
"Could not get paste data: %s",
"Impossible d'obtenir les données du paste: %s",
"QR code": "QR code",
"I love you too, bot…": "I love you too, bot…",
"I love you too, bot…": "Je taime aussi, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"Ce site web utilise une connexion HTTP non sécurisée ! Veuillez lutiliser uniquement pour des tests.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"Pour plus d'informations <a href=\"%s\">consultez cette rubrique de la FAQ</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Votre navigateur peut nécessiter une connexion HTTPS pour prendre en charge lAPI WebCrypto. Essayez <a href=\"%s\">de passer en HTTPS</a>."
}

View File

@@ -30,7 +30,7 @@
"Wrong deletion token. Paste was not deleted.":
"Geton de supression incorrècte. Lo tèxte es pas estat suprimit.",
"Paste was properly deleted.":
"Lo tèxte es estat correctament suprimit.",
"Lo tèxte es estat corrèctament suprimit.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"JavaScript es requesit per far foncionar %s. <br />O planhèm per linconvenient.",
"%s requires a modern browser to work.":
@@ -109,7 +109,7 @@
"unknown status":
"Estatut desconegut",
"server error or not responding":
"Lo servidor respond pas o a rencontrat una error",
"Lo servidor respond pas o a rescontrat una error",
"Could not post comment: %s":
"Impossible de mandar lo comentari:%s",
"Sending paste…":
@@ -159,16 +159,16 @@
"Decrypting paste…": "Deschirament del tèxte…",
"Preparing new paste…": "Preparacion…",
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
"Se per cas aqueste messatge quita pas de safichar mercés de gaitar <a href=\"%s\">aquesta FAQ per las solucions</a> (en anglés).",
"Se per cas aqueste messatge quite pas de safichar mercés de gaitar <a href=\"%s\">aquesta FAQ per las solucions</a> (en anglés).",
"+++ no paste text +++": "+++ cap de tèxte pegat +++",
"Could not get paste data: %s":
"Recuperacion impossibla de las donadas copiadas: %s",
"QR code": "Còdi QR",
"I love you too, bot…": "I love you too, bot…",
"I love you too, bot…": "Taimi tanben, robòt…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"Aqueste site utiliza una connexion HTTP pas segura ! Mercés de lutilizar pas que per densages.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"Per mai dinformacions <a href=\"%s\">vejatz aqueste article de FAQ</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Se pòt que vòstre navigator faga besonh duna connexion HTTPS per èsser compatible amb lAPI WebCrypto. Ensajatz de <a href=\"%s\">passar al HTTPS</a>."
}

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
// change this, if your php files and data is outside of your webservers document root

View File

@@ -1,6 +1,6 @@
{
"name": "privatebin",
"version": "1.2.1",
"version": "1.3",
"description": "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bit AES in Galois Counter mode (GCM).",
"main": "privatebin.js",
"directories": {

View File

@@ -26,9 +26,6 @@
},
"time_to_live": {
"@type": "pb:RemainingSeconds"
},
"challenge": {
"@type": "pb:Challenge"
}
}
}

View File

@@ -6,7 +6,7 @@
* @see {@link https://github.com/PrivateBin/PrivateBin}
* @copyright 2012 Sébastien SAUVAGE ({@link http://sebsauvage.net})
* @license {@link https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License}
* @version 1.2.1
* @version 1.3
* @name PrivateBin
* @namespace
*/
@@ -851,12 +851,10 @@ jQuery.PrivateBin = (function($, RawDeflate) {
* @param {string} key
* @param {string} password
* @param {array} spec cryptographic specification
* @param {bool} exportKey
* @return {CryptoKey} derived key
*/
async function deriveKey(key, password, spec, exportKey)
async function deriveKey(key, password, spec)
{
exportKey = exportKey || false;
let keyArray = stringToArraybuffer(key);
if (password.length > 0) {
// version 1 pastes did append the passwords SHA-256 hash in hex
@@ -901,38 +899,11 @@ jQuery.PrivateBin = (function($, RawDeflate) {
name: 'AES-' + spec[6].toUpperCase(), // can be any supported AES algorithm ("AES-CTR", "AES-CBC", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH" or "HMAC")
length: spec[3] // can be 128, 192 or 256
},
exportKey, // may the key get exported, false by default
false, // the key may not be exported
['encrypt', 'decrypt'] // we may only use it for en- and decryption
);
}
/**
* derive PBKDF2 protected credentials for server to validate password
*
* @name CryptTool.deriveCredentials
* @function
* @private
* @param {string} key
* @param {string} password
* @return {string} derived key
*/
async function deriveCredentials(key, password)
{
const spec = [
null, // initialization vector
key.slice(0, 16), // salt
100000, // iterations
256, // key size
null, // tag size
null, // algorithm
'gcm', // algorithm mode
'none' // compression
];
return window.crypto.subtle.exportKey(
'raw', await deriveKey(key.slice(16), password, spec, true)
);
}
/**
* gets crypto settings from specification and authenticated data
*
@@ -953,56 +924,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
};
}
/**
* get PBKDF2 protected credentials for server to validate password
*
* @name CryptTool.getCredentials
* @function
* @param {string} key
* @param {string} password
* @return {string} derived key
*/
me.getCredentials = async function(key, password)
{
return btoa(
arraybufferToString(
await deriveCredentials(key, password)
)
);
}
/**
* get HMAC of paste ID and PBKDF2 protected credentials for server to validate
*
* @name CryptTool.getToken
* @function
* @param {string} id
* @param {string} key
* @param {string} password
* @return {string} decrypted message, empty if decryption failed
*/
me.getToken = async function(id, key, password)
{
return btoa(
arraybufferToString(
await window.crypto.subtle.sign(
{name: 'HMAC'},
await window.crypto.subtle.importKey(
'raw',
await deriveCredentials(key, password),
{
name: 'HMAC',
hash: {name: 'SHA-256'} // can be "SHA-1", "SHA-256", "SHA-384" or "SHA-512"
},
false, // may not export this
['sign']
),
stringToArraybuffer(id)
)
)
);
}
/**
* compress, then encrypt message with given key and password
*
@@ -1207,7 +1128,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
* force a data reload. Default: true
* @return string
*/
me.getPasteData = async function(callback, useCache)
me.getPasteData = function(callback, useCache)
{
// use cache if possible/allowed
if (useCache !== false && pasteData !== null) {
@@ -1220,31 +1141,17 @@ jQuery.PrivateBin = (function($, RawDeflate) {
return pasteData;
}
// load data
// reload data
ServerInteraction.prepare();
ServerInteraction.setUrl(
Helper.baseUri() + '?' + $.param({
pasteid: me.getPasteId(),
token: await CryptTool.getToken(
me.getPasteId(), me.getPasteKey(), Prompt.getPassword()
)
})
);
ServerInteraction.setUrl(Helper.baseUri() + '?pasteid=' + me.getPasteId());
ServerInteraction.setFailure(function (status, data) {
// revert loading status…
Alert.hideLoading();
TopNav.showViewButtons();
// might be a missing password, try one more time after getting one
if (Prompt.getPassword().length === 0) {
Prompt.requestPassword(function () {
me.getPasteData(callback, useCache);
});
} else {
// show error message
Alert.showError(ServerInteraction.parseUploadError(status, data, 'get paste data'));
}
// show error message
Alert.showError(ServerInteraction.parseUploadError(status, data, 'get paste data'));
});
ServerInteraction.setSuccess(function (status, data) {
pasteData = new Paste(data);
@@ -1970,9 +1877,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
*
* @name Prompt.requestPassword
* @function
* @param {function} callback
*/
me.requestPassword = function(callback)
me.requestPassword = function()
{
// show new bootstrap method (if available)
if ($passwordModal.length !== 0) {
@@ -1990,9 +1896,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
}
if (password.length === 0) {
// recurse…
return me.requestPassword(callback);
return me.requestPassword();
}
callback();
PasteDecrypter.run();
};
/**
@@ -4149,7 +4055,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
// show notification
const baseUri = Helper.baseUri() + '?',
url = baseUri + data.id + '#' + CryptTool.base58encode(data.encryptionKey),
deleteUrl = baseUri + $.param({pasteid: data.id, deletetoken: data.deletetoken});
deleteUrl = baseUri + 'pasteid=' + data.id + '&deletetoken=' + data.deletetoken;
PasteStatus.createPasteNotification(url, deleteUrl);
// show new URL in browser bar
@@ -4291,9 +4197,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
// prepare server interaction
ServerInteraction.prepare();
const key = CryptTool.getSymmetricKey(),
password = TopNav.getPassword();
ServerInteraction.setCryptParameters(password, key);
ServerInteraction.setCryptParameters(TopNav.getPassword());
// set success/fail functions
ServerInteraction.setSuccess(showCreatedPaste);
@@ -4314,10 +4218,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
TopNav.getOpenDiscussion() ? 1 : 0,
TopNav.getBurnAfterReading() ? 1 : 0
]);
ServerInteraction.setUnencryptedData('meta', {
'expire': TopNav.getExpiration(),
'challenge': await CryptTool.getCredentials(key, password)
});
ServerInteraction.setUnencryptedData('meta', {'expire': TopNav.getExpiration()});
// prepare PasteViewer for later preview
PasteViewer.setText(plainText);
@@ -4380,7 +4281,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
// if it fails, request password
if (plaindata.length === 0 && password.length === 0) {
// show prompt
Prompt.requestPassword(me.run);
Prompt.requestPassword();
// Thus, we cannot do anything yet, we need to wait for the user
// input.
@@ -4826,15 +4727,31 @@ jQuery.PrivateBin = (function($, RawDeflate) {
const orgPosition = $(window).scrollTop();
Model.getPasteData(function (data) {
PasteDecrypter.run(new Paste(data));
ServerInteraction.prepare();
ServerInteraction.setUrl(Helper.baseUri() + '?pasteid=' + Model.getPasteId());
// restore position
window.scrollTo(0, orgPosition);
ServerInteraction.setFailure(function (status, data) {
// revert loading status…
Alert.hideLoading();
TopNav.showViewButtons();
// NOTE: could create problems as callback may be called
// asyncronously if PasteDecrypter e.g. needs to wait for a
// password being entered
callback();
// show error message
Alert.showError(
ServerInteraction.parseUploadError(status, data, 'refresh display')
);
});
ServerInteraction.setSuccess(function (status, data) {
PasteDecrypter.run(new Paste(data));
// restore position
window.scrollTo(0, orgPosition);
// NOTE: could create problems as callback may be called
// asyncronously if PasteDecrypter e.g. needs to wait for a
// password being entered
callback();
});
ServerInteraction.run();
}, false); // this false is important as it circumvents the cache
}

View File

@@ -4,6 +4,9 @@ var common = require('../common');
describe('AttachmentViewer', function () {
describe('setAttachment, showAttachment, removeAttachment, hideAttachment, hideAttachmentPreview, hasAttachment, getAttachment & moveAttachmentTo', function () {
this.timeout(30000);
before(function () {
cleanup();
});
jsc.property(
'displays & hides data as requested',

View File

@@ -237,48 +237,19 @@ conseq_or_bottom inv (interp (nth_iterate sBody n) (MemElem mem))
});
});
describe('getCredentials', function () {
it('generates credentials with password', async function () {
const clean = jsdom();
window.crypto = new WebCrypto();
// choosen by fair dice roll
const key = atob('EqueAutxlrekNNEvJWB1uaaiwbk/GGpn4++cdk+uDMc='),
// -- "That's amazing. I've got the same combination on my luggage."
password = Array.apply(0, Array(6)).map((_,b) => b + 1).join('');
const credentials = await $.PrivateBin.CryptTool.getCredentials(
key, password
);
clean();
assert.strictEqual(credentials, 'JS8bJWFx1bAPI2LMxfWrw4AQ7cedNVl8UmjUd/pW7Yg=');
});
it('generates credentials without password', async function () {
const clean = jsdom();
window.crypto = new WebCrypto();
// choosen by fair dice roll
const key = atob('U844LK1y2uUPthTgMvPECwGyQzwScCwkaEI/+qLfQSE='),
password = '';
const credentials = await $.PrivateBin.CryptTool.getCredentials(
key, password
);
clean();
assert.strictEqual(credentials, 'VfAvY7T9rm3K3JKtiOeb+B+rXnE6yZ4bYQTaD9jwjEk=');
});
});
describe('getSymmetricKey', function () {
this.timeout(30000);
let keys = [];
var keys = [];
// the parameter is used to ensure the test is run more then one time
jsc.property(
'returns random, non-empty keys',
'integer',
function(counter) {
const clean = jsdom();
var clean = jsdom();
window.crypto = new WebCrypto();
const key = $.PrivateBin.CryptTool.getSymmetricKey(),
result = (key !== '' && keys.indexOf(key) === -1);
var key = $.PrivateBin.CryptTool.getSymmetricKey(),
result = (key !== '' && keys.indexOf(key) === -1);
keys.push(key);
clean();
return result;

View File

@@ -22,7 +22,7 @@ describe('InitialCheck', function () {
'</body></html>'
);
$.PrivateBin.Alert.init();
window.crypto = new WebCrypto();
window.crypto = null;
const result1 = !$.PrivateBin.InitialCheck.init(),
result2 = !$('#errormessage').hasClass('hidden');
clean();
@@ -76,7 +76,7 @@ describe('InitialCheck', function () {
'</body></html>'
);
$.PrivateBin.Alert.init();
window.crypto = new WebCrypto();
window.crypto = null;
const result1 = $.PrivateBin.InitialCheck.init(),
result2 = isSecureContext === $('#httpnotice').hasClass('hidden');
clean();

View File

@@ -92,9 +92,6 @@
"@type": "dp:Second",
"@minimum": 1
},
"Challenge": {
"@type": "pb:Base64"
},
"CipherParameters": {
"@container": "@list",
"@value": [

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin;
@@ -28,7 +28,7 @@ class Controller
*
* @const string
*/
const VERSION = '1.2.1';
const VERSION = '1.3';
/**
* minimal required PHP version
@@ -276,7 +276,9 @@ class Controller
// accessing this method ensures that the paste would be
// deleted if it has already expired
$paste->get();
if ($paste->isDeleteTokenCorrect($deletetoken)) {
if (
Filter::slowEquals($deletetoken, $paste->getDeleteToken())
) {
// Paste exists and deletion token is valid: Delete the paste.
$paste->delete();
$this->_status = 'Paste was properly deleted.';
@@ -313,20 +315,9 @@ class Controller
try {
$paste = $this->_model->getPaste($dataid);
if ($paste->exists()) {
// handle challenge response
if (!$paste->isTokenCorrect($this->_request->getParam('token'))) {
// we send a generic error to avoid leaking information
// about the existance of a burn after reading pastes
// this avoids an attacker being able to poll, if it has
// been read by the intended recipient or not
$this->_return_message(1, self::GENERIC_ERROR);
return;
}
$data = $paste->get();
foreach (array('salt', 'challenge') as $key) {
if (array_key_exists($key, $data['meta'])) {
unset($data['meta'][$key]);
}
if (array_key_exists('salt', $data['meta'])) {
unset($data['meta']['salt']);
}
$this->_return_message(0, $dataid, (array) $data);
} else {

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin\Data;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin\Data;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin\Data;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin;
@@ -72,7 +72,6 @@ class Filter
/**
* fixed time string comparison operation to prevent timing attacks
* https://crackstation.net/hashing-security.htm?=rd#slowequals
* can be replaced with hash_equals() after we drop PHP 5.5 support
*
* @access public
* @static

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin;
@@ -67,13 +67,6 @@ class FormatV2
if (!($ct = base64_decode($message['ct'], true))) {
return false;
}
// - (optional) challenge
if (
!$isComment && array_key_exists('challenge', $message['meta']) &&
!base64_decode($message['meta']['challenge'], true)
) {
return false;
}
// Make sure some fields have a reasonable size:
// - initialization vector
@@ -123,7 +116,8 @@ class FormatV2
// require only the key 'expire' in the metadata of pastes
if (!$isComment && (
count($message['meta']) === 0 ||
!array_key_exists('expire', $message['meta'])
!array_key_exists('expire', $message['meta']) ||
count($message['meta']) > 1
)) {
return false;
}

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin\Model;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin\Model;

View File

@@ -7,14 +7,13 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin\Model;
use Exception;
use PrivateBin\Controller;
use PrivateBin\Filter;
use PrivateBin\Persistence\ServerSalt;
/**
@@ -24,14 +23,6 @@ use PrivateBin\Persistence\ServerSalt;
*/
class Paste extends AbstractModel
{
/**
* Token for challenge/response.
*
* @access protected
* @var string
*/
protected $_token = '';
/**
* Get paste data.
*
@@ -41,11 +32,6 @@ class Paste extends AbstractModel
*/
public function get()
{
// return cached result if one is found
if (array_key_exists('adata', $this->_data) || array_key_exists('data', $this->_data)) {
return $this->_data;
}
$data = $this->_store->read($this->getId());
if ($data === false) {
throw new Exception(Controller::GENERIC_ERROR, 64);
@@ -62,16 +48,10 @@ class Paste extends AbstractModel
unset($data['meta']['expire_date']);
}
// check if non-expired burn after reading paste needs to be deleted,
// but don't delete it if an incorrect token was sent
// check if non-expired burn after reading paste needs to be deleted
if (
(
(array_key_exists('adata', $data) && $data['adata'][3] === 1) ||
(array_key_exists('burnafterreading', $data['meta']) && $data['meta']['burnafterreading'])
) && (
!array_key_exists('challenge', $data['meta']) ||
$this->_token === $data['meta']['challenge']
)
(array_key_exists('adata', $data) && $data['adata'][3] === 1) ||
(array_key_exists('burnafterreading', $data['meta']) && $data['meta']['burnafterreading'])
) {
$this->delete();
}
@@ -114,12 +94,6 @@ class Paste extends AbstractModel
$this->_data['meta']['created'] = time();
$this->_data['meta']['salt'] = serversalt::generate();
// if a challenge was sent, we store the HMAC of paste ID & challenge
if (array_key_exists('challenge', $this->_data['meta'])) {
$this->_data['meta']['challenge'] = base64_encode(hash_hmac(
'sha256', $this->getId(), base64_decode($this->_data['meta']['challenge']), true
));
}
// store paste
if (
@@ -227,40 +201,6 @@ class Paste extends AbstractModel
(array_key_exists('opendiscussion', $this->_data['meta']) && $this->_data['meta']['opendiscussion']);
}
/**
* Check if paste challenge matches provided token.
*
* @access public
* @param string $token
* @throws Exception
* @return bool
*/
public function isTokenCorrect($token)
{
$this->_token = $token;
if (!array_key_exists('challenge', $this->_data['meta'])) {
$this->get();
}
if (array_key_exists('challenge', $this->_data['meta'])) {
return Filter::slowEquals($token, $this->_data['meta']['challenge']);
}
// paste created without challenge, accept every token sent
return true;
}
/**
* Check if paste salt based HMAC matches provided delete token.
*
* @access public
* @param string $deletetoken
* @throws Exception
* @return bool
*/
public function isDeleteTokenCorrect($deletetoken)
{
return Filter::slowEquals($deletetoken, $this->getDeleteToken());
}
/**
* Sanitizes data to conform with current configuration.
*

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.2.1
* @version 1.3
*/
namespace PrivateBin;

View File

@@ -8,7 +8,7 @@
* @link http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 0.0.5 beta PrivateBin 1.2.1
* @version 0.0.5 beta PrivateBin 1.3
*/
namespace PrivateBin;

View File

@@ -71,7 +71,7 @@ if ($MARKDOWN):
endif;
?>
<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.11.js" integrity="sha512-p7UyJuyBkhMcMgE4mDsgK0Lz70OvetLefua1oXs1OujWv9gOxh4xy8InFux7bZ4/DAZsTmO4rgVwZW9BHKaTaw==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-r9MutKcgP/igbs8aUbENyJEie7LMyJ22f2On0RwGL0Hq0seJnmnPo4avDfhR0E/TZWDoux2arzxYHneH2/Ltmw==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-dNBKGlXagUZhkKcI+HhEH0otOswA5g2QnJV8BxYxNK/piW9jJWZvADCbzDJNRjt6A6QgMwBM8+lH7K3lgsOuQw==" crossorigin="anonymous"></script>
<!--[if IE]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;}</style>
<![endif]-->

View File

@@ -49,7 +49,7 @@ if ($MARKDOWN):
endif;
?>
<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.11.js" integrity="sha512-p7UyJuyBkhMcMgE4mDsgK0Lz70OvetLefua1oXs1OujWv9gOxh4xy8InFux7bZ4/DAZsTmO4rgVwZW9BHKaTaw==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-r9MutKcgP/igbs8aUbENyJEie7LMyJ22f2On0RwGL0Hq0seJnmnPo4avDfhR0E/TZWDoux2arzxYHneH2/Ltmw==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-dNBKGlXagUZhkKcI+HhEH0otOswA5g2QnJV8BxYxNK/piW9jJWZvADCbzDJNRjt6A6QgMwBM8+lH7K3lgsOuQw==" crossorigin="anonymous"></script>
<!--[if IE]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;}</style>
<![endif]-->

View File

@@ -155,7 +155,7 @@ class Helper
public static function getPastePost($version = 2, array $meta = array())
{
$example = self::getPaste($version, $meta);
$example['meta'] = array_merge(array('expire' => $example['meta']['expire']), $meta);
$example['meta'] = array('expire' => $example['meta']['expire']);
return $example;
}

View File

@@ -387,7 +387,7 @@ class ConfigurationTestGenerator
}
}
$code .= $this->_getFunction(
ucfirst($step), $key, $options, $preCode, $testCode
ucfirst($step), $key, $options, $preCode, $testCode, $fullOptions['main']['discussion']
);
}
}
@@ -408,10 +408,11 @@ class ConfigurationTestGenerator
* DO NOT EDIT: This file is generated automatically using configGenerator.php
*/
use PrivateBin\PrivateBin;
use PrivateBin\Controller;
use PrivateBin\Data\Filesystem;
use PrivateBin\Persistence\ServerSalt;
use PrivateBin\Persistence\TrafficLimiter;
use PrivateBin\Request;
class ConfigurationCombinationsTest extends PHPUnit_Framework_TestCase
{
@@ -448,8 +449,8 @@ class ConfigurationCombinationsTest extends PHPUnit_Framework_TestCase
if ($this->_model->exists(Helper::getPasteId()))
$this->_model->delete(Helper::getPasteId());
$configuration['model_options']['dir'] = $this->_path;
$configuration['traffic']['dir'] = $this->_path;
$configuration['purge']['dir'] = $this->_path;
$configuration['traffic']['dir'] = $this->_path;
$configuration['purge']['dir'] = $this->_path;
Helper::createIniFile(CONF, $configuration);
}
@@ -467,7 +468,7 @@ EOT;
* @param array $testCode
* @return string
*/
private function _getFunction($step, $key, &$options, $preCode, $testCode)
private function _getFunction($step, $key, &$options, $preCode, $testCode, $discussionEnabled)
{
if (count($testCode) == 0) {
echo "skipping creation of test$step$key, no valid tests found for configuration: $options" . PHP_EOL;
@@ -495,18 +496,31 @@ EOT;
// step specific initialization
switch ($step) {
case 'Create':
if ($discussionEnabled) {
$code .= PHP_EOL . <<<'EOT'
$paste = Helper::getPasteJson();
EOT;
} else {
$code .= PHP_EOL . <<<'EOT'
$paste = json_decode(Helper::getPasteJson(), true);
$paste['adata'][2] = 0;
$paste = json_encode($paste);
EOT;
}
$code .= PHP_EOL . <<<'EOT'
$_POST = Helper::getPaste();
$file = tempnam(sys_get_temp_dir(), 'FOO');
file_put_contents($file, $paste);
Request::setInputStream($file);
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'POST';
$_SERVER['REMOTE_ADDR'] = '::1';
$_SERVER['REQUEST_METHOD'] = 'POST';
$_SERVER['REMOTE_ADDR'] = '::1';
TrafficLimiter::canPass();
EOT;
break;
case 'Read':
$code .= PHP_EOL . <<<'EOT'
$this->_model->create(Helper::getPasteId(), Helper::getPaste());
$_SERVER['QUERY_STRING'] = Helper::getPasteId();
$_SERVER['QUERY_STRING'] = Helper::getPasteId();
$_GET[Helper::getPasteId()] = '';
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
EOT;
@@ -525,7 +539,7 @@ EOT;
$code .= PHP_EOL . $preString;
$code .= <<<'EOT'
ob_start();
new PrivateBin;
new Controller;
$content = ob_get_contents();
ob_end_clean();
EOT;

View File

@@ -366,30 +366,6 @@ class ControllerTest extends PHPUnit_Framework_TestCase
$this->assertEquals(1, $paste['adata'][2], 'discussion is enabled');
}
/**
* @runInSeparateProcess
*/
public function testCreateInvalidFormat()
{
$options = parse_ini_file(CONF, true);
$options['traffic']['limit'] = 0;
Helper::createIniFile(CONF, $options);
$paste = Helper::getPasteJson(2, array('challenge' => '$'));
$file = tempnam(sys_get_temp_dir(), 'FOO');
file_put_contents($file, $paste);
Request::setInputStream($file);
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
$_SERVER['REQUEST_METHOD'] = 'POST';
$_SERVER['REMOTE_ADDR'] = '::1';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$response = json_decode($content, true);
$this->assertEquals(1, $response['status'], 'outputs error status');
$this->assertFalse($this->_data->exists(Helper::getPasteId()), 'paste exists after posting data');
}
/**
* @runInSeparateProcess
*/
@@ -808,56 +784,6 @@ class ControllerTest extends PHPUnit_Framework_TestCase
$this->assertFalse($this->_data->exists(Helper::getPasteId()), 'paste successfully deleted');
}
/**
* @runInSeparateProcess
*/
public function testReadBurnAfterReadingWithToken()
{
$token = base64_encode(hash_hmac(
'sha256', Helper::getPasteId(), random_bytes(32), true
));
$burnPaste = Helper::getPaste(2, array('challenge' => $token));
$burnPaste['adata'][3] = 1;
$this->_data->create(Helper::getPasteId(), $burnPaste);
$this->assertTrue($this->_data->exists(Helper::getPasteId()), 'paste exists before deleting data');
$_SERVER['QUERY_STRING'] = Helper::getPasteId() . '&token=' . $token;
$_GET[Helper::getPasteId()] = '';
$_GET['token'] = $token;
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$response = json_decode($content, true);
$this->assertEquals(0, $response['status'], 'outputs status');
$this->assertFalse($this->_data->exists(Helper::getPasteId()), 'paste successfully deleted');
}
/**
* @runInSeparateProcess
*/
public function testReadBurnAfterReadingWithIncorrectToken()
{
$token = base64_encode(hash_hmac(
'sha256', Helper::getPasteId(), random_bytes(32), true
));
$burnPaste = Helper::getPaste(2, array('challenge' => base64_encode(random_bytes(32))));
$burnPaste['adata'][3] = 1;
$this->_data->create(Helper::getPasteId(), $burnPaste);
$this->assertTrue($this->_data->exists(Helper::getPasteId()), 'paste exists before deleting data');
$_SERVER['QUERY_STRING'] = Helper::getPasteId() . '&token=' . $token;
$_GET[Helper::getPasteId()] = '';
$_GET['token'] = $token;
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
ob_start();
new Controller;
$content = ob_get_contents();
ob_end_clean();
$response = json_decode($content, true);
$this->assertEquals(1, $response['status'], 'outputs status');
$this->assertTrue($this->_data->exists(Helper::getPasteId()), 'paste not deleted');
}
/**
* @runInSeparateProcess
*/

View File

@@ -21,10 +21,6 @@ class FormatV2Test extends PHPUnit_Framework_TestCase
$paste['ct'] = '$';
$this->assertFalse(FormatV2::isValid($paste), 'invalid base64 encoding of ct');
$paste = Helper::getPastePost();
$paste['meta']['challenge'] = '$';
$this->assertFalse(FormatV2::isValid($paste), 'invalid base64 encoding of ct');
$paste = Helper::getPastePost();
$paste['ct'] = 'bm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhCg==';
$this->assertFalse(FormatV2::isValid($paste), 'low ct entropy');
@@ -71,8 +67,6 @@ class FormatV2Test extends PHPUnit_Framework_TestCase
$paste['adata'][0][7] = '!#@';
$this->assertFalse(FormatV2::isValid($paste), 'invalid compression');
$paste = Helper::getPastePost();
unset($paste['meta']['expire']);
$this->assertFalse(FormatV2::isValid($paste), 'invalid missing meta key');
$this->assertFalse(FormatV2::isValid(Helper::getPaste()), 'invalid meta key');
}
}

View File

@@ -268,48 +268,10 @@ class ModelTest extends PHPUnit_Framework_TestCase
$paste->setData($pasteData);
$paste->store();
$paste = $this->_model->getPaste(Helper::getPasteId())->get();
$paste = $paste->get();
$this->assertEquals((float) 300, (float) $paste['meta']['time_to_live'], 'remaining time is set correctly', 1.0);
}
public function testToken()
{
$pasteData = Helper::getPastePost();
$pasteData['meta']['challenge'] = base64_encode(random_bytes(32));
$token = base64_encode(hash_hmac(
'sha256', Helper::getPasteId(), base64_decode($pasteData['meta']['challenge']), true
));
$this->_model->getPaste(Helper::getPasteId())->delete();
$paste = $this->_model->getPaste(Helper::getPasteId());
$this->assertFalse($paste->exists(), 'paste does not yet exist');
$paste = $this->_model->getPaste();
$paste->setData($pasteData);
$paste->store();
$paste = $this->_model->getPaste(Helper::getPasteId());
$this->assertTrue(
$paste->isTokenCorrect($token),
'token is accepted after store and retrieval'
);
}
public function testDeleteToken()
{
$pasteData = Helper::getPastePost();
$this->_model->getPaste(Helper::getPasteId())->delete();
$paste = $this->_model->getPaste(Helper::getPasteId());
$this->assertFalse($paste->exists(), 'paste does not yet exist');
$paste = $this->_model->getPaste();
$paste->setData($pasteData);
$paste->store();
$deletetoken = $paste->getDeleteToken();
$paste = $this->_model->getPaste(Helper::getPasteId());
$this->assertTrue($paste->isDeleteTokenCorrect($deletetoken), 'delete token is accepted after store and retrieval');
}
/**
* @expectedException Exception
* @expectedExceptionCode 64
@@ -325,20 +287,6 @@ class ModelTest extends PHPUnit_Framework_TestCase
$paste->getComment(Helper::getPasteId())->delete();
}
/**
* @expectedException Exception
* @expectedExceptionCode 75
*/
public function testInvalidFormat()
{
$pasteData = Helper::getPastePost();
$pasteData['adata'][1] = 'foo';
$this->_model->getPaste(Helper::getPasteId())->delete();
$paste = $this->_model->getPaste();
$paste->setData($pasteData);
}
public function testPurge()
{
$conf = new Configuration;

View File

@@ -130,22 +130,6 @@ class RequestTest extends PHPUnit_Framework_TestCase
$this->assertEquals('read', $request->getOperation());
}
public function testApiReadWithToken()
{
$this->reset();
$id = $this->getRandomId();
$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['HTTP_ACCEPT'] = 'application/json, text/javascript, */*; q=0.01';
$_SERVER['QUERY_STRING'] = $id . '&token=foo';
$_GET[$id] = '';
$_GET['token'] = 'foo';
$request = new Request;
$this->assertTrue($request->isJsonApiCall(), 'is JSON Api call');
$this->assertEquals($id, $request->getParam('pasteid'));
$this->assertEquals('foo', $request->getParam('token'));
$this->assertEquals('read', $request->getOperation());
}
public function testApiDelete()
{
$this->reset();