Compare commits

..

52 Commits
1.7.3 ... 1.7.4

Author SHA1 Message Date
El RIDO
031bcef317 incrementing version 2024-07-09 20:36:26 +02:00
El RIDO
0c4e810e67 Merge branch 'shorten-non-self-url' 2024-07-09 20:33:54 +02:00
El RIDO
8712ed6a5d Merge pull request #1357 from PrivateBin/b5-textarea-height
bootstrap5 textarea height relative to viewport height
2024-07-09 20:28:17 +02:00
El RIDO
3cba170f32 re-order stubs to the end of the file for easier maintenance 2024-07-07 15:10:17 +02:00
El RIDO
d097631469 possibly not necessary? 2024-07-07 14:28:29 +02:00
El RIDO
84d4d31c73 composer is not part of the matrix, don't try and process event.json 2024-07-07 14:22:48 +02:00
El RIDO
17f924118e address warnings and errors in github actions 2024-07-07 14:13:59 +02:00
El RIDO
f662640554 Merge pull request #1366 from PrivateBin/crowdin-translation
New Crowdin updates
2024-06-30 19:46:57 +02:00
PrivateBin Translator Bot
4fe51b5578 New translations en.json (Ukrainian) 2024-06-30 13:22:12 +02:00
El RIDO
8e6e31db5c fix test, basepath needs to be set 2024-06-30 07:45:06 +02:00
El RIDO
2c711e9d3c prevent bypassing YOURLS proxy URL filter, allowing to shorten non-self URLs 2024-06-29 20:28:18 +02:00
El RIDO
0eae149474 Merge pull request #1360 from PrivateBin/crowdin-translation
New Crowdin updates
2024-06-22 06:51:27 +02:00
PrivateBin Translator Bot
5461f279d7 New translations en.json (Corsican) 2024-06-21 16:11:15 +02:00
El RIDO
3abbd107ca Merge pull request #1356 from PrivateBin/b5-darkmode-toggle-state-init
bootstrap5 dark mode toggle unset on dark browser preference
2024-06-15 08:42:05 +02:00
El RIDO
eb42915991 bootstrap5 textarea height relative to viewport height, fixes #1349 2024-06-13 20:22:40 +02:00
El RIDO
ab05ed9532 bootstrap5 dark mode toggle unset on dark browser preference, fixes #1340 2024-06-13 20:00:26 +02:00
El RIDO
e4902e1bf1 Merge pull request #1355 from PrivateBin/dependabot/github_actions/dawidd6/action-download-artifact-6
Bump dawidd6/action-download-artifact from 5 to 6
2024-06-13 07:49:28 +02:00
dependabot[bot]
4d912b082b Bump dawidd6/action-download-artifact from 5 to 6
Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 5 to 6.
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](deb3bb8325...bf251b5aa9)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-12 11:12:15 +00:00
El RIDO
d190507fbe Merge pull request #1350 from PrivateBin/strict_types
enable strict types
2024-06-08 18:36:17 +02:00
El RIDO
3c6bf26dc8 Merge pull request #1353 from PrivateBin/crowdin-translation
New Crowdin updates
2024-06-06 06:10:06 +02:00
PrivateBin Translator Bot
036563d320 New translations en.json (Norwegian) 2024-06-06 06:08:07 +02:00
El RIDO
51eec9a776 Merge pull request #1352 from PrivateBin/dependabot/github_actions/dawidd6/action-download-artifact-5
Bump dawidd6/action-download-artifact from 3.1.4 to 5
2024-06-06 06:03:25 +02:00
dependabot[bot]
48b4c6ce5b Bump dawidd6/action-download-artifact from 3.1.4 to 5
Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 3.1.4 to 5.
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](09f2f74827...deb3bb8325)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-04 11:09:50 +00:00
El RIDO
662d0e1430 document change 2024-06-04 07:32:13 +02:00
El RIDO
68ccaaace0 address unit test failures due to strict typing 2024-06-04 07:27:45 +02:00
El RIDO
cebc9acce6 enable strict types in PHP 2024-06-04 07:13:55 +02:00
El RIDO
b9d24b74b3 Merge branch 'version-sed' 2024-05-30 18:52:18 +02:00
El RIDO
b32efe0187 disable snyk scan on forks, they won't have the necessary secret 2024-05-30 07:54:19 +02:00
El RIDO
6aa292e33d document changes 2024-05-30 07:31:13 +02:00
El RIDO
4875bedac7 Merge pull request #1346 from 9401adarsh/password-input-bug-fix
fix: reset password input field on creation of new paste
2024-05-29 22:12:56 +02:00
9401adarsh
750a0adce4 chore: update sri hashes to reflect changes in js/ 2024-05-29 16:21:08 +05:30
9401adarsh
372fb58d20 fix: password input not resetting bug, add resetPasswordInput() method 2024-05-29 16:20:28 +05:30
El RIDO
4c347ea08e Merge pull request #1345 from PrivateBin/crowdin-translation
New Crowdin updates
2024-05-29 07:49:55 +02:00
PrivateBin Translator Bot
9f5de7284e New translations en.json (French) 2024-05-28 22:11:41 +02:00
El RIDO
05402ef304 remove version from doc blocs
- @version in file header level isn't used on code docs, it is intended
  for API versions at class or method level
- avoids needing to update all these files on version increment
- avoids needing to regenerate SRI hashes for privatebin.js through
  extra phpunit run
- simplifies VERSION_FILES list
- avoids having to filter above list during loop
- adds a few missing doc bloc headers
2024-05-28 21:03:22 +02:00
El RIDO
f313578892 Merge pull request #1343 from PrivateBin/db-version-upgrade
refactor database schema upgrade to support skipping versions
2024-05-26 08:40:29 +02:00
El RIDO
99a3e087ed refactor database schema upgrade to support skipping versions 2024-05-25 09:40:41 +02:00
El RIDO
b96c8ae531 revert version increment in database upgrade 2024-05-25 09:14:24 +02:00
El RIDO
1264418102 Merge branch '9401adarsh-file-download-md-format-support-feature' 2024-05-21 07:14:54 +02:00
El RIDO
c04c7b0f34 update SRI hashes, npm lock file 2024-05-21 07:14:12 +02:00
El RIDO
a240dbc616 Merge pull request #1341 from FingerlessGlov3s/patch-1
Fix bootstrap5 template width
2024-05-21 06:46:11 +02:00
FingerlessGloves
4913837d37 Fix bootstrap5 template width 2024-05-20 20:28:13 +01:00
Adarsh Ashokan
7c7b5abad3 fix: downloadText() method to accommodate .md file format 2024-05-21 00:51:41 +05:30
El RIDO
a0e42aae9e Merge pull request #1333 from PrivateBin/crowdin-translation
New Crowdin updates
2024-05-18 21:56:57 +02:00
El RIDO
f9f8f18781 helper interacts with rawText call 2024-05-18 21:55:14 +02:00
El RIDO
5e5b394291 fix rawText test and split parts into hideAllButtons test 2024-05-18 20:02:54 +02:00
El RIDO
39a359c23f Merge pull request #1338 from ankiiisharma/ankit#1336
Added test case to verify rawText
2024-05-18 08:39:13 +02:00
Ankiiisharma
bae6e6ff25 Added test case to verify rawText
Added test case to verify rawText manipulates button visibility correctly
2024-05-18 00:09:23 +05:30
El RIDO
2324e83b84 Merge pull request #1331 from PrivateBin/dependabot/github_actions/dawidd6/action-download-artifact-3.1.4
Bump dawidd6/action-download-artifact from 3.0.0 to 3.1.4
2024-05-14 05:43:30 +02:00
PrivateBin Translator Bot
451f4af484 New translations en.json (Romanian) 2024-05-13 22:01:08 +02:00
El RIDO
d961a892f2 chore: prepare for next release 2024-05-13 19:33:43 +02:00
dependabot[bot]
2aeec14a52 Bump dawidd6/action-download-artifact from 3.0.0 to 3.1.4
Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 3.0.0 to 3.1.4.
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](e7466d1a75...09f2f74827)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-13 12:00:22 +00:00
76 changed files with 742 additions and 649 deletions

View File

@@ -12,6 +12,7 @@ jobs:
# https://github.com/snyk/actions/tree/master/php
snyk-php:
runs-on: ubuntu-latest
if: ${{ github.repository == 'PrivateBin/PrivateBin' }}
steps:
- uses: actions/checkout@v4
- name: Install Google Cloud Storage

View File

@@ -24,7 +24,7 @@ jobs:
steps:
- name: Download and Extract Artifacts
uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d
uses: dawidd6/action-download-artifact@bf251b5aa9c2f7eeb574a96ee720e24f801b7c11
with:
run_id: ${{ github.event.workflow_run.id }}
path: artifacts
@@ -32,11 +32,7 @@ jobs:
- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
with:
check_name: "Test Results (${{ github.event.workflow_run.event || github.event_name }})"
commit: ${{ github.event.workflow_run.head_sha }}
event_file: artifacts/Event File/event.json
event_name: ${{ github.event.workflow_run.event }}
files: |
artifacts/**/*.xml
artifacts/**/*.trx
artifacts/**/*.json
files: "artifacts/**/*.xml"

View File

@@ -7,9 +7,6 @@ jobs:
Composer:
runs-on: ubuntu-latest
# https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#handling-failures
continue-on-error: ${{ matrix.experimental }}
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -21,7 +18,8 @@ jobs:
PHPunit:
name: PHP ${{ matrix.php-versions }} unit tests on ${{ matrix.operating-system }}
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.experimental }}
# https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#handling-failures
continue-on-error: "${{ matrix.experimental }}"
strategy:
matrix:
php-versions: ['7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
@@ -86,9 +84,9 @@ jobs:
- name: Cache dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ steps.get-date.outputs.date }}-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-${{ steps.get-date.outputs.date }}-
path: "${{ steps.composer-cache.outputs.dir }}"
key: "${{ runner.os }}-composer-${{ steps.get-date.outputs.date }}-${{ hashFiles('**/composer.json') }}"
restore-keys: "${{ runner.os }}-composer-${{ steps.get-date.outputs.date }}-"
# composer installation
- name: Unset platform requirement
@@ -136,14 +134,14 @@ jobs:
- name: Run unit tests
run: npm run ci-test
working-directory: js
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v4
with:
name: Test Results (Mocha)
path: js/mocha-results.xml
event_file:
name: "Event File"
runs-on: ubuntu-latest
@@ -152,5 +150,4 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: Event File
path: ${{ github.event_path }}
path: "${{ github.event_path }}"

1
.gitignore vendored
View File

@@ -28,6 +28,7 @@ vendor/**/build_phar.php
# Ignore local node modules, unit testing logs, api docs and IDE project files
js/node_modules/
js/mocha-results.xml
js/test.log
tst/log/
tst/ConfigurationCombinationsTest.php

View File

@@ -1,5 +1,14 @@
# PrivateBin version history
## 1.7.4 (2024-07-09)
* CHANGED: Saving markdown pastes uses `.md` extension instead of `.txt` (#1293)
* CHANGED: Enable strict type checking in PHP (#1350)
* CHANGED: Various tweaks of the `bootstrap5` template, suggested by the community
* FIXED: Reset password input field on creation of new paste (#1194)
* FIXED: Allow database schema upgrade to skip versions (#1343)
* FIXED: `bootstrap5` dark mode toggle unset on dark browser preference (#1340)
* FIXED: Prevent bypassing YOURLS proxy URL filter, allowing to shorten non-self URLs
## 1.7.3 (2024-05-13)
* CHANGED: Various tweaks of the `bootstrap5` template, suggested by the community
* CHANGED: Upgrading libraries to: DOMpurify 3.1.3

View File

@@ -1,8 +1,8 @@
.PHONY: all coverage coverage-js coverage-php doc doc-js doc-php increment sign test test-js test-php help
CURRENT_VERSION = 1.7.3
CURRENT_VERSION = 1.7.4
VERSION ?= 1.7.4
VERSION_FILES = index.php bin/ cfg/ *.md doc/Installation.md css/ i18n/ img/ js/package.json js/privatebin.js lib/ Makefile tpl/ tst/
VERSION_FILES = README.md SECURITY.md doc/Installation.md js/package*.json lib/Controller.php Makefile
REGEX_CURRENT_VERSION := $(shell echo $(CURRENT_VERSION) | sed "s/\./\\\./g")
REGEX_VERSION := $(shell echo $(VERSION) | sed "s/\./\\\./g")
@@ -29,12 +29,11 @@ doc-php: ## Generate JS code documentation.
phpdoc --visibility=public,protected,private --target=doc/phpdoc --directory=lib/
increment: ## Increment and commit new version number, set target version using `make increment VERSION=1.2.3`.
for F in `grep -l -R $(REGEX_CURRENT_VERSION) $(VERSION_FILES) | grep -v -e tst/log/ -e ":0" -e CHANGELOG.md`; \
for F in `grep -l -R $(REGEX_CURRENT_VERSION) $(VERSION_FILES)`; \
do \
sed -i "s/$(REGEX_CURRENT_VERSION)/$(REGEX_VERSION)/g" $$F; \
done
cd tst && phpunit --no-coverage && cd ..
git add $(VERSION_FILES) tpl/
git add $(VERSION_FILES)
git commit -m "incrementing version"
sign: ## Sign a release.

View File

@@ -1,6 +1,6 @@
# [![PrivateBin](https://cdn.rawgit.com/PrivateBin/assets/master/images/preview/logoSmall.png)](https://privatebin.info/)
*Current version: 1.7.3*
*Current version: 1.7.4*
**PrivateBin** is a minimalist, open source online
[pastebin](https://en.wikipedia.org/wiki/Pastebin)

View File

@@ -4,8 +4,8 @@
| Version | Supported |
| ------- | ------------------ |
| 1.7.3 | :heavy_check_mark: |
| < 1.7.3 | :x: |
| 1.7.4 | :heavy_check_mark: |
| < 1.7.4 | :x: |
## Reporting a Vulnerability

View File

@@ -1,6 +1,5 @@
#!/usr/bin/env php
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -9,7 +8,6 @@
* @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.7.3
*/
namespace PrivateBin;

View File

@@ -1,6 +1,14 @@
#!/usr/bin/env php
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
* a zero-knowledge paste bin
*
* @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
*
* generates a config unit test class
*
* This generator is meant to test all possible configuration combinations
@@ -405,7 +413,7 @@ class ConfigurationTestGenerator
private function _getHeader()
{
return <<<'EOT'
<?php
<?php declare(strict_types=1);
/**
* DO NOT EDIT: This file is generated automatically using configGenerator.php
*/

View File

@@ -1,9 +1,17 @@
#!/usr/bin/env php
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
* a zero-knowledge paste bin
*
* @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
*/
define('ITERATIONS', 100000);
require dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
use Identicon\Generator\GdGenerator;
use Identicon\Generator\ImageMagickGenerator;
@@ -12,8 +20,6 @@ use Identicon\Identicon;
use Jdenticon\Identicon as Jdenticon;
use PrivateBin\Vizhash16x16;
$vizhash = new Vizhash16x16();
$identiconGenerators = array(
'identicon GD' => new Identicon(new GdGenerator()),

View File

@@ -1,7 +1,16 @@
#!/usr/bin/env php
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
* a zero-knowledge paste bin
*
* @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
*/
// change this, if your php files and data is outside of your webservers document root
// change this, if your php files and data are outside of your webservers document root
define('PATH', dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR);
define('PUBLIC_PATH', __DIR__ . DIRECTORY_SEPARATOR);

View File

@@ -6,7 +6,6 @@
* @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.7.3
*/
@import url("../common.css");

View File

@@ -6,7 +6,6 @@
* @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.7.3
*/
@import url("../common.css");
@@ -37,6 +36,10 @@
margin-bottom: 10px;
}
#message {
height: 70vh;
}
#message, .replymessage {
font-family: monospace;
resize: vertical;

View File

@@ -6,7 +6,6 @@
* @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.7.3
*/
#attachmentPreview img {

View File

@@ -6,7 +6,6 @@
* @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.7.3
*/
.noscript-hide {

View File

@@ -6,7 +6,6 @@
* @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.7.3
*/
@import url("common.css");

View File

@@ -201,7 +201,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.7.3');
INSERT INTO prefix_config VALUES('VERSION', '1.7.4');
```
In **PostgreSQL**, the `data`, `attachment`, `nickname` and `vizhash` columns

View File

@@ -31,9 +31,9 @@
"Raw text": "Testu grossu",
"Expires": "Scadenza",
"Burn after reading": "Squassà dopu a lettura",
"Open discussion": "Apre una chjachjarata",
"Open discussion": "Apre una chjachjerata",
"Password (recommended)": "Parolla dintesa (ricumandata)",
"Discussion": "Chjachjarata",
"Discussion": "Chjachjerata",
"Toggle navigation": "Invertisce a navigazione",
"%d seconds": [
"%d seconda",
@@ -213,7 +213,7 @@
"Save paste": "Arregistrà lappiccicu",
"Your IP is not authorized to create pastes.": "U vostru indirizzu IP ùn hè micca auturizatu à creà lappiccichi.",
"Trying to shorten a URL that isn't pointing at our instance.": "Pruvate dammuzzà un indirizzu web chì ùn punta micca versu a vostra instanza.",
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Sbagliu à a chjama di YOURLS. Seria forse una cunfigurazione gattiva, tale una \"apiurl\" o \"signature\" falsa o assente.",
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Sbagliu à a chjama di YOURLS. Seria forse una cunfigurazione gattiva, tale una « apiurl » o « signature » falsa o assente.",
"Error parsing YOURLS response.": "Sbagliu durante lanalisa di a risposta di YOURLS.",
"This secret message can only be displayed once. Would you like to see it now?": "Stu messaghju secretu pò esse affissatu solu una volta. Vulete fighjallu subitu ?",
"Yes, see it": "Iè, fighjallu",

View File

@@ -212,12 +212,12 @@
"URL shortener may expose your decrypt key in URL.": "Raccourcir l'URL peut exposer votre clé de déchiffrement dans l'URL.",
"Save paste": "Sauver le paste",
"Your IP is not authorized to create pastes.": "Votre adresse IP n'est pas autorisée à créer des pastes.",
"Trying to shorten a URL that isn't pointing at our instance.": "Essayer de raccourcir une URL qui ne pointe pas vers notre instance.",
"Trying to shorten a URL that isn't pointing at our instance.": "Tentative de raccourcir une URL qui ne pointe pas vers notre instance.",
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Erreur lors de l'appel de YOURLS. Peut-être un problème de configuration, comme \"apiurl\" ou \"signature\" manquant.",
"Error parsing YOURLS response.": "Erreur d'analyse de la réponse YOURLS.",
"This secret message can only be displayed once. Would you like to see it now?": "Les pastes de type \"Effacer après la lecture\" ne peuvent être affichés qu'une seule fois. Voulez-vous le voir maintenant ?",
"Yes, see it": "Oui, voyez le",
"Yes, see it": "Oui, le voir",
"Dark Mode": "Mode Sombre",
"Error compressing paste, due to missing WebAssembly support.": "Erreur lors de la compression du paste, en raison du support de WebAssembly manquant.",
"Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Erreur lors de la décompression du paste, votre navigateur ne supporte pas WebAssembly. Veuillez utiliser un autre navigateur pour voir ce collage."
"Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Erreur lors de la décompression du paste, votre navigateur ne supporte pas WebAssembly. Veuillez utiliser un autre navigateur pour voir ce paste."
}

View File

@@ -215,7 +215,7 @@
"Trying to shorten a URL that isn't pointing at our instance.": "Prøver å forkorte en URL som ikke peker i vår instans.",
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Feil ved å ringe YOURLS. Sannsynligvis et konfigurasjonsproblem, som feil eller mangler, \"apiurl\" eller \"signatur\".",
"Error parsing YOURLS response.": "Feil ved analyse av YOURLS svar.",
"This secret message can only be displayed once. Would you like to see it now?": "Brenne etter lesing av pasta kan kun vises når den lastes inn. Vil du se den nå?",
"This secret message can only be displayed once. Would you like to see it now?": "Denne hemmelige meldingen kan bare vises én gang. Vil du se den nå?",
"Yes, see it": "Ja, se det",
"Dark Mode": "Mørk modus",
"Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.",

View File

@@ -26,7 +26,7 @@
"JavaScript is required for %s to work. Sorry for the inconvenience.": "JavaScript este necesar pentru ca %s să funcționeze. Ne cerem scuze pentru neplăceri.",
"%s requires a modern browser to work.": "%s necesită un browser modern pentru a funcționa.",
"New": "Nou",
"Create": "Creează",
"Create": "Creați",
"Clone": "Clonați",
"Raw text": "Text brut",
"Expires": "Expiră",
@@ -215,9 +215,9 @@
"Trying to shorten a URL that isn't pointing at our instance.": "Încercarea de a scurta un URL care nu direcționează spre instanța noastră.",
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Eroare la apelarea YOURLS. Probabil o problemă de configurare, cum ar fi \"apiurl\" sau \"signature\" greșite sau lipsă.",
"Error parsing YOURLS response.": "Eroare la analizarea răspunsului YOURLS.",
"This secret message can only be displayed once. Would you like to see it now?": "Paste-urile care se șterg după citire pot fi afișate numai o dată după încărcare. Doriți să o vedeți acum?",
"This secret message can only be displayed once. Would you like to see it now?": "Acest mesaj secret poate fi afișat o singură dată. Doriți să îl vedeți acum?",
"Yes, see it": "Da, vezi",
"Dark Mode": "Mod Întunecat",
"Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.",
"Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste."
"Dark Mode": "Mod întunecat",
"Error compressing paste, due to missing WebAssembly support.": "Eroare la compresia paste-ului din cauza incompatibilității cu WebAssembly.",
"Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Eroare la deschiderea paste-ului, browserul dvs. nu acceptă WebAssembly. Vă rugăm să utilizați un alt browser pentru a vedea acest paste."
}

View File

@@ -218,6 +218,6 @@
"This secret message can only be displayed once. Would you like to see it now?": "Спалити після вставки читання можна вивести лише один раз під час завантаження. Відкрити його зараз?",
"Yes, see it": "Так, завантажити",
"Dark Mode": "Темний режим",
"Error compressing paste, due to missing WebAssembly support.": "Error compressing paste, due to missing WebAssembly support.",
"Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste."
"Error compressing paste, due to missing WebAssembly support.": "Помилка при стисканні допису, через відсутність підтримки WebAssembly сервера.",
"Error decompressing paste, your browser does not support WebAssembly. Please use another browser to view this paste.": "Помилка при розпакуванні допису, бо ваш браузер не підтримує WebAssembly. Будь ласка, відкрийте інший браузер для перегляду цього допису."
}

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
// change this, if your php files and data is outside of your webservers document root

View File

@@ -68,9 +68,10 @@
} else {
delStoredPrettifyTheme()
}
setTheme(getStoredPreferredTheme())
const toggle = document.querySelector('#bd-theme')
toggle.checked = getStoredTheme() === 'dark'
const theme = getStoredPreferredTheme()
setTheme(theme)
toggle.checked = (theme === 'dark')
toggle.addEventListener('change', (event) => {
const theme = event.currentTarget.checked ? 'dark' : 'light'
setStoredTheme(theme)

4
js/package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "privatebin",
"version": "1.6.2",
"version": "1.7.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "privatebin",
"version": "1.6.2",
"version": "1.7.4",
"license": "zlib-acknowledgement",
"devDependencies": {
"@peculiar/webcrypto": "^1.1.1",

View File

@@ -1,6 +1,6 @@
{
"name": "privatebin",
"version": "1.7.3",
"version": "1.7.4",
"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": {
@@ -16,7 +16,7 @@
},
"scripts": {
"test": "mocha",
"ci-test": "mocha --reporter-option output=mocha-results.xml"
"ci-test": "mocha --reporter xunit --reporter-option output=mocha-results.xml"
},
"repository": {
"type": "git",

View File

@@ -6,7 +6,6 @@
* @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.7.3
* @name PrivateBin
* @namespace
*/
@@ -3767,6 +3766,18 @@ jQuery.PrivateBin = (function($, RawDeflate) {
}
}
/**
* Clear the password input in the top navigation
*
* @name TopNav.clearPasswordInput
* @function
*/
function clearPasswordInput()
{
$passwordInput.val('');
}
/**
* Clear the attachment input in the top navigation.
@@ -3831,7 +3842,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
*/
function downloadText()
{
var filename='paste-' + Model.getPasteId() + '.txt';
var fileFormat = PasteViewer.getFormat() === 'markdown' ? '.md' : '.txt';
var filename='paste-' + Model.getPasteId() + fileFormat;
var text = PasteViewer.getText();
var element = document.createElement('a');
@@ -4348,6 +4360,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
me.resetInput = function()
{
clearAttachmentInput();
clearPasswordInput();
$burnAfterReading.prop('checked', burnAfterReadingDefault);
$openDiscussion.prop('checked', openDiscussionDefault);
if (openDiscussionDefault || !burnAfterReadingDefault) $openDiscussionOption.removeClass('buttondisabled');

View File

@@ -612,7 +612,6 @@ describe('TopNav', function () {
);
});
describe('getPassword', function () {
before(function () {
cleanup();
@@ -681,4 +680,67 @@ describe('TopNav', function () {
}
);
});
describe('hideAllButtons', function () {
before(function () {
cleanup();
});
it(
'hides all buttons correctly',
function () {
// Insert any setup code needed for the hideAllButtons function
// Example: Initialize the DOM elements required for testing
$('body').html(
'<nav class="navbar navbar-inverse navbar-static-top">' +
'<div id="navbar" class="navbar-collapse collapse"><ul ' +
'class="nav navbar-nav"><li><button id="newbutton" ' +
'type="button" class="hidden btn btn-warning navbar-btn">' +
'<span class="glyphicon glyphicon-file" aria-hidden="true">' +
'</span> New</button><button id="clonebutton" type="button"' +
' class="hidden btn btn-warning navbar-btn">' +
'<span class="glyphicon glyphicon-duplicate" ' +
'aria-hidden="true"></span> Clone</button><button ' +
'id="rawtextbutton" type="button" class="hidden btn ' +
'btn-warning navbar-btn"><span class="glyphicon ' +
'glyphicon-text-background" aria-hidden="true"></span> ' +
'Raw text</button><button id="qrcodelink" type="button" ' +
'data-toggle="modal" data-target="#qrcodemodal" ' +
'class="hidden btn btn-warning navbar-btn"><span ' +
'class="glyphicon glyphicon-qrcode" aria-hidden="true">' +
'</span> QR code</button></li></ul></div></nav>'
);
$.PrivateBin.TopNav.init();
$.PrivateBin.TopNav.hideAllButtons();
assert.ok($('#newbutton').hasClass('hidden'));
assert.ok($('#clonebutton').hasClass('hidden'));
assert.ok($('#rawtextbutton').hasClass('hidden'));
assert.ok($('#qrcodelink').hasClass('hidden'));
cleanup();
}
);
});
describe('rawText', function () {
before(function () {
cleanup();
});
it(
'displays raw text view correctly',
function () {
const clean = jsdom('', {url: 'https://privatebin.net/?0123456789abcdef#0'});
global.URL = require('jsdom-url').URL;
$('body').html('<button id="rawtextbutton"></button>');
const sample = 'example';
$.PrivateBin.PasteViewer.setText(sample);
$.PrivateBin.Helper.reset();
$.PrivateBin.TopNav.init();
$('#rawtextbutton').click();
assert.equal($('pre').text(), sample);
clean();
}
);
});
});

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin;
@@ -28,7 +27,7 @@ class Controller
*
* @const string
*/
const VERSION = '1.7.3';
const VERSION = '1.7.4';
/**
* minimal required PHP version

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin\Data;
@@ -182,7 +181,7 @@ abstract class AbstractData
protected function getOpenSlot(array &$comments, $postdate)
{
if (array_key_exists($postdate, $comments)) {
$parts = explode('.', $postdate, 2);
$parts = explode('.', (string) $postdate, 2);
if (!array_key_exists(1, $parts)) {
$parts[1] = 0;
}

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin\Data;
@@ -853,90 +852,87 @@ class Database extends AbstractData
{
$dataType = $this->_getDataType();
$attachmentType = $this->_getAttachmentType();
switch ($oldversion) {
case '0.21':
// create the meta column if necessary (pre 0.21 change)
try {
$this->_db->exec(
'SELECT "meta" FROM "' . $this->_sanitizeIdentifier('paste') . '" ' .
($this->_type === 'oci' ? 'FETCH NEXT 1 ROWS ONLY' : 'LIMIT 1')
);
} catch (PDOException $e) {
$this->_db->exec('ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . '" ADD COLUMN "meta" TEXT');
}
// SQLite only allows one ALTER statement at a time...
if (version_compare($oldversion, '0.21', '<=')) {
// create the meta column if necessary (pre 0.21 change)
try {
$this->_db->exec(
'SELECT "meta" FROM "' . $this->_sanitizeIdentifier('paste') . '" ' .
($this->_type === 'oci' ? 'FETCH NEXT 1 ROWS ONLY' : 'LIMIT 1')
);
} catch (PDOException $e) {
$this->_db->exec('ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . '" ADD COLUMN "meta" TEXT');
}
// SQLite only allows one ALTER statement at a time...
$this->_db->exec(
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') .
"\" ADD COLUMN \"attachment\" $attachmentType"
);
$this->_db->exec(
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . "\" ADD COLUMN \"attachmentname\" $dataType"
);
// SQLite doesn't support MODIFY, but it allows TEXT of similar
// size as BLOB, so there is no need to change it there
if ($this->_type !== 'sqlite') {
$this->_db->exec(
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') .
"\" ADD COLUMN \"attachment\" $attachmentType"
"\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType"
);
$this->_db->exec(
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') . "\" ADD COLUMN \"attachmentname\" $dataType"
'ALTER TABLE "' . $this->_sanitizeIdentifier('comment') .
"\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType, " .
"MODIFY COLUMN \"nickname\" $dataType, MODIFY COLUMN \"vizhash\" $dataType"
);
// SQLite doesn't support MODIFY, but it allows TEXT of similar
// size as BLOB, so there is no need to change it there
if ($this->_type !== 'sqlite') {
$this->_db->exec(
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') .
"\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType"
);
$this->_db->exec(
'ALTER TABLE "' . $this->_sanitizeIdentifier('comment') .
"\" ADD PRIMARY KEY (\"dataid\"), MODIFY COLUMN \"data\" $dataType, " .
"MODIFY COLUMN \"nickname\" $dataType, MODIFY COLUMN \"vizhash\" $dataType"
);
} else {
$this->_db->exec(
'CREATE UNIQUE INDEX IF NOT EXISTS "' .
$this->_sanitizeIdentifier('paste_dataid') . '" ON "' .
$this->_sanitizeIdentifier('paste') . '" ("dataid")'
);
$this->_db->exec(
'CREATE UNIQUE INDEX IF NOT EXISTS "' .
$this->_sanitizeIdentifier('comment_dataid') . '" ON "' .
$this->_sanitizeIdentifier('comment') . '" ("dataid")'
);
}
// CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0
} else {
$this->_db->exec(
'CREATE INDEX "' .
$this->_sanitizeIdentifier('comment_parent') . '" ON "' .
$this->_sanitizeIdentifier('comment') . '" ("pasteid")'
'CREATE UNIQUE INDEX IF NOT EXISTS "' .
$this->_sanitizeIdentifier('paste_dataid') . '" ON "' .
$this->_sanitizeIdentifier('paste') . '" ("dataid")'
);
// no break, continue with updates for 0.22 and later
case '1.3':
// SQLite doesn't support MODIFY, but it allows TEXT of similar
// size as BLOB and PostgreSQL uses TEXT, so there is no need
// to change it there
if ($this->_type !== 'sqlite' && $this->_type !== 'pgsql') {
$this->_db->exec(
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') .
"\" MODIFY COLUMN \"data\" $attachmentType"
);
}
// no break, continue with updates for all newer versions
case '1.7.3':
$supportsDropColumn = true;
if ($this->_type === 'sqlite') {
try {
$row = $this->_select('SELECT sqlite_version() AS "v"', array(), true);
$supportsDropColumn = version_compare($row['v'], '3.35.0', '>=');
} catch (PDOException $e) {
$supportsDropColumn = false;
}
}
if ($supportsDropColumn) {
$this->_db->exec(
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') .
'" DROP COLUMN "postdate"'
);
}
// no break, continue with updates for all newer versions
default:
$this->_exec(
'UPDATE "' . $this->_sanitizeIdentifier('config') .
'" SET "value" = ? WHERE "id" = ?',
array(Controller::VERSION, 'VERSION')
$this->_db->exec(
'CREATE UNIQUE INDEX IF NOT EXISTS "' .
$this->_sanitizeIdentifier('comment_dataid') . '" ON "' .
$this->_sanitizeIdentifier('comment') . '" ("dataid")'
);
}
// CREATE INDEX IF NOT EXISTS not supported as of Oracle MySQL <= 8.0
$this->_db->exec(
'CREATE INDEX "' .
$this->_sanitizeIdentifier('comment_parent') . '" ON "' .
$this->_sanitizeIdentifier('comment') . '" ("pasteid")'
);
}
if (version_compare($oldversion, '1.3', '<=')) {
// SQLite doesn't support MODIFY, but it allows TEXT of similar
// size as BLOB and PostgreSQL uses TEXT, so there is no need
// to change it there
if ($this->_type !== 'sqlite' && $this->_type !== 'pgsql') {
$this->_db->exec(
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') .
"\" MODIFY COLUMN \"data\" $attachmentType"
);
}
}
if (version_compare($oldversion, '1.7.1', '<=')) {
$supportsDropColumn = true;
if ($this->_type === 'sqlite') {
try {
$row = $this->_select('SELECT sqlite_version() AS "v"', array(), true);
$supportsDropColumn = version_compare($row['v'], '3.35.0', '>=');
} catch (PDOException $e) {
$supportsDropColumn = false;
}
}
if ($supportsDropColumn) {
$this->_db->exec(
'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') .
'" DROP COLUMN "postdate"'
);
}
}
$this->_exec(
'UPDATE "' . $this->_sanitizeIdentifier('config') .
'" SET "value" = ? WHERE "id" = ?',
array(Controller::VERSION, 'VERSION')
);
}
}

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin\Data;

View File

@@ -1,4 +1,13 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
* a zero-knowledge paste bin
*
* @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
*/
namespace PrivateBin\Data;

View File

@@ -1,15 +1,15 @@
<?php
<?php declare(strict_types=1);
/**
* S3.php
* PrivateBin
*
* an S3 compatible data backend for PrivateBin with CEPH/RadosGW in mind
* see https://docs.ceph.com/en/latest/radosgw/s3/php/
* based on lib/Data/GoogleCloudStorage.php from PrivateBin version 1.7.3
* a zero-knowledge paste bin
*
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2022 Felix J. Ogris (https://ogris.de/)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.4.1
*
* an S3 compatible data backend for PrivateBin with CEPH/RadosGW in mind
* see https://docs.ceph.com/en/latest/radosgw/s3/php/
*
* Installation:
* 1. Make sure you have composer.lock and composer.json in the document root of your PasteBin

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin\Model;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin\Model;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin\Model;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin\Persistence;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin\Persistence;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin\Persistence;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
@@ -8,7 +8,6 @@
* @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.7.3
*/
namespace PrivateBin\Persistence;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin;

View File

@@ -1,14 +1,13 @@
<?php
<?php declare(strict_types=1);
/**
* VizHash_GD
*
* Visual Hash implementation in php4+GD,
* stripped down and modified version for PrivateBin
* stripped down from version 0.0.5 beta, modified for PrivateBin
*
* @link https://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.7.3
*/
namespace PrivateBin;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* PrivateBin
*
@@ -7,7 +7,6 @@
* @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.7.3
*/
namespace PrivateBin;
@@ -48,7 +47,7 @@ class YourlsProxy
*/
public function __construct(Configuration $conf, $link)
{
if (strpos($link, $conf->getKey('basepath') . '?') === false) {
if (strpos($link, $conf->getKey('basepath') . '?') !== 0) {
$this->_error = 'Trying to shorten a URL that isn\'t pointing at our instance.';
return;
}

View File

@@ -73,7 +73,7 @@ endif;
?>
<script type="text/javascript" data-cfasync="false" src="js/purify-3.1.3.js" integrity="sha512-t/FKG/ucQVMWTWVouSMABSEx1r+uSyAI9eNDq0KEr9mPhkgxpJztHI/E72JIpv/+VwPs/Q4husxj14TE9Ps/wg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-yu72BaFLyleZ0WOZKoJto93zrW1opLQKZqZaIJsEy19epCHUqyDUP6QzGDQGfoe1tZ1zAgWP/ChkjgwOitYtnA==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-cbmXvtZ/5gZPFjQDzP3IEhUAIhFPAoM31gw2kRYCT5xOh8wv9gXeDqI/t798luRW1xdC4gaYodjEFCzrsZR4mA==" crossorigin="anonymous"></script>
<!-- icon -->
<link rel="apple-touch-icon" href="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" sizes="180x180" />
<link rel="icon" type="image/png" href="img/favicon-32x32.png" sizes="32x32" />

View File

@@ -42,7 +42,7 @@ endif;
<script type="text/javascript" data-cfasync="false" src="js/base-x-4.0.0.js" integrity="sha512-nNPg5IGCwwrveZ8cA/yMGr5HiRS5Ps2H+s0J/mKTPjCPWUgFGGw7M5nqdnPD3VsRwCVysUh3Y8OWjeSKGkEQJQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/bootstrap-5.3.3.js" integrity="sha512-in2rcOpLTdJ7/pw5qjF4LWHFRtgoBDxXCy49H4YGOcVdGiPaQucGIbOqxt1JvmpvOpq3J/C7VTa0FlioakB2gQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/dark-mode-switch.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-xdW325H1OW06oUf/Lc4ccJXOUW41tU08iyXVOiVL3SbTufQtKVWi1/cQPrWZ3FagPTNL2CwDMqZsHNmXruHnHg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/dark-mode-switch.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-CCbdHdeWDbDO7aqFFmhgnvFESzaILHbUYmbhNjTpcjyO/XYdouQ9Pw8W9rpV8oJT1TsK5FbwSHU1oazmnb7BWA==" crossorigin="anonymous"></script>
<?php
if ($SYNTAXHIGHLIGHTING) :
?>
@@ -57,7 +57,7 @@ endif;
?>
<script type="text/javascript" data-cfasync="false" src="js/purify-3.1.3.js" integrity="sha512-t/FKG/ucQVMWTWVouSMABSEx1r+uSyAI9eNDq0KEr9mPhkgxpJztHI/E72JIpv/+VwPs/Q4husxj14TE9Ps/wg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-yu72BaFLyleZ0WOZKoJto93zrW1opLQKZqZaIJsEy19epCHUqyDUP6QzGDQGfoe1tZ1zAgWP/ChkjgwOitYtnA==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-cbmXvtZ/5gZPFjQDzP3IEhUAIhFPAoM31gw2kRYCT5xOh8wv9gXeDqI/t798luRW1xdC4gaYodjEFCzrsZR4mA==" crossorigin="anonymous"></script>
<!-- icon -->
<link rel="apple-touch-icon" href="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" sizes="180x180" />
<link rel="icon" type="image/png" href="img/favicon-32x32.png" sizes="32x32" />
@@ -329,7 +329,7 @@ endif;
</div>
</nav>
<main>
<section class="container mt-2">
<section class="container-fluid mt-2">
<?php
if (!empty($NOTICE)) :
?>
@@ -422,8 +422,8 @@ endif;
</li>
</ul>
</section>
<section class="container">
<article class="row">
<section class="container-fluid">
<article>
<div id="placeholder" class="col-md-12 hidden"><?php echo I18n::_('+++ no paste text +++'); ?></div>
<div id="attachmentPreview" class="col-md-12 text-center hidden"></div>
<div id="prettymessage" class="card col-md-12 hidden">
@@ -433,20 +433,20 @@ endif;
<p class="col-md-12"><textarea id="message" name="message" cols="80" rows="25" class="form-control hidden"></textarea></p>
</article>
</section>
<section class="container">
<section class="container-fluid">
<div id="discussion" class="hidden">
<h4><?php echo I18n::_('Discussion'); ?></h4>
<div id="commentcontainer"></div>
</div>
</section>
<section class="container">
<section class="container-fluid">
<div id="noscript" role="alert" class="alert alert-info noscript-hide">
<svg width="16" height="16" fill="currentColor" aria-hidden="true"><use href="img/bootstrap-icons.svg#exclamation-circle" /></svg>
<?php echo I18n::_('Loading…'); ?><br />
<span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="%s">this FAQ for information to troubleshoot</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-the-loading-message-not-go-away'); ?></span>
</div>
</section>
<footer class="container">
<footer class="container-fluid">
<div class="row">
<h5 class="col-md-5 col-xs-8"><?php echo I18n::_($NAME); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h5>
<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>

View File

@@ -51,7 +51,7 @@ endif;
?>
<script type="text/javascript" data-cfasync="false" src="js/purify-3.1.3.js" integrity="sha512-t/FKG/ucQVMWTWVouSMABSEx1r+uSyAI9eNDq0KEr9mPhkgxpJztHI/E72JIpv/+VwPs/Q4husxj14TE9Ps/wg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-yu72BaFLyleZ0WOZKoJto93zrW1opLQKZqZaIJsEy19epCHUqyDUP6QzGDQGfoe1tZ1zAgWP/ChkjgwOitYtnA==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-cbmXvtZ/5gZPFjQDzP3IEhUAIhFPAoM31gw2kRYCT5xOh8wv9gXeDqI/t798luRW1xdC4gaYodjEFCzrsZR4mA==" crossorigin="anonymous"></script>
<!-- icon -->
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use Google\Cloud\Core\Exception\BadRequestException;
use Google\Cloud\Core\Exception\NotFoundException;
@@ -28,94 +28,386 @@ require PATH . 'vendor/autoload.php';
Helper::updateSubresourceIntegrity();
/**
* Class StorageClientStub provides a limited stub for performing the unit test
* Class Helper provides unit tests pastes and comments of various formats
*/
class StorageClientStub extends StorageClient
class Helper
{
private $_config = null;
private $_connection = null;
private static $_buckets = array();
/**
* example ID of a paste
*
* @var string
*/
private static $pasteid = '5b65a01b43987bc2';
public function __construct(array $config = array())
{
$this->_config = $config;
$this->_connection = new ConnectionInterfaceStub();
}
/**
* example paste version 1
*
* @var array
*/
private static $pasteV1 = array(
'data' => '{"iv":"EN39/wd5Nk8HAiSG2K5AsQ","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"QKN1DBXe5PI","ct":"8hA83xDdXjD7K2qfmw5NdA"}',
'attachment' => '{"iv":"Pd4pOKWkmDTT9uPwVwd5Ag","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"ZIUhFTliVz4","ct":"6nOCU3peNDclDDpFtJEBKA"}',
'attachmentname' => '{"iv":"76MkAtOGC4oFogX/aSMxRA","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"ZIUhFTliVz4","ct":"b6Ae/U1xJdsX/+lATud4sQ"}',
'meta' => array(
'formatter' => 'plaintext',
'postdate' => 1344803344,
'opendiscussion' => true,
),
);
public function bucket($name, $userProject = false)
/**
* example paste version 2
*
* @var array
*/
private static $pasteV2 = array(
'adata' => array(
array(
'gMSNoLOk4z0RnmsYwXZ8mw==',
'TZO+JWuIuxs=',
100000,
256,
128,
'aes',
'gcm',
'zlib',
),
'plaintext',
1,
0,
),
'meta' => array(
'expire' => '5min',
),
'v' => 2,
'ct' => 'ME5JF/YBEijp2uYMzLZozbKtWc5wfy6R59NBb7SmRig=',
);
/**
* example ID of a comment
*
* @var string
*/
private static $commentid = '5a52eebf11c4c94b';
/**
* example comment
*
* @var array
*/
private static $commentV1 = array(
'data' => '{"iv":"Pd4pOKWkmDTT9uPwVwd5Ag","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"ZIUhFTliVz4","ct":"6nOCU3peNDclDDpFtJEBKA"}',
'meta' => array(
'nickname' => '{"iv":"76MkAtOGC4oFogX/aSMxRA","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"ZIUhFTliVz4","ct":"b6Ae/U1xJdsX/+lATud4sQ"}',
'vizhash' => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGUlEQVQokWOsl5/94983CNKQMjnxaOePf98MeKwPfNjkLZ3AgARab6b9+PeNEVnDj3/ff/z7ZiHnzsDA8Pv7H2TVPJw8EAYLAwb48OaVgIgYKycLsrYv378wMDB8//qdCVMDRA9EKSsnCwRBxNsepaLboMFlyMDAICAi9uHNK24GITQ/MDAwoNhgIGMLtwGrzegaLjw5jMz9+vUdnN17uwDCQDhJgk0O07yvX9+teDX1x79v6DYIsIjgcgMaYGFgYOBg4kJx2JejkAiBxAw+PzAwMNz4dp6wDXDw4MdNNOl0rWYsNkD89OLXI/xmo9sgzatJjAYmBgYGDiauD3/ePP18nVgb4MF89+M5ZX6js293wUMpnr8KTQMAxsCJnJ30apMAAAAASUVORK5CYII=',
'postdate' => 1344803528,
),
);
/**
* JS files and their SRI hashes
*
* @var array
*/
private static $hashes = array();
/**
* get example paste ID
*
* @return string
*/
public static function getPasteId()
{
if (!key_exists($name, self::$_buckets)) {
$b = new BucketStub($this->_connection, $name, array(), $this);
self::$_buckets[$name] = $b;
}
return self::$_buckets[$name];
return self::$pasteid;
}
/**
* @throws \Google\Cloud\Core\Exception\NotFoundException
* get example paste, as stored on server
*
* @param int $version
* @param array $meta
* @return array
*/
public function deleteBucket($name)
public static function getPaste($version = 2, array $meta = array())
{
if (key_exists($name, self::$_buckets)) {
unset(self::$_buckets[$name]);
$example = self::getPasteWithAttachment($version, $meta);
// v1 has the attachment stored in a separate property
if ($version === 1) {
unset($example['attachment'], $example['attachmentname']);
}
return $example;
}
/**
* get example paste with attachment, as stored on server
*
* @param int $version
* @param array $meta
* @return array
*/
public static function getPasteWithAttachment($version = 2, array $meta = array())
{
$example = $version === 1 ? self::$pasteV1 : self::$pasteV2;
$example['meta']['salt'] = ServerSalt::generate();
$example['meta'] = array_merge($example['meta'], $meta);
return $example;
}
/**
* get example paste, as decoded from POST by the request object
*
* @param int $version
* @param array $meta
* @return array
*/
public static function getPastePost($version = 2, array $meta = array())
{
$example = self::getPaste($version, $meta);
if ($version == 2) {
$example['meta'] = array('expire' => $example['meta']['expire']);
} else {
throw new NotFoundException();
unset($example['meta']['postdate']);
}
return $example;
}
/**
* get example paste, as received via POST by the user
*
* @param int $version
* @param array $meta
* @return array
*/
public static function getPasteJson($version = 2, array $meta = array())
{
return json_encode(self::getPastePost($version, $meta));
}
/**
* get example paste ID
*
* @return string
*/
public static function getCommentId()
{
return self::$commentid;
}
/**
* get example comment, as stored on server
*
* @param int $version
* @param array $meta
* @return array
*/
public static function getComment($version = 2, array $meta = array())
{
$example = $version === 1 ? self::$commentV1 : self::$pasteV2;
if ($version === 2) {
$example['adata'] = $example['adata'][0];
$example['pasteid'] = $example['parentid'] = self::getPasteId();
$example['meta']['created'] = self::$commentV1['meta']['postdate'];
$example['meta']['icon'] = self::$commentV1['meta']['vizhash'];
unset($example['meta']['expire']);
}
$example['meta'] = array_merge($example['meta'], $meta);
return $example;
}
/**
* get example comment, as decoded from POST by the request object
*
* @param int $version
* @return array
*/
public static function getCommentPost()
{
$example = self::getComment();
unset($example['meta']);
return $example;
}
/**
* get example comment, as received via POST by user
*
* @param int $version
* @return array
*/
public static function getCommentJson()
{
return json_encode(self::getCommentPost());
}
/**
* delete directory and all its contents recursively
*
* @param string $path
* @throws Exception
*/
public static function rmDir($path)
{
if (is_dir($path)) {
$path .= DIRECTORY_SEPARATOR;
$dir = dir($path);
while (false !== ($file = $dir->read())) {
if ($file != '.' && $file != '..') {
if (is_dir($path . $file)) {
self::rmDir($path . $file);
} elseif (is_file($path . $file)) {
if (!unlink($path . $file)) {
throw new Exception('Error deleting file "' . $path . $file . '".');
}
}
}
}
$dir->close();
if (!rmdir($path)) {
throw new Exception('Error deleting directory "' . $path . '".');
}
}
}
public function buckets(array $options = array())
/**
* create a backup of the config file
*
* @return void
*/
public static function confBackup()
{
throw new BadMethodCallException('not supported by this stub');
}
public function registerStreamWrapper($protocol = null)
{
throw new BadMethodCallException('not supported by this stub');
}
public function unregisterStreamWrapper($protocol = null)
{
throw new BadMethodCallException('not supported by this stub');
}
public function signedUrlUploader($uri, $data, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function timestamp(\DateTimeInterface $timestamp, $nanoSeconds = null)
{
throw new BadMethodCallException('not supported by this stub');
}
public function getServiceAccount(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function hmacKeys(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function hmacKey($accessId, $projectId = null, array $metadata = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function createHmacKey($serviceAccountEmail, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function createBucket($name, array $options = array())
{
if (key_exists($name, self::$_buckets)) {
throw new BadRequestException('already exists');
if (!is_file(CONF . '.bak') && is_file(CONF)) {
rename(CONF, CONF . '.bak');
}
if (!is_file(CONF_SAMPLE . '.bak') && is_file(CONF_SAMPLE)) {
copy(CONF_SAMPLE, CONF_SAMPLE . '.bak');
}
}
/**
* restor backup of the config file
*
* @return void
*/
public static function confRestore()
{
if (is_file(CONF . '.bak')) {
rename(CONF . '.bak', CONF);
}
if (is_file(CONF_SAMPLE . '.bak')) {
rename(CONF_SAMPLE . '.bak', CONF_SAMPLE);
}
}
/**
* create ini file
*
* @param string $pathToFile
* @param array $values
*/
public static function createIniFile($pathToFile, array $values)
{
if (count($values)) {
@unlink($pathToFile);
$ini = fopen($pathToFile, 'a');
foreach ($values as $section => $options) {
fwrite($ini, "[$section]" . PHP_EOL);
foreach ($options as $option => $setting) {
if (is_null($setting)) {
continue;
} elseif (is_string($setting)) {
$setting = '"' . $setting . '"';
} elseif (is_array($setting)) {
foreach ($setting as $key => $value) {
if (is_null($value)) {
$value = 'null';
} elseif (is_string($value)) {
$value = '"' . $value . '"';
} else {
$value = var_export($value, true);
}
fwrite($ini, $option . "[$key] = $value" . PHP_EOL);
}
continue;
} else {
$setting = var_export($setting, true);
}
fwrite($ini, "$option = $setting" . PHP_EOL);
}
fwrite($ini, PHP_EOL);
}
fclose($ini);
}
}
/**
* a var_export that returns arrays without line breaks
* by linus@flowingcreativity.net via php.net
*
* @param mixed $var
* @param bool $return
* @return void|string
*/
public static function varExportMin($var, $return = false)
{
if (is_array($var)) {
$toImplode = array();
foreach ($var as $key => $value) {
$toImplode[] = var_export($key, true) . ' => ' . self::varExportMin($value, true);
}
$code = 'array(' . implode(', ', $toImplode) . ')';
if ($return) {
return $code;
} else {
echo $code;
}
} else {
return var_export($var, $return);
}
}
/**
* update all templates with the latest SRI hashes for all JS files
*
* @return void
*/
public static function updateSubresourceIntegrity()
{
$dir = dir(PATH . 'js');
while (false !== ($file = $dir->read())) {
if (substr($file, -3) === '.js') {
self::$hashes[$file] = base64_encode(
hash('sha512', file_get_contents(
PATH . 'js' . DIRECTORY_SEPARATOR . $file
), true)
);
}
}
$dir = dir(PATH . 'tpl');
while (false !== ($file = $dir->read())) {
if (substr($file, -4) === '.php') {
$content = file_get_contents(
PATH . 'tpl' . DIRECTORY_SEPARATOR . $file
);
$content = preg_replace_callback(
'#<script ([^>]+) src="js/([a-z0-9.-]+.js)([^"]*)"( integrity="[^"]+" crossorigin="[^"]+")?></script>#',
function ($matches) {
if (array_key_exists($matches[2], Helper::$hashes)) {
return '<script ' . $matches[1] . ' src="js/' .
$matches[2] . $matches[3] .
'" integrity="sha512-' . Helper::$hashes[$matches[2]] .
'" crossorigin="anonymous"></script>';
} else {
return $matches[0];
}
},
$content
);
file_put_contents(
PATH . 'tpl' . DIRECTORY_SEPARATOR . $file,
$content
);
}
}
$b = new BucketStub($this->_connection, $name, array(), $this);
self::$_buckets[$name] = $b;
return $b;
}
}
@@ -610,385 +902,93 @@ class ConnectionInterfaceStub implements ConnectionInterface
}
/**
* Class Helper provides unit tests pastes and comments of various formats
* Class StorageClientStub provides a limited stub for performing the unit test
*/
class Helper
class StorageClientStub extends StorageClient
{
/**
* example ID of a paste
*
* @var string
*/
private static $pasteid = '5b65a01b43987bc2';
private $_config = null;
private $_connection = null;
private static $_buckets = array();
/**
* example paste version 1
*
* @var array
*/
private static $pasteV1 = array(
'data' => '{"iv":"EN39/wd5Nk8HAiSG2K5AsQ","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"QKN1DBXe5PI","ct":"8hA83xDdXjD7K2qfmw5NdA"}',
'attachment' => '{"iv":"Pd4pOKWkmDTT9uPwVwd5Ag","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"ZIUhFTliVz4","ct":"6nOCU3peNDclDDpFtJEBKA"}',
'attachmentname' => '{"iv":"76MkAtOGC4oFogX/aSMxRA","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"ZIUhFTliVz4","ct":"b6Ae/U1xJdsX/+lATud4sQ"}',
'meta' => array(
'formatter' => 'plaintext',
'postdate' => 1344803344,
'opendiscussion' => true,
),
);
/**
* example paste version 2
*
* @var array
*/
private static $pasteV2 = array(
'adata' => array(
array(
'gMSNoLOk4z0RnmsYwXZ8mw==',
'TZO+JWuIuxs=',
100000,
256,
128,
'aes',
'gcm',
'zlib',
),
'plaintext',
1,
0,
),
'meta' => array(
'expire' => '5min',
),
'v' => 2,
'ct' => 'ME5JF/YBEijp2uYMzLZozbKtWc5wfy6R59NBb7SmRig=',
);
/**
* example ID of a comment
*
* @var string
*/
private static $commentid = '5a52eebf11c4c94b';
/**
* example comment
*
* @var array
*/
private static $commentV1 = array(
'data' => '{"iv":"Pd4pOKWkmDTT9uPwVwd5Ag","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"ZIUhFTliVz4","ct":"6nOCU3peNDclDDpFtJEBKA"}',
'meta' => array(
'nickname' => '{"iv":"76MkAtOGC4oFogX/aSMxRA","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"ZIUhFTliVz4","ct":"b6Ae/U1xJdsX/+lATud4sQ"}',
'vizhash' => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGUlEQVQokWOsl5/94983CNKQMjnxaOePf98MeKwPfNjkLZ3AgARab6b9+PeNEVnDj3/ff/z7ZiHnzsDA8Pv7H2TVPJw8EAYLAwb48OaVgIgYKycLsrYv378wMDB8//qdCVMDRA9EKSsnCwRBxNsepaLboMFlyMDAICAi9uHNK24GITQ/MDAwoNhgIGMLtwGrzegaLjw5jMz9+vUdnN17uwDCQDhJgk0O07yvX9+teDX1x79v6DYIsIjgcgMaYGFgYOBg4kJx2JejkAiBxAw+PzAwMNz4dp6wDXDw4MdNNOl0rWYsNkD89OLXI/xmo9sgzatJjAYmBgYGDiauD3/ePP18nVgb4MF89+M5ZX6js293wUMpnr8KTQMAxsCJnJ30apMAAAAASUVORK5CYII=',
'postdate' => 1344803528,
),
);
/**
* JS files and their SRI hashes
*
* @var array
*/
private static $hashes = array();
/**
* get example paste ID
*
* @return string
*/
public static function getPasteId()
public function __construct(array $config = array())
{
return self::$pasteid;
$this->_config = $config;
$this->_connection = new ConnectionInterfaceStub();
}
/**
* get example paste, as stored on server
*
* @param int $version
* @param array $meta
* @return array
*/
public static function getPaste($version = 2, array $meta = array())
public function bucket($name, $userProject = false)
{
$example = self::getPasteWithAttachment($version, $meta);
// v1 has the attachment stored in a separate property
if ($version === 1) {
unset($example['attachment'], $example['attachmentname']);
if (!key_exists($name, self::$_buckets)) {
$b = new BucketStub($this->_connection, $name, array(), $this);
self::$_buckets[$name] = $b;
}
return $example;
return self::$_buckets[$name];
}
/**
* get example paste with attachment, as stored on server
*
* @param int $version
* @param array $meta
* @return array
* @throws \Google\Cloud\Core\Exception\NotFoundException
*/
public static function getPasteWithAttachment($version = 2, array $meta = array())
public function deleteBucket($name)
{
$example = $version === 1 ? self::$pasteV1 : self::$pasteV2;
$example['meta']['salt'] = ServerSalt::generate();
$example['meta'] = array_merge($example['meta'], $meta);
return $example;
}
/**
* get example paste, as decoded from POST by the request object
*
* @param int $version
* @param array $meta
* @return array
*/
public static function getPastePost($version = 2, array $meta = array())
{
$example = self::getPaste($version, $meta);
if ($version == 2) {
$example['meta'] = array('expire' => $example['meta']['expire']);
if (key_exists($name, self::$_buckets)) {
unset(self::$_buckets[$name]);
} else {
unset($example['meta']['postdate']);
}
return $example;
}
/**
* get example paste, as received via POST by the user
*
* @param int $version
* @param array $meta
* @return array
*/
public static function getPasteJson($version = 2, array $meta = array())
{
return json_encode(self::getPastePost($version, $meta));
}
/**
* get example paste ID
*
* @return string
*/
public static function getCommentId()
{
return self::$commentid;
}
/**
* get example comment, as stored on server
*
* @param int $version
* @param array $meta
* @return array
*/
public static function getComment($version = 2, array $meta = array())
{
$example = $version === 1 ? self::$commentV1 : self::$pasteV2;
if ($version === 2) {
$example['adata'] = $example['adata'][0];
$example['pasteid'] = $example['parentid'] = self::getPasteId();
$example['meta']['created'] = self::$commentV1['meta']['postdate'];
$example['meta']['icon'] = self::$commentV1['meta']['vizhash'];
unset($example['meta']['expire']);
}
$example['meta'] = array_merge($example['meta'], $meta);
return $example;
}
/**
* get example comment, as decoded from POST by the request object
*
* @param int $version
* @return array
*/
public static function getCommentPost()
{
$example = self::getComment();
unset($example['meta']);
return $example;
}
/**
* get example comment, as received via POST by user
*
* @param int $version
* @return array
*/
public static function getCommentJson()
{
return json_encode(self::getCommentPost());
}
/**
* delete directory and all its contents recursively
*
* @param string $path
* @throws Exception
*/
public static function rmDir($path)
{
if (is_dir($path)) {
$path .= DIRECTORY_SEPARATOR;
$dir = dir($path);
while (false !== ($file = $dir->read())) {
if ($file != '.' && $file != '..') {
if (is_dir($path . $file)) {
self::rmDir($path . $file);
} elseif (is_file($path . $file)) {
if (!unlink($path . $file)) {
throw new Exception('Error deleting file "' . $path . $file . '".');
}
}
}
}
$dir->close();
if (!rmdir($path)) {
throw new Exception('Error deleting directory "' . $path . '".');
}
throw new NotFoundException();
}
}
/**
* create a backup of the config file
*
* @return void
*/
public static function confBackup()
public function buckets(array $options = array())
{
if (!is_file(CONF . '.bak') && is_file(CONF)) {
rename(CONF, CONF . '.bak');
}
if (!is_file(CONF_SAMPLE . '.bak') && is_file(CONF_SAMPLE)) {
copy(CONF_SAMPLE, CONF_SAMPLE . '.bak');
}
throw new BadMethodCallException('not supported by this stub');
}
/**
* restor backup of the config file
*
* @return void
*/
public static function confRestore()
public function registerStreamWrapper($protocol = null)
{
if (is_file(CONF . '.bak')) {
rename(CONF . '.bak', CONF);
}
if (is_file(CONF_SAMPLE . '.bak')) {
rename(CONF_SAMPLE . '.bak', CONF_SAMPLE);
}
throw new BadMethodCallException('not supported by this stub');
}
/**
* create ini file
*
* @param string $pathToFile
* @param array $values
*/
public static function createIniFile($pathToFile, array $values)
public function unregisterStreamWrapper($protocol = null)
{
if (count($values)) {
@unlink($pathToFile);
$ini = fopen($pathToFile, 'a');
foreach ($values as $section => $options) {
fwrite($ini, "[$section]" . PHP_EOL);
foreach ($options as $option => $setting) {
if (is_null($setting)) {
continue;
} elseif (is_string($setting)) {
$setting = '"' . $setting . '"';
} elseif (is_array($setting)) {
foreach ($setting as $key => $value) {
if (is_null($value)) {
$value = 'null';
} elseif (is_string($value)) {
$value = '"' . $value . '"';
} else {
$value = var_export($value, true);
}
fwrite($ini, $option . "[$key] = $value" . PHP_EOL);
}
continue;
} else {
$setting = var_export($setting, true);
}
fwrite($ini, "$option = $setting" . PHP_EOL);
}
fwrite($ini, PHP_EOL);
}
fclose($ini);
}
throw new BadMethodCallException('not supported by this stub');
}
/**
* a var_export that returns arrays without line breaks
* by linus@flowingcreativity.net via php.net
*
* @param mixed $var
* @param bool $return
* @return void|string
*/
public static function varExportMin($var, $return = false)
public function signedUrlUploader($uri, $data, array $options = array())
{
if (is_array($var)) {
$toImplode = array();
foreach ($var as $key => $value) {
$toImplode[] = var_export($key, true) . ' => ' . self::varExportMin($value, true);
}
$code = 'array(' . implode(', ', $toImplode) . ')';
if ($return) {
return $code;
} else {
echo $code;
}
} else {
return var_export($var, $return);
}
throw new BadMethodCallException('not supported by this stub');
}
/**
* update all templates with the latest SRI hashes for all JS files
*
* @return void
*/
public static function updateSubresourceIntegrity()
public function timestamp(\DateTimeInterface $timestamp, $nanoSeconds = null)
{
$dir = dir(PATH . 'js');
while (false !== ($file = $dir->read())) {
if (substr($file, -3) === '.js') {
self::$hashes[$file] = base64_encode(
hash('sha512', file_get_contents(
PATH . 'js' . DIRECTORY_SEPARATOR . $file
), true)
);
}
}
throw new BadMethodCallException('not supported by this stub');
}
$dir = dir(PATH . 'tpl');
while (false !== ($file = $dir->read())) {
if (substr($file, -4) === '.php') {
$content = file_get_contents(
PATH . 'tpl' . DIRECTORY_SEPARATOR . $file
);
$content = preg_replace_callback(
'#<script ([^>]+) src="js/([a-z0-9.-]+.js)([^"]*)"( integrity="[^"]+" crossorigin="[^"]+")?></script>#',
function ($matches) {
if (array_key_exists($matches[2], Helper::$hashes)) {
return '<script ' . $matches[1] . ' src="js/' .
$matches[2] . $matches[3] .
'" integrity="sha512-' . Helper::$hashes[$matches[2]] .
'" crossorigin="anonymous"></script>';
} else {
return $matches[0];
}
},
$content
);
file_put_contents(
PATH . 'tpl' . DIRECTORY_SEPARATOR . $file,
$content
);
}
public function getServiceAccount(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function hmacKeys(array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function hmacKey($accessId, $projectId = null, array $metadata = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function createHmacKey($serviceAccountEmail, array $options = array())
{
throw new BadMethodCallException('not supported by this stub');
}
public function createBucket($name, array $options = array())
{
if (key_exists($name, self::$_buckets)) {
throw new BadRequestException('already exists');
}
$b = new BucketStub($this->_connection, $name, array(), $this);
self::$_buckets[$name] = $b;
return $b;
}
}

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Configuration;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Controller;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PrivateBin\Data\Database;
use PrivateBin\Persistence\ServerSalt;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use Google\Auth\HttpHandler\HttpHandlerFactory;
use GuzzleHttp\Client;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Controller;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Data\Filesystem;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use Google\Auth\HttpHandler\HttpHandlerFactory;
use GuzzleHttp\Client;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Filter;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\FormatV2;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\I18n;
@@ -198,7 +198,7 @@ class I18nTest extends TestCase
$languageCount = 0;
foreach ($languageIterator as $file) {
++$languageCount;
$this->assertTrue(copy($file, $path . DIRECTORY_SEPARATOR . $file->getBasename()));
$this->assertTrue(copy($file->getPathname(), $path . DIRECTORY_SEPARATOR . $file->getBasename()));
}
I18nMock::resetPath($path);

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Controller;
@@ -325,6 +325,9 @@ class JsonApiTest extends TestCase
*/
public function testShortenViaYourlsFailure()
{
$options = parse_ini_file(CONF, true);
$options['main']['basepath'] = 'https://example.com/path'; // missing slash gets added by Configuration constructor
Helper::createIniFile(CONF, $options);
$_SERVER['REQUEST_URI'] = '/path/shortenviayourls?link=https%3A%2F%2Fexample.com%2Fpath%2F%3Ffoo%23bar';
$_GET['link'] = 'https://example.com/path/?foo#bar';
ob_start();

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Data\Database;
use PrivateBin\Data\Filesystem;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use Identicon\Identicon;
use PHPUnit\Framework\TestCase;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Data\Filesystem;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Data\Filesystem;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Data\Filesystem;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Request;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\I18n;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Data\Filesystem;

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PrivateBin\Configuration;
@@ -54,6 +54,13 @@ class YourlsProxyTest extends TestCase
$this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.');
}
public function testSneakyForeignUrl()
{
$yourls = new YourlsProxy($this->_conf, 'https://other.example.com/?q=https://example.com/?foo#bar');
$this->assertTrue($yourls->isError());
$this->assertEquals($yourls->getError(), 'Trying to shorten a URL that isn\'t pointing at our instance.');
}
public function testYourlsError()
{
// when statusCode is not 200, shorturl may not have been set